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.28 2003/05/29 02:09:14 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
385 int err
= if_readlist_proc(NULL
);
396 /* Support for fetching an IPX address */
399 static int ipx_getaddr(int sock
, int ft
, struct ifreq
*ifr
)
401 ((struct sockaddr_ipx
*) &ifr
->ifr_addr
)->sipx_type
= ft
;
402 return ioctl(sock
, SIOCGIFADDR
, ifr
);
406 /* Fetch the interface configuration from the kernel. */
407 int if_fetch(struct interface
*ife
)
411 char *ifname
= ife
->name
;
413 strcpy(ifr
.ifr_name
, ifname
);
414 if (ioctl(skfd
, SIOCGIFFLAGS
, &ifr
) < 0)
416 ife
->flags
= ifr
.ifr_flags
;
418 strcpy(ifr
.ifr_name
, ifname
);
419 if (ioctl(skfd
, SIOCGIFHWADDR
, &ifr
) < 0)
420 memset(ife
->hwaddr
, 0, 32);
422 memcpy(ife
->hwaddr
, ifr
.ifr_hwaddr
.sa_data
, 8);
424 ife
->type
= ifr
.ifr_hwaddr
.sa_family
;
426 strcpy(ifr
.ifr_name
, ifname
);
427 if (ioctl(skfd
, SIOCGIFMETRIC
, &ifr
) < 0)
430 ife
->metric
= ifr
.ifr_metric
;
432 strcpy(ifr
.ifr_name
, ifname
);
433 if (ioctl(skfd
, SIOCGIFMTU
, &ifr
) < 0)
436 ife
->mtu
= ifr
.ifr_mtu
;
439 if (ife
->type
== ARPHRD_SLIP
|| ife
->type
== ARPHRD_CSLIP
||
440 ife
->type
== ARPHRD_SLIP6
|| ife
->type
== ARPHRD_CSLIP6
||
441 ife
->type
== ARPHRD_ADAPT
) {
443 strcpy(ifr
.ifr_name
, ifname
);
444 if (ioctl(skfd
, SIOCGOUTFILL
, &ifr
) < 0)
447 ife
->outfill
= (unsigned int) ifr
.ifr_data
;
449 #ifdef SIOCGKEEPALIVE
450 strcpy(ifr
.ifr_name
, ifname
);
451 if (ioctl(skfd
, SIOCGKEEPALIVE
, &ifr
) < 0)
454 ife
->keepalive
= (unsigned int) ifr
.ifr_data
;
459 strcpy(ifr
.ifr_name
, ifname
);
460 if (ioctl(skfd
, SIOCGIFMAP
, &ifr
) < 0)
461 memset(&ife
->map
, 0, sizeof(struct ifmap
));
463 memcpy(&ife
->map
, &ifr
.ifr_map
, sizeof(struct ifmap
));
465 strcpy(ifr
.ifr_name
, ifname
);
466 if (ioctl(skfd
, SIOCGIFMAP
, &ifr
) < 0)
467 memset(&ife
->map
, 0, sizeof(struct ifmap
));
469 ife
->map
= ifr
.ifr_map
;
471 #ifdef HAVE_TXQUEUELEN
472 strcpy(ifr
.ifr_name
, ifname
);
473 if (ioctl(skfd
, SIOCGIFTXQLEN
, &ifr
) < 0)
474 ife
->tx_queue_len
= -1; /* unknown value */
476 ife
->tx_queue_len
= ifr
.ifr_qlen
;
478 ife
->tx_queue_len
= -1; /* unknown value */
483 fd
= get_socket_for_af(AF_INET
);
485 strcpy(ifr
.ifr_name
, ifname
);
486 ifr
.ifr_addr
.sa_family
= AF_INET
;
487 if (ioctl(fd
, SIOCGIFADDR
, &ifr
) == 0) {
489 ife
->addr
= ifr
.ifr_addr
;
490 strcpy(ifr
.ifr_name
, ifname
);
491 if (ioctl(fd
, SIOCGIFDSTADDR
, &ifr
) < 0)
492 memset(&ife
->dstaddr
, 0, sizeof(struct sockaddr
));
494 ife
->dstaddr
= ifr
.ifr_dstaddr
;
496 strcpy(ifr
.ifr_name
, ifname
);
497 if (ioctl(fd
, SIOCGIFBRDADDR
, &ifr
) < 0)
498 memset(&ife
->broadaddr
, 0, sizeof(struct sockaddr
));
500 ife
->broadaddr
= ifr
.ifr_broadaddr
;
502 strcpy(ifr
.ifr_name
, ifname
);
503 if (ioctl(fd
, SIOCGIFNETMASK
, &ifr
) < 0)
504 memset(&ife
->netmask
, 0, sizeof(struct sockaddr
));
506 ife
->netmask
= ifr
.ifr_netmask
;
508 memset(&ife
->addr
, 0, sizeof(struct sockaddr
));
513 /* DDP address maybe ? */
514 fd
= get_socket_for_af(AF_APPLETALK
);
516 strcpy(ifr
.ifr_name
, ifname
);
517 if (ioctl(fd
, SIOCGIFADDR
, &ifr
) == 0) {
518 ife
->ddpaddr
= ifr
.ifr_addr
;
525 /* Look for IPX addresses with all framing types */
526 fd
= get_socket_for_af(AF_IPX
);
528 strcpy(ifr
.ifr_name
, ifname
);
529 if (!ipx_getaddr(fd
, IPX_FRAME_ETHERII
, &ifr
)) {
531 ife
->ipxaddr_bb
= ifr
.ifr_addr
;
533 strcpy(ifr
.ifr_name
, ifname
);
534 if (!ipx_getaddr(fd
, IPX_FRAME_SNAP
, &ifr
)) {
536 ife
->ipxaddr_sn
= ifr
.ifr_addr
;
538 strcpy(ifr
.ifr_name
, ifname
);
539 if (!ipx_getaddr(fd
, IPX_FRAME_8023
, &ifr
)) {
541 ife
->ipxaddr_e3
= ifr
.ifr_addr
;
543 strcpy(ifr
.ifr_name
, ifname
);
544 if (!ipx_getaddr(fd
, IPX_FRAME_8022
, &ifr
)) {
546 ife
->ipxaddr_e2
= ifr
.ifr_addr
;
552 /* Econet address maybe? */
553 fd
= get_socket_for_af(AF_ECONET
);
555 strcpy(ifr
.ifr_name
, ifname
);
556 if (ioctl(fd
, SIOCGIFADDR
, &ifr
) == 0) {
557 ife
->ecaddr
= ifr
.ifr_addr
;
566 int do_if_fetch(struct interface
*ife
)
568 if (if_fetch(ife
) < 0) {
570 if (errno
== ENODEV
) {
571 /* Give better error message for this case. */
572 errmsg
= _("Device not found");
574 errmsg
= strerror(errno
);
576 fprintf(stderr
, _("%s: error fetching interface information: %s\n"),
583 int do_if_print(struct interface
*ife
, void *cookie
)
585 int *opt_a
= (int *) cookie
;
588 res
= do_if_fetch(ife
);
590 if ((ife
->flags
& IFF_UP
) || *opt_a
)
596 void ife_print_short(struct interface
*ptr
)
598 printf("%-5.5s ", ptr
->name
);
599 printf("%5d %-2d ", ptr
->mtu
, ptr
->metric
);
600 /* If needed, display the interface statistics. */
601 if (ptr
->statistics_valid
) {
602 printf("%8llu %6lu %6lu %-6lu ",
603 ptr
->stats
.rx_packets
, ptr
->stats
.rx_errors
,
604 ptr
->stats
.rx_dropped
, ptr
->stats
.rx_fifo_errors
);
605 printf("%8llu %6lu %6lu %6lu ",
606 ptr
->stats
.tx_packets
, ptr
->stats
.tx_errors
,
607 ptr
->stats
.tx_dropped
, ptr
->stats
.tx_fifo_errors
);
609 printf("%-56s", _(" - no statistics available -"));
611 /* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
613 printf(_("[NO FLAGS]"));
614 if (ptr
->flags
& IFF_ALLMULTI
)
616 if (ptr
->flags
& IFF_BROADCAST
)
618 if (ptr
->flags
& IFF_DEBUG
)
620 if (ptr
->flags
& IFF_LOOPBACK
)
622 if (ptr
->flags
& IFF_MULTICAST
)
625 if (ptr
->flags
& IFF_DYNAMIC
)
628 if (ptr
->flags
& IFF_PROMISC
)
630 if (ptr
->flags
& IFF_NOTRAILERS
)
632 if (ptr
->flags
& IFF_NOARP
)
634 if (ptr
->flags
& IFF_POINTOPOINT
)
636 if (ptr
->flags
& IFF_SLAVE
)
638 if (ptr
->flags
& IFF_MASTER
)
640 if (ptr
->flags
& IFF_RUNNING
)
642 if (ptr
->flags
& IFF_UP
)
644 /* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
648 void ife_print_long(struct interface
*ptr
)
653 int can_compress
= 0;
654 unsigned long long rx
, tx
, short_rx
, short_tx
;
655 const char *Rext
= "b";
656 const char *Text
= "b";
657 static char flags
[200];
660 static struct aftype
*ipxtype
= NULL
;
663 static struct aftype
*ectype
= NULL
;
666 static struct aftype
*ddptype
= NULL
;
670 char addr6
[40], devname
[20];
671 struct sockaddr_in6 sap
;
672 int plen
, scope
, dad_status
, if_idx
;
673 extern struct aftype inet6_aftype
;
677 ap
= get_afntype(ptr
->addr
.sa_family
);
683 if (hf
== ARPHRD_CSLIP
|| hf
== ARPHRD_CSLIP6
)
686 hw
= get_hwntype(hf
);
688 hw
= get_hwntype(-1);
690 sprintf(flags
, "flags=%d<", ptr
->flags
);
691 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
694 if (ptr
->flags
& IFF_UP
)
695 strcat(flags
,_("UP,"));
696 if (ptr
->flags
& IFF_BROADCAST
)
697 strcat(flags
,_("BROADCAST,"));
698 if (ptr
->flags
& IFF_DEBUG
)
699 strcat(flags
,_("DEBUG,"));
700 if (ptr
->flags
& IFF_LOOPBACK
)
701 strcat(flags
,_("LOOPBACK,"));
702 if (ptr
->flags
& IFF_POINTOPOINT
)
703 strcat(flags
,_("POINTOPOINT,"));
704 if (ptr
->flags
& IFF_NOTRAILERS
)
705 strcat(flags
,_("NOTRAILERS,"));
706 if (ptr
->flags
& IFF_RUNNING
)
707 strcat(flags
,_("RUNNING,"));
708 if (ptr
->flags
& IFF_NOARP
)
709 strcat(flags
,_("NOARP,"));
710 if (ptr
->flags
& IFF_PROMISC
)
711 strcat(flags
,_("PROMISC,"));
712 if (ptr
->flags
& IFF_ALLMULTI
)
713 strcat(flags
,_("ALLMULTI,"));
714 if (ptr
->flags
& IFF_SLAVE
)
715 strcat(flags
,_("SLAVE,"));
716 if (ptr
->flags
& IFF_MASTER
)
717 strcat(flags
,_("MASTER,"));
718 if (ptr
->flags
& IFF_MULTICAST
)
719 strcat(flags
,_("MULTICAST,"));
721 if (ptr
->flags
& IFF_DYNAMIC
)
722 strcat(flags
,_("DYNAMIC,"));
724 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
725 if (flags
[strlen(flags
)-1] == ',')
726 flags
[strlen(flags
)-1] = '>';
728 flags
[strlen(flags
)-1] = 0;
731 printf(_("%s: %s mtu %d metric %d"),
732 ptr
->name
, flags
, ptr
->mtu
, ptr
->metric
? ptr
->metric
: 1);
733 #ifdef SIOCSKEEPALIVE
734 if (ptr
->outfill
|| ptr
->keepalive
)
735 printf(_(" outfill %d keepalive %d"),
736 ptr
->outfill
, ptr
->keepalive
);
744 printf(_(" %s %s"), ap
->name
,
745 ap
->sprint(&ptr
->addr
, 1));
746 printf(_(" netmask %s"), ap
->sprint(&ptr
->netmask
, 1));
747 if (ptr
->flags
& IFF_BROADCAST
) {
748 printf(_(" broadcast %s"), ap
->sprint(&ptr
->broadaddr
, 1));
750 if (ptr
->flags
& IFF_POINTOPOINT
) {
751 printf(_(" destination %s"), ap
->sprint(&ptr
->dstaddr
, 1));
758 /* FIXME: should be integrated into interface.c. */
760 if ((f
= fopen(_PATH_PROCNET_IFINET6
, "r")) != NULL
) {
761 while (fscanf(f
, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
762 addr6p
[0], addr6p
[1], addr6p
[2], addr6p
[3],
763 addr6p
[4], addr6p
[5], addr6p
[6], addr6p
[7],
764 &if_idx
, &plen
, &scope
, &dad_status
, devname
) != EOF
) {
765 if (!strcmp(devname
, ptr
->name
)) {
766 sprintf(addr6
, "%s:%s:%s:%s:%s:%s:%s:%s",
767 addr6p
[0], addr6p
[1], addr6p
[2], addr6p
[3],
768 addr6p
[4], addr6p
[5], addr6p
[6], addr6p
[7]);
769 inet6_aftype
.input(1, addr6
, (struct sockaddr
*) &sap
);
770 printf(_(" %s %s prefixlen %d"),
772 inet6_aftype
.sprint((struct sockaddr
*) &sap
, 1),
774 printf(_(" scopeid 0x%x"), scope
);
776 flags
[0] = '<'; flags
[1] = 0;
777 if (scope
& IPV6_ADDR_COMPATv4
) {
778 strcat(flags
, _("compat,"));
779 scope
-= IPV6_ADDR_COMPATv4
;
782 strcat(flags
, _("global,"));
783 if (scope
& IPV6_ADDR_LINKLOCAL
)
784 strcat(flags
, _("link,"));
785 if (scope
& IPV6_ADDR_SITELOCAL
)
786 strcat(flags
, _("site,"));
787 if (scope
& IPV6_ADDR_LOOPBACK
)
788 strcat(flags
, _("host,"));
789 if (flags
[strlen(flags
)-1] == ',')
790 flags
[strlen(flags
)-1] = '>';
792 flags
[strlen(flags
)-1] = 0;
793 printf("%s\n", flags
);
802 ipxtype
= get_afntype(AF_IPX
);
804 if (ipxtype
!= NULL
) {
806 printf(_(" %s Ethernet-II %s\n"),
807 ipxtype
->name
, ipxtype
->sprint(&ptr
->ipxaddr_bb
, 1));
809 printf(_(" %s Ethernet-SNAP %s\n"),
810 ipxtype
->name
, ipxtype
->sprint(&ptr
->ipxaddr_sn
, 1));
812 printf(_(" %s Ethernet802.2 %s\n"),
813 ipxtype
->name
, ipxtype
->sprint(&ptr
->ipxaddr_e2
, 1));
815 printf(_(" %s Ethernet802.3 %s\n"),
816 ipxtype
->name
, ipxtype
->sprint(&ptr
->ipxaddr_e3
, 1));
822 ddptype
= get_afntype(AF_APPLETALK
);
823 if (ddptype
!= NULL
) {
825 printf(_(" %s %s\n"), ddptype
->name
, ddptype
->sprint(&ptr
->ddpaddr
, 1));
831 ectype
= get_afntype(AF_ECONET
);
832 if (ectype
!= NULL
) {
834 printf(_(" %s %s\n"), ectype
->name
, ectype
->sprint(&ptr
->ecaddr
, 1));
838 /* For some hardware types (eg Ash, ATM) we don't print the
839 hardware address if it's null. */
840 if (hw
->print
!= NULL
&& (! (hw_null_address(hw
, ptr
->hwaddr
) &&
841 hw
->suppress_null_addr
)))
842 printf(_(" %s %s"), hw
->name
, hw
->print(ptr
->hwaddr
));
844 printf(_(" %s"), hw
->name
);
845 if (ptr
->tx_queue_len
!= -1)
846 printf(_(" txqueuelen %d"), ptr
->tx_queue_len
);
847 printf(" (%s)\n", hw
->title
);
850 if (ptr
->flags
& IFF_PORTSEL
) {
851 printf(_(" media %s"), if_port_text
[ptr
->map
.port
][0]);
852 if (ptr
->flags
& IFF_AUTOMEDIA
)
853 printf(_("autoselect"));
859 /* If needed, display the interface statistics. */
861 if (ptr
->statistics_valid
) {
862 /* XXX: statistics are currently only printed for the primary address,
863 * not for the aliases, although strictly speaking they're shared
866 rx
= ptr
->stats
.rx_bytes
;
868 if (rx
> 1125899906842624ull) {
869 short_rx
/= 1125899906842624ull;
871 } else if (rx
> 1099511627776ull) {
872 short_rx
/= 1099511627776ull;
874 } else if (rx
> 1073741824ull) {
875 short_rx
/= 1073741824ull;
877 } else if (rx
> 1048576) {
880 } else if (rx
> 1024) {
884 tx
= ptr
->stats
.tx_bytes
;
886 if (tx
> 1125899906842624ull) {
887 short_tx
/= 1125899906842624ull;
889 } else if (tx
> 1099511627776ull) {
890 short_tx
/= 1099511627776ull;
892 } else if (tx
> 1073741824ull) {
893 short_tx
/= 1073741824ull;
895 } else if (tx
> 1048576) {
898 } else if (tx
> 1024) {
904 printf(_("RX packets %llu bytes %llu (%lu.%lu %s)\n"),
905 ptr
->stats
.rx_packets
,
906 rx
, (unsigned long)(short_rx
/ 10),
907 (unsigned long)(short_rx
% 10), Rext
);
910 printf(_("RX compressed:%lu\n"), ptr
->stats
.rx_compressed
);
913 printf(_("RX errors %lu dropped %lu overruns %lu frame %lu\n"),
914 ptr
->stats
.rx_errors
, ptr
->stats
.rx_dropped
,
915 ptr
->stats
.rx_fifo_errors
, ptr
->stats
.rx_frame_errors
);
919 printf(_("TX packets %llu bytes %llu (%lu.%lu %s)\n"),
920 ptr
->stats
.tx_packets
,
921 tx
, (unsigned long)(short_tx
/ 10),
922 (unsigned long)(short_tx
% 10), Text
);
925 printf(_("TX compressed %lu\n"), ptr
->stats
.tx_compressed
);
928 printf(_("TX errors %lu dropped %lu overruns %lu carrier %lu collisions %lu\n"),
929 ptr
->stats
.tx_errors
,
930 ptr
->stats
.tx_dropped
, ptr
->stats
.tx_fifo_errors
,
931 ptr
->stats
.tx_carrier_errors
, ptr
->stats
.collisions
);
934 if ((ptr
->map
.irq
|| ptr
->map
.mem_start
|| ptr
->map
.dma
||
935 ptr
->map
.base_addr
>= 0x100)) {
938 printf(_("interrupt %d "), ptr
->map
.irq
);
939 if (ptr
->map
.base_addr
>= 0x100) /* Only print devices using it for
941 printf(_("base 0x%x "), ptr
->map
.base_addr
);
942 if (ptr
->map
.mem_start
) {
943 printf(_("memory 0x%lx-%lx "), ptr
->map
.mem_start
, ptr
->map
.mem_end
);
946 printf(_(" dma 0x%x"), ptr
->map
.dma
);
952 void ife_print(struct interface
*i
)