From 4a4c677fccabdcd6db509488c9cb5d784afaa59d Mon Sep 17 00:00:00 2001 From: Glenn L McGrath Date: Sat, 15 Feb 2003 11:50:33 +0000 Subject: Patch from Bastian Blank - ip route flush - different usage for telnetd in inetd mode - changes for the default flags of the ip features - if no /usr requested, udhcpc should use the script also without /usr. --- networking/libiproute/iproute.c | 116 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 3 deletions(-) (limited to 'networking/libiproute') diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c index 114fb6c90..be4435f66 100644 --- a/networking/libiproute/iproute.c +++ b/networking/libiproute/iproute.c @@ -19,6 +19,8 @@ #include #include +#include +#include #include "rt_names.h" #include "utils.h" @@ -33,6 +35,8 @@ static struct { int tb; + int flushed; + char *flushb; int flushp; int flushe; struct rtnl_handle *rth; @@ -51,6 +55,16 @@ static struct inet_prefix msrc; } filter; +static int flush_update(void) +{ + if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) { + perror("Failed to send flush request\n"); + return -1; + } + filter.flushp = 0; + return 0; +} + static int print_route(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = (FILE*)arg; @@ -67,6 +81,8 @@ static int print_route(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; } + if (filter.flushb && n->nlmsg_type != RTM_NEWROUTE) + return 0; len -= NLMSG_LENGTH(sizeof(*r)); if (len < 0) { error_msg("wrong nlmsg len %d", len); @@ -128,6 +144,30 @@ static int print_route(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) memset(tb, 0, sizeof(tb)); parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); + if (filter.flushb && + r->rtm_family == AF_INET6 && + r->rtm_dst_len == 0 && + r->rtm_type == RTN_UNREACHABLE && + tb[RTA_PRIORITY] && + *(int*)RTA_DATA(tb[RTA_PRIORITY]) == -1) + return 0; + + if (filter.flushb) { + struct nlmsghdr *fn; + if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) { + if (flush_update()) + return -1; + } + fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp)); + memcpy(fn, n, n->nlmsg_len); + fn->nlmsg_type = RTM_DELROUTE; + fn->nlmsg_flags = NLM_F_REQUEST; + fn->nlmsg_seq = ++filter.rth->seq; + filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb; + filter.flushed++; + return 0; + } + if (n->nlmsg_type == RTM_DELROUTE) { fprintf(fp, "Deleted "); } @@ -393,6 +433,29 @@ static int rtnl_rtcache_request(struct rtnl_handle *rth, int family) return sendto(rth->fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr)); } +static int iproute_flush_cache(void) +{ +#define ROUTE_FLUSH_PATH "/proc/sys/net/ipv4/route/flush" + + int len; + int flush_fd = open (ROUTE_FLUSH_PATH, O_WRONLY); + char *buffer = "-1"; + + if (flush_fd < 0) { + fprintf (stderr, "Cannot open \"%s\"\n", ROUTE_FLUSH_PATH); + return -1; + } + + len = strlen (buffer); + + if ((write (flush_fd, (void *)buffer, len)) < len) { + fprintf (stderr, "Cannot flush routing cache\n"); + return -1; + } + close(flush_fd); + return 0; +} + static void iproute_reset_filter(void) { memset(&filter, 0, sizeof(filter)); @@ -400,7 +463,7 @@ static void iproute_reset_filter(void) filter.msrc.bitlen = -1; } -static int iproute_list(int argc, char **argv) +static int iproute_list_or_flush(int argc, char **argv, int flush) { int do_ipv6 = preferred_family; struct rtnl_handle rth; @@ -410,6 +473,11 @@ static int iproute_list(int argc, char **argv) iproute_reset_filter(); filter.tb = RT_TABLE_MAIN; + if (flush && argc <= 0) { + fprintf(stderr, "\"ip route flush\" requires arguments.\n"); + return -1; + } + while (argc > 0) { if (matches(*argv, "protocol") == 0) { int prot = 0; @@ -496,6 +564,46 @@ static int iproute_list(int argc, char **argv) } } + if (flush) { + int round = 0; + char flushb[4096-512]; + + if (filter.tb == -1) { + if (do_ipv6 != AF_INET6) + iproute_flush_cache(); + if (do_ipv6 == AF_INET) + return 0; + } + + filter.flushb = flushb; + filter.flushp = 0; + filter.flushe = sizeof(flushb); + filter.rth = &rth; + + for (;;) { + if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) { + perror("Cannot send dump request"); + return -1; + } + filter.flushed = 0; + if (rtnl_dump_filter(&rth, print_route, stdout, NULL, NULL) < 0) { + error_msg("Flush terminated\n"); + return -1; + } + if (filter.flushed == 0) { + if (round == 0) { + if (filter.tb != -1 || do_ipv6 == AF_INET6) + fprintf(stderr, "Nothing to flush.\n"); + } + fflush(stdout); + return 0; + } + round++; + if (flush_update() < 0) + exit(1); + } + } + if (filter.tb != -1) { if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) { perror_msg_and_die("Cannot send dump request"); @@ -686,7 +794,7 @@ static int iproute_get(int argc, char **argv) int do_iproute(int argc, char **argv) { const char *ip_route_commands[] = { "add", "append", "change", "chg", - "delete", "get", "list", "show", "prepend", "replace", "test", 0 }; + "delete", "get", "list", "show", "prepend", "replace", "test", "flush", 0 }; unsigned short command_num = 6; unsigned int flags = 0; int cmd = RTM_NEWROUTE; @@ -712,13 +820,15 @@ int do_iproute(int argc, char **argv) return iproute_get(argc-1, argv+1); case 6: /* list */ case 7: /* show */ - return iproute_list(argc-1, argv+1); + return iproute_list_or_flush(argc-1, argv+1, 0); case 8: /* prepend */ flags = NLM_F_CREATE; case 9: /* replace */ flags = NLM_F_CREATE|NLM_F_REPLACE; case 10: /* test */ flags = NLM_F_EXCL; + case 11: /* flush */ + return iproute_list_or_flush(argc-1, argv+1, 1); default: error_msg_and_die("Unknown command %s", *argv); } -- cgit v1.2.3