Whitespace / formatting / bracket cleanup.
[oweals/busybox.git] / interface.c
1 /*
2  * ifconfig   This file contains an implementation of the command
3  *              that either displays or sets the characteristics of
4  *              one or more of the system's networking interfaces.
5  *
6  * Version:     $Id: interface.c,v 1.2 2001/03/06 20:54:43 andersen Exp $
7  *
8  * Author:      Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
9  *              and others.  Copyright 1993 MicroWalt Corporation
10  *
11  *              This program is free software; you can redistribute it
12  *              and/or  modify it under  the terms of  the GNU General
13  *              Public  License as  published  by  the  Free  Software
14  *              Foundation;  either  version 2 of the License, or  (at
15  *              your option) any later version.
16  *
17  * Patched to support 'add' and 'del' keywords for INET(4) addresses
18  * by Mrs. Brisby <mrs.brisby@nimh.org>
19  *
20  * {1.34} - 19980630 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
21  *                     - gettext instead of catgets for i18n
22  *          10/1998  - Andi Kleen. Use interface list primitives.       
23  *          20001008 - Bernd Eckenfels, Patch from RH for setting mtu 
24  *                      (default AF was wrong)
25  * stolen from net-tools-1.59 and stripped down for busybox by 
26  *                      Erik Andersen <andersee@debian.org>
27  */
28
29 #include "busybox.h"
30
31 /* 
32  * 
33  * Protocol Families.
34  * 
35  */
36 #define HAVE_AFINET 1
37 #undef HAVE_AFINET6
38 #undef HAVE_AFIPX
39 #undef HAVE_AFATALK
40 #undef HAVE_AFNETROM
41 #undef HAVE_AFX25
42 #undef HAVE_AFECONET
43
44 /* 
45  * 
46  * Device Hardware types.
47  * 
48  */
49 #define HAVE_HWETHER    1
50 #define HAVE_HWPPP      1
51 #undef HAVE_HWSLIP
52
53
54 #include <features.h>
55 #include <sys/types.h>
56 #include <sys/socket.h>
57 #include <sys/ioctl.h>
58 #include <netinet/in.h>
59 #include <net/if.h>
60 #include <net/if_arp.h>
61 #include <stdio.h>
62 #include <errno.h>
63 #include <fcntl.h>
64 #include <ctype.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include <unistd.h>
68 #include <netdb.h>
69 #include <netinet/in.h>
70 #include <arpa/inet.h>
71 #include <arpa/nameser.h>
72
73 #define _(x) x
74 #define _PATH_PROCNET_DEV               "/proc/net/dev"
75 #define new(p) ((p) = xcalloc(1,sizeof(*(p))))
76 #define KRELEASE(maj,min,patch) ((maj) * 10000 + (min)*1000 + (patch))
77
78 int procnetdev_vsn = 1;
79
80
81 /* Ugh.  But libc5 doesn't provide POSIX types.  */
82 #include <asm/types.h>
83
84
85 #ifdef HAVE_HWSLIP
86 #include <linux/if_slip.h>
87 #endif
88
89 #if HAVE_AFINET6
90
91 #ifndef _LINUX_IN6_H
92 /*
93  *    This is in linux/include/net/ipv6.h.
94  */
95
96 struct in6_ifreq {
97     struct in6_addr ifr6_addr;
98     __u32 ifr6_prefixlen;
99     unsigned int ifr6_ifindex;
100 };
101
102 #endif
103
104 #endif                          /* HAVE_AFINET6 */
105
106 #if HAVE_AFIPX
107 #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
108 #include <netipx/ipx.h>
109 #else
110 #include "ipx.h"
111 #endif
112 #endif
113 #if 0
114 #include "net-support.h"
115 #include "pathnames.h"
116 #include "version.h"
117 #include "../intl.h"
118 #include "interface.h"
119 #include "sockets.h"
120 #include "util.h"
121 #endif
122
123 /* This structure defines protocol families and their handlers. */
124 struct aftype {
125     char *name;
126     char *title;
127     int af;
128     int alen;
129     char *(*print) (unsigned char *);
130     char *(*sprint) (struct sockaddr *, int numeric);
131     int (*input) (int type, char *bufp, struct sockaddr *);
132     void (*herror) (char *text);
133     int (*rprint) (int options);
134     int (*rinput) (int typ, int ext, char **argv);
135
136     /* may modify src */
137     int (*getmask) (char *src, struct sockaddr * mask, char *name);
138
139     int fd;
140     char *flag_file;
141 };
142
143 extern struct aftype *aftypes[];
144 int flag_unx;
145 int flag_ipx;
146 int flag_ax25;
147 int flag_ddp;
148 int flag_netrom;
149 int flag_inet;
150 int flag_inet6;
151 int flag_econet;
152 int flag_x25 = 0;
153 int flag_ash;
154
155
156 struct aftrans_t {
157     char *alias;
158     char *name;
159     int *flag;
160 } aftrans[] = {
161
162     {
163         "ax25", "ax25", &flag_ax25
164     },
165     {
166         "ip", "inet", &flag_inet
167     },
168     {
169         "ip6", "inet6", &flag_inet6
170     },
171     {
172         "ipx", "ipx", &flag_ipx
173     },
174     {
175         "appletalk", "ddp", &flag_ddp
176     },
177     {
178         "netrom", "netrom", &flag_netrom
179     },
180     {
181         "inet", "inet", &flag_inet
182     },
183     {
184         "inet6", "inet6", &flag_inet6
185     },
186     {
187         "ddp", "ddp", &flag_ddp
188     },
189     {
190         "unix", "unix", &flag_unx
191     },
192     {
193         "tcpip", "inet", &flag_inet
194     },
195     {
196         "econet", "ec", &flag_econet
197     },
198     {
199         "x25", "x25", &flag_x25
200     },
201     {
202         "ash", "ash", &flag_ash
203     },
204     {
205         0, 0, 0
206     }
207 };
208
209 char afname[256] = "";
210
211 #if HAVE_AFUNIX
212
213 /* Display a UNIX domain address. */
214 static char *UNIX_print(unsigned char *ptr)
215 {
216     return (ptr);
217 }
218
219
220 /* Display a UNIX domain address. */
221 static char *UNIX_sprint(struct sockaddr *sap, int numeric)
222 {
223     static char buf[64];
224
225     if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
226         return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf));
227     return (UNIX_print(sap->sa_data));
228 }
229
230
231 struct aftype unix_aftype =
232 {
233     "unix", NULL, /*"UNIX Domain", */ AF_UNIX, 0,
234     UNIX_print, UNIX_sprint, NULL, NULL,
235     NULL, NULL, NULL,
236     -1,
237     "/proc/net/unix"
238 };
239 #endif                          /* HAVE_AFUNIX */
240
241 #if HAVE_AFINET
242
243 extern int h_errno;             /* some netdb.h versions don't export this */
244
245 /* cache */
246 struct addr {
247     struct sockaddr_in addr;
248     char *name;
249     int host;
250     struct addr *next;
251 };
252
253 static struct addr *INET_nn = NULL;     /* addr-to-name cache           */
254
255 static int INET_resolve(char *name, struct sockaddr_in *sin, int hostfirst)
256 {
257     struct hostent *hp;
258     struct netent *np;
259
260     /* Grmpf. -FvK */
261     sin->sin_family = AF_INET;
262     sin->sin_port = 0;
263
264     /* Default is special, meaning 0.0.0.0. */
265     if (!strcmp(name, "default")) {
266         sin->sin_addr.s_addr = INADDR_ANY;
267         return (1);
268     }
269     /* Look to see if it's a dotted quad. */
270     if (inet_aton(name, &sin->sin_addr)) {
271         return 0;
272     }
273     /* If we expect this to be a hostname, try hostname database first */
274 #ifdef DEBUG
275     if (hostfirst) fprintf (stderr, "gethostbyname (%s)\n", name);
276 #endif
277     if (hostfirst && 
278         (hp = gethostbyname(name)) != (struct hostent *) NULL) {
279         memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0], 
280                 sizeof(struct in_addr));
281         return 0;
282     }
283     /* Try the NETWORKS database to see if this is a known network. */
284 #ifdef DEBUG
285     fprintf (stderr, "getnetbyname (%s)\n", name);
286 #endif
287     if ((np = getnetbyname(name)) != (struct netent *) NULL) {
288         sin->sin_addr.s_addr = htonl(np->n_net);
289         return 1;
290     }
291     if (hostfirst) {
292         /* Don't try again */
293         errno = h_errno;
294         return -1;
295     }
296 #ifdef DEBUG
297     res_init();
298     _res.options |= RES_DEBUG;
299 #endif
300
301 #ifdef DEBUG
302     fprintf (stderr, "gethostbyname (%s)\n", name);
303 #endif
304     if ((hp = gethostbyname(name)) == (struct hostent *) NULL) {
305         errno = h_errno;
306         return -1;
307     }
308     memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0], 
309            sizeof(struct in_addr));
310
311     return 0;
312 }
313
314
315 /* numeric: & 0x8000: default instead of *, 
316  *          & 0x4000: host instead of net, 
317  *          & 0x0fff: don't resolve
318  */
319 static int INET_rresolve(char *name, size_t len, struct sockaddr_in *sin, 
320                          int numeric, unsigned int netmask)
321 {
322     struct hostent *ent;
323     struct netent *np;
324     struct addr *pn;
325     unsigned long ad, host_ad;
326     int host = 0;
327
328     /* Grmpf. -FvK */
329     if (sin->sin_family != AF_INET) {
330 #ifdef DEBUG
331         fprintf(stderr, _("rresolve: unsupport address family %d !\n"), sin->sin_family);
332 #endif
333         errno = EAFNOSUPPORT;
334         return (-1);
335     }
336     ad = (unsigned long) sin->sin_addr.s_addr;
337 #ifdef DEBUG
338     fprintf (stderr, "rresolve: %08lx, mask %08x, num %08x \n", ad, netmask, numeric);
339 #endif
340     if (ad == INADDR_ANY) {
341         if ((numeric & 0x0FFF) == 0) {
342             if (numeric & 0x8000)
343                 safe_strncpy(name, "default", len);
344             else
345                 safe_strncpy(name, "*", len);
346             return (0);
347         }
348     }
349     if (numeric & 0x0FFF) {
350         safe_strncpy(name, inet_ntoa(sin->sin_addr), len);
351         return (0);
352     }
353
354     if ((ad & (~netmask)) != 0 || (numeric & 0x4000))
355         host = 1;
356 #if 0
357     INET_nn = NULL;
358 #endif
359     pn = INET_nn;
360     while (pn != NULL) {
361         if (pn->addr.sin_addr.s_addr == ad && pn->host == host) {
362             safe_strncpy(name, pn->name, len);
363 #ifdef DEBUG
364             fprintf (stderr, "rresolve: found %s %08lx in cache\n", (host? "host": "net"), ad);
365 #endif
366             return (0);
367         }
368         pn = pn->next;
369     }
370
371     host_ad = ntohl(ad);
372     np = NULL;
373     ent = NULL;
374     if (host) {
375 #ifdef DEBUG
376         fprintf (stderr, "gethostbyaddr (%08lx)\n", ad);
377 #endif
378         ent = gethostbyaddr((char *) &ad, 4, AF_INET);
379         if (ent != NULL)
380             safe_strncpy(name, ent->h_name, len);
381     } else {
382 #ifdef DEBUG
383         fprintf (stderr, "getnetbyaddr (%08lx)\n", host_ad);
384 #endif
385         np = getnetbyaddr(host_ad, AF_INET);
386         if (np != NULL)
387             safe_strncpy(name, np->n_name, len);
388     }
389     if ((ent == NULL) && (np == NULL))
390         safe_strncpy(name, inet_ntoa(sin->sin_addr), len);
391     pn = (struct addr *) xmalloc(sizeof(struct addr));
392     pn->addr = *sin;
393     pn->next = INET_nn;
394     pn->host = host;
395     pn->name = (char *) xmalloc(strlen(name) + 1);
396     strcpy(pn->name, name);
397     INET_nn = pn;
398
399     return (0);
400 }
401
402
403 static void INET_reserror(char *text)
404 {
405     herror(text);
406 }
407
408
409 /* Display an Internet socket address. */
410 static char *INET_print(unsigned char *ptr)
411 {
412     return (inet_ntoa((*(struct in_addr *) ptr)));
413 }
414
415
416 /* Display an Internet socket address. */
417 static char *INET_sprint(struct sockaddr *sap, int numeric)
418 {
419     static char buff[128];
420
421     if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
422         return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
423
424     if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap, 
425                       numeric, 0xffffff00) != 0)
426         return (NULL);
427
428     return (buff);
429 }
430
431 char *INET_sprintmask(struct sockaddr *sap, int numeric, 
432                       unsigned int netmask)
433 {
434     static char buff[128];
435
436     if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
437         return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
438     if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap, 
439                       numeric, netmask) != 0)
440         return (NULL);
441     return (buff);
442 }
443
444
445 static int INET_getsock(char *bufp, struct sockaddr *sap)
446 {
447     char *sp = bufp, *bp;
448     unsigned int i;
449     unsigned val;
450     struct sockaddr_in *sin;
451
452     sin = (struct sockaddr_in *) sap;
453     sin->sin_family = AF_INET;
454     sin->sin_port = 0;
455
456     val = 0;
457     bp = (char *) &val;
458     for (i = 0; i < sizeof(sin->sin_addr.s_addr); i++) {
459         *sp = toupper(*sp);
460
461         if ((*sp >= 'A') && (*sp <= 'F'))
462             bp[i] |= (int) (*sp - 'A') + 10;
463         else if ((*sp >= '0') && (*sp <= '9'))
464             bp[i] |= (int) (*sp - '0');
465         else
466             return (-1);
467
468         bp[i] <<= 4;
469         sp++;
470         *sp = toupper(*sp);
471
472         if ((*sp >= 'A') && (*sp <= 'F'))
473             bp[i] |= (int) (*sp - 'A') + 10;
474         else if ((*sp >= '0') && (*sp <= '9'))
475             bp[i] |= (int) (*sp - '0');
476         else
477             return (-1);
478
479         sp++;
480     }
481     sin->sin_addr.s_addr = htonl(val);
482
483     return (sp - bufp);
484 }
485
486 static int INET_input(int type, char *bufp, struct sockaddr *sap)
487 {
488     switch (type) {
489     case 1:
490         return (INET_getsock(bufp, sap));
491     case 256:
492         return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1));
493     default:
494         return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0));
495     }
496 }
497
498 static int INET_getnetmask(char *adr, struct sockaddr *m, char *name)
499 {
500     struct sockaddr_in *mask = (struct sockaddr_in *) m;
501     char *slash, *end;
502     int prefix;
503
504     if ((slash = strchr(adr, '/')) == NULL)
505         return 0;
506
507     *slash++ = '\0';
508     prefix = strtoul(slash, &end, 0);
509     if (*end != '\0')
510         return -1;
511
512     if (name) {
513         sprintf(name, "/%d", prefix);
514     }
515     mask->sin_family = AF_INET;
516     mask->sin_addr.s_addr = htonl(~(0xffffffffU >> prefix));
517     return 1;
518 }
519
520
521 struct aftype inet_aftype =
522 {
523     "inet", NULL, /*"DARPA Internet", */ AF_INET, sizeof(unsigned long),
524     INET_print, INET_sprint, INET_input, INET_reserror,
525     NULL /*INET_rprint */ , NULL /*INET_rinput */ ,
526     INET_getnetmask,
527     -1,
528     NULL
529 };
530
531 #endif                          /* HAVE_AFINET */
532
533 /* Display an UNSPEC address. */
534 static char *UNSPEC_print(unsigned char *ptr)
535 {
536     static char buff[64];
537     char *pos;
538     unsigned int i;
539
540     pos = buff;
541     for (i = 0; i < sizeof(struct sockaddr); i++) {
542         pos += sprintf(pos, "%02X-", (*ptr++ & 0377));
543     }
544     buff[strlen(buff) - 1] = '\0';
545     return (buff);
546 }
547
548 /* Display an UNSPEC socket address. */
549 static char *UNSPEC_sprint(struct sockaddr *sap, int numeric)
550 {
551     static char buf[64];
552
553     if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
554         return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf));
555     return (UNSPEC_print(sap->sa_data));
556 }
557
558 struct aftype unspec_aftype =
559 {
560     "unspec", NULL, /*"UNSPEC", */ AF_UNSPEC, 0,
561     UNSPEC_print, UNSPEC_sprint, NULL, NULL,
562     NULL,
563 };
564
565 static short sVafinit = 0;
566
567 struct aftype *aftypes[] =
568 {
569 #if HAVE_AFUNIX
570     &unix_aftype,
571 #endif
572 #if HAVE_AFINET
573     &inet_aftype,
574 #endif
575 #if HAVE_AFINET6
576     &inet6_aftype,
577 #endif
578 #if HAVE_AFAX25
579     &ax25_aftype,
580 #endif
581 #if HAVE_AFNETROM
582     &netrom_aftype,
583 #endif
584 #if HAVE_AFROSE
585     &rose_aftype,
586 #endif
587 #if HAVE_AFIPX
588     &ipx_aftype,
589 #endif
590 #if HAVE_AFATALK
591     &ddp_aftype,
592 #endif
593 #if HAVE_AFECONET
594     &ec_aftype,
595 #endif
596 #if HAVE_AFASH
597     &ash_aftype,
598 #endif
599 #if HAVE_AFX25
600     &x25_aftype,
601 #endif
602     &unspec_aftype,
603     NULL
604 };
605
606 void afinit()
607 {
608     unspec_aftype.title = _("UNSPEC");
609 #if HAVE_AFUNIX
610     unix_aftype.title = _("UNIX Domain");
611 #endif
612 #if HAVE_AFINET
613     inet_aftype.title = _("DARPA Internet");
614 #endif
615 #if HAVE_AFINET6
616     inet6_aftype.title = _("IPv6");
617 #endif
618 #if HAVE_AFAX25
619     ax25_aftype.title = _("AMPR AX.25");
620 #endif
621 #if HAVE_AFNETROM
622     netrom_aftype.title = _("AMPR NET/ROM");
623 #endif
624 #if HAVE_AFIPX
625     ipx_aftype.title = _("Novell IPX");
626 #endif
627 #if HAVE_AFATALK
628     ddp_aftype.title = _("Appletalk DDP");
629 #endif
630 #if HAVE_AFECONET
631     ec_aftype.title = _("Econet");
632 #endif
633 #if HAVE_AFX25
634     x25_aftype.title = _("CCITT X.25");
635 #endif
636 #if HAVE_AFROSE
637     rose_aftype.title = _("AMPR ROSE");
638 #endif
639 #if HAVE_AFASH
640     ash_aftype.title = _("Ash");
641 #endif  
642     sVafinit = 1;
643 }
644
645 int aftrans_opt(const char *arg)
646 {
647     struct aftrans_t *paft;
648     char *tmp1, *tmp2;
649     char buf[256];
650
651     safe_strncpy(buf, arg, sizeof(buf));
652
653     tmp1 = buf;
654
655     while (tmp1) {
656
657         tmp2 = index(tmp1, ',');
658
659         if (tmp2)
660             *(tmp2++) = '\0';
661
662         paft = aftrans;
663         for (paft = aftrans; paft->alias; paft++) {
664             if (strcmp(tmp1, paft->alias))
665                 continue;
666             if (strlen(paft->name) + strlen(afname) + 1 >= sizeof(afname)) {
667                 fprintf(stderr, _("Too much address family arguments.\n"));
668                 return (0);
669             }
670             if (paft->flag)
671                 (*paft->flag)++;
672             if (afname[0])
673                 strcat(afname, ",");
674             strcat(afname, paft->name);
675             break;
676         }
677         if (!paft->alias) {
678             fprintf(stderr, _("Unknown address family `%s'.\n"), tmp1);
679             return (1);
680         }
681         tmp1 = tmp2;
682     }
683
684     return (0);
685 }
686
687 /* set the default AF list from the program name or a constant value    */
688 void aftrans_def(char *tool, char *argv0, char *dflt)
689 {
690     char *tmp;
691     char *buf;
692
693     strcpy(afname, dflt);
694
695     if (!(tmp = strrchr(argv0, '/')))
696         tmp = argv0;            /* no slash?! */
697     else
698         tmp++;
699
700     if (!(buf = strdup(tmp)))
701         return;
702
703     if (strlen(tool) >= strlen(tmp)) {
704         free(buf);
705         return;
706     }
707     tmp = buf + (strlen(tmp) - strlen(tool));
708
709     if (strcmp(tmp, tool) != 0) {
710         free(buf);
711         return;
712     }
713     *tmp = '\0';
714     if ((tmp = strchr(buf, '_')))
715         *tmp = '\0';
716
717     afname[0] = '\0';
718     if (aftrans_opt(buf))
719         strcpy(afname, buf);
720
721     free(buf);
722 }
723
724
725 /* Check our protocol family table for this family. */
726 struct aftype *get_aftype(const char *name)
727 {
728     struct aftype **afp;
729
730     if (!sVafinit)
731         afinit();
732
733     afp = aftypes;
734     while (*afp != NULL) {
735         if (!strcmp((*afp)->name, name))
736             return (*afp);
737         afp++;
738     }
739     if (index(name, ','))
740         fprintf(stderr, _("Please don't supply more than one address family.\n"));
741     return (NULL);
742 }
743
744
745 /* Check our protocol family table for this family. */
746 struct aftype *get_afntype(int af)
747 {
748     struct aftype **afp;
749
750     if (!sVafinit)
751         afinit();
752
753     afp = aftypes;
754     while (*afp != NULL) {
755         if ((*afp)->af == af)
756             return (*afp);
757         afp++;
758     }
759     return (NULL);
760 }
761
762 /* Check our protocol family table for this family and return its socket */
763 int get_socket_for_af(int af)
764 {
765     struct aftype **afp;
766
767     if (!sVafinit)
768         afinit();
769
770     afp = aftypes;
771     while (*afp != NULL) {
772         if ((*afp)->af == af)
773             return (*afp)->fd;
774         afp++;
775     }
776     return -1;
777 }
778
779 /* type: 0=all, 1=getroute */
780 void print_aflist(int type) {
781     int count = 0;
782     char * txt;
783     struct aftype **afp;
784
785     if (!sVafinit)
786         afinit();
787
788     afp = aftypes;
789     while (*afp != NULL) {
790         if ((type == 1 && ((*afp)->rprint == NULL)) || ((*afp)->af == 0)) {
791                 afp++; continue;
792         }
793         if ((count % 3) == 0) fprintf(stderr,count?"\n    ":"    "); 
794         txt = (*afp)->name; if (!txt) txt = "..";
795         fprintf(stderr,"%s (%s) ",txt,(*afp)->title);
796         count++;
797         afp++;
798     }
799     fprintf(stderr,"\n");
800 }
801
802 struct user_net_device_stats {
803     unsigned long long rx_packets;      /* total packets received       */
804     unsigned long long tx_packets;      /* total packets transmitted    */
805     unsigned long long rx_bytes;        /* total bytes received         */
806     unsigned long long tx_bytes;        /* total bytes transmitted      */
807     unsigned long rx_errors;    /* bad packets received         */
808     unsigned long tx_errors;    /* packet transmit problems     */
809     unsigned long rx_dropped;   /* no space in linux buffers    */
810     unsigned long tx_dropped;   /* no space available in linux  */
811     unsigned long rx_multicast; /* multicast packets received   */
812     unsigned long rx_compressed;
813     unsigned long tx_compressed;
814     unsigned long collisions;
815
816     /* detailed rx_errors: */
817     unsigned long rx_length_errors;
818     unsigned long rx_over_errors;       /* receiver ring buff overflow  */
819     unsigned long rx_crc_errors;        /* recved pkt with crc error    */
820     unsigned long rx_frame_errors;      /* recv'd frame alignment error */
821     unsigned long rx_fifo_errors;       /* recv'r fifo overrun          */
822     unsigned long rx_missed_errors;     /* receiver missed packet     */
823     /* detailed tx_errors */
824     unsigned long tx_aborted_errors;
825     unsigned long tx_carrier_errors;
826     unsigned long tx_fifo_errors;
827     unsigned long tx_heartbeat_errors;
828     unsigned long tx_window_errors;
829 };
830
831 struct interface {
832     struct interface *next, *prev; 
833     char name[IFNAMSIZ];        /* interface name        */
834     short type;                 /* if type               */
835     short flags;                /* various flags         */
836     int metric;                 /* routing metric        */
837     int mtu;                    /* MTU value             */
838     int tx_queue_len;           /* transmit queue length */
839     struct ifmap map;           /* hardware setup        */
840     struct sockaddr addr;       /* IP address            */
841     struct sockaddr dstaddr;    /* P-P IP address        */
842     struct sockaddr broadaddr;  /* IP broadcast address  */
843     struct sockaddr netmask;    /* IP network mask       */
844     struct sockaddr ipxaddr_bb; /* IPX network address   */
845     struct sockaddr ipxaddr_sn; /* IPX network address   */
846     struct sockaddr ipxaddr_e3; /* IPX network address   */
847     struct sockaddr ipxaddr_e2; /* IPX network address   */
848     struct sockaddr ddpaddr;    /* Appletalk DDP address */
849     struct sockaddr ecaddr;     /* Econet address        */
850     int has_ip;
851     int has_ipx_bb;
852     int has_ipx_sn;
853     int has_ipx_e3;
854     int has_ipx_e2;
855     int has_ax25;
856     int has_ddp;
857     int has_econet;
858     char hwaddr[32];            /* HW address            */
859     int statistics_valid;
860     struct user_net_device_stats stats;         /* statistics            */
861     int keepalive;              /* keepalive value for SLIP */
862     int outfill;                /* outfill value for SLIP */
863 };
864
865
866 int opt_a = 0;                  /* show all interfaces          */
867 int opt_i = 0;                  /* show the statistics          */
868 int opt_v = 0;                  /* debugging output flag        */
869
870 int addr_family = 0;            /* currently selected AF        */
871 static struct interface *int_list, *int_last;
872 int skfd = -1;                  /* generic raw socket desc.     */
873
874
875 int sockets_open(int family)
876 {
877     struct aftype **aft;
878     int sfd = -1;
879     static int force = -1;
880
881     if (force < 0) {
882         force = 0;
883         if (get_kernel_revision() < KRELEASE(2, 1, 0))
884             force = 1;
885         if (access("/proc/net", R_OK))
886             force = 1;
887     }
888     for (aft = aftypes; *aft; aft++) {
889         struct aftype *af = *aft;
890         int type = SOCK_DGRAM;
891         if (af->af == AF_UNSPEC)
892             continue;
893         if (family && family != af->af)
894             continue;
895         if (af->fd != -1) {
896             sfd = af->fd;
897             continue;
898         }
899         /* Check some /proc file first to not stress kmod */
900         if (!family && !force && af->flag_file) {
901             if (access(af->flag_file, R_OK))
902                 continue;
903         }
904 #if HAVE_AFNETROM
905         if (af->af == AF_NETROM)
906             type = SOCK_SEQPACKET;
907 #endif
908 #if HAVE_AFX25
909        if (af->af == AF_X25)
910            type = SOCK_SEQPACKET;
911 #endif
912         af->fd = socket(af->af, type, 0);
913         if (af->fd >= 0)
914             sfd = af->fd;
915     }
916     if (sfd < 0)
917         fprintf(stderr, _("No usable address families found.\n"));
918     return sfd;
919 }
920
921 /* like strcmp(), but knows about numbers */
922 int nstrcmp(const char *astr, const char *b)
923 {
924     const char *a = astr;
925
926     while (*a == *b) {
927         if (*a == '\0')
928             return 0;
929         a++;
930         b++;
931     }
932     if (isdigit(*a)) {
933         if (!isdigit(*b))
934             return -1;
935         while (a > astr) {
936             a--;
937             if (!isdigit(*a)) {
938                 a++;
939                 break;
940             }
941             if (!isdigit(*b))
942                 return -1;
943             b--;
944         }
945         return atoi(a) > atoi(b) ? 1 : -1;
946     }
947     return *a - *b;
948 }
949
950 static struct interface *add_interface(char *name)
951 {
952     struct interface *ife, **nextp, *new;
953
954     for (ife = int_last; ife; ife = ife->prev) {
955             int n = nstrcmp(ife->name, name); 
956             if (n == 0) 
957                     return ife; 
958             if (n < 0) 
959                     break; 
960     }
961     new(new); 
962     safe_strncpy(new->name, name, IFNAMSIZ); 
963     nextp = ife ? &ife->next : &int_list;
964     new->prev = ife;
965     new->next = *nextp; 
966     if (new->next) 
967             new->next->prev = new; 
968     else
969             int_last = new; 
970     *nextp = new; 
971     return new; 
972 }
973
974
975 static int if_readconf(void)
976 {
977     int numreqs = 30;
978     struct ifconf ifc;
979     struct ifreq *ifr;
980     int n, err = -1;
981     int skfd;
982
983     /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
984        (as of 2.1.128) */ 
985     skfd = get_socket_for_af(AF_INET);
986     if (skfd < 0) {
987         fprintf(stderr, _("warning: no inet socket available: %s\n"),
988                 strerror(errno));
989         /* Try to soldier on with whatever socket we can get hold of.  */
990         skfd = sockets_open(0);
991         if (skfd < 0)
992             return -1;
993     }
994
995     ifc.ifc_buf = NULL;
996     for (;;) {
997         ifc.ifc_len = sizeof(struct ifreq) * numreqs;
998         ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
999
1000         if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
1001             perror("SIOCGIFCONF");
1002             goto out;
1003         }
1004         if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
1005             /* assume it overflowed and try again */
1006             numreqs += 10;
1007             continue;
1008         }
1009         break;
1010     }
1011
1012     ifr = ifc.ifc_req;
1013     for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
1014         add_interface(ifr->ifr_name);
1015         ifr++;
1016     }
1017     err = 0;
1018
1019 out:
1020     free(ifc.ifc_buf);
1021     return err;
1022 }
1023
1024 static char *get_name(char *name, char *p)
1025 {
1026     while (isspace(*p))
1027         p++;
1028     while (*p) {
1029         if (isspace(*p))
1030             break;
1031         if (*p == ':') {        /* could be an alias */
1032             char *dot = p, *dotname = name;
1033             *name++ = *p++;
1034             while (isdigit(*p))
1035                 *name++ = *p++;
1036             if (*p != ':') {    /* it wasn't, backup */
1037                 p = dot;
1038                 name = dotname;
1039             }
1040             if (*p == '\0')
1041                 return NULL;
1042             p++;
1043             break;
1044         }
1045         *name++ = *p++;
1046     }
1047     *name++ = '\0';
1048     return p;
1049 }
1050
1051 static int get_dev_fields(char *bp, struct interface *ife)
1052 {
1053     switch (procnetdev_vsn) {
1054     case 3:
1055         sscanf(bp,
1056         "%llu %llu %lu %lu %lu %lu %lu %lu %llu %llu %lu %lu %lu %lu %lu %lu",
1057                &ife->stats.rx_bytes,
1058                &ife->stats.rx_packets,
1059                &ife->stats.rx_errors,
1060                &ife->stats.rx_dropped,
1061                &ife->stats.rx_fifo_errors,
1062                &ife->stats.rx_frame_errors,
1063                &ife->stats.rx_compressed,
1064                &ife->stats.rx_multicast,
1065
1066                &ife->stats.tx_bytes,
1067                &ife->stats.tx_packets,
1068                &ife->stats.tx_errors,
1069                &ife->stats.tx_dropped,
1070                &ife->stats.tx_fifo_errors,
1071                &ife->stats.collisions,
1072                &ife->stats.tx_carrier_errors,
1073                &ife->stats.tx_compressed);
1074         break;
1075     case 2:
1076         sscanf(bp, "%llu %llu %lu %lu %lu %lu %llu %llu %lu %lu %lu %lu %lu",
1077                &ife->stats.rx_bytes,
1078                &ife->stats.rx_packets,
1079                &ife->stats.rx_errors,
1080                &ife->stats.rx_dropped,
1081                &ife->stats.rx_fifo_errors,
1082                &ife->stats.rx_frame_errors,
1083
1084                &ife->stats.tx_bytes,
1085                &ife->stats.tx_packets,
1086                &ife->stats.tx_errors,
1087                &ife->stats.tx_dropped,
1088                &ife->stats.tx_fifo_errors,
1089                &ife->stats.collisions,
1090                &ife->stats.tx_carrier_errors);
1091         ife->stats.rx_multicast = 0;
1092         break;
1093     case 1:
1094         sscanf(bp, "%llu %lu %lu %lu %lu %llu %lu %lu %lu %lu %lu",
1095                &ife->stats.rx_packets,
1096                &ife->stats.rx_errors,
1097                &ife->stats.rx_dropped,
1098                &ife->stats.rx_fifo_errors,
1099                &ife->stats.rx_frame_errors,
1100
1101                &ife->stats.tx_packets,
1102                &ife->stats.tx_errors,
1103                &ife->stats.tx_dropped,
1104                &ife->stats.tx_fifo_errors,
1105                &ife->stats.collisions,
1106                &ife->stats.tx_carrier_errors);
1107         ife->stats.rx_bytes = 0;
1108         ife->stats.tx_bytes = 0;
1109         ife->stats.rx_multicast = 0;
1110         break;
1111     }
1112     return 0;
1113 }
1114
1115 static int procnetdev_version(char *buf)
1116 {
1117     if (strstr(buf, "compressed"))
1118         return 3;
1119     if (strstr(buf, "bytes"))
1120         return 2;
1121     return 1;
1122 }
1123
1124 static int if_readlist_proc(char *target)
1125 {
1126     static int proc_read; 
1127     FILE *fh;
1128     char buf[512];
1129     struct interface *ife;
1130     int err;
1131
1132     if (proc_read) 
1133             return 0; 
1134     if (!target) 
1135             proc_read = 1;
1136
1137     fh = fopen(_PATH_PROCNET_DEV, "r");
1138     if (!fh) {
1139                 fprintf(stderr, _("Warning: cannot open %s (%s). Limited output.\n"),
1140                         _PATH_PROCNET_DEV, strerror(errno)); 
1141                 return if_readconf();
1142         }       
1143     fgets(buf, sizeof buf, fh); /* eat line */
1144     fgets(buf, sizeof buf, fh);
1145
1146 #if 0                           /* pretty, but can't cope with missing fields */
1147     fmt = proc_gen_fmt(_PATH_PROCNET_DEV, 1, fh,
1148                        "face", "",      /* parsed separately */
1149                        "bytes", "%lu",
1150                        "packets", "%lu",
1151                        "errs", "%lu",
1152                        "drop", "%lu",
1153                        "fifo", "%lu",
1154                        "frame", "%lu",
1155                        "compressed", "%lu",
1156                        "multicast", "%lu",
1157                        "bytes", "%lu",
1158                        "packets", "%lu",
1159                        "errs", "%lu",
1160                        "drop", "%lu",
1161                        "fifo", "%lu",
1162                        "colls", "%lu",
1163                        "carrier", "%lu",
1164                        "compressed", "%lu",
1165                        NULL);
1166     if (!fmt)
1167         return -1;
1168 #else
1169     procnetdev_vsn = procnetdev_version(buf);
1170 #endif
1171
1172     err = 0;
1173     while (fgets(buf, sizeof buf, fh)) {
1174         char *s, name[IFNAMSIZ];
1175         s = get_name(name, buf);    
1176         ife = add_interface(name);
1177         get_dev_fields(s, ife);
1178         ife->statistics_valid = 1;
1179         if (target && !strcmp(target,name))
1180                 break;
1181     }
1182     if (ferror(fh)) {
1183         perror(_PATH_PROCNET_DEV);
1184         err = -1;
1185         proc_read = 0; 
1186     }
1187
1188 #if 0
1189     free(fmt);
1190 #endif
1191     fclose(fh);
1192     return err;
1193 }
1194
1195 int if_readlist(void) 
1196
1197     int err = if_readlist_proc(NULL); 
1198     if (!err)
1199             err = if_readconf();
1200     return err;
1201
1202
1203 int for_all_interfaces(int (*doit) (struct interface *, void *), void *cookie)
1204 {
1205     struct interface *ife;
1206
1207     if (!int_list && (if_readlist() < 0))
1208         return -1;
1209     for (ife = int_list; ife; ife = ife->next) {
1210         int err = doit(ife, cookie);
1211         if (err)
1212             return err;
1213     }
1214     return 0;
1215 }
1216
1217 /* Support for fetching an IPX address */
1218
1219 #if HAVE_AFIPX
1220 static int ipx_getaddr(int sock, int ft, struct ifreq *ifr)
1221 {
1222     ((struct sockaddr_ipx *) &ifr->ifr_addr)->sipx_type = ft;
1223     return ioctl(sock, SIOCGIFADDR, ifr);
1224 }
1225 #endif
1226
1227
1228 /* Fetch the interface configuration from the kernel. */
1229 int if_fetch(struct interface *ife)
1230 {
1231     struct ifreq ifr;
1232     int fd;
1233     char *ifname = ife->name; 
1234
1235     strcpy(ifr.ifr_name, ifname);
1236     if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
1237         return (-1);
1238     ife->flags = ifr.ifr_flags;
1239
1240     strcpy(ifr.ifr_name, ifname);
1241     if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
1242         memset(ife->hwaddr, 0, 32);
1243     else
1244         memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
1245
1246     ife->type = ifr.ifr_hwaddr.sa_family;
1247
1248     strcpy(ifr.ifr_name, ifname);
1249     if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
1250         ife->metric = 0;
1251     else
1252         ife->metric = ifr.ifr_metric;
1253
1254     strcpy(ifr.ifr_name, ifname);
1255     if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
1256         ife->mtu = 0;
1257     else
1258         ife->mtu = ifr.ifr_mtu;
1259
1260 #ifdef HAVE_HWSLIP
1261     if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
1262         ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 ||
1263         ife->type == ARPHRD_ADAPT) {
1264 #ifdef SIOCGOUTFILL
1265         strcpy(ifr.ifr_name, ifname);
1266         if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0)
1267             ife->outfill = 0;
1268         else
1269             ife->outfill = (unsigned int) ifr.ifr_data;
1270 #endif
1271 #ifdef SIOCGKEEPALIVE
1272         strcpy(ifr.ifr_name, ifname);
1273         if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0)
1274             ife->keepalive = 0;
1275         else
1276             ife->keepalive = (unsigned int) ifr.ifr_data;
1277 #endif
1278     }
1279 #endif
1280
1281     strcpy(ifr.ifr_name, ifname);
1282     if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
1283         memset(&ife->map, 0, sizeof(struct ifmap));
1284     else
1285         memcpy(&ife->map, &ifr.ifr_map, sizeof(struct ifmap));
1286
1287     strcpy(ifr.ifr_name, ifname);
1288     if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
1289         memset(&ife->map, 0, sizeof(struct ifmap));
1290     else
1291         ife->map = ifr.ifr_map;
1292
1293 #ifdef HAVE_TXQUEUELEN
1294     strcpy(ifr.ifr_name, ifname);
1295     if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
1296         ife->tx_queue_len = -1; /* unknown value */
1297     else
1298         ife->tx_queue_len = ifr.ifr_qlen;
1299 #else
1300     ife->tx_queue_len = -1;     /* unknown value */
1301 #endif
1302
1303 #if HAVE_AFINET
1304     /* IPv4 address? */
1305     fd = get_socket_for_af(AF_INET);
1306     if (fd >= 0) {
1307         strcpy(ifr.ifr_name, ifname);
1308         ifr.ifr_addr.sa_family = AF_INET;
1309         if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1310             ife->has_ip = 1;
1311             ife->addr = ifr.ifr_addr;
1312             strcpy(ifr.ifr_name, ifname);
1313             if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
1314                 memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
1315             else
1316                 ife->dstaddr = ifr.ifr_dstaddr;
1317
1318             strcpy(ifr.ifr_name, ifname);
1319             if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
1320                 memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
1321             else
1322                 ife->broadaddr = ifr.ifr_broadaddr;
1323
1324             strcpy(ifr.ifr_name, ifname);
1325             if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
1326                 memset(&ife->netmask, 0, sizeof(struct sockaddr));
1327             else
1328                 ife->netmask = ifr.ifr_netmask;
1329         } else
1330             memset(&ife->addr, 0, sizeof(struct sockaddr));
1331     }
1332 #endif
1333
1334 #if HAVE_AFATALK
1335     /* DDP address maybe ? */
1336     fd = get_socket_for_af(AF_APPLETALK);
1337     if (fd >= 0) {
1338         strcpy(ifr.ifr_name, ifname);
1339         if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1340             ife->ddpaddr = ifr.ifr_addr;
1341             ife->has_ddp = 1;
1342         }
1343     }
1344 #endif
1345
1346 #if HAVE_AFIPX
1347     /* Look for IPX addresses with all framing types */
1348     fd = get_socket_for_af(AF_IPX);
1349     if (fd >= 0) {
1350         strcpy(ifr.ifr_name, ifname);
1351         if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) {
1352             ife->has_ipx_bb = 1;
1353             ife->ipxaddr_bb = ifr.ifr_addr;
1354         }
1355         strcpy(ifr.ifr_name, ifname);
1356         if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) {
1357             ife->has_ipx_sn = 1;
1358             ife->ipxaddr_sn = ifr.ifr_addr;
1359         }
1360         strcpy(ifr.ifr_name, ifname);
1361         if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) {
1362             ife->has_ipx_e3 = 1;
1363             ife->ipxaddr_e3 = ifr.ifr_addr;
1364         }
1365         strcpy(ifr.ifr_name, ifname);
1366         if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) {
1367             ife->has_ipx_e2 = 1;
1368             ife->ipxaddr_e2 = ifr.ifr_addr;
1369         }
1370     }
1371 #endif
1372
1373 #if HAVE_AFECONET
1374     /* Econet address maybe? */
1375     fd = get_socket_for_af(AF_ECONET);
1376     if (fd >= 0) {
1377         strcpy(ifr.ifr_name, ifname);
1378         if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
1379             ife->ecaddr = ifr.ifr_addr;
1380             ife->has_econet = 1;
1381         }
1382     }
1383 #endif
1384
1385     return 0;
1386 }
1387
1388
1389 int do_if_fetch(struct interface *ife)
1390
1391     if (if_fetch(ife) < 0) {
1392         char *errmsg; 
1393         if (errno == ENODEV) { 
1394             /* Give better error message for this case. */ 
1395             errmsg = _("Device not found"); 
1396         } else { 
1397             errmsg = strerror(errno); 
1398         }
1399         fprintf(stderr, _("%s: error fetching interface information: %s\n"),
1400                 ife->name, errmsg);
1401         return -1;
1402     }
1403     return 0; 
1404 }
1405
1406 /* This structure defines hardware protocols and their handlers. */
1407 struct hwtype {
1408     char *name;
1409     char *title;
1410     int type;
1411     int alen;
1412     char *(*print) (unsigned char *);
1413     int (*input) (char *, struct sockaddr *);
1414     int (*activate) (int fd);
1415     int suppress_null_addr;
1416 };
1417
1418 /* Display an UNSPEC address. */
1419 static char *pr_unspec(unsigned char *ptr)
1420 {
1421     static char buff[64];
1422     char *pos;
1423     unsigned int i;
1424
1425     pos = buff;
1426     for (i = 0; i < sizeof(struct sockaddr); i++) {
1427         pos += sprintf(pos, "%02X-", (*ptr++ & 0377));
1428     }
1429     buff[strlen(buff) - 1] = '\0';
1430     return (buff);
1431 }
1432
1433 struct hwtype unspec_hwtype =
1434 {
1435     "unspec", NULL, /*"UNSPEC", */ -1, 0,
1436     pr_unspec, NULL, NULL
1437 };
1438
1439 struct hwtype loop_hwtype =
1440 {
1441     "loop", NULL, /*"Local Loopback", */ ARPHRD_LOOPBACK, 0,
1442     NULL, NULL, NULL
1443 };
1444
1445 #if HAVE_HWETHER
1446 #include <net/if_arp.h>
1447 #include <linux/if_ether.h>
1448
1449 extern struct hwtype ether_hwtype;
1450
1451 /* Display an Ethernet address in readable format. */
1452 static char *pr_ether(unsigned char *ptr)
1453 {
1454     static char buff[64];
1455
1456     snprintf(buff, sizeof(buff), "%02X:%02X:%02X:%02X:%02X:%02X",
1457              (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
1458              (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
1459         );
1460     return (buff);
1461 }
1462
1463
1464 /* Input an Ethernet address and convert to binary. */
1465 static int in_ether(char *bufp, struct sockaddr *sap)
1466 {
1467     unsigned char *ptr;
1468     char c, *orig;
1469     int i;
1470     unsigned val;
1471
1472     sap->sa_family = ether_hwtype.type;
1473     ptr = sap->sa_data;
1474
1475     i = 0;
1476     orig = bufp;
1477     while ((*bufp != '\0') && (i < ETH_ALEN)) {
1478         val = 0;
1479         c = *bufp++;
1480         if (isdigit(c))
1481             val = c - '0';
1482         else if (c >= 'a' && c <= 'f')
1483             val = c - 'a' + 10;
1484         else if (c >= 'A' && c <= 'F')
1485             val = c - 'A' + 10;
1486         else {
1487 #ifdef DEBUG
1488             fprintf(stderr, _("in_ether(%s): invalid ether address!\n"), orig);
1489 #endif
1490             errno = EINVAL;
1491             return (-1);
1492         }
1493         val <<= 4;
1494         c = *bufp;
1495         if (isdigit(c))
1496             val |= c - '0';
1497         else if (c >= 'a' && c <= 'f')
1498             val |= c - 'a' + 10;
1499         else if (c >= 'A' && c <= 'F')
1500             val |= c - 'A' + 10;
1501         else if (c == ':' || c == 0)
1502             val >>= 4;
1503         else {
1504 #ifdef DEBUG
1505             fprintf(stderr, _("in_ether(%s): invalid ether address!\n"), orig);
1506 #endif
1507             errno = EINVAL;
1508             return (-1);
1509         }
1510         if (c != 0)
1511             bufp++;
1512         *ptr++ = (unsigned char) (val & 0377);
1513         i++;
1514
1515         /* We might get a semicolon here - not required. */
1516         if (*bufp == ':') {
1517             if (i == ETH_ALEN) {
1518 #ifdef DEBUG
1519                 fprintf(stderr, _("in_ether(%s): trailing : ignored!\n"),
1520                         orig)
1521 #endif
1522                     ;           /* nothing */
1523             }
1524             bufp++;
1525         }
1526     }
1527
1528     /* That's it.  Any trailing junk? */
1529     if ((i == ETH_ALEN) && (*bufp != '\0')) {
1530 #ifdef DEBUG
1531         fprintf(stderr, _("in_ether(%s): trailing junk!\n"), orig);
1532         errno = EINVAL;
1533         return (-1);
1534 #endif
1535     }
1536 #ifdef DEBUG
1537     fprintf(stderr, "in_ether(%s): %s\n", orig, pr_ether(sap->sa_data));
1538 #endif
1539
1540     return (0);
1541 }
1542
1543
1544 struct hwtype ether_hwtype =
1545 {
1546     "ether", NULL, /*"10Mbps Ethernet", */ ARPHRD_ETHER, ETH_ALEN,
1547     pr_ether, in_ether, NULL
1548 };
1549
1550
1551 #endif                          /* HAVE_HWETHER */
1552
1553
1554 #if HAVE_HWPPP
1555
1556 #include <net/if_arp.h>
1557
1558 /* Start the PPP encapsulation on the file descriptor. */
1559 static int do_ppp(int fd)
1560 {
1561     fprintf(stderr, _("You cannot start PPP with this program.\n"));
1562     return -1;
1563 }
1564
1565
1566 struct hwtype ppp_hwtype =
1567 {
1568     "ppp", NULL, /*"Point-Point Protocol", */ ARPHRD_PPP, 0,
1569     NULL, NULL, do_ppp, 0
1570 };
1571
1572
1573 #endif                          /* HAVE_PPP */
1574
1575 static struct hwtype *hwtypes[] =
1576 {
1577
1578     &loop_hwtype,
1579
1580 #if HAVE_HWSLIP
1581     &slip_hwtype,
1582     &cslip_hwtype,
1583     &slip6_hwtype,
1584     &cslip6_hwtype,
1585     &adaptive_hwtype,
1586 #endif
1587 #if HAVE_HWSTRIP
1588     &strip_hwtype,
1589 #endif
1590 #if HAVE_HWASH
1591     &ash_hwtype,
1592 #endif
1593 #if HAVE_HWETHER
1594     &ether_hwtype,
1595 #endif
1596 #if HAVE_HWTR
1597     &tr_hwtype,
1598 #ifdef ARPHRD_IEEE802_TR
1599     &tr_hwtype1, 
1600 #endif
1601 #endif
1602 #if HAVE_HWAX25
1603     &ax25_hwtype,
1604 #endif
1605 #if HAVE_HWNETROM
1606     &netrom_hwtype,
1607 #endif
1608 #if HAVE_HWROSE
1609     &rose_hwtype,
1610 #endif
1611 #if HAVE_HWTUNNEL
1612     &tunnel_hwtype,
1613 #endif
1614 #if HAVE_HWPPP
1615     &ppp_hwtype,
1616 #endif
1617 #if HAVE_HWHDLCLAPB
1618     &hdlc_hwtype,
1619     &lapb_hwtype,
1620 #endif
1621 #if HAVE_HWARC
1622     &arcnet_hwtype,
1623 #endif
1624 #if HAVE_HWFR
1625     &dlci_hwtype,
1626     &frad_hwtype,
1627 #endif
1628 #if HAVE_HWSIT
1629     &sit_hwtype,
1630 #endif
1631 #if HAVE_HWFDDI
1632     &fddi_hwtype,
1633 #endif
1634 #if HAVE_HWHIPPI
1635     &hippi_hwtype,
1636 #endif
1637 #if HAVE_HWIRDA
1638     &irda_hwtype,
1639 #endif
1640 #if HAVE_HWEC
1641     &ec_hwtype,
1642 #endif
1643 #if HAVE_HWX25
1644     &x25_hwtype,
1645 #endif
1646     &unspec_hwtype,
1647     NULL
1648 };
1649
1650 static short sVhwinit = 0;
1651
1652 void hwinit()
1653 {
1654     loop_hwtype.title = _("Local Loopback");
1655     unspec_hwtype.title = _("UNSPEC");
1656 #if HAVE_HWSLIP
1657     slip_hwtype.title = _("Serial Line IP");
1658     cslip_hwtype.title = _("VJ Serial Line IP");
1659     slip6_hwtype.title = _("6-bit Serial Line IP");
1660     cslip6_hwtype.title = _("VJ 6-bit Serial Line IP");
1661     adaptive_hwtype.title = _("Adaptive Serial Line IP");
1662 #endif
1663 #if HAVE_HWETHER
1664     ether_hwtype.title = _("Ethernet");
1665 #endif
1666 #if HAVE_HWASH
1667     ash_hwtype.title = _("Ash");
1668 #endif
1669 #if HAVE_HWFDDI
1670     fddi_hwtype.title = _("Fiber Distributed Data Interface");
1671 #endif
1672 #if HAVE_HWHIPPI
1673     hippi_hwtype.title = _("HIPPI");
1674 #endif
1675 #if HAVE_HWAX25
1676     ax25_hwtype.title = _("AMPR AX.25");
1677 #endif
1678 #if HAVE_HWROSE
1679     rose_hwtype.title = _("AMPR ROSE");
1680 #endif
1681 #if HAVE_HWNETROM
1682     netrom_hwtype.title = _("AMPR NET/ROM");
1683 #endif
1684 #if HAVE_HWX25
1685     x25_hwtype.title = _("generic X.25");
1686 #endif
1687 #if HAVE_HWTUNNEL
1688     tunnel_hwtype.title = _("IPIP Tunnel");
1689 #endif
1690 #if HAVE_HWPPP
1691     ppp_hwtype.title = _("Point-to-Point Protocol");
1692 #endif
1693 #if HAVE_HWHDLCLAPB
1694     hdlc_hwtype.title = _("(Cisco)-HDLC");
1695     lapb_hwtype.title = _("LAPB");
1696 #endif
1697 #if HAVE_HWARC
1698     arcnet_hwtype.title = _("ARCnet");
1699 #endif
1700 #if HAVE_HWFR
1701     dlci_hwtype.title = _("Frame Relay DLCI");
1702     frad_hwtype.title = _("Frame Relay Access Device");
1703 #endif
1704 #if HAVE_HWSIT
1705     sit_hwtype.title = _("IPv6-in-IPv4");
1706 #endif
1707 #if HAVE_HWIRDA
1708     irda_hwtype.title = _("IrLAP");
1709 #endif
1710 #if HAVE_HWTR
1711     tr_hwtype.title = _("16/4 Mbps Token Ring");
1712 #ifdef ARPHRD_IEEE802_TR
1713     tr_hwtype1.title = _("16/4 Mbps Token Ring (New)") ; 
1714 #endif
1715 #endif
1716 #if HAVE_HWEC
1717     ec_hwtype.title = _("Econet");
1718 #endif
1719     sVhwinit = 1;
1720 }
1721
1722 #ifdef IFF_PORTSEL
1723 const char *if_port_text[][4] =
1724 {
1725     /* Keep in step with <linux/netdevice.h> */
1726     {"unknown", NULL, NULL, NULL},
1727     {"10base2", "bnc", "coax", NULL},
1728     {"10baseT", "utp", "tpe", NULL},
1729     {"AUI", "thick", "db15", NULL},
1730     {"100baseT", NULL, NULL, NULL},
1731     {"100baseTX", NULL, NULL, NULL},
1732     {"100baseFX", NULL, NULL, NULL},
1733     {NULL, NULL, NULL, NULL},
1734 };
1735 #endif
1736
1737 /* Check our hardware type table for this type. */
1738 struct hwtype *get_hwntype(int type)
1739 {
1740     struct hwtype **hwp;
1741
1742     if (!sVhwinit)
1743         hwinit();
1744
1745     hwp = hwtypes;
1746     while (*hwp != NULL) {
1747         if ((*hwp)->type == type)
1748             return (*hwp);
1749         hwp++;
1750     }
1751     return (NULL);
1752 }
1753
1754 /* return 1 if address is all zeros */
1755 int hw_null_address(struct hwtype *hw, void *ap)
1756 {
1757     unsigned int i;
1758     unsigned char *address = (unsigned char *)ap;
1759     for (i = 0; i < hw->alen; i++)
1760         if (address[i])
1761             return 0;
1762     return 1;
1763 }
1764
1765 void ife_print(struct interface *ptr)
1766 {
1767     struct aftype *ap;
1768     struct hwtype *hw;
1769     int hf;
1770     int can_compress = 0;
1771     unsigned long long rx, tx, short_rx, short_tx;
1772     char Rext[5]="b";
1773     char Text[5]="b";
1774
1775 #if HAVE_AFIPX
1776     static struct aftype *ipxtype = NULL;
1777 #endif
1778 #if HAVE_AFECONET
1779     static struct aftype *ectype = NULL;
1780 #endif
1781 #if HAVE_AFATALK
1782     static struct aftype *ddptype = NULL;
1783 #endif
1784 #if HAVE_AFINET6
1785     FILE *f;
1786     char addr6[40], devname[20];
1787     struct sockaddr_in6 sap;
1788     int plen, scope, dad_status, if_idx;
1789     extern struct aftype inet6_aftype;
1790     char addr6p[8][5];
1791 #endif
1792
1793     ap = get_afntype(ptr->addr.sa_family);
1794     if (ap == NULL)
1795         ap = get_afntype(0);
1796
1797     hf = ptr->type;
1798
1799     if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)
1800         can_compress = 1;
1801
1802     hw = get_hwntype(hf);
1803     if (hw == NULL)
1804         hw = get_hwntype(-1);
1805
1806     printf(_("%-9.9s Link encap:%s  "), ptr->name, hw->title);
1807     /* For some hardware types (eg Ash, ATM) we don't print the 
1808        hardware address if it's null.  */
1809     if (hw->print != NULL && (! (hw_null_address(hw, ptr->hwaddr) &&
1810                                   hw->suppress_null_addr)))
1811         printf(_("HWaddr %s  "), hw->print(ptr->hwaddr));
1812 #ifdef IFF_PORTSEL
1813     if (ptr->flags & IFF_PORTSEL) {
1814         printf(_("Media:%s"), if_port_text[ptr->map.port][0]);
1815         if (ptr->flags & IFF_AUTOMEDIA)
1816             printf(_("(auto)"));
1817     }
1818 #endif
1819     printf("\n");
1820
1821 #if HAVE_AFINET
1822     if (ptr->has_ip) {
1823         printf(_("          %s addr:%s "), ap->name,
1824                ap->sprint(&ptr->addr, 1));
1825         if (ptr->flags & IFF_POINTOPOINT) {
1826             printf(_(" P-t-P:%s "), ap->sprint(&ptr->dstaddr, 1));
1827         }
1828         if (ptr->flags & IFF_BROADCAST) {
1829             printf(_(" Bcast:%s "), ap->sprint(&ptr->broadaddr, 1));
1830         }
1831         printf(_(" Mask:%s\n"), ap->sprint(&ptr->netmask, 1));
1832     }
1833 #endif
1834
1835 #if HAVE_AFINET6
1836     /* FIXME: should be integrated into interface.c.   */
1837
1838     if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
1839         while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
1840                       addr6p[0], addr6p[1], addr6p[2], addr6p[3],
1841                       addr6p[4], addr6p[5], addr6p[6], addr6p[7],
1842                   &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
1843             if (!strcmp(devname, ptr->name)) {
1844                 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
1845                         addr6p[0], addr6p[1], addr6p[2], addr6p[3],
1846                         addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
1847                 inet6_aftype.input(1, addr6, (struct sockaddr *) &sap);
1848                 printf(_("          inet6 addr: %s/%d"),
1849                  inet6_aftype.sprint((struct sockaddr *) &sap, 1), plen);
1850                 printf(_(" Scope:"));
1851                 switch (scope) {
1852                 case 0:
1853                     printf(_("Global"));
1854                     break;
1855                 case IPV6_ADDR_LINKLOCAL:
1856                     printf(_("Link"));
1857                     break;
1858                 case IPV6_ADDR_SITELOCAL:
1859                     printf(_("Site"));
1860                     break;
1861                 case IPV6_ADDR_COMPATv4:
1862                     printf(_("Compat"));
1863                     break;
1864                 case IPV6_ADDR_LOOPBACK:
1865                     printf(_("Host"));
1866                     break;
1867                 default:
1868                     printf(_("Unknown"));
1869                 }
1870                 printf("\n");
1871             }
1872         }
1873         fclose(f);
1874     }
1875 #endif
1876
1877 #if HAVE_AFIPX
1878     if (ipxtype == NULL)
1879         ipxtype = get_afntype(AF_IPX);
1880
1881     if (ipxtype != NULL) {
1882         if (ptr->has_ipx_bb)
1883             printf(_("          IPX/Ethernet II addr:%s\n"),
1884                    ipxtype->sprint(&ptr->ipxaddr_bb, 1));
1885         if (ptr->has_ipx_sn)
1886             printf(_("          IPX/Ethernet SNAP addr:%s\n"),
1887                    ipxtype->sprint(&ptr->ipxaddr_sn, 1));
1888         if (ptr->has_ipx_e2)
1889             printf(_("          IPX/Ethernet 802.2 addr:%s\n"),
1890                    ipxtype->sprint(&ptr->ipxaddr_e2, 1));
1891         if (ptr->has_ipx_e3)
1892             printf(_("          IPX/Ethernet 802.3 addr:%s\n"),
1893                    ipxtype->sprint(&ptr->ipxaddr_e3, 1));
1894     }
1895 #endif
1896
1897 #if HAVE_AFATALK
1898     if (ddptype == NULL)
1899         ddptype = get_afntype(AF_APPLETALK);
1900     if (ddptype != NULL) {
1901         if (ptr->has_ddp)
1902             printf(_("          EtherTalk Phase 2 addr:%s\n"), ddptype->sprint(&ptr->ddpaddr, 1));
1903     }
1904 #endif
1905
1906 #if HAVE_AFECONET
1907     if (ectype == NULL)
1908         ectype = get_afntype(AF_ECONET);
1909     if (ectype != NULL) {
1910         if (ptr->has_econet)
1911             printf(_("          econet addr:%s\n"), ectype->sprint(&ptr->ecaddr, 1));
1912     }
1913 #endif
1914
1915     printf("          ");
1916     /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
1917     if (ptr->flags == 0)
1918         printf(_("[NO FLAGS] "));
1919     if (ptr->flags & IFF_UP)
1920         printf(_("UP "));
1921     if (ptr->flags & IFF_BROADCAST)
1922         printf(_("BROADCAST "));
1923     if (ptr->flags & IFF_DEBUG)
1924         printf(_("DEBUG "));
1925     if (ptr->flags & IFF_LOOPBACK)
1926         printf(_("LOOPBACK "));
1927     if (ptr->flags & IFF_POINTOPOINT)
1928         printf(_("POINTOPOINT "));
1929     if (ptr->flags & IFF_NOTRAILERS)
1930         printf(_("NOTRAILERS "));
1931     if (ptr->flags & IFF_RUNNING)
1932         printf(_("RUNNING "));
1933     if (ptr->flags & IFF_NOARP)
1934         printf(_("NOARP "));
1935     if (ptr->flags & IFF_PROMISC)
1936         printf(_("PROMISC "));
1937     if (ptr->flags & IFF_ALLMULTI)
1938         printf(_("ALLMULTI "));
1939     if (ptr->flags & IFF_SLAVE)
1940         printf(_("SLAVE "));
1941     if (ptr->flags & IFF_MASTER)
1942         printf(_("MASTER "));
1943     if (ptr->flags & IFF_MULTICAST)
1944         printf(_("MULTICAST "));
1945 #ifdef HAVE_DYNAMIC
1946     if (ptr->flags & IFF_DYNAMIC)
1947         printf(_("DYNAMIC "));
1948 #endif
1949     /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
1950     printf(_(" MTU:%d  Metric:%d"),
1951            ptr->mtu, ptr->metric ? ptr->metric : 1);
1952 #ifdef SIOCSKEEPALIVE
1953     if (ptr->outfill || ptr->keepalive)
1954         printf(_("  Outfill:%d  Keepalive:%d"),
1955                ptr->outfill, ptr->keepalive);
1956 #endif
1957     printf("\n");
1958
1959     /* If needed, display the interface statistics. */
1960
1961     if (ptr->statistics_valid) {
1962         /* XXX: statistics are currently only printed for the primary address,
1963          *      not for the aliases, although strictly speaking they're shared
1964          *      by all addresses.
1965          */
1966         printf("          ");
1967
1968         printf(_("RX packets:%llu errors:%lu dropped:%lu overruns:%lu frame:%lu\n"),
1969                ptr->stats.rx_packets, ptr->stats.rx_errors,
1970                ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
1971                ptr->stats.rx_frame_errors);
1972         if (can_compress)
1973             printf(_("             compressed:%lu\n"), ptr->stats.rx_compressed);
1974
1975         rx = ptr->stats.rx_bytes;  
1976         tx = ptr->stats.tx_bytes;
1977         short_rx = rx * 10;  
1978         short_tx = tx * 10;
1979         if (rx > 1048576) { short_rx /= 1048576;  strcpy(Rext, "Mb"); }
1980         else if (rx > 1024) { short_rx /= 1024;  strcpy(Rext, "Kb"); }
1981         if (tx > 1048576) { short_tx /= 1048576;  strcpy(Text, "Mb"); }
1982         else if (tx > 1024) { short_tx /= 1024;  strcpy(Text, "Kb"); }
1983
1984         printf("          ");
1985         printf(_("TX packets:%llu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n"),
1986                ptr->stats.tx_packets, ptr->stats.tx_errors,
1987                ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
1988                ptr->stats.tx_carrier_errors);
1989         printf(_("          collisions:%lu "), ptr->stats.collisions);
1990         if (can_compress)
1991             printf(_("compressed:%lu "), ptr->stats.tx_compressed);
1992         if (ptr->tx_queue_len != -1)
1993             printf(_("txqueuelen:%d "), ptr->tx_queue_len);
1994         printf("\n          ");
1995         printf(_("RX bytes:%llu (%lu.%lu %s)  TX bytes:%llu (%lu.%lu %s)\n"),
1996                rx, (unsigned long)(short_rx / 10), 
1997                (unsigned long)(short_rx % 10), Rext, 
1998                tx, (unsigned long)(short_tx / 10), 
1999                (unsigned long)(short_tx % 10), Text);
2000     }
2001
2002     if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma ||
2003          ptr->map.base_addr)) {
2004         printf("          ");
2005         if (ptr->map.irq)
2006             printf(_("Interrupt:%d "), ptr->map.irq);
2007         if (ptr->map.base_addr >= 0x100)        /* Only print devices using it for 
2008                                                    I/O maps */
2009             printf(_("Base address:0x%x "), ptr->map.base_addr);
2010         if (ptr->map.mem_start) {
2011             printf(_("Memory:%lx-%lx "), ptr->map.mem_start, ptr->map.mem_end);
2012         }
2013         if (ptr->map.dma)
2014             printf(_("DMA chan:%x "), ptr->map.dma);
2015         printf("\n");
2016     }
2017     printf("\n");
2018 }
2019
2020
2021 int do_if_print(struct interface *ife, void *cookie)
2022 {
2023     int *opt_a = (int *) cookie;
2024     int res; 
2025
2026     res = do_if_fetch(ife); 
2027     if (res >= 0) {   
2028         if ((ife->flags & IFF_UP) || *opt_a)
2029             ife_print(ife);
2030     }
2031     return res;
2032 }
2033
2034 struct interface *lookup_interface(char *name)
2035 {
2036     struct interface *ife = NULL;
2037
2038     if (if_readlist_proc(name) < 0) 
2039             return NULL; 
2040     ife = add_interface(name); 
2041     return ife;
2042 }
2043
2044 /* for ipv4 add/del modes */
2045 static int if_print(char *ifname)
2046 {
2047     int res;
2048
2049     if (!ifname) {
2050         res = for_all_interfaces(do_if_print, &opt_a);
2051     } else {
2052         struct interface *ife;
2053
2054         ife = lookup_interface(ifname);
2055         res = do_if_fetch(ife); 
2056         if (res >= 0) 
2057             ife_print(ife);
2058     }
2059     return res; 
2060 }
2061
2062 int display_interfaces(void)
2063 {
2064     int status;
2065
2066     /* Create a channel to the NET kernel. */
2067     if ((skfd = sockets_open(0)) < 0) {
2068         perror("socket");
2069         exit(1);
2070     }
2071
2072     /* Do we have to show the current setup? */
2073     status = if_print((char *) NULL);
2074     close(skfd);
2075     exit(status < 0);
2076 }
2077