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