1 /* $OpenBSD: if.c,v 1.77 2021/01/16 17:42:52 claudio 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. 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 #include <sys/param.h> /* roundup() */ 34 #include <sys/types.h> 35 #include <sys/ioctl.h> 36 #include <sys/protosw.h> 37 #include <sys/socket.h> 38 #include <sys/sysctl.h> 39 40 #include <net/if.h> 41 #include <net/if_dl.h> 42 #include <net/if_types.h> 43 #include <net/route.h> 44 #include <netinet/in.h> 45 #include <netinet/in_var.h> 46 #include <netinet/if_ether.h> 47 #include <arpa/inet.h> 48 49 #include <err.h> 50 #include <limits.h> 51 #include <signal.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 #include <unistd.h> 56 #include <util.h> 57 58 #include "netstat.h" 59 60 static void print_addr(struct sockaddr *, struct sockaddr **, struct if_data *); 61 static void sidewaysintpr(u_int, int); 62 static void catchalarm(int); 63 static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); 64 static void fetchifs(void); 65 66 struct iftot; 67 68 struct if_show_err { 69 const char *name; 70 const char *iname; 71 const char *oname; 72 uint64_t (*count)(uint64_t, uint64_t); 73 }; 74 75 static uint64_t if_show_fails(uint64_t, uint64_t); 76 static uint64_t if_show_errors(uint64_t, uint64_t); 77 static uint64_t if_show_qdrops(uint64_t, uint64_t); 78 79 static const struct if_show_err if_show_errs[] = { 80 [IF_SHOW_FAIL] = { "fails", "Ifail", "Ofail", if_show_fails }, 81 [IF_SHOW_ERRS] = { "errs", "Ierrs", "Oerrs", if_show_errors }, 82 [IF_SHOW_DROP] = { "drops", "Idrop", "Odrop", if_show_qdrops }, 83 }; 84 static const struct if_show_err *if_errs = if_show_errs; 85 86 /* 87 * Print a description of the network interfaces. 88 * NOTE: ifnetaddr is the location of the kernel global "ifnet", 89 * which is a TAILQ_HEAD. 90 */ 91 void 92 intpr(int interval, int repeatcount) 93 { 94 struct if_msghdr ifm; 95 int mib[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; 96 char name[IFNAMSIZ + 1]; /* + 1 for the '*' */ 97 char *buf = NULL, *next, *lim, *cp; 98 struct rt_msghdr *rtm; 99 struct ifa_msghdr *ifam; 100 struct if_data *ifd; 101 struct sockaddr *sa, *rti_info[RTAX_MAX]; 102 struct sockaddr_dl *sdl; 103 u_int64_t total = 0; 104 size_t len; 105 106 if_errs = &if_show_errs[dflag]; 107 108 if (interval) { 109 sidewaysintpr((unsigned)interval, repeatcount); 110 return; 111 } 112 113 len = get_sysctl(mib, 6, &buf); 114 115 printf("%-7.7s %-5.5s %-11.11s %-17.17s ", 116 "Name", "Mtu", "Network", "Address"); 117 if (bflag) 118 printf("%10.10s %10.10s", "Ibytes", "Obytes"); 119 else { 120 printf("%8.8s %5.5s %8.8s %5.5s %5.5s", 121 "Ipkts", if_errs->iname, 122 "Opkts", if_errs->oname, "Colls"); 123 } 124 if (tflag) 125 printf(" %s", "Time"); 126 putchar('\n'); 127 128 lim = buf + len; 129 for (next = buf; next < lim; next += rtm->rtm_msglen) { 130 rtm = (struct rt_msghdr *)next; 131 if (rtm->rtm_version != RTM_VERSION) 132 continue; 133 switch (rtm->rtm_type) { 134 case RTM_IFINFO: 135 total = 0; 136 bcopy(next, &ifm, sizeof ifm); 137 ifd = &ifm.ifm_data; 138 139 sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); 140 get_rtaddrs(ifm.ifm_addrs, sa, rti_info); 141 142 sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP]; 143 if (sdl == NULL || sdl->sdl_family != AF_LINK) 144 continue; 145 bzero(name, sizeof(name)); 146 if (sdl->sdl_nlen >= IFNAMSIZ) 147 memcpy(name, sdl->sdl_data, IFNAMSIZ - 1); 148 else if (sdl->sdl_nlen > 0) 149 memcpy(name, sdl->sdl_data, sdl->sdl_nlen); 150 151 if (interface != 0 && strcmp(name, interface) != 0) 152 continue; 153 154 /* mark inactive interfaces with a '*' */ 155 cp = strchr(name, '\0'); 156 if ((ifm.ifm_flags & IFF_UP) == 0) 157 *cp++ = '*'; 158 *cp = '\0'; 159 160 if (qflag) { 161 total = ifd->ifi_ibytes + ifd->ifi_obytes + 162 ifd->ifi_ipackets + 163 ifd->ifi_opackets + 164 ifd->ifi_collisions; 165 total += if_errs->count(ifd->ifi_ierrors, 166 ifd->ifi_iqdrops); 167 total += if_errs->count(ifd->ifi_oerrors, 168 ifd->ifi_oqdrops); 169 if (tflag) 170 total += 0; // XXX ifnet.if_timer; 171 if (total == 0) 172 continue; 173 } 174 175 printf("%-7s %-5d ", name, ifd->ifi_mtu); 176 print_addr(rti_info[RTAX_IFP], rti_info, ifd); 177 break; 178 case RTM_NEWADDR: 179 if (qflag && total == 0) 180 continue; 181 if (interface != 0 && strcmp(name, interface) != 0) 182 continue; 183 184 ifam = (struct ifa_msghdr *)next; 185 if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA | 186 RTA_BRD)) == 0) 187 break; 188 189 sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); 190 get_rtaddrs(ifam->ifam_addrs, sa, rti_info); 191 192 printf("%-7s %-5d ", name, ifd->ifi_mtu); 193 print_addr(rti_info[RTAX_IFA], rti_info, ifd); 194 break; 195 } 196 } 197 free(buf); 198 } 199 200 static void 201 print_addr(struct sockaddr *sa, struct sockaddr **rtinfo, struct if_data *ifd) 202 { 203 struct sockaddr_dl *sdl; 204 struct sockaddr_in *sin; 205 struct sockaddr_in6 *sin6; 206 char *cp; 207 int m, n; 208 209 switch (sa->sa_family) { 210 case AF_UNSPEC: 211 printf("%-11.11s ", "none"); 212 printf("%-17.17s ", "none"); 213 break; 214 case AF_INET: 215 sin = (struct sockaddr_in *)sa; 216 cp = netname4(sin->sin_addr.s_addr, 217 ((struct sockaddr_in *)rtinfo[RTAX_NETMASK])->sin_addr.s_addr); 218 if (vflag) 219 n = strlen(cp) < 11 ? 11 : strlen(cp); 220 else 221 n = 11; 222 printf("%-*.*s ", n, n, cp); 223 cp = routename4(sin->sin_addr.s_addr); 224 if (vflag) 225 n = strlen(cp) < 17 ? 17 : strlen(cp); 226 else 227 n = 17; 228 printf("%-*.*s ", n, n, cp); 229 230 break; 231 case AF_INET6: 232 sin6 = (struct sockaddr_in6 *)sa; 233 #ifdef __KAME__ 234 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 235 sin6->sin6_scope_id == 0) { 236 sin6->sin6_scope_id = 237 ntohs(*(u_int16_t *) 238 &sin6->sin6_addr.s6_addr[2]); 239 sin6->sin6_addr.s6_addr[2] = 0; 240 sin6->sin6_addr.s6_addr[3] = 0; 241 } 242 #endif 243 cp = netname6(sin6, 244 (struct sockaddr_in6 *)rtinfo[RTAX_NETMASK]); 245 if (vflag) 246 n = strlen(cp) < 11 ? 11 : strlen(cp); 247 else 248 n = 11; 249 printf("%-*.*s ", n, n, cp); 250 cp = routename6(sin6); 251 if (vflag) 252 n = strlen(cp) < 17 ? 17 : strlen(cp); 253 else 254 n = 17; 255 printf("%-*.*s ", n, n, cp); 256 break; 257 case AF_LINK: 258 sdl = (struct sockaddr_dl *)sa; 259 m = printf("%-11.11s ", "<Link>"); 260 if (sdl->sdl_type == IFT_ETHER || 261 sdl->sdl_type == IFT_CARP || 262 sdl->sdl_type == IFT_FDDI || 263 sdl->sdl_type == IFT_ISO88025) 264 printf("%-17.17s ", 265 ether_ntoa((struct ether_addr *)LLADDR(sdl))); 266 else { 267 cp = (char *)LLADDR(sdl); 268 n = sdl->sdl_alen; 269 goto hexprint; 270 } 271 break; 272 default: 273 m = printf("(%d)", sa->sa_family); 274 for (cp = sa->sa_len + (char *)sa; 275 --cp > sa->sa_data && (*cp == 0);) {} 276 n = cp - sa->sa_data + 1; 277 cp = sa->sa_data; 278 hexprint: 279 while (--n >= 0) 280 m += printf("%x%c", *cp++ & 0xff, 281 n > 0 ? '.' : ' '); 282 m = 30 - m; 283 while (m-- > 0) 284 putchar(' '); 285 break; 286 } 287 if (bflag) { 288 if (hflag) { 289 char ibytes[FMT_SCALED_STRSIZE]; 290 char obytes[FMT_SCALED_STRSIZE]; 291 fmt_scaled(ifd->ifi_ibytes, ibytes); 292 fmt_scaled(ifd->ifi_obytes, obytes); 293 printf("%10s %10s", ibytes, obytes); 294 } else 295 printf("%10llu %10llu", 296 ifd->ifi_ibytes, ifd->ifi_obytes); 297 } else 298 printf("%8llu %5llu %8llu %5llu %5llu", 299 ifd->ifi_ipackets, 300 if_errs->count(ifd->ifi_ierrors, ifd->ifi_iqdrops), 301 ifd->ifi_opackets, 302 if_errs->count(ifd->ifi_oerrors, ifd->ifi_oqdrops), 303 ifd->ifi_collisions); 304 if (tflag) 305 printf(" %4d", 0 /* XXX ifnet.if_timer */); 306 putchar('\n'); 307 } 308 309 struct iftot { 310 char ift_name[IFNAMSIZ]; /* interface name */ 311 u_int64_t ift_ip; /* input packets */ 312 u_int64_t ift_ib; /* input bytes */ 313 u_int64_t ift_ie; /* input errors */ 314 u_int64_t ift_iq; /* input qdrops */ 315 u_int64_t ift_op; /* output packets */ 316 u_int64_t ift_ob; /* output bytes */ 317 u_int64_t ift_oe; /* output errors */ 318 u_int64_t ift_oq; /* output qdrops */ 319 u_int64_t ift_co; /* collisions */ 320 } ip_cur, ip_old, sum_cur, sum_old; 321 322 volatile sig_atomic_t signalled; /* set if alarm goes off "early" */ 323 324 /* 325 * Print a running summary of interface statistics. 326 * Repeat display every interval seconds, showing statistics 327 * collected over that interval. Assumes that interval is non-zero. 328 * First line printed at top of screen is always cumulative. 329 */ 330 static void 331 sidewaysintpr(unsigned int interval, int repeatcount) 332 { 333 sigset_t emptyset; 334 int line; 335 char ibytes[FMT_SCALED_STRSIZE]; 336 char obytes[FMT_SCALED_STRSIZE]; 337 338 fetchifs(); 339 if (ip_cur.ift_name[0] == '\0') { 340 fprintf(stderr, "%s: %s: unknown interface\n", 341 __progname, interface); 342 exit(1); 343 } 344 345 (void)signal(SIGALRM, catchalarm); 346 signalled = 0; 347 (void)alarm(interval); 348 banner: 349 if (bflag) 350 printf("%7.7s in %8.8s %6.6s out %5.5s", 351 ip_cur.ift_name, " ", 352 ip_cur.ift_name, " "); 353 else 354 printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s", 355 ip_cur.ift_name, " ", 356 ip_cur.ift_name, " ", " "); 357 358 if (bflag) 359 printf(" %7.7s in %8.8s %6.6s out %5.5s", 360 "total", " ", "total", " "); 361 else 362 printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s", 363 "total", " ", "total", " ", " "); 364 putchar('\n'); 365 if (bflag) 366 printf("%10.10s %8.8s %10.10s %5.5s", 367 "bytes", " ", "bytes", " "); 368 else 369 printf("%8.8s %5.5s %8.8s %5.5s %5.5s", 370 "packets", if_errs->name, 371 "packets", if_errs->name, "colls"); 372 373 if (bflag) 374 printf("%10.10s %8.8s %10.10s %5.5s", 375 "bytes", " ", "bytes", " "); 376 else 377 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s", 378 "packets", "errs", "packets", "errs", "colls"); 379 putchar('\n'); 380 fflush(stdout); 381 line = 0; 382 bzero(&ip_old, sizeof(ip_old)); 383 bzero(&sum_old, sizeof(sum_old)); 384 loop: 385 bzero(&sum_cur, sizeof(sum_cur)); 386 387 fetchifs(); 388 389 if (bflag) { 390 if (hflag) { 391 fmt_scaled(ip_cur.ift_ib - ip_old.ift_ib, ibytes); 392 fmt_scaled(ip_cur.ift_ob - ip_old.ift_ob, obytes); 393 printf("%10s %8.8s %10s %5.5s", 394 ibytes, " ", obytes, " "); 395 } else 396 printf("%10llu %8.8s %10llu %5.5s", 397 ip_cur.ift_ib - ip_old.ift_ib, " ", 398 ip_cur.ift_ob - ip_old.ift_ob, " "); 399 } else 400 printf("%8llu %5llu %8llu %5llu %5llu", 401 ip_cur.ift_ip - ip_old.ift_ip, 402 if_errs->count(ip_cur.ift_ie - ip_old.ift_ie, 403 ip_cur.ift_iq - ip_old.ift_iq), 404 ip_cur.ift_op - ip_old.ift_op, 405 if_errs->count(ip_cur.ift_oe - ip_old.ift_oe, 406 ip_cur.ift_oq - ip_old.ift_oq), 407 ip_cur.ift_co - ip_old.ift_co); 408 409 ip_old = ip_cur; 410 411 if (bflag) { 412 if (hflag) { 413 fmt_scaled(sum_cur.ift_ib - sum_old.ift_ib, ibytes); 414 fmt_scaled(sum_cur.ift_ob - sum_old.ift_ob, obytes); 415 printf("%10s %8.8s %10s %5.5s", 416 ibytes, " ", obytes, " "); 417 } else 418 printf("%10llu %8.8s %10llu %5.5s", 419 sum_cur.ift_ib - sum_old.ift_ib, " ", 420 sum_cur.ift_ob - sum_old.ift_ob, " "); 421 } else 422 printf("%8llu %5llu %8llu %5llu %5llu", 423 sum_cur.ift_ip - sum_old.ift_ip, 424 if_errs->count(sum_cur.ift_ie - sum_old.ift_ie, 425 sum_cur.ift_iq - sum_old.ift_iq), 426 sum_cur.ift_op - sum_old.ift_op, 427 if_errs->count(sum_cur.ift_oe - sum_old.ift_oe, 428 sum_cur.ift_oq - sum_old.ift_oq), 429 sum_cur.ift_co - sum_old.ift_co); 430 431 sum_old = sum_cur; 432 433 putchar('\n'); 434 fflush(stdout); 435 if (repeatcount && --repeatcount == 0) 436 return; 437 line++; 438 sigemptyset(&emptyset); 439 if (!signalled) 440 sigsuspend(&emptyset); 441 signalled = 0; 442 (void)alarm(interval); 443 if (line == 21 && isatty(STDOUT_FILENO)) 444 goto banner; 445 goto loop; 446 } 447 448 /* 449 * Called if an interval expires before sidewaysintpr has completed a loop. 450 * Sets a flag to not wait for the alarm. 451 */ 452 /* ARGSUSED */ 453 static void 454 catchalarm(int signo) 455 { 456 signalled = 1; 457 } 458 459 static void 460 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 461 { 462 int i; 463 464 for (i = 0; i < RTAX_MAX; i++) { 465 if (addrs & (1 << i)) { 466 rti_info[i] = sa; 467 sa = (struct sockaddr *)((char *)(sa) + 468 roundup(sa->sa_len, sizeof(long))); 469 } else 470 rti_info[i] = NULL; 471 } 472 } 473 474 475 static int 476 isegress(char *name) 477 { 478 static int s = -1; 479 int len; 480 struct ifgroupreq ifgr; 481 struct ifg_req *ifg; 482 int rv = 0; 483 484 if (s == -1) { 485 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 486 return 0; 487 } 488 489 memset(&ifgr, 0, sizeof(ifgr)); 490 strlcpy(ifgr.ifgr_name, name, IFNAMSIZ); 491 492 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) { 493 return 0; 494 } 495 496 len = ifgr.ifgr_len; 497 ifgr.ifgr_groups = calloc(len, 1); 498 if (ifgr.ifgr_groups == NULL) 499 err(1, "getifgroups"); 500 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 501 err(1, "SIOCGIFGROUP"); 502 503 ifg = ifgr.ifgr_groups; 504 for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 505 len -= sizeof(struct ifg_req); 506 if (strcmp(ifg->ifgrq_group, IFG_EGRESS) == 0) 507 rv = 1; 508 } 509 510 free(ifgr.ifgr_groups); 511 return rv; 512 } 513 514 static void 515 fetchifs(void) 516 { 517 struct if_msghdr ifm; 518 int mib[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; 519 struct rt_msghdr *rtm; 520 struct if_data *ifd; 521 struct sockaddr *sa, *rti_info[RTAX_MAX]; 522 struct sockaddr_dl *sdl; 523 char *buf = NULL, *next, *lim; 524 char name[IFNAMSIZ]; 525 size_t len; 526 int takeit = 0; 527 int foundone = 0; 528 529 len = get_sysctl(mib, 6, &buf); 530 531 memset(&ip_cur, 0, sizeof(ip_cur)); 532 lim = buf + len; 533 for (next = buf; next < lim; next += rtm->rtm_msglen) { 534 rtm = (struct rt_msghdr *)next; 535 if (rtm->rtm_version != RTM_VERSION) 536 continue; 537 switch (rtm->rtm_type) { 538 case RTM_IFINFO: 539 bcopy(next, &ifm, sizeof ifm); 540 ifd = &ifm.ifm_data; 541 542 sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); 543 get_rtaddrs(ifm.ifm_addrs, sa, rti_info); 544 545 sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP]; 546 if (sdl == NULL || sdl->sdl_family != AF_LINK) 547 continue; 548 bzero(name, sizeof(name)); 549 if (sdl->sdl_nlen >= IFNAMSIZ) 550 memcpy(name, sdl->sdl_data, IFNAMSIZ - 1); 551 else if (sdl->sdl_nlen > 0) 552 memcpy(name, sdl->sdl_data, sdl->sdl_nlen); 553 554 if (interface != NULL && !strcmp(name, interface)) { 555 takeit = 1; 556 } else if (interface == NULL && foundone == 0 && 557 isegress(name)) { 558 takeit = 1; 559 foundone = 1; 560 } else 561 takeit = 0; 562 if (takeit) { 563 strlcpy(ip_cur.ift_name, name, 564 sizeof(ip_cur.ift_name)); 565 ip_cur.ift_ip = ifd->ifi_ipackets; 566 ip_cur.ift_ib = ifd->ifi_ibytes; 567 ip_cur.ift_ie = ifd->ifi_ierrors; 568 ip_cur.ift_iq = ifd->ifi_iqdrops; 569 ip_cur.ift_op = ifd->ifi_opackets; 570 ip_cur.ift_ob = ifd->ifi_obytes; 571 ip_cur.ift_oe = ifd->ifi_oerrors; 572 ip_cur.ift_oq = ifd->ifi_oqdrops; 573 ip_cur.ift_co = ifd->ifi_collisions; 574 } 575 576 sum_cur.ift_ip += ifd->ifi_ipackets; 577 sum_cur.ift_ib += ifd->ifi_ibytes; 578 sum_cur.ift_ie += ifd->ifi_ierrors; 579 sum_cur.ift_iq += ifd->ifi_iqdrops; 580 sum_cur.ift_op += ifd->ifi_opackets; 581 sum_cur.ift_ob += ifd->ifi_obytes; 582 sum_cur.ift_oe += ifd->ifi_oerrors; 583 sum_cur.ift_oq += ifd->ifi_oqdrops; 584 sum_cur.ift_co += ifd->ifi_collisions; 585 break; 586 } 587 } 588 if (interface == NULL && foundone == 0) { 589 strlcpy(ip_cur.ift_name, name, 590 sizeof(ip_cur.ift_name)); 591 ip_cur.ift_ip = ifd->ifi_ipackets; 592 ip_cur.ift_ib = ifd->ifi_ibytes; 593 ip_cur.ift_ie = ifd->ifi_ierrors; 594 ip_cur.ift_iq = ifd->ifi_iqdrops; 595 ip_cur.ift_op = ifd->ifi_opackets; 596 ip_cur.ift_ob = ifd->ifi_obytes; 597 ip_cur.ift_oe = ifd->ifi_oerrors; 598 ip_cur.ift_oq = ifd->ifi_oqdrops; 599 ip_cur.ift_co = ifd->ifi_collisions; 600 } 601 free(buf); 602 } 603 604 static uint64_t 605 if_show_fails(uint64_t errors, uint64_t qdrops) 606 { 607 return (errors + qdrops); 608 } 609 610 static uint64_t 611 if_show_errors(uint64_t errors, uint64_t qdrops) 612 { 613 return (errors); 614 } 615 616 static uint64_t 617 if_show_qdrops(uint64_t errors, uint64_t qdrops) 618 { 619 return (qdrops); 620 } 621