Fix reporting of IPv6 multicast addresses.
[oss-qm-packages.git] / lib / interface.c
blobf4d2a9aca83ae0b766daf3afcb49ade9cf6b7e15
1 /* Code to manipulate interface information, shared between ifconfig and
2 netstat.
4 10/1998 partly rewriten by Andi Kleen to support an interface list.
5 I don't claim that the list operations are efficient @).
7 8/2000 Andi Kleen make the list operations a bit more efficient.
8 People are crazy enough to use thousands of aliases now.
10 $Id: interface.c,v 1.14 2001/02/10 19:31:15 pb Exp $
13 #include "config.h"
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/ioctl.h>
18 #include <netinet/in.h>
19 #include <net/if.h>
20 #include <stdio.h>
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <ctype.h>
27 #if HAVE_AFIPX
28 #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
29 #include <netipx/ipx.h>
30 #else
31 #include "ipx.h"
32 #endif
33 #endif
35 #if HAVE_AFECONET
36 #include <neteconet/ec.h>
37 #endif
39 #ifdef HAVE_HWSLIP
40 #include <linux/if_slip.h>
41 #include <net/if_arp.h>
42 #endif
44 #include "net-support.h"
45 #include "pathnames.h"
46 #include "version.h"
47 #include "proc.h"
49 #include "interface.h"
50 #include "sockets.h"
51 #include "util.h"
52 #include "intl.h"
54 #ifdef IFF_PORTSEL
55 const char *if_port_text[][4] =
57 /* Keep in step with <linux/netdevice.h> */
58 {"unknown", NULL, NULL, NULL},
59 {"10base2", "bnc", "coax", NULL},
60 {"10baseT", "utp", "tpe", NULL},
61 {"AUI", "thick", "db15", NULL},
62 {"100baseT", NULL, NULL, NULL},
63 {"100baseTX", NULL, NULL, NULL},
64 {"100baseFX", NULL, NULL, NULL},
65 {NULL, NULL, NULL, NULL},
67 #endif
69 #define IPV6_ADDR_ANY 0x0000U
71 #define IPV6_ADDR_UNICAST 0x0001U
72 #define IPV6_ADDR_MULTICAST 0x0002U
73 #define IPV6_ADDR_ANYCAST 0x0004U
75 #define IPV6_ADDR_LOOPBACK 0x0010U
76 #define IPV6_ADDR_LINKLOCAL 0x0020U
77 #define IPV6_ADDR_SITELOCAL 0x0040U
79 #define IPV6_ADDR_COMPATv4 0x0080U
81 #define IPV6_ADDR_SCOPE_MASK 0x00f0U
83 #define IPV6_ADDR_MAPPED 0x1000U
84 #define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */
86 int procnetdev_vsn = 1;
88 int ife_short;
90 static struct interface *int_list, *int_last;
92 static int if_readlist_proc(char *);
94 static struct interface *add_interface(char *name)
96 struct interface *ife, **nextp, *new;
98 for (ife = int_last; ife; ife = ife->prev) {
99 int n = nstrcmp(ife->name, name);
100 if (n == 0)
101 return ife;
102 if (n < 0)
103 break;
105 new(new);
106 safe_strncpy(new->name, name, IFNAMSIZ);
107 nextp = ife ? &ife->next : &int_list;
108 new->prev = ife;
109 new->next = *nextp;
110 if (new->next)
111 new->next->prev = new;
112 else
113 int_last = new;
114 *nextp = new;
115 return new;
118 struct interface *lookup_interface(char *name)
120 struct interface *ife = NULL;
122 if (if_readlist_proc(name) < 0)
123 return NULL;
124 ife = add_interface(name);
125 return ife;
128 int for_all_interfaces(int (*doit) (struct interface *, void *), void *cookie)
130 struct interface *ife;
132 if (!int_list && (if_readlist() < 0))
133 return -1;
134 for (ife = int_list; ife; ife = ife->next) {
135 int err = doit(ife, cookie);
136 if (err)
137 return err;
139 return 0;
142 int free_interface_list(void)
144 struct interface *ife;
145 while ((ife = int_list) != NULL) {
146 int_list = ife->next;
147 free(ife);
149 return 0;
152 static int if_readconf(void)
154 int numreqs = 30;
155 struct ifconf ifc;
156 struct ifreq *ifr;
157 int n, err = -1;
158 int skfd;
160 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
161 (as of 2.1.128) */
162 skfd = get_socket_for_af(AF_INET);
163 if (skfd < 0) {
164 fprintf(stderr, _("warning: no inet socket available: %s\n"),
165 strerror(errno));
166 /* Try to soldier on with whatever socket we can get hold of. */
167 skfd = sockets_open(0);
168 if (skfd < 0)
169 return -1;
172 ifc.ifc_buf = NULL;
173 for (;;) {
174 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
175 ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
177 if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
178 perror("SIOCGIFCONF");
179 goto out;
181 if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
182 /* assume it overflowed and try again */
183 numreqs += 10;
184 continue;
186 break;
189 ifr = ifc.ifc_req;
190 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
191 add_interface(ifr->ifr_name);
192 ifr++;
194 err = 0;
196 out:
197 free(ifc.ifc_buf);
198 return err;
201 static char *get_name(char *name, char *p)
203 while (isspace(*p))
204 p++;
205 while (*p) {
206 if (isspace(*p))
207 break;
208 if (*p == ':') { /* could be an alias */
209 char *dot = p, *dotname = name;
210 *name++ = *p++;
211 while (isdigit(*p))
212 *name++ = *p++;
213 if (*p != ':') { /* it wasn't, backup */
214 p = dot;
215 name = dotname;
217 if (*p == '\0')
218 return NULL;
219 p++;
220 break;
222 *name++ = *p++;
224 *name++ = '\0';
225 return p;
228 static int procnetdev_version(char *buf)
230 if (strstr(buf, "compressed"))
231 return 3;
232 if (strstr(buf, "bytes"))
233 return 2;
234 return 1;
237 static int get_dev_fields(char *bp, struct interface *ife)
239 switch (procnetdev_vsn) {
240 case 3:
241 sscanf(bp,
242 "%llu %llu %lu %lu %lu %lu %lu %lu %llu %llu %lu %lu %lu %lu %lu %lu",
243 &ife->stats.rx_bytes,
244 &ife->stats.rx_packets,
245 &ife->stats.rx_errors,
246 &ife->stats.rx_dropped,
247 &ife->stats.rx_fifo_errors,
248 &ife->stats.rx_frame_errors,
249 &ife->stats.rx_compressed,
250 &ife->stats.rx_multicast,
252 &ife->stats.tx_bytes,
253 &ife->stats.tx_packets,
254 &ife->stats.tx_errors,
255 &ife->stats.tx_dropped,
256 &ife->stats.tx_fifo_errors,
257 &ife->stats.collisions,
258 &ife->stats.tx_carrier_errors,
259 &ife->stats.tx_compressed);
260 break;
261 case 2:
262 sscanf(bp, "%llu %llu %lu %lu %lu %lu %llu %llu %lu %lu %lu %lu %lu",
263 &ife->stats.rx_bytes,
264 &ife->stats.rx_packets,
265 &ife->stats.rx_errors,
266 &ife->stats.rx_dropped,
267 &ife->stats.rx_fifo_errors,
268 &ife->stats.rx_frame_errors,
270 &ife->stats.tx_bytes,
271 &ife->stats.tx_packets,
272 &ife->stats.tx_errors,
273 &ife->stats.tx_dropped,
274 &ife->stats.tx_fifo_errors,
275 &ife->stats.collisions,
276 &ife->stats.tx_carrier_errors);
277 ife->stats.rx_multicast = 0;
278 break;
279 case 1:
280 sscanf(bp, "%llu %lu %lu %lu %lu %llu %lu %lu %lu %lu %lu",
281 &ife->stats.rx_packets,
282 &ife->stats.rx_errors,
283 &ife->stats.rx_dropped,
284 &ife->stats.rx_fifo_errors,
285 &ife->stats.rx_frame_errors,
287 &ife->stats.tx_packets,
288 &ife->stats.tx_errors,
289 &ife->stats.tx_dropped,
290 &ife->stats.tx_fifo_errors,
291 &ife->stats.collisions,
292 &ife->stats.tx_carrier_errors);
293 ife->stats.rx_bytes = 0;
294 ife->stats.tx_bytes = 0;
295 ife->stats.rx_multicast = 0;
296 break;
298 return 0;
301 static int if_readlist_proc(char *target)
303 static int proc_read;
304 FILE *fh;
305 char buf[512];
306 struct interface *ife;
307 int err;
309 if (proc_read)
310 return 0;
311 if (!target)
312 proc_read = 1;
314 fh = fopen(_PATH_PROCNET_DEV, "r");
315 if (!fh) {
316 fprintf(stderr, _("Warning: cannot open %s (%s). Limited output.\n"),
317 _PATH_PROCNET_DEV, strerror(errno));
318 return if_readconf();
320 fgets(buf, sizeof buf, fh); /* eat line */
321 fgets(buf, sizeof buf, fh);
323 #if 0 /* pretty, but can't cope with missing fields */
324 fmt = proc_gen_fmt(_PATH_PROCNET_DEV, 1, fh,
325 "face", "", /* parsed separately */
326 "bytes", "%lu",
327 "packets", "%lu",
328 "errs", "%lu",
329 "drop", "%lu",
330 "fifo", "%lu",
331 "frame", "%lu",
332 "compressed", "%lu",
333 "multicast", "%lu",
334 "bytes", "%lu",
335 "packets", "%lu",
336 "errs", "%lu",
337 "drop", "%lu",
338 "fifo", "%lu",
339 "colls", "%lu",
340 "carrier", "%lu",
341 "compressed", "%lu",
342 NULL);
343 if (!fmt)
344 return -1;
345 #else
346 procnetdev_vsn = procnetdev_version(buf);
347 #endif
349 err = 0;
350 while (fgets(buf, sizeof buf, fh)) {
351 char *s, name[IFNAMSIZ];
352 s = get_name(name, buf);
353 ife = add_interface(name);
354 get_dev_fields(s, ife);
355 ife->statistics_valid = 1;
356 if (target && !strcmp(target,name))
357 break;
359 if (ferror(fh)) {
360 perror(_PATH_PROCNET_DEV);
361 err = -1;
362 proc_read = 0;
365 #if 0
366 free(fmt);
367 #endif
368 fclose(fh);
369 return err;
372 int if_readlist(void)
374 int err = if_readlist_proc(NULL);
375 if (!err)
376 err = if_readconf();
377 return err;
380 /* Support for fetching an IPX address */
382 #if HAVE_AFIPX
383 static int ipx_getaddr(int sock, int ft, struct ifreq *ifr)
385 ((struct sockaddr_ipx *) &ifr->ifr_addr)->sipx_type = ft;
386 return ioctl(sock, SIOCGIFADDR, ifr);
388 #endif
390 /* Fetch the interface configuration from the kernel. */
391 int if_fetch(struct interface *ife)
393 struct ifreq ifr;
394 int fd;
395 char *ifname = ife->name;
397 strcpy(ifr.ifr_name, ifname);
398 if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
399 return (-1);
400 ife->flags = ifr.ifr_flags;
402 strcpy(ifr.ifr_name, ifname);
403 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
404 memset(ife->hwaddr, 0, 32);
405 else
406 memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
408 ife->type = ifr.ifr_hwaddr.sa_family;
410 strcpy(ifr.ifr_name, ifname);
411 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
412 ife->metric = 0;
413 else
414 ife->metric = ifr.ifr_metric;
416 strcpy(ifr.ifr_name, ifname);
417 if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
418 ife->mtu = 0;
419 else
420 ife->mtu = ifr.ifr_mtu;
422 #ifdef HAVE_HWSLIP
423 if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
424 ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 ||
425 ife->type == ARPHRD_ADAPT) {
426 #ifdef SIOCGOUTFILL
427 strcpy(ifr.ifr_name, ifname);
428 if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0)
429 ife->outfill = 0;
430 else
431 ife->outfill = (unsigned int) ifr.ifr_data;
432 #endif
433 #ifdef SIOCGKEEPALIVE
434 strcpy(ifr.ifr_name, ifname);
435 if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0)
436 ife->keepalive = 0;
437 else
438 ife->keepalive = (unsigned int) ifr.ifr_data;
439 #endif
441 #endif
443 strcpy(ifr.ifr_name, ifname);
444 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
445 memset(&ife->map, 0, sizeof(struct ifmap));
446 else
447 memcpy(&ife->map, &ifr.ifr_map, sizeof(struct ifmap));
449 strcpy(ifr.ifr_name, ifname);
450 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
451 memset(&ife->map, 0, sizeof(struct ifmap));
452 else
453 ife->map = ifr.ifr_map;
455 #ifdef HAVE_TXQUEUELEN
456 strcpy(ifr.ifr_name, ifname);
457 if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
458 ife->tx_queue_len = -1; /* unknown value */
459 else
460 ife->tx_queue_len = ifr.ifr_qlen;
461 #else
462 ife->tx_queue_len = -1; /* unknown value */
463 #endif
465 #if HAVE_AFINET
466 /* IPv4 address? */
467 fd = get_socket_for_af(AF_INET);
468 if (fd >= 0) {
469 strcpy(ifr.ifr_name, ifname);
470 ifr.ifr_addr.sa_family = AF_INET;
471 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
472 ife->has_ip = 1;
473 ife->addr = ifr.ifr_addr;
474 strcpy(ifr.ifr_name, ifname);
475 if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
476 memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
477 else
478 ife->dstaddr = ifr.ifr_dstaddr;
480 strcpy(ifr.ifr_name, ifname);
481 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
482 memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
483 else
484 ife->broadaddr = ifr.ifr_broadaddr;
486 strcpy(ifr.ifr_name, ifname);
487 if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
488 memset(&ife->netmask, 0, sizeof(struct sockaddr));
489 else
490 ife->netmask = ifr.ifr_netmask;
491 } else
492 memset(&ife->addr, 0, sizeof(struct sockaddr));
494 #endif
496 #if HAVE_AFATALK
497 /* DDP address maybe ? */
498 fd = get_socket_for_af(AF_APPLETALK);
499 if (fd >= 0) {
500 strcpy(ifr.ifr_name, ifname);
501 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
502 ife->ddpaddr = ifr.ifr_addr;
503 ife->has_ddp = 1;
506 #endif
508 #if HAVE_AFIPX
509 /* Look for IPX addresses with all framing types */
510 fd = get_socket_for_af(AF_IPX);
511 if (fd >= 0) {
512 strcpy(ifr.ifr_name, ifname);
513 if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) {
514 ife->has_ipx_bb = 1;
515 ife->ipxaddr_bb = ifr.ifr_addr;
517 strcpy(ifr.ifr_name, ifname);
518 if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) {
519 ife->has_ipx_sn = 1;
520 ife->ipxaddr_sn = ifr.ifr_addr;
522 strcpy(ifr.ifr_name, ifname);
523 if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) {
524 ife->has_ipx_e3 = 1;
525 ife->ipxaddr_e3 = ifr.ifr_addr;
527 strcpy(ifr.ifr_name, ifname);
528 if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) {
529 ife->has_ipx_e2 = 1;
530 ife->ipxaddr_e2 = ifr.ifr_addr;
533 #endif
535 #if HAVE_AFECONET
536 /* Econet address maybe? */
537 fd = get_socket_for_af(AF_ECONET);
538 if (fd >= 0) {
539 strcpy(ifr.ifr_name, ifname);
540 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
541 ife->ecaddr = ifr.ifr_addr;
542 ife->has_econet = 1;
545 #endif
547 return 0;
550 int do_if_fetch(struct interface *ife)
552 if (if_fetch(ife) < 0) {
553 char *errmsg;
554 if (errno == ENODEV) {
555 /* Give better error message for this case. */
556 errmsg = _("Device not found");
557 } else {
558 errmsg = strerror(errno);
560 fprintf(stderr, _("%s: error fetching interface information: %s\n"),
561 ife->name, errmsg);
562 return -1;
564 return 0;
567 int do_if_print(struct interface *ife, void *cookie)
569 int *opt_a = (int *) cookie;
570 int res;
572 res = do_if_fetch(ife);
573 if (res >= 0) {
574 if ((ife->flags & IFF_UP) || *opt_a)
575 ife_print(ife);
577 return res;
580 void ife_print_short(struct interface *ptr)
582 printf("%-5.5s ", ptr->name);
583 printf("%5d %3d", ptr->mtu, ptr->metric);
584 /* If needed, display the interface statistics. */
585 if (ptr->statistics_valid) {
586 printf("%8llu %6lu %6lu %6lu",
587 ptr->stats.rx_packets, ptr->stats.rx_errors,
588 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors);
589 printf("%8llu %6lu %6lu %6lu ",
590 ptr->stats.tx_packets, ptr->stats.tx_errors,
591 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors);
592 } else {
593 printf("%-56s", _(" - no statistics available -"));
595 /* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
596 if (ptr->flags == 0)
597 printf(_("[NO FLAGS]"));
598 if (ptr->flags & IFF_ALLMULTI)
599 printf("A");
600 if (ptr->flags & IFF_BROADCAST)
601 printf("B");
602 if (ptr->flags & IFF_DEBUG)
603 printf("D");
604 if (ptr->flags & IFF_LOOPBACK)
605 printf("L");
606 if (ptr->flags & IFF_MULTICAST)
607 printf("M");
608 #ifdef HAVE_DYNAMIC
609 if (ptr->flags & IFF_DYNAMIC)
610 printf("d");
611 #endif
612 if (ptr->flags & IFF_PROMISC)
613 printf("P");
614 if (ptr->flags & IFF_NOTRAILERS)
615 printf("N");
616 if (ptr->flags & IFF_NOARP)
617 printf("O");
618 if (ptr->flags & IFF_POINTOPOINT)
619 printf("P");
620 if (ptr->flags & IFF_SLAVE)
621 printf("s");
622 if (ptr->flags & IFF_MASTER)
623 printf("m");
624 if (ptr->flags & IFF_RUNNING)
625 printf("R");
626 if (ptr->flags & IFF_UP)
627 printf("U");
628 /* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
629 printf("\n");
632 void ife_print_long(struct interface *ptr)
634 struct aftype *ap;
635 struct hwtype *hw;
636 int hf;
637 int can_compress = 0;
638 unsigned long long rx, tx, short_rx, short_tx;
639 char Rext[5]="b";
640 char Text[5]="b";
642 #if HAVE_AFIPX
643 static struct aftype *ipxtype = NULL;
644 #endif
645 #if HAVE_AFECONET
646 static struct aftype *ectype = NULL;
647 #endif
648 #if HAVE_AFATALK
649 static struct aftype *ddptype = NULL;
650 #endif
651 #if HAVE_AFINET6
652 FILE *f;
653 char addr6[40], devname[20];
654 struct sockaddr_in6 sap;
655 int plen, scope, dad_status, if_idx;
656 extern struct aftype inet6_aftype;
657 char addr6p[8][5];
658 #endif
660 ap = get_afntype(ptr->addr.sa_family);
661 if (ap == NULL)
662 ap = get_afntype(0);
664 hf = ptr->type;
666 if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)
667 can_compress = 1;
669 hw = get_hwntype(hf);
670 if (hw == NULL)
671 hw = get_hwntype(-1);
673 printf(_("%-9.9s Link encap:%s "), ptr->name, hw->title);
674 /* For some hardware types (eg Ash, ATM) we don't print the
675 hardware address if it's null. */
676 if (hw->print != NULL && (! (hw_null_address(hw, ptr->hwaddr) &&
677 hw->suppress_null_addr)))
678 printf(_("HWaddr %s "), hw->print(ptr->hwaddr));
679 #ifdef IFF_PORTSEL
680 if (ptr->flags & IFF_PORTSEL) {
681 printf(_("Media:%s"), if_port_text[ptr->map.port][0]);
682 if (ptr->flags & IFF_AUTOMEDIA)
683 printf(_("(auto)"));
685 #endif
686 printf("\n");
688 #if HAVE_AFINET
689 if (ptr->has_ip) {
690 printf(_(" %s addr:%s "), ap->name,
691 ap->sprint(&ptr->addr, 1));
692 if (ptr->flags & IFF_POINTOPOINT) {
693 printf(_(" P-t-P:%s "), ap->sprint(&ptr->dstaddr, 1));
695 if (ptr->flags & IFF_BROADCAST) {
696 printf(_(" Bcast:%s "), ap->sprint(&ptr->broadaddr, 1));
698 printf(_(" Mask:%s\n"), ap->sprint(&ptr->netmask, 1));
700 #endif
702 #if HAVE_AFINET6
703 /* FIXME: should be integrated into interface.c. */
705 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
706 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
707 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
708 addr6p[4], addr6p[5], addr6p[6], addr6p[7],
709 &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
710 if (!strcmp(devname, ptr->name)) {
711 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
712 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
713 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
714 inet6_aftype.input(1, addr6, (struct sockaddr *) &sap);
715 printf(_(" inet6 addr: %s/%d"),
716 inet6_aftype.sprint((struct sockaddr *) &sap, 1), plen);
717 printf(_(" Scope:"));
718 switch (scope) {
719 case 0:
720 printf(_("Global"));
721 break;
722 case IPV6_ADDR_LINKLOCAL:
723 printf(_("Link"));
724 break;
725 case IPV6_ADDR_SITELOCAL:
726 printf(_("Site"));
727 break;
728 case IPV6_ADDR_COMPATv4:
729 printf(_("Compat"));
730 break;
731 case IPV6_ADDR_LOOPBACK:
732 printf(_("Host"));
733 break;
734 default:
735 printf(_("Unknown"));
737 printf("\n");
740 fclose(f);
742 #endif
744 #if HAVE_AFIPX
745 if (ipxtype == NULL)
746 ipxtype = get_afntype(AF_IPX);
748 if (ipxtype != NULL) {
749 if (ptr->has_ipx_bb)
750 printf(_(" IPX/Ethernet II addr:%s\n"),
751 ipxtype->sprint(&ptr->ipxaddr_bb, 1));
752 if (ptr->has_ipx_sn)
753 printf(_(" IPX/Ethernet SNAP addr:%s\n"),
754 ipxtype->sprint(&ptr->ipxaddr_sn, 1));
755 if (ptr->has_ipx_e2)
756 printf(_(" IPX/Ethernet 802.2 addr:%s\n"),
757 ipxtype->sprint(&ptr->ipxaddr_e2, 1));
758 if (ptr->has_ipx_e3)
759 printf(_(" IPX/Ethernet 802.3 addr:%s\n"),
760 ipxtype->sprint(&ptr->ipxaddr_e3, 1));
762 #endif
764 #if HAVE_AFATALK
765 if (ddptype == NULL)
766 ddptype = get_afntype(AF_APPLETALK);
767 if (ddptype != NULL) {
768 if (ptr->has_ddp)
769 printf(_(" EtherTalk Phase 2 addr:%s\n"), ddptype->sprint(&ptr->ddpaddr, 1));
771 #endif
773 #if HAVE_AFECONET
774 if (ectype == NULL)
775 ectype = get_afntype(AF_ECONET);
776 if (ectype != NULL) {
777 if (ptr->has_econet)
778 printf(_(" econet addr:%s\n"), ectype->sprint(&ptr->ecaddr, 1));
780 #endif
782 printf(" ");
783 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
784 if (ptr->flags == 0)
785 printf(_("[NO FLAGS] "));
786 if (ptr->flags & IFF_UP)
787 printf(_("UP "));
788 if (ptr->flags & IFF_BROADCAST)
789 printf(_("BROADCAST "));
790 if (ptr->flags & IFF_DEBUG)
791 printf(_("DEBUG "));
792 if (ptr->flags & IFF_LOOPBACK)
793 printf(_("LOOPBACK "));
794 if (ptr->flags & IFF_POINTOPOINT)
795 printf(_("POINTOPOINT "));
796 if (ptr->flags & IFF_NOTRAILERS)
797 printf(_("NOTRAILERS "));
798 if (ptr->flags & IFF_RUNNING)
799 printf(_("RUNNING "));
800 if (ptr->flags & IFF_NOARP)
801 printf(_("NOARP "));
802 if (ptr->flags & IFF_PROMISC)
803 printf(_("PROMISC "));
804 if (ptr->flags & IFF_ALLMULTI)
805 printf(_("ALLMULTI "));
806 if (ptr->flags & IFF_SLAVE)
807 printf(_("SLAVE "));
808 if (ptr->flags & IFF_MASTER)
809 printf(_("MASTER "));
810 if (ptr->flags & IFF_MULTICAST)
811 printf(_("MULTICAST "));
812 #ifdef HAVE_DYNAMIC
813 if (ptr->flags & IFF_DYNAMIC)
814 printf(_("DYNAMIC "));
815 #endif
816 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
817 printf(_(" MTU:%d Metric:%d"),
818 ptr->mtu, ptr->metric ? ptr->metric : 1);
819 #ifdef SIOCSKEEPALIVE
820 if (ptr->outfill || ptr->keepalive)
821 printf(_(" Outfill:%d Keepalive:%d"),
822 ptr->outfill, ptr->keepalive);
823 #endif
824 printf("\n");
826 /* If needed, display the interface statistics. */
828 if (ptr->statistics_valid) {
829 /* XXX: statistics are currently only printed for the primary address,
830 * not for the aliases, although strictly speaking they're shared
831 * by all addresses.
833 printf(" ");
835 printf(_("RX packets:%llu errors:%lu dropped:%lu overruns:%lu frame:%lu\n"),
836 ptr->stats.rx_packets, ptr->stats.rx_errors,
837 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
838 ptr->stats.rx_frame_errors);
839 if (can_compress)
840 printf(_(" compressed:%lu\n"), ptr->stats.rx_compressed);
842 rx = ptr->stats.rx_bytes;
843 tx = ptr->stats.tx_bytes;
844 short_rx = rx * 10;
845 short_tx = tx * 10;
846 if (rx > 1048576) { short_rx /= 1048576; strcpy(Rext, "Mb"); }
847 else if (rx > 1024) { short_rx /= 1024; strcpy(Rext, "Kb"); }
848 if (tx > 1048576) { short_tx /= 1048576; strcpy(Text, "Mb"); }
849 else if (tx > 1024) { short_tx /= 1024; strcpy(Text, "Kb"); }
851 printf(" ");
852 printf(_("TX packets:%llu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n"),
853 ptr->stats.tx_packets, ptr->stats.tx_errors,
854 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
855 ptr->stats.tx_carrier_errors);
856 printf(_(" collisions:%lu "), ptr->stats.collisions);
857 if (can_compress)
858 printf(_("compressed:%lu "), ptr->stats.tx_compressed);
859 if (ptr->tx_queue_len != -1)
860 printf(_("txqueuelen:%d "), ptr->tx_queue_len);
861 printf("\n ");
862 printf(_("RX bytes:%llu (%lu.%lu %s) TX bytes:%llu (%lu.%lu %s)\n"),
863 rx, (unsigned long)(short_rx / 10),
864 (unsigned long)(short_rx % 10), Rext,
865 tx, (unsigned long)(short_tx / 10),
866 (unsigned long)(short_tx % 10), Text);
869 if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma ||
870 ptr->map.base_addr)) {
871 printf(" ");
872 if (ptr->map.irq)
873 printf(_("Interrupt:%d "), ptr->map.irq);
874 if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
875 I/O maps */
876 printf(_("Base address:0x%x "), ptr->map.base_addr);
877 if (ptr->map.mem_start) {
878 printf(_("Memory:%lx-%lx "), ptr->map.mem_start, ptr->map.mem_end);
880 if (ptr->map.dma)
881 printf(_("DMA chan:%x "), ptr->map.dma);
882 printf("\n");
884 printf("\n");
887 void ife_print(struct interface *i)
889 if (ife_short)
890 ife_print_short(i);
891 else
892 ife_print_long(i);