aboutsummaryrefslogtreecommitdiff
path: root/networking/libiproute/ipaddress.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/libiproute/ipaddress.c')
-rw-r--r--networking/libiproute/ipaddress.c83
1 files changed, 80 insertions, 3 deletions
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c
index 2821f2e8d..77368fb3c 100644
--- a/networking/libiproute/ipaddress.c
+++ b/networking/libiproute/ipaddress.c
@@ -42,6 +42,10 @@ static struct
42 int flags, flagmask; 42 int flags, flagmask;
43 int up; 43 int up;
44 char *label; 44 char *label;
45 int flushed;
46 char *flushb;
47 int flushp;
48 int flushe;
45 struct rtnl_handle *rth; 49 struct rtnl_handle *rth;
46} filter; 50} filter;
47 51
@@ -191,6 +195,16 @@ static int print_linkinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg
191 return 0; 195 return 0;
192} 196}
193 197
198static int flush_update(void)
199{
200 if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) {
201 perror("Failed to send flush request\n");
202 return -1;
203 }
204 filter.flushp = 0;
205 return 0;
206}
207
194static int print_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) 208static int print_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
195{ 209{
196 FILE *fp = (FILE*)arg; 210 FILE *fp = (FILE*)arg;
@@ -208,6 +222,9 @@ static int print_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg
208 return -1; 222 return -1;
209 } 223 }
210 224
225 if (filter.flushb && n->nlmsg_type != RTM_NEWADDR)
226 return 0;
227
211 memset(rta_tb, 0, sizeof(rta_tb)); 228 memset(rta_tb, 0, sizeof(rta_tb));
212 parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa))); 229 parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
213 230
@@ -242,6 +259,22 @@ static int print_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg
242 } 259 }
243 } 260 }
244 261
262 if (filter.flushb) {
263 struct nlmsghdr *fn;
264 if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
265 if (flush_update())
266 return -1;
267 }
268 fn = (struct nlmsghdr*)(filter.flushb + NLMSG_ALIGN(filter.flushp));
269 memcpy(fn, n, n->nlmsg_len);
270 fn->nlmsg_type = RTM_DELADDR;
271 fn->nlmsg_flags = NLM_F_REQUEST;
272 fn->nlmsg_seq = ++filter.rth->seq;
273 filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb;
274 filter.flushed++;
275 return 0;
276 }
277
245 if (n->nlmsg_type == RTM_DELADDR) 278 if (n->nlmsg_type == RTM_DELADDR)
246 fprintf(fp, "Deleted "); 279 fprintf(fp, "Deleted ");
247 280
@@ -382,7 +415,7 @@ static void ipaddr_reset_filter(int _oneline)
382 filter.oneline = _oneline; 415 filter.oneline = _oneline;
383} 416}
384 417
385extern int ipaddr_list(int argc, char **argv) 418extern int ipaddr_list_or_flush(int argc, char **argv, int flush)
386{ 419{
387 const char *option[] = { "to", "scope", "up", "label", "dev", 0 }; 420 const char *option[] = { "to", "scope", "up", "label", "dev", 0 };
388 struct nlmsg_list *linfo = NULL; 421 struct nlmsg_list *linfo = NULL;
@@ -398,6 +431,17 @@ extern int ipaddr_list(int argc, char **argv)
398 if (filter.family == AF_UNSPEC) 431 if (filter.family == AF_UNSPEC)
399 filter.family = preferred_family; 432 filter.family = preferred_family;
400 433
434 if (flush) {
435 if (argc <= 0) {
436 fprintf(stderr, "Flush requires arguments.\n");
437 return -1;
438 }
439 if (filter.family == AF_PACKET) {
440 fprintf(stderr, "Cannot flush link addresses.\n");
441 return -1;
442 }
443 }
444
401 while (argc > 0) { 445 while (argc > 0) {
402 const unsigned short option_num = compare_string_array(option, *argv); 446 const unsigned short option_num = compare_string_array(option, *argv);
403 switch (option_num) { 447 switch (option_num) {
@@ -461,6 +505,37 @@ extern int ipaddr_list(int argc, char **argv)
461 } 505 }
462 } 506 }
463 507
508 if (flush) {
509 int round = 0;
510 char flushb[4096-512];
511
512 filter.flushb = flushb;
513 filter.flushp = 0;
514 filter.flushe = sizeof(flushb);
515 filter.rth = &rth;
516
517 for (;;) {
518 if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
519 perror("Cannot send dump request");
520 exit(1);
521 }
522 filter.flushed = 0;
523 if (rtnl_dump_filter(&rth, print_addrinfo, stdout, NULL, NULL) < 0) {
524 fprintf(stderr, "Flush terminated\n");
525 exit(1);
526 }
527 if (filter.flushed == 0) {
528 if (round == 0)
529 fprintf(stderr, "Nothing to flush.\n");
530 fflush(stdout);
531 return 0;
532 }
533 round++;
534 if (flush_update() < 0)
535 exit(1);
536 }
537 }
538
464 if (filter.family != AF_PACKET) { 539 if (filter.family != AF_PACKET) {
465 if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { 540 if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
466 perror_msg_and_die("Cannot send dump request"); 541 perror_msg_and_die("Cannot send dump request");
@@ -727,7 +802,7 @@ static int ipaddr_modify(int cmd, int argc, char **argv)
727 802
728extern int do_ipaddr(int argc, char **argv) 803extern int do_ipaddr(int argc, char **argv)
729{ 804{
730 const char *commands[] = { "add", "delete", "list", "show", "lst", 0 }; 805 const char *commands[] = { "add", "delete", "list", "show", "lst", "flush", 0 };
731 unsigned short command_num = 2; 806 unsigned short command_num = 2;
732 807
733 if (*argv) { 808 if (*argv) {
@@ -741,7 +816,9 @@ extern int do_ipaddr(int argc, char **argv)
741 case 2: /* list */ 816 case 2: /* list */
742 case 3: /* show */ 817 case 3: /* show */
743 case 4: /* lst */ 818 case 4: /* lst */
744 return ipaddr_list(argc-1, argv+1); 819 return ipaddr_list_or_flush(argc-1, argv+1, 0);
820 case 5: /* flush */
821 return ipaddr_list_or_flush(argc-1, argv+1, 1);
745 } 822 }
746 error_msg_and_die("Unknown command %s", *argv); 823 error_msg_and_die("Unknown command %s", *argv);
747} 824}