if.c revision 1.32
1/* $NetBSD: if.c,v 1.32 1999/07/01 18:40:35 itojun 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.32 1999/07/01 18:40:35 itojun 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 %-5lu ", name, ifnet.if_mtu); 161 if (ifaddraddr == 0) { 162 printf("%-13.13s ", "none"); 163 printf("%-17.17s ", "none"); 164 } else { 165 char hexsep = '.'; /* for hexprint */ 166 const char *hexfmt = "%x%c"; /* for hexprint */ 167 if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) { 168 ifaddraddr = 0; 169 continue; 170 } 171#define CP(x) ((char *)(x)) 172 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) + 173 CP(&ifaddr); sa = (struct sockaddr *)cp; 174 switch (sa->sa_family) { 175 case AF_UNSPEC: 176 printf("%-13.13s ", "none"); 177 printf("%-17.17s ", "none"); 178 break; 179 case AF_INET: 180 sin = (struct sockaddr_in *)sa; 181#ifdef notdef 182 /* 183 * can't use inet_makeaddr because kernel 184 * keeps nets unshifted. 185 */ 186 in = inet_makeaddr(ifaddr.in.ia_subnet, 187 INADDR_ANY); 188 printf("%-13.13s ", netname(in.s_addr, 189 ifaddr.in.ia_subnetmask)); 190#else 191 printf("%-13.13s ", 192 netname(ifaddr.in.ia_subnet, 193 ifaddr.in.ia_subnetmask)); 194#endif 195 printf("%-17.17s ", 196 routename(sin->sin_addr.s_addr)); 197 198 if (aflag) { 199 u_long multiaddr; 200 struct in_multi inm; 201 202 multiaddr = (u_long) 203 ifaddr.in.ia_multiaddrs.lh_first; 204 while (multiaddr != 0) { 205 kread(multiaddr, (char *)&inm, 206 sizeof inm); 207 printf("\n%25s %-17.17s ", "", 208 routename( 209 inm.inm_addr.s_addr)); 210 multiaddr = 211 (u_long)inm.inm_list.le_next; 212 } 213 } 214 break; 215#ifdef INET6 216 case AF_INET6: 217 sin6 = (struct sockaddr_in6 *)sa; 218 printf("%-13.13s ", 219 netname6(&ifaddr.in6.ia_addr.sin6_addr, 220 &ifaddr.in6.ia_prefixmask.sin6_addr)); 221 printf("%-17.17s ", 222 (char *)inet_ntop(AF_INET6, 223 &sin6->sin6_addr, 224 ntop_buf, sizeof(ntop_buf))); 225 break; 226#endif /*INET6*/ 227#ifndef SMALL 228 case AF_APPLETALK: 229 printf("atalk:%-7.7s ", 230 atalk_print(sa,0x10)); 231 printf("%-17.17s ", atalk_print(sa,0x0b)); 232 break; 233 case AF_NS: 234 { 235 struct sockaddr_ns *sns = 236 (struct sockaddr_ns *)sa; 237 u_long net; 238 char netnum[8]; 239 240 *(union ns_net *)&net = sns->sns_addr.x_net; 241 (void)sprintf(netnum, "%xH", 242 (u_int32_t)ntohl(net)); 243 upHex(netnum); 244 printf("ns:%-10s ", netnum); 245 printf("%-17.17s ", 246 ns_phost((struct sockaddr *)sns)); 247 } 248 break; 249#endif 250 case AF_LINK: 251 { 252 struct sockaddr_dl *sdl = 253 (struct sockaddr_dl *)sa; 254 cp = (char *)LLADDR(sdl); 255 if (sdl->sdl_type == IFT_FDDI 256 || sdl->sdl_type == IFT_ETHER) 257 hexsep = ':', hexfmt = "%02x%c"; 258 n = sdl->sdl_alen; 259 } 260 m = printf("%-13.13s ", "<Link>"); 261 goto hexprint; 262 default: 263 m = printf("(%d)", sa->sa_family); 264 for (cp = sa->sa_len + (char *)sa; 265 --cp > sa->sa_data && (*cp == 0);) {} 266 n = cp - sa->sa_data + 1; 267 cp = sa->sa_data; 268 hexprint: 269 while (--n >= 0) 270 m += printf(hexfmt, *cp++ & 0xff, 271 n > 0 ? hexsep : ' '); 272 m = 32 - m; 273 while (m-- > 0) 274 putchar(' '); 275 break; 276 } 277 ifaddraddr = (u_long)ifaddr.ifa.ifa_list.tqe_next; 278 } 279 if (bflag) { 280 printf("%10lu %10lu", 281 ifnet.if_ibytes, ifnet.if_obytes); 282 } else { 283 printf("%8lu %5lu %8lu %5lu %5lu", 284 ifnet.if_ipackets, ifnet.if_ierrors, 285 ifnet.if_opackets, ifnet.if_oerrors, 286 ifnet.if_collisions); 287 } 288 if (tflag) 289 printf(" %4d", ifnet.if_timer); 290 if (dflag) 291 printf(" %5d", ifnet.if_snd.ifq_drops); 292 putchar('\n'); 293 } 294} 295 296#define MAXIF 100 297struct iftot { 298 char ift_name[IFNAMSIZ]; /* interface name */ 299 u_long ift_ip; /* input packets */ 300 u_long ift_ib; /* input bytes */ 301 u_long ift_ie; /* input errors */ 302 u_long ift_op; /* output packets */ 303 u_long ift_ob; /* output bytes */ 304 u_long ift_oe; /* output errors */ 305 u_long ift_co; /* collisions */ 306 int ift_dr; /* drops */ 307} iftot[MAXIF]; 308 309u_char signalled; /* set if alarm goes off "early" */ 310 311/* 312 * Print a running summary of interface statistics. 313 * Repeat display every interval seconds, showing statistics 314 * collected over that interval. Assumes that interval is non-zero. 315 * First line printed at top of screen is always cumulative. 316 */ 317static void 318sidewaysintpr(interval, off) 319 unsigned interval; 320 u_long off; 321{ 322 struct ifnet ifnet; 323 u_long firstifnet; 324 struct iftot *ip, *total; 325 int line; 326 struct iftot *lastif, *sum, *interesting; 327 struct ifnet_head ifhead; /* TAILQ_HEAD */ 328 int oldmask; 329 330 /* 331 * Find the pointer to the first ifnet structure. Replace 332 * the pointer to the TAILQ_HEAD with the actual pointer 333 * to the first list element. 334 */ 335 if (kread(off, (char *)&ifhead, sizeof ifhead)) 336 return; 337 firstifnet = (u_long)ifhead.tqh_first; 338 339 lastif = iftot; 340 sum = iftot + MAXIF - 1; 341 total = sum - 1; 342 interesting = (interface == NULL) ? iftot : NULL; 343 for (off = firstifnet, ip = iftot; off;) { 344 if (kread(off, (char *)&ifnet, sizeof ifnet)) 345 break; 346 memset(ip->ift_name, 0, sizeof(ip->ift_name)); 347 snprintf(ip->ift_name, IFNAMSIZ, "%s", ifnet.if_xname); 348 if (interface && strcmp(ifnet.if_xname, interface) == 0) 349 interesting = ip; 350 ip++; 351 if (ip >= iftot + MAXIF - 2) 352 break; 353 off = (u_long)ifnet.if_list.tqe_next; 354 } 355 if (interesting == NULL) { 356 fprintf(stderr, "%s: %s: unknown interface\n", 357 __progname, interface); 358 exit(1); 359 } 360 lastif = ip; 361 362 (void)signal(SIGALRM, catchalarm); 363 signalled = NO; 364 (void)alarm(interval); 365banner: 366 if (bflag) 367 printf("%7.7s in %8.8s %6.6s out %5.5s", 368 interesting->ift_name, " ", 369 interesting->ift_name, " "); 370 else 371 printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s", 372 interesting->ift_name, " ", 373 interesting->ift_name, " ", " "); 374 if (dflag) 375 printf(" %5.5s", " "); 376 if (lastif - iftot > 0) { 377 if (bflag) 378 printf(" %7.7s in %8.8s %6.6s out %5.5s", 379 "total", " ", "total", " "); 380 else 381 printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s", 382 "total", " ", "total", " ", " "); 383 if (dflag) 384 printf(" %5.5s", " "); 385 } 386 for (ip = iftot; ip < iftot + MAXIF; ip++) { 387 ip->ift_ip = 0; 388 ip->ift_ib = 0; 389 ip->ift_ie = 0; 390 ip->ift_op = 0; 391 ip->ift_ob = 0; 392 ip->ift_oe = 0; 393 ip->ift_co = 0; 394 ip->ift_dr = 0; 395 } 396 putchar('\n'); 397 if (bflag) 398 printf("%10.10s %8.8s %10.10s %5.5s", 399 "bytes", " ", "bytes", " "); 400 else 401 printf("%8.8s %5.5s %8.8s %5.5s %5.5s", 402 "packets", "errs", "packets", "errs", "colls"); 403 if (dflag) 404 printf(" %5.5s", "drops"); 405 if (lastif - iftot > 0) { 406 if (bflag) 407 printf(" %10.10s %8.8s %10.10s %5.5s", 408 "bytes", " ", "bytes", " "); 409 else 410 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s", 411 "packets", "errs", "packets", "errs", "colls"); 412 if (dflag) 413 printf(" %5.5s", "drops"); 414 } 415 putchar('\n'); 416 fflush(stdout); 417 line = 0; 418loop: 419 sum->ift_ip = 0; 420 sum->ift_ib = 0; 421 sum->ift_ie = 0; 422 sum->ift_op = 0; 423 sum->ift_ob = 0; 424 sum->ift_oe = 0; 425 sum->ift_co = 0; 426 sum->ift_dr = 0; 427 for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) { 428 if (kread(off, (char *)&ifnet, sizeof ifnet)) { 429 off = 0; 430 continue; 431 } 432 if (ip == interesting) { 433 if (bflag) { 434 printf("%10lu %8.8s %10lu %5.5s", 435 ifnet.if_ibytes - ip->ift_ib, " ", 436 ifnet.if_obytes - ip->ift_ob, " "); 437 } else { 438 printf("%8lu %5lu %8lu %5lu %5lu", 439 ifnet.if_ipackets - ip->ift_ip, 440 ifnet.if_ierrors - ip->ift_ie, 441 ifnet.if_opackets - ip->ift_op, 442 ifnet.if_oerrors - ip->ift_oe, 443 ifnet.if_collisions - ip->ift_co); 444 } 445 if (dflag) 446 printf(" %5d", 447 ifnet.if_snd.ifq_drops - ip->ift_dr); 448 } 449 ip->ift_ip = ifnet.if_ipackets; 450 ip->ift_ib = ifnet.if_ibytes; 451 ip->ift_ie = ifnet.if_ierrors; 452 ip->ift_op = ifnet.if_opackets; 453 ip->ift_ob = ifnet.if_obytes; 454 ip->ift_oe = ifnet.if_oerrors; 455 ip->ift_co = ifnet.if_collisions; 456 ip->ift_dr = ifnet.if_snd.ifq_drops; 457 sum->ift_ip += ip->ift_ip; 458 sum->ift_ib += ip->ift_ib; 459 sum->ift_ie += ip->ift_ie; 460 sum->ift_op += ip->ift_op; 461 sum->ift_ob += ip->ift_ob; 462 sum->ift_oe += ip->ift_oe; 463 sum->ift_co += ip->ift_co; 464 sum->ift_dr += ip->ift_dr; 465 off = (u_long)ifnet.if_list.tqe_next; 466 } 467 if (lastif - iftot > 0) { 468 if (bflag) { 469 printf(" %10lu %8.8s %10lu %5.5s", 470 sum->ift_ib - total->ift_ib, " ", 471 sum->ift_ob - total->ift_ob, " "); 472 } else { 473 printf(" %8lu %5lu %8lu %5lu %5lu", 474 sum->ift_ip - total->ift_ip, 475 sum->ift_ie - total->ift_ie, 476 sum->ift_op - total->ift_op, 477 sum->ift_oe - total->ift_oe, 478 sum->ift_co - total->ift_co); 479 } 480 if (dflag) 481 printf(" %5d", sum->ift_dr - total->ift_dr); 482 } 483 *total = *sum; 484 putchar('\n'); 485 fflush(stdout); 486 line++; 487 oldmask = sigblock(sigmask(SIGALRM)); 488 if (! signalled) { 489 sigpause(0); 490 } 491 sigsetmask(oldmask); 492 signalled = NO; 493 (void)alarm(interval); 494 if (line == 21) 495 goto banner; 496 goto loop; 497 /*NOTREACHED*/ 498} 499 500/* 501 * Called if an interval expires before sidewaysintpr has completed a loop. 502 * Sets a flag to not wait for the alarm. 503 */ 504static void 505catchalarm(signo) 506 int signo; 507{ 508 509 signalled = YES; 510} 511