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