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