if.c revision 1.78
1/* $NetBSD: if.c,v 1.78 2013/10/19 00:28:38 christos Exp $ */ 2 3/* 4 * Copyright (c) 1983, 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33#ifndef lint 34#if 0 35static char sccsid[] = "from: @(#)if.c 8.2 (Berkeley) 2/21/94"; 36#else 37__RCSID("$NetBSD: if.c,v 1.78 2013/10/19 00:28:38 christos Exp $"); 38#endif 39#endif /* not lint */ 40 41#include <sys/param.h> 42#include <sys/types.h> 43#include <sys/protosw.h> 44#include <sys/socket.h> 45#include <sys/time.h> 46#include <sys/sysctl.h> 47 48#include <net/if.h> 49#include <net/if_dl.h> 50#include <net/if_types.h> 51#include <net/route.h> 52#include <netinet/in.h> 53#include <netinet/in_var.h> 54#include <arpa/inet.h> 55 56#include <kvm.h> 57#include <signal.h> 58#include <stdio.h> 59#include <stdlib.h> 60#include <string.h> 61#include <unistd.h> 62#include <netdb.h> 63#include <err.h> 64 65#include "netstat.h" 66#include "prog_ops.h" 67 68#define MAXIF 100 69 70#define HUMBUF_SIZE 7 71 72struct iftot { 73 char ift_name[IFNAMSIZ]; /* interface name */ 74 u_quad_t ift_ip; /* input packets */ 75 u_quad_t ift_ib; /* input bytes */ 76 u_quad_t ift_ie; /* input errors */ 77 u_quad_t ift_op; /* output packets */ 78 u_quad_t ift_ob; /* output bytes */ 79 u_quad_t ift_oe; /* output errors */ 80 u_quad_t ift_co; /* collisions */ 81 int ift_dr; /* drops */ 82}; 83 84static void print_addr(struct sockaddr *, struct sockaddr **, struct if_data *, 85 struct ifnet *); 86static void sidewaysintpr(u_int, u_long); 87 88static void iftot_banner(struct iftot *); 89static void iftot_print_sum(struct iftot *, struct iftot *); 90static void iftot_print(struct iftot *, struct iftot *); 91 92static void catchalarm __P((int)); 93static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); 94static void fetchifs(void); 95 96static void intpr_sysctl(void); 97static void intpr_kvm(u_long, void (*)(const char *)); 98 99struct iftot iftot[MAXIF], ip_cur, ip_old, sum_cur, sum_old; 100bool signalled; /* set if alarm goes off "early" */ 101 102/* 103 * Print a description of the network interfaces. 104 * NOTE: ifnetaddr is the location of the kernel global "ifnet", 105 * which is a TAILQ_HEAD. 106 */ 107void 108intpr(int interval, u_long ifnetaddr, void (*pfunc)(const char *)) 109{ 110 111 if (interval) { 112 sidewaysintpr((unsigned)interval, ifnetaddr); 113 return; 114 } 115 116 if (use_sysctl) { 117 intpr_sysctl(); 118 } else { 119 intpr_kvm(ifnetaddr, pfunc); 120 } 121 122} 123 124static void 125intpr_header(void) 126{ 127 128 if (!sflag & !pflag) { 129 if (bflag) { 130 printf("%-5.5s %-5.5s %-13.13s %-17.17s " 131 "%10.10s %10.10s", 132 "Name", "Mtu", "Network", "Address", 133 "Ibytes", "Obytes"); 134 } else { 135 printf("%-5.5s %-5.5s %-13.13s %-17.17s " 136 "%8.8s %5.5s %8.8s %5.5s %5.5s", 137 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs", 138 "Opkts", "Oerrs", "Colls"); 139 } 140 if (tflag) 141 printf(" %4.4s", "Time"); 142 if (dflag) 143 printf(" %5.5s", "Drops"); 144 putchar('\n'); 145 } 146} 147 148static void 149intpr_sysctl(void) 150{ 151 struct if_msghdr *ifm; 152 int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; 153 char *buf = NULL, *next, *lim, *cp; 154 struct rt_msghdr *rtm; 155 struct ifa_msghdr *ifam; 156 struct if_data *ifd = NULL; 157 struct sockaddr *sa, *rti_info[RTAX_MAX]; 158 struct sockaddr_dl *sdl; 159 uint64_t total = 0; 160 size_t len; 161 char name[IFNAMSIZ + 1]; /* + 1 for `*' */ 162 163 if (prog_sysctl(mib, 6, NULL, &len, NULL, 0) == -1) 164 err(1, "sysctl"); 165 if ((buf = malloc(len)) == NULL) 166 err(1, NULL); 167 if (prog_sysctl(mib, 6, buf, &len, NULL, 0) == -1) 168 err(1, "sysctl"); 169 170 intpr_header(); 171 172 lim = buf + len; 173 for (next = buf; next < lim; next += rtm->rtm_msglen) { 174 rtm = (struct rt_msghdr *)next; 175 if (rtm->rtm_version != RTM_VERSION) 176 continue; 177 switch (rtm->rtm_type) { 178 case RTM_IFINFO: 179 total = 0; 180 ifm = (struct if_msghdr *)next; 181 ifd = &ifm->ifm_data; 182 183 sa = (struct sockaddr *)(ifm + 1); 184 get_rtaddrs(ifm->ifm_addrs, sa, rti_info); 185 186 sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP]; 187 if (sdl == NULL || sdl->sdl_family != AF_LINK) { 188 continue; 189 } 190 bzero(name, sizeof(name)); 191 if (sdl->sdl_nlen >= IFNAMSIZ) 192 memcpy(name, sdl->sdl_data, IFNAMSIZ - 1); 193 else if (sdl->sdl_nlen > 0) 194 memcpy(name, sdl->sdl_data, sdl->sdl_nlen); 195 196 if (interface != 0 && strcmp(name, interface) != 0) 197 continue; 198 199 /* mark inactive interfaces with a '*' */ 200 cp = strchr(name, '\0'); 201 if ((ifm->ifm_flags & IFF_UP) == 0) 202 *cp++ = '*'; 203 *cp = '\0'; 204 205 if (qflag) { 206 total = ifd->ifi_ibytes + ifd->ifi_obytes + 207 ifd->ifi_ipackets + ifd->ifi_ierrors + 208 ifd->ifi_opackets + ifd->ifi_oerrors + 209 ifd->ifi_collisions; 210 if (tflag) 211 total += 0; // XXX-elad ifnet.if_timer; 212 if (dflag) 213 total += 0; // XXX-elad ifnet.if_snd.ifq_drops; 214 if (total == 0) 215 continue; 216 } 217 218 printf("%-5s %-5" PRIu64, name, ifd->ifi_mtu); 219 print_addr(rti_info[RTAX_IFP], rti_info, ifd, NULL); 220 break; 221 222 case RTM_NEWADDR: 223 if (qflag && total == 0) 224 continue; 225 if (interface != 0 && strcmp(name, interface) != 0) 226 continue; 227 ifam = (struct ifa_msghdr *)next; 228 if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA | 229 RTA_BRD)) == 0) 230 break; 231 232 sa = (struct sockaddr *)(ifam + 1); 233 234 get_rtaddrs(ifam->ifam_addrs, sa, rti_info); 235 236 printf("%-5s %-5" PRIu64, name, ifd->ifi_mtu); 237 print_addr(rti_info[RTAX_IFA], rti_info, ifd, NULL); 238 break; 239 } 240 } 241} 242 243union ifaddr_u { 244 struct ifaddr ifa; 245 struct in_ifaddr in; 246#ifdef INET6 247 struct in6_ifaddr in6; 248#endif /* INET6 */ 249}; 250 251static void 252intpr_kvm(u_long ifnetaddr, void (*pfunc)(const char *)) 253{ 254 struct ifnet ifnet; 255 union ifaddr_u ifaddr; 256 u_long ifaddraddr; 257 struct ifnet_head ifhead; /* TAILQ_HEAD */ 258 char name[IFNAMSIZ + 1]; /* + 1 for `*' */ 259 260 if (ifnetaddr == 0) { 261 printf("ifnet: symbol not defined\n"); 262 return; 263 } 264 265 /* 266 * Find the pointer to the first ifnet structure. Replace 267 * the pointer to the TAILQ_HEAD with the actual pointer 268 * to the first list element. 269 */ 270 if (kread(ifnetaddr, (char *)&ifhead, sizeof ifhead)) 271 return; 272 ifnetaddr = (u_long)ifhead.tqh_first; 273 274 intpr_header(); 275 276 ifaddraddr = 0; 277 while (ifnetaddr || ifaddraddr) { 278 char *cp; 279 int n; 280 281 if (ifaddraddr == 0) { 282 if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet)) 283 return; 284 memmove(name, ifnet.if_xname, IFNAMSIZ); 285 name[IFNAMSIZ - 1] = '\0'; /* sanity */ 286 ifnetaddr = (u_long)ifnet.if_list.tqe_next; 287 if (interface != 0 && strcmp(name, interface) != 0) 288 continue; 289 cp = strchr(name, '\0'); 290 291 if (pfunc) { 292 (*pfunc)(name); 293 continue; 294 } 295 296 if ((ifnet.if_flags & IFF_UP) == 0) 297 *cp++ = '*'; 298 *cp = '\0'; 299 ifaddraddr = (u_long)ifnet.if_addrlist.tqh_first; 300 } 301 if (vflag) 302 n = strlen(name) < 5 ? 5 : strlen(name); 303 else 304 n = 5; 305 printf("%-*.*s %-5llu ", n, n, name, 306 (unsigned long long)ifnet.if_mtu); 307 if (ifaddraddr == 0) { 308 printf("%-13.13s ", "none"); 309 printf("%-17.17s ", "none"); 310 } else { 311 struct sockaddr *sa; 312 313 if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) { 314 ifaddraddr = 0; 315 continue; 316 } 317#define CP(x) ((char *)(x)) 318 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) + 319 CP(&ifaddr); 320 sa = (struct sockaddr *)cp; 321 print_addr(sa, (void *)&ifaddr, &ifnet.if_data, &ifnet); 322 } 323 ifaddraddr = (u_long)ifaddr.ifa.ifa_list.tqe_next; 324 } 325 326} 327 328static void 329print_addr(struct sockaddr *sa, struct sockaddr **rtinfo, struct if_data *ifd, 330 struct ifnet *ifnet) 331{ 332 char hexsep = '.'; /* for hexprint */ 333 static const char hexfmt[] = "%02x%c"; /* for hexprint */ 334 char hbuf[NI_MAXHOST]; /* for getnameinfo() */ 335#ifdef INET6 336 const int niflag = NI_NUMERICHOST; 337 struct sockaddr_in6 *sin6, *netmask6; 338#endif 339 in_addr_t netmask; 340 struct sockaddr_in *sin; 341 char *cp; 342 int n, m; 343 344 switch (sa->sa_family) { 345 case AF_UNSPEC: 346 printf("%-13.13s ", "none"); 347 printf("%-17.17s ", "none"); 348 break; 349 case AF_INET: 350 sin = (struct sockaddr_in *)sa; 351#ifdef notdef 352 /* 353 * can't use inet_makeaddr because kernel 354 * keeps nets unshifted. 355 */ 356 in = inet_makeaddr(ifaddr.in.ia_subnet, 357 INADDR_ANY); 358 cp = netname4(in.s_addr, 359 ifaddr.in.ia_subnetmask); 360#else 361 if (use_sysctl) { 362 netmask = ((struct sockaddr_in *)rtinfo[RTAX_NETMASK])->sin_addr.s_addr; 363 } else { 364 struct in_ifaddr *ifaddr_in = (void *)rtinfo; 365 netmask = ifaddr_in->ia_subnetmask; 366 } 367 cp = netname4(sin->sin_addr.s_addr, netmask); 368#endif 369 if (vflag) 370 n = strlen(cp) < 13 ? 13 : strlen(cp); 371 else 372 n = 13; 373 printf("%-*.*s ", n, n, cp); 374 cp = routename4(sin->sin_addr.s_addr); 375 if (vflag) 376 n = strlen(cp) < 17 ? 17 : strlen(cp); 377 else 378 n = 17; 379 printf("%-*.*s ", n, n, cp); 380 381 if (aflag && ifnet) { 382 u_long multiaddr; 383 struct in_multi inm; 384 union ifaddr_u *ifaddr = (union ifaddr_u *)rtinfo; 385 386 multiaddr = (u_long) 387 ifaddr->in.ia_multiaddrs.lh_first; 388 while (multiaddr != 0) { 389 kread(multiaddr, (char *)&inm, 390 sizeof inm); 391 printf("\n%25s %-17.17s ", "", 392 routename4( 393 inm.inm_addr.s_addr)); 394 multiaddr = 395 (u_long)inm.inm_list.le_next; 396 } 397 } 398 break; 399#ifdef INET6 400 case AF_INET6: 401 sin6 = (struct sockaddr_in6 *)sa; 402 inet6_putscopeid(sin6, 1); 403#ifdef __KAME__ 404 if (!vflag) 405 sin6->sin6_scope_id = 0; 406#endif 407 408 if (use_sysctl) { 409 netmask6 = (struct sockaddr_in6 *)rtinfo[RTAX_NETMASK]; 410 } else { 411 struct in6_ifaddr *ifaddr_in6 = (void *)rtinfo; 412 netmask6 = &ifaddr_in6->ia_prefixmask; 413 } 414 415 cp = netname6(sin6, netmask6); 416 if (vflag) 417 n = strlen(cp) < 13 ? 13 : strlen(cp); 418 else 419 n = 13; 420 printf("%-*.*s ", n, n, cp); 421 if (getnameinfo((struct sockaddr *)sin6, 422 sin6->sin6_len, 423 hbuf, sizeof(hbuf), NULL, 0, 424 niflag) != 0) { 425 strlcpy(hbuf, "?", sizeof(hbuf)); 426 } 427 cp = hbuf; 428 if (vflag) 429 n = strlen(cp) < 17 ? 17 : strlen(cp); 430 else 431 n = 17; 432 printf("%-*.*s ", n, n, cp); 433 434 if (aflag && ifnet) { 435 u_long multiaddr; 436 struct in6_multi inm; 437 struct sockaddr_in6 as6; 438 union ifaddr_u *ifaddr = (union ifaddr_u *)rtinfo; 439 440 multiaddr = (u_long) 441 ifaddr->in6.ia6_multiaddrs.lh_first; 442 while (multiaddr != 0) { 443 kread(multiaddr, (char *)&inm, 444 sizeof inm); 445 memset(&as6, 0, sizeof(as6)); 446 as6.sin6_len = sizeof(struct sockaddr_in6); 447 as6.sin6_family = AF_INET6; 448 as6.sin6_addr = inm.in6m_addr; 449 inet6_putscopeid(&as6, 2); 450 if (getnameinfo((struct sockaddr *)&as6, 451 as6.sin6_len, hbuf, 452 sizeof(hbuf), NULL, 0, 453 niflag) != 0) { 454 strlcpy(hbuf, "??", 455 sizeof(hbuf)); 456 } 457 cp = hbuf; 458 if (vflag) 459 n = strlen(cp) < 17 460 ? 17 : strlen(cp); 461 else 462 n = 17; 463 printf("\n%25s %-*.*s ", "", 464 n, n, cp); 465 multiaddr = 466 (u_long)inm.in6m_entry.le_next; 467 } 468 } 469 break; 470#endif /*INET6*/ 471#ifndef SMALL 472 case AF_APPLETALK: 473 printf("atalk:%-7.7s ", 474 atalk_print(sa,0x10)); 475 printf("%-17.17s ", atalk_print(sa,0x0b)); 476 break; 477#endif 478 case AF_LINK: 479 printf("%-13.13s ", "<Link>"); 480 if (getnameinfo(sa, sa->sa_len, 481 hbuf, sizeof(hbuf), NULL, 0, 482 NI_NUMERICHOST) != 0) { 483 strlcpy(hbuf, "?", sizeof(hbuf)); 484 } 485 cp = hbuf; 486 if (vflag) 487 n = strlen(cp) < 17 ? 17 : strlen(cp); 488 else 489 n = 17; 490 printf("%-*.*s ", n, n, cp); 491 break; 492 493 default: 494 m = printf("(%d)", sa->sa_family); 495 for (cp = sa->sa_len + (char *)sa; 496 --cp > sa->sa_data && (*cp == 0);) {} 497 n = cp - sa->sa_data + 1; 498 cp = sa->sa_data; 499 500 while (--n >= 0) 501 m += printf(hexfmt, *cp++ & 0xff, 502 n > 0 ? hexsep : ' '); 503 m = 32 - m; 504 while (m-- > 0) 505 putchar(' '); 506 break; 507 } 508 509 if (bflag) { 510 char humbuf[HUMBUF_SIZE]; 511 512 if (hflag && humanize_number(humbuf, sizeof(humbuf), 513 ifd->ifi_ibytes, "", HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0) 514 printf("%10s ", humbuf); 515 else 516 printf("%10llu ", (unsigned long long)ifd->ifi_ibytes); 517 518 if (hflag && humanize_number(humbuf, sizeof(humbuf), 519 ifd->ifi_obytes, "", HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0) 520 printf("%10s", humbuf); 521 else 522 printf("%10llu", (unsigned long long)ifd->ifi_obytes); 523 } else { 524 printf("%8llu %5llu %8llu %5llu %5llu", 525 (unsigned long long)ifd->ifi_ipackets, 526 (unsigned long long)ifd->ifi_ierrors, 527 (unsigned long long)ifd->ifi_opackets, 528 (unsigned long long)ifd->ifi_oerrors, 529 (unsigned long long)ifd->ifi_collisions); 530 } 531 if (tflag) 532 printf(" %4d", ifnet ? ifnet->if_timer : 0); 533 if (dflag) 534 printf(" %5d", ifnet ? ifnet->if_snd.ifq_drops : 0); 535 putchar('\n'); 536} 537 538static void 539iftot_banner(struct iftot *ift) 540{ 541 if (bflag) 542 printf("%7.7s in %8.8s %6.6s out %5.5s", 543 ift->ift_name, " ", 544 ift->ift_name, " "); 545 else 546 printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s", 547 ift->ift_name, " ", 548 ift->ift_name, " ", " "); 549 if (dflag) 550 printf(" %5.5s", " "); 551 552 if (bflag) 553 printf(" %7.7s in %8.8s %6.6s out %5.5s", 554 "total", " ", "total", " "); 555 else 556 printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s", 557 "total", " ", "total", " ", " "); 558 if (dflag) 559 printf(" %5.5s", " "); 560 putchar('\n'); 561 if (bflag) 562 printf("%10.10s %8.8s %10.10s %5.5s", 563 "bytes", " ", "bytes", " "); 564 else 565 printf("%8.8s %5.5s %8.8s %5.5s %5.5s", 566 "packets", "errs", "packets", "errs", "colls"); 567 if (dflag) 568 printf(" %5.5s", "drops"); 569 570 if (bflag) 571 printf(" %10.10s %8.8s %10.10s %5.5s", 572 "bytes", " ", "bytes", " "); 573 else 574 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s", 575 "packets", "errs", "packets", "errs", "colls"); 576 if (dflag) 577 printf(" %5.5s", "drops"); 578 putchar('\n'); 579 fflush(stdout); 580} 581 582static void 583iftot_print(struct iftot *cur, struct iftot *old) 584{ 585 if (bflag) 586 printf("%10" PRIu64 " %8.8s %10" PRIu64 " %5.5s", 587 cur->ift_ib - old->ift_ib, " ", 588 cur->ift_ob - old->ift_ob, " "); 589 else 590 printf("%8" PRIu64 " %5" PRIu64 " %8" PRIu64 " %5" PRIu64 " %5" PRIu64, 591 cur->ift_ip - old->ift_ip, 592 cur->ift_ie - old->ift_ie, 593 cur->ift_op - old->ift_op, 594 cur->ift_oe - old->ift_oe, 595 cur->ift_co - old->ift_co); 596 if (dflag) 597 printf(" %5llu", 598 /* XXX ifnet.if_snd.ifq_drops - ip->ift_dr); */ 599 0LL); 600} 601 602static void 603iftot_print_sum(struct iftot *cur, struct iftot *old) 604{ 605 if (bflag) 606 printf(" %10" PRIu64 " %8.8s %10" PRIu64 " %5.5s", 607 cur->ift_ib - old->ift_ib, " ", 608 cur->ift_ob - old->ift_ob, " "); 609 else 610 printf(" %8" PRIu64 " %5" PRIu64 " %8" PRIu64 " %5" PRIu64 " %5" PRIu64, 611 cur->ift_ip - old->ift_ip, 612 cur->ift_ie - old->ift_ie, 613 cur->ift_op - old->ift_op, 614 cur->ift_oe - old->ift_oe, 615 cur->ift_co - old->ift_co); 616 617 if (dflag) 618 printf(" %5llu", (unsigned long long)(cur->ift_dr - old->ift_dr)); 619} 620 621__dead static void 622sidewaysintpr_sysctl(unsigned interval) 623{ 624 sigset_t emptyset; 625 int line; 626 627 fetchifs(); 628 if (ip_cur.ift_name[0] == '\0') { 629 fprintf(stderr, "%s: %s: unknown interface\n", 630 getprogname(), interface); 631 exit(1); 632 } 633 634 (void)signal(SIGALRM, catchalarm); 635 signalled = 0; 636 (void)alarm(interval); 637banner: 638 iftot_banner(&ip_cur); 639 640 line = 0; 641 bzero(&ip_old, sizeof(ip_old)); 642 bzero(&sum_old, sizeof(sum_old)); 643loop: 644 bzero(&sum_cur, sizeof(sum_cur)); 645 646 fetchifs(); 647 648 iftot_print(&ip_cur, &ip_old); 649 650 ip_old = ip_cur; 651 652 iftot_print_sum(&sum_cur, &sum_old); 653 654 sum_old = sum_cur; 655 656 putchar('\n'); 657 fflush(stdout); 658 line++; 659 sigemptyset(&emptyset); 660 if (!signalled) 661 sigsuspend(&emptyset); 662 signalled = 0; 663 (void)alarm(interval); 664 if (line == 21) 665 goto banner; 666 goto loop; 667 /*NOTREACHED*/ 668} 669 670static void 671sidewaysintpr_kvm(unsigned interval, u_long off) 672{ 673 struct itimerval it; 674 struct ifnet ifnet; 675 u_long firstifnet; 676 struct iftot *ip, *total; 677 int line; 678 struct iftot *lastif, *sum, *interesting; 679 struct ifnet_head ifhead; /* TAILQ_HEAD */ 680 int oldmask; 681 682 /* 683 * Find the pointer to the first ifnet structure. Replace 684 * the pointer to the TAILQ_HEAD with the actual pointer 685 * to the first list element. 686 */ 687 if (kread(off, (char *)&ifhead, sizeof ifhead)) 688 return; 689 firstifnet = (u_long)ifhead.tqh_first; 690 691 lastif = iftot; 692 sum = iftot + MAXIF - 1; 693 total = sum - 1; 694 interesting = (interface == NULL) ? iftot : NULL; 695 for (off = firstifnet, ip = iftot; off;) { 696 if (kread(off, (char *)&ifnet, sizeof ifnet)) 697 break; 698 memset(ip->ift_name, 0, sizeof(ip->ift_name)); 699 snprintf(ip->ift_name, IFNAMSIZ, "%s", ifnet.if_xname); 700 if (interface && strcmp(ifnet.if_xname, interface) == 0) 701 interesting = ip; 702 ip++; 703 if (ip >= iftot + MAXIF - 2) 704 break; 705 off = (u_long)ifnet.if_list.tqe_next; 706 } 707 if (interesting == NULL) { 708 fprintf(stderr, "%s: %s: unknown interface\n", 709 getprogname(), interface); 710 exit(1); 711 } 712 lastif = ip; 713 714 (void)signal(SIGALRM, catchalarm); 715 signalled = false; 716 717 it.it_interval.tv_sec = it.it_value.tv_sec = interval; 718 it.it_interval.tv_usec = it.it_value.tv_usec = 0; 719 setitimer(ITIMER_REAL, &it, NULL); 720 721banner: 722 if (bflag) 723 printf("%7.7s in %8.8s %6.6s out %5.5s", 724 interesting->ift_name, " ", 725 interesting->ift_name, " "); 726 else 727 printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s", 728 interesting->ift_name, " ", 729 interesting->ift_name, " ", " "); 730 if (dflag) 731 printf(" %5.5s", " "); 732 if (lastif - iftot > 0) { 733 if (bflag) 734 printf(" %7.7s in %8.8s %6.6s out %5.5s", 735 "total", " ", "total", " "); 736 else 737 printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s", 738 "total", " ", "total", " ", " "); 739 if (dflag) 740 printf(" %5.5s", " "); 741 } 742 for (ip = iftot; ip < iftot + MAXIF; ip++) { 743 ip->ift_ip = 0; 744 ip->ift_ib = 0; 745 ip->ift_ie = 0; 746 ip->ift_op = 0; 747 ip->ift_ob = 0; 748 ip->ift_oe = 0; 749 ip->ift_co = 0; 750 ip->ift_dr = 0; 751 } 752 putchar('\n'); 753 if (bflag) 754 printf("%10.10s %8.8s %10.10s %5.5s", 755 "bytes", " ", "bytes", " "); 756 else 757 printf("%8.8s %5.5s %8.8s %5.5s %5.5s", 758 "packets", "errs", "packets", "errs", "colls"); 759 if (dflag) 760 printf(" %5.5s", "drops"); 761 if (lastif - iftot > 0) { 762 if (bflag) 763 printf(" %10.10s %8.8s %10.10s %5.5s", 764 "bytes", " ", "bytes", " "); 765 else 766 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s", 767 "packets", "errs", "packets", "errs", "colls"); 768 if (dflag) 769 printf(" %5.5s", "drops"); 770 } 771 putchar('\n'); 772 fflush(stdout); 773 line = 0; 774loop: 775 sum->ift_ip = 0; 776 sum->ift_ib = 0; 777 sum->ift_ie = 0; 778 sum->ift_op = 0; 779 sum->ift_ob = 0; 780 sum->ift_oe = 0; 781 sum->ift_co = 0; 782 sum->ift_dr = 0; 783 for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) { 784 if (kread(off, (char *)&ifnet, sizeof ifnet)) { 785 off = 0; 786 continue; 787 } 788 if (ip == interesting) { 789 if (bflag) { 790 char humbuf[HUMBUF_SIZE]; 791 792 if (hflag && humanize_number(humbuf, 793 sizeof(humbuf), 794 ifnet.if_ibytes - ip->ift_ib, "", 795 HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0) 796 printf("%10s %8.8s ", humbuf, " "); 797 else 798 printf("%10llu %8.8s ", 799 (unsigned long long) 800 (ifnet.if_ibytes-ip->ift_ib), " "); 801 802 if (hflag && humanize_number(humbuf, 803 sizeof(humbuf), 804 ifnet.if_obytes - ip->ift_ob, "", 805 HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0) 806 printf("%10s %5.5s", humbuf, " "); 807 else 808 printf("%10llu %5.5s", 809 (unsigned long long) 810 (ifnet.if_obytes-ip->ift_ob), " "); 811 } else { 812 printf("%8llu %5llu %8llu %5llu %5llu", 813 (unsigned long long) 814 (ifnet.if_ipackets - ip->ift_ip), 815 (unsigned long long) 816 (ifnet.if_ierrors - ip->ift_ie), 817 (unsigned long long) 818 (ifnet.if_opackets - ip->ift_op), 819 (unsigned long long) 820 (ifnet.if_oerrors - ip->ift_oe), 821 (unsigned long long) 822 (ifnet.if_collisions - ip->ift_co)); 823 } 824 if (dflag) 825 printf(" %5llu", 826 (unsigned long long) 827 (ifnet.if_snd.ifq_drops - ip->ift_dr)); 828 } 829 ip->ift_ip = ifnet.if_ipackets; 830 ip->ift_ib = ifnet.if_ibytes; 831 ip->ift_ie = ifnet.if_ierrors; 832 ip->ift_op = ifnet.if_opackets; 833 ip->ift_ob = ifnet.if_obytes; 834 ip->ift_oe = ifnet.if_oerrors; 835 ip->ift_co = ifnet.if_collisions; 836 ip->ift_dr = ifnet.if_snd.ifq_drops; 837 sum->ift_ip += ip->ift_ip; 838 sum->ift_ib += ip->ift_ib; 839 sum->ift_ie += ip->ift_ie; 840 sum->ift_op += ip->ift_op; 841 sum->ift_ob += ip->ift_ob; 842 sum->ift_oe += ip->ift_oe; 843 sum->ift_co += ip->ift_co; 844 sum->ift_dr += ip->ift_dr; 845 off = (u_long)ifnet.if_list.tqe_next; 846 } 847 if (lastif - iftot > 0) { 848 if (bflag) { 849 char humbuf[HUMBUF_SIZE]; 850 851 if (hflag && humanize_number(humbuf, 852 sizeof(humbuf), sum->ift_ib - total->ift_ib, "", 853 HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0) 854 printf(" %10s %8.8s ", humbuf, " "); 855 else 856 printf(" %10llu %8.8s ", 857 (unsigned long long) 858 (sum->ift_ib - total->ift_ib), " "); 859 860 if (hflag && humanize_number(humbuf, 861 sizeof(humbuf), sum->ift_ob - total->ift_ob, "", 862 HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0) 863 printf("%10s %5.5s", humbuf, " "); 864 else 865 printf("%10llu %5.5s", 866 (unsigned long long) 867 (sum->ift_ob - total->ift_ob), " "); 868 } else { 869 printf(" %8llu %5llu %8llu %5llu %5llu", 870 (unsigned long long) 871 (sum->ift_ip - total->ift_ip), 872 (unsigned long long) 873 (sum->ift_ie - total->ift_ie), 874 (unsigned long long) 875 (sum->ift_op - total->ift_op), 876 (unsigned long long) 877 (sum->ift_oe - total->ift_oe), 878 (unsigned long long) 879 (sum->ift_co - total->ift_co)); 880 } 881 if (dflag) 882 printf(" %5llu", 883 (unsigned long long)(sum->ift_dr - total->ift_dr)); 884 } 885 *total = *sum; 886 putchar('\n'); 887 fflush(stdout); 888 line++; 889 oldmask = sigblock(sigmask(SIGALRM)); 890 if (! signalled) { 891 sigpause(0); 892 } 893 sigsetmask(oldmask); 894 signalled = false; 895 if (line == 21) 896 goto banner; 897 goto loop; 898 /*NOTREACHED*/ 899} 900 901/* 902 * Print a running summary of interface statistics. 903 * Repeat display every interval seconds, showing statistics 904 * collected over that interval. Assumes that interval is non-zero. 905 * First line printed at top of screen is always cumulative. 906 */ 907static void 908sidewaysintpr(unsigned int interval, u_long off) 909{ 910 911 if (use_sysctl) { 912 sidewaysintpr_sysctl(interval); 913 } else { 914 sidewaysintpr_kvm(interval, off); 915 } 916} 917 918/* 919 * Called if an interval expires before sidewaysintpr has completed a loop. 920 * Sets a flag to not wait for the alarm. 921 */ 922static void 923catchalarm(int signo) 924{ 925 926 signalled = true; 927} 928 929static void 930get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 931{ 932 int i; 933 934 for (i = 0; i < RTAX_MAX; i++) { 935 if (addrs & (1 << i)) { 936 rti_info[i] = sa; 937 sa = (struct sockaddr *)((char *)(sa) + 938 RT_ROUNDUP(sa->sa_len)); 939 } else 940 rti_info[i] = NULL; 941 } 942} 943 944static void 945fetchifs(void) 946{ 947 struct if_msghdr *ifm; 948 int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; 949 struct rt_msghdr *rtm; 950 struct if_data *ifd = NULL; 951 struct sockaddr *sa, *rti_info[RTAX_MAX]; 952 struct sockaddr_dl *sdl; 953 char *buf, *next, *lim; 954 char name[IFNAMSIZ]; 955 size_t len; 956 957 if (prog_sysctl(mib, 6, NULL, &len, NULL, 0) == -1) 958 err(1, "sysctl"); 959 if ((buf = malloc(len)) == NULL) 960 err(1, NULL); 961 if (prog_sysctl(mib, 6, buf, &len, NULL, 0) == -1) 962 err(1, "sysctl"); 963 964 lim = buf + len; 965 for (next = buf; next < lim; next += rtm->rtm_msglen) { 966 rtm = (struct rt_msghdr *)next; 967 if (rtm->rtm_version != RTM_VERSION) 968 continue; 969 switch (rtm->rtm_type) { 970 case RTM_IFINFO: 971 ifm = (struct if_msghdr *)next; 972 ifd = &ifm->ifm_data; 973 974 sa = (struct sockaddr *)(ifm + 1); 975 get_rtaddrs(ifm->ifm_addrs, sa, rti_info); 976 977 sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP]; 978 if (sdl == NULL || sdl->sdl_family != AF_LINK) 979 continue; 980 bzero(name, sizeof(name)); 981 if (sdl->sdl_nlen >= IFNAMSIZ) 982 memcpy(name, sdl->sdl_data, IFNAMSIZ - 1); 983 else if (sdl->sdl_nlen > 0) 984 memcpy(name, sdl->sdl_data, sdl->sdl_nlen); 985 986 if (interface != 0 && !strcmp(name, interface)) { 987 strlcpy(ip_cur.ift_name, name, 988 sizeof(ip_cur.ift_name)); 989 ip_cur.ift_ip = ifd->ifi_ipackets; 990 ip_cur.ift_ib = ifd->ifi_ibytes; 991 ip_cur.ift_ie = ifd->ifi_ierrors; 992 ip_cur.ift_op = ifd->ifi_opackets; 993 ip_cur.ift_ob = ifd->ifi_obytes; 994 ip_cur.ift_oe = ifd->ifi_oerrors; 995 ip_cur.ift_co = ifd->ifi_collisions; 996 ip_cur.ift_dr = 0; 997 /* XXX-elad ifnet.if_snd.ifq_drops */ 998 } 999 1000 sum_cur.ift_ip += ifd->ifi_ipackets; 1001 sum_cur.ift_ib += ifd->ifi_ibytes; 1002 sum_cur.ift_ie += ifd->ifi_ierrors; 1003 sum_cur.ift_op += ifd->ifi_opackets; 1004 sum_cur.ift_ob += ifd->ifi_obytes; 1005 sum_cur.ift_oe += ifd->ifi_oerrors; 1006 sum_cur.ift_co += ifd->ifi_collisions; 1007 sum_cur.ift_dr += 0; /* XXX-elad ifnet.if_snd.ifq_drops */ 1008 break; 1009 } 1010 } 1011 if (interface == NULL) { 1012 strlcpy(ip_cur.ift_name, name, 1013 sizeof(ip_cur.ift_name)); 1014 ip_cur.ift_ip = ifd->ifi_ipackets; 1015 ip_cur.ift_ib = ifd->ifi_ibytes; 1016 ip_cur.ift_ie = ifd->ifi_ierrors; 1017 ip_cur.ift_op = ifd->ifi_opackets; 1018 ip_cur.ift_ob = ifd->ifi_obytes; 1019 ip_cur.ift_oe = ifd->ifi_oerrors; 1020 ip_cur.ift_co = ifd->ifi_collisions; 1021 ip_cur.ift_dr = 0; 1022 /* XXX-elad ifnet.if_snd.ifq_drops */ 1023 } 1024} 1025