if.c revision 1.65
1/* $NetBSD: if.c,v 1.65 2009/09/13 19:04:29 elad 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.65 2009/09/13 19:04:29 elad 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 69#define MAXIF 100 70 71struct iftot { 72 char ift_name[IFNAMSIZ]; /* interface name */ 73 u_quad_t ift_ip; /* input packets */ 74 u_quad_t ift_ib; /* input bytes */ 75 u_quad_t ift_ie; /* input errors */ 76 u_quad_t ift_op; /* output packets */ 77 u_quad_t ift_ob; /* output bytes */ 78 u_quad_t ift_oe; /* output errors */ 79 u_quad_t ift_co; /* collisions */ 80 int ift_dr; /* drops */ 81}; 82 83static void print_addr(struct sockaddr *, struct sockaddr **, struct if_data *); 84static void sidewaysintpr(u_int, u_long); 85 86static void iftot_banner(struct iftot *); 87static void iftot_print_sum(struct iftot *, struct iftot *); 88static void iftot_print(struct iftot *, struct iftot *); 89 90static void catchalarm __P((int)); 91static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); 92static void fetchifs(void); 93 94static void intpr_sysctl(void); 95static void intpr_kvm(u_long, void (*)(const char *)); 96 97struct iftot iftot[MAXIF], ip_cur, ip_old, sum_cur, sum_old; 98bool signalled; /* set if alarm goes off "early" */ 99 100/* 101 * Print a description of the network interfaces. 102 * NOTE: ifnetaddr is the location of the kernel global "ifnet", 103 * which is a TAILQ_HEAD. 104 */ 105void 106intpr(interval, ifnetaddr, pfunc) 107 int interval; 108 u_long ifnetaddr; 109 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 (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) 165 err(1, "sysctl"); 166 if ((buf = malloc(len)) == NULL) 167 err(1, NULL); 168 if (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 %-5qu ", name, ifd->ifi_mtu); 220 print_addr(rti_info[RTAX_IFP], rti_info, ifd); 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 %-5qu ", name, ifd->ifi_mtu); 238 print_addr(rti_info[RTAX_IFA], rti_info, ifd); 239 break; 240 } 241 } 242} 243 244static void 245intpr_kvm(u_long ifnetaddr, void (*pfunc)(const char *)) 246{ 247 struct ifnet ifnet; 248 union { 249 struct ifaddr ifa; 250 struct in_ifaddr in; 251#ifdef INET6 252 struct in6_ifaddr in6; 253#endif /* INET6 */ 254 struct iso_ifaddr iso; 255 } 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); 322 } 323 ifaddraddr = (u_long)ifaddr.ifa.ifa_list.tqe_next; 324 } 325 326} 327 328static void 329print_addr(struct sockaddr *sa, struct sockaddr **rtinfo, struct if_data *ifd) 330{ 331 char hexsep = '.'; /* for hexprint */ 332 static const char hexfmt[] = "%02x%c"; /* for hexprint */ 333 char hbuf[NI_MAXHOST]; /* for getnameinfo() */ 334#ifdef INET6 335 const int niflag = NI_NUMERICHOST; 336#endif 337 in_addr_t netmask; 338 struct sockaddr_in *sin; 339 struct sockaddr_in6 *sin6, *netmask6; 340 char *cp; 341 int n, m; 342 343 switch (sa->sa_family) { 344 case AF_UNSPEC: 345 printf("%-13.13s ", "none"); 346 printf("%-17.17s ", "none"); 347 break; 348 case AF_INET: 349 sin = (struct sockaddr_in *)sa; 350#ifdef notdef 351 /* 352 * can't use inet_makeaddr because kernel 353 * keeps nets unshifted. 354 */ 355 in = inet_makeaddr(ifaddr.in.ia_subnet, 356 INADDR_ANY); 357 cp = netname4(in.s_addr, 358 ifaddr.in.ia_subnetmask); 359#else 360 if (use_sysctl) { 361 netmask = ((struct sockaddr_in *)rtinfo[RTAX_NETMASK])->sin_addr.s_addr; 362 } else { 363 struct in_ifaddr *ifaddr_in = (void *)rtinfo; 364 netmask = ifaddr_in->ia_subnetmask; 365 } 366 cp = netname4(sin->sin_addr.s_addr, netmask); 367#endif 368 if (vflag) 369 n = strlen(cp) < 13 ? 13 : strlen(cp); 370 else 371 n = 13; 372 printf("%-*.*s ", n, n, cp); 373 cp = routename4(sin->sin_addr.s_addr); 374 if (vflag) 375 n = strlen(cp) < 17 ? 17 : strlen(cp); 376 else 377 n = 17; 378 printf("%-*.*s ", n, n, cp); 379 380#if 0 /* XXX-elad */ 381 if (aflag) { 382 u_long multiaddr; 383 struct in_multi inm; 384 385 multiaddr = (u_long) 386 ifaddr.in.ia_multiaddrs.lh_first; 387 while (multiaddr != 0) { 388 kread(multiaddr, (char *)&inm, 389 sizeof inm); 390 printf("\n%25s %-17.17s ", "", 391 routename4( 392 inm.inm_addr.s_addr)); 393 multiaddr = 394 (u_long)inm.inm_list.le_next; 395 } 396 } 397#endif /* 0 */ 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 0 /* XXX-elad */ 442 if (aflag) { 443 u_long multiaddr; 444 struct in6_multi inm; 445 struct sockaddr_in6 as6; 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#endif /* 0 */ 485 break; 486#endif /*INET6*/ 487#ifndef SMALL 488 case AF_APPLETALK: 489 printf("atalk:%-7.7s ", 490 atalk_print(sa,0x10)); 491 printf("%-17.17s ", atalk_print(sa,0x0b)); 492 break; 493#endif 494 case AF_LINK: 495 printf("%-13.13s ", "<Link>"); 496 if (getnameinfo(sa, sa->sa_len, 497 hbuf, sizeof(hbuf), NULL, 0, 498 NI_NUMERICHOST) != 0) { 499 strlcpy(hbuf, "?", sizeof(hbuf)); 500 } 501 cp = hbuf; 502 if (vflag) 503 n = strlen(cp) < 17 ? 17 : strlen(cp); 504 else 505 n = 17; 506 printf("%-*.*s ", n, n, cp); 507 break; 508 509 default: 510 m = printf("(%d)", sa->sa_family); 511 for (cp = sa->sa_len + (char *)sa; 512 --cp > sa->sa_data && (*cp == 0);) {} 513 n = cp - sa->sa_data + 1; 514 cp = sa->sa_data; 515 516 while (--n >= 0) 517 m += printf(hexfmt, *cp++ & 0xff, 518 n > 0 ? hexsep : ' '); 519 m = 32 - m; 520 while (m-- > 0) 521 putchar(' '); 522 break; 523 } 524 525 if (bflag) { 526 printf("%10llu %10llu", 527 (unsigned long long)ifd->ifi_ibytes, 528 (unsigned long long)ifd->ifi_obytes); 529 } else { 530 printf("%8llu %5llu %8llu %5llu %5llu", 531 (unsigned long long)ifd->ifi_ipackets, 532 (unsigned long long)ifd->ifi_ierrors, 533 (unsigned long long)ifd->ifi_opackets, 534 (unsigned long long)ifd->ifi_oerrors, 535 (unsigned long long)ifd->ifi_collisions); 536 } 537 if (tflag) 538 printf(" %4d", 0 /* XXX-elad ifnet.if_timer */); 539 if (dflag) 540 printf(" %5d", 0 /* XXX-elad ifnet.if_snd.ifq_drops */); 541 putchar('\n'); 542} 543 544static void 545iftot_banner(struct iftot *ift) 546{ 547 if (bflag) 548 printf("%7.7s in %8.8s %6.6s out %5.5s", 549 ift->ift_name, " ", 550 ift->ift_name, " "); 551 else 552 printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s", 553 ift->ift_name, " ", 554 ift->ift_name, " ", " "); 555 if (dflag) 556 printf(" %5.5s", " "); 557 558 if (bflag) 559 printf(" %7.7s in %8.8s %6.6s out %5.5s", 560 "total", " ", "total", " "); 561 else 562 printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s", 563 "total", " ", "total", " ", " "); 564 if (dflag) 565 printf(" %5.5s", " "); 566 putchar('\n'); 567 if (bflag) 568 printf("%10.10s %8.8s %10.10s %5.5s", 569 "bytes", " ", "bytes", " "); 570 else 571 printf("%8.8s %5.5s %8.8s %5.5s %5.5s", 572 "packets", "errs", "packets", "errs", "colls"); 573 if (dflag) 574 printf(" %5.5s", "drops"); 575 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 putchar('\n'); 585 fflush(stdout); 586} 587 588static void 589iftot_print(struct iftot *cur, struct iftot *old) 590{ 591 if (bflag) 592 printf("%10llu %8.8s %10llu %5.5s", 593 (unsigned long long)(cur->ift_ib - old->ift_ib), " ", 594 (unsigned long long)(cur->ift_ob - old->ift_ob), " "); 595 else 596 printf("%8llu %5llu %8llu %5llu %5llu", 597 (unsigned long long)(cur->ift_ip - old->ift_ip), 598 (unsigned long long)(cur->ift_ie - old->ift_ie), 599 (unsigned long long)(cur->ift_op - old->ift_op), 600 (unsigned long long)(cur->ift_oe - old->ift_oe), 601 (unsigned long long)(cur->ift_co - old->ift_co)); 602 if (dflag) 603 printf(" %5llu", 604 /* XXX ifnet.if_snd.ifq_drops - ip->ift_dr); */ 605 0LL); 606} 607 608static void 609iftot_print_sum(struct iftot *cur, struct iftot *old) 610{ 611 if (bflag) 612 printf(" %10llu %8.8s %10llu %5.5s", 613 (unsigned long long)(cur->ift_ib - old->ift_ib), " ", 614 (unsigned long long)(cur->ift_ob - old->ift_ob), " "); 615 else 616 printf(" %8llu %5llu %8llu %5llu %5llu", 617 (unsigned long long)(cur->ift_ip - old->ift_ip), 618 (unsigned long long)(cur->ift_ie - old->ift_ie), 619 (unsigned long long)(cur->ift_op - old->ift_op), 620 (unsigned long long)(cur->ift_oe - old->ift_oe), 621 (unsigned long long)(cur->ift_co - old->ift_co)); 622 623 if (dflag) 624 printf(" %5llu", (unsigned long long)(cur->ift_dr - old->ift_dr)); 625} 626 627static void 628sidewaysintpr_sysctl(unsigned interval) 629{ 630 sigset_t emptyset; 631 int line; 632 633 fetchifs(); 634 if (ip_cur.ift_name[0] == '\0') { 635 fprintf(stderr, "%s: %s: unknown interface\n", 636 getprogname(), interface); 637 exit(1); 638 } 639 640 (void)signal(SIGALRM, catchalarm); 641 signalled = 0; 642 (void)alarm(interval); 643banner: 644 iftot_banner(&ip_cur); 645 646 line = 0; 647 bzero(&ip_old, sizeof(ip_old)); 648 bzero(&sum_old, sizeof(sum_old)); 649loop: 650 bzero(&sum_cur, sizeof(sum_cur)); 651 652 fetchifs(); 653 654 iftot_print(&ip_cur, &ip_old); 655 656 ip_old = ip_cur; 657 658 iftot_print_sum(&sum_cur, &sum_old); 659 660 sum_old = sum_cur; 661 662 putchar('\n'); 663 fflush(stdout); 664 line++; 665 sigemptyset(&emptyset); 666 if (!signalled) 667 sigsuspend(&emptyset); 668 signalled = 0; 669 (void)alarm(interval); 670 if (line == 21) 671 goto banner; 672 goto loop; 673 /*NOTREACHED*/ 674} 675 676static void 677sidewaysintpr_kvm(unsigned interval, u_long off) 678{ 679 struct itimerval it; 680 struct ifnet ifnet; 681 u_long firstifnet; 682 struct iftot *ip, *total; 683 int line; 684 struct iftot *lastif, *sum, *interesting; 685 struct ifnet_head ifhead; /* TAILQ_HEAD */ 686 int oldmask; 687 688 /* 689 * Find the pointer to the first ifnet structure. Replace 690 * the pointer to the TAILQ_HEAD with the actual pointer 691 * to the first list element. 692 */ 693 if (kread(off, (char *)&ifhead, sizeof ifhead)) 694 return; 695 firstifnet = (u_long)ifhead.tqh_first; 696 697 lastif = iftot; 698 sum = iftot + MAXIF - 1; 699 total = sum - 1; 700 interesting = (interface == NULL) ? iftot : NULL; 701 for (off = firstifnet, ip = iftot; off;) { 702 if (kread(off, (char *)&ifnet, sizeof ifnet)) 703 break; 704 memset(ip->ift_name, 0, sizeof(ip->ift_name)); 705 snprintf(ip->ift_name, IFNAMSIZ, "%s", ifnet.if_xname); 706 if (interface && strcmp(ifnet.if_xname, interface) == 0) 707 interesting = ip; 708 ip++; 709 if (ip >= iftot + MAXIF - 2) 710 break; 711 off = (u_long)ifnet.if_list.tqe_next; 712 } 713 if (interesting == NULL) { 714 fprintf(stderr, "%s: %s: unknown interface\n", 715 getprogname(), interface); 716 exit(1); 717 } 718 lastif = ip; 719 720 (void)signal(SIGALRM, catchalarm); 721 signalled = false; 722 723 it.it_interval.tv_sec = it.it_value.tv_sec = interval; 724 it.it_interval.tv_usec = it.it_value.tv_usec = 0; 725 setitimer(ITIMER_REAL, &it, NULL); 726 727banner: 728 if (bflag) 729 printf("%7.7s in %8.8s %6.6s out %5.5s", 730 interesting->ift_name, " ", 731 interesting->ift_name, " "); 732 else 733 printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s", 734 interesting->ift_name, " ", 735 interesting->ift_name, " ", " "); 736 if (dflag) 737 printf(" %5.5s", " "); 738 if (lastif - iftot > 0) { 739 if (bflag) 740 printf(" %7.7s in %8.8s %6.6s out %5.5s", 741 "total", " ", "total", " "); 742 else 743 printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s", 744 "total", " ", "total", " ", " "); 745 if (dflag) 746 printf(" %5.5s", " "); 747 } 748 for (ip = iftot; ip < iftot + MAXIF; ip++) { 749 ip->ift_ip = 0; 750 ip->ift_ib = 0; 751 ip->ift_ie = 0; 752 ip->ift_op = 0; 753 ip->ift_ob = 0; 754 ip->ift_oe = 0; 755 ip->ift_co = 0; 756 ip->ift_dr = 0; 757 } 758 putchar('\n'); 759 if (bflag) 760 printf("%10.10s %8.8s %10.10s %5.5s", 761 "bytes", " ", "bytes", " "); 762 else 763 printf("%8.8s %5.5s %8.8s %5.5s %5.5s", 764 "packets", "errs", "packets", "errs", "colls"); 765 if (dflag) 766 printf(" %5.5s", "drops"); 767 if (lastif - iftot > 0) { 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 } 777 putchar('\n'); 778 fflush(stdout); 779 line = 0; 780loop: 781 sum->ift_ip = 0; 782 sum->ift_ib = 0; 783 sum->ift_ie = 0; 784 sum->ift_op = 0; 785 sum->ift_ob = 0; 786 sum->ift_oe = 0; 787 sum->ift_co = 0; 788 sum->ift_dr = 0; 789 for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) { 790 if (kread(off, (char *)&ifnet, sizeof ifnet)) { 791 off = 0; 792 continue; 793 } 794 if (ip == interesting) { 795 if (bflag) { 796 printf("%10llu %8.8s %10llu %5.5s", 797 (unsigned long long)(ifnet.if_ibytes - 798 ip->ift_ib), " ", 799 (unsigned long long)(ifnet.if_obytes - 800 ip->ift_ob), " "); 801 } else { 802 printf("%8llu %5llu %8llu %5llu %5llu", 803 (unsigned long long) 804 (ifnet.if_ipackets - ip->ift_ip), 805 (unsigned long long) 806 (ifnet.if_ierrors - ip->ift_ie), 807 (unsigned long long) 808 (ifnet.if_opackets - ip->ift_op), 809 (unsigned long long) 810 (ifnet.if_oerrors - ip->ift_oe), 811 (unsigned long long) 812 (ifnet.if_collisions - ip->ift_co)); 813 } 814 if (dflag) 815 printf(" %5llu", 816 (unsigned long long) 817 (ifnet.if_snd.ifq_drops - ip->ift_dr)); 818 } 819 ip->ift_ip = ifnet.if_ipackets; 820 ip->ift_ib = ifnet.if_ibytes; 821 ip->ift_ie = ifnet.if_ierrors; 822 ip->ift_op = ifnet.if_opackets; 823 ip->ift_ob = ifnet.if_obytes; 824 ip->ift_oe = ifnet.if_oerrors; 825 ip->ift_co = ifnet.if_collisions; 826 ip->ift_dr = ifnet.if_snd.ifq_drops; 827 sum->ift_ip += ip->ift_ip; 828 sum->ift_ib += ip->ift_ib; 829 sum->ift_ie += ip->ift_ie; 830 sum->ift_op += ip->ift_op; 831 sum->ift_ob += ip->ift_ob; 832 sum->ift_oe += ip->ift_oe; 833 sum->ift_co += ip->ift_co; 834 sum->ift_dr += ip->ift_dr; 835 off = (u_long)ifnet.if_list.tqe_next; 836 } 837 if (lastif - iftot > 0) { 838 if (bflag) { 839 printf(" %10llu %8.8s %10llu %5.5s", 840 (unsigned long long) 841 (sum->ift_ib - total->ift_ib), " ", 842 (unsigned long long) 843 (sum->ift_ob - total->ift_ob), " "); 844 } else { 845 printf(" %8llu %5llu %8llu %5llu %5llu", 846 (unsigned long long) 847 (sum->ift_ip - total->ift_ip), 848 (unsigned long long) 849 (sum->ift_ie - total->ift_ie), 850 (unsigned long long) 851 (sum->ift_op - total->ift_op), 852 (unsigned long long) 853 (sum->ift_oe - total->ift_oe), 854 (unsigned long long) 855 (sum->ift_co - total->ift_co)); 856 } 857 if (dflag) 858 printf(" %5llu", 859 (unsigned long long)(sum->ift_dr - total->ift_dr)); 860 } 861 *total = *sum; 862 putchar('\n'); 863 fflush(stdout); 864 line++; 865 oldmask = sigblock(sigmask(SIGALRM)); 866 if (! signalled) { 867 sigpause(0); 868 } 869 sigsetmask(oldmask); 870 signalled = false; 871 if (line == 21) 872 goto banner; 873 goto loop; 874 /*NOTREACHED*/ 875} 876 877/* 878 * Print a running summary of interface statistics. 879 * Repeat display every interval seconds, showing statistics 880 * collected over that interval. Assumes that interval is non-zero. 881 * First line printed at top of screen is always cumulative. 882 */ 883static void 884sidewaysintpr(interval, off) 885 unsigned interval; 886 u_long off; 887{ 888 889 if (use_sysctl) { 890 sidewaysintpr_sysctl(interval); 891 } else { 892 sidewaysintpr_kvm(interval, off); 893 } 894} 895 896/* 897 * Called if an interval expires before sidewaysintpr has completed a loop. 898 * Sets a flag to not wait for the alarm. 899 */ 900static void 901catchalarm(signo) 902 int signo; 903{ 904 905 signalled = true; 906} 907 908#define ROUNDUP(a, size) \ 909 (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) 910 911#define NEXT_SA(ap) (ap) = (struct sockaddr *) \ 912 ((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\ 913 sizeof(u_long)) : sizeof(u_long))) 914 915static void 916get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 917{ 918 int i; 919 920 for (i = 0; i < RTAX_MAX; i++) { 921 if (addrs & (1 << i)) { 922 rti_info[i] = sa; 923 NEXT_SA(sa); 924 /* sa = (struct sockaddr *)((char *)(sa) + 925 roundup(sa->sa_len, sizeof(long))); */ 926 } else 927 rti_info[i] = NULL; 928 } 929} 930 931static void 932fetchifs(void) 933{ 934 struct if_msghdr *ifm; 935 int mib[6] = { CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; 936 struct rt_msghdr *rtm; 937 struct if_data *ifd = NULL; 938 struct sockaddr *sa, *rti_info[RTAX_MAX]; 939 struct sockaddr_dl *sdl; 940 char *buf, *next, *lim; 941 char name[IFNAMSIZ]; 942 size_t len; 943 944 if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) 945 err(1, "sysctl"); 946 if ((buf = malloc(len)) == NULL) 947 err(1, NULL); 948 if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) 949 err(1, "sysctl"); 950 951 lim = buf + len; 952 for (next = buf; next < lim; next += rtm->rtm_msglen) { 953 rtm = (struct rt_msghdr *)next; 954 if (rtm->rtm_version != RTM_VERSION) 955 continue; 956 switch (rtm->rtm_type) { 957 case RTM_IFINFO: 958 ifm = (struct if_msghdr *)next; 959 ifd = &ifm->ifm_data; 960 961 sa = (struct sockaddr *)(ifm + 1); 962 get_rtaddrs(ifm->ifm_addrs, sa, rti_info); 963 964 sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP]; 965 if (sdl == NULL || sdl->sdl_family != AF_LINK) 966 continue; 967 bzero(name, sizeof(name)); 968 if (sdl->sdl_nlen >= IFNAMSIZ) 969 memcpy(name, sdl->sdl_data, IFNAMSIZ - 1); 970 else if (sdl->sdl_nlen > 0) 971 memcpy(name, sdl->sdl_data, sdl->sdl_nlen); 972 973 if (interface != 0 && !strcmp(name, interface)) { 974 strlcpy(ip_cur.ift_name, name, 975 sizeof(ip_cur.ift_name)); 976 ip_cur.ift_ip = ifd->ifi_ipackets; 977 ip_cur.ift_ib = ifd->ifi_ibytes; 978 ip_cur.ift_ie = ifd->ifi_ierrors; 979 ip_cur.ift_op = ifd->ifi_opackets; 980 ip_cur.ift_ob = ifd->ifi_obytes; 981 ip_cur.ift_oe = ifd->ifi_oerrors; 982 ip_cur.ift_co = ifd->ifi_collisions; 983 ip_cur.ift_dr = 0; 984 /* XXX-elad ifnet.if_snd.ifq_drops */ 985 } 986 987 sum_cur.ift_ip += ifd->ifi_ipackets; 988 sum_cur.ift_ib += ifd->ifi_ibytes; 989 sum_cur.ift_ie += ifd->ifi_ierrors; 990 sum_cur.ift_op += ifd->ifi_opackets; 991 sum_cur.ift_ob += ifd->ifi_obytes; 992 sum_cur.ift_oe += ifd->ifi_oerrors; 993 sum_cur.ift_co += ifd->ifi_collisions; 994 sum_cur.ift_dr += 0; /* XXX-elad ifnet.if_snd.ifq_drops */ 995 break; 996 } 997 } 998 if (interface == NULL) { 999 strlcpy(ip_cur.ift_name, name, 1000 sizeof(ip_cur.ift_name)); 1001 ip_cur.ift_ip = ifd->ifi_ipackets; 1002 ip_cur.ift_ib = ifd->ifi_ibytes; 1003 ip_cur.ift_ie = ifd->ifi_ierrors; 1004 ip_cur.ift_op = ifd->ifi_opackets; 1005 ip_cur.ift_ob = ifd->ifi_obytes; 1006 ip_cur.ift_oe = ifd->ifi_oerrors; 1007 ip_cur.ift_co = ifd->ifi_collisions; 1008 ip_cur.ift_dr = 0; 1009 /* XXX-elad ifnet.if_snd.ifq_drops */ 1010 } 1011} 1012