diff options
Diffstat (limited to 'networking/interface.c')
-rw-r--r-- | networking/interface.c | 235 |
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 | 344 | struct iface_list { | |
338 | smallint interface_opt_a; /* show all interfaces */ | 345 | struct interface *int_list, *int_last; |
339 | 346 | }; | |
340 | static 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 */ |
345 | except that the freshly added calls to xatoul() brf on ethernet aliases with | 351 | except that the freshly added calls to xatoul() barf on ethernet aliases with |
346 | uClibc with e.g.: ife->name='lo' name='eth0:1' | 352 | uClibc with e.g.: ife->name='lo' name='eth0:1' |
347 | static int nstrcmp(const char *a, const char *b) | 353 | static 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 | ||
371 | static struct interface *add_interface(char *name) | 377 | static 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 | ||
397 | static char *get_name(char *name, char *p) | 404 | static 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 |
440 | static const char *const ss_fmt[] = { | 449 | static 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 | ||
454 | static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn) | 462 | static 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 | ||
497 | static int if_readconf(void) | 505 | static 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 | ||
543 | static int if_readlist_proc(char *target) | 542 | static 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 | ||
586 | static int if_readlist(void) | 576 | static 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 | ||
1080 | static int do_if_print(struct interface *ife) /*, int *opt_a)*/ | 1069 | static 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 | ||
1092 | static struct interface *lookup_interface(char *name) | 1081 | int 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 | ||
1103 | static 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) { |
1120 | static 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 | |||
1157 | int 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 | } | ||