1 /* $NetBSD: if.c,v 1.79 2013/10/19 15:56:06 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.79 2013/10/19 15:56:06 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 72 struct 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 84 static void print_addr(struct sockaddr *, struct sockaddr **, struct if_data *, 85 struct ifnet *); 86 static void sidewaysintpr(u_int, u_long); 87 88 static void iftot_banner(struct iftot *); 89 static void iftot_print_sum(struct iftot *, struct iftot *); 90 static void iftot_print(struct iftot *, struct iftot *); 91 92 static void catchalarm __P((int)); 93 static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); 94 static void fetchifs(void); 95 96 static void intpr_sysctl(void); 97 static void intpr_kvm(u_long, void (*)(const char *)); 98 99 struct iftot iftot[MAXIF], ip_cur, ip_old, sum_cur, sum_old; 100 bool 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 */ 107 void 108 intpr(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 124 static void 125 intpr_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 148 static void 149 intpr_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 243 union ifaddr_u { 244 struct ifaddr ifa; 245 struct in_ifaddr in; 246 #ifdef INET6 247 struct in6_ifaddr in6; 248 #endif /* INET6 */ 249 }; 250 251 static void 252 intpr_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 328 static void 329 print_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_getscopeid(sin6, INET6_IS_ADDR_LINKLOCAL); 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_getscopeid(&as6, 450 INET6_IS_ADDR_MC_LINKLOCAL); 451 if (getnameinfo((struct sockaddr *)&as6, 452 as6.sin6_len, hbuf, 453 sizeof(hbuf), NULL, 0, 454 niflag) != 0) { 455 strlcpy(hbuf, "??", 456 sizeof(hbuf)); 457 } 458 cp = hbuf; 459 if (vflag) 460 n = strlen(cp) < 17 461 ? 17 : strlen(cp); 462 else 463 n = 17; 464 printf("\n%25s %-*.*s ", "", 465 n, n, cp); 466 multiaddr = 467 (u_long)inm.in6m_entry.le_next; 468 } 469 } 470 break; 471 #endif /*INET6*/ 472 #ifndef SMALL 473 case AF_APPLETALK: 474 printf("atalk:%-7.7s ", 475 atalk_print(sa,0x10)); 476 printf("%-17.17s ", atalk_print(sa,0x0b)); 477 break; 478 #endif 479 case AF_LINK: 480 printf("%-13.13s ", "<Link>"); 481 if (getnameinfo(sa, sa->sa_len, 482 hbuf, sizeof(hbuf), NULL, 0, 483 NI_NUMERICHOST) != 0) { 484 strlcpy(hbuf, "?", sizeof(hbuf)); 485 } 486 cp = hbuf; 487 if (vflag) 488 n = strlen(cp) < 17 ? 17 : strlen(cp); 489 else 490 n = 17; 491 printf("%-*.*s ", n, n, cp); 492 break; 493 494 default: 495 m = printf("(%d)", sa->sa_family); 496 for (cp = sa->sa_len + (char *)sa; 497 --cp > sa->sa_data && (*cp == 0);) {} 498 n = cp - sa->sa_data + 1; 499 cp = sa->sa_data; 500 501 while (--n >= 0) 502 m += printf(hexfmt, *cp++ & 0xff, 503 n > 0 ? hexsep : ' '); 504 m = 32 - m; 505 while (m-- > 0) 506 putchar(' '); 507 break; 508 } 509 510 if (bflag) { 511 char humbuf[HUMBUF_SIZE]; 512 513 if (hflag && humanize_number(humbuf, sizeof(humbuf), 514 ifd->ifi_ibytes, "", HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0) 515 printf("%10s ", humbuf); 516 else 517 printf("%10llu ", (unsigned long long)ifd->ifi_ibytes); 518 519 if (hflag && humanize_number(humbuf, sizeof(humbuf), 520 ifd->ifi_obytes, "", HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0) 521 printf("%10s", humbuf); 522 else 523 printf("%10llu", (unsigned long long)ifd->ifi_obytes); 524 } else { 525 printf("%8llu %5llu %8llu %5llu %5llu", 526 (unsigned long long)ifd->ifi_ipackets, 527 (unsigned long long)ifd->ifi_ierrors, 528 (unsigned long long)ifd->ifi_opackets, 529 (unsigned long long)ifd->ifi_oerrors, 530 (unsigned long long)ifd->ifi_collisions); 531 } 532 if (tflag) 533 printf(" %4d", ifnet ? ifnet->if_timer : 0); 534 if (dflag) 535 printf(" %5d", ifnet ? ifnet->if_snd.ifq_drops : 0); 536 putchar('\n'); 537 } 538 539 static void 540 iftot_banner(struct iftot *ift) 541 { 542 if (bflag) 543 printf("%7.7s in %8.8s %6.6s out %5.5s", 544 ift->ift_name, " ", 545 ift->ift_name, " "); 546 else 547 printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s", 548 ift->ift_name, " ", 549 ift->ift_name, " ", " "); 550 if (dflag) 551 printf(" %5.5s", " "); 552 553 if (bflag) 554 printf(" %7.7s in %8.8s %6.6s out %5.5s", 555 "total", " ", "total", " "); 556 else 557 printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s", 558 "total", " ", "total", " ", " "); 559 if (dflag) 560 printf(" %5.5s", " "); 561 putchar('\n'); 562 if (bflag) 563 printf("%10.10s %8.8s %10.10s %5.5s", 564 "bytes", " ", "bytes", " "); 565 else 566 printf("%8.8s %5.5s %8.8s %5.5s %5.5s", 567 "packets", "errs", "packets", "errs", "colls"); 568 if (dflag) 569 printf(" %5.5s", "drops"); 570 571 if (bflag) 572 printf(" %10.10s %8.8s %10.10s %5.5s", 573 "bytes", " ", "bytes", " "); 574 else 575 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s", 576 "packets", "errs", "packets", "errs", "colls"); 577 if (dflag) 578 printf(" %5.5s", "drops"); 579 putchar('\n'); 580 fflush(stdout); 581 } 582 583 static void 584 iftot_print(struct iftot *cur, struct iftot *old) 585 { 586 if (bflag) 587 printf("%10" PRIu64 " %8.8s %10" PRIu64 " %5.5s", 588 cur->ift_ib - old->ift_ib, " ", 589 cur->ift_ob - old->ift_ob, " "); 590 else 591 printf("%8" PRIu64 " %5" PRIu64 " %8" PRIu64 " %5" PRIu64 " %5" PRIu64, 592 cur->ift_ip - old->ift_ip, 593 cur->ift_ie - old->ift_ie, 594 cur->ift_op - old->ift_op, 595 cur->ift_oe - old->ift_oe, 596 cur->ift_co - old->ift_co); 597 if (dflag) 598 printf(" %5llu", 599 /* XXX ifnet.if_snd.ifq_drops - ip->ift_dr); */ 600 0LL); 601 } 602 603 static void 604 iftot_print_sum(struct iftot *cur, struct iftot *old) 605 { 606 if (bflag) 607 printf(" %10" PRIu64 " %8.8s %10" PRIu64 " %5.5s", 608 cur->ift_ib - old->ift_ib, " ", 609 cur->ift_ob - old->ift_ob, " "); 610 else 611 printf(" %8" PRIu64 " %5" PRIu64 " %8" PRIu64 " %5" PRIu64 " %5" PRIu64, 612 cur->ift_ip - old->ift_ip, 613 cur->ift_ie - old->ift_ie, 614 cur->ift_op - old->ift_op, 615 cur->ift_oe - old->ift_oe, 616 cur->ift_co - old->ift_co); 617 618 if (dflag) 619 printf(" %5llu", (unsigned long long)(cur->ift_dr - old->ift_dr)); 620 } 621 622 __dead static void 623 sidewaysintpr_sysctl(unsigned interval) 624 { 625 sigset_t emptyset; 626 int line; 627 628 fetchifs(); 629 if (ip_cur.ift_name[0] == '\0') { 630 fprintf(stderr, "%s: %s: unknown interface\n", 631 getprogname(), interface); 632 exit(1); 633 } 634 635 (void)signal(SIGALRM, catchalarm); 636 signalled = 0; 637 (void)alarm(interval); 638 banner: 639 iftot_banner(&ip_cur); 640 641 line = 0; 642 bzero(&ip_old, sizeof(ip_old)); 643 bzero(&sum_old, sizeof(sum_old)); 644 loop: 645 bzero(&sum_cur, sizeof(sum_cur)); 646 647 fetchifs(); 648 649 iftot_print(&ip_cur, &ip_old); 650 651 ip_old = ip_cur; 652 653 iftot_print_sum(&sum_cur, &sum_old); 654 655 sum_old = sum_cur; 656 657 putchar('\n'); 658 fflush(stdout); 659 line++; 660 sigemptyset(&emptyset); 661 if (!signalled) 662 sigsuspend(&emptyset); 663 signalled = 0; 664 (void)alarm(interval); 665 if (line == 21) 666 goto banner; 667 goto loop; 668 /*NOTREACHED*/ 669 } 670 671 static void 672 sidewaysintpr_kvm(unsigned interval, u_long off) 673 { 674 struct itimerval it; 675 struct ifnet ifnet; 676 u_long firstifnet; 677 struct iftot *ip, *total; 678 int line; 679 struct iftot *lastif, *sum, *interesting; 680 struct ifnet_head ifhead; /* TAILQ_HEAD */ 681 int oldmask; 682 683 /* 684 * Find the pointer to the first ifnet structure. Replace 685 * the pointer to the TAILQ_HEAD with the actual pointer 686 * to the first list element. 687 */ 688 if (kread(off, (char *)&ifhead, sizeof ifhead)) 689 return; 690 firstifnet = (u_long)ifhead.tqh_first; 691 692 lastif = iftot; 693 sum = iftot + MAXIF - 1; 694 total = sum - 1; 695 interesting = (interface == NULL) ? iftot : NULL; 696 for (off = firstifnet, ip = iftot; off;) { 697 if (kread(off, (char *)&ifnet, sizeof ifnet)) 698 break; 699 memset(ip->ift_name, 0, sizeof(ip->ift_name)); 700 snprintf(ip->ift_name, IFNAMSIZ, "%s", ifnet.if_xname); 701 if (interface && strcmp(ifnet.if_xname, interface) == 0) 702 interesting = ip; 703 ip++; 704 if (ip >= iftot + MAXIF - 2) 705 break; 706 off = (u_long)ifnet.if_list.tqe_next; 707 } 708 if (interesting == NULL) { 709 fprintf(stderr, "%s: %s: unknown interface\n", 710 getprogname(), interface); 711 exit(1); 712 } 713 lastif = ip; 714 715 (void)signal(SIGALRM, catchalarm); 716 signalled = false; 717 718 it.it_interval.tv_sec = it.it_value.tv_sec = interval; 719 it.it_interval.tv_usec = it.it_value.tv_usec = 0; 720 setitimer(ITIMER_REAL, &it, NULL); 721 722 banner: 723 if (bflag) 724 printf("%7.7s in %8.8s %6.6s out %5.5s", 725 interesting->ift_name, " ", 726 interesting->ift_name, " "); 727 else 728 printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s", 729 interesting->ift_name, " ", 730 interesting->ift_name, " ", " "); 731 if (dflag) 732 printf(" %5.5s", " "); 733 if (lastif - iftot > 0) { 734 if (bflag) 735 printf(" %7.7s in %8.8s %6.6s out %5.5s", 736 "total", " ", "total", " "); 737 else 738 printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s", 739 "total", " ", "total", " ", " "); 740 if (dflag) 741 printf(" %5.5s", " "); 742 } 743 for (ip = iftot; ip < iftot + MAXIF; ip++) { 744 ip->ift_ip = 0; 745 ip->ift_ib = 0; 746 ip->ift_ie = 0; 747 ip->ift_op = 0; 748 ip->ift_ob = 0; 749 ip->ift_oe = 0; 750 ip->ift_co = 0; 751 ip->ift_dr = 0; 752 } 753 putchar('\n'); 754 if (bflag) 755 printf("%10.10s %8.8s %10.10s %5.5s", 756 "bytes", " ", "bytes", " "); 757 else 758 printf("%8.8s %5.5s %8.8s %5.5s %5.5s", 759 "packets", "errs", "packets", "errs", "colls"); 760 if (dflag) 761 printf(" %5.5s", "drops"); 762 if (lastif - iftot > 0) { 763 if (bflag) 764 printf(" %10.10s %8.8s %10.10s %5.5s", 765 "bytes", " ", "bytes", " "); 766 else 767 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s", 768 "packets", "errs", "packets", "errs", "colls"); 769 if (dflag) 770 printf(" %5.5s", "drops"); 771 } 772 putchar('\n'); 773 fflush(stdout); 774 line = 0; 775 loop: 776 sum->ift_ip = 0; 777 sum->ift_ib = 0; 778 sum->ift_ie = 0; 779 sum->ift_op = 0; 780 sum->ift_ob = 0; 781 sum->ift_oe = 0; 782 sum->ift_co = 0; 783 sum->ift_dr = 0; 784 for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) { 785 if (kread(off, (char *)&ifnet, sizeof ifnet)) { 786 off = 0; 787 continue; 788 } 789 if (ip == interesting) { 790 if (bflag) { 791 char humbuf[HUMBUF_SIZE]; 792 793 if (hflag && humanize_number(humbuf, 794 sizeof(humbuf), 795 ifnet.if_ibytes - ip->ift_ib, "", 796 HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0) 797 printf("%10s %8.8s ", humbuf, " "); 798 else 799 printf("%10llu %8.8s ", 800 (unsigned long long) 801 (ifnet.if_ibytes-ip->ift_ib), " "); 802 803 if (hflag && humanize_number(humbuf, 804 sizeof(humbuf), 805 ifnet.if_obytes - ip->ift_ob, "", 806 HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0) 807 printf("%10s %5.5s", humbuf, " "); 808 else 809 printf("%10llu %5.5s", 810 (unsigned long long) 811 (ifnet.if_obytes-ip->ift_ob), " "); 812 } else { 813 printf("%8llu %5llu %8llu %5llu %5llu", 814 (unsigned long long) 815 (ifnet.if_ipackets - ip->ift_ip), 816 (unsigned long long) 817 (ifnet.if_ierrors - ip->ift_ie), 818 (unsigned long long) 819 (ifnet.if_opackets - ip->ift_op), 820 (unsigned long long) 821 (ifnet.if_oerrors - ip->ift_oe), 822 (unsigned long long) 823 (ifnet.if_collisions - ip->ift_co)); 824 } 825 if (dflag) 826 printf(" %5llu", 827 (unsigned long long) 828 (ifnet.if_snd.ifq_drops - ip->ift_dr)); 829 } 830 ip->ift_ip = ifnet.if_ipackets; 831 ip->ift_ib = ifnet.if_ibytes; 832 ip->ift_ie = ifnet.if_ierrors; 833 ip->ift_op = ifnet.if_opackets; 834 ip->ift_ob = ifnet.if_obytes; 835 ip->ift_oe = ifnet.if_oerrors; 836 ip->ift_co = ifnet.if_collisions; 837 ip->ift_dr = ifnet.if_snd.ifq_drops; 838 sum->ift_ip += ip->ift_ip; 839 sum->ift_ib += ip->ift_ib; 840 sum->ift_ie += ip->ift_ie; 841 sum->ift_op += ip->ift_op; 842 sum->ift_ob += ip->ift_ob; 843 sum->ift_oe += ip->ift_oe; 844 sum->ift_co += ip->ift_co; 845 sum->ift_dr += ip->ift_dr; 846 off = (u_long)ifnet.if_list.tqe_next; 847 } 848 if (lastif - iftot > 0) { 849 if (bflag) { 850 char humbuf[HUMBUF_SIZE]; 851 852 if (hflag && humanize_number(humbuf, 853 sizeof(humbuf), sum->ift_ib - total->ift_ib, "", 854 HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0) 855 printf(" %10s %8.8s ", humbuf, " "); 856 else 857 printf(" %10llu %8.8s ", 858 (unsigned long long) 859 (sum->ift_ib - total->ift_ib), " "); 860 861 if (hflag && humanize_number(humbuf, 862 sizeof(humbuf), sum->ift_ob - total->ift_ob, "", 863 HN_AUTOSCALE, HN_NOSPACE | HN_B) > 0) 864 printf("%10s %5.5s", humbuf, " "); 865 else 866 printf("%10llu %5.5s", 867 (unsigned long long) 868 (sum->ift_ob - total->ift_ob), " "); 869 } else { 870 printf(" %8llu %5llu %8llu %5llu %5llu", 871 (unsigned long long) 872 (sum->ift_ip - total->ift_ip), 873 (unsigned long long) 874 (sum->ift_ie - total->ift_ie), 875 (unsigned long long) 876 (sum->ift_op - total->ift_op), 877 (unsigned long long) 878 (sum->ift_oe - total->ift_oe), 879 (unsigned long long) 880 (sum->ift_co - total->ift_co)); 881 } 882 if (dflag) 883 printf(" %5llu", 884 (unsigned long long)(sum->ift_dr - total->ift_dr)); 885 } 886 *total = *sum; 887 putchar('\n'); 888 fflush(stdout); 889 line++; 890 oldmask = sigblock(sigmask(SIGALRM)); 891 if (! signalled) { 892 sigpause(0); 893 } 894 sigsetmask(oldmask); 895 signalled = false; 896 if (line == 21) 897 goto banner; 898 goto loop; 899 /*NOTREACHED*/ 900 } 901 902 /* 903 * Print a running summary of interface statistics. 904 * Repeat display every interval seconds, showing statistics 905 * collected over that interval. Assumes that interval is non-zero. 906 * First line printed at top of screen is always cumulative. 907 */ 908 static void 909 sidewaysintpr(unsigned int interval, u_long off) 910 { 911 912 if (use_sysctl) { 913 sidewaysintpr_sysctl(interval); 914 } else { 915 sidewaysintpr_kvm(interval, off); 916 } 917 } 918 919 /* 920 * Called if an interval expires before sidewaysintpr has completed a loop. 921 * Sets a flag to not wait for the alarm. 922 */ 923 static void 924 catchalarm(int signo) 925 { 926 927 signalled = true; 928 } 929 930 static void 931 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 932 { 933 int i; 934 935 for (i = 0; i < RTAX_MAX; i++) { 936 if (addrs & (1 << i)) { 937 rti_info[i] = sa; 938 sa = (struct sockaddr *)((char *)(sa) + 939 RT_ROUNDUP(sa->sa_len)); 940 } else 941 rti_info[i] = NULL; 942 } 943 } 944 945 static void 946 fetchifs(void) 947 { 948 struct if_msghdr *ifm; 949 int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; 950 struct rt_msghdr *rtm; 951 struct if_data *ifd = NULL; 952 struct sockaddr *sa, *rti_info[RTAX_MAX]; 953 struct sockaddr_dl *sdl; 954 char *buf, *next, *lim; 955 char name[IFNAMSIZ]; 956 size_t len; 957 958 if (prog_sysctl(mib, 6, NULL, &len, NULL, 0) == -1) 959 err(1, "sysctl"); 960 if ((buf = malloc(len)) == NULL) 961 err(1, NULL); 962 if (prog_sysctl(mib, 6, buf, &len, NULL, 0) == -1) 963 err(1, "sysctl"); 964 965 lim = buf + len; 966 for (next = buf; next < lim; next += rtm->rtm_msglen) { 967 rtm = (struct rt_msghdr *)next; 968 if (rtm->rtm_version != RTM_VERSION) 969 continue; 970 switch (rtm->rtm_type) { 971 case RTM_IFINFO: 972 ifm = (struct if_msghdr *)next; 973 ifd = &ifm->ifm_data; 974 975 sa = (struct sockaddr *)(ifm + 1); 976 get_rtaddrs(ifm->ifm_addrs, sa, rti_info); 977 978 sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP]; 979 if (sdl == NULL || sdl->sdl_family != AF_LINK) 980 continue; 981 bzero(name, sizeof(name)); 982 if (sdl->sdl_nlen >= IFNAMSIZ) 983 memcpy(name, sdl->sdl_data, IFNAMSIZ - 1); 984 else if (sdl->sdl_nlen > 0) 985 memcpy(name, sdl->sdl_data, sdl->sdl_nlen); 986 987 if (interface != 0 && !strcmp(name, interface)) { 988 strlcpy(ip_cur.ift_name, name, 989 sizeof(ip_cur.ift_name)); 990 ip_cur.ift_ip = ifd->ifi_ipackets; 991 ip_cur.ift_ib = ifd->ifi_ibytes; 992 ip_cur.ift_ie = ifd->ifi_ierrors; 993 ip_cur.ift_op = ifd->ifi_opackets; 994 ip_cur.ift_ob = ifd->ifi_obytes; 995 ip_cur.ift_oe = ifd->ifi_oerrors; 996 ip_cur.ift_co = ifd->ifi_collisions; 997 ip_cur.ift_dr = 0; 998 /* XXX-elad ifnet.if_snd.ifq_drops */ 999 } 1000 1001 sum_cur.ift_ip += ifd->ifi_ipackets; 1002 sum_cur.ift_ib += ifd->ifi_ibytes; 1003 sum_cur.ift_ie += ifd->ifi_ierrors; 1004 sum_cur.ift_op += ifd->ifi_opackets; 1005 sum_cur.ift_ob += ifd->ifi_obytes; 1006 sum_cur.ift_oe += ifd->ifi_oerrors; 1007 sum_cur.ift_co += ifd->ifi_collisions; 1008 sum_cur.ift_dr += 0; /* XXX-elad ifnet.if_snd.ifq_drops */ 1009 break; 1010 } 1011 } 1012 if (interface == NULL) { 1013 strlcpy(ip_cur.ift_name, name, 1014 sizeof(ip_cur.ift_name)); 1015 ip_cur.ift_ip = ifd->ifi_ipackets; 1016 ip_cur.ift_ib = ifd->ifi_ibytes; 1017 ip_cur.ift_ie = ifd->ifi_ierrors; 1018 ip_cur.ift_op = ifd->ifi_opackets; 1019 ip_cur.ift_ob = ifd->ifi_obytes; 1020 ip_cur.ift_oe = ifd->ifi_oerrors; 1021 ip_cur.ift_co = ifd->ifi_collisions; 1022 ip_cur.ift_dr = 0; 1023 /* XXX-elad ifnet.if_snd.ifq_drops */ 1024 } 1025 } 1026