aboutsummaryrefslogtreecommitdiff
path: root/networking/interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/interface.c')
-rw-r--r--networking/interface.c235
1 files changed, 96 insertions, 139 deletions
diff --git a/networking/interface.c b/networking/interface.c
index 89427f2f4..e5e55d8d4 100644
--- a/networking/interface.c
+++ b/networking/interface.c
@@ -318,31 +318,37 @@ struct interface {
318 char name[IFNAMSIZ]; /* interface name */ 318 char name[IFNAMSIZ]; /* interface name */
319 short type; /* if type */ 319 short type; /* if type */
320 short flags; /* various flags */ 320 short flags; /* various flags */
321 int tx_queue_len; /* transmit queue length */
322
323 /* these should be contiguous, zeroed in one go in if_fetch(): */
324#define FIRST_TO_ZERO metric
321 int metric; /* routing metric */ 325 int metric; /* routing metric */
322 int mtu; /* MTU value */ 326 int mtu; /* MTU value */
323 int tx_queue_len; /* transmit queue length */
324 struct ifmap map; /* hardware setup */ 327 struct ifmap map; /* hardware setup */
325 struct sockaddr addr; /* IP address */ 328 struct sockaddr addr; /* IP address */
326 struct sockaddr dstaddr; /* P-P IP address */ 329 struct sockaddr dstaddr; /* P-P IP address */
327 struct sockaddr broadaddr; /* IP broadcast address */ 330 struct sockaddr broadaddr; /* IP broadcast address */
328 struct sockaddr netmask; /* IP network mask */ 331 struct sockaddr netmask; /* IP network mask */
329 int has_ip;
330 char hwaddr[32]; /* HW address */ 332 char hwaddr[32]; /* HW address */
331 int statistics_valid; 333#define LAST_TO_ZERO hwaddr
334
335 smallint has_ip;
336 smallint statistics_valid;
332 struct user_net_device_stats stats; /* statistics */ 337 struct user_net_device_stats stats; /* statistics */
338#if 0 /* UNUSED */
333 int keepalive; /* keepalive value for SLIP */ 339 int keepalive; /* keepalive value for SLIP */
334 int outfill; /* outfill value for SLIP */ 340 int outfill; /* outfill value for SLIP */
341#endif
335}; 342};
336 343
337 344struct iface_list {
338smallint interface_opt_a; /* show all interfaces */ 345 struct interface *int_list, *int_last;
339 346};
340static struct interface *int_list, *int_last;
341 347
342 348
343#if 0 349#if 0
344/* like strcmp(), but knows about numbers */ 350/* like strcmp(), but knows about numbers */
345except that the freshly added calls to xatoul() brf on ethernet aliases with 351except that the freshly added calls to xatoul() barf on ethernet aliases with
346uClibc with e.g.: ife->name='lo' name='eth0:1' 352uClibc with e.g.: ife->name='lo' name='eth0:1'
347static int nstrcmp(const char *a, const char *b) 353static int nstrcmp(const char *a, const char *b)
348{ 354{
@@ -368,11 +374,11 @@ static int nstrcmp(const char *a, const char *b)
368} 374}
369#endif 375#endif
370 376
371static struct interface *add_interface(char *name) 377static struct interface *add_interface(struct iface_list *ilist, char *name)
372{ 378{
373 struct interface *ife, **nextp, *new; 379 struct interface *ife, **nextp, *new;
374 380
375 for (ife = int_last; ife; ife = ife->prev) { 381 for (ife = ilist->int_last; ife; ife = ife->prev) {
376 int n = /*n*/strcmp(ife->name, name); 382 int n = /*n*/strcmp(ife->name, name);
377 383
378 if (n == 0) 384 if (n == 0)
@@ -383,43 +389,43 @@ static struct interface *add_interface(char *name)
383 389
384 new = xzalloc(sizeof(*new)); 390 new = xzalloc(sizeof(*new));
385 strncpy_IFNAMSIZ(new->name, name); 391 strncpy_IFNAMSIZ(new->name, name);
386 nextp = ife ? &ife->next : &int_list; 392
393 nextp = ife ? &ife->next : &ilist->int_list;
387 new->prev = ife; 394 new->prev = ife;
388 new->next = *nextp; 395 new->next = *nextp;
389 if (new->next) 396 if (new->next)
390 new->next->prev = new; 397 new->next->prev = new;
391 else 398 else
392 int_last = new; 399 ilist->int_last = new;
393 *nextp = new; 400 *nextp = new;
394 return new; 401 return new;
395} 402}
396 403
397static char *get_name(char *name, char *p) 404static char *get_name(char name[IFNAMSIZ], char *p)
398{ 405{
399 /* Extract <name> from nul-terminated p where p matches 406 /* Extract NAME from nul-terminated p of the form "<whitespace>NAME:"
400 * <name>: after leading whitespace. 407 * If match is not made, set NAME to "" and return unchanged p.
401 * If match is not made, set name empty and return unchanged p
402 */ 408 */
403 char *nameend; 409 char *nameend;
404 char *namestart = skip_whitespace(p); 410 char *namestart;
405 411
406 nameend = namestart; 412 nameend = namestart = skip_whitespace(p);
407 while (*nameend && *nameend != ':' && !isspace(*nameend)) 413
408 nameend++; 414 for (;;) {
409 if (*nameend == ':') { 415 if ((nameend - namestart) >= IFNAMSIZ)
410 if ((nameend - namestart) < IFNAMSIZ) { 416 break; /* interface name too large - return "" */
417 if (*nameend == ':') {
411 memcpy(name, namestart, nameend - namestart); 418 memcpy(name, namestart, nameend - namestart);
412 name[nameend - namestart] = '\0'; 419 name[nameend - namestart] = '\0';
413 p = nameend; 420 return nameend + 1;
414 } else {
415 /* Interface name too large */
416 name[0] = '\0';
417 } 421 }
418 } else { 422 nameend++;
419 /* trailing ':' not found - return empty */ 423 /* isspace, NUL, any control char? */
420 name[0] = '\0'; 424 if ((unsigned char)*nameend <= (unsigned char)' ')
425 break; /* trailing ':' not found - return "" */
421 } 426 }
422 return p + 1; 427 name[0] = '\0';
428 return p;
423} 429}
424 430
425/* If scanf supports size qualifiers for %n conversions, then we can 431/* If scanf supports size qualifiers for %n conversions, then we can
@@ -435,7 +441,10 @@ static char *get_name(char *name, char *p)
435/* "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" */ 441/* "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" */
436/* }; */ 442/* }; */
437 443
438 /* Lie about the size of the int pointed to for %n. */ 444/* We use %n for unavailable data in older versions of /proc/net/dev formats.
445 * This results in bogus stores to ife->FOO members corresponding to
446 * %n specifiers (even the size of integers may not match).
447 */
439#if INT_MAX == LONG_MAX 448#if INT_MAX == LONG_MAX
440static const char *const ss_fmt[] = { 449static const char *const ss_fmt[] = {
441 "%n%llu%u%u%u%u%n%n%n%llu%u%u%u%u%u", 450 "%n%llu%u%u%u%u%n%n%n%llu%u%u%u%u%u",
@@ -448,7 +457,6 @@ static const char *const ss_fmt[] = {
448 "%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu", 457 "%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu",
449 "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" 458 "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu"
450}; 459};
451
452#endif 460#endif
453 461
454static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn) 462static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn)
@@ -456,22 +464,22 @@ static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn)
456 memset(&ife->stats, 0, sizeof(struct user_net_device_stats)); 464 memset(&ife->stats, 0, sizeof(struct user_net_device_stats));
457 465
458 sscanf(bp, ss_fmt[procnetdev_vsn], 466 sscanf(bp, ss_fmt[procnetdev_vsn],
459 &ife->stats.rx_bytes, /* missing for 0 */ 467 &ife->stats.rx_bytes, /* missing for v0 */
460 &ife->stats.rx_packets, 468 &ife->stats.rx_packets,
461 &ife->stats.rx_errors, 469 &ife->stats.rx_errors,
462 &ife->stats.rx_dropped, 470 &ife->stats.rx_dropped,
463 &ife->stats.rx_fifo_errors, 471 &ife->stats.rx_fifo_errors,
464 &ife->stats.rx_frame_errors, 472 &ife->stats.rx_frame_errors,
465 &ife->stats.rx_compressed, /* missing for <= 1 */ 473 &ife->stats.rx_compressed, /* missing for v0, v1 */
466 &ife->stats.rx_multicast, /* missing for <= 1 */ 474 &ife->stats.rx_multicast, /* missing for v0, v1 */
467 &ife->stats.tx_bytes, /* missing for 0 */ 475 &ife->stats.tx_bytes, /* missing for v0 */
468 &ife->stats.tx_packets, 476 &ife->stats.tx_packets,
469 &ife->stats.tx_errors, 477 &ife->stats.tx_errors,
470 &ife->stats.tx_dropped, 478 &ife->stats.tx_dropped,
471 &ife->stats.tx_fifo_errors, 479 &ife->stats.tx_fifo_errors,
472 &ife->stats.collisions, 480 &ife->stats.collisions,
473 &ife->stats.tx_carrier_errors, 481 &ife->stats.tx_carrier_errors,
474 &ife->stats.tx_compressed /* missing for <= 1 */ 482 &ife->stats.tx_compressed /* missing for v0, v1 */
475 ); 483 );
476 484
477 if (procnetdev_vsn <= 1) { 485 if (procnetdev_vsn <= 1) {
@@ -494,31 +502,25 @@ static int procnetdev_version(char *buf)
494 return 0; 502 return 0;
495} 503}
496 504
497static int if_readconf(void) 505static void if_readconf(struct iface_list *ilist)
498{ 506{
499 int numreqs = 30; 507 int numreqs = 30;
500 struct ifconf ifc; 508 struct ifconf ifc;
501 struct ifreq *ifr; 509 struct ifreq *ifr;
502 int n, err = -1; 510 int n;
503 int skfd; 511 int skfd;
504 512
505 ifc.ifc_buf = NULL; 513 ifc.ifc_buf = NULL;
506 514
507 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets 515 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
508 (as of 2.1.128) */ 516 (as of 2.1.128) */
509 skfd = socket(AF_INET, SOCK_DGRAM, 0); 517 skfd = xsocket(AF_INET, SOCK_DGRAM, 0);
510 if (skfd < 0) {
511 bb_perror_msg("error: no inet socket available");
512 return -1;
513 }
514 518
515 for (;;) { 519 for (;;) {
516 ifc.ifc_len = sizeof(struct ifreq) * numreqs; 520 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
517 ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len); 521 ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
518 522
519 if (ioctl_or_warn(skfd, SIOCGIFCONF, &ifc) < 0) { 523 xioctl(skfd, SIOCGIFCONF, &ifc);
520 goto out;
521 }
522 if (ifc.ifc_len == (int)(sizeof(struct ifreq) * numreqs)) { 524 if (ifc.ifc_len == (int)(sizeof(struct ifreq) * numreqs)) {
523 /* assume it overflowed and try again */ 525 /* assume it overflowed and try again */
524 numreqs += 10; 526 numreqs += 10;
@@ -529,67 +531,54 @@ static int if_readconf(void)
529 531
530 ifr = ifc.ifc_req; 532 ifr = ifc.ifc_req;
531 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) { 533 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
532 add_interface(ifr->ifr_name); 534 add_interface(ilist, ifr->ifr_name);
533 ifr++; 535 ifr++;
534 } 536 }
535 err = 0;
536 537
537 out:
538 close(skfd); 538 close(skfd);
539 free(ifc.ifc_buf); 539 free(ifc.ifc_buf);
540 return err;
541} 540}
542 541
543static int if_readlist_proc(char *target) 542static int if_readlist_proc(struct iface_list *ilist, char *ifname)
544{ 543{
545 static smallint proc_read;
546
547 FILE *fh; 544 FILE *fh;
548 char buf[512]; 545 char buf[512];
549 struct interface *ife; 546 struct interface *ife;
550 int err, procnetdev_vsn; 547 int procnetdev_vsn;
551 548 int ret;
552 if (proc_read)
553 return 0;
554 if (!target)
555 proc_read = 1;
556 549
557 fh = fopen_or_warn(_PATH_PROCNET_DEV, "r"); 550 fh = fopen_or_warn(_PATH_PROCNET_DEV, "r");
558 if (!fh) { 551 if (!fh) {
559 return if_readconf(); 552 return 0; /* "not found" */
560 } 553 }
561 fgets(buf, sizeof buf, fh); /* eat line */ 554 fgets(buf, sizeof buf, fh); /* eat line */
562 fgets(buf, sizeof buf, fh); 555 fgets(buf, sizeof buf, fh);
563 556
564 procnetdev_vsn = procnetdev_version(buf); 557 procnetdev_vsn = procnetdev_version(buf);
565 558
566 err = 0; 559 ret = 0;
567 while (fgets(buf, sizeof buf, fh)) { 560 while (fgets(buf, sizeof buf, fh)) {
568 char *s, name[128]; 561 char *s, name[IFNAMSIZ];
569 562
570 s = get_name(name, buf); 563 s = get_name(name, buf);
571 ife = add_interface(name); 564 ife = add_interface(ilist, name);
572 get_dev_fields(s, ife, procnetdev_vsn); 565 get_dev_fields(s, ife, procnetdev_vsn);
573 ife->statistics_valid = 1; 566 ife->statistics_valid = 1;
574 if (target && strcmp(target, name) == 0) 567 if (ifname && strcmp(ifname, name) == 0) {
568 ret = 1; /* found */
575 break; 569 break;
576 } 570 }
577 if (ferror(fh)) {
578 bb_perror_msg(_PATH_PROCNET_DEV);
579 err = -1;
580 proc_read = 0;
581 } 571 }
582 fclose(fh); 572 fclose(fh);
583 return err; 573 return ret;
584} 574}
585 575
586static int if_readlist(void) 576static void if_readlist(struct iface_list *ilist, char *ifname)
587{ 577{
588 int err = if_readlist_proc(NULL); 578 int found = if_readlist_proc(ilist, ifname);
589 /* Needed in order to get ethN:M aliases */ 579 /* Needed in order to get ethN:M aliases */
590 if (!err) 580 if (!found)
591 err = if_readconf(); 581 if_readconf(ilist);
592 return err;
593} 582}
594 583
595/* Fetch the interface configuration from the kernel. */ 584/* Fetch the interface configuration from the kernel. */
@@ -608,24 +597,29 @@ static int if_fetch(struct interface *ife)
608 } 597 }
609 ife->flags = ifr.ifr_flags; 598 ife->flags = ifr.ifr_flags;
610 599
600 /* set up default values if ioctl's would fail */
601 ife->tx_queue_len = -1; /* unknown value */
602 memset(&ife->FIRST_TO_ZERO, 0,
603 offsetof(struct interface, LAST_TO_ZERO)
604 - offsetof(struct interface, FIRST_TO_ZERO)
605 + sizeof(ife->LAST_TO_ZERO)
606 );
607
611 strncpy_IFNAMSIZ(ifr.ifr_name, ifname); 608 strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
612 memset(ife->hwaddr, 0, 32);
613 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0) 609 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0)
614 memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8); 610 memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
615 611
612//er.... why this _isnt_ inside if()?
616 ife->type = ifr.ifr_hwaddr.sa_family; 613 ife->type = ifr.ifr_hwaddr.sa_family;
617 614
618 strncpy_IFNAMSIZ(ifr.ifr_name, ifname); 615 strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
619 ife->metric = 0;
620 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0) 616 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0)
621 ife->metric = ifr.ifr_metric; 617 ife->metric = ifr.ifr_metric;
622 618
623 strncpy_IFNAMSIZ(ifr.ifr_name, ifname); 619 strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
624 ife->mtu = 0;
625 if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0) 620 if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0)
626 ife->mtu = ifr.ifr_mtu; 621 ife->mtu = ifr.ifr_mtu;
627 622
628 memset(&ife->map, 0, sizeof(struct ifmap));
629#ifdef SIOCGIFMAP 623#ifdef SIOCGIFMAP
630 strncpy_IFNAMSIZ(ifr.ifr_name, ifname); 624 strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
631 if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0) 625 if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0)
@@ -634,31 +628,24 @@ static int if_fetch(struct interface *ife)
634 628
635#ifdef HAVE_TXQUEUELEN 629#ifdef HAVE_TXQUEUELEN
636 strncpy_IFNAMSIZ(ifr.ifr_name, ifname); 630 strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
637 ife->tx_queue_len = -1; /* unknown value */
638 if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0) 631 if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0)
639 ife->tx_queue_len = ifr.ifr_qlen; 632 ife->tx_queue_len = ifr.ifr_qlen;
640#else
641 ife->tx_queue_len = -1; /* unknown value */
642#endif 633#endif
643 634
644 strncpy_IFNAMSIZ(ifr.ifr_name, ifname); 635 strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
645 ifr.ifr_addr.sa_family = AF_INET; 636 ifr.ifr_addr.sa_family = AF_INET;
646 memset(&ife->addr, 0, sizeof(struct sockaddr));
647 if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) { 637 if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) {
648 ife->has_ip = 1; 638 ife->has_ip = 1;
649 ife->addr = ifr.ifr_addr; 639 ife->addr = ifr.ifr_addr;
650 strncpy_IFNAMSIZ(ifr.ifr_name, ifname); 640 strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
651 memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
652 if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0) 641 if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0)
653 ife->dstaddr = ifr.ifr_dstaddr; 642 ife->dstaddr = ifr.ifr_dstaddr;
654 643
655 strncpy_IFNAMSIZ(ifr.ifr_name, ifname); 644 strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
656 memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
657 if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0) 645 if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0)
658 ife->broadaddr = ifr.ifr_broadaddr; 646 ife->broadaddr = ifr.ifr_broadaddr;
659 647
660 strncpy_IFNAMSIZ(ifr.ifr_name, ifname); 648 strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
661 memset(&ife->netmask, 0, sizeof(struct sockaddr));
662 if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0) 649 if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0)
663 ife->netmask = ifr.ifr_netmask; 650 ife->netmask = ifr.ifr_netmask;
664 } 651 }
@@ -1020,10 +1007,12 @@ static void ife_print(struct interface *ptr)
1020 1007
1021 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */ 1008 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
1022 printf(" MTU:%d Metric:%d", ptr->mtu, ptr->metric ? ptr->metric : 1); 1009 printf(" MTU:%d Metric:%d", ptr->mtu, ptr->metric ? ptr->metric : 1);
1010#if 0
1023#ifdef SIOCSKEEPALIVE 1011#ifdef SIOCSKEEPALIVE
1024 if (ptr->outfill || ptr->keepalive) 1012 if (ptr->outfill || ptr->keepalive)
1025 printf(" Outfill:%d Keepalive:%d", ptr->outfill, ptr->keepalive); 1013 printf(" Outfill:%d Keepalive:%d", ptr->outfill, ptr->keepalive);
1026#endif 1014#endif
1015#endif
1027 bb_putchar('\n'); 1016 bb_putchar('\n');
1028 1017
1029 /* If needed, display the interface statistics. */ 1018 /* If needed, display the interface statistics. */
@@ -1077,67 +1066,44 @@ static void ife_print(struct interface *ptr)
1077 bb_putchar('\n'); 1066 bb_putchar('\n');
1078} 1067}
1079 1068
1080static int do_if_print(struct interface *ife) /*, int *opt_a)*/ 1069static int do_if_print(struct interface *ife, int show_downed_too)
1081{ 1070{
1082 int res; 1071 int res;
1083 1072
1084 res = do_if_fetch(ife); 1073 res = do_if_fetch(ife);
1085 if (res >= 0) { 1074 if (res >= 0) {
1086 if ((ife->flags & IFF_UP) || interface_opt_a) 1075 if ((ife->flags & IFF_UP) || show_downed_too)
1087 ife_print(ife); 1076 ife_print(ife);
1088 } 1077 }
1089 return res; 1078 return res;
1090} 1079}
1091 1080
1092static struct interface *lookup_interface(char *name) 1081int FAST_FUNC display_interfaces(char *ifname)
1093{
1094 struct interface *ife = NULL;
1095
1096 if (if_readlist_proc(name) < 0)
1097 return NULL;
1098 ife = add_interface(name);
1099 return ife;
1100}
1101
1102#ifdef UNUSED
1103static int for_all_interfaces(int (*doit) (struct interface *, void *),
1104 void *cookie)
1105{ 1082{
1106 struct interface *ife; 1083 struct interface *ife;
1084 int res;
1085 struct iface_list ilist;
1107 1086
1108 if (!int_list && (if_readlist() < 0)) 1087 ilist.int_list = NULL;
1109 return -1; 1088 ilist.int_last = NULL;
1110 for (ife = int_list; ife; ife = ife->next) { 1089 if_readlist(&ilist, ifname != IFNAME_SHOW_DOWNED_TOO ? ifname : NULL);
1111 int err = doit(ife, cookie);
1112 if (err)
1113 return err;
1114 }
1115 return 0;
1116}
1117#endif
1118 1090
1119/* for ipv4 add/del modes */ 1091 if (!ifname || ifname == IFNAME_SHOW_DOWNED_TOO) {
1120static int if_print(char *ifname) 1092 for (ife = ilist.int_list; ife; ife = ife->next) {
1121{
1122 struct interface *ife;
1123 int res;
1124 1093
1125 if (!ifname) { 1094 BUILD_BUG_ON((int)(intptr_t)IFNAME_SHOW_DOWNED_TOO != 1);
1126 /*res = for_all_interfaces(do_if_print, &interface_opt_a);*/ 1095
1127 if (!int_list && (if_readlist() < 0)) 1096 res = do_if_print(ife, (int)(intptr_t)ifname);
1128 return -1; 1097 if (res < 0)
1129 for (ife = int_list; ife; ife = ife->next) { 1098 goto ret;
1130 int err = do_if_print(ife); /*, &interface_opt_a);*/
1131 if (err)
1132 return err;
1133 } 1099 }
1134 return 0; 1100 return 0;
1135 } 1101 }
1136 ife = lookup_interface(ifname); 1102
1137 res = do_if_fetch(ife); 1103 ife = add_interface(&ilist, ifname);
1138 if (res >= 0) 1104 res = do_if_print(ife, /*show_downed_too:*/ 1);
1139 ife_print(ife); 1105 ret:
1140 return res; 1106 return (res < 0); /* status < 0 == 1 -- error */
1141} 1107}
1142 1108
1143#if ENABLE_FEATURE_HWIB 1109#if ENABLE_FEATURE_HWIB
@@ -1153,12 +1119,3 @@ int FAST_FUNC in_ib(const char *bufp, struct sockaddr *sap)
1153 return 0; 1119 return 0;
1154} 1120}
1155#endif 1121#endif
1156
1157int FAST_FUNC display_interfaces(char *ifname)
1158{
1159 int status;
1160
1161 status = if_print(ifname);
1162
1163 return (status < 0); /* status < 0 == 1 -- error */
1164}