1 /* $OpenBSD: if.c,v 1.26 2001/09/04 23:35:59 millert Exp $ */ 2 /* $NetBSD: if.c,v 1.16.4.2 1996/06/07 21:46:46 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1983, 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "from: @(#)if.c 8.2 (Berkeley) 2/21/94"; 40 #else 41 static char *rcsid = "$OpenBSD: if.c,v 1.26 2001/09/04 23:35:59 millert Exp $"; 42 #endif 43 #endif /* not lint */ 44 45 #include <sys/types.h> 46 #include <sys/protosw.h> 47 #include <sys/socket.h> 48 49 #include <net/if.h> 50 #include <net/if_dl.h> 51 #include <net/if_types.h> 52 #include <netinet/in.h> 53 #include <netinet/in_var.h> 54 #include <netinet/if_ether.h> 55 #include <netns/ns.h> 56 #include <netns/ns_if.h> 57 #include <netipx/ipx.h> 58 #include <netipx/ipx_if.h> 59 #include <netiso/iso.h> 60 #include <netiso/iso_var.h> 61 #include <arpa/inet.h> 62 63 #include <limits.h> 64 #include <signal.h> 65 #include <stdio.h> 66 #include <string.h> 67 #include <unistd.h> 68 69 #include "netstat.h" 70 71 #define YES 1 72 #define NO 0 73 74 static void sidewaysintpr __P((u_int, u_long)); 75 static void catchalarm __P((int)); 76 77 /* 78 * Print a description of the network interfaces. 79 * NOTE: ifnetaddr is the location of the kernel global "ifnet", 80 * which is a TAILQ_HEAD. 81 */ 82 void 83 intpr(interval, ifnetaddr) 84 int interval; 85 u_long ifnetaddr; 86 { 87 struct ifnet ifnet; 88 union { 89 struct ifaddr ifa; 90 struct in_ifaddr in; 91 #ifdef INET6 92 struct in6_ifaddr in6; 93 #endif 94 struct ns_ifaddr ns; 95 struct ipx_ifaddr ipx; 96 struct iso_ifaddr iso; 97 } ifaddr; 98 u_long total; 99 u_long ifaddraddr; 100 struct sockaddr *sa; 101 struct ifnet_head ifhead; /* TAILQ_HEAD */ 102 char name[IFNAMSIZ]; 103 104 if (ifnetaddr == 0) { 105 printf("ifnet: symbol not defined\n"); 106 return; 107 } 108 if (interval) { 109 sidewaysintpr((unsigned)interval, ifnetaddr); 110 return; 111 } 112 113 /* 114 * Find the pointer to the first ifnet structure. Replace 115 * the pointer to the TAILQ_HEAD with the actual pointer 116 * to the first list element. 117 */ 118 if (kread(ifnetaddr, (char *)&ifhead, sizeof ifhead)) 119 return; 120 ifnetaddr = (u_long)ifhead.tqh_first; 121 122 printf("%-7.7s %-5.5s %-11.11s %-17.17s ", 123 "Name", "Mtu", "Network", "Address"); 124 if (bflag) 125 printf("%10.10s %10.10s", "Ibytes", "Obytes"); 126 else 127 printf("%8.8s %5.5s %8.8s %5.5s %5.5s", 128 "Ipkts", "Ierrs", "Opkts", "Oerrs", "Colls"); 129 if (tflag) 130 printf(" %s", "Time"); 131 if (dflag) 132 printf(" %s", "Drop"); 133 putchar('\n'); 134 ifaddraddr = 0; 135 while (ifnetaddr || ifaddraddr) { 136 struct sockaddr_in *sin; 137 #ifdef INET6 138 struct sockaddr_in6 *sin6; 139 #endif 140 register char *cp; 141 int n, m; 142 143 if (ifaddraddr == 0) { 144 if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet)) 145 return; 146 bcopy(ifnet.if_xname, name, IFNAMSIZ); 147 name[IFNAMSIZ - 1] = '\0'; /* sanity */ 148 ifnetaddr = (u_long)ifnet.if_list.tqe_next; 149 if (interface != 0 && strcmp(name, interface) != 0) 150 continue; 151 cp = strchr(name, '\0'); 152 if ((ifnet.if_flags & IFF_UP) == 0) 153 *cp++ = '*'; 154 *cp = '\0'; 155 ifaddraddr = (u_long)ifnet.if_addrlist.tqh_first; 156 } 157 158 if (qflag) { 159 total = ifnet.if_ibytes + ifnet.if_obytes + 160 ifnet.if_ipackets + ifnet.if_ierrors + 161 ifnet.if_opackets + ifnet.if_oerrors + 162 ifnet.if_collisions; 163 if (tflag) 164 total += ifnet.if_timer; 165 if (dflag) 166 total += ifnet.if_snd.ifq_drops; 167 if (total == 0) { 168 ifaddraddr = 0; 169 continue; 170 } 171 } 172 173 printf("%-7.7s %-5ld ", name, ifnet.if_mtu); 174 if (ifaddraddr == 0) { 175 printf("%-11.11s ", "none"); 176 printf("%-15.15s ", "none"); 177 } else { 178 if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) { 179 ifaddraddr = 0; 180 continue; 181 } 182 #define CP(x) ((char *)(x)) 183 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) + 184 CP(&ifaddr); sa = (struct sockaddr *)cp; 185 switch (sa->sa_family) { 186 case AF_UNSPEC: 187 printf("%-11.11s ", "none"); 188 printf("%-17.17s ", "none"); 189 break; 190 case AF_INET: 191 sin = (struct sockaddr_in *)sa; 192 #ifdef notdef 193 /* can't use inet_makeaddr because kernel 194 * keeps nets unshifted. 195 */ 196 in = inet_makeaddr(ifaddr.in.ia_subnet, 197 INADDR_ANY); 198 cp = netname(in.s_addr, 199 ifaddr.in.ia_subnetmask); 200 #else 201 cp = netname(ifaddr.in.ia_subnet, 202 ifaddr.in.ia_subnetmask); 203 #endif 204 if (vflag) 205 n = strlen(cp) < 11 ? 11 : strlen(cp); 206 else 207 n = 11; 208 printf("%-*.*s ", n, n, cp); 209 cp = routename(sin->sin_addr.s_addr); 210 if (vflag) 211 n = strlen(cp) < 17 ? 17 : strlen(cp); 212 else 213 n = 17; 214 printf("%-*.*s ", n, n, cp); 215 216 if (aflag) { 217 u_long multiaddr; 218 struct in_multi inm; 219 220 multiaddr = (u_long)ifaddr.in.ia_multiaddrs.lh_first; 221 while (multiaddr != 0) { 222 kread(multiaddr, (char *)&inm, 223 sizeof inm); 224 printf("\n%25s %-17.17s ", "", 225 routename(inm.inm_addr.s_addr)); 226 multiaddr = (u_long)inm.inm_list.le_next; 227 } 228 } 229 break; 230 #ifdef INET6 231 case AF_INET6: 232 sin6 = (struct sockaddr_in6 *)sa; 233 #ifdef KAME_SCOPEID 234 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 235 sin6->sin6_scope_id = 236 ntohs(*(u_int16_t *) 237 &sin6->sin6_addr.s6_addr[2]); 238 /* too little width */ 239 if (!vflag) 240 sin6->sin6_scope_id = 0; 241 sin6->sin6_addr.s6_addr[2] = 0; 242 sin6->sin6_addr.s6_addr[3] = 0; 243 } 244 #endif 245 cp = netname6(&ifaddr.in6.ia_addr, 246 &ifaddr.in6.ia_prefixmask.sin6_addr); 247 if (vflag) 248 n = strlen(cp) < 11 ? 11 : strlen(cp); 249 else 250 n = 11; 251 printf("%-*.*s ", n, n, cp); 252 cp = routename6(sin6); 253 if (vflag) 254 n = strlen(cp) < 17 ? 17 : strlen(cp); 255 else 256 n = 17; 257 printf("%-*.*s ", n, n, cp); 258 if (aflag) { 259 u_long multiaddr; 260 struct in6_multi inm; 261 char hbuf[INET6_ADDRSTRLEN]; 262 263 multiaddr = (u_long)ifaddr.in6.ia6_multiaddrs.lh_first; 264 while (multiaddr != 0) { 265 kread(multiaddr, (char *)&inm, 266 sizeof inm); 267 inet_ntop(AF_INET6, &inm.in6m_addr, 268 hbuf, sizeof(hbuf)); 269 if (vflag) 270 n = strlen(hbuf) < 17 ? 17 : strlen(hbuf); 271 else 272 n = 17; 273 printf("\n%25s %-*.*s ", "", 274 n, n, hbuf); 275 multiaddr = (u_long)inm.in6m_entry.le_next; 276 } 277 } 278 break; 279 #endif 280 case AF_IPX: 281 { 282 struct sockaddr_ipx *sipx = 283 (struct sockaddr_ipx *)sa; 284 u_long net; 285 char netnum[8]; 286 287 *(union ipx_net *)&net = sipx->sipx_addr.ipx_net; 288 snprintf(netnum, sizeof netnum, "%xH", 289 ntohl(net)); 290 upHex(netnum); 291 printf("ipx:%-8s", netnum); 292 printf("%-17s ", 293 ipx_phost((struct sockaddr *)sipx)); 294 } 295 break; 296 case AF_APPLETALK: 297 printf("atlk:%-12s",atalk_print(sa,0x10) ); 298 printf("%-12s ",atalk_print(sa,0x0b) ); 299 break; 300 case AF_NS: 301 { 302 struct sockaddr_ns *sns = 303 (struct sockaddr_ns *)sa; 304 u_long net; 305 char netnum[8]; 306 307 *(union ns_net *)&net = sns->sns_addr.x_net; 308 snprintf(netnum, sizeof netnum, "%xH", 309 ntohl(net)); 310 upHex(netnum); 311 printf("ns:%-8s ", netnum); 312 printf("%-17s ", 313 ns_phost((struct sockaddr *)sns)); 314 } 315 break; 316 case AF_LINK: 317 { 318 struct sockaddr_dl *sdl = 319 (struct sockaddr_dl *)sa; 320 m = printf("%-11.11s ", "<Link>"); 321 if (sdl->sdl_type == IFT_ETHER || 322 sdl->sdl_type == IFT_FDDI || 323 sdl->sdl_type == IFT_ISO88025) 324 printf("%-17.17s ", 325 ether_ntoa((struct ether_addr *)LLADDR(sdl))); 326 else { 327 cp = (char *)LLADDR(sdl); 328 n = sdl->sdl_alen; 329 goto hexprint; 330 } 331 } 332 break; 333 default: 334 m = printf("(%d)", sa->sa_family); 335 for (cp = sa->sa_len + (char *)sa; 336 --cp > sa->sa_data && (*cp == 0);) {} 337 n = cp - sa->sa_data + 1; 338 cp = sa->sa_data; 339 hexprint: 340 while (--n >= 0) 341 m += printf("%x%c", *cp++ & 0xff, 342 n > 0 ? '.' : ' '); 343 m = 30 - m; 344 while (m-- > 0) 345 putchar(' '); 346 break; 347 } 348 ifaddraddr = (u_long)ifaddr.ifa.ifa_list.tqe_next; 349 } 350 if (bflag) 351 printf("%10lu %10lu", 352 ifnet.if_ibytes, ifnet.if_obytes); 353 else 354 printf("%8lu %5lu %8lu %5lu %5lu", 355 ifnet.if_ipackets, ifnet.if_ierrors, 356 ifnet.if_opackets, ifnet.if_oerrors, 357 ifnet.if_collisions); 358 if (tflag) 359 printf(" %4d", ifnet.if_timer); 360 if (dflag) 361 printf(" %4d", ifnet.if_snd.ifq_drops); 362 putchar('\n'); 363 } 364 } 365 366 #define MAXIF 100 367 struct iftot { 368 char ift_name[IFNAMSIZ]; /* interface name */ 369 int ift_ip; /* input packets */ 370 int ift_ib; /* input bytes */ 371 int ift_ie; /* input errors */ 372 int ift_op; /* output packets */ 373 int ift_ob; /* output bytes */ 374 int ift_oe; /* output errors */ 375 int ift_co; /* collisions */ 376 int ift_dr; /* drops */ 377 } iftot[MAXIF]; 378 379 volatile sig_atomic_t signalled; /* set if alarm goes off "early" */ 380 381 /* 382 * Print a running summary of interface statistics. 383 * Repeat display every interval seconds, showing statistics 384 * collected over that interval. Assumes that interval is non-zero. 385 * First line printed at top of screen is always cumulative. 386 */ 387 static void 388 sidewaysintpr(interval, off) 389 unsigned interval; 390 u_long off; 391 { 392 struct ifnet ifnet; 393 u_long firstifnet; 394 register struct iftot *ip, *total; 395 register int line; 396 struct iftot *lastif, *sum, *interesting; 397 struct ifnet_head ifhead; /* TAILQ_HEAD */ 398 sigset_t emptyset; 399 400 /* 401 * Find the pointer to the first ifnet structure. Replace 402 * the pointer to the TAILQ_HEAD with the actual pointer 403 * to the first list element. 404 */ 405 if (kread(off, (char *)&ifhead, sizeof ifhead)) 406 return; 407 firstifnet = (u_long)ifhead.tqh_first; 408 409 lastif = iftot; 410 sum = iftot + MAXIF - 1; 411 total = sum - 1; 412 interesting = (interface == NULL) ? iftot : NULL; 413 for (off = firstifnet, ip = iftot; off;) { 414 if (kread(off, (char *)&ifnet, sizeof ifnet)) 415 break; 416 bzero(ip->ift_name, sizeof(ip->ift_name)); 417 snprintf(ip->ift_name, IFNAMSIZ, "%s", ifnet.if_xname); 418 if (interface && strcmp(ifnet.if_xname, interface) == 0) 419 interesting = ip; 420 ip++; 421 if (ip >= iftot + MAXIF - 2) 422 break; 423 off = (u_long)ifnet.if_list.tqe_next; 424 } 425 if (interesting == NULL) { 426 fprintf(stderr, "%s: %s: unknown interface\n", 427 __progname, interface); 428 exit(1); 429 } 430 lastif = ip; 431 432 (void)signal(SIGALRM, catchalarm); 433 signalled = NO; 434 (void)alarm(interval); 435 banner: 436 if (bflag) 437 printf("%7.7s in %8.8s %6.6s out %5.5s", 438 interesting->ift_name, " ", 439 interesting->ift_name, " "); 440 else 441 printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s", 442 interesting->ift_name, " ", 443 interesting->ift_name, " ", " "); 444 if (dflag) 445 printf(" %5.5s", " "); 446 if (lastif - iftot > 0) { 447 if (bflag) 448 printf(" %7.7s in %8.8s %6.6s out %5.5s", 449 "total", " ", "total", " "); 450 else 451 printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s", 452 "total", " ", "total", " ", " "); 453 if (dflag) 454 printf(" %5.5s", " "); 455 } 456 for (ip = iftot; ip < iftot + MAXIF; ip++) { 457 ip->ift_ip = 0; 458 ip->ift_ib = 0; 459 ip->ift_ie = 0; 460 ip->ift_op = 0; 461 ip->ift_ob = 0; 462 ip->ift_oe = 0; 463 ip->ift_co = 0; 464 ip->ift_dr = 0; 465 } 466 putchar('\n'); 467 if (bflag) 468 printf("%10.10s %8.8s %10.10s %5.5s", 469 "bytes", " ", "bytes", " "); 470 else 471 printf("%8.8s %5.5s %8.8s %5.5s %5.5s", 472 "packets", "errs", "packets", "errs", "colls"); 473 if (dflag) 474 printf(" %5.5s", "drops"); 475 if (lastif - iftot > 0) { 476 if (bflag) 477 printf(" %10.10s %8.8s %10.10s %5.5s", 478 "bytes", " ", "bytes", " "); 479 else 480 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s", 481 "packets", "errs", "packets", "errs", "colls"); 482 if (dflag) 483 printf(" %5.5s", "drops"); 484 } 485 putchar('\n'); 486 fflush(stdout); 487 line = 0; 488 loop: 489 sum->ift_ip = 0; 490 sum->ift_ib = 0; 491 sum->ift_ie = 0; 492 sum->ift_op = 0; 493 sum->ift_ob = 0; 494 sum->ift_oe = 0; 495 sum->ift_co = 0; 496 sum->ift_dr = 0; 497 for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) { 498 if (kread(off, (char *)&ifnet, sizeof ifnet)) { 499 off = 0; 500 continue; 501 } 502 if (ip == interesting) { 503 if (bflag) 504 printf("%10lu %8.8s %10lu %5.5s", 505 ifnet.if_ibytes - ip->ift_ib, " ", 506 ifnet.if_obytes - ip->ift_ob, " "); 507 else 508 printf("%8lu %5lu %8lu %5lu %5lu", 509 ifnet.if_ipackets - ip->ift_ip, 510 ifnet.if_ierrors - ip->ift_ie, 511 ifnet.if_opackets - ip->ift_op, 512 ifnet.if_oerrors - ip->ift_oe, 513 ifnet.if_collisions - ip->ift_co); 514 if (dflag) 515 printf(" %5d", 516 ifnet.if_snd.ifq_drops - ip->ift_dr); 517 } 518 ip->ift_ip = ifnet.if_ipackets; 519 ip->ift_ib = ifnet.if_ibytes; 520 ip->ift_ie = ifnet.if_ierrors; 521 ip->ift_op = ifnet.if_opackets; 522 ip->ift_ob = ifnet.if_obytes; 523 ip->ift_oe = ifnet.if_oerrors; 524 ip->ift_co = ifnet.if_collisions; 525 ip->ift_dr = ifnet.if_snd.ifq_drops; 526 sum->ift_ip += ip->ift_ip; 527 sum->ift_ib += ip->ift_ib; 528 sum->ift_ie += ip->ift_ie; 529 sum->ift_op += ip->ift_op; 530 sum->ift_ob += ip->ift_ob; 531 sum->ift_oe += ip->ift_oe; 532 sum->ift_co += ip->ift_co; 533 sum->ift_dr += ip->ift_dr; 534 off = (u_long)ifnet.if_list.tqe_next; 535 } 536 if (lastif - iftot > 0) { 537 if (bflag) 538 printf(" %10lu %8.8s %10lu %5.5s", 539 (unsigned long)sum->ift_ib - total->ift_ib, " ", 540 (unsigned long)sum->ift_ob - total->ift_ob, " "); 541 else 542 printf(" %8lu %5lu %8lu %5lu %5lu", 543 (unsigned long)sum->ift_ip - total->ift_ip, 544 (unsigned long)sum->ift_ie - total->ift_ie, 545 (unsigned long)sum->ift_op - total->ift_op, 546 (unsigned long)sum->ift_oe - total->ift_oe, 547 (unsigned long)sum->ift_co - total->ift_co); 548 if (dflag) 549 printf(" %5d", sum->ift_dr - total->ift_dr); 550 } 551 *total = *sum; 552 putchar('\n'); 553 fflush(stdout); 554 line++; 555 sigemptyset(&emptyset); 556 if (!signalled) 557 sigsuspend(&emptyset); 558 signalled = NO; 559 (void)alarm(interval); 560 if (line == 21) 561 goto banner; 562 goto loop; 563 /*NOTREACHED*/ 564 } 565 566 /* 567 * Called if an interval expires before sidewaysintpr has completed a loop. 568 * Sets a flag to not wait for the alarm. 569 */ 570 static void 571 catchalarm(signo) 572 int signo; 573 { 574 signalled = YES; 575 } 576