1 /* Code to manipulate interface information, shared between ifconfig and
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.31 2009/07/08 00:24:03 ecki Exp $
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/ioctl.h>
18 #include <netinet/in.h>
29 #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
30 #include <netipx/ipx.h>
37 #include <neteconet/ec.h>
41 #include <linux/if_slip.h>
42 #include <net/if_arp.h>
45 #include "net-support.h"
46 #include "pathnames.h"
50 #include "interface.h"
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},
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;
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;
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);
113 safe_strncpy(new->name, name, IFNAMSIZ);
114 nextp = ife ? &ife->next : &int_list; // keep sorting
118 new->next->prev = new;
125 struct interface *lookup_interface(char *name)
127 /* if we have read all, use it */
129 return if_cache_add(name);
131 /* otherwise we read a limited list */
132 if (if_readlist_proc(name) < 0)
135 return if_cache_add(name);
138 int for_all_interfaces(int (*doit) (struct interface *, void *), void *cookie)
140 struct interface *ife;
142 if (!if_list_all && (if_readlist() < 0))
144 for (ife = int_list; ife; ife = ife->next) {
145 int err = doit(ife, cookie);
152 int if_cache_free(void)
154 struct interface *ife;
155 while ((ife = int_list) != NULL) {
156 int_list = ife->next;
164 static int if_readconf(void)
172 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
174 skfd = get_socket_for_af(AF_INET);
176 fprintf(stderr, _("warning: no inet socket available: %s\n"),
178 /* Try to soldier on with whatever socket we can get hold of. */
179 skfd = sockets_open(0);
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");
193 if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
194 /* assume it overflowed and try again */
202 for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
203 if_cache_add(ifr->ifr_name);
213 char *get_name(char *name, char *p)
220 if (*p == ':') { /* could be an alias */
222 while (*p && isdigit(*p)) p++;
224 /* Yes it is, backup and copy it. */
227 while (*p && isdigit(*p)) {
243 int procnetdev_version(char *buf)
245 if (strstr(buf, "compressed"))
247 if (strstr(buf, "bytes"))
252 int get_dev_fields(char *bp, struct interface *ife)
254 switch (procnetdev_vsn) {
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);
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;
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;
316 static int if_readlist_proc(char *target)
320 struct interface *ife;
323 fh = fopen(_PATH_PROCNET_DEV, "r");
325 fprintf(stderr, _("Warning: cannot open %s (%s). Limited output.\n"),
326 _PATH_PROCNET_DEV, strerror(errno));
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 */
355 procnetdev_vsn = procnetdev_version(buf);
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))
369 perror(_PATH_PROCNET_DEV);
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
387 err |= if_readlist_proc(NULL);
388 err |= if_readconf();
395 /* Support for fetching an IPX address */
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);
405 /* Fetch the interface configuration from the kernel. */
406 int if_fetch(struct interface *ife)
410 char *ifname = ife->name;
412 strcpy(ifr.ifr_name, ifname);
413 if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
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);
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)
429 ife->metric = ifr.ifr_metric;
431 strcpy(ifr.ifr_name, ifname);
432 if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
435 ife->mtu = ifr.ifr_mtu;
438 if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
439 ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 ||
440 ife->type == ARPHRD_ADAPT) {
442 strcpy(ifr.ifr_name, ifname);
443 if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0)
446 ife->outfill = (unsigned int) ifr.ifr_data;
448 #ifdef SIOCGKEEPALIVE
449 strcpy(ifr.ifr_name, ifname);
450 if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0)
453 ife->keepalive = (unsigned int) ifr.ifr_data;
458 strcpy(ifr.ifr_name, ifname);
459 if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
460 memset(&ife->map, 0, sizeof(struct ifmap));
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));
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 */
475 ife->tx_queue_len = ifr.ifr_qlen;
477 ife->tx_queue_len = -1; /* unknown value */
482 fd = get_socket_for_af(AF_INET);
484 strcpy(ifr.ifr_name, ifname);
485 ifr.ifr_addr.sa_family = AF_INET;
486 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
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));
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));
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));
505 ife->netmask = ifr.ifr_netmask;
507 memset(&ife->addr, 0, sizeof(struct sockaddr));
512 /* DDP address maybe ? */
513 fd = get_socket_for_af(AF_APPLETALK);
515 strcpy(ifr.ifr_name, ifname);
516 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
517 ife->ddpaddr = ifr.ifr_addr;
524 /* Look for IPX addresses with all framing types */
525 fd = get_socket_for_af(AF_IPX);
527 strcpy(ifr.ifr_name, ifname);
528 if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) {
530 ife->ipxaddr_bb = ifr.ifr_addr;
532 strcpy(ifr.ifr_name, ifname);
533 if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) {
535 ife->ipxaddr_sn = ifr.ifr_addr;
537 strcpy(ifr.ifr_name, ifname);
538 if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) {
540 ife->ipxaddr_e3 = ifr.ifr_addr;
542 strcpy(ifr.ifr_name, ifname);
543 if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) {
545 ife->ipxaddr_e2 = ifr.ifr_addr;
551 /* Econet address maybe? */
552 fd = get_socket_for_af(AF_ECONET);
554 strcpy(ifr.ifr_name, ifname);
555 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
556 ife->ecaddr = ifr.ifr_addr;
565 int do_if_fetch(struct interface *ife)
567 if (if_fetch(ife) < 0) {
569 if (errno == ENODEV) {
570 /* Give better error message for this case. */
571 errmsg = _("Device not found");
573 errmsg = strerror(errno);
575 fprintf(stderr, _("%s: error fetching interface information: %s\n"),
582 int do_if_print(struct interface *ife, void *cookie)
584 int *opt_a = (int *) cookie;
587 res = do_if_fetch(ife);
589 if ((ife->flags & IFF_UP) || *opt_a)
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);
608 printf("%-56s", _(" - no statistics available -"));
610 /* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
612 printf(_("[NO FLAGS]"));
613 if (ptr->flags & IFF_ALLMULTI)
615 if (ptr->flags & IFF_BROADCAST)
617 if (ptr->flags & IFF_DEBUG)
619 if (ptr->flags & IFF_LOOPBACK)
621 if (ptr->flags & IFF_MULTICAST)
624 if (ptr->flags & IFF_DYNAMIC)
627 if (ptr->flags & IFF_PROMISC)
629 if (ptr->flags & IFF_NOTRAILERS)
631 if (ptr->flags & IFF_NOARP)
633 if (ptr->flags & IFF_POINTOPOINT)
635 if (ptr->flags & IFF_SLAVE)
637 if (ptr->flags & IFF_MASTER)
639 if (ptr->flags & IFF_RUNNING)
641 if (ptr->flags & IFF_UP)
643 /* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
647 void ife_print_long(struct interface *ptr)
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";
656 static char flags[200];
659 static struct aftype *ipxtype = NULL;
662 static struct aftype *ectype = NULL;
665 static struct aftype *ddptype = NULL;
669 char addr6[40], devname[21];
670 struct sockaddr_in6 sap;
671 int plen, scope, dad_status, if_idx;
672 extern struct aftype inet6_aftype;
676 ap = get_afntype(ptr->addr.sa_family);
682 if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)
685 hw = get_hwntype(hf);
687 hw = get_hwntype(-1);
689 sprintf(flags, "flags=%d<", ptr->flags);
690 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
693 if (ptr->flags & IFF_UP)
694 strcat(flags,_("UP,"));
695 if (ptr->flags & IFF_BROADCAST)
696 strcat(flags,_("BROADCAST,"));
697 if (ptr->flags & IFF_DEBUG)
698 strcat(flags,_("DEBUG,"));
699 if (ptr->flags & IFF_LOOPBACK)
700 strcat(flags,_("LOOPBACK,"));
701 if (ptr->flags & IFF_POINTOPOINT)
702 strcat(flags,_("POINTOPOINT,"));
703 if (ptr->flags & IFF_NOTRAILERS)
704 strcat(flags,_("NOTRAILERS,"));
705 if (ptr->flags & IFF_RUNNING)
706 strcat(flags,_("RUNNING,"));
707 if (ptr->flags & IFF_NOARP)
708 strcat(flags,_("NOARP,"));
709 if (ptr->flags & IFF_PROMISC)
710 strcat(flags,_("PROMISC,"));
711 if (ptr->flags & IFF_ALLMULTI)
712 strcat(flags,_("ALLMULTI,"));
713 if (ptr->flags & IFF_SLAVE)
714 strcat(flags,_("SLAVE,"));
715 if (ptr->flags & IFF_MASTER)
716 strcat(flags,_("MASTER,"));
717 if (ptr->flags & IFF_MULTICAST)
718 strcat(flags,_("MULTICAST,"));
720 if (ptr->flags & IFF_DYNAMIC)
721 strcat(flags,_("DYNAMIC,"));
723 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
724 if (flags[strlen(flags)-1] == ',')
725 flags[strlen(flags)-1] = '>';
727 flags[strlen(flags)-1] = 0;
730 printf(_("%s: %s mtu %d metric %d"),
731 ptr->name, flags, ptr->mtu, ptr->metric ? ptr->metric : 1);
732 #ifdef SIOCSKEEPALIVE
733 if (ptr->outfill || ptr->keepalive)
734 printf(_(" outfill %d keepalive %d"),
735 ptr->outfill, ptr->keepalive);
743 printf(_(" %s %s"), ap->name,
744 ap->sprint(&ptr->addr, 1));
745 printf(_(" netmask %s"), ap->sprint(&ptr->netmask, 1));
746 if (ptr->flags & IFF_BROADCAST) {
747 printf(_(" broadcast %s"), ap->sprint(&ptr->broadaddr, 1));
749 if (ptr->flags & IFF_POINTOPOINT) {
750 printf(_(" destination %s"), ap->sprint(&ptr->dstaddr, 1));
757 /* FIXME: should be integrated into interface.c. */
759 if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
760 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
761 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
762 addr6p[4], addr6p[5], addr6p[6], addr6p[7],
763 &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
764 if (!strcmp(devname, ptr->name)) {
765 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
766 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
767 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
768 inet6_aftype.input(1, addr6, (struct sockaddr *) &sap);
769 printf(_(" %s %s prefixlen %d"),
771 inet6_aftype.sprint((struct sockaddr *) &sap, 1),
773 printf(_(" scopeid 0x%x"), scope);
775 flags[0] = '<'; flags[1] = 0;
776 if (scope & IPV6_ADDR_COMPATv4) {
777 strcat(flags, _("compat,"));
778 scope -= IPV6_ADDR_COMPATv4;
781 strcat(flags, _("global,"));
782 if (scope & IPV6_ADDR_LINKLOCAL)
783 strcat(flags, _("link,"));
784 if (scope & IPV6_ADDR_SITELOCAL)
785 strcat(flags, _("site,"));
786 if (scope & IPV6_ADDR_LOOPBACK)
787 strcat(flags, _("host,"));
788 if (flags[strlen(flags)-1] == ',')
789 flags[strlen(flags)-1] = '>';
791 flags[strlen(flags)-1] = 0;
792 printf("%s\n", flags);
801 ipxtype = get_afntype(AF_IPX);
803 if (ipxtype != NULL) {
805 printf(_(" %s Ethernet-II %s\n"),
806 ipxtype->name, ipxtype->sprint(&ptr->ipxaddr_bb, 1));
808 printf(_(" %s Ethernet-SNAP %s\n"),
809 ipxtype->name, ipxtype->sprint(&ptr->ipxaddr_sn, 1));
811 printf(_(" %s Ethernet802.2 %s\n"),
812 ipxtype->name, ipxtype->sprint(&ptr->ipxaddr_e2, 1));
814 printf(_(" %s Ethernet802.3 %s\n"),
815 ipxtype->name, ipxtype->sprint(&ptr->ipxaddr_e3, 1));
821 ddptype = get_afntype(AF_APPLETALK);
822 if (ddptype != NULL) {
824 printf(_(" %s %s\n"), ddptype->name, ddptype->sprint(&ptr->ddpaddr, 1));
830 ectype = get_afntype(AF_ECONET);
831 if (ectype != NULL) {
833 printf(_(" %s %s\n"), ectype->name, ectype->sprint(&ptr->ecaddr, 1));
837 /* For some hardware types (eg Ash, ATM) we don't print the
838 hardware address if it's null. */
839 if (hw->print != NULL && (! (hw_null_address(hw, ptr->hwaddr) &&
840 hw->suppress_null_addr)))
841 printf(_(" %s %s"), hw->name, hw->print(ptr->hwaddr));
843 printf(_(" %s"), hw->name);
844 if (ptr->tx_queue_len != -1)
845 printf(_(" txqueuelen %d"), ptr->tx_queue_len);
846 printf(" (%s)\n", hw->title);
849 if (ptr->flags & IFF_PORTSEL) {
850 printf(_(" media %s"), if_port_text[ptr->map.port][0]);
851 if (ptr->flags & IFF_AUTOMEDIA)
852 printf(_("autoselect"));
858 /* If needed, display the interface statistics. */
860 if (ptr->statistics_valid) {
861 /* XXX: statistics are currently only printed for the primary address,
862 * not for the aliases, although strictly speaking they're shared
865 rx = ptr->stats.rx_bytes;
867 if (rx > 1125899906842624ull) {
868 short_rx /= 1125899906842624ull;
870 } else if (rx > 1099511627776ull) {
871 short_rx /= 1099511627776ull;
873 } else if (rx > 1073741824ull) {
874 short_rx /= 1073741824ull;
876 } else if (rx > 1048576) {
879 } else if (rx > 1024) {
883 tx = ptr->stats.tx_bytes;
885 if (tx > 1125899906842624ull) {
886 short_tx /= 1125899906842624ull;
888 } else if (tx > 1099511627776ull) {
889 short_tx /= 1099511627776ull;
891 } else if (tx > 1073741824ull) {
892 short_tx /= 1073741824ull;
894 } else if (tx > 1048576) {
897 } else if (tx > 1024) {
903 printf(_("RX packets %llu bytes %llu (%lu.%lu %s)\n"),
904 ptr->stats.rx_packets,
905 rx, (unsigned long)(short_rx / 10),
906 (unsigned long)(short_rx % 10), Rext);
909 printf(_("RX compressed:%lu\n"), ptr->stats.rx_compressed);
912 printf(_("RX errors %lu dropped %lu overruns %lu frame %lu\n"),
913 ptr->stats.rx_errors, ptr->stats.rx_dropped,
914 ptr->stats.rx_fifo_errors, ptr->stats.rx_frame_errors);
918 printf(_("TX packets %llu bytes %llu (%lu.%lu %s)\n"),
919 ptr->stats.tx_packets,
920 tx, (unsigned long)(short_tx / 10),
921 (unsigned long)(short_tx % 10), Text);
924 printf(_("TX compressed %lu\n"), ptr->stats.tx_compressed);
927 printf(_("TX errors %lu dropped %lu overruns %lu carrier %lu collisions %lu\n"),
928 ptr->stats.tx_errors,
929 ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
930 ptr->stats.tx_carrier_errors, ptr->stats.collisions);
933 if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma ||
934 ptr->map.base_addr >= 0x100)) {
937 printf(_("interrupt %d "), ptr->map.irq);
938 if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
940 printf(_("base 0x%x "), ptr->map.base_addr);
941 if (ptr->map.mem_start) {
942 printf(_("memory 0x%lx-%lx "), ptr->map.mem_start, ptr->map.mem_end);
945 printf(_(" dma 0x%x"), ptr->map.dma);
951 void ife_print(struct interface *i)