thanks to "Erik A. Hendriks" <hendriks@lanl.gov> the interface nane
[oss-qm-packages.git] / lib / interface.c
blobaa7e91cc841ab219303f45bd69e6c5aa3220f0d0
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.24 2002/06/14 01:33:50 ecki 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 *if_cache_add(char *name)
96 struct interface *ife, **nextp, *new;
98 if (!int_list)
99 int_last = NULL;
101 for (ife = int_last; ife; ife = ife->prev) {
102 int n = nstrcmp(ife->name, name);
103 if (n == 0)
104 return ife;
105 if (n < 0)
106 break;
108 new(new);
109 safe_strncpy(new->name, name, IFNAMSIZ);
110 nextp = ife ? &ife->next : &int_list;
111 new->prev = ife;
112 new->next = *nextp;
113 if (new->next)
114 new->next->prev = new;
115 else
116 int_last = new;
117 *nextp = new;
118 return new;
121 struct interface *lookup_interface(char *name)
123 struct interface *ife = NULL;
125 if (if_readlist_proc(name) < 0)
126 return NULL;
127 ife = if_cache_add(name);
128 return ife;
131 int for_all_interfaces(int (*doit) (struct interface *, void *), void *cookie)
133 struct interface *ife;
135 if (!int_list && (if_readlist() < 0))
136 return -1;
137 for (ife = int_list; ife; ife = ife->next) {
138 int err = doit(ife, cookie);
139 if (err)
140 return err;
142 return 0;
145 int if_cache_free(void)
147 struct interface *ife;
148 while ((ife = int_list) != NULL) {
149 int_list = ife->next;
150 free(ife);
152 int_last = NULL;
153 return 0;
156 static int if_readconf(void)
158 int numreqs = 30;
159 struct ifconf ifc;
160 struct ifreq *ifr;
161 int n, err = -1;
162 int skfd;
164 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
165 (as of 2.1.128) */
166 skfd = get_socket_for_af(AF_INET);
167 if (skfd < 0) {
168 fprintf(stderr, _("warning: no inet socket available: %s\n"),
169 strerror(errno));
170 /* Try to soldier on with whatever socket we can get hold of. */
171 skfd = sockets_open(0);
172 if (skfd < 0)
173 return -1;
176 ifc.ifc_buf = NULL;
177 for (;;) {
178 ifc.ifc_len = sizeof(struct ifreq) * numreqs;
179 ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
181 if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
182 perror("SIOCGIFCONF");
183 goto out;
185 if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
186 /* assume it overflowed and try again */
187 numreqs *= 2;
188 continue;
190 break;
193 ifr = ifc.ifc_req;
194 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
195 if_cache_add(ifr->ifr_name);
196 ifr++;
198 err = 0;
200 out:
201 free(ifc.ifc_buf);
202 return err;
205 char *get_name(char *name, char *p)
207 while (isspace(*p))
208 p++;
209 while (*p) {
210 if (isspace(*p))
211 break;
212 if (*p == ':') { /* could be an alias */
213 char *dot = p++;
214 while (*p && isdigit(*p)) p++;
215 if (*p == ':') {
216 /* Yes it is, backup and copy it. */
217 p = dot;
218 *name++ = *p++;
219 while (*p && isdigit(*p)) {
220 *name++ = *p++;
222 } else {
223 /* No, it isn't */
224 p = dot;
226 p++;
227 break;
229 *name++ = *p++;
231 *name++ = '\0';
232 return p;
235 int procnetdev_version(char *buf)
237 if (strstr(buf, "compressed"))
238 return 3;
239 if (strstr(buf, "bytes"))
240 return 2;
241 return 1;
244 int get_dev_fields(char *bp, struct interface *ife)
246 switch (procnetdev_vsn) {
247 case 3:
248 sscanf(bp,
249 "%Lu %Lu %lu %lu %lu %lu %lu %lu %Lu %Lu %lu %lu %lu %lu %lu %lu",
250 &ife->stats.rx_bytes,
251 &ife->stats.rx_packets,
252 &ife->stats.rx_errors,
253 &ife->stats.rx_dropped,
254 &ife->stats.rx_fifo_errors,
255 &ife->stats.rx_frame_errors,
256 &ife->stats.rx_compressed,
257 &ife->stats.rx_multicast,
259 &ife->stats.tx_bytes,
260 &ife->stats.tx_packets,
261 &ife->stats.tx_errors,
262 &ife->stats.tx_dropped,
263 &ife->stats.tx_fifo_errors,
264 &ife->stats.collisions,
265 &ife->stats.tx_carrier_errors,
266 &ife->stats.tx_compressed);
267 break;
268 case 2:
269 sscanf(bp, "%Lu %Lu %lu %lu %lu %lu %Lu %Lu %lu %lu %lu %lu %lu",
270 &ife->stats.rx_bytes,
271 &ife->stats.rx_packets,
272 &ife->stats.rx_errors,
273 &ife->stats.rx_dropped,
274 &ife->stats.rx_fifo_errors,
275 &ife->stats.rx_frame_errors,
277 &ife->stats.tx_bytes,
278 &ife->stats.tx_packets,
279 &ife->stats.tx_errors,
280 &ife->stats.tx_dropped,
281 &ife->stats.tx_fifo_errors,
282 &ife->stats.collisions,
283 &ife->stats.tx_carrier_errors);
284 ife->stats.rx_multicast = 0;
285 break;
286 case 1:
287 sscanf(bp, "%Lu %lu %lu %lu %lu %Lu %lu %lu %lu %lu %lu",
288 &ife->stats.rx_packets,
289 &ife->stats.rx_errors,
290 &ife->stats.rx_dropped,
291 &ife->stats.rx_fifo_errors,
292 &ife->stats.rx_frame_errors,
294 &ife->stats.tx_packets,
295 &ife->stats.tx_errors,
296 &ife->stats.tx_dropped,
297 &ife->stats.tx_fifo_errors,
298 &ife->stats.collisions,
299 &ife->stats.tx_carrier_errors);
300 ife->stats.rx_bytes = 0;
301 ife->stats.tx_bytes = 0;
302 ife->stats.rx_multicast = 0;
303 break;
305 return 0;
308 static int if_readlist_proc(char *target)
310 FILE *fh;
311 char buf[512];
312 struct interface *ife;
313 int err;
315 fh = fopen(_PATH_PROCNET_DEV, "r");
316 if (!fh) {
317 fprintf(stderr, _("Warning: cannot open %s (%s). Limited output.\n"),
318 _PATH_PROCNET_DEV, strerror(errno));
319 return if_readconf();
321 fgets(buf, sizeof buf, fh); /* eat line */
322 fgets(buf, sizeof buf, fh);
324 #if 0 /* pretty, but can't cope with missing fields */
325 fmt = proc_gen_fmt(_PATH_PROCNET_DEV, 1, fh,
326 "face", "", /* parsed separately */
327 "bytes", "%lu",
328 "packets", "%lu",
329 "errs", "%lu",
330 "drop", "%lu",
331 "fifo", "%lu",
332 "frame", "%lu",
333 "compressed", "%lu",
334 "multicast", "%lu",
335 "bytes", "%lu",
336 "packets", "%lu",
337 "errs", "%lu",
338 "drop", "%lu",
339 "fifo", "%lu",
340 "colls", "%lu",
341 "carrier", "%lu",
342 "compressed", "%lu",
343 NULL);
344 if (!fmt)
345 return -1;
346 #else
347 procnetdev_vsn = procnetdev_version(buf);
348 #endif
350 err = 0;
351 while (fgets(buf, sizeof buf, fh)) {
352 char *s, name[IFNAMSIZ];
353 s = get_name(name, buf);
354 ife = if_cache_add(name);
355 get_dev_fields(s, ife);
356 ife->statistics_valid = 1;
357 if (target && !strcmp(target,name))
358 break;
360 if (ferror(fh)) {
361 perror(_PATH_PROCNET_DEV);
362 err = -1;
365 #if 0
366 free(fmt);
367 #endif
368 fclose(fh);
369 return err;
372 int if_readlist(void)
374 /* caller will/should check not to call this too often
375 * (i.e. only if int_list!= NULL
377 int err = if_readlist_proc(NULL);
378 if (!err)
379 err = if_readconf();
380 return err;
383 /* Support for fetching an IPX address */
385 #if HAVE_AFIPX
386 static int ipx_getaddr(int sock, int ft, struct ifreq *ifr)
388 ((struct sockaddr_ipx *) &ifr->ifr_addr)->sipx_type = ft;
389 return ioctl(sock, SIOCGIFADDR, ifr);
391 #endif
393 /* Fetch the interface configuration from the kernel. */
394 int if_fetch(struct interface *ife)
396 struct ifreq ifr;
397 int fd;
398 char *ifname = ife->name;
400 strcpy(ifr.ifr_name, ifname);
401 if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
402 return (-1);
403 ife->flags = ifr.ifr_flags;
405 strcpy(ifr.ifr_name, ifname);
406 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
407 memset(ife->hwaddr, 0, 32);
408 else
409 memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
411 ife->type = ifr.ifr_hwaddr.sa_family;
413 strcpy(ifr.ifr_name, ifname);
414 if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
415 ife->metric = 0;
416 else
417 ife->metric = ifr.ifr_metric;
419 strcpy(ifr.ifr_name, ifname);
420 if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
421 ife->mtu = 0;
422 else
423 ife->mtu = ifr.ifr_mtu;
425 #ifdef HAVE_HWSLIP
426 if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
427 ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 ||
428 ife->type == ARPHRD_ADAPT) {
429 #ifdef SIOCGOUTFILL
430 strcpy(ifr.ifr_name, ifname);
431 if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0)
432 ife->outfill = 0;
433 else
434 ife->outfill = (unsigned int) ifr.ifr_data;
435 #endif
436 #ifdef SIOCGKEEPALIVE
437 strcpy(ifr.ifr_name, ifname);
438 if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0)
439 ife->keepalive = 0;
440 else
441 ife->keepalive = (unsigned int) ifr.ifr_data;
442 #endif
444 #endif
446 strcpy(ifr.ifr_name, ifname);
447 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
448 memset(&ife->map, 0, sizeof(struct ifmap));
449 else
450 memcpy(&ife->map, &ifr.ifr_map, sizeof(struct ifmap));
452 strcpy(ifr.ifr_name, ifname);
453 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
454 memset(&ife->map, 0, sizeof(struct ifmap));
455 else
456 ife->map = ifr.ifr_map;
458 #ifdef HAVE_TXQUEUELEN
459 strcpy(ifr.ifr_name, ifname);
460 if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
461 ife->tx_queue_len = -1; /* unknown value */
462 else
463 ife->tx_queue_len = ifr.ifr_qlen;
464 #else
465 ife->tx_queue_len = -1; /* unknown value */
466 #endif
468 #if HAVE_AFINET
469 /* IPv4 address? */
470 fd = get_socket_for_af(AF_INET);
471 if (fd >= 0) {
472 strcpy(ifr.ifr_name, ifname);
473 ifr.ifr_addr.sa_family = AF_INET;
474 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
475 ife->has_ip = 1;
476 ife->addr = ifr.ifr_addr;
477 strcpy(ifr.ifr_name, ifname);
478 if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
479 memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
480 else
481 ife->dstaddr = ifr.ifr_dstaddr;
483 strcpy(ifr.ifr_name, ifname);
484 if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
485 memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
486 else
487 ife->broadaddr = ifr.ifr_broadaddr;
489 strcpy(ifr.ifr_name, ifname);
490 if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
491 memset(&ife->netmask, 0, sizeof(struct sockaddr));
492 else
493 ife->netmask = ifr.ifr_netmask;
494 } else
495 memset(&ife->addr, 0, sizeof(struct sockaddr));
497 #endif
499 #if HAVE_AFATALK
500 /* DDP address maybe ? */
501 fd = get_socket_for_af(AF_APPLETALK);
502 if (fd >= 0) {
503 strcpy(ifr.ifr_name, ifname);
504 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
505 ife->ddpaddr = ifr.ifr_addr;
506 ife->has_ddp = 1;
509 #endif
511 #if HAVE_AFIPX
512 /* Look for IPX addresses with all framing types */
513 fd = get_socket_for_af(AF_IPX);
514 if (fd >= 0) {
515 strcpy(ifr.ifr_name, ifname);
516 if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) {
517 ife->has_ipx_bb = 1;
518 ife->ipxaddr_bb = ifr.ifr_addr;
520 strcpy(ifr.ifr_name, ifname);
521 if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) {
522 ife->has_ipx_sn = 1;
523 ife->ipxaddr_sn = ifr.ifr_addr;
525 strcpy(ifr.ifr_name, ifname);
526 if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) {
527 ife->has_ipx_e3 = 1;
528 ife->ipxaddr_e3 = ifr.ifr_addr;
530 strcpy(ifr.ifr_name, ifname);
531 if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) {
532 ife->has_ipx_e2 = 1;
533 ife->ipxaddr_e2 = ifr.ifr_addr;
536 #endif
538 #if HAVE_AFECONET
539 /* Econet address maybe? */
540 fd = get_socket_for_af(AF_ECONET);
541 if (fd >= 0) {
542 strcpy(ifr.ifr_name, ifname);
543 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
544 ife->ecaddr = ifr.ifr_addr;
545 ife->has_econet = 1;
548 #endif
550 return 0;
553 int do_if_fetch(struct interface *ife)
555 if (if_fetch(ife) < 0) {
556 char *errmsg;
557 if (errno == ENODEV) {
558 /* Give better error message for this case. */
559 errmsg = _("Device not found");
560 } else {
561 errmsg = strerror(errno);
563 fprintf(stderr, _("%s: error fetching interface information: %s\n"),
564 ife->name, errmsg);
565 return -1;
567 return 0;
570 int do_if_print(struct interface *ife, void *cookie)
572 int *opt_a = (int *) cookie;
573 int res;
575 res = do_if_fetch(ife);
576 if (res >= 0) {
577 if ((ife->flags & IFF_UP) || *opt_a)
578 ife_print(ife);
580 return res;
583 void ife_print_short(struct interface *ptr)
585 printf("%-5.5s ", ptr->name);
586 printf("%5d %-2d", ptr->mtu, ptr->metric);
587 /* If needed, display the interface statistics. */
588 if (ptr->statistics_valid) {
589 printf("%9llu %6lu %6lu %-5lu",
590 ptr->stats.rx_packets, ptr->stats.rx_errors,
591 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors);
592 printf("%9llu %6lu %6lu %6lu ",
593 ptr->stats.tx_packets, ptr->stats.tx_errors,
594 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors);
595 } else {
596 printf("%-56s", _(" - no statistics available -"));
598 /* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
599 if (ptr->flags == 0)
600 printf(_("[NO FLAGS]"));
601 if (ptr->flags & IFF_ALLMULTI)
602 printf("A");
603 if (ptr->flags & IFF_BROADCAST)
604 printf("B");
605 if (ptr->flags & IFF_DEBUG)
606 printf("D");
607 if (ptr->flags & IFF_LOOPBACK)
608 printf("L");
609 if (ptr->flags & IFF_MULTICAST)
610 printf("M");
611 #ifdef HAVE_DYNAMIC
612 if (ptr->flags & IFF_DYNAMIC)
613 printf("d");
614 #endif
615 if (ptr->flags & IFF_PROMISC)
616 printf("P");
617 if (ptr->flags & IFF_NOTRAILERS)
618 printf("N");
619 if (ptr->flags & IFF_NOARP)
620 printf("O");
621 if (ptr->flags & IFF_POINTOPOINT)
622 printf("P");
623 if (ptr->flags & IFF_SLAVE)
624 printf("s");
625 if (ptr->flags & IFF_MASTER)
626 printf("m");
627 if (ptr->flags & IFF_RUNNING)
628 printf("R");
629 if (ptr->flags & IFF_UP)
630 printf("U");
631 /* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
632 printf("\n");
635 void ife_print_long(struct interface *ptr)
637 struct aftype *ap;
638 struct hwtype *hw;
639 int hf;
640 int can_compress = 0;
641 unsigned long long rx, tx, short_rx, short_tx;
642 const char *Rext = "b";
643 const char *Text = "b";
645 #if HAVE_AFIPX
646 static struct aftype *ipxtype = NULL;
647 #endif
648 #if HAVE_AFECONET
649 static struct aftype *ectype = NULL;
650 #endif
651 #if HAVE_AFATALK
652 static struct aftype *ddptype = NULL;
653 #endif
654 #if HAVE_AFINET6
655 FILE *f;
656 char addr6[40], devname[20];
657 struct sockaddr_in6 sap;
658 int plen, scope, dad_status, if_idx;
659 extern struct aftype inet6_aftype;
660 char addr6p[8][5];
661 #endif
663 ap = get_afntype(ptr->addr.sa_family);
664 if (ap == NULL)
665 ap = get_afntype(0);
667 hf = ptr->type;
669 if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)
670 can_compress = 1;
672 hw = get_hwntype(hf);
673 if (hw == NULL)
674 hw = get_hwntype(-1);
676 printf(_("%-9.9s Link encap:%s "), ptr->name, hw->title);
677 /* For some hardware types (eg Ash, ATM) we don't print the
678 hardware address if it's null. */
679 if (hw->print != NULL && (! (hw_null_address(hw, ptr->hwaddr) &&
680 hw->suppress_null_addr)))
681 printf(_("HWaddr %s "), hw->print(ptr->hwaddr));
682 #ifdef IFF_PORTSEL
683 if (ptr->flags & IFF_PORTSEL) {
684 printf(_("Media:%s"), if_port_text[ptr->map.port][0]);
685 if (ptr->flags & IFF_AUTOMEDIA)
686 printf(_("(auto)"));
688 #endif
689 printf("\n");
691 #if HAVE_AFINET
692 if (ptr->has_ip) {
693 printf(_(" %s addr:%s "), ap->name,
694 ap->sprint(&ptr->addr, 1));
695 if (ptr->flags & IFF_POINTOPOINT) {
696 printf(_(" P-t-P:%s "), ap->sprint(&ptr->dstaddr, 1));
698 if (ptr->flags & IFF_BROADCAST) {
699 printf(_(" Bcast:%s "), ap->sprint(&ptr->broadaddr, 1));
701 printf(_(" Mask:%s\n"), ap->sprint(&ptr->netmask, 1));
703 #endif
705 #if HAVE_AFINET6
706 /* FIXME: should be integrated into interface.c. */
708 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
709 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
710 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
711 addr6p[4], addr6p[5], addr6p[6], addr6p[7],
712 &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
713 if (!strcmp(devname, ptr->name)) {
714 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
715 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
716 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
717 inet6_aftype.input(1, addr6, (struct sockaddr *) &sap);
718 printf(_(" inet6 addr: %s/%d"),
719 inet6_aftype.sprint((struct sockaddr *) &sap, 1), plen);
720 printf(_(" Scope:"));
721 switch (scope) {
722 case 0:
723 printf(_("Global"));
724 break;
725 case IPV6_ADDR_LINKLOCAL:
726 printf(_("Link"));
727 break;
728 case IPV6_ADDR_SITELOCAL:
729 printf(_("Site"));
730 break;
731 case IPV6_ADDR_COMPATv4:
732 printf(_("Compat"));
733 break;
734 case IPV6_ADDR_LOOPBACK:
735 printf(_("Host"));
736 break;
737 default:
738 printf(_("Unknown"));
740 printf("\n");
743 fclose(f);
745 #endif
747 #if HAVE_AFIPX
748 if (ipxtype == NULL)
749 ipxtype = get_afntype(AF_IPX);
751 if (ipxtype != NULL) {
752 if (ptr->has_ipx_bb)
753 printf(_(" IPX/Ethernet II addr:%s\n"),
754 ipxtype->sprint(&ptr->ipxaddr_bb, 1));
755 if (ptr->has_ipx_sn)
756 printf(_(" IPX/Ethernet SNAP addr:%s\n"),
757 ipxtype->sprint(&ptr->ipxaddr_sn, 1));
758 if (ptr->has_ipx_e2)
759 printf(_(" IPX/Ethernet 802.2 addr:%s\n"),
760 ipxtype->sprint(&ptr->ipxaddr_e2, 1));
761 if (ptr->has_ipx_e3)
762 printf(_(" IPX/Ethernet 802.3 addr:%s\n"),
763 ipxtype->sprint(&ptr->ipxaddr_e3, 1));
765 #endif
767 #if HAVE_AFATALK
768 if (ddptype == NULL)
769 ddptype = get_afntype(AF_APPLETALK);
770 if (ddptype != NULL) {
771 if (ptr->has_ddp)
772 printf(_(" EtherTalk Phase 2 addr:%s\n"), ddptype->sprint(&ptr->ddpaddr, 1));
774 #endif
776 #if HAVE_AFECONET
777 if (ectype == NULL)
778 ectype = get_afntype(AF_ECONET);
779 if (ectype != NULL) {
780 if (ptr->has_econet)
781 printf(_(" econet addr:%s\n"), ectype->sprint(&ptr->ecaddr, 1));
783 #endif
785 printf(" ");
786 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
787 if (ptr->flags == 0)
788 printf(_("[NO FLAGS] "));
789 if (ptr->flags & IFF_UP)
790 printf(_("UP "));
791 if (ptr->flags & IFF_BROADCAST)
792 printf(_("BROADCAST "));
793 if (ptr->flags & IFF_DEBUG)
794 printf(_("DEBUG "));
795 if (ptr->flags & IFF_LOOPBACK)
796 printf(_("LOOPBACK "));
797 if (ptr->flags & IFF_POINTOPOINT)
798 printf(_("POINTOPOINT "));
799 if (ptr->flags & IFF_NOTRAILERS)
800 printf(_("NOTRAILERS "));
801 if (ptr->flags & IFF_RUNNING)
802 printf(_("RUNNING "));
803 if (ptr->flags & IFF_NOARP)
804 printf(_("NOARP "));
805 if (ptr->flags & IFF_PROMISC)
806 printf(_("PROMISC "));
807 if (ptr->flags & IFF_ALLMULTI)
808 printf(_("ALLMULTI "));
809 if (ptr->flags & IFF_SLAVE)
810 printf(_("SLAVE "));
811 if (ptr->flags & IFF_MASTER)
812 printf(_("MASTER "));
813 if (ptr->flags & IFF_MULTICAST)
814 printf(_("MULTICAST "));
815 #ifdef HAVE_DYNAMIC
816 if (ptr->flags & IFF_DYNAMIC)
817 printf(_("DYNAMIC "));
818 #endif
819 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
820 printf(_(" MTU:%d Metric:%d"),
821 ptr->mtu, ptr->metric ? ptr->metric : 1);
822 #ifdef SIOCSKEEPALIVE
823 if (ptr->outfill || ptr->keepalive)
824 printf(_(" Outfill:%d Keepalive:%d"),
825 ptr->outfill, ptr->keepalive);
826 #endif
827 printf("\n");
829 /* If needed, display the interface statistics. */
831 if (ptr->statistics_valid) {
832 /* XXX: statistics are currently only printed for the primary address,
833 * not for the aliases, although strictly speaking they're shared
834 * by all addresses.
836 printf(" ");
838 printf(_("RX packets:%llu errors:%lu dropped:%lu overruns:%lu frame:%lu\n"),
839 ptr->stats.rx_packets, ptr->stats.rx_errors,
840 ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
841 ptr->stats.rx_frame_errors);
842 if (can_compress)
843 printf(_(" compressed:%lu\n"), ptr->stats.rx_compressed);
845 rx = ptr->stats.rx_bytes;
846 tx = ptr->stats.tx_bytes;
847 short_rx = rx * 10;
848 short_tx = tx * 10;
849 if (rx > 1125899906842624) {
850 short_rx /= 1125899906842624;
851 Rext = "PiB";
852 } else if (rx > 1099511627776) {
853 short_rx /= 1099511627776;
854 Rext = "TiB";
855 } else if (rx > 1073741824) {
856 short_rx /= 1073741824;
857 Rext = "GiB";
858 } else if (rx > 1048576) {
859 short_rx /= 1048576;
860 Rext = "MiB";
861 } else if (rx > 1024) {
862 short_rx /= 1024;
863 Rext = "KiB";
865 if (tx > 1125899906842624) {
866 short_tx /= 1125899906842624;
867 Text = "PiB";
868 } else if (tx > 1099511627776) {
869 short_tx /= 1099511627776;
870 Text = "TiB";
871 } else if (tx > 1073741824) {
872 short_tx /= 1073741824;
873 Text = "GiB";
874 } else if (tx > 1048576) {
875 short_tx /= 1048576;
876 Text = "MiB";
877 } else if (tx > 1024) {
878 short_tx /= 1024;
879 Text = "KiB";
882 printf(" ");
883 printf(_("TX packets:%llu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n"),
884 ptr->stats.tx_packets, ptr->stats.tx_errors,
885 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
886 ptr->stats.tx_carrier_errors);
887 printf(_(" collisions:%lu "), ptr->stats.collisions);
888 if (can_compress)
889 printf(_("compressed:%lu "), ptr->stats.tx_compressed);
890 if (ptr->tx_queue_len != -1)
891 printf(_("txqueuelen:%d "), ptr->tx_queue_len);
892 printf("\n ");
893 printf(_("RX bytes:%llu (%lu.%lu %s) TX bytes:%llu (%lu.%lu %s)\n"),
894 rx, (unsigned long)(short_rx / 10),
895 (unsigned long)(short_rx % 10), Rext,
896 tx, (unsigned long)(short_tx / 10),
897 (unsigned long)(short_tx % 10), Text);
900 if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma ||
901 ptr->map.base_addr >= 0x100)) {
902 printf(" ");
903 if (ptr->map.irq)
904 printf(_("Interrupt:%d "), ptr->map.irq);
905 if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
906 I/O maps */
907 printf(_("Base address:0x%x "), ptr->map.base_addr);
908 if (ptr->map.mem_start) {
909 printf(_("Memory:%lx-%lx "), ptr->map.mem_start, ptr->map.mem_end);
911 if (ptr->map.dma)
912 printf(_("DMA chan:%x "), ptr->map.dma);
913 printf("\n");
915 printf("\n");
918 void ife_print(struct interface *i)
920 if (ife_short)
921 ife_print_short(i);
922 else
923 ife_print_long(i);