https://bugs.gentoo.org/274973 If the routing table that I wanna flush has 60 entries or more, "ip route flush table foo" fails with the following error: Failed to send flush request: Success Flush terminated Patch by Alin Năstac --- iproute2-2.6.29-1/ip/ipaddress.c +++ iproute2-2.6.29-1/ip/ipaddress.c @@ -37,6 +37,8 @@ #define MAX_ROUNDS 10 +static struct rtnl_handle rth_flush = { .fd = -1 }; + static struct { int ifindex; @@ -339,7 +341,7 @@ static int flush_update(void) { - if (rtnl_send_check(&rth, filter.flushb, filter.flushp) < 0) { + if (rtnl_send_check(&rth_flush, filter.flushb, filter.flushp) < 0) { perror("Failed to send flush request"); return -1; } @@ -697,6 +699,9 @@ filter.flushp = 0; filter.flushe = sizeof(flushb); + if (rtnl_open(&rth_flush, 0) < 0) + return 1; + while (round < MAX_ROUNDS) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { perror("Cannot send dump request"); @@ -715,18 +720,20 @@ printf("*** Flush is complete after %d round%s ***\n", round, round>1?"s":""); } fflush(stdout); + rtnl_close(&rth_flush); return 0; } round++; if (flush_update() < 0) - return 1; + break; if (show_stats) { printf("\n*** Round %d, deleting %d addresses ***\n", round, filter.flushed); fflush(stdout); } } - fprintf(stderr, "*** Flush remains incomplete after %d rounds. ***\n", MAX_ROUNDS); fflush(stderr); + fprintf(stderr, "*** Flush remains incomplete after %d rounds. ***\n", round); fflush(stderr); + rtnl_close(&rth_flush); return 1; } --- iproute2-2.6.29-1/ip/ipneigh.c +++ iproute2-2.6.29-1/ip/ipneigh.c @@ -32,6 +32,8 @@ #define NUD_VALID (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY) #define MAX_ROUNDS 10 +static struct rtnl_handle rth_flush = { .fd = -1 }; + static struct { int family; @@ -87,7 +89,7 @@ static int flush_update(void) { - if (rtnl_send_check(&rth, filter.flushb, filter.flushp) < 0) { + if (rtnl_send_check(&rth_flush, filter.flushb, filter.flushp) < 0) { perror("Failed to send flush request"); return -1; } @@ -391,6 +393,9 @@ filter.flushe = sizeof(flushb); filter.state &= ~NUD_FAILED; + if (rtnl_open(&rth_flush, 0) < 0) + return 1; + while (round < MAX_ROUNDS) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETNEIGH) < 0) { perror("Cannot send dump request"); @@ -409,18 +414,20 @@ printf("*** Flush is complete after %d round%s ***\n", round, round>1?"s":""); } fflush(stdout); + rtnl_close(&rth_flush); return 0; } round++; if (flush_update() < 0) - exit(1); + break; + if (show_stats) { printf("\n*** Round %d, deleting %d entries ***\n", round, filter.flushed); fflush(stdout); } } - printf("*** Flush not complete bailing out after %d rounds\n", - MAX_ROUNDS); + fprintf(stderr, "*** Flush remains incomplete after %d rounds. ***\n", round); fflush(stderr); + rtnl_close(&rth_flush); return 1; } --- iproute2-2.6.29-1/ip/iproute.c +++ iproute2-2.6.29-1/ip/iproute.c @@ -37,6 +37,7 @@ #define RTAX_RTTVAR RTAX_HOPS #endif +static struct rtnl_handle rth_flush = { .fd = -1 }; static const char *mx_names[RTAX_MAX+1] = { [RTAX_MTU] = "mtu", @@ -112,7 +113,7 @@ static int flush_update(void) { - if (rtnl_send_check(&rth, filter.flushb, filter.flushp) < 0) { + if (rtnl_send_check(&rth_flush, filter.flushb, filter.flushp) < 0) { perror("Failed to send flush request"); return -1; } @@ -1210,6 +1211,9 @@ filter.flushp = 0; filter.flushe = sizeof(flushb); + if (rtnl_open(&rth_flush, 0) < 0) + return 1; + for (;;) { if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) { perror("Cannot send dump request"); @@ -1228,6 +1232,7 @@ printf("*** Flush is complete after %d round%s ***\n", round, round>1?"s":""); } fflush(stdout); + rtnl_close(&rth_flush); return 0; } round++; --- iproute2-2.6.29-1/ip/xfrm_policy.c +++ iproute2-2.6.29-1/ip/xfrm_policy.c @@ -756,11 +756,15 @@ struct xfrm_buffer xb; char buf[NLMSG_DELETEALL_BUF_SIZE]; int i; + struct rtnl_handle rth2; xb.buf = buf; xb.size = sizeof(buf); xb.rth = &rth; + if (rtnl_open(&rth2, 0) < 0) + exit(1); + for (i = 0; ; i++) { xb.offset = 0; xb.nlmsg_count = 0; @@ -783,7 +787,7 @@ break; } - if (rtnl_send_check(&rth, xb.buf, xb.offset) < 0) { + if (rtnl_send_check(&rth2, xb.buf, xb.offset) < 0) { perror("Failed to send delete-all request"); exit(1); } @@ -793,6 +797,8 @@ xb.offset = 0; xb.nlmsg_count = 0; } + + rtnl_close(&rth2); } else { if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETPOLICY) < 0) { perror("Cannot send dump request"); --- iproute2-2.6.29-1/ip/xfrm_state.c +++ iproute2-2.6.29-1/ip/xfrm_state.c @@ -924,11 +924,15 @@ struct xfrm_buffer xb; char buf[NLMSG_DELETEALL_BUF_SIZE]; int i; + struct rtnl_handle rth2; xb.buf = buf; xb.size = sizeof(buf); xb.rth = &rth; + if (rtnl_open(&rth2, 0) < 0) + exit(1); + for (i = 0; ; i++) { xb.offset = 0; xb.nlmsg_count = 0; @@ -951,7 +955,7 @@ break; } - if (rtnl_send_check(&rth, xb.buf, xb.offset) < 0) { + if (rtnl_send_check(&rth2, xb.buf, xb.offset) < 0) { perror("Failed to send delete-all request\n"); exit(1); } @@ -962,6 +966,7 @@ xb.nlmsg_count = 0; } + rtnl_close(&rth2); } else { if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETSA) < 0) { perror("Cannot send dump request");