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