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:
@@ -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 */
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user