3 #include <sys/socket.h>
9 #include <linux/sockios.h>
13 #if defined(__FreeBSD_kernel__)
21 #if defined(__APPLE__) || defined(__OpenBSD__)
22 #define s6_addr16 __u6_addr.__u6_addr16
27 #define s6_addr16 _S6_un._S6_u8
29 #include <sys/sockio.h>
32 #include <netinet/in.h>
73 unsigned long long in_packets
, in_bytes
, in_errors
, in_drops
;
74 unsigned long long in_fifo
, in_frame
, in_compress
, in_multicast
;
75 unsigned long long out_bytes
, out_packets
, out_errors
, out_drops
;
76 unsigned long long out_fifo
, out_colls
, out_carrier
, out_multicast
;
80 void print_quad_ipv4(in_addr_t i
) {
83 (i
& 0xff000000) >> 24,
84 (i
& 0x00ff0000) >> 16,
85 (i
& 0x0000ff00) >> 8,
89 void print_quad_ipv6(uint16_t *a
) {
90 printf("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
91 a
[0], a
[1], a
[2], a
[3], a
[4], a
[5], a
[6], a
[7]);
94 void print_quad(struct sockaddr
*adr
) {
95 switch (adr
->sa_family
) {
97 print_quad_ipv4(((struct sockaddr_in
*)adr
)->sin_addr
.s_addr
);
100 print_quad_ipv6(((struct sockaddr_in6
*)adr
)->sin6_addr
.s6_addr16
);
108 enum print_error_enum
{
117 static int do_socket_ioctl(const char *ifname
, const unsigned long int request
,
118 struct ifreq
*req
, int *ioctl_errno
,
119 const enum print_error_enum print_error
) {
122 if ((sock
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_IP
)) == -1)
124 strncpy(req
->ifr_name
, ifname
, IFNAMSIZ
);
125 req
->ifr_name
[IFNAMSIZ
- 1] = 0;
127 if ((res
= ioctl(sock
, request
, req
)) == -1) {
129 *ioctl_errno
= errno
;
130 if (print_error
== PRINT_ERROR
) {
131 if (errno
== ENODEV
) {
132 fprintf(stderr
, "No such network interface: %s\n", ifname
);
136 fprintf(stderr
, "ioctl on %s: %s\n", ifname
,
148 int if_exists(const char *iface
) {
150 return !do_socket_ioctl(iface
, SIOCGIFFLAGS
, &r
, NULL
, PRINT_NO_ERROR
);
153 #if defined(__linux__)
155 void if_flags(const char *iface
) {
163 { IFF_BROADCAST
, "Broadcast" },
164 { IFF_DEBUG
, "Debugging" },
165 { IFF_LOOPBACK
, "Loopback" },
166 { IFF_POINTOPOINT
, "Ppp" },
167 { IFF_NOTRAILERS
, "No-trailers" },
168 { IFF_RUNNING
, "Running" },
169 { IFF_NOARP
, "No-arp" },
170 { IFF_PROMISC
, "Promiscuous" },
171 { IFF_ALLMULTI
, "All-multicast" },
172 { IFF_MASTER
, "Load-master" },
173 { IFF_SLAVE
, "Load-slave" },
174 { IFF_MULTICAST
, "Multicast" },
175 { IFF_PORTSEL
, "Port-select" },
176 { IFF_AUTOMEDIA
, "Auto-detect" },
177 { IFF_DYNAMIC
, "Dynaddr" },
178 { 0xffff0000, "Unknown-flags" },
181 if (do_socket_ioctl(iface
, SIOCGIFFLAGS
, &r
, NULL
, PRINT_ERROR
))
184 for (i
= 0; i
< sizeof(flags
) / sizeof(flags
[0]); i
++)
185 printf("%s%s%s", (r
.ifr_flags
& flags
[i
].flag
) ? "On " : "Off ",
187 sizeof(flags
) / sizeof(flags
[0]) - 1 == i
? "" : "\n");
190 void if_hwaddr(const char *iface
) {
192 unsigned char *hwaddr
;
194 if (do_socket_ioctl(iface
, SIOCGIFHWADDR
, &r
, NULL
, PRINT_ERROR
))
197 hwaddr
= (unsigned char *)r
.ifr_hwaddr
.sa_data
;
199 if (!hwaddr
[0] && !hwaddr
[1] && !hwaddr
[2] &&
200 !hwaddr
[3] && !hwaddr
[4] && !hwaddr
[5]) {
201 fprintf(stderr
, "Error: %s: no hardware address\n", iface
);
205 printf("%02X:%02X:%02X:%02X:%02X:%02X",
206 hwaddr
[0], hwaddr
[1], hwaddr
[2], hwaddr
[3], hwaddr
[4], hwaddr
[5]);
211 static struct sockaddr
*if_addr_value(const char *iface
, struct ifreq
*r
,
212 unsigned long int request
) {
215 if (do_socket_ioctl(iface
, request
, r
, &e
, PRINT_NO_ERROR
)) {
216 if (e
== EADDRNOTAVAIL
)
223 struct sockaddr
*if_addr(const char *iface
, struct ifreq
*r
) {
224 return if_addr_value(iface
, r
, SIOCGIFADDR
);
227 struct sockaddr
*if_mask(const char *iface
, struct ifreq
*r
) {
228 return if_addr_value(iface
, r
, SIOCGIFNETMASK
);
231 struct sockaddr
*if_bcast(const char *iface
, struct ifreq
*r
) {
232 return if_addr_value(iface
, r
, SIOCGIFBRDADDR
);
235 struct sockaddr
*if_network(const char *iface
) {
236 struct sockaddr
*saddr
;
237 static struct ifreq req
;
240 if (!(saddr
= if_mask(iface
, &req
)))
243 mask
= ((struct sockaddr_in
*)saddr
)->sin_addr
.s_addr
;
245 if (!(saddr
= if_addr(iface
, &req
)))
248 ((struct sockaddr_in
*)saddr
)->sin_addr
.s_addr
&= mask
;
252 int ifd_if_mtu(const char *iface
) {
253 static struct ifreq req
;
255 if (do_socket_ioctl(iface
, SIOCGIFMTU
, &req
, NULL
, PRINT_ERROR
))
261 #if defined(__linux__)
263 static void skipline(FILE *fd
) {
267 } while (ch
!= '\n' && ch
!= EOF
);
270 struct if_stat
*get_stats(const char *iface
) {
272 struct if_stat
*ifstat
;
275 if (!(ifstat
= malloc(sizeof(struct if_stat
)))) {
280 if ((fd
= fopen("/proc/net/dev", "r")) == NULL
) {
281 perror("fopen(\"/proc/net/dev\")");
291 int items
= fscanf(fd
,
292 " %20[^:]:%llu %llu %llu %llu %llu %llu %llu %llu "
293 "%llu %llu %llu %llu %llu %llu %llu %llu",
295 &ifstat
->in_bytes
, &ifstat
->in_packets
,
296 &ifstat
->in_errors
, &ifstat
->in_drops
,
297 &ifstat
->in_fifo
, &ifstat
->in_frame
,
298 &ifstat
->in_compress
, &ifstat
->in_multicast
,
299 &ifstat
->out_bytes
, &ifstat
->out_packets
,
300 &ifstat
->out_errors
, &ifstat
->out_drops
,
301 &ifstat
->out_fifo
, &ifstat
->out_colls
,
302 &ifstat
->out_carrier
, &ifstat
->out_carrier
308 fprintf(stderr
, "Invalid data read, check!\n");
312 if (!strncmp(name
, iface
, sizeof(name
))) {
328 unsigned int is_stat
;
331 { "-e", DO_EXISTS
, 0, "Reports interface existence via return code" },
332 { "-p", DO_PALL
, 0, "Print out the whole config of iface" },
333 { "-pe", DO_PEXISTS
, 0, "Print out yes or no according to existence" },
334 { "-pa", DO_PADDRESS
, 0, "Print out the address" },
335 { "-pn", DO_PMASK
, 0, "Print netmask" },
336 { "-pN", DO_PNETWORK
, 0, "Print network address" },
337 { "-pb", DO_PCAST
, 0, "Print broadcast" },
338 { "-pm", DO_PMTU
, 0, "Print mtu" },
339 #if defined(__linux__)
340 { "-ph", DO_PHWADDRESS
, 0, "Print out the hardware address" },
341 { "-pf", DO_PFLAGS
, 0, "Print flags" },
342 { "-si", DO_SINALL
, 1, "Print all statistics on input" },
343 { "-sip", DO_SINPACKETS
, 1, "Print # of in packets" },
344 { "-sib", DO_SINBYTES
, 1, "Print # of in bytes" },
345 { "-sie", DO_SINERRORS
, 1, "Print # of in errors" },
346 { "-sid", DO_SINDROPS
, 1, "Print # of in drops" },
347 { "-sif", DO_SINFIFO
, 1, "Print # of in fifo overruns" },
348 { "-sic", DO_SINCOMPRESSES
, 1, "Print # of in compress" },
349 { "-sim", DO_SINMULTICAST
, 1, "Print # of in multicast" },
350 { "-so", DO_SOUTALL
, 1, "Print all statistics on output" },
351 { "-sop", DO_SOUTPACKETS
, 1, "Print # of out packets" },
352 { "-sob", DO_SOUTBYTES
, 1, "Print # of out bytes" },
353 { "-soe", DO_SOUTERRORS
, 1, "Print # of out errors" },
354 { "-sod", DO_SOUTDROPS
, 1, "Print # of out drops" },
355 { "-sof", DO_SOUTFIFO
, 1, "Print # of out fifo overruns" },
356 { "-sox", DO_SOUTCOLLS
, 1, "Print # of out collisions" },
357 { "-soc", DO_SOUTCARRIER
, 1, "Print # of out carrier loss" },
358 { "-som", DO_SOUTMULTICAST
, 1, "Print # of out multicast" },
359 { "-bips",DO_BIPS
, 1, "Print # of incoming bytes per second" },
360 { "-bops",DO_BOPS
, 1, "Print # of outgoing bytes per second" },
364 void usage(const char *name
) {
367 fprintf(stderr
, "Usage: %s [options] iface\n", name
);
368 for (i
= 0; i
< sizeof(options
) / sizeof(options
[0]); i
++) {
369 fprintf(stderr
, " %5s %s\n",
370 options
[i
].option
, options
[i
].description
);
374 void add_do(int *ndo
, int **todo
, int act
) {
375 *todo
= realloc(*todo
, (*ndo
+1) * sizeof(int));
380 static void print_addr(struct sockaddr
*sadr
) {
382 fprintf(stderr
, "Error\n");
388 struct if_stat
*ifstats
, *ifstats2
= NULL
;
390 void please_do(int ndo
, int *todo
, const char *ifname
) {
393 static struct ifreq req
;
396 exists
= if_exists(ifname
);
398 // printf("I have %d items in my queue.\n",ndo);
399 for (i
=0; i
<ndo
; i
++) {
401 (todo
[i
] != DO_EXISTS
) && (todo
[i
] != DO_PEXISTS
)) {
402 fprintf(stderr
, "No such network interface: %s\n", ifname
);
410 printf("%s", exists
? "yes" : "no");
413 print_addr(if_addr(ifname
, &req
));
415 #if defined(__linux__)
424 print_addr(if_mask(ifname
, &req
));
427 print_addr(if_bcast(ifname
, &req
));
430 printf("%d", ifd_if_mtu(ifname
));
433 print_addr(if_network(ifname
));
436 print_addr(if_addr(ifname
, &req
));
438 print_addr(if_mask(ifname
, &req
));
440 print_addr(if_bcast(ifname
, &req
));
442 printf("%d", ifd_if_mtu(ifname
));
444 #if defined(__linux__)
446 printf("%llu",ifstats
->in_packets
);
449 printf("%llu",ifstats
->in_bytes
);
452 printf("%llu",ifstats
->in_errors
);
455 printf("%llu",ifstats
->in_drops
);
458 printf("%llu",ifstats
->in_fifo
);
461 printf("%llu",ifstats
->in_frame
);
463 case DO_SINCOMPRESSES
:
464 printf("%llu",ifstats
->in_compress
);
466 case DO_SINMULTICAST
:
467 printf("%llu",ifstats
->in_multicast
);
470 printf("%llu %llu %llu %llu %llu %llu %llu %llu",
471 ifstats
->in_bytes
, ifstats
->in_packets
,
472 ifstats
->in_errors
, ifstats
->in_drops
,
473 ifstats
->in_fifo
, ifstats
->in_frame
,
474 ifstats
->in_compress
, ifstats
->in_multicast
);
477 printf("%llu",ifstats
->out_bytes
);
480 printf("%llu",ifstats
->out_packets
);
483 printf("%llu",ifstats
->out_errors
);
486 printf("%llu",ifstats
->out_drops
);
489 printf("%llu",ifstats
->out_fifo
);
492 printf("%llu",ifstats
->out_colls
);
495 printf("%llu",ifstats
->out_carrier
);
497 case DO_SOUTMULTICAST
:
498 printf("%llu",ifstats
->out_multicast
);
501 if (ifstats2
== NULL
) {
503 ifstats2
= get_stats(ifname
);
505 printf("%llu", ifstats2
->in_bytes
-ifstats
->in_bytes
);
508 if (ifstats2
== NULL
) {
510 ifstats2
= get_stats(ifname
);
512 printf("%llu", ifstats2
->out_bytes
-ifstats
->out_bytes
);
515 printf("%llu %llu %llu %llu %llu %llu %llu %llu",
516 ifstats
->out_bytes
, ifstats
->out_packets
,
517 ifstats
->out_errors
, ifstats
->out_drops
,
518 ifstats
->out_fifo
, ifstats
->out_colls
,
519 ifstats
->out_carrier
, ifstats
->out_multicast
);
523 printf("Unknown command: %d", todo
[i
]);
530 int main(int argc
, char *argv
[]) {
536 unsigned int i
, found
;
543 while (narg
< argc
- 1) {
548 for (i
= 0; i
< sizeof(options
) / sizeof(options
[0]); i
++) {
549 if (!strcmp(argv
[narg
], options
[i
].option
)) {
550 add_do(&ndo
, &todo
, options
[i
].flag
);
551 do_stats
|= options
[i
].is_stat
;
560 if (argv
[narg
][0] == '-') {
570 if (narg
+ 1 < argc
|| !ifname
) {
575 #if defined(__linux__)
576 if (do_stats
&& (ifstats
= get_stats(ifname
)) == NULL
) {
577 fprintf(stderr
, "Error getting statistics for %s\n", ifname
);
582 please_do(ndo
, todo
, ifname
);