Base: LCDproc 0.5.2
[lcdproc-de200c.git] / contrib / interface-demo2 / interface.c
blob9df0ed1fb13bd06dd13fb56ba0dd527b224bbc1d
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.1.2.3 2007/04/14 18:07:42 marschap 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>
26 #include <string.h>
28 #if HAVE_AFIPX
29 #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
30 #include <netipx/ipx.h>
31 #else
32 #include "ipx.h"
33 #endif
34 #endif
36 #if HAVE_AFECONET
37 #include <neteconet/ec.h>
38 #endif
40 #ifdef HAVE_HWSLIP
41 #include <linux/if_slip.h>
42 #include <net/if_arp.h>
43 #endif
45 #include "net-support.h"
46 #include "pathnames.h"
47 #include "version.h"
48 #include "proc.h"
50 #include "interface.h"
51 #include "sockets.h"
52 #include "util.h"
53 #include "intl.h"
55 #ifdef IFF_PORTSEL
56 const char *if_port_text[][4] =
58 /* Keep in step with <linux/netdevice.h> */
59 {"unknown", NULL, NULL, NULL},
60 {"10base2", "bnc", "coax", NULL},
61 {"10baseT", "utp", "tpe", NULL},
62 {"AUI", "thick", "db15", NULL},
63 {"100baseT", NULL, NULL, NULL},
64 {"100baseTX", NULL, NULL, NULL},
65 {"100baseFX", NULL, NULL, NULL},
66 {NULL, NULL, NULL, NULL},
68 #endif
70 #define IPV6_ADDR_ANY 0x0000U
72 #define IPV6_ADDR_UNICAST 0x0001U
73 #define IPV6_ADDR_MULTICAST 0x0002U
74 #define IPV6_ADDR_ANYCAST 0x0004U
76 #define IPV6_ADDR_LOOPBACK 0x0010U
77 #define IPV6_ADDR_LINKLOCAL 0x0020U
78 #define IPV6_ADDR_SITELOCAL 0x0040U
80 #define IPV6_ADDR_COMPATv4 0x0080U
82 #define IPV6_ADDR_SCOPE_MASK 0x00f0U
84 #define IPV6_ADDR_MAPPED 0x1000U
85 #define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */
87 int procnetdev_vsn = 1;
89 int ife_short;
91 int if_list_all = 0; /* do we have requested the complete proc list, yet? */
93 static struct interface *int_list, *int_last;
95 static int if_readlist_proc(char *);
97 static struct interface *if_cache_add(char *name)
99 struct interface *ife, **nextp, *new;
101 if (!int_list)
102 int_last = NULL;
104 /* the cache is sorted, so if we hit a smaller if, exit */
105 for (ife = int_last; ife; ife = ife->prev) {
106 int n = nstrcmp(ife->name, name);
107 if (n == 0)
108 return ife;
109 if (n < 0)
110 break;
112 new(new);
113 safe_strncpy(new->name, name, IFNAMSIZ);
114 nextp = ife ? &ife->next : &int_list; // keep sorting
115 new->prev = ife;
116 new->next = *nextp;
117 if (new->next)
118 new->next->prev = new;
119 else
120 int_last = new;
121 *nextp = new;
122 return new;
125 struct interface *lookup_interface(char *name)
127 /* if we have read all, use it */
128 if (if_list_all)
129 return if_cache_add(name);
131 /* otherwise we read a limited list */
132 if (if_readlist_proc(name) < 0)
133 return NULL;
135 return if_cache_add(name);
138 int for_all_interfaces(int SD, int (*doit) (int, struct interface *, void *), void *cookie)
140 struct interface *ife;
142 if (!if_list_all && (if_readlist() < 0))
143 return -1;
144 for (ife = int_list; ife; ife = ife->next) {
145 int err = doit(SD, ife, cookie);
146 if (err)
147 return err;
149 return 0;
152 int if_cache_free(void)
154 struct interface *ife;
155 while ((ife = int_list) != NULL) {
156 int_list = ife->next;
157 free(ife);
159 int_last = NULL;
160 if_list_all = 0;
161 return 0;
164 static int if_readconf(void)
166 int numreqs = 30;
167 struct ifconf ifc;
168 struct ifreq *ifr;
169 int n, err = -1;
170 int skfd;
172 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
173 (as of 2.1.128) */
174 skfd = get_socket_for_af(AF_INET);
175 if (skfd < 0) {
176 fprintf(stderr, _("warning: no inet socket available: %s\n"),
177 strerror(errno));
178 /* Try to soldier on with whatever socket we can get hold of. */
179 skfd = sockets_open(0);
180 if (skfd < 0)
181 return -1;
184 ifc.ifc_buf = NULL;
185 for (;;) {
186 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
187 ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
189 if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
190 perror("SIOCGIFCONF");
191 goto out;
193 if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
194 /* assume it overflowed and try again */
195 numreqs *= 2;
196 continue;
198 break;
201 ifr = ifc.ifc_req;
202 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
203 if_cache_add(ifr->ifr_name);
204 ifr++;
206 err = 0;
208 out:
209 free(ifc.ifc_buf);
210 return err;
213 char *get_name(char *name, char *p)
215 while (isspace(*p))
216 p++;
217 while (*p) {
218 if (isspace(*p))
219 break;
220 if (*p == ':') { /* could be an alias */
221 char *dot = p++;
222 while (*p && isdigit(*p)) p++;
223 if (*p == ':') {
224 /* Yes it is, backup and copy it. */
225 p = dot;
226 *name++ = *p++;
227 while (*p && isdigit(*p)) {
228 *name++ = *p++;
230 } else {
231 /* No, it isn't */
232 p = dot;
234 p++;
235 break;
237 *name++ = *p++;
239 *name++ = '\0';
240 return p;
243 int procnetdev_version(char *buf)
245 if (strstr(buf, "compressed"))
246 return 3;
247 if (strstr(buf, "bytes"))
248 return 2;
249 return 1;
252 int get_dev_fields(char *bp, struct interface *ife)
254 switch (procnetdev_vsn) {
255 case 3:
256 sscanf(bp,
257 "%Lu %Lu %lu %lu %lu %lu %lu %lu %Lu %Lu %lu %lu %lu %lu %lu %lu",
258 &ife->stats.rx_bytes,
259 &ife->stats.rx_packets,
260 &ife->stats.rx_errors,
261 &ife->stats.rx_dropped,
262 &ife->stats.rx_fifo_errors,
263 &ife->stats.rx_frame_errors,
264 &ife->stats.rx_compressed,
265 &ife->stats.rx_multicast,
267 &ife->stats.tx_bytes,
268 &ife->stats.tx_packets,
269 &ife->stats.tx_errors,
270 &ife->stats.tx_dropped,
271 &ife->stats.tx_fifo_errors,
272 &ife->stats.collisions,
273 &ife->stats.tx_carrier_errors,
274 &ife->stats.tx_compressed);
275 break;
276 case 2:
277 sscanf(bp, "%Lu %Lu %lu %lu %lu %lu %Lu %Lu %lu %lu %lu %lu %lu",
278 &ife->stats.rx_bytes,
279 &ife->stats.rx_packets,
280 &ife->stats.rx_errors,
281 &ife->stats.rx_dropped,
282 &ife->stats.rx_fifo_errors,
283 &ife->stats.rx_frame_errors,
285 &ife->stats.tx_bytes,
286 &ife->stats.tx_packets,
287 &ife->stats.tx_errors,
288 &ife->stats.tx_dropped,
289 &ife->stats.tx_fifo_errors,
290 &ife->stats.collisions,
291 &ife->stats.tx_carrier_errors);
292 ife->stats.rx_multicast = 0;
293 break;
294 case 1:
295 sscanf(bp, "%Lu %lu %lu %lu %lu %Lu %lu %lu %lu %lu %lu",
296 &ife->stats.rx_packets,
297 &ife->stats.rx_errors,
298 &ife->stats.rx_dropped,
299 &ife->stats.rx_fifo_errors,
300 &ife->stats.rx_frame_errors,
302 &ife->stats.tx_packets,
303 &ife->stats.tx_errors,
304 &ife->stats.tx_dropped,
305 &ife->stats.tx_fifo_errors,
306 &ife->stats.collisions,
307 &ife->stats.tx_carrier_errors);
308 ife->stats.rx_bytes = 0;
309 ife->stats.tx_bytes = 0;
310 ife->stats.rx_multicast = 0;
311 break;
313 return 0;
316 static int if_readlist_proc(char *target)
318 FILE *fh;
319 char buf[512];
320 struct interface *ife;
321 int err;
323 fh = fopen(_PATH_PROCNET_DEV, "r");
324 if (!fh) {
325 fprintf(stderr, _("Warning: cannot open %s (%s). Limited output.\n"),
326 _PATH_PROCNET_DEV, strerror(errno));
327 return -2;
329 fgets(buf, sizeof buf, fh); /* eat line */
330 fgets(buf, sizeof buf, fh);
332 #if 0 /* pretty, but can't cope with missing fields */
333 fmt = proc_gen_fmt(_PATH_PROCNET_DEV, 1, fh,
334 "face", "", /* parsed separately */
335 "bytes", "%lu",
336 "packets", "%lu",
337 "errs", "%lu",
338 "drop", "%lu",
339 "fifo", "%lu",
340 "frame", "%lu",
341 "compressed", "%lu",
342 "multicast", "%lu",
343 "bytes", "%lu",
344 "packets", "%lu",
345 "errs", "%lu",
346 "drop", "%lu",
347 "fifo", "%lu",
348 "colls", "%lu",
349 "carrier", "%lu",
350 "compressed", "%lu",
351 NULL);
352 if (!fmt)
353 return -1;
354 #else
355 procnetdev_vsn = procnetdev_version(buf);
356 #endif
358 err = 0;
359 while (fgets(buf, sizeof buf, fh)) {
360 char *s, name[IFNAMSIZ];
361 s = get_name(name, buf);
362 ife = if_cache_add(name);
363 get_dev_fields(s, ife);
364 ife->statistics_valid = 1;
365 if (target && !strcmp(target,name))
366 break;
368 if (ferror(fh)) {
369 perror(_PATH_PROCNET_DEV);
370 err = -1;
373 #if 0
374 free(fmt);
375 #endif
376 fclose(fh);
377 return err;
380 int if_readlist(void)
382 /* caller will/should check not to call this too often
383 * (i.e. only if if_list_all == 0
385 int err = 0;
387 err |= if_readlist_proc(NULL);
388 err |= if_readconf();
390 if_list_all = 1;
392 return err;
395 /* Support for fetching an IPX address */
397 #if HAVE_AFIPX
398 static int ipx_getaddr(int sock, int ft, struct ifreq *ifr)
400 ((struct sockaddr_ipx *) &ifr->ifr_addr)->sipx_type = ft;
401 return ioctl(sock, SIOCGIFADDR, ifr);
403 #endif
405 /* Fetch the interface configuration from the kernel. */
406 int if_fetch(struct interface *ife)
408 struct ifreq ifr;
409 int fd;
410 char *ifname = ife->name;
412 strcpy(ifr.ifr_name, ifname);
413 if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
414 return (-1);
415 ife->flags = ifr.ifr_flags;
417 strcpy(ifr.ifr_name, ifname);
418 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
419 memset(ife->hwaddr, 0, 32);
420 else
421 memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
423 ife->type = ifr.ifr_hwaddr.sa_family;
425 strcpy(ifr.ifr_name, ifname);
426 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
427 ife->metric = 0;
428 else
429 ife->metric = ifr.ifr_metric;
431 strcpy(ifr.ifr_name, ifname);
432 if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
433 ife->mtu = 0;
434 else
435 ife->mtu = ifr.ifr_mtu;
437 #ifdef HAVE_HWSLIP
438 if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
439 ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 ||
440 ife->type == ARPHRD_ADAPT) {
441 #ifdef SIOCGOUTFILL
442 strcpy(ifr.ifr_name, ifname);
443 if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0)
444 ife->outfill = 0;
445 else
446 ife->outfill = (unsigned int) ifr.ifr_data;
447 #endif
448 #ifdef SIOCGKEEPALIVE
449 strcpy(ifr.ifr_name, ifname);
450 if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0)
451 ife->keepalive = 0;
452 else
453 ife->keepalive = (unsigned int) ifr.ifr_data;
454 #endif
456 #endif
458 strcpy(ifr.ifr_name, ifname);
459 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
460 memset(&ife->map, 0, sizeof(struct ifmap));
461 else
462 memcpy(&ife->map, &ifr.ifr_map, sizeof(struct ifmap));
464 strcpy(ifr.ifr_name, ifname);
465 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
466 memset(&ife->map, 0, sizeof(struct ifmap));
467 else
468 ife->map = ifr.ifr_map;
470 #ifdef HAVE_TXQUEUELEN
471 strcpy(ifr.ifr_name, ifname);
472 if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
473 ife->tx_queue_len = -1; /* unknown value */
474 else
475 ife->tx_queue_len = ifr.ifr_qlen;
476 #else
477 ife->tx_queue_len = -1; /* unknown value */
478 #endif
480 #if HAVE_AFINET
481 /* IPv4 address? */
482 fd = get_socket_for_af(AF_INET);
483 if (fd >= 0) {
484 strcpy(ifr.ifr_name, ifname);
485 ifr.ifr_addr.sa_family = AF_INET;
486 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
487 ife->has_ip = 1;
488 ife->addr = ifr.ifr_addr;
489 strcpy(ifr.ifr_name, ifname);
490 if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
491 memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
492 else
493 ife->dstaddr = ifr.ifr_dstaddr;
495 strcpy(ifr.ifr_name, ifname);
496 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
497 memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
498 else
499 ife->broadaddr = ifr.ifr_broadaddr;
501 strcpy(ifr.ifr_name, ifname);
502 if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
503 memset(&ife->netmask, 0, sizeof(struct sockaddr));
504 else
505 ife->netmask = ifr.ifr_netmask;
506 } else
507 memset(&ife->addr, 0, sizeof(struct sockaddr));
509 #endif
511 #if HAVE_AFATALK
512 /* DDP address maybe ? */
513 fd = get_socket_for_af(AF_APPLETALK);
514 if (fd >= 0) {
515 strcpy(ifr.ifr_name, ifname);
516 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
517 ife->ddpaddr = ifr.ifr_addr;
518 ife->has_ddp = 1;
521 #endif
523 #if HAVE_AFIPX
524 /* Look for IPX addresses with all framing types */
525 fd = get_socket_for_af(AF_IPX);
526 if (fd >= 0) {
527 strcpy(ifr.ifr_name, ifname);
528 if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) {
529 ife->has_ipx_bb = 1;
530 ife->ipxaddr_bb = ifr.ifr_addr;
532 strcpy(ifr.ifr_name, ifname);
533 if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) {
534 ife->has_ipx_sn = 1;
535 ife->ipxaddr_sn = ifr.ifr_addr;
537 strcpy(ifr.ifr_name, ifname);
538 if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) {
539 ife->has_ipx_e3 = 1;
540 ife->ipxaddr_e3 = ifr.ifr_addr;
542 strcpy(ifr.ifr_name, ifname);
543 if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) {
544 ife->has_ipx_e2 = 1;
545 ife->ipxaddr_e2 = ifr.ifr_addr;
548 #endif
550 #if HAVE_AFECONET
551 /* Econet address maybe? */
552 fd = get_socket_for_af(AF_ECONET);
553 if (fd >= 0) {
554 strcpy(ifr.ifr_name, ifname);
555 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
556 ife->ecaddr = ifr.ifr_addr;
557 ife->has_econet = 1;
560 #endif
562 return 0;
565 int do_if_fetch(struct interface *ife)
567 if (if_fetch(ife) < 0) {
568 char *errmsg;
569 if (errno == ENODEV) {
570 /* Give better error message for this case. */
571 errmsg = _("Device not found");
572 } else {
573 errmsg = strerror(errno);
575 fprintf(stderr, _("%s: error fetching interface information: %s\n"),
576 ife->name, errmsg);
577 return -1;
579 return 0;
582 int do_if_print(struct interface *ife, void *cookie)
584 int *opt_a = (int *) cookie;
585 int res;
587 res = do_if_fetch(ife);
588 if (res >= 0) {
589 if ((ife->flags & IFF_UP) || *opt_a)
590 ife_print(ife);
592 return res;
595 void ife_print_short(struct interface *ptr)
597 printf("%-5.5s ", ptr->name);
598 printf("%5d %-2d ", ptr->mtu, ptr->metric);
599 /* If needed, display the interface statistics. */
600 if (ptr->statistics_valid) {
601 printf("%8llu %6lu %6lu %6lu ",
602 ptr->stats.rx_packets, ptr->stats.rx_errors,
603 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors);
604 printf("%8llu %6lu %6lu %6lu ",
605 ptr->stats.tx_packets, ptr->stats.tx_errors,
606 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors);
607 } else {
608 printf("%-56s", _(" - no statistics available -"));
610 /* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
611 if (ptr->flags == 0)
612 printf(_("[NO FLAGS]"));
613 if (ptr->flags & IFF_ALLMULTI)
614 printf("A");
615 if (ptr->flags & IFF_BROADCAST)
616 printf("B");
617 if (ptr->flags & IFF_DEBUG)
618 printf("D");
619 if (ptr->flags & IFF_LOOPBACK)
620 printf("L");
621 if (ptr->flags & IFF_MULTICAST)
622 printf("M");
623 #ifdef HAVE_DYNAMIC
624 if (ptr->flags & IFF_DYNAMIC)
625 printf("d");
626 #endif
627 if (ptr->flags & IFF_PROMISC)
628 printf("P");
629 if (ptr->flags & IFF_NOTRAILERS)
630 printf("N");
631 if (ptr->flags & IFF_NOARP)
632 printf("O");
633 if (ptr->flags & IFF_POINTOPOINT)
634 printf("P");
635 if (ptr->flags & IFF_SLAVE)
636 printf("s");
637 if (ptr->flags & IFF_MASTER)
638 printf("m");
639 if (ptr->flags & IFF_RUNNING)
640 printf("R");
641 if (ptr->flags & IFF_UP)
642 printf("U");
643 /* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
644 printf("\n");
647 void ife_print_long(struct interface *ptr)
649 struct aftype *ap;
650 struct hwtype *hw;
651 int hf;
652 int can_compress = 0;
653 unsigned long long rx, tx, short_rx, short_tx;
654 const char *Rext = "b";
655 const char *Text = "b";
657 #if HAVE_AFIPX
658 static struct aftype *ipxtype = NULL;
659 #endif
660 #if HAVE_AFECONET
661 static struct aftype *ectype = NULL;
662 #endif
663 #if HAVE_AFATALK
664 static struct aftype *ddptype = NULL;
665 #endif
666 #if HAVE_AFINET6
667 FILE *f;
668 char addr6[40], devname[20];
669 struct sockaddr_in6 sap;
670 int plen, scope, dad_status, if_idx;
671 extern struct aftype inet6_aftype;
672 char addr6p[8][5];
673 #endif
675 ap = get_afntype(ptr->addr.sa_family);
676 if (ap == NULL)
677 ap = get_afntype(0);
679 hf = ptr->type;
681 if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)
682 can_compress = 1;
684 hw = get_hwntype(hf);
685 if (hw == NULL)
686 hw = get_hwntype(-1);
688 printf(_("%-9.9s Link encap:%s "), ptr->name, hw->title);
689 /* For some hardware types (eg Ash, ATM) we don't print the
690 hardware address if it's null. */
691 if (hw->print != NULL && (! (hw_null_address(hw, ptr->hwaddr) &&
692 hw->suppress_null_addr)))
693 printf(_("HWaddr %s "), hw->print(ptr->hwaddr));
694 #ifdef IFF_PORTSEL
695 if (ptr->flags & IFF_PORTSEL) {
696 printf(_("Media:%s"), if_port_text[ptr->map.port][0]);
697 if (ptr->flags & IFF_AUTOMEDIA)
698 printf(_("(auto)"));
700 #endif
701 printf("\n");
703 #if HAVE_AFINET
704 if (ptr->has_ip) {
705 printf(_(" %s addr:%s "), ap->name,
706 ap->sprint(&ptr->addr, 1));
707 if (ptr->flags & IFF_POINTOPOINT) {
708 printf(_(" P-t-P:%s "), ap->sprint(&ptr->dstaddr, 1));
710 if (ptr->flags & IFF_BROADCAST) {
711 printf(_(" Bcast:%s "), ap->sprint(&ptr->broadaddr, 1));
713 printf(_(" Mask:%s\n"), ap->sprint(&ptr->netmask, 1));
715 #endif
717 #if HAVE_AFINET6
718 /* FIXME: should be integrated into interface.c. */
720 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
721 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
722 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
723 addr6p[4], addr6p[5], addr6p[6], addr6p[7],
724 &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
725 if (!strcmp(devname, ptr->name)) {
726 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
727 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
728 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
729 inet6_aftype.input(1, addr6, (struct sockaddr *) &sap);
730 printf(_(" inet6 addr: %s/%d"),
731 inet6_aftype.sprint((struct sockaddr *) &sap, 1), plen);
732 printf(_(" Scope:"));
733 switch (scope) {
734 case 0:
735 printf(_("Global"));
736 break;
737 case IPV6_ADDR_LINKLOCAL:
738 printf(_("Link"));
739 break;
740 case IPV6_ADDR_SITELOCAL:
741 printf(_("Site"));
742 break;
743 case IPV6_ADDR_COMPATv4:
744 printf(_("Compat"));
745 break;
746 case IPV6_ADDR_LOOPBACK:
747 printf(_("Host"));
748 break;
749 default:
750 printf(_("Unknown"));
752 printf("\n");
755 fclose(f);
757 #endif
759 #if HAVE_AFIPX
760 if (ipxtype == NULL)
761 ipxtype = get_afntype(AF_IPX);
763 if (ipxtype != NULL) {
764 if (ptr->has_ipx_bb)
765 printf(_(" IPX/Ethernet II addr:%s\n"),
766 ipxtype->sprint(&ptr->ipxaddr_bb, 1));
767 if (ptr->has_ipx_sn)
768 printf(_(" IPX/Ethernet SNAP addr:%s\n"),
769 ipxtype->sprint(&ptr->ipxaddr_sn, 1));
770 if (ptr->has_ipx_e2)
771 printf(_(" IPX/Ethernet 802.2 addr:%s\n"),
772 ipxtype->sprint(&ptr->ipxaddr_e2, 1));
773 if (ptr->has_ipx_e3)
774 printf(_(" IPX/Ethernet 802.3 addr:%s\n"),
775 ipxtype->sprint(&ptr->ipxaddr_e3, 1));
777 #endif
779 #if HAVE_AFATALK
780 if (ddptype == NULL)
781 ddptype = get_afntype(AF_APPLETALK);
782 if (ddptype != NULL) {
783 if (ptr->has_ddp)
784 printf(_(" EtherTalk Phase 2 addr:%s\n"), ddptype->sprint(&ptr->ddpaddr, 1));
786 #endif
788 #if HAVE_AFECONET
789 if (ectype == NULL)
790 ectype = get_afntype(AF_ECONET);
791 if (ectype != NULL) {
792 if (ptr->has_econet)
793 printf(_(" econet addr:%s\n"), ectype->sprint(&ptr->ecaddr, 1));
795 #endif
797 printf(" ");
798 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
799 if (ptr->flags == 0)
800 printf(_("[NO FLAGS] "));
801 if (ptr->flags & IFF_UP)
802 printf(_("UP "));
803 if (ptr->flags & IFF_BROADCAST)
804 printf(_("BROADCAST "));
805 if (ptr->flags & IFF_DEBUG)
806 printf(_("DEBUG "));
807 if (ptr->flags & IFF_LOOPBACK)
808 printf(_("LOOPBACK "));
809 if (ptr->flags & IFF_POINTOPOINT)
810 printf(_("POINTOPOINT "));
811 if (ptr->flags & IFF_NOTRAILERS)
812 printf(_("NOTRAILERS "));
813 if (ptr->flags & IFF_RUNNING)
814 printf(_("RUNNING "));
815 if (ptr->flags & IFF_NOARP)
816 printf(_("NOARP "));
817 if (ptr->flags & IFF_PROMISC)
818 printf(_("PROMISC "));
819 if (ptr->flags & IFF_ALLMULTI)
820 printf(_("ALLMULTI "));
821 if (ptr->flags & IFF_SLAVE)
822 printf(_("SLAVE "));
823 if (ptr->flags & IFF_MASTER)
824 printf(_("MASTER "));
825 if (ptr->flags & IFF_MULTICAST)
826 printf(_("MULTICAST "));
827 #ifdef HAVE_DYNAMIC
828 if (ptr->flags & IFF_DYNAMIC)
829 printf(_("DYNAMIC "));
830 #endif
831 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
832 printf(_(" MTU:%d Metric:%d"),
833 ptr->mtu, ptr->metric ? ptr->metric : 1);
834 #ifdef SIOCSKEEPALIVE
835 if (ptr->outfill || ptr->keepalive)
836 printf(_(" Outfill:%d Keepalive:%d"),
837 ptr->outfill, ptr->keepalive);
838 #endif
839 printf("\n");
841 /* If needed, display the interface statistics. */
843 if (ptr->statistics_valid) {
844 /* XXX: statistics are currently only printed for the primary address,
845 * not for the aliases, although strictly speaking they're shared
846 * by all addresses.
848 printf(" ");
850 printf(_("RX packets:%llu errors:%lu dropped:%lu overruns:%lu frame:%lu\n"),
851 ptr->stats.rx_packets, ptr->stats.rx_errors,
852 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
853 ptr->stats.rx_frame_errors);
854 if (can_compress)
855 printf(_(" compressed:%lu\n"), ptr->stats.rx_compressed);
857 rx = ptr->stats.rx_bytes;
858 tx = ptr->stats.tx_bytes;
859 short_rx = rx * 10;
860 short_tx = tx * 10;
861 if (rx > 1125899906842624ull) {
862 short_rx /= 1125899906842624ull;
863 Rext = "PiB";
864 } else if (rx > 1099511627776ull) {
865 short_rx /= 1099511627776ull;
866 Rext = "TiB";
867 } else if (rx > 1073741824ull) {
868 short_rx /= 1073741824ull;
869 Rext = "GiB";
870 } else if (rx > 1048576) {
871 short_rx /= 1048576;
872 Rext = "MiB";
873 } else if (rx > 1024) {
874 short_rx /= 1024;
875 Rext = "KiB";
877 if (tx > 1125899906842624ull) {
878 short_tx /= 1125899906842624ull;
879 Text = "PiB";
880 } else if (tx > 1099511627776ull) {
881 short_tx /= 1099511627776ull;
882 Text = "TiB";
883 } else if (tx > 1073741824ull) {
884 short_tx /= 1073741824ull;
885 Text = "GiB";
886 } else if (tx > 1048576) {
887 short_tx /= 1048576;
888 Text = "MiB";
889 } else if (tx > 1024) {
890 short_tx /= 1024;
891 Text = "KiB";
894 printf(" ");
895 printf(_("TX packets:%llu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n"),
896 ptr->stats.tx_packets, ptr->stats.tx_errors,
897 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
898 ptr->stats.tx_carrier_errors);
899 printf(_(" collisions:%lu "), ptr->stats.collisions);
900 if (can_compress)
901 printf(_("compressed:%lu "), ptr->stats.tx_compressed);
902 if (ptr->tx_queue_len != -1)
903 printf(_("txqueuelen:%d "), ptr->tx_queue_len);
904 printf("\n ");
905 printf(_("RX bytes:%llu (%lu.%lu %s) TX bytes:%llu (%lu.%lu %s)\n"),
906 rx, (unsigned long)(short_rx / 10),
907 (unsigned long)(short_rx % 10), Rext,
908 tx, (unsigned long)(short_tx / 10),
909 (unsigned long)(short_tx % 10), Text);
912 if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma ||
913 ptr->map.base_addr >= 0x100)) {
914 printf(" ");
915 if (ptr->map.irq)
916 printf(_("Interrupt:%d "), ptr->map.irq);
917 if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
918 I/O maps */
919 printf(_("Base address:0x%x "), ptr->map.base_addr);
920 if (ptr->map.mem_start) {
921 printf(_("Memory:%lx-%lx "), ptr->map.mem_start, ptr->map.mem_end);
923 if (ptr->map.dma)
924 printf(_("DMA chan:%x "), ptr->map.dma);
925 printf("\n");
927 printf("\n");
930 void ife_print(struct interface *i)
932 if (ife_short)
933 ife_print_short(i);
934 else
935 ife_print_long(i);