1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2013 Gleb Smirnoff <glebius@FreeBSD.org> 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. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #if 0 34 #ifndef lint 35 static char sccsid[] = "@(#)if.c 8.3 (Berkeley) 4/28/95"; 36 #endif /* not lint */ 37 #endif 38 39 #include <sys/cdefs.h> 40 __FBSDID("$FreeBSD$"); 41 42 #include <sys/param.h> 43 #include <sys/protosw.h> 44 #include <sys/socket.h> 45 #include <sys/socketvar.h> 46 #include <sys/time.h> 47 48 #include <net/if.h> 49 #include <net/if_dl.h> 50 #include <net/if_types.h> 51 #include <net/ethernet.h> 52 #include <netinet/in.h> 53 #include <netinet/in_var.h> 54 #include <arpa/inet.h> 55 #ifdef PF 56 #include <net/pfvar.h> 57 #include <net/if_pfsync.h> 58 #endif 59 60 #include <err.h> 61 #include <errno.h> 62 #include <ifaddrs.h> 63 #include <libutil.h> 64 #ifdef INET6 65 #include <netdb.h> 66 #endif 67 #include <signal.h> 68 #include <stdbool.h> 69 #include <stdint.h> 70 #include <stdio.h> 71 #include <stdlib.h> 72 #include <string.h> 73 #include <sysexits.h> 74 #include <unistd.h> 75 #include <libxo/xo.h> 76 77 #include "netstat.h" 78 79 static void sidewaysintpr(void); 80 81 #ifdef PF 82 static const char* pfsyncacts[] = { 83 /* PFSYNC_ACT_CLR */ "clear all request", 84 /* PFSYNC_ACT_INS_1301 */ "13.1 state insert", 85 /* PFSYNC_ACT_INS_ACK */ "state inserted ack", 86 /* PFSYNC_ACT_UPD_1301 */ "13.1 state update", 87 /* PFSYNC_ACT_UPD_C */ "compressed state update", 88 /* PFSYNC_ACT_UPD_REQ */ "uncompressed state request", 89 /* PFSYNC_ACT_DEL */ "state delete", 90 /* PFSYNC_ACT_DEL_C */ "compressed state delete", 91 /* PFSYNC_ACT_INS_F */ "fragment insert", 92 /* PFSYNC_ACT_DEL_F */ "fragment delete", 93 /* PFSYNC_ACT_BUS */ "bulk update mark", 94 /* PFSYNC_ACT_TDB */ "TDB replay counter update", 95 /* PFSYNC_ACT_EOF */ "end of frame mark", 96 /* PFSYNC_ACT_INS_1400 */ "state insert", 97 /* PFSYNC_ACT_UPD_1400 */ "state update", 98 }; 99 100 static const char* pfsyncacts_name[] = { 101 /* PFSYNC_ACT_CLR */ "clear-all-request", 102 /* PFSYNC_ACT_INS_1301 */ "state-insert-1301", 103 /* PFSYNC_ACT_INS_ACK */ "state-inserted-ack", 104 /* PFSYNC_ACT_UPD_1301 */ "state-update-1301", 105 /* PFSYNC_ACT_UPD_C */ "compressed-state-update", 106 /* PFSYNC_ACT_UPD_REQ */ "uncompressed-state-request", 107 /* PFSYNC_ACT_DEL */ "state-delete", 108 /* PFSYNC_ACT_DEL_C */ "compressed-state-delete", 109 /* PFSYNC_ACT_INS_F */ "fragment-insert", 110 /* PFSYNC_ACT_DEL_F */ "fragment-delete", 111 /* PFSYNC_ACT_BUS */ "bulk-update-mark", 112 /* PFSYNC_ACT_TDB */ "TDB-replay-counter-update", 113 /* PFSYNC_ACT_EOF */ "end-of-frame-mark", 114 /* PFSYNC_ACT_INS_1400 */ "state-insert", 115 /* PFSYNC_ACT_UPD_1400 */ "state-update", 116 }; 117 118 static void 119 pfsync_acts_stats(const char *list, const char *desc, uint64_t *a) 120 { 121 int i; 122 123 xo_open_list(list); 124 for (i = 0; i < PFSYNC_ACT_MAX; i++, a++) { 125 if (*a || sflag <= 1) { 126 xo_open_instance(list); 127 xo_emit("\t\t{e:name}{:count/%ju} {N:/%s%s %s}\n", 128 pfsyncacts_name[i], (uintmax_t)(*a), 129 pfsyncacts[i], plural(*a), desc); 130 xo_close_instance(list); 131 } 132 } 133 xo_close_list(list); 134 } 135 136 /* 137 * Dump pfsync statistics structure. 138 */ 139 void 140 pfsync_stats(u_long off, const char *name, int af1 __unused, int proto __unused) 141 { 142 struct pfsyncstats pfsyncstat; 143 144 if (fetch_stats("net.pfsync.stats", off, &pfsyncstat, 145 sizeof(pfsyncstat), kread) != 0) 146 return; 147 148 xo_emit("{T:/%s}:\n", name); 149 xo_open_container(name); 150 151 #define p(f, m) if (pfsyncstat.f || sflag <= 1) \ 152 xo_emit(m, (uintmax_t)pfsyncstat.f, plural(pfsyncstat.f)) 153 154 p(pfsyncs_ipackets, "\t{:received-inet-packets/%ju} " 155 "{N:/packet%s received (IPv4)}\n"); 156 p(pfsyncs_ipackets6, "\t{:received-inet6-packets/%ju} " 157 "{N:/packet%s received (IPv6)}\n"); 158 pfsync_acts_stats("input-histogram", "received", 159 &pfsyncstat.pfsyncs_iacts[0]); 160 p(pfsyncs_badif, "\t\t{:dropped-bad-interface/%ju} " 161 "{N:/packet%s discarded for bad interface}\n"); 162 p(pfsyncs_badttl, "\t\t{:dropped-bad-ttl/%ju} " 163 "{N:/packet%s discarded for bad ttl}\n"); 164 p(pfsyncs_hdrops, "\t\t{:dropped-short-header/%ju} " 165 "{N:/packet%s shorter than header}\n"); 166 p(pfsyncs_badver, "\t\t{:dropped-bad-version/%ju} " 167 "{N:/packet%s discarded for bad version}\n"); 168 p(pfsyncs_badauth, "\t\t{:dropped-bad-auth/%ju} " 169 "{N:/packet%s discarded for bad HMAC}\n"); 170 p(pfsyncs_badact,"\t\t{:dropped-bad-action/%ju} " 171 "{N:/packet%s discarded for bad action}\n"); 172 p(pfsyncs_badlen, "\t\t{:dropped-short/%ju} " 173 "{N:/packet%s discarded for short packet}\n"); 174 p(pfsyncs_badval, "\t\t{:dropped-bad-values/%ju} " 175 "{N:/state%s discarded for bad values}\n"); 176 p(pfsyncs_stale, "\t\t{:dropped-stale-state/%ju} " 177 "{N:/stale state%s}\n"); 178 p(pfsyncs_badstate, "\t\t{:dropped-failed-lookup/%ju} " 179 "{N:/failed state lookup\\/insert%s}\n"); 180 p(pfsyncs_opackets, "\t{:sent-inet-packets/%ju} " 181 "{N:/packet%s sent (IPv4})\n"); 182 p(pfsyncs_opackets6, "\t{:send-inet6-packets/%ju} " 183 "{N:/packet%s sent (IPv6})\n"); 184 pfsync_acts_stats("output-histogram", "sent", 185 &pfsyncstat.pfsyncs_oacts[0]); 186 p(pfsyncs_onomem, "\t\t{:discarded-no-memory/%ju} " 187 "{N:/failure%s due to mbuf memory error}\n"); 188 p(pfsyncs_oerrors, "\t\t{:send-errors/%ju} " 189 "{N:/send error%s}\n"); 190 #undef p 191 xo_close_container(name); 192 } 193 #endif /* PF */ 194 195 /* 196 * Display a formatted value, or a '-' in the same space. 197 */ 198 static void 199 show_stat(const char *fmt, int width, const char *name, 200 u_long value, short showvalue, int div1000) 201 { 202 const char *lsep, *rsep; 203 char newfmt[64]; 204 205 lsep = ""; 206 if (strncmp(fmt, "LS", 2) == 0) { 207 lsep = " "; 208 fmt += 2; 209 } 210 rsep = " "; 211 if (strncmp(fmt, "NRS", 3) == 0) { 212 rsep = ""; 213 fmt += 3; 214 } 215 if (showvalue == 0) { 216 /* Print just dash. */ 217 xo_emit("{P:/%s}{D:/%*s}{P:/%s}", lsep, width, "-", rsep); 218 return; 219 } 220 221 /* 222 * XXX: workaround {P:} modifier can't be empty and doesn't seem to 223 * take args... so we need to conditionally include it in the format. 224 */ 225 #define maybe_pad(pad) do { \ 226 if (strlen(pad)) { \ 227 snprintf(newfmt, sizeof(newfmt), "{P:%s}", pad); \ 228 xo_emit(newfmt); \ 229 } \ 230 } while (0) 231 232 if (hflag) { 233 char buf[5]; 234 235 /* Format in human readable form. */ 236 humanize_number(buf, sizeof(buf), (int64_t)value, "", 237 HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL | \ 238 ((div1000) ? HN_DIVISOR_1000 : 0)); 239 maybe_pad(lsep); 240 snprintf(newfmt, sizeof(newfmt), "{:%s/%%%ds}", name, width); 241 xo_emit(newfmt, buf); 242 maybe_pad(rsep); 243 } else { 244 /* Construct the format string. */ 245 maybe_pad(lsep); 246 snprintf(newfmt, sizeof(newfmt), "{:%s/%%%d%s}", 247 name, width, fmt); 248 xo_emit(newfmt, value); 249 maybe_pad(rsep); 250 } 251 } 252 253 /* 254 * Find next multiaddr for a given interface name. 255 */ 256 static struct ifmaddrs * 257 next_ifma(struct ifmaddrs *ifma, const char *name, const sa_family_t family) 258 { 259 260 for(; ifma != NULL; ifma = ifma->ifma_next) { 261 struct sockaddr_dl *sdl; 262 263 sdl = (struct sockaddr_dl *)ifma->ifma_name; 264 if (ifma->ifma_addr->sa_family == family && 265 strcmp(sdl->sdl_data, name) == 0) 266 break; 267 } 268 269 return (ifma); 270 } 271 272 /* 273 * Print a description of the network interfaces. 274 */ 275 void 276 intpr(void (*pfunc)(char *), int af) 277 { 278 struct ifaddrs *ifap, *ifa; 279 struct ifmaddrs *ifmap, *ifma; 280 u_int ifn_len_max = 5, ifn_len; 281 u_int has_ipv6 = 0, net_len = 13, addr_len = 17; 282 283 if (interval) 284 return sidewaysintpr(); 285 286 if (getifaddrs(&ifap) != 0) 287 err(EX_OSERR, "getifaddrs"); 288 if (aflag && getifmaddrs(&ifmap) != 0) 289 err(EX_OSERR, "getifmaddrs"); 290 291 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 292 if (interface != NULL && 293 strcmp(ifa->ifa_name, interface) != 0) 294 continue; 295 if (af != AF_UNSPEC && ifa->ifa_addr->sa_family != af) 296 continue; 297 ifn_len = strlen(ifa->ifa_name); 298 if ((ifa->ifa_flags & IFF_UP) == 0) 299 ++ifn_len; 300 ifn_len_max = MAX(ifn_len_max, ifn_len); 301 if (ifa->ifa_addr->sa_family == AF_INET6) 302 has_ipv6 = 1; 303 } 304 if (Wflag) { 305 if (has_ipv6) { 306 net_len = 24; 307 addr_len = 39; 308 } else 309 net_len = 18; 310 } 311 312 xo_open_list("interface"); 313 if (!pfunc) { 314 xo_emit("{T:/%-*.*s}", ifn_len_max, ifn_len_max, "Name"); 315 xo_emit(" {T:/%5.5s} {T:/%-*.*s} {T:/%-*.*s} {T:/%8.8s} " 316 "{T:/%5.5s} {T:/%5.5s}", 317 "Mtu", net_len, net_len, "Network", addr_len, addr_len, 318 "Address", "Ipkts", "Ierrs", "Idrop"); 319 if (bflag) 320 xo_emit(" {T:/%10.10s}","Ibytes"); 321 xo_emit(" {T:/%8.8s} {T:/%5.5s}", "Opkts", "Oerrs"); 322 if (bflag) 323 xo_emit(" {T:/%10.10s}","Obytes"); 324 xo_emit(" {T:/%5s}", "Coll"); 325 if (dflag) 326 xo_emit(" {T:/%5.5s}", "Drop"); 327 xo_emit("\n"); 328 } 329 330 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 331 bool network = false, link = false; 332 char *name, *xname, buf[IFNAMSIZ+1]; 333 const char *nn, *rn; 334 335 if (interface != NULL && strcmp(ifa->ifa_name, interface) != 0) 336 continue; 337 338 name = ifa->ifa_name; 339 340 if (pfunc) { 341 342 (*pfunc)(name); 343 344 /* 345 * Skip all ifaddrs belonging to same interface. 346 */ 347 while(ifa->ifa_next != NULL && 348 (strcmp(ifa->ifa_next->ifa_name, name) == 0)) { 349 ifa = ifa->ifa_next; 350 } 351 continue; 352 } 353 354 if (af != AF_UNSPEC && ifa->ifa_addr->sa_family != af) 355 continue; 356 357 xo_open_instance("interface"); 358 359 if ((ifa->ifa_flags & IFF_UP) == 0) { 360 xname = stpcpy(buf, name); 361 *xname++ = '*'; 362 *xname = '\0'; 363 xname = buf; 364 } else 365 xname = name; 366 367 xo_emit("{d:/%-*.*s}{etk:name}{eq:flags/0x%x}", 368 ifn_len_max, ifn_len_max, xname, name, ifa->ifa_flags); 369 370 #define IFA_MTU(ifa) (((struct if_data *)(ifa)->ifa_data)->ifi_mtu) 371 show_stat("lu", 6, "mtu", IFA_MTU(ifa), IFA_MTU(ifa), 0); 372 #undef IFA_MTU 373 374 switch (ifa->ifa_addr->sa_family) { 375 case AF_UNSPEC: 376 xo_emit("{:network/%-*.*s} ", net_len, net_len, 377 "none"); 378 xo_emit("{:address/%-*.*s} ", addr_len, addr_len, 379 "none"); 380 break; 381 case AF_INET: 382 #ifdef INET6 383 case AF_INET6: 384 #endif /* INET6 */ 385 nn = netname(ifa->ifa_addr, ifa->ifa_netmask); 386 rn = routename(ifa->ifa_addr, numeric_addr); 387 if (Wflag) { 388 xo_emit("{t:network/%-*s} ", net_len, nn); 389 xo_emit("{t:address/%-*s} ", addr_len, rn); 390 } else { 391 xo_emit("{d:network/%-*.*s}{et:network} ", 392 net_len, net_len, nn, nn); 393 xo_emit("{d:address/%-*.*s}{et:address} ", 394 addr_len, addr_len, rn, rn); 395 } 396 397 network = true; 398 break; 399 case AF_LINK: 400 { 401 struct sockaddr_dl *sdl; 402 char linknum[sizeof("<Link#32767>")]; 403 404 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 405 snprintf(linknum, sizeof(linknum), "<Link#%d>", sdl->sdl_index); 406 xo_emit("{t:network/%-*.*s} ", net_len, net_len, 407 linknum); 408 if (sdl->sdl_nlen == 0 && 409 sdl->sdl_alen == 0 && 410 sdl->sdl_slen == 0) 411 xo_emit("{P:/%*s} ", addr_len, ""); 412 else 413 xo_emit("{t:address/%-*.*s} ", addr_len, 414 addr_len, routename(ifa->ifa_addr, 1)); 415 link = true; 416 break; 417 } 418 } 419 420 #define IFA_STAT(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s) 421 show_stat("lu", 8, "received-packets", IFA_STAT(ipackets), 422 link|network, 1); 423 show_stat("lu", 5, "received-errors", IFA_STAT(ierrors), 424 link, 1); 425 show_stat("lu", 5, "dropped-packets", IFA_STAT(iqdrops), 426 link, 1); 427 if (bflag) 428 show_stat("lu", 10, "received-bytes", IFA_STAT(ibytes), 429 link|network, 0); 430 show_stat("lu", 8, "sent-packets", IFA_STAT(opackets), 431 link|network, 1); 432 show_stat("lu", 5, "send-errors", IFA_STAT(oerrors), link, 1); 433 if (bflag) 434 show_stat("lu", 10, "sent-bytes", IFA_STAT(obytes), 435 link|network, 0); 436 show_stat("NRSlu", 5, "collisions", IFA_STAT(collisions), 437 link, 1); 438 if (dflag) 439 show_stat("LSlu", 5, "dropped-packets", 440 IFA_STAT(oqdrops), link, 1); 441 xo_emit("\n"); 442 443 if (!aflag) { 444 xo_close_instance("interface"); 445 continue; 446 } 447 448 /* 449 * Print family's multicast addresses. 450 */ 451 xo_open_list("multicast-address"); 452 for (ifma = next_ifma(ifmap, ifa->ifa_name, 453 ifa->ifa_addr->sa_family); 454 ifma != NULL; 455 ifma = next_ifma(ifma, ifa->ifa_name, 456 ifa->ifa_addr->sa_family)) { 457 const char *fmt = NULL; 458 459 xo_open_instance("multicast-address"); 460 switch (ifma->ifma_addr->sa_family) { 461 case AF_LINK: 462 { 463 struct sockaddr_dl *sdl; 464 465 sdl = (struct sockaddr_dl *)ifma->ifma_addr; 466 if (sdl->sdl_type != IFT_ETHER && 467 sdl->sdl_type != IFT_FDDI) 468 break; 469 } 470 /* FALLTHROUGH */ 471 case AF_INET: 472 #ifdef INET6 473 case AF_INET6: 474 #endif /* INET6 */ 475 fmt = routename(ifma->ifma_addr, numeric_addr); 476 break; 477 } 478 if (fmt) { 479 if (Wflag) 480 xo_emit("{P:/%27s }" 481 "{t:address/%-17s/}", "", fmt); 482 else 483 xo_emit("{P:/%25s }" 484 "{t:address/%-17.17s/}", "", fmt); 485 if (ifma->ifma_addr->sa_family == AF_LINK) { 486 xo_emit(" {:received-packets/%8lu}", 487 IFA_STAT(imcasts)); 488 xo_emit("{P:/%*s}", bflag? 17 : 6, ""); 489 xo_emit(" {:sent-packets/%8lu}", 490 IFA_STAT(omcasts)); 491 } 492 xo_emit("\n"); 493 } 494 xo_close_instance("multicast-address"); 495 ifma = ifma->ifma_next; 496 } 497 xo_close_list("multicast-address"); 498 xo_close_instance("interface"); 499 } 500 xo_close_list("interface"); 501 502 freeifaddrs(ifap); 503 if (aflag) 504 freeifmaddrs(ifmap); 505 } 506 507 struct iftot { 508 u_long ift_ip; /* input packets */ 509 u_long ift_ie; /* input errors */ 510 u_long ift_id; /* input drops */ 511 u_long ift_op; /* output packets */ 512 u_long ift_oe; /* output errors */ 513 u_long ift_od; /* output drops */ 514 u_long ift_co; /* collisions */ 515 u_long ift_ib; /* input bytes */ 516 u_long ift_ob; /* output bytes */ 517 }; 518 519 /* 520 * Obtain stats for interface(s). 521 */ 522 static void 523 fill_iftot(struct iftot *st) 524 { 525 struct ifaddrs *ifap, *ifa; 526 bool found = false; 527 528 if (getifaddrs(&ifap) != 0) 529 xo_err(EX_OSERR, "getifaddrs"); 530 531 bzero(st, sizeof(*st)); 532 533 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 534 if (ifa->ifa_addr->sa_family != AF_LINK) 535 continue; 536 if (interface) { 537 if (strcmp(ifa->ifa_name, interface) == 0) 538 found = true; 539 else 540 continue; 541 } 542 543 st->ift_ip += IFA_STAT(ipackets); 544 st->ift_ie += IFA_STAT(ierrors); 545 st->ift_id += IFA_STAT(iqdrops); 546 st->ift_ib += IFA_STAT(ibytes); 547 st->ift_op += IFA_STAT(opackets); 548 st->ift_oe += IFA_STAT(oerrors); 549 st->ift_od += IFA_STAT(oqdrops); 550 st->ift_ob += IFA_STAT(obytes); 551 st->ift_co += IFA_STAT(collisions); 552 } 553 554 if (interface && found == false) 555 xo_err(EX_DATAERR, "interface %s not found", interface); 556 557 freeifaddrs(ifap); 558 } 559 560 /* 561 * Set a flag to indicate that a signal from the periodic itimer has been 562 * caught. 563 */ 564 static sig_atomic_t signalled; 565 static void 566 catchalarm(int signo __unused) 567 { 568 signalled = true; 569 } 570 571 /* 572 * Print a running summary of interface statistics. 573 * Repeat display every interval seconds, showing statistics 574 * collected over that interval. Assumes that interval is non-zero. 575 * First line printed at top of screen is always cumulative. 576 */ 577 static void 578 sidewaysintpr(void) 579 { 580 struct iftot ift[2], *new, *old; 581 struct itimerval interval_it; 582 int oldmask, line; 583 584 new = &ift[0]; 585 old = &ift[1]; 586 fill_iftot(old); 587 588 (void)signal(SIGALRM, catchalarm); 589 signalled = false; 590 interval_it.it_interval.tv_sec = interval; 591 interval_it.it_interval.tv_usec = 0; 592 interval_it.it_value = interval_it.it_interval; 593 setitimer(ITIMER_REAL, &interval_it, NULL); 594 xo_open_list("interface-statistics"); 595 596 banner: 597 xo_emit("{T:/%17s} {T:/%14s} {T:/%16s}\n", "input", 598 interface != NULL ? interface : "(Total)", "output"); 599 xo_emit("{T:/%10s} {T:/%5s} {T:/%5s} {T:/%10s} {T:/%10s} {T:/%5s} " 600 "{T:/%10s} {T:/%5s}", 601 "packets", "errs", "idrops", "bytes", "packets", "errs", "bytes", 602 "colls"); 603 if (dflag) 604 xo_emit(" {T:/%5.5s}", "drops"); 605 xo_emit("\n"); 606 xo_flush(); 607 line = 0; 608 609 loop: 610 if ((noutputs != 0) && (--noutputs == 0)) { 611 xo_close_list("interface-statistics"); 612 return; 613 } 614 oldmask = sigblock(sigmask(SIGALRM)); 615 while (!signalled) 616 sigpause(0); 617 signalled = false; 618 sigsetmask(oldmask); 619 line++; 620 621 fill_iftot(new); 622 623 xo_open_instance("stats"); 624 show_stat("lu", 10, "received-packets", 625 new->ift_ip - old->ift_ip, 1, 1); 626 show_stat("lu", 5, "received-errors", 627 new->ift_ie - old->ift_ie, 1, 1); 628 show_stat("lu", 5, "dropped-packets", 629 new->ift_id - old->ift_id, 1, 1); 630 show_stat("lu", 10, "received-bytes", 631 new->ift_ib - old->ift_ib, 1, 0); 632 show_stat("lu", 10, "sent-packets", 633 new->ift_op - old->ift_op, 1, 1); 634 show_stat("lu", 5, "send-errors", 635 new->ift_oe - old->ift_oe, 1, 1); 636 show_stat("lu", 10, "sent-bytes", 637 new->ift_ob - old->ift_ob, 1, 0); 638 show_stat("NRSlu", 5, "collisions", 639 new->ift_co - old->ift_co, 1, 1); 640 if (dflag) 641 show_stat("LSlu", 5, "dropped-packets", 642 new->ift_od - old->ift_od, 1, 1); 643 xo_close_instance("stats"); 644 xo_emit("\n"); 645 xo_flush(); 646 647 if (new == &ift[0]) { 648 new = &ift[1]; 649 old = &ift[0]; 650 } else { 651 new = &ift[0]; 652 old = &ift[1]; 653 } 654 655 if (line == 21) 656 goto banner; 657 else 658 goto loop; 659 660 /* NOTREACHED */ 661 } 662