91 |
/* Display an Internet socket address. */ |
/* Display an Internet socket address. */ |
92 |
static const char* FAST_FUNC INET_sprint(struct sockaddr *sap, int numeric) |
static const char* FAST_FUNC INET_sprint(struct sockaddr *sap, int numeric) |
93 |
{ |
{ |
94 |
static char *buff; |
static char *buff; /* defaults to NULL */ |
95 |
|
|
96 |
free(buff); |
free(buff); |
97 |
if (sap->sa_family == 0xFFFF || sap->sa_family == 0) |
if (sap->sa_family == 0xFFFF || sap->sa_family == 0) |
395 |
} |
} |
396 |
|
|
397 |
new = xzalloc(sizeof(*new)); |
new = xzalloc(sizeof(*new)); |
398 |
strncpy(new->name, name, IFNAMSIZ); |
strncpy_IFNAMSIZ(new->name, name); |
399 |
nextp = ife ? &ife->next : &int_list; |
nextp = ife ? &ife->next : &int_list; |
400 |
new->prev = ife; |
new->prev = ife; |
401 |
new->next = *nextp; |
new->next = *nextp; |
410 |
static char *get_name(char *name, char *p) |
static char *get_name(char *name, char *p) |
411 |
{ |
{ |
412 |
/* Extract <name> from nul-terminated p where p matches |
/* Extract <name> from nul-terminated p where p matches |
413 |
<name>: after leading whitespace. |
* <name>: after leading whitespace. |
414 |
If match is not made, set name empty and return unchanged p */ |
* If match is not made, set name empty and return unchanged p |
415 |
int namestart = 0, nameend = 0; |
*/ |
416 |
|
char *nameend; |
417 |
|
char *namestart = skip_whitespace(p); |
418 |
|
|
|
while (isspace(p[namestart])) |
|
|
namestart++; |
|
419 |
nameend = namestart; |
nameend = namestart; |
420 |
while (p[nameend] && p[nameend] != ':' && !isspace(p[nameend])) |
while (*nameend && *nameend != ':' && !isspace(*nameend)) |
421 |
nameend++; |
nameend++; |
422 |
if (p[nameend] == ':') { |
if (*nameend == ':') { |
423 |
if ((nameend - namestart) < IFNAMSIZ) { |
if ((nameend - namestart) < IFNAMSIZ) { |
424 |
memcpy(name, &p[namestart], nameend - namestart); |
memcpy(name, namestart, nameend - namestart); |
425 |
name[nameend - namestart] = '\0'; |
name[nameend - namestart] = '\0'; |
426 |
p = &p[nameend]; |
p = nameend; |
427 |
} else { |
} else { |
428 |
/* Interface name too large */ |
/* Interface name too large */ |
429 |
name[0] = '\0'; |
name[0] = '\0'; |
614 |
|
|
615 |
skfd = xsocket(AF_INET, SOCK_DGRAM, 0); |
skfd = xsocket(AF_INET, SOCK_DGRAM, 0); |
616 |
|
|
617 |
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); |
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
618 |
if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) { |
if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) { |
619 |
close(skfd); |
close(skfd); |
620 |
return -1; |
return -1; |
621 |
} |
} |
622 |
ife->flags = ifr.ifr_flags; |
ife->flags = ifr.ifr_flags; |
623 |
|
|
624 |
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); |
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
625 |
memset(ife->hwaddr, 0, 32); |
memset(ife->hwaddr, 0, 32); |
626 |
if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0) |
if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0) |
627 |
memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8); |
memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8); |
628 |
|
|
629 |
ife->type = ifr.ifr_hwaddr.sa_family; |
ife->type = ifr.ifr_hwaddr.sa_family; |
630 |
|
|
631 |
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); |
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
632 |
ife->metric = 0; |
ife->metric = 0; |
633 |
if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0) |
if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0) |
634 |
ife->metric = ifr.ifr_metric; |
ife->metric = ifr.ifr_metric; |
635 |
|
|
636 |
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); |
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
637 |
ife->mtu = 0; |
ife->mtu = 0; |
638 |
if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0) |
if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0) |
639 |
ife->mtu = ifr.ifr_mtu; |
ife->mtu = ifr.ifr_mtu; |
640 |
|
|
641 |
memset(&ife->map, 0, sizeof(struct ifmap)); |
memset(&ife->map, 0, sizeof(struct ifmap)); |
642 |
#ifdef SIOCGIFMAP |
#ifdef SIOCGIFMAP |
643 |
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); |
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
644 |
if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0) |
if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0) |
645 |
ife->map = ifr.ifr_map; |
ife->map = ifr.ifr_map; |
646 |
#endif |
#endif |
647 |
|
|
648 |
#ifdef HAVE_TXQUEUELEN |
#ifdef HAVE_TXQUEUELEN |
649 |
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); |
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
650 |
ife->tx_queue_len = -1; /* unknown value */ |
ife->tx_queue_len = -1; /* unknown value */ |
651 |
if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0) |
if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0) |
652 |
ife->tx_queue_len = ifr.ifr_qlen; |
ife->tx_queue_len = ifr.ifr_qlen; |
654 |
ife->tx_queue_len = -1; /* unknown value */ |
ife->tx_queue_len = -1; /* unknown value */ |
655 |
#endif |
#endif |
656 |
|
|
657 |
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); |
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
658 |
ifr.ifr_addr.sa_family = AF_INET; |
ifr.ifr_addr.sa_family = AF_INET; |
659 |
memset(&ife->addr, 0, sizeof(struct sockaddr)); |
memset(&ife->addr, 0, sizeof(struct sockaddr)); |
660 |
if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) { |
if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) { |
661 |
ife->has_ip = 1; |
ife->has_ip = 1; |
662 |
ife->addr = ifr.ifr_addr; |
ife->addr = ifr.ifr_addr; |
663 |
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); |
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
664 |
memset(&ife->dstaddr, 0, sizeof(struct sockaddr)); |
memset(&ife->dstaddr, 0, sizeof(struct sockaddr)); |
665 |
if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0) |
if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0) |
666 |
ife->dstaddr = ifr.ifr_dstaddr; |
ife->dstaddr = ifr.ifr_dstaddr; |
667 |
|
|
668 |
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); |
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
669 |
memset(&ife->broadaddr, 0, sizeof(struct sockaddr)); |
memset(&ife->broadaddr, 0, sizeof(struct sockaddr)); |
670 |
if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0) |
if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0) |
671 |
ife->broadaddr = ifr.ifr_broadaddr; |
ife->broadaddr = ifr.ifr_broadaddr; |
672 |
|
|
673 |
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); |
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); |
674 |
memset(&ife->netmask, 0, sizeof(struct sockaddr)); |
memset(&ife->netmask, 0, sizeof(struct sockaddr)); |
675 |
if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0) |
if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0) |
676 |
ife->netmask = ifr.ifr_netmask; |
ife->netmask = ifr.ifr_netmask; |
916 |
printf("X bytes:%llu (%llu.%u %sB)%s", ull, int_part, frac_part, ext, end); |
printf("X bytes:%llu (%llu.%u %sB)%s", ull, int_part, frac_part, ext, end); |
917 |
} |
} |
918 |
|
|
|
static void ife_print(struct interface *ptr) |
|
|
{ |
|
|
const struct aftype *ap; |
|
|
const struct hwtype *hw; |
|
|
int hf; |
|
|
int can_compress = 0; |
|
919 |
|
|
920 |
#ifdef HAVE_AFINET6 |
#ifdef HAVE_AFINET6 |
921 |
|
#define IPV6_ADDR_ANY 0x0000U |
922 |
|
|
923 |
|
#define IPV6_ADDR_UNICAST 0x0001U |
924 |
|
#define IPV6_ADDR_MULTICAST 0x0002U |
925 |
|
#define IPV6_ADDR_ANYCAST 0x0004U |
926 |
|
|
927 |
|
#define IPV6_ADDR_LOOPBACK 0x0010U |
928 |
|
#define IPV6_ADDR_LINKLOCAL 0x0020U |
929 |
|
#define IPV6_ADDR_SITELOCAL 0x0040U |
930 |
|
|
931 |
|
#define IPV6_ADDR_COMPATv4 0x0080U |
932 |
|
|
933 |
|
#define IPV6_ADDR_SCOPE_MASK 0x00f0U |
934 |
|
|
935 |
|
#define IPV6_ADDR_MAPPED 0x1000U |
936 |
|
#define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */ |
937 |
|
|
938 |
|
|
939 |
|
static void ife_print6(struct interface *ptr) |
940 |
|
{ |
941 |
|
|
942 |
FILE *f; |
FILE *f; |
943 |
char addr6[40], devname[20]; |
char addr6[40], devname[20]; |
944 |
struct sockaddr_in6 sap; |
struct sockaddr_in6 sap; |
945 |
int plen, scope, dad_status, if_idx; |
int plen, scope, dad_status, if_idx; |
946 |
char addr6p[8][5]; |
char addr6p[8][5]; |
947 |
|
|
948 |
|
f = fopen_for_read(_PATH_PROCNET_IFINET6); |
949 |
|
if (f == NULL) |
950 |
|
return; |
951 |
|
|
952 |
|
while (fscanf |
953 |
|
(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n", |
954 |
|
addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], |
955 |
|
addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope, |
956 |
|
&dad_status, devname) != EOF |
957 |
|
) { |
958 |
|
if (!strcmp(devname, ptr->name)) { |
959 |
|
sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", |
960 |
|
addr6p[0], addr6p[1], addr6p[2], addr6p[3], |
961 |
|
addr6p[4], addr6p[5], addr6p[6], addr6p[7]); |
962 |
|
inet_pton(AF_INET6, addr6, |
963 |
|
(struct sockaddr *) &sap.sin6_addr); |
964 |
|
sap.sin6_family = AF_INET6; |
965 |
|
printf(" inet6 addr: %s/%d", |
966 |
|
INET6_sprint((struct sockaddr *) &sap, 1), |
967 |
|
plen); |
968 |
|
printf(" Scope:"); |
969 |
|
switch (scope & IPV6_ADDR_SCOPE_MASK) { |
970 |
|
case 0: |
971 |
|
puts("Global"); |
972 |
|
break; |
973 |
|
case IPV6_ADDR_LINKLOCAL: |
974 |
|
puts("Link"); |
975 |
|
break; |
976 |
|
case IPV6_ADDR_SITELOCAL: |
977 |
|
puts("Site"); |
978 |
|
break; |
979 |
|
case IPV6_ADDR_COMPATv4: |
980 |
|
puts("Compat"); |
981 |
|
break; |
982 |
|
case IPV6_ADDR_LOOPBACK: |
983 |
|
puts("Host"); |
984 |
|
break; |
985 |
|
default: |
986 |
|
puts("Unknown"); |
987 |
|
} |
988 |
|
} |
989 |
|
} |
990 |
|
fclose(f); |
991 |
|
} |
992 |
|
#else |
993 |
|
#define ife_print6(a) ((void)0) |
994 |
#endif |
#endif |
995 |
|
|
996 |
|
|
997 |
|
static void ife_print(struct interface *ptr) |
998 |
|
{ |
999 |
|
const struct aftype *ap; |
1000 |
|
const struct hwtype *hw; |
1001 |
|
int hf; |
1002 |
|
int can_compress = 0; |
1003 |
|
|
1004 |
ap = get_afntype(ptr->addr.sa_family); |
ap = get_afntype(ptr->addr.sa_family); |
1005 |
if (ap == NULL) |
if (ap == NULL) |
1006 |
ap = get_afntype(0); |
ap = get_afntype(0); |
1017 |
printf("%-9.9s Link encap:%s ", ptr->name, hw->title); |
printf("%-9.9s Link encap:%s ", ptr->name, hw->title); |
1018 |
/* For some hardware types (eg Ash, ATM) we don't print the |
/* For some hardware types (eg Ash, ATM) we don't print the |
1019 |
hardware address if it's null. */ |
hardware address if it's null. */ |
1020 |
if (hw->print != NULL && (!(hw_null_address(hw, ptr->hwaddr) && |
if (hw->print != NULL |
1021 |
hw->suppress_null_addr))) |
&& !(hw_null_address(hw, ptr->hwaddr) && hw->suppress_null_addr) |
1022 |
|
) { |
1023 |
printf("HWaddr %s ", hw->print((unsigned char *)ptr->hwaddr)); |
printf("HWaddr %s ", hw->print((unsigned char *)ptr->hwaddr)); |
1024 |
|
} |
1025 |
#ifdef IFF_PORTSEL |
#ifdef IFF_PORTSEL |
1026 |
if (ptr->flags & IFF_PORTSEL) { |
if (ptr->flags & IFF_PORTSEL) { |
1027 |
printf("Media:%s", if_port_text[ptr->map.port] /* [0] */); |
printf("Media:%s", if_port_text[ptr->map.port] /* [0] */); |
1043 |
printf(" Mask:%s\n", ap->sprint(&ptr->netmask, 1)); |
printf(" Mask:%s\n", ap->sprint(&ptr->netmask, 1)); |
1044 |
} |
} |
1045 |
|
|
1046 |
#ifdef HAVE_AFINET6 |
ife_print6(ptr); |
|
|
|
|
#define IPV6_ADDR_ANY 0x0000U |
|
|
|
|
|
#define IPV6_ADDR_UNICAST 0x0001U |
|
|
#define IPV6_ADDR_MULTICAST 0x0002U |
|
|
#define IPV6_ADDR_ANYCAST 0x0004U |
|
|
|
|
|
#define IPV6_ADDR_LOOPBACK 0x0010U |
|
|
#define IPV6_ADDR_LINKLOCAL 0x0020U |
|
|
#define IPV6_ADDR_SITELOCAL 0x0040U |
|
|
|
|
|
#define IPV6_ADDR_COMPATv4 0x0080U |
|
|
|
|
|
#define IPV6_ADDR_SCOPE_MASK 0x00f0U |
|
|
|
|
|
#define IPV6_ADDR_MAPPED 0x1000U |
|
|
#define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */ |
|
|
|
|
|
f = fopen_for_read(_PATH_PROCNET_IFINET6); |
|
|
if (f != NULL) { |
|
|
while (fscanf |
|
|
(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n", |
|
|
addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], |
|
|
addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope, |
|
|
&dad_status, devname) != EOF |
|
|
) { |
|
|
if (!strcmp(devname, ptr->name)) { |
|
|
sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", |
|
|
addr6p[0], addr6p[1], addr6p[2], addr6p[3], |
|
|
addr6p[4], addr6p[5], addr6p[6], addr6p[7]); |
|
|
inet_pton(AF_INET6, addr6, |
|
|
(struct sockaddr *) &sap.sin6_addr); |
|
|
sap.sin6_family = AF_INET6; |
|
|
printf(" inet6 addr: %s/%d", |
|
|
INET6_sprint((struct sockaddr *) &sap, 1), |
|
|
plen); |
|
|
printf(" Scope:"); |
|
|
switch (scope & IPV6_ADDR_SCOPE_MASK) { |
|
|
case 0: |
|
|
puts("Global"); |
|
|
break; |
|
|
case IPV6_ADDR_LINKLOCAL: |
|
|
puts("Link"); |
|
|
break; |
|
|
case IPV6_ADDR_SITELOCAL: |
|
|
puts("Site"); |
|
|
break; |
|
|
case IPV6_ADDR_COMPATv4: |
|
|
puts("Compat"); |
|
|
break; |
|
|
case IPV6_ADDR_LOOPBACK: |
|
|
puts("Host"); |
|
|
break; |
|
|
default: |
|
|
puts("Unknown"); |
|
|
} |
|
|
} |
|
|
} |
|
|
fclose(f); |
|
|
} |
|
|
#endif |
|
1047 |
|
|
1048 |
printf(" "); |
printf(" "); |
1049 |
/* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */ |
/* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */ |
1135 |
printf("\n R"); |
printf("\n R"); |
1136 |
print_bytes_scaled(ptr->stats.rx_bytes, " T"); |
print_bytes_scaled(ptr->stats.rx_bytes, " T"); |
1137 |
print_bytes_scaled(ptr->stats.tx_bytes, "\n"); |
print_bytes_scaled(ptr->stats.tx_bytes, "\n"); |
|
|
|
1138 |
} |
} |
1139 |
|
|
1140 |
if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma || |
if (ptr->map.irq || ptr->map.mem_start |
1141 |
ptr->map.base_addr)) { |
|| ptr->map.dma || ptr->map.base_addr |
1142 |
|
) { |
1143 |
printf(" "); |
printf(" "); |
1144 |
if (ptr->map.irq) |
if (ptr->map.irq) |
1145 |
printf("Interrupt:%d ", ptr->map.irq); |
printf("Interrupt:%d ", ptr->map.irq); |
1158 |
bb_putchar('\n'); |
bb_putchar('\n'); |
1159 |
} |
} |
1160 |
|
|
|
|
|
1161 |
static int do_if_print(struct interface *ife) /*, int *opt_a)*/ |
static int do_if_print(struct interface *ife) /*, int *opt_a)*/ |
1162 |
{ |
{ |
1163 |
int res; |
int res; |
1242 |
c = *bufp++; |
c = *bufp++; |
1243 |
if (isdigit(c)) |
if (isdigit(c)) |
1244 |
val = c - '0'; |
val = c - '0'; |
1245 |
else if (c >= 'a' && c <= 'f') |
else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') |
1246 |
val = c - 'a' + 10; |
val = (c|0x20) - ('a' - 10); |
|
else if (c >= 'A' && c <= 'F') |
|
|
val = c - 'A' + 10; |
|
1247 |
else { |
else { |
1248 |
errno = EINVAL; |
errno = EINVAL; |
1249 |
return -1; |
return -1; |
1252 |
c = *bufp; |
c = *bufp; |
1253 |
if (isdigit(c)) |
if (isdigit(c)) |
1254 |
val |= c - '0'; |
val |= c - '0'; |
1255 |
else if (c >= 'a' && c <= 'f') |
else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') |
1256 |
val |= c - 'a' + 10; |
val |= (c|0x20) - ('a' - 10); |
1257 |
else if (c >= 'A' && c <= 'F') |
else if (c == ':' || c == '\0') |
|
val |= c - 'A' + 10; |
|
|
else if (c == ':' || c == 0) |
|
1258 |
val >>= 4; |
val >>= 4; |
1259 |
else { |
else { |
1260 |
errno = EINVAL; |
errno = EINVAL; |
1261 |
return -1; |
return -1; |
1262 |
} |
} |
1263 |
if (c != 0) |
if (c != '\0') |
1264 |
bufp++; |
bufp++; |
1265 |
*ptr++ = (unsigned char) (val & 0377); |
*ptr++ = (unsigned char) (val & 0377); |
1266 |
i++; |
i++; |