Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/networking/interface.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 532 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 15  Line 15 
15   *              that either displays or sets the characteristics of   *              that either displays or sets the characteristics of
16   *              one or more of the system's networking interfaces.   *              one or more of the system's networking interfaces.
17   *   *
  * Version:     $Id: interface.c,v 1.1 2007-09-01 22:43:53 niro Exp $  
18   *   *
19   * Author:      Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>   * Author:      Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
20   *              and others.  Copyright 1993 MicroWalt Corporation   *              and others.  Copyright 1993 MicroWalt Corporation
# Line 32  Line 31 
31   * (default AF was wrong)   * (default AF was wrong)
32   */   */
33    
 #include "inet_common.h"  
 #include <stdio.h>  
 #include <errno.h>  
 #include <stdlib.h>  
 #include <string.h>  
 #include <unistd.h>  
 #include <fcntl.h>  
 #include <ctype.h>  
 #include <sys/ioctl.h>  
 #include <sys/types.h>  
34  #include <net/if.h>  #include <net/if.h>
35  #include <net/if_arp.h>  #include <net/if_arp.h>
36  #include "busybox.h"  #include "inet_common.h"
37    #include "libbb.h"
38    
39    
40    #if ENABLE_FEATURE_HWIB
41    /* #include <linux/if_infiniband.h> */
42    #undef INFINIBAND_ALEN
43    #define INFINIBAND_ALEN 20
44    #endif
45    
46  #ifdef CONFIG_FEATURE_IPV6  #if ENABLE_FEATURE_IPV6
47  # define HAVE_AFINET6 1  # define HAVE_AFINET6 1
48  #else  #else
49  # undef HAVE_AFINET6  # undef HAVE_AFINET6
# Line 92  struct in6_ifreq { Line 89  struct in6_ifreq {
89  #endif  #endif
90    
91  /* Display an Internet socket address. */  /* Display an Internet socket address. */
92  static char *INET_sprint(struct sockaddr *sap, int numeric)  static const char* FAST_FUNC INET_sprint(struct sockaddr *sap, int numeric)
93  {  {
94   static char buff[128];   static char *buff;
95    
96     free(buff);
97   if (sap->sa_family == 0xFFFF || sap->sa_family == 0)   if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
98   return safe_strncpy(buff, "[NONE SET]", sizeof(buff));   return "[NONE SET]";
99     buff = INET_rresolve((struct sockaddr_in *) sap, numeric, 0xffffff00);
  if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap,  
   numeric, 0xffffff00) != 0)  
  return NULL;  
   
100   return buff;   return buff;
101  }  }
102    
103    #ifdef UNUSED_AND_BUGGY
104  static int INET_getsock(char *bufp, struct sockaddr *sap)  static int INET_getsock(char *bufp, struct sockaddr *sap)
105  {  {
106   char *sp = bufp, *bp;   char *sp = bufp, *bp;
# Line 146  static int INET_getsock(char *bufp, stru Line 141  static int INET_getsock(char *bufp, stru
141    
142   return (sp - bufp);   return (sp - bufp);
143  }  }
144    #endif
145    
146  static int INET_input(int type, char *bufp, struct sockaddr *sap)  static int FAST_FUNC INET_input(/*int type,*/ const char *bufp, struct sockaddr *sap)
147  {  {
148     return INET_resolve(bufp, (struct sockaddr_in *) sap, 0);
149    /*
150   switch (type) {   switch (type) {
151   case 1:   case 1:
152   return (INET_getsock(bufp, sap));   return (INET_getsock(bufp, sap));
# Line 157  static int INET_input(int type, char *bu Line 155  static int INET_input(int type, char *bu
155   default:   default:
156   return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0));   return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0));
157   }   }
158    */
159  }  }
160    
161  static struct aftype inet_aftype = {  static const struct aftype inet_aftype = {
162   .name = "inet",   .name   = "inet",
163   .title = "DARPA Internet",   .title  = "DARPA Internet",
164   .af = AF_INET,   .af     = AF_INET,
165   .alen = 4,   .alen   = 4,
166   .sprint = INET_sprint,   .sprint = INET_sprint,
167   .input = INET_input,   .input  = INET_input,
  .fd = -1  
168  };  };
169    
170  #ifdef HAVE_AFINET6  #ifdef HAVE_AFINET6
171    
172  /* Display an Internet socket address. */  /* Display an Internet socket address. */
173  /* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */  /* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */
174  static char *INET6_sprint(struct sockaddr *sap, int numeric)  static const char* FAST_FUNC INET6_sprint(struct sockaddr *sap, int numeric)
175  {  {
176   static char buff[128];   static char *buff;
177    
178     free(buff);
179   if (sap->sa_family == 0xFFFF || sap->sa_family == 0)   if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
180   return safe_strncpy(buff, "[NONE SET]", sizeof(buff));   return "[NONE SET]";
181   if (INET6_rresolve   buff = INET6_rresolve((struct sockaddr_in6 *) sap, numeric);
  (buff, sizeof(buff), (struct sockaddr_in6 *) sap, numeric) != 0)  
  return safe_strncpy(buff, "[UNKNOWN]", sizeof(buff));  
182   return buff;   return buff;
183  }  }
184    
185    #ifdef UNUSED
186  static int INET6_getsock(char *bufp, struct sockaddr *sap)  static int INET6_getsock(char *bufp, struct sockaddr *sap)
187  {  {
188   struct sockaddr_in6 *sin6;   struct sockaddr_in6 *sin6;
# Line 198  static int INET6_getsock(char *bufp, str Line 196  static int INET6_getsock(char *bufp, str
196    
197   return 16; /* ?;) */   return 16; /* ?;) */
198  }  }
199    #endif
200    
201  static int INET6_input(int type, char *bufp, struct sockaddr *sap)  static int FAST_FUNC INET6_input(/*int type,*/ const char *bufp, struct sockaddr *sap)
202  {  {
203     return INET6_resolve(bufp, (struct sockaddr_in6 *) sap);
204    /*
205   switch (type) {   switch (type) {
206   case 1:   case 1:
207   return (INET6_getsock(bufp, sap));   return (INET6_getsock(bufp, sap));
208   default:   default:
209   return (INET6_resolve(bufp, (struct sockaddr_in6 *) sap));   return (INET6_resolve(bufp, (struct sockaddr_in6 *) sap));
210   }   }
211    */
212  }  }
213    
214  static struct aftype inet6_aftype = {  static const struct aftype inet6_aftype = {
215   .name = "inet6",   .name   = "inet6",
216   .title = "IPv6",   .title  = "IPv6",
217   .af = AF_INET6,   .af     = AF_INET6,
218   .alen = sizeof(struct in6_addr),   .alen   = sizeof(struct in6_addr),
219   .sprint = INET6_sprint,   .sprint = INET6_sprint,
220   .input = INET6_input,   .input  = INET6_input,
  .fd = -1  
221  };  };
222    
223  #endif /* HAVE_AFINET6 */  #endif /* HAVE_AFINET6 */
224    
225  /* Display an UNSPEC address. */  /* Display an UNSPEC address. */
226  static char *UNSPEC_print(unsigned char *ptr)  static char* FAST_FUNC UNSPEC_print(unsigned char *ptr)
227  {  {
228   static char buff[sizeof(struct sockaddr) * 3 + 1];   static char *buff;
229    
230   char *pos;   char *pos;
231   unsigned int i;   unsigned int i;
232    
233     if (!buff)
234     buff = xmalloc(sizeof(struct sockaddr) * 3 + 1);
235   pos = buff;   pos = buff;
236   for (i = 0; i < sizeof(struct sockaddr); i++) {   for (i = 0; i < sizeof(struct sockaddr); i++) {
237   /* careful -- not every libc's sprintf returns # bytes written */   /* careful -- not every libc's sprintf returns # bytes written */
# Line 240  static char *UNSPEC_print(unsigned char Line 244  static char *UNSPEC_print(unsigned char
244  }  }
245    
246  /* Display an UNSPEC socket address. */  /* Display an UNSPEC socket address. */
247  static char *UNSPEC_sprint(struct sockaddr *sap, int numeric)  static const char* FAST_FUNC UNSPEC_sprint(struct sockaddr *sap, int numeric UNUSED_PARAM)
248  {  {
  static char buf[64];  
   
249   if (sap->sa_family == 0xFFFF || sap->sa_family == 0)   if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
250   return safe_strncpy(buf, "[NONE SET]", sizeof(buf));   return "[NONE SET]";
251   return UNSPEC_print((unsigned char *)sap->sa_data);   return UNSPEC_print((unsigned char *)sap->sa_data);
252  }  }
253    
254  static struct aftype unspec_aftype = {  static const struct aftype unspec_aftype = {
255   "unspec", "UNSPEC", AF_UNSPEC, 0,   .name   = "unspec",
256   UNSPEC_print, UNSPEC_sprint, NULL, NULL,   .title  = "UNSPEC",
257   NULL,   .af     = AF_UNSPEC,
258     .alen   = 0,
259     .print  = UNSPEC_print,
260     .sprint = UNSPEC_sprint,
261  };  };
262    
263  static struct aftype * const aftypes[] = {  static const struct aftype *const aftypes[] = {
264   &inet_aftype,   &inet_aftype,
265  #ifdef HAVE_AFINET6  #ifdef HAVE_AFINET6
266   &inet6_aftype,   &inet6_aftype,
# Line 265  static struct aftype * const aftypes[] = Line 270  static struct aftype * const aftypes[] =
270  };  };
271    
272  /* Check our protocol family table for this family. */  /* Check our protocol family table for this family. */
273  struct aftype *get_aftype(const char *name)  const struct aftype* FAST_FUNC get_aftype(const char *name)
274  {  {
275   struct aftype * const *afp;   const struct aftype *const *afp;
276    
277   afp = aftypes;   afp = aftypes;
278   while (*afp != NULL) {   while (*afp != NULL) {
# Line 279  struct aftype *get_aftype(const char *na Line 284  struct aftype *get_aftype(const char *na
284  }  }
285    
286  /* Check our protocol family table for this family. */  /* Check our protocol family table for this family. */
287  static struct aftype *get_afntype(int af)  static const struct aftype *get_afntype(int af)
288  {  {
289   struct aftype * const *afp;   const struct aftype *const *afp;
290    
291   afp = aftypes;   afp = aftypes;
292   while (*afp != NULL) {   while (*afp != NULL) {
# Line 292  static struct aftype *get_afntype(int af Line 297  static struct aftype *get_afntype(int af
297   return NULL;   return NULL;
298  }  }
299    
 /* Check our protocol family table for this family and return its socket */  
 static int get_socket_for_af(int af)  
 {  
  struct aftype * const *afp;  
   
  afp = aftypes;  
  while (*afp != NULL) {  
  if ((*afp)->af == af)  
  return (*afp)->fd;  
  afp++;  
  }  
  return -1;  
 }  
   
300  struct user_net_device_stats {  struct user_net_device_stats {
301   unsigned long long rx_packets; /* total packets received       */   unsigned long long rx_packets; /* total packets received       */
302   unsigned long long tx_packets; /* total packets transmitted    */   unsigned long long tx_packets; /* total packets transmitted    */
# Line 337  struct user_net_device_stats { Line 328  struct user_net_device_stats {
328    
329  struct interface {  struct interface {
330   struct interface *next, *prev;   struct interface *next, *prev;
331   char name[IFNAMSIZ]; /* interface name        */   char name[IFNAMSIZ];                    /* interface name        */
332   short type; /* if type               */   short type;                             /* if type               */
333   short flags; /* various flags         */   short flags;                            /* various flags         */
334   int metric; /* routing metric        */   int metric;                             /* routing metric        */
335   int mtu; /* MTU value             */   int mtu;                                /* MTU value             */
336   int tx_queue_len; /* transmit queue length */   int tx_queue_len;                       /* transmit queue length */
337   struct ifmap map; /* hardware setup        */   struct ifmap map;                       /* hardware setup        */
338   struct sockaddr addr; /* IP address            */   struct sockaddr addr;                   /* IP address            */
339   struct sockaddr dstaddr; /* P-P IP address        */   struct sockaddr dstaddr;                /* P-P IP address        */
340   struct sockaddr broadaddr; /* IP broadcast address  */   struct sockaddr broadaddr;              /* IP broadcast address  */
341   struct sockaddr netmask; /* IP network mask       */   struct sockaddr netmask;                /* IP network mask       */
342   int has_ip;   int has_ip;
343   char hwaddr[32]; /* HW address            */   char hwaddr[32];                        /* HW address            */
344   int statistics_valid;   int statistics_valid;
345   struct user_net_device_stats stats; /* statistics            */   struct user_net_device_stats stats;     /* statistics            */
346   int keepalive; /* keepalive value for SLIP */   int keepalive;                          /* keepalive value for SLIP */
347   int outfill; /* outfill value for SLIP */   int outfill;                            /* outfill value for SLIP */
348  };  };
349    
350    
351  int interface_opt_a; /* show all interfaces          */  smallint interface_opt_a; /* show all interfaces */
352    
353  static struct interface *int_list, *int_last;  static struct interface *int_list, *int_last;
 static int skfd = -1; /* generic raw socket desc.     */  
   
   
 static int sockets_open(int family)  
 {  
  struct aftype * const *aft;  
  int sfd = -1;  
  static int force = -1;  
354    
  if (force < 0) {  
  force = 0;  
  if (get_linux_version_code() < KERNEL_VERSION(2,1,0))  
  force = 1;  
  if (access("/proc/net", R_OK))  
  force = 1;  
  }  
  for (aft = aftypes; *aft; aft++) {  
  struct aftype *af = *aft;  
  int type = SOCK_DGRAM;  
   
  if (af->af == AF_UNSPEC)  
  continue;  
  if (family && family != af->af)  
  continue;  
  if (af->fd != -1) {  
  sfd = af->fd;  
  continue;  
  }  
  /* Check some /proc file first to not stress kmod */  
  if (!family && !force && af->flag_file) {  
  if (access(af->flag_file, R_OK))  
  continue;  
  }  
  af->fd = socket(af->af, type, 0);  
  if (af->fd >= 0)  
  sfd = af->fd;  
  }  
  if (sfd < 0) {  
  bb_error_msg("no usable address families found");  
  }  
  return sfd;  
 }  
355    
 #ifdef CONFIG_FEATURE_CLEAN_UP  
 static void sockets_close(void)  
 {  
  struct aftype * const *aft;  
  for (aft = aftypes; *aft != NULL; aft++) {  
  struct aftype *af = *aft;  
  if( af->fd != -1 ) {  
  close(af->fd);  
  af->fd = -1;  
  }  
  }  
 }  
 #endif  
356  #if 0  #if 0
357  /* like strcmp(), but knows about numbers */  /* like strcmp(), but knows about numbers */
358  except that the freshly added calls to xatoul() brf on ethernet aliases with  except that the freshly added calls to xatoul() brf on ethernet aliases with
# Line 458  static struct interface *add_interface(c Line 395  static struct interface *add_interface(c
395   }   }
396    
397   new = xzalloc(sizeof(*new));   new = xzalloc(sizeof(*new));
398   safe_strncpy(new->name, name, IFNAMSIZ);   strncpy(new->name, name, IFNAMSIZ);
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;
# Line 470  static struct interface *add_interface(c Line 407  static struct interface *add_interface(c
407   return new;   return new;
408  }  }
409    
   
 static int if_readconf(void)  
 {  
  int numreqs = 30;  
  struct ifconf ifc;  
  struct ifreq *ifr;  
  int n, err = -1;  
  int skfd2;  
   
  /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets  
    (as of 2.1.128) */  
  skfd2 = get_socket_for_af(AF_INET);  
  if (skfd2 < 0) {  
  bb_perror_msg(("warning: no inet socket available"));  
  /* Try to soldier on with whatever socket we can get hold of.  */  
  skfd2 = sockets_open(0);  
  if (skfd2 < 0)  
  return -1;  
  }  
   
  ifc.ifc_buf = NULL;  
  for (;;) {  
  ifc.ifc_len = sizeof(struct ifreq) * numreqs;  
  ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);  
   
  if (ioctl(skfd2, SIOCGIFCONF, &ifc) < 0) {  
  perror("SIOCGIFCONF");  
  goto out;  
  }  
  if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {  
  /* assume it overflowed and try again */  
  numreqs += 10;  
  continue;  
  }  
  break;  
  }  
   
  ifr = ifc.ifc_req;  
  for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {  
  add_interface(ifr->ifr_name);  
  ifr++;  
  }  
  err = 0;  
   
   out:  
  free(ifc.ifc_buf);  
  return err;  
 }  
   
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;   int namestart = 0, nameend = 0;
416    
417   while (isspace(p[namestart]))   while (isspace(p[namestart]))
418   namestart++;   namestart++;
419   nameend=namestart;   nameend = namestart;
420   while (p[nameend] && p[nameend]!=':' && !isspace(p[nameend]))   while (p[nameend] && p[nameend] != ':' && !isspace(p[nameend]))
421   nameend++;   nameend++;
422   if (p[nameend]==':') {   if (p[nameend] == ':') {
423   if ((nameend-namestart)<IFNAMSIZ) {   if ((nameend - namestart) < IFNAMSIZ) {
424   memcpy(name,&p[namestart],nameend-namestart);   memcpy(name, &p[namestart], nameend - namestart);
425   name[nameend-namestart]='\0';   name[nameend - namestart] = '\0';
426   p=&p[nameend];   p = &p[nameend];
427   } else {   } else {
428   /* Interface name too large */   /* Interface name too large */
429   name[0]='\0';   name[0] = '\0';
430   }   }
431   } else {   } else {
432   /* trailing ':' not found - return empty */   /* trailing ':' not found - return empty */
433   name[0]='\0';   name[0] = '\0';
434   }   }
435   return p + 1;   return p + 1;
436  }  }
# Line 553  static char *get_name(char *name, char * Line 442  static char *get_name(char *name, char *
442   * old approach of multiple scanf occurrences with large numbers of   * old approach of multiple scanf occurrences with large numbers of
443   * args. */   * args. */
444    
445  /* static const char * const ss_fmt[] = { */  /* static const char *const ss_fmt[] = { */
446  /* "%lln%llu%lu%lu%lu%lu%ln%ln%lln%llu%lu%lu%lu%lu%lu", */  /* "%lln%llu%lu%lu%lu%lu%ln%ln%lln%llu%lu%lu%lu%lu%lu", */
447  /* "%llu%llu%lu%lu%lu%lu%ln%ln%llu%llu%lu%lu%lu%lu%lu", */  /* "%llu%llu%lu%lu%lu%lu%ln%ln%llu%llu%lu%lu%lu%lu%lu", */
448  /* "%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" */
# Line 561  static char *get_name(char *name, char * Line 450  static char *get_name(char *name, char *
450    
451   /* Lie about the size of the int pointed to for %n. */   /* Lie about the size of the int pointed to for %n. */
452  #if INT_MAX == LONG_MAX  #if INT_MAX == LONG_MAX
453  static const char * const ss_fmt[] = {  static const char *const ss_fmt[] = {
454   "%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",
455   "%llu%llu%u%u%u%u%n%n%llu%llu%u%u%u%u%u",   "%llu%llu%u%u%u%u%n%n%llu%llu%u%u%u%u%u",
456   "%llu%llu%u%u%u%u%u%u%llu%llu%u%u%u%u%u%u"   "%llu%llu%u%u%u%u%u%u%llu%llu%u%u%u%u%u%u"
457  };  };
458  #else  #else
459  static const char * const ss_fmt[] = {  static const char *const ss_fmt[] = {
460   "%n%llu%lu%lu%lu%lu%n%n%n%llu%lu%lu%lu%lu%lu",   "%n%llu%lu%lu%lu%lu%n%n%n%llu%lu%lu%lu%lu%lu",
461   "%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",
462   "%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"
# Line 609  static void get_dev_fields(char *bp, str Line 498  static void get_dev_fields(char *bp, str
498   }   }
499  }  }
500    
501  static inline int procnetdev_version(char *buf)  static int procnetdev_version(char *buf)
502  {  {
503   if (strstr(buf, "compressed"))   if (strstr(buf, "compressed"))
504   return 2;   return 2;
# Line 618  static inline int procnetdev_version(cha Line 507  static inline int procnetdev_version(cha
507   return 0;   return 0;
508  }  }
509    
510    static int if_readconf(void)
511    {
512     int numreqs = 30;
513     struct ifconf ifc;
514     struct ifreq *ifr;
515     int n, err = -1;
516     int skfd;
517    
518     ifc.ifc_buf = NULL;
519    
520     /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
521       (as of 2.1.128) */
522     skfd = socket(AF_INET, SOCK_DGRAM, 0);
523     if (skfd < 0) {
524     bb_perror_msg("error: no inet socket available");
525     return -1;
526     }
527    
528     for (;;) {
529     ifc.ifc_len = sizeof(struct ifreq) * numreqs;
530     ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
531    
532     if (ioctl_or_warn(skfd, SIOCGIFCONF, &ifc) < 0) {
533     goto out;
534     }
535     if (ifc.ifc_len == (int)(sizeof(struct ifreq) * numreqs)) {
536     /* assume it overflowed and try again */
537     numreqs += 10;
538     continue;
539     }
540     break;
541     }
542    
543     ifr = ifc.ifc_req;
544     for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
545     add_interface(ifr->ifr_name);
546     ifr++;
547     }
548     err = 0;
549    
550     out:
551     close(skfd);
552     free(ifc.ifc_buf);
553     return err;
554    }
555    
556  static int if_readlist_proc(char *target)  static int if_readlist_proc(char *target)
557  {  {
558   static int proc_read;   static smallint proc_read;
559    
560   FILE *fh;   FILE *fh;
561   char buf[512];   char buf[512];
562   struct interface *ife;   struct interface *ife;
# Line 631  static int if_readlist_proc(char *target Line 567  static int if_readlist_proc(char *target
567   if (!target)   if (!target)
568   proc_read = 1;   proc_read = 1;
569    
570   fh = fopen(_PATH_PROCNET_DEV, "r");   fh = fopen_or_warn(_PATH_PROCNET_DEV, "r");
571   if (!fh) {   if (!fh) {
  bb_perror_msg("warning: cannot open %s, limiting output", _PATH_PROCNET_DEV);  
572   return if_readconf();   return if_readconf();
573   }   }
574   fgets(buf, sizeof buf, fh); /* eat line */   fgets(buf, sizeof buf, fh); /* eat line */
# Line 653  static int if_readlist_proc(char *target Line 588  static int if_readlist_proc(char *target
588   break;   break;
589   }   }
590   if (ferror(fh)) {   if (ferror(fh)) {
591   perror(_PATH_PROCNET_DEV);   bb_perror_msg(_PATH_PROCNET_DEV);
592   err = -1;   err = -1;
593   proc_read = 0;   proc_read = 0;
594   }   }
# Line 664  static int if_readlist_proc(char *target Line 599  static int if_readlist_proc(char *target
599  static int if_readlist(void)  static int if_readlist(void)
600  {  {
601   int err = if_readlist_proc(NULL);   int err = if_readlist_proc(NULL);
602     /* Needed in order to get ethN:M aliases */
603   if (!err)   if (!err)
604   err = if_readconf();   err = if_readconf();
605   return err;   return err;
606  }  }
607    
 static int for_all_interfaces(int (*doit) (struct interface *, void *),  
   void *cookie)  
 {  
  struct interface *ife;  
   
  if (!int_list && (if_readlist() < 0))  
  return -1;  
  for (ife = int_list; ife; ife = ife->next) {  
  int err = doit(ife, cookie);  
   
  if (err)  
  return err;  
  }  
  return 0;  
 }  
   
608  /* Fetch the interface configuration from the kernel. */  /* Fetch the interface configuration from the kernel. */
609  static int if_fetch(struct interface *ife)  static int if_fetch(struct interface *ife)
610  {  {
611   struct ifreq ifr;   struct ifreq ifr;
  int fd;  
612   char *ifname = ife->name;   char *ifname = ife->name;
613     int skfd;
614    
615     skfd = xsocket(AF_INET, SOCK_DGRAM, 0);
616    
617   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
618   if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)   if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) {
619     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(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
625   if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)   memset(ife->hwaddr, 0, 32);
626   memset(ife->hwaddr, 0, 32);   if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0)
  else  
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(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
632   if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)   ife->metric = 0;
633   ife->metric = 0;   if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0)
  else  
634   ife->metric = ifr.ifr_metric;   ife->metric = ifr.ifr_metric;
635    
636   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
637   if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)   ife->mtu = 0;
638   ife->mtu = 0;   if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0)
  else  
639   ife->mtu = ifr.ifr_mtu;   ife->mtu = ifr.ifr_mtu;
640    
641     memset(&ife->map, 0, sizeof(struct ifmap));
642  #ifdef SIOCGIFMAP  #ifdef SIOCGIFMAP
643   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
644   if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0)   if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0)
645   ife->map = ifr.ifr_map;   ife->map = ifr.ifr_map;
  else  
646  #endif  #endif
  memset(&ife->map, 0, sizeof(struct ifmap));  
647    
648  #ifdef HAVE_TXQUEUELEN  #ifdef HAVE_TXQUEUELEN
649   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
650   if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)   ife->tx_queue_len = -1; /* unknown value */
651   ife->tx_queue_len = -1; /* unknown value */   if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0)
  else  
652   ife->tx_queue_len = ifr.ifr_qlen;   ife->tx_queue_len = ifr.ifr_qlen;
653  #else  #else
654   ife->tx_queue_len = -1; /* unknown value */   ife->tx_queue_len = -1; /* unknown value */
655  #endif  #endif
656    
657   /* IPv4 address? */   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
658   fd = get_socket_for_af(AF_INET);   ifr.ifr_addr.sa_family = AF_INET;
659   if (fd >= 0) {   memset(&ife->addr, 0, sizeof(struct sockaddr));
660     if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) {
661     ife->has_ip = 1;
662     ife->addr = ifr.ifr_addr;
663     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
664     memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
665     if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0)
666     ife->dstaddr = ifr.ifr_dstaddr;
667    
668     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
669     memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
670     if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0)
671     ife->broadaddr = ifr.ifr_broadaddr;
672    
673   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
674   ifr.ifr_addr.sa_family = AF_INET;   memset(&ife->netmask, 0, sizeof(struct sockaddr));
675   if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {   if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0)
676   ife->has_ip = 1;   ife->netmask = ifr.ifr_netmask;
  ife->addr = ifr.ifr_addr;  
  strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));  
  if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)  
  memset(&ife->dstaddr, 0, sizeof(struct sockaddr));  
  else  
  ife->dstaddr = ifr.ifr_dstaddr;  
   
  strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));  
  if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)  
  memset(&ife->broadaddr, 0, sizeof(struct sockaddr));  
  else  
  ife->broadaddr = ifr.ifr_broadaddr;  
   
  strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));  
  if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)  
  memset(&ife->netmask, 0, sizeof(struct sockaddr));  
  else  
  ife->netmask = ifr.ifr_netmask;  
  } else  
  memset(&ife->addr, 0, sizeof(struct sockaddr));  
677   }   }
678    
679     close(skfd);
680   return 0;   return 0;
681  }  }
682    
   
683  static int do_if_fetch(struct interface *ife)  static int do_if_fetch(struct interface *ife)
684  {  {
685   if (if_fetch(ife) < 0) {   if (if_fetch(ife) < 0) {
686   char *errmsg;   const char *errmsg;
687    
688   if (errno == ENODEV) {   if (errno == ENODEV) {
689   /* Give better error message for this case. */   /* Give better error message for this case. */
# Line 809  static const struct hwtype loop_hwtype = Line 720  static const struct hwtype loop_hwtype =
720  #endif  #endif
721    
722  /* Display an Ethernet address in readable format. */  /* Display an Ethernet address in readable format. */
723  static char *pr_ether(unsigned char *ptr)  static char* FAST_FUNC ether_print(unsigned char *ptr)
724  {  {
725   static char buff[64];   static char *buff;
726    
727   snprintf(buff, sizeof(buff), "%02X:%02X:%02X:%02X:%02X:%02X",   free(buff);
728     buff = xasprintf("%02X:%02X:%02X:%02X:%02X:%02X",
729   (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),   (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
730   (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)   (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
731   );   );
732   return buff;   return buff;
733  }  }
734    
735  static int in_ether(char *bufp, struct sockaddr *sap);  static int FAST_FUNC ether_input(const char *bufp, struct sockaddr *sap);
736    
737  static struct hwtype ether_hwtype = {  static const struct hwtype ether_hwtype = {
738   .name = "ether",   .name  = "ether",
739   .title = "Ethernet",   .title = "Ethernet",
740   .type = ARPHRD_ETHER,   .type  = ARPHRD_ETHER,
741   .alen = ETH_ALEN,   .alen  = ETH_ALEN,
742   .print = pr_ether,   .print = ether_print,
743   .input = in_ether   .input = ether_input
744  };  };
745    
746  static unsigned hexchar2int(char c)  static unsigned hexchar2int(char c)
# Line 842  static unsigned hexchar2int(char c) Line 754  static unsigned hexchar2int(char c)
754  }  }
755    
756  /* Input an Ethernet address and convert to binary. */  /* Input an Ethernet address and convert to binary. */
757  static int in_ether(char *bufp, struct sockaddr *sap)  static int FAST_FUNC ether_input(const char *bufp, struct sockaddr *sap)
758  {  {
759   unsigned char *ptr;   unsigned char *ptr;
760   char c, *orig;   char c;
761   int i;   int i;
762   unsigned val;   unsigned val;
763    
764   sap->sa_family = ether_hwtype.type;   sap->sa_family = ether_hwtype.type;
765   ptr = sap->sa_data;   ptr = (unsigned char*) sap->sa_data;
766    
767   i = 0;   i = 0;
  orig = bufp;  
768   while ((*bufp != '\0') && (i < ETH_ALEN)) {   while ((*bufp != '\0') && (i < ETH_ALEN)) {
769   val = hexchar2int(*bufp++) * 0x10;   val = hexchar2int(*bufp++) * 0x10;
770   if (val > 0xff) {   if (val > 0xff) {
# Line 891  static const struct hwtype ppp_hwtype = Line 802  static const struct hwtype ppp_hwtype =
802   .type = ARPHRD_PPP   .type = ARPHRD_PPP
803  };  };
804    
805  #ifdef CONFIG_FEATURE_IPV6  #if ENABLE_FEATURE_IPV6
806  static const struct hwtype sit_hwtype = {  static const struct hwtype sit_hwtype = {
807   .name = "sit",   .name = "sit",
808   .title = "IPv6-in-IPv4",   .title = "IPv6-in-IPv4",
809   .type = ARPHRD_SIT,   .type = ARPHRD_SIT,
810   .print = UNSPEC_print,   .print = UNSPEC_print,
811   .suppress_null_addr = 1   .suppress_null_addr = 1
812  } ;  };
813    #endif
814    #if ENABLE_FEATURE_HWIB
815    static const struct hwtype ib_hwtype = {
816     .name  = "infiniband",
817     .title = "InfiniBand",
818     .type  = ARPHRD_INFINIBAND,
819     .alen  = INFINIBAND_ALEN,
820     .print = UNSPEC_print,
821     .input = in_ib,
822    };
823  #endif  #endif
824    
825  static const struct hwtype * const hwtypes[] = {  
826    static const struct hwtype *const hwtypes[] = {
827   &loop_hwtype,   &loop_hwtype,
828   &ether_hwtype,   &ether_hwtype,
829   &ppp_hwtype,   &ppp_hwtype,
830   &unspec_hwtype,   &unspec_hwtype,
831  #ifdef CONFIG_FEATURE_IPV6  #if ENABLE_FEATURE_IPV6
832   &sit_hwtype,   &sit_hwtype,
833  #endif  #endif
834    #if ENABLE_FEATURE_HWIB
835     &ib_hwtype,
836    #endif
837   NULL   NULL
838  };  };
839    
840  #ifdef IFF_PORTSEL  #ifdef IFF_PORTSEL
841  static const char * const if_port_text[] = {  static const char *const if_port_text[] = {
842   /* Keep in step with <linux/netdevice.h> */   /* Keep in step with <linux/netdevice.h> */
843   "unknown",   "unknown",
844   "10base2",   "10base2",
# Line 927  static const char * const if_port_text[] Line 852  static const char * const if_port_text[]
852  #endif  #endif
853    
854  /* Check our hardware type table for this type. */  /* Check our hardware type table for this type. */
855  const struct hwtype *get_hwtype(const char *name)  const struct hwtype* FAST_FUNC get_hwtype(const char *name)
856  {  {
857   const struct hwtype * const *hwp;   const struct hwtype *const *hwp;
858    
859   hwp = hwtypes;   hwp = hwtypes;
860   while (*hwp != NULL) {   while (*hwp != NULL) {
# Line 941  const struct hwtype *get_hwtype(const ch Line 866  const struct hwtype *get_hwtype(const ch
866  }  }
867    
868  /* Check our hardware type table for this type. */  /* Check our hardware type table for this type. */
869  const struct hwtype *get_hwntype(int type)  const struct hwtype* FAST_FUNC get_hwntype(int type)
870  {  {
871   const struct hwtype * const *hwp;   const struct hwtype *const *hwp;
872    
873   hwp = hwtypes;   hwp = hwtypes;
874   while (*hwp != NULL) {   while (*hwp != NULL) {
# Line 957  const struct hwtype *get_hwntype(int typ Line 882  const struct hwtype *get_hwntype(int typ
882  /* return 1 if address is all zeros */  /* return 1 if address is all zeros */
883  static int hw_null_address(const struct hwtype *hw, void *ap)  static int hw_null_address(const struct hwtype *hw, void *ap)
884  {  {
885   unsigned int i;   int i;
886   unsigned char *address = (unsigned char *) ap;   unsigned char *address = (unsigned char *) ap;
887    
888   for (i = 0; i < hw->alen; i++)   for (i = 0; i < hw->alen; i++)
# Line 966  static int hw_null_address(const struct Line 891  static int hw_null_address(const struct
891   return 1;   return 1;
892  }  }
893    
894  static const char TRext[] = "\0\0\0Ki\0Mi\0Gi\0Ti";  static const char TRext[] ALIGN1 = "\0\0\0Ki\0Mi\0Gi\0Ti";
895    
896  static void print_bytes_scaled(unsigned long long ull, const char *end)  static void print_bytes_scaled(unsigned long long ull, const char *end)
897  {  {
# Line 991  static void print_bytes_scaled(unsigned Line 916  static void print_bytes_scaled(unsigned
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 const char * const ife_print_flags_strs[] = {  
  "UP ",  
  "BROADCAST ",  
  "DEBUG ",  
  "LOOPBACK ",  
  "POINTOPOINT ",  
  "NOTRAILERS ",  
  "RUNNING ",  
  "NOARP ",  
  "PROMISC ",  
  "ALLMULTI ",  
  "SLAVE ",  
  "MASTER ",  
  "MULTICAST ",  
 #ifdef HAVE_DYNAMIC  
  "DYNAMIC "  
 #endif  
 };  
   
 static const unsigned short ife_print_flags_mask[] = {  
  IFF_UP,  
  IFF_BROADCAST,  
  IFF_DEBUG,  
  IFF_LOOPBACK,  
  IFF_POINTOPOINT,  
  IFF_NOTRAILERS,  
  IFF_RUNNING,  
  IFF_NOARP,  
  IFF_PROMISC,  
  IFF_ALLMULTI,  
  IFF_SLAVE,  
  IFF_MASTER,  
  IFF_MULTICAST,  
 #ifdef HAVE_DYNAMIC  
  IFF_DYNAMIC  
 #endif  
  0  
 };  
   
919  static void ife_print(struct interface *ptr)  static void ife_print(struct interface *ptr)
920  {  {
921   struct aftype *ap;   const struct aftype *ap;
922   const struct hwtype *hw;   const struct hwtype *hw;
923   int hf;   int hf;
924   int can_compress = 0;   int can_compress = 0;
# Line 1071  static void ife_print(struct interface * Line 957  static void ife_print(struct interface *
957   printf("(auto)");   printf("(auto)");
958   }   }
959  #endif  #endif
960   puts("");   bb_putchar('\n');
961    
962   if (ptr->has_ip) {   if (ptr->has_ip) {
963   printf("          %s addr:%s ", ap->name,   printf("          %s addr:%s ", ap->name,
# Line 1104  static void ife_print(struct interface * Line 990  static void ife_print(struct interface *
990  #define IPV6_ADDR_MAPPED        0x1000U  #define IPV6_ADDR_MAPPED        0x1000U
991  #define IPV6_ADDR_RESERVED      0x2000U /* reserved address space */  #define IPV6_ADDR_RESERVED      0x2000U /* reserved address space */
992    
993   if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {   f = fopen_for_read(_PATH_PROCNET_IFINET6);
994     if (f != NULL) {
995   while (fscanf   while (fscanf
996     (f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",     (f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
997   addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],   addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
998   addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope,   addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope,
999   &dad_status, devname) != EOF) {   &dad_status, devname) != EOF
1000     ) {
1001   if (!strcmp(devname, ptr->name)) {   if (!strcmp(devname, ptr->name)) {
1002   sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",   sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
1003   addr6p[0], addr6p[1], addr6p[2], addr6p[3],   addr6p[0], addr6p[1], addr6p[2], addr6p[3],
# Line 1118  static void ife_print(struct interface * Line 1006  static void ife_print(struct interface *
1006    (struct sockaddr *) &sap.sin6_addr);    (struct sockaddr *) &sap.sin6_addr);
1007   sap.sin6_family = AF_INET6;   sap.sin6_family = AF_INET6;
1008   printf("          inet6 addr: %s/%d",   printf("          inet6 addr: %s/%d",
1009     inet6_aftype.sprint((struct sockaddr *) &sap, 1),     INET6_sprint((struct sockaddr *) &sap, 1),
1010     plen);     plen);
1011   printf(" Scope:");   printf(" Scope:");
1012   switch (scope & IPV6_ADDR_SCOPE_MASK) {   switch (scope & IPV6_ADDR_SCOPE_MASK) {
1013   case 0:   case 0:
1014   printf("Global");   puts("Global");
1015   break;   break;
1016   case IPV6_ADDR_LINKLOCAL:   case IPV6_ADDR_LINKLOCAL:
1017   printf("Link");   puts("Link");
1018   break;   break;
1019   case IPV6_ADDR_SITELOCAL:   case IPV6_ADDR_SITELOCAL:
1020   printf("Site");   puts("Site");
1021   break;   break;
1022   case IPV6_ADDR_COMPATv4:   case IPV6_ADDR_COMPATv4:
1023   printf("Compat");   puts("Compat");
1024   break;   break;
1025   case IPV6_ADDR_LOOPBACK:   case IPV6_ADDR_LOOPBACK:
1026   printf("Host");   puts("Host");
1027   break;   break;
1028   default:   default:
1029   printf("Unknown");   puts("Unknown");
1030   }   }
  puts("");  
1031   }   }
1032   }   }
1033   fclose(f);   fclose(f);
# Line 1153  static void ife_print(struct interface * Line 1040  static void ife_print(struct interface *
1040   if (ptr->flags == 0) {   if (ptr->flags == 0) {
1041   printf("[NO FLAGS] ");   printf("[NO FLAGS] ");
1042   } else {   } else {
1043   int i = 0;   static const char ife_print_flags_strs[] ALIGN1 =
1044     "UP\0"
1045     "BROADCAST\0"
1046     "DEBUG\0"
1047     "LOOPBACK\0"
1048     "POINTOPOINT\0"
1049     "NOTRAILERS\0"
1050     "RUNNING\0"
1051     "NOARP\0"
1052     "PROMISC\0"
1053     "ALLMULTI\0"
1054     "SLAVE\0"
1055     "MASTER\0"
1056     "MULTICAST\0"
1057    #ifdef HAVE_DYNAMIC
1058     "DYNAMIC\0"
1059    #endif
1060     ;
1061     static const unsigned short ife_print_flags_mask[] ALIGN2 = {
1062     IFF_UP,
1063     IFF_BROADCAST,
1064     IFF_DEBUG,
1065     IFF_LOOPBACK,
1066     IFF_POINTOPOINT,
1067     IFF_NOTRAILERS,
1068     IFF_RUNNING,
1069     IFF_NOARP,
1070     IFF_PROMISC,
1071     IFF_ALLMULTI,
1072     IFF_SLAVE,
1073     IFF_MASTER,
1074     IFF_MULTICAST
1075    #ifdef HAVE_DYNAMIC
1076     ,IFF_DYNAMIC
1077    #endif
1078     };
1079     const unsigned short *mask = ife_print_flags_mask;
1080     const char *str = ife_print_flags_strs;
1081   do {   do {
1082   if (ptr->flags & ife_print_flags_mask[i]) {   if (ptr->flags & *mask) {
1083   printf(ife_print_flags_strs[i]);   printf("%s ", str);
1084   }   }
1085   } while (ife_print_flags_mask[++i]);   mask++;
1086     str += strlen(str) + 1;
1087     } while (*str);
1088   }   }
1089    
1090   /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */   /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
# Line 1167  static void ife_print(struct interface * Line 1093  static void ife_print(struct interface *
1093   if (ptr->outfill || ptr->keepalive)   if (ptr->outfill || ptr->keepalive)
1094   printf("  Outfill:%d  Keepalive:%d", ptr->outfill, ptr->keepalive);   printf("  Outfill:%d  Keepalive:%d", ptr->outfill, ptr->keepalive);
1095  #endif  #endif
1096   puts("");   bb_putchar('\n');
1097    
1098   /* If needed, display the interface statistics. */   /* If needed, display the interface statistics. */
1099    
# Line 1216  static void ife_print(struct interface * Line 1142  static void ife_print(struct interface *
1142   }   }
1143   if (ptr->map.dma)   if (ptr->map.dma)
1144   printf("DMA chan:%x ", ptr->map.dma);   printf("DMA chan:%x ", ptr->map.dma);
1145   puts("");   bb_putchar('\n');
1146   }   }
1147   puts("");   bb_putchar('\n');
1148  }  }
1149    
1150    
1151  static int do_if_print(struct interface *ife, void *cookie)  static int do_if_print(struct interface *ife) /*, int *opt_a)*/
1152  {  {
  int *opt_a = (int *) cookie;  
1153   int res;   int res;
1154    
1155   res = do_if_fetch(ife);   res = do_if_fetch(ife);
1156   if (res >= 0) {   if (res >= 0) {
1157   if ((ife->flags & IFF_UP) || *opt_a)   if ((ife->flags & IFF_UP) || interface_opt_a)
1158   ife_print(ife);   ife_print(ife);
1159   }   }
1160   return res;   return res;
# Line 1245  static struct interface *lookup_interfac Line 1170  static struct interface *lookup_interfac
1170   return ife;   return ife;
1171  }  }
1172    
1173    #ifdef UNUSED
1174    static int for_all_interfaces(int (*doit) (struct interface *, void *),
1175      void *cookie)
1176    {
1177     struct interface *ife;
1178    
1179     if (!int_list && (if_readlist() < 0))
1180     return -1;
1181     for (ife = int_list; ife; ife = ife->next) {
1182     int err = doit(ife, cookie);
1183    
1184     if (err)
1185     return err;
1186     }
1187     return 0;
1188    }
1189    #endif
1190    
1191  /* for ipv4 add/del modes */  /* for ipv4 add/del modes */
1192  static int if_print(char *ifname)  static int if_print(char *ifname)
1193  {  {
1194     struct interface *ife;
1195   int res;   int res;
1196    
1197   if (!ifname) {   if (!ifname) {
1198   res = for_all_interfaces(do_if_print, &interface_opt_a);   /*res = for_all_interfaces(do_if_print, &interface_opt_a);*/
1199   } else {   if (!int_list && (if_readlist() < 0))
1200   struct interface *ife;   return -1;
1201     for (ife = int_list; ife; ife = ife->next) {
1202   ife = lookup_interface(ifname);   int err = do_if_print(ife); /*, &interface_opt_a);*/
1203   res = do_if_fetch(ife);   if (err)
1204   if (res >= 0)   return err;
1205   ife_print(ife);   }
1206     return 0;
1207   }   }
1208     ife = lookup_interface(ifname);
1209     res = do_if_fetch(ife);
1210     if (res >= 0)
1211     ife_print(ife);
1212   return res;   return res;
1213  }  }
1214    
1215  int display_interfaces(char *ifname)  #if ENABLE_FEATURE_HWIB
1216    /* Input an Infiniband address and convert to binary. */
1217    int FAST_FUNC in_ib(const char *bufp, struct sockaddr *sap)
1218  {  {
1219   int status;   unsigned char *ptr;
1220     char c;
1221     const char *orig;
1222     int i;
1223     unsigned val;
1224    
1225   /* Create a channel to the NET kernel. */   sap->sa_family = ib_hwtype.type;
1226   if ((skfd = sockets_open(0)) < 0) {   ptr = (unsigned char *) sap->sa_data;
1227   bb_perror_msg_and_die("socket");  
1228     i = 0;
1229     orig = bufp;
1230     while ((*bufp != '\0') && (i < INFINIBAND_ALEN)) {
1231     val = 0;
1232     c = *bufp++;
1233     if (isdigit(c))
1234     val = c - '0';
1235     else if (c >= 'a' && c <= 'f')
1236     val = c - 'a' + 10;
1237     else if (c >= 'A' && c <= 'F')
1238     val = c - 'A' + 10;
1239     else {
1240     errno = EINVAL;
1241     return -1;
1242     }
1243     val <<= 4;
1244     c = *bufp;
1245     if (isdigit(c))
1246     val |= c - '0';
1247     else if (c >= 'a' && c <= 'f')
1248     val |= c - 'a' + 10;
1249     else if (c >= 'A' && c <= 'F')
1250     val |= c - 'A' + 10;
1251     else if (c == ':' || c == 0)
1252     val >>= 4;
1253     else {
1254     errno = EINVAL;
1255     return -1;
1256     }
1257     if (c != 0)
1258     bufp++;
1259     *ptr++ = (unsigned char) (val & 0377);
1260     i++;
1261    
1262     /* We might get a semicolon here - not required. */
1263     if (*bufp == ':') {
1264     bufp++;
1265     }
1266   }   }
1267    #ifdef DEBUG
1268     fprintf(stderr, "in_ib(%s): %s\n", orig, UNSPEC_print(sap->sa_data));
1269    #endif
1270     return 0;
1271    }
1272    #endif
1273    
1274    
1275    int FAST_FUNC display_interfaces(char *ifname)
1276    {
1277     int status;
1278    
  /* Do we have to show the current setup? */  
1279   status = if_print(ifname);   status = if_print(ifname);
1280  #ifdef CONFIG_FEATURE_CLEAN_UP  
1281   sockets_close();   return (status < 0); /* status < 0 == 1 -- error */
 #endif  
  exit(status < 0);  
1282  }  }

Legend:
Removed from v.532  
changed lines
  Added in v.816