networking/interface.c: code shrink

function                                             old     new   delta
ife_print                                           1293    1296      +3
display_interfaces                                   145     146      +1
if_readconf                                          162     141     -21
if_readlist_proc                                     631     560     -71
do_if_fetch                                          753     643    -110
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/3 up/down: 4/-202)           Total: -198 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko
2018-03-05 16:56:16 +01:00
parent 804ce5a6fe
commit 8a5299fcfd

View File

@@ -318,20 +318,27 @@ struct interface {
char name[IFNAMSIZ]; /* interface name */ char name[IFNAMSIZ]; /* interface name */
short type; /* if type */ short type; /* if type */
short flags; /* various flags */ short flags; /* various flags */
int tx_queue_len; /* transmit queue length */
/* these should be contiguous, zeroed in one go in if_fetch(): */
#define FIRST_TO_ZERO metric
int metric; /* routing metric */ int metric; /* routing metric */
int mtu; /* MTU value */ int mtu; /* MTU value */
int tx_queue_len; /* transmit queue length */
struct ifmap map; /* hardware setup */ struct ifmap map; /* hardware setup */
struct sockaddr addr; /* IP address */ struct sockaddr addr; /* IP address */
struct sockaddr dstaddr; /* P-P IP address */ struct sockaddr dstaddr; /* P-P IP address */
struct sockaddr broadaddr; /* IP broadcast address */ struct sockaddr broadaddr; /* IP broadcast address */
struct sockaddr netmask; /* IP network mask */ struct sockaddr netmask; /* IP network mask */
int has_ip;
char hwaddr[32]; /* HW address */ char hwaddr[32]; /* HW address */
int statistics_valid; #define LAST_TO_ZERO hwaddr
smallint has_ip;
smallint statistics_valid;
struct user_net_device_stats stats; /* statistics */ struct user_net_device_stats stats; /* statistics */
#if 0 /* UNUSED */
int keepalive; /* keepalive value for SLIP */ int keepalive; /* keepalive value for SLIP */
int outfill; /* outfill value for SLIP */ int outfill; /* outfill value for SLIP */
#endif
}; };
@@ -342,7 +349,7 @@ static struct interface *int_list, *int_last;
#if 0 #if 0
/* like strcmp(), but knows about numbers */ /* like strcmp(), but knows about numbers */
except that the freshly added calls to xatoul() brf on ethernet aliases with except that the freshly added calls to xatoul() barf on ethernet aliases with
uClibc with e.g.: ife->name='lo' name='eth0:1' uClibc with e.g.: ife->name='lo' name='eth0:1'
static int nstrcmp(const char *a, const char *b) static int nstrcmp(const char *a, const char *b)
{ {
@@ -394,32 +401,31 @@ static struct interface *add_interface(char *name)
return new; return new;
} }
static char *get_name(char *name, char *p) static char *get_name(char name[IFNAMSIZ], char *p)
{ {
/* Extract <name> from nul-terminated p where p matches /* Extract NAME from nul-terminated p of the form "<whitespace>NAME:"
* <name>: after leading whitespace. * If match is not made, set NAME to "" and return unchanged p.
* If match is not made, set name empty and return unchanged p
*/ */
char *nameend; char *nameend;
char *namestart = skip_whitespace(p); char *namestart;
nameend = namestart; nameend = namestart = skip_whitespace(p);
while (*nameend && *nameend != ':' && !isspace(*nameend))
nameend++; for (;;) {
if (*nameend == ':') { if ((nameend - namestart) >= IFNAMSIZ)
if ((nameend - namestart) < IFNAMSIZ) { break; /* interface name too large - return "" */
if (*nameend == ':') {
memcpy(name, namestart, nameend - namestart); memcpy(name, namestart, nameend - namestart);
name[nameend - namestart] = '\0'; name[nameend - namestart] = '\0';
p = nameend; return nameend + 1;
} else {
/* Interface name too large */
name[0] = '\0';
} }
} else { nameend++;
/* trailing ':' not found - return empty */ /* isspace, NUL, any control char? */
name[0] = '\0'; if ((unsigned char)*nameend <= (unsigned char)' ')
break; /* trailing ':' not found - return "" */
} }
return p + 1; name[0] = '\0';
return p;
} }
/* If scanf supports size qualifiers for %n conversions, then we can /* If scanf supports size qualifiers for %n conversions, then we can
@@ -435,7 +441,10 @@ static char *get_name(char *name, char *p)
/* "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" */ /* "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" */
/* }; */ /* }; */
/* Lie about the size of the int pointed to for %n. */ /* We use %n for unavailable data in older versions of /proc/net/dev formats.
* This results in bogus stores to ife->FOO members corresponding to
* %n specifiers (even the size of integers may not match).
*/
#if INT_MAX == LONG_MAX #if INT_MAX == LONG_MAX
static const char *const ss_fmt[] = { static const char *const ss_fmt[] = {
"%n%llu%u%u%u%u%n%n%n%llu%u%u%u%u%u", "%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[] = {
"%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu", "%llu%llu%lu%lu%lu%lu%n%n%llu%llu%lu%lu%lu%lu%lu",
"%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu" "%llu%llu%lu%lu%lu%lu%lu%lu%llu%llu%lu%lu%lu%lu%lu%lu"
}; };
#endif #endif
static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn) 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)
memset(&ife->stats, 0, sizeof(struct user_net_device_stats)); memset(&ife->stats, 0, sizeof(struct user_net_device_stats));
sscanf(bp, ss_fmt[procnetdev_vsn], sscanf(bp, ss_fmt[procnetdev_vsn],
&ife->stats.rx_bytes, /* missing for 0 */ &ife->stats.rx_bytes, /* missing for v0 */
&ife->stats.rx_packets, &ife->stats.rx_packets,
&ife->stats.rx_errors, &ife->stats.rx_errors,
&ife->stats.rx_dropped, &ife->stats.rx_dropped,
&ife->stats.rx_fifo_errors, &ife->stats.rx_fifo_errors,
&ife->stats.rx_frame_errors, &ife->stats.rx_frame_errors,
&ife->stats.rx_compressed, /* missing for <= 1 */ &ife->stats.rx_compressed, /* missing for v0, v1 */
&ife->stats.rx_multicast, /* missing for <= 1 */ &ife->stats.rx_multicast, /* missing for v0, v1 */
&ife->stats.tx_bytes, /* missing for 0 */ &ife->stats.tx_bytes, /* missing for v0 */
&ife->stats.tx_packets, &ife->stats.tx_packets,
&ife->stats.tx_errors, &ife->stats.tx_errors,
&ife->stats.tx_dropped, &ife->stats.tx_dropped,
&ife->stats.tx_fifo_errors, &ife->stats.tx_fifo_errors,
&ife->stats.collisions, &ife->stats.collisions,
&ife->stats.tx_carrier_errors, &ife->stats.tx_carrier_errors,
&ife->stats.tx_compressed /* missing for <= 1 */ &ife->stats.tx_compressed /* missing for v0, v1 */
); );
if (procnetdev_vsn <= 1) { if (procnetdev_vsn <= 1) {
@@ -499,24 +507,21 @@ static int if_readconf(void)
int numreqs = 30; int numreqs = 30;
struct ifconf ifc; struct ifconf ifc;
struct ifreq *ifr; struct ifreq *ifr;
int n, err = -1; int n, err;
int skfd; int skfd;
ifc.ifc_buf = NULL; ifc.ifc_buf = NULL;
/* SIOCGIFCONF currently seems to only work properly on AF_INET sockets /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
(as of 2.1.128) */ (as of 2.1.128) */
skfd = socket(AF_INET, SOCK_DGRAM, 0); skfd = xsocket(AF_INET, SOCK_DGRAM, 0);
if (skfd < 0) {
bb_perror_msg("error: no inet socket available");
return -1;
}
for (;;) { for (;;) {
ifc.ifc_len = sizeof(struct ifreq) * numreqs; ifc.ifc_len = sizeof(struct ifreq) * numreqs;
ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len); ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
if (ioctl_or_warn(skfd, SIOCGIFCONF, &ifc) < 0) { err = ioctl_or_warn(skfd, SIOCGIFCONF, &ifc);
if (err < 0) {
goto out; goto out;
} }
if (ifc.ifc_len == (int)(sizeof(struct ifreq) * numreqs)) { if (ifc.ifc_len == (int)(sizeof(struct ifreq) * numreqs)) {
@@ -565,7 +570,7 @@ static int if_readlist_proc(char *target)
err = 0; err = 0;
while (fgets(buf, sizeof buf, fh)) { while (fgets(buf, sizeof buf, fh)) {
char *s, name[128]; char *s, name[IFNAMSIZ];
s = get_name(name, buf); s = get_name(name, buf);
ife = add_interface(name); ife = add_interface(name);
@@ -574,11 +579,15 @@ static int if_readlist_proc(char *target)
if (target && strcmp(target, name) == 0) if (target && strcmp(target, name) == 0)
break; break;
} }
#if 0 /* we trust kernel to not be buggy, /proc/net/dev reads never fail */
if (ferror(fh)) { if (ferror(fh)) {
bb_perror_msg(_PATH_PROCNET_DEV); bb_perror_msg(_PATH_PROCNET_DEV);
err = -1; err = -1;
proc_read = 0; proc_read = 0;
} }
#endif
fclose(fh); fclose(fh);
return err; return err;
} }
@@ -608,24 +617,29 @@ static int if_fetch(struct interface *ife)
} }
ife->flags = ifr.ifr_flags; ife->flags = ifr.ifr_flags;
/* set up default values if ioctl's would fail */
ife->tx_queue_len = -1; /* unknown value */
memset(&ife->FIRST_TO_ZERO, 0,
offsetof(struct interface, LAST_TO_ZERO)
- offsetof(struct interface, FIRST_TO_ZERO)
+ sizeof(ife->LAST_TO_ZERO)
);
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
memset(ife->hwaddr, 0, 32);
if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0) if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0)
memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8); memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
//er.... why this _isnt_ inside if()?
ife->type = ifr.ifr_hwaddr.sa_family; ife->type = ifr.ifr_hwaddr.sa_family;
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
ife->metric = 0;
if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0) if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0)
ife->metric = ifr.ifr_metric; ife->metric = ifr.ifr_metric;
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
ife->mtu = 0;
if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0) if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0)
ife->mtu = ifr.ifr_mtu; ife->mtu = ifr.ifr_mtu;
memset(&ife->map, 0, sizeof(struct ifmap));
#ifdef SIOCGIFMAP #ifdef SIOCGIFMAP
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0) if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0)
@@ -634,31 +648,24 @@ static int if_fetch(struct interface *ife)
#ifdef HAVE_TXQUEUELEN #ifdef HAVE_TXQUEUELEN
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
ife->tx_queue_len = -1; /* unknown value */
if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0) if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0)
ife->tx_queue_len = ifr.ifr_qlen; ife->tx_queue_len = ifr.ifr_qlen;
#else
ife->tx_queue_len = -1; /* unknown value */
#endif #endif
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
ifr.ifr_addr.sa_family = AF_INET; ifr.ifr_addr.sa_family = AF_INET;
memset(&ife->addr, 0, sizeof(struct sockaddr));
if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) { if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) {
ife->has_ip = 1; ife->has_ip = 1;
ife->addr = ifr.ifr_addr; ife->addr = ifr.ifr_addr;
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0) if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0)
ife->dstaddr = ifr.ifr_dstaddr; ife->dstaddr = ifr.ifr_dstaddr;
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0) if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0)
ife->broadaddr = ifr.ifr_broadaddr; ife->broadaddr = ifr.ifr_broadaddr;
strncpy_IFNAMSIZ(ifr.ifr_name, ifname); strncpy_IFNAMSIZ(ifr.ifr_name, ifname);
memset(&ife->netmask, 0, sizeof(struct sockaddr));
if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0) if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0)
ife->netmask = ifr.ifr_netmask; ife->netmask = ifr.ifr_netmask;
} }
@@ -1020,9 +1027,11 @@ static void ife_print(struct interface *ptr)
/* DONT FORGET TO ADD THE FLAGS IN ife_print_short */ /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
printf(" MTU:%d Metric:%d", ptr->mtu, ptr->metric ? ptr->metric : 1); printf(" MTU:%d Metric:%d", ptr->mtu, ptr->metric ? ptr->metric : 1);
#if 0
#ifdef SIOCSKEEPALIVE #ifdef SIOCSKEEPALIVE
if (ptr->outfill || ptr->keepalive) if (ptr->outfill || ptr->keepalive)
printf(" Outfill:%d Keepalive:%d", ptr->outfill, ptr->keepalive); printf(" Outfill:%d Keepalive:%d", ptr->outfill, ptr->keepalive);
#endif
#endif #endif
bb_putchar('\n'); bb_putchar('\n');
@@ -1105,8 +1114,11 @@ static int for_all_interfaces(int (*doit) (struct interface *, void *),
{ {
struct interface *ife; struct interface *ife;
if (!int_list && (if_readlist() < 0)) if (!int_list) {
return -1; int err = if_readlist();
if (err < 0)
return err;
}
for (ife = int_list; ife; ife = ife->next) { for (ife = int_list; ife; ife = ife->next) {
int err = doit(ife, cookie); int err = doit(ife, cookie);
if (err) if (err)
@@ -1124,8 +1136,11 @@ static int if_print(char *ifname)
if (!ifname) { if (!ifname) {
/*res = for_all_interfaces(do_if_print, &interface_opt_a);*/ /*res = for_all_interfaces(do_if_print, &interface_opt_a);*/
if (!int_list && (if_readlist() < 0)) if (!int_list) {
return -1; int err = if_readlist();
if (err < 0)
return err;
}
for (ife = int_list; ife; ife = ife->next) { for (ife = int_list; ife; ife = ife->next) {
int err = do_if_print(ife); /*, &interface_opt_a);*/ int err = do_if_print(ife); /*, &interface_opt_a);*/
if (err) if (err)
@@ -1140,6 +1155,15 @@ static int if_print(char *ifname)
return res; return res;
} }
int FAST_FUNC display_interfaces(char *ifname)
{
int status;
status = if_print(ifname);
return (status < 0); /* status < 0 == 1 -- error */
}
#if ENABLE_FEATURE_HWIB #if ENABLE_FEATURE_HWIB
/* Input an Infiniband address and convert to binary. */ /* Input an Infiniband address and convert to binary. */
int FAST_FUNC in_ib(const char *bufp, struct sockaddr *sap) int FAST_FUNC in_ib(const char *bufp, struct sockaddr *sap)
@@ -1153,12 +1177,3 @@ int FAST_FUNC in_ib(const char *bufp, struct sockaddr *sap)
return 0; return 0;
} }
#endif #endif
int FAST_FUNC display_interfaces(char *ifname)
{
int status;
status = if_print(ifname);
return (status < 0); /* status < 0 == 1 -- error */
}