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