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