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.14 2001/02/10 19:31:15 pb Exp $
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/ioctl.h>
18 #include <netinet/in.h>
28 #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
29 #include <netipx/ipx.h>
36 #include <neteconet/ec.h>
40 #include <linux/if_slip.h>
41 #include <net/if_arp.h>
44 #include "net-support.h"
45 #include "pathnames.h"
49 #include "interface.h"
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
},
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;
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
);
106 safe_strncpy(new->name
, name
, IFNAMSIZ
);
107 nextp
= ife
? &ife
->next
: &int_list
;
111 new->next
->prev
= new;
118 struct interface
*lookup_interface(char *name
)
120 struct interface
*ife
= NULL
;
122 if (if_readlist_proc(name
) < 0)
124 ife
= add_interface(name
);
128 int for_all_interfaces(int (*doit
) (struct interface
*, void *), void *cookie
)
130 struct interface
*ife
;
132 if (!int_list
&& (if_readlist() < 0))
134 for (ife
= int_list
; ife
; ife
= ife
->next
) {
135 int err
= doit(ife
, cookie
);
142 int free_interface_list(void)
144 struct interface
*ife
;
145 while ((ife
= int_list
) != NULL
) {
146 int_list
= ife
->next
;
152 static int if_readconf(void)
160 /* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
162 skfd
= get_socket_for_af(AF_INET
);
164 fprintf(stderr
, _("warning: no inet socket available: %s\n"),
166 /* Try to soldier on with whatever socket we can get hold of. */
167 skfd
= sockets_open(0);
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");
181 if (ifc
.ifc_len
== sizeof(struct ifreq
) * numreqs
) {
182 /* assume it overflowed and try again */
190 for (n
= 0; n
< ifc
.ifc_len
; n
+= sizeof(struct ifreq
)) {
191 add_interface(ifr
->ifr_name
);
201 static char *get_name(char *name
, char *p
)
208 if (*p
== ':') { /* could be an alias */
209 char *dot
= p
, *dotname
= name
;
213 if (*p
!= ':') { /* it wasn't, backup */
228 static int procnetdev_version(char *buf
)
230 if (strstr(buf
, "compressed"))
232 if (strstr(buf
, "bytes"))
237 static int get_dev_fields(char *bp
, struct interface
*ife
)
239 switch (procnetdev_vsn
) {
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
);
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;
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;
301 static int if_readlist_proc(char *target
)
303 static int proc_read
;
306 struct interface
*ife
;
314 fh
= fopen(_PATH_PROCNET_DEV
, "r");
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 */
346 procnetdev_vsn
= procnetdev_version(buf
);
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
))
360 perror(_PATH_PROCNET_DEV
);
372 int if_readlist(void)
374 int err
= if_readlist_proc(NULL
);
380 /* Support for fetching an IPX address */
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
);
390 /* Fetch the interface configuration from the kernel. */
391 int if_fetch(struct interface
*ife
)
395 char *ifname
= ife
->name
;
397 strcpy(ifr
.ifr_name
, ifname
);
398 if (ioctl(skfd
, SIOCGIFFLAGS
, &ifr
) < 0)
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);
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)
414 ife
->metric
= ifr
.ifr_metric
;
416 strcpy(ifr
.ifr_name
, ifname
);
417 if (ioctl(skfd
, SIOCGIFMTU
, &ifr
) < 0)
420 ife
->mtu
= ifr
.ifr_mtu
;
423 if (ife
->type
== ARPHRD_SLIP
|| ife
->type
== ARPHRD_CSLIP
||
424 ife
->type
== ARPHRD_SLIP6
|| ife
->type
== ARPHRD_CSLIP6
||
425 ife
->type
== ARPHRD_ADAPT
) {
427 strcpy(ifr
.ifr_name
, ifname
);
428 if (ioctl(skfd
, SIOCGOUTFILL
, &ifr
) < 0)
431 ife
->outfill
= (unsigned int) ifr
.ifr_data
;
433 #ifdef SIOCGKEEPALIVE
434 strcpy(ifr
.ifr_name
, ifname
);
435 if (ioctl(skfd
, SIOCGKEEPALIVE
, &ifr
) < 0)
438 ife
->keepalive
= (unsigned int) ifr
.ifr_data
;
443 strcpy(ifr
.ifr_name
, ifname
);
444 if (ioctl(skfd
, SIOCGIFMAP
, &ifr
) < 0)
445 memset(&ife
->map
, 0, sizeof(struct ifmap
));
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
));
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 */
460 ife
->tx_queue_len
= ifr
.ifr_qlen
;
462 ife
->tx_queue_len
= -1; /* unknown value */
467 fd
= get_socket_for_af(AF_INET
);
469 strcpy(ifr
.ifr_name
, ifname
);
470 ifr
.ifr_addr
.sa_family
= AF_INET
;
471 if (ioctl(fd
, SIOCGIFADDR
, &ifr
) == 0) {
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
));
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
));
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
));
490 ife
->netmask
= ifr
.ifr_netmask
;
492 memset(&ife
->addr
, 0, sizeof(struct sockaddr
));
497 /* DDP address maybe ? */
498 fd
= get_socket_for_af(AF_APPLETALK
);
500 strcpy(ifr
.ifr_name
, ifname
);
501 if (ioctl(fd
, SIOCGIFADDR
, &ifr
) == 0) {
502 ife
->ddpaddr
= ifr
.ifr_addr
;
509 /* Look for IPX addresses with all framing types */
510 fd
= get_socket_for_af(AF_IPX
);
512 strcpy(ifr
.ifr_name
, ifname
);
513 if (!ipx_getaddr(fd
, IPX_FRAME_ETHERII
, &ifr
)) {
515 ife
->ipxaddr_bb
= ifr
.ifr_addr
;
517 strcpy(ifr
.ifr_name
, ifname
);
518 if (!ipx_getaddr(fd
, IPX_FRAME_SNAP
, &ifr
)) {
520 ife
->ipxaddr_sn
= ifr
.ifr_addr
;
522 strcpy(ifr
.ifr_name
, ifname
);
523 if (!ipx_getaddr(fd
, IPX_FRAME_8023
, &ifr
)) {
525 ife
->ipxaddr_e3
= ifr
.ifr_addr
;
527 strcpy(ifr
.ifr_name
, ifname
);
528 if (!ipx_getaddr(fd
, IPX_FRAME_8022
, &ifr
)) {
530 ife
->ipxaddr_e2
= ifr
.ifr_addr
;
536 /* Econet address maybe? */
537 fd
= get_socket_for_af(AF_ECONET
);
539 strcpy(ifr
.ifr_name
, ifname
);
540 if (ioctl(fd
, SIOCGIFADDR
, &ifr
) == 0) {
541 ife
->ecaddr
= ifr
.ifr_addr
;
550 int do_if_fetch(struct interface
*ife
)
552 if (if_fetch(ife
) < 0) {
554 if (errno
== ENODEV
) {
555 /* Give better error message for this case. */
556 errmsg
= _("Device not found");
558 errmsg
= strerror(errno
);
560 fprintf(stderr
, _("%s: error fetching interface information: %s\n"),
567 int do_if_print(struct interface
*ife
, void *cookie
)
569 int *opt_a
= (int *) cookie
;
572 res
= do_if_fetch(ife
);
574 if ((ife
->flags
& IFF_UP
) || *opt_a
)
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
);
593 printf("%-56s", _(" - no statistics available -"));
595 /* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
597 printf(_("[NO FLAGS]"));
598 if (ptr
->flags
& IFF_ALLMULTI
)
600 if (ptr
->flags
& IFF_BROADCAST
)
602 if (ptr
->flags
& IFF_DEBUG
)
604 if (ptr
->flags
& IFF_LOOPBACK
)
606 if (ptr
->flags
& IFF_MULTICAST
)
609 if (ptr
->flags
& IFF_DYNAMIC
)
612 if (ptr
->flags
& IFF_PROMISC
)
614 if (ptr
->flags
& IFF_NOTRAILERS
)
616 if (ptr
->flags
& IFF_NOARP
)
618 if (ptr
->flags
& IFF_POINTOPOINT
)
620 if (ptr
->flags
& IFF_SLAVE
)
622 if (ptr
->flags
& IFF_MASTER
)
624 if (ptr
->flags
& IFF_RUNNING
)
626 if (ptr
->flags
& IFF_UP
)
628 /* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
632 void ife_print_long(struct interface
*ptr
)
637 int can_compress
= 0;
638 unsigned long long rx
, tx
, short_rx
, short_tx
;
643 static struct aftype
*ipxtype
= NULL
;
646 static struct aftype
*ectype
= NULL
;
649 static struct aftype
*ddptype
= NULL
;
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
;
660 ap
= get_afntype(ptr
->addr
.sa_family
);
666 if (hf
== ARPHRD_CSLIP
|| hf
== ARPHRD_CSLIP6
)
669 hw
= get_hwntype(hf
);
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
));
680 if (ptr
->flags
& IFF_PORTSEL
) {
681 printf(_("Media:%s"), if_port_text
[ptr
->map
.port
][0]);
682 if (ptr
->flags
& IFF_AUTOMEDIA
)
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));
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:"));
722 case IPV6_ADDR_LINKLOCAL
:
725 case IPV6_ADDR_SITELOCAL
:
728 case IPV6_ADDR_COMPATv4
:
731 case IPV6_ADDR_LOOPBACK
:
735 printf(_("Unknown"));
746 ipxtype
= get_afntype(AF_IPX
);
748 if (ipxtype
!= NULL
) {
750 printf(_(" IPX/Ethernet II addr:%s\n"),
751 ipxtype
->sprint(&ptr
->ipxaddr_bb
, 1));
753 printf(_(" IPX/Ethernet SNAP addr:%s\n"),
754 ipxtype
->sprint(&ptr
->ipxaddr_sn
, 1));
756 printf(_(" IPX/Ethernet 802.2 addr:%s\n"),
757 ipxtype
->sprint(&ptr
->ipxaddr_e2
, 1));
759 printf(_(" IPX/Ethernet 802.3 addr:%s\n"),
760 ipxtype
->sprint(&ptr
->ipxaddr_e3
, 1));
766 ddptype
= get_afntype(AF_APPLETALK
);
767 if (ddptype
!= NULL
) {
769 printf(_(" EtherTalk Phase 2 addr:%s\n"), ddptype
->sprint(&ptr
->ddpaddr
, 1));
775 ectype
= get_afntype(AF_ECONET
);
776 if (ectype
!= NULL
) {
778 printf(_(" econet addr:%s\n"), ectype
->sprint(&ptr
->ecaddr
, 1));
783 /* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
785 printf(_("[NO FLAGS] "));
786 if (ptr
->flags
& IFF_UP
)
788 if (ptr
->flags
& IFF_BROADCAST
)
789 printf(_("BROADCAST "));
790 if (ptr
->flags
& IFF_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
)
802 if (ptr
->flags
& IFF_PROMISC
)
803 printf(_("PROMISC "));
804 if (ptr
->flags
& IFF_ALLMULTI
)
805 printf(_("ALLMULTI "));
806 if (ptr
->flags
& IFF_SLAVE
)
808 if (ptr
->flags
& IFF_MASTER
)
809 printf(_("MASTER "));
810 if (ptr
->flags
& IFF_MULTICAST
)
811 printf(_("MULTICAST "));
813 if (ptr
->flags
& IFF_DYNAMIC
)
814 printf(_("DYNAMIC "));
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
);
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
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
);
840 printf(_(" compressed:%lu\n"), ptr
->stats
.rx_compressed
);
842 rx
= ptr
->stats
.rx_bytes
;
843 tx
= ptr
->stats
.tx_bytes
;
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"); }
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
);
858 printf(_("compressed:%lu "), ptr
->stats
.tx_compressed
);
859 if (ptr
->tx_queue_len
!= -1)
860 printf(_("txqueuelen:%d "), ptr
->tx_queue_len
);
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
)) {
873 printf(_("Interrupt:%d "), ptr
->map
.irq
);
874 if (ptr
->map
.base_addr
>= 0x100) /* Only print devices using it for
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
);
881 printf(_("DMA chan:%x "), ptr
->map
.dma
);
887 void ife_print(struct interface
*i
)