Annotation of src/usr.bin/netstat/if.c, Revision 1.69
1.69 ! mikeb 1: /* $OpenBSD: if.c,v 1.68 2014/06/23 03:46:17 guenther Exp $ */
1.6 deraadt 2: /* $NetBSD: if.c,v 1.16.4.2 1996/06/07 21:46:46 thorpej Exp $ */
1.1 deraadt 3:
4: /*
5: * Copyright (c) 1983, 1988, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.35 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
1.56 claudio 33: #include <sys/param.h>
1.1 deraadt 34: #include <sys/types.h>
1.63 tedu 35: #include <sys/ioctl.h>
1.1 deraadt 36: #include <sys/protosw.h>
37: #include <sys/socket.h>
1.56 claudio 38: #include <sys/sysctl.h>
1.1 deraadt 39:
40: #include <net/if.h>
41: #include <net/if_dl.h>
1.5 deraadt 42: #include <net/if_types.h>
1.56 claudio 43: #include <net/route.h>
1.1 deraadt 44: #include <netinet/in.h>
45: #include <netinet/in_var.h>
1.11 millert 46: #include <netinet/if_ether.h>
1.1 deraadt 47: #include <arpa/inet.h>
48:
1.60 chl 49: #include <err.h>
1.13 millert 50: #include <limits.h>
1.1 deraadt 51: #include <signal.h>
52: #include <stdio.h>
1.36 david 53: #include <stdlib.h>
1.1 deraadt 54: #include <string.h>
55: #include <unistd.h>
1.65 tedu 56: #include <util.h>
1.1 deraadt 57:
58: #include "netstat.h"
59:
1.56 claudio 60: static void print_addr(struct sockaddr *, struct sockaddr **, struct if_data *);
1.62 tedu 61: static void sidewaysintpr(u_int, int);
1.29 millert 62: static void catchalarm(int);
1.56 claudio 63: static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
64: static void fetchifs(void);
1.1 deraadt 65:
66: /*
67: * Print a description of the network interfaces.
1.3 deraadt 68: * NOTE: ifnetaddr is the location of the kernel global "ifnet",
69: * which is a TAILQ_HEAD.
1.1 deraadt 70: */
71: void
1.62 tedu 72: intpr(int interval, int repeatcount)
1.1 deraadt 73: {
1.56 claudio 74: struct if_msghdr ifm;
1.68 guenther 75: int mib[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
1.56 claudio 76: char name[IFNAMSIZ + 1]; /* + 1 for the '*' */
77: char *buf, *next, *lim, *cp;
78: struct rt_msghdr *rtm;
79: struct ifa_msghdr *ifam;
80: struct if_data *ifd;
81: struct sockaddr *sa, *rti_info[RTAX_MAX];
82: struct sockaddr_dl *sdl;
83: u_int64_t total = 0;
84: size_t len;
1.1 deraadt 85:
86: if (interval) {
1.62 tedu 87: sidewaysintpr((unsigned)interval, repeatcount);
1.1 deraadt 88: return;
89: }
1.3 deraadt 90:
1.56 claudio 91: if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
92: err(1, "sysctl");
93: if ((buf = malloc(len)) == NULL)
94: err(1, NULL);
95: if (sysctl(mib, 6, buf, &len, NULL, 0) == -1)
96: err(1, "sysctl");
1.3 deraadt 97:
1.22 camield 98: printf("%-7.7s %-5.5s %-11.11s %-17.17s ",
1.33 deraadt 99: "Name", "Mtu", "Network", "Address");
1.22 camield 100: if (bflag)
101: printf("%10.10s %10.10s", "Ibytes", "Obytes");
102: else
103: printf("%8.8s %5.5s %8.8s %5.5s %5.5s",
104: "Ipkts", "Ierrs", "Opkts", "Oerrs", "Colls");
1.1 deraadt 105: if (tflag)
106: printf(" %s", "Time");
107: if (dflag)
108: printf(" %s", "Drop");
109: putchar('\n');
1.56 claudio 110:
111: lim = buf + len;
112: for (next = buf; next < lim; next += rtm->rtm_msglen) {
113: rtm = (struct rt_msghdr *)next;
114: if (rtm->rtm_version != RTM_VERSION)
115: continue;
116: switch (rtm->rtm_type) {
117: case RTM_IFINFO:
118: total = 0;
119: bcopy(next, &ifm, sizeof ifm);
120: ifd = &ifm.ifm_data;
121:
122: sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
123: get_rtaddrs(ifm.ifm_addrs, sa, rti_info);
124:
125: sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP];
126: if (sdl == NULL || sdl->sdl_family != AF_LINK)
127: continue;
128: bzero(name, sizeof(name));
129: if (sdl->sdl_nlen >= IFNAMSIZ)
130: memcpy(name, sdl->sdl_data, IFNAMSIZ - 1);
131: else if (sdl->sdl_nlen > 0)
132: memcpy(name, sdl->sdl_data, sdl->sdl_nlen);
133:
1.3 deraadt 134: if (interface != 0 && strcmp(name, interface) != 0)
1.1 deraadt 135: continue;
1.56 claudio 136:
137: /* mark inactive interfaces with a '*' */
1.10 millert 138: cp = strchr(name, '\0');
1.56 claudio 139: if ((ifm.ifm_flags & IFF_UP) == 0)
1.1 deraadt 140: *cp++ = '*';
141: *cp = '\0';
1.25 brian 142:
1.56 claudio 143: if (qflag) {
144: total = ifd->ifi_ibytes + ifd->ifi_obytes +
145: ifd->ifi_ipackets + ifd->ifi_ierrors +
146: ifd->ifi_opackets + ifd->ifi_oerrors +
147: ifd->ifi_collisions;
148: if (tflag)
149: total += 0; // XXX ifnet.if_timer;
150: if (dflag)
151: total += 0; // XXX ifnet.if_snd.ifq_drops;
152: if (total == 0)
153: continue;
154: }
155:
1.61 tedu 156: printf("%-7s %-5d ", name, ifd->ifi_mtu);
1.56 claudio 157: print_addr(rti_info[RTAX_IFP], rti_info, ifd);
158: break;
159: case RTM_NEWADDR:
160: if (qflag && total == 0)
1.25 brian 161: continue;
1.57 claudio 162: if (interface != 0 && strcmp(name, interface) != 0)
163: continue;
164:
1.56 claudio 165: ifam = (struct ifa_msghdr *)next;
166: if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
167: RTA_BRD)) == 0)
168: break;
169:
170: sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
171: get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
172:
1.61 tedu 173: printf("%-7s %-5d ", name, ifd->ifi_mtu);
1.56 claudio 174: print_addr(rti_info[RTAX_IFA], rti_info, ifd);
175: break;
1.25 brian 176: }
1.56 claudio 177: }
1.58 dhill 178: free(buf);
1.56 claudio 179: }
1.25 brian 180:
1.56 claudio 181: static void
182: print_addr(struct sockaddr *sa, struct sockaddr **rtinfo, struct if_data *ifd)
183: {
184: struct sockaddr_dl *sdl;
185: struct sockaddr_in *sin;
186: struct sockaddr_in6 *sin6;
187: char *cp;
188: int m, n;
189:
190: switch (sa->sa_family) {
191: case AF_UNSPEC:
192: printf("%-11.11s ", "none");
193: printf("%-17.17s ", "none");
194: break;
195: case AF_INET:
196: sin = (struct sockaddr_in *)sa;
197: cp = netname4(sin->sin_addr.s_addr,
198: ((struct sockaddr_in *)rtinfo[RTAX_NETMASK])->sin_addr.s_addr);
199: if (vflag)
200: n = strlen(cp) < 11 ? 11 : strlen(cp);
201: else
202: n = 11;
203: printf("%-*.*s ", n, n, cp);
204: cp = routename4(sin->sin_addr.s_addr);
205: if (vflag)
206: n = strlen(cp) < 17 ? 17 : strlen(cp);
207: else
208: n = 17;
209: printf("%-*.*s ", n, n, cp);
210:
211: #if 0
212: if (aflag) {
213: u_long multiaddr;
214: struct in_multi inm;
215:
216: multiaddr = (u_long)LIST_FIRST(&ifaddr.in.ia_multiaddrs);
217: while (multiaddr != 0) {
218: kread(multiaddr, &inm, sizeof inm);
219: printf("\n%25s %-17.17s ", "",
220: routename4(inm.inm_addr.s_addr));
221: multiaddr = (u_long)LIST_NEXT(&inm, inm_list);
1.1 deraadt 222: }
1.56 claudio 223: }
224: #endif
225: break;
226: case AF_INET6:
227: sin6 = (struct sockaddr_in6 *)sa;
228: #ifdef __KAME__
229: if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
230: sin6->sin6_scope_id =
231: ntohs(*(u_int16_t *)
232: &sin6->sin6_addr.s6_addr[2]);
233: sin6->sin6_addr.s6_addr[2] = 0;
234: sin6->sin6_addr.s6_addr[3] = 0;
235: }
1.1 deraadt 236: #endif
1.56 claudio 237: cp = netname6(sin6,
238: (struct sockaddr_in6 *)rtinfo[RTAX_NETMASK]);
239: if (vflag)
240: n = strlen(cp) < 11 ? 11 : strlen(cp);
241: else
242: n = 11;
243: printf("%-*.*s ", n, n, cp);
244: cp = routename6(sin6);
245: if (vflag)
246: n = strlen(cp) < 17 ? 17 : strlen(cp);
247: else
248: n = 17;
249: printf("%-*.*s ", n, n, cp);
250: #if 0
251: if (aflag) {
252: u_long multiaddr;
253: struct in6_multi inm;
254: struct sockaddr_in6 m6;
255:
256: multiaddr = (u_long)LIST_FIRST(&ifaddr.in6.ia6_multiaddrs);
257: while (multiaddr != 0) {
258: kread(multiaddr, &inm, sizeof inm);
259: memset(&m6, 0, sizeof(m6));
260: m6.sin6_len = sizeof(struct sockaddr_in6);
261: m6.sin6_family = AF_INET6;
262: m6.sin6_addr = inm.in6m_addr;
1.34 itojun 263: #ifdef __KAME__
1.56 claudio 264: if (IN6_IS_ADDR_MC_LINKLOCAL(&m6.sin6_addr) ||
265: IN6_IS_ADDR_MC_INTFACELOCAL(&m6.sin6_addr)) {
266: m6.sin6_scope_id =
1.30 deraadt 267: ntohs(*(u_int16_t *)
1.56 claudio 268: &m6.sin6_addr.s6_addr[2]);
269: m6.sin6_addr.s6_addr[2] = 0;
270: m6.sin6_addr.s6_addr[3] = 0;
1.20 itojun 271: }
272: #endif
1.56 claudio 273: cp = routename6(&m6);
1.20 itojun 274: if (vflag)
275: n = strlen(cp) < 17 ? 17 : strlen(cp);
276: else
277: n = 17;
1.56 claudio 278: printf("\n%25s %-*.*s ", "",
279: n, n, cp);
280: multiaddr = (u_long)LIST_NEXT(&inm, in6m_entry);
281: }
282: }
1.31 itojun 283: #endif
1.56 claudio 284: break;
285: case AF_LINK:
286: sdl = (struct sockaddr_dl *)sa;
287: m = printf("%-11.11s ", "<Link>");
288: if (sdl->sdl_type == IFT_ETHER ||
289: sdl->sdl_type == IFT_CARP ||
290: sdl->sdl_type == IFT_FDDI ||
291: sdl->sdl_type == IFT_ISO88025)
292: printf("%-17.17s ",
293: ether_ntoa((struct ether_addr *)LLADDR(sdl)));
294: else {
295: cp = (char *)LLADDR(sdl);
296: n = sdl->sdl_alen;
297: goto hexprint;
1.1 deraadt 298: }
1.56 claudio 299: break;
300: default:
301: m = printf("(%d)", sa->sa_family);
302: for (cp = sa->sa_len + (char *)sa;
303: --cp > sa->sa_data && (*cp == 0);) {}
304: n = cp - sa->sa_data + 1;
305: cp = sa->sa_data;
306: hexprint:
307: while (--n >= 0)
308: m += printf("%x%c", *cp++ & 0xff,
309: n > 0 ? '.' : ' ');
310: m = 30 - m;
311: while (m-- > 0)
312: putchar(' ');
313: break;
1.1 deraadt 314: }
1.65 tedu 315: if (bflag) {
316: if (hflag) {
317: char ibytes[FMT_SCALED_STRSIZE];
318: char obytes[FMT_SCALED_STRSIZE];
319: fmt_scaled(ifd->ifi_ibytes, ibytes);
320: fmt_scaled(ifd->ifi_obytes, obytes);
321: printf("%10s %10s", ibytes, obytes);
322: } else
1.66 tedu 323: printf("%10llu %10llu",
1.65 tedu 324: ifd->ifi_ibytes, ifd->ifi_obytes);
325: } else
1.56 claudio 326: printf("%8llu %5llu %8llu %5llu %5llu",
327: ifd->ifi_ipackets, ifd->ifi_ierrors,
328: ifd->ifi_opackets, ifd->ifi_oerrors,
329: ifd->ifi_collisions);
330: if (tflag)
331: printf(" %4d", 0 /* XXX ifnet.if_timer */);
332: if (dflag)
333: printf(" %4d", 0 /* XXX ifnet.if_snd.ifq_drops */);
334: putchar('\n');
1.1 deraadt 335: }
336:
337: struct iftot {
1.3 deraadt 338: char ift_name[IFNAMSIZ]; /* interface name */
1.53 mk 339: u_int64_t ift_ip; /* input packets */
340: u_int64_t ift_ib; /* input bytes */
341: u_int64_t ift_ie; /* input errors */
342: u_int64_t ift_op; /* output packets */
343: u_int64_t ift_ob; /* output bytes */
344: u_int64_t ift_oe; /* output errors */
345: u_int64_t ift_co; /* collisions */
346: u_int64_t ift_dr; /* drops */
1.56 claudio 347: } ip_cur, ip_old, sum_cur, sum_old;
1.1 deraadt 348:
1.26 millert 349: volatile sig_atomic_t signalled; /* set if alarm goes off "early" */
1.1 deraadt 350:
351: /*
352: * Print a running summary of interface statistics.
353: * Repeat display every interval seconds, showing statistics
354: * collected over that interval. Assumes that interval is non-zero.
355: * First line printed at top of screen is always cumulative.
356: */
357: static void
1.62 tedu 358: sidewaysintpr(unsigned int interval, int repeatcount)
1.1 deraadt 359: {
1.56 claudio 360: sigset_t emptyset;
1.27 mpech 361: int line;
1.65 tedu 362: char ibytes[FMT_SCALED_STRSIZE];
363: char obytes[FMT_SCALED_STRSIZE];
1.3 deraadt 364:
1.56 claudio 365: fetchifs();
366: if (ip_cur.ift_name[0] == '\0') {
1.4 deraadt 367: fprintf(stderr, "%s: %s: unknown interface\n",
368: __progname, interface);
369: exit(1);
1.1 deraadt 370: }
371:
372: (void)signal(SIGALRM, catchalarm);
1.56 claudio 373: signalled = 0;
1.1 deraadt 374: (void)alarm(interval);
375: banner:
1.22 camield 376: if (bflag)
377: printf("%7.7s in %8.8s %6.6s out %5.5s",
1.56 claudio 378: ip_cur.ift_name, " ",
379: ip_cur.ift_name, " ");
1.22 camield 380: else
381: printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s",
1.56 claudio 382: ip_cur.ift_name, " ",
383: ip_cur.ift_name, " ", " ");
384: if (dflag)
385: printf(" %5.5s", " ");
386:
387: if (bflag)
388: printf(" %7.7s in %8.8s %6.6s out %5.5s",
389: "total", " ", "total", " ");
390: else
391: printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s",
392: "total", " ", "total", " ", " ");
1.22 camield 393: if (dflag)
394: printf(" %5.5s", " ");
1.1 deraadt 395: putchar('\n');
1.22 camield 396: if (bflag)
397: printf("%10.10s %8.8s %10.10s %5.5s",
398: "bytes", " ", "bytes", " ");
399: else
400: printf("%8.8s %5.5s %8.8s %5.5s %5.5s",
401: "packets", "errs", "packets", "errs", "colls");
1.1 deraadt 402: if (dflag)
403: printf(" %5.5s", "drops");
1.56 claudio 404:
405: if (bflag)
1.65 tedu 406: printf("%10.10s %8.8s %10.10s %5.5s",
1.56 claudio 407: "bytes", " ", "bytes", " ");
408: else
409: printf(" %8.8s %5.5s %8.8s %5.5s %5.5s",
410: "packets", "errs", "packets", "errs", "colls");
411: if (dflag)
412: printf(" %5.5s", "drops");
1.1 deraadt 413: putchar('\n');
414: fflush(stdout);
415: line = 0;
1.56 claudio 416: bzero(&ip_old, sizeof(ip_old));
417: bzero(&sum_old, sizeof(sum_old));
1.1 deraadt 418: loop:
1.56 claudio 419: bzero(&sum_cur, sizeof(sum_cur));
420:
421: fetchifs();
422:
1.65 tedu 423: if (bflag) {
424: if (hflag) {
425: fmt_scaled(ip_cur.ift_ib - ip_old.ift_ib, ibytes);
426: fmt_scaled(ip_cur.ift_ob - ip_old.ift_ob, obytes);
427: printf("%10s %8.8s %10s %5.5s",
428: ibytes, " ", obytes, " ");
429: } else
430: printf("%10llu %8.8s %10llu %5.5s",
431: ip_cur.ift_ib - ip_old.ift_ib, " ",
432: ip_cur.ift_ob - ip_old.ift_ob, " ");
433: } else
1.56 claudio 434: printf("%8llu %5llu %8llu %5llu %5llu",
435: ip_cur.ift_ip - ip_old.ift_ip,
436: ip_cur.ift_ie - ip_old.ift_ie,
437: ip_cur.ift_op - ip_old.ift_op,
438: ip_cur.ift_oe - ip_old.ift_oe,
439: ip_cur.ift_co - ip_old.ift_co);
440: if (dflag)
441: printf(" %5llu",
442: /* XXX ifnet.if_snd.ifq_drops - ip->ift_dr); */
1.61 tedu 443: 0LL);
1.56 claudio 444:
445: ip_old = ip_cur;
446:
1.65 tedu 447: if (bflag) {
448: if (hflag) {
449: fmt_scaled(sum_cur.ift_ib - sum_old.ift_ib, ibytes);
450: fmt_scaled(sum_cur.ift_ob - sum_old.ift_ob, obytes);
451: printf(" %10s %8.8s %10s %5.5s",
452: ibytes, " ", obytes, " ");
453: } else
454: printf(" %10llu %8.8s %10llu %5.5s",
455: sum_cur.ift_ib - sum_old.ift_ib, " ",
456: sum_cur.ift_ob - sum_old.ift_ob, " ");
457: } else
1.56 claudio 458: printf(" %8llu %5llu %8llu %5llu %5llu",
459: sum_cur.ift_ip - sum_old.ift_ip,
460: sum_cur.ift_ie - sum_old.ift_ie,
461: sum_cur.ift_op - sum_old.ift_op,
462: sum_cur.ift_oe - sum_old.ift_oe,
463: sum_cur.ift_co - sum_old.ift_co);
464: if (dflag)
465: printf(" %5llu", sum_cur.ift_dr - sum_old.ift_dr);
466:
467: sum_old = sum_cur;
468:
1.1 deraadt 469: putchar('\n');
470: fflush(stdout);
1.62 tedu 471: if (repeatcount && --repeatcount == 0)
472: return;
1.1 deraadt 473: line++;
1.26 millert 474: sigemptyset(&emptyset);
475: if (!signalled)
476: sigsuspend(&emptyset);
1.56 claudio 477: signalled = 0;
1.1 deraadt 478: (void)alarm(interval);
1.62 tedu 479: if (line == 21 && isatty(STDOUT_FILENO))
1.1 deraadt 480: goto banner;
481: goto loop;
482: }
483:
484: /*
485: * Called if an interval expires before sidewaysintpr has completed a loop.
486: * Sets a flag to not wait for the alarm.
487: */
1.46 deraadt 488: /* ARGSUSED */
1.1 deraadt 489: static void
1.33 deraadt 490: catchalarm(int signo)
1.1 deraadt 491: {
1.56 claudio 492: signalled = 1;
493: }
494:
495: static void
496: get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
497: {
498: int i;
499:
500: for (i = 0; i < RTAX_MAX; i++) {
501: if (addrs & (1 << i)) {
502: rti_info[i] = sa;
503: sa = (struct sockaddr *)((char *)(sa) +
504: roundup(sa->sa_len, sizeof(long)));
505: } else
506: rti_info[i] = NULL;
507: }
508: }
509:
1.63 tedu 510:
511: static int
512: isegress(char *name)
513: {
514: static int s = -1;
515: int len;
516: struct ifgroupreq ifgr;
517: struct ifg_req *ifg;
518: int rv = 0;
519:
520: if (s == -1) {
521: if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
522: return 0;
523: }
524:
525: memset(&ifgr, 0, sizeof(ifgr));
526: strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
527:
528: if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) {
529: return 0;
530: }
531:
532: len = ifgr.ifgr_len;
533: ifgr.ifgr_groups = calloc(len, 1);
534: if (ifgr.ifgr_groups == NULL)
535: err(1, "getifgroups");
536: if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1)
537: err(1, "SIOCGIFGROUP");
538:
539: ifg = ifgr.ifgr_groups;
540: for (; ifg && len >= sizeof(struct ifg_req); ifg++) {
541: len -= sizeof(struct ifg_req);
542: if (strcmp(ifg->ifgrq_group, IFG_EGRESS) == 0)
543: rv = 1;
544: }
545:
546: free(ifgr.ifgr_groups);
547: return rv;
548: }
549:
1.56 claudio 550: static void
551: fetchifs(void)
552: {
553: struct if_msghdr ifm;
1.68 guenther 554: int mib[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
1.56 claudio 555: struct rt_msghdr *rtm;
556: struct if_data *ifd;
557: struct sockaddr *sa, *rti_info[RTAX_MAX];
558: struct sockaddr_dl *sdl;
559: char *buf, *next, *lim;
560: char name[IFNAMSIZ];
561: size_t len;
1.63 tedu 562: int takeit = 0;
563: int foundone = 0;
1.56 claudio 564:
565: if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
566: err(1, "sysctl");
567: if ((buf = malloc(len)) == NULL)
568: err(1, NULL);
569: if (sysctl(mib, 6, buf, &len, NULL, 0) == -1)
570: err(1, "sysctl");
571:
1.63 tedu 572: memset(&ip_cur, 0, sizeof(ip_cur));
1.56 claudio 573: lim = buf + len;
574: for (next = buf; next < lim; next += rtm->rtm_msglen) {
575: rtm = (struct rt_msghdr *)next;
576: if (rtm->rtm_version != RTM_VERSION)
577: continue;
578: switch (rtm->rtm_type) {
579: case RTM_IFINFO:
580: bcopy(next, &ifm, sizeof ifm);
581: ifd = &ifm.ifm_data;
582:
583: sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
584: get_rtaddrs(ifm.ifm_addrs, sa, rti_info);
585:
586: sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP];
587: if (sdl == NULL || sdl->sdl_family != AF_LINK)
588: continue;
589: bzero(name, sizeof(name));
590: if (sdl->sdl_nlen >= IFNAMSIZ)
591: memcpy(name, sdl->sdl_data, IFNAMSIZ - 1);
592: else if (sdl->sdl_nlen > 0)
593: memcpy(name, sdl->sdl_data, sdl->sdl_nlen);
594:
1.59 claudio 595: if (interface != NULL && !strcmp(name, interface)) {
1.63 tedu 596: takeit = 1;
597: } else if (interface == NULL && foundone == 0 &&
598: isegress(name)) {
599: takeit = 1;
600: foundone = 1;
601: } else
602: takeit = 0;
603: if (takeit) {
1.56 claudio 604: strlcpy(ip_cur.ift_name, name,
605: sizeof(ip_cur.ift_name));
606: ip_cur.ift_ip = ifd->ifi_ipackets;
607: ip_cur.ift_ib = ifd->ifi_ibytes;
608: ip_cur.ift_ie = ifd->ifi_ierrors;
609: ip_cur.ift_op = ifd->ifi_opackets;
610: ip_cur.ift_ob = ifd->ifi_obytes;
611: ip_cur.ift_oe = ifd->ifi_oerrors;
612: ip_cur.ift_co = ifd->ifi_collisions;
613: ip_cur.ift_dr = 0;
614: /* XXX ifnet.if_snd.ifq_drops */
615: }
616:
617: sum_cur.ift_ip += ifd->ifi_ipackets;
618: sum_cur.ift_ib += ifd->ifi_ibytes;
619: sum_cur.ift_ie += ifd->ifi_ierrors;
620: sum_cur.ift_op += ifd->ifi_opackets;
621: sum_cur.ift_ob += ifd->ifi_obytes;
622: sum_cur.ift_oe += ifd->ifi_oerrors;
623: sum_cur.ift_co += ifd->ifi_collisions;
624: sum_cur.ift_dr += 0; /* XXX ifnet.if_snd.ifq_drops */
625: break;
626: }
627: }
1.63 tedu 628: if (interface == NULL && foundone == 0) {
1.56 claudio 629: strlcpy(ip_cur.ift_name, name,
630: sizeof(ip_cur.ift_name));
631: ip_cur.ift_ip = ifd->ifi_ipackets;
632: ip_cur.ift_ib = ifd->ifi_ibytes;
633: ip_cur.ift_ie = ifd->ifi_ierrors;
634: ip_cur.ift_op = ifd->ifi_opackets;
635: ip_cur.ift_ob = ifd->ifi_obytes;
636: ip_cur.ift_oe = ifd->ifi_oerrors;
637: ip_cur.ift_co = ifd->ifi_collisions;
638: ip_cur.ift_dr = 0;
639: /* XXX ifnet.if_snd.ifq_drops */
640: }
1.58 dhill 641: free(buf);
1.47 claudio 642: }