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