| File: | src/usr.bin/netstat/if.c |
| Warning: | line 187, column 31 Access to field 'ifi_mtu' results in a dereference of an undefined pointer value (loaded from variable 'ifd') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: if.c,v 1.81 2023/03/08 04:43:12 guenther 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)) ((((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_FAIL0] = { "fails", "Ifail", "Ofail", if_show_fails }, | |||
| 82 | [IF_SHOW_ERRS1] = { "errs", "Ierrs", "Oerrs", if_show_errors }, | |||
| 83 | [IF_SHOW_DROP2] = { "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 | */ | |||
| 90 | void | |||
| 91 | intpr(int interval, int repeatcount) | |||
| 92 | { | |||
| 93 | struct if_msghdr ifm; | |||
| 94 | int mib[6] = { CTL_NET4, PF_ROUTE17, 0, 0, NET_RT_IFLIST3, 0 }; | |||
| 95 | char name[IFNAMSIZ16 + 1]; /* + 1 for the '*' */ | |||
| 96 | char *buf = NULL((void *)0), *next, *lim, *cp; | |||
| 97 | struct rt_msghdr *rtm; | |||
| 98 | struct ifa_msghdr *ifam; | |||
| 99 | struct if_data *ifd; | |||
| ||||
| 100 | struct sockaddr *sa, *rti_info[RTAX_MAX15]; | |||
| 101 | struct sockaddr_dl *sdl; | |||
| 102 | u_int64_t total = 0; | |||
| 103 | size_t len; | |||
| 104 | ||||
| 105 | if_errs = &if_show_errs[dflag]; | |||
| 106 | ||||
| 107 | if (interval) { | |||
| 108 | sidewaysintpr((unsigned)interval, repeatcount); | |||
| 109 | return; | |||
| 110 | } | |||
| 111 | ||||
| 112 | len = get_sysctl(mib, 6, &buf); | |||
| 113 | ||||
| 114 | printf("%-7.7s %-5.5s %-11.11s %-17.17s ", | |||
| 115 | "Name", "Mtu", "Network", "Address"); | |||
| 116 | if (bflag) | |||
| 117 | printf("%10.10s %10.10s", "Ibytes", "Obytes"); | |||
| 118 | else { | |||
| 119 | printf("%8.8s %5.5s %8.8s %5.5s %5.5s", | |||
| 120 | "Ipkts", if_errs->iname, | |||
| 121 | "Opkts", if_errs->oname, "Colls"); | |||
| 122 | } | |||
| 123 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
| 124 | ||||
| 125 | lim = buf + len; | |||
| 126 | for (next = buf; next < lim; next += rtm->rtm_msglen) { | |||
| 127 | rtm = (struct rt_msghdr *)next; | |||
| 128 | if (rtm->rtm_version != RTM_VERSION5) | |||
| 129 | continue; | |||
| 130 | switch (rtm->rtm_type) { | |||
| 131 | case RTM_IFINFO0xe: | |||
| 132 | total = 0; | |||
| 133 | bcopy(next, &ifm, sizeof ifm); | |||
| 134 | ifd = &ifm.ifm_data; | |||
| 135 | ||||
| 136 | sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); | |||
| 137 | get_rtaddrs(ifm.ifm_addrs, sa, rti_info); | |||
| 138 | ||||
| 139 | sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP4]; | |||
| 140 | if (sdl == NULL((void *)0) || sdl->sdl_family != AF_LINK18) | |||
| 141 | continue; | |||
| 142 | bzero(name, sizeof(name)); | |||
| 143 | if (sdl->sdl_nlen >= IFNAMSIZ16) | |||
| 144 | memcpy(name, sdl->sdl_data, IFNAMSIZ16 - 1); | |||
| 145 | else if (sdl->sdl_nlen > 0) | |||
| 146 | memcpy(name, sdl->sdl_data, sdl->sdl_nlen); | |||
| 147 | ||||
| 148 | if (interface != 0 && strcmp(name, interface) != 0) | |||
| 149 | continue; | |||
| 150 | ||||
| 151 | /* mark inactive interfaces with a '*' */ | |||
| 152 | cp = strchr(name, '\0'); | |||
| 153 | if ((ifm.ifm_flags & IFF_UP0x1) == 0) | |||
| 154 | *cp++ = '*'; | |||
| 155 | *cp = '\0'; | |||
| 156 | ||||
| 157 | if (qflag) { | |||
| 158 | total = ifd->ifi_ibytes + ifd->ifi_obytes + | |||
| 159 | ifd->ifi_ipackets + | |||
| 160 | ifd->ifi_opackets + | |||
| 161 | ifd->ifi_collisions; | |||
| 162 | total += if_errs->count(ifd->ifi_ierrors, | |||
| 163 | ifd->ifi_iqdrops); | |||
| 164 | total += if_errs->count(ifd->ifi_oerrors, | |||
| 165 | ifd->ifi_oqdrops); | |||
| 166 | if (total == 0) | |||
| 167 | continue; | |||
| 168 | } | |||
| 169 | ||||
| 170 | printf("%-7s %-5d ", name, ifd->ifi_mtu); | |||
| 171 | print_addr(rti_info[RTAX_IFP4], rti_info, ifd); | |||
| 172 | break; | |||
| 173 | case RTM_NEWADDR0xc: | |||
| 174 | if (qflag && total == 0) | |||
| 175 | continue; | |||
| 176 | if (interface != 0 && strcmp(name, interface) != 0) | |||
| 177 | continue; | |||
| 178 | ||||
| 179 | ifam = (struct ifa_msghdr *)next; | |||
| 180 | if ((ifam->ifam_addrs & (RTA_NETMASK0x4 | RTA_IFA0x20 | | |||
| 181 | RTA_BRD0x80)) == 0) | |||
| 182 | break; | |||
| 183 | ||||
| 184 | sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); | |||
| 185 | get_rtaddrs(ifam->ifam_addrs, sa, rti_info); | |||
| 186 | ||||
| 187 | printf("%-7s %-5d ", name, ifd->ifi_mtu); | |||
| ||||
| 188 | print_addr(rti_info[RTAX_IFA5], rti_info, ifd); | |||
| 189 | break; | |||
| 190 | } | |||
| 191 | } | |||
| 192 | free(buf); | |||
| 193 | } | |||
| 194 | ||||
| 195 | static void | |||
| 196 | print_addr(struct sockaddr *sa, struct sockaddr **rtinfo, struct if_data *ifd) | |||
| 197 | { | |||
| 198 | struct sockaddr_dl *sdl; | |||
| 199 | struct sockaddr_in *sin; | |||
| 200 | struct sockaddr_in6 *sin6; | |||
| 201 | char *cp; | |||
| 202 | int m, n; | |||
| 203 | ||||
| 204 | switch (sa->sa_family) { | |||
| 205 | case AF_UNSPEC0: | |||
| 206 | printf("%-11.11s ", "none"); | |||
| 207 | printf("%-17.17s ", "none"); | |||
| 208 | break; | |||
| 209 | case AF_INET2: | |||
| 210 | sin = (struct sockaddr_in *)sa; | |||
| 211 | cp = netname4(sin->sin_addr.s_addr, | |||
| 212 | ((struct sockaddr_in *)rtinfo[RTAX_NETMASK2])->sin_addr.s_addr); | |||
| 213 | if (vflag) | |||
| 214 | n = strlen(cp) < 11 ? 11 : strlen(cp); | |||
| 215 | else | |||
| 216 | n = 11; | |||
| 217 | printf("%-*.*s ", n, n, cp); | |||
| 218 | cp = routename4(sin->sin_addr.s_addr); | |||
| 219 | if (vflag) | |||
| 220 | n = strlen(cp) < 17 ? 17 : strlen(cp); | |||
| 221 | else | |||
| 222 | n = 17; | |||
| 223 | printf("%-*.*s ", n, n, cp); | |||
| 224 | ||||
| 225 | break; | |||
| 226 | case AF_INET624: | |||
| 227 | sin6 = (struct sockaddr_in6 *)sa; | |||
| 228 | #ifdef __KAME__ | |||
| 229 | if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)(((&sin6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xfe ) && (((&sin6->sin6_addr)->__u6_addr.__u6_addr8 [1] & 0xc0) == 0x80)) && | |||
| 230 | sin6->sin6_scope_id == 0) { | |||
| 231 | sin6->sin6_scope_id = | |||
| 232 | ntohs(*(u_int16_t *)(__uint16_t)(__builtin_constant_p(*(u_int16_t *) &sin6-> sin6_addr.__u6_addr.__u6_addr8[2]) ? (__uint16_t)(((__uint16_t )(*(u_int16_t *) &sin6->sin6_addr.__u6_addr.__u6_addr8 [2]) & 0xffU) << 8 | ((__uint16_t)(*(u_int16_t *) & sin6->sin6_addr.__u6_addr.__u6_addr8[2]) & 0xff00U) >> 8) : __swap16md(*(u_int16_t *) &sin6->sin6_addr.__u6_addr .__u6_addr8[2])) | |||
| 233 | &sin6->sin6_addr.s6_addr[2])(__uint16_t)(__builtin_constant_p(*(u_int16_t *) &sin6-> sin6_addr.__u6_addr.__u6_addr8[2]) ? (__uint16_t)(((__uint16_t )(*(u_int16_t *) &sin6->sin6_addr.__u6_addr.__u6_addr8 [2]) & 0xffU) << 8 | ((__uint16_t)(*(u_int16_t *) & sin6->sin6_addr.__u6_addr.__u6_addr8[2]) & 0xff00U) >> 8) : __swap16md(*(u_int16_t *) &sin6->sin6_addr.__u6_addr .__u6_addr8[2])); | |||
| 234 | sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[2] = 0; | |||
| 235 | sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[3] = 0; | |||
| 236 | } | |||
| 237 | #endif | |||
| 238 | cp = netname6(sin6, | |||
| 239 | (struct sockaddr_in6 *)rtinfo[RTAX_NETMASK2]); | |||
| 240 | if (vflag) | |||
| 241 | n = strlen(cp) < 11 ? 11 : strlen(cp); | |||
| 242 | else | |||
| 243 | n = 11; | |||
| 244 | printf("%-*.*s ", n, n, cp); | |||
| 245 | cp = routename6(sin6); | |||
| 246 | if (vflag) | |||
| 247 | n = strlen(cp) < 17 ? 17 : strlen(cp); | |||
| 248 | else | |||
| 249 | n = 17; | |||
| 250 | printf("%-*.*s ", n, n, cp); | |||
| 251 | break; | |||
| 252 | case AF_LINK18: | |||
| 253 | sdl = (struct sockaddr_dl *)sa; | |||
| 254 | m = printf("%-11.11s ", "<Link>"); | |||
| 255 | if (sdl->sdl_type == IFT_ETHER0x06 || | |||
| 256 | sdl->sdl_type == IFT_CARP0xf7 || | |||
| 257 | sdl->sdl_type == IFT_FDDI0x0f || | |||
| 258 | sdl->sdl_type == IFT_ISO880250x09) | |||
| 259 | printf("%-17.17s ", | |||
| 260 | ether_ntoa((struct ether_addr *)LLADDR(sdl)((caddr_t)((sdl)->sdl_data + (sdl)->sdl_nlen)))); | |||
| 261 | else { | |||
| 262 | cp = (char *)LLADDR(sdl)((caddr_t)((sdl)->sdl_data + (sdl)->sdl_nlen)); | |||
| 263 | n = sdl->sdl_alen; | |||
| 264 | goto hexprint; | |||
| 265 | } | |||
| 266 | break; | |||
| 267 | default: | |||
| 268 | m = printf("(%d)", sa->sa_family); | |||
| 269 | for (cp = sa->sa_len + (char *)sa; | |||
| 270 | --cp > sa->sa_data && (*cp == 0);) {} | |||
| 271 | n = cp - sa->sa_data + 1; | |||
| 272 | cp = sa->sa_data; | |||
| 273 | hexprint: | |||
| 274 | while (--n >= 0) | |||
| 275 | m += printf("%x%c", *cp++ & 0xff, | |||
| 276 | n > 0 ? '.' : ' '); | |||
| 277 | m = 30 - m; | |||
| 278 | while (m-- > 0) | |||
| 279 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
| 280 | break; | |||
| 281 | } | |||
| 282 | if (bflag) { | |||
| 283 | if (hflag) { | |||
| 284 | char ibytes[FMT_SCALED_STRSIZE7]; | |||
| 285 | char obytes[FMT_SCALED_STRSIZE7]; | |||
| 286 | fmt_scaled(ifd->ifi_ibytes, ibytes); | |||
| 287 | fmt_scaled(ifd->ifi_obytes, obytes); | |||
| 288 | printf("%10s %10s", ibytes, obytes); | |||
| 289 | } else | |||
| 290 | printf("%10llu %10llu", | |||
| 291 | ifd->ifi_ibytes, ifd->ifi_obytes); | |||
| 292 | } else | |||
| 293 | printf("%8llu %5llu %8llu %5llu %5llu", | |||
| 294 | ifd->ifi_ipackets, | |||
| 295 | if_errs->count(ifd->ifi_ierrors, ifd->ifi_iqdrops), | |||
| 296 | ifd->ifi_opackets, | |||
| 297 | if_errs->count(ifd->ifi_oerrors, ifd->ifi_oqdrops), | |||
| 298 | ifd->ifi_collisions); | |||
| 299 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
| 300 | } | |||
| 301 | ||||
| 302 | struct iftot { | |||
| 303 | char ift_name[IFNAMSIZ16]; /* interface name */ | |||
| 304 | u_int64_t ift_ip; /* input packets */ | |||
| 305 | u_int64_t ift_ib; /* input bytes */ | |||
| 306 | u_int64_t ift_ie; /* input errors */ | |||
| 307 | u_int64_t ift_iq; /* input qdrops */ | |||
| 308 | u_int64_t ift_op; /* output packets */ | |||
| 309 | u_int64_t ift_ob; /* output bytes */ | |||
| 310 | u_int64_t ift_oe; /* output errors */ | |||
| 311 | u_int64_t ift_oq; /* output qdrops */ | |||
| 312 | u_int64_t ift_co; /* collisions */ | |||
| 313 | } ip_cur, ip_old, sum_cur, sum_old; | |||
| 314 | ||||
| 315 | volatile sig_atomic_t signalled; /* set if alarm goes off "early" */ | |||
| 316 | ||||
| 317 | /* | |||
| 318 | * Print a running summary of interface statistics. | |||
| 319 | * Repeat display every interval seconds, showing statistics | |||
| 320 | * collected over that interval. Assumes that interval is non-zero. | |||
| 321 | * First line printed at top of screen is always cumulative. | |||
| 322 | */ | |||
| 323 | static void | |||
| 324 | sidewaysintpr(unsigned int interval, int repeatcount) | |||
| 325 | { | |||
| 326 | sigset_t emptyset; | |||
| 327 | int line; | |||
| 328 | char ibytes[FMT_SCALED_STRSIZE7]; | |||
| 329 | char obytes[FMT_SCALED_STRSIZE7]; | |||
| 330 | ||||
| 331 | fetchifs(); | |||
| 332 | if (ip_cur.ift_name[0] == '\0') { | |||
| 333 | fprintf(stderr(&__sF[2]), "%s: %s: unknown interface\n", | |||
| 334 | __progname, interface); | |||
| 335 | exit(1); | |||
| 336 | } | |||
| 337 | ||||
| 338 | (void)signal(SIGALRM14, catchalarm); | |||
| 339 | signalled = 0; | |||
| 340 | (void)alarm(interval); | |||
| 341 | banner: | |||
| 342 | if (bflag) | |||
| 343 | printf("%7.7s in %8.8s %6.6s out %5.5s", | |||
| 344 | ip_cur.ift_name, " ", | |||
| 345 | ip_cur.ift_name, " "); | |||
| 346 | else | |||
| 347 | printf("%5.5s in %5.5s%5.5s out %5.5s %5.5s", | |||
| 348 | ip_cur.ift_name, " ", | |||
| 349 | ip_cur.ift_name, " ", " "); | |||
| 350 | ||||
| 351 | if (bflag) | |||
| 352 | printf(" %7.7s in %8.8s %6.6s out %5.5s", | |||
| 353 | "total", " ", "total", " "); | |||
| 354 | else | |||
| 355 | printf(" %5.5s in %5.5s%5.5s out %5.5s %5.5s", | |||
| 356 | "total", " ", "total", " ", " "); | |||
| 357 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
| 358 | if (bflag) | |||
| 359 | printf("%10.10s %8.8s %10.10s %5.5s", | |||
| 360 | "bytes", " ", "bytes", " "); | |||
| 361 | else | |||
| 362 | printf("%8.8s %5.5s %8.8s %5.5s %5.5s", | |||
| 363 | "packets", if_errs->name, | |||
| 364 | "packets", if_errs->name, "colls"); | |||
| 365 | ||||
| 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", "errs", "packets", "errs", "colls"); | |||
| 372 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
| 373 | fflush(stdout(&__sF[1])); | |||
| 374 | line = 0; | |||
| 375 | bzero(&ip_old, sizeof(ip_old)); | |||
| 376 | bzero(&sum_old, sizeof(sum_old)); | |||
| 377 | loop: | |||
| 378 | bzero(&sum_cur, sizeof(sum_cur)); | |||
| 379 | ||||
| 380 | fetchifs(); | |||
| 381 | ||||
| 382 | if (bflag) { | |||
| 383 | if (hflag) { | |||
| 384 | fmt_scaled(ip_cur.ift_ib - ip_old.ift_ib, ibytes); | |||
| 385 | fmt_scaled(ip_cur.ift_ob - ip_old.ift_ob, obytes); | |||
| 386 | printf("%10s %8.8s %10s %5.5s", | |||
| 387 | ibytes, " ", obytes, " "); | |||
| 388 | } else | |||
| 389 | printf("%10llu %8.8s %10llu %5.5s", | |||
| 390 | ip_cur.ift_ib - ip_old.ift_ib, " ", | |||
| 391 | ip_cur.ift_ob - ip_old.ift_ob, " "); | |||
| 392 | } else | |||
| 393 | printf("%8llu %5llu %8llu %5llu %5llu", | |||
| 394 | ip_cur.ift_ip - ip_old.ift_ip, | |||
| 395 | if_errs->count(ip_cur.ift_ie - ip_old.ift_ie, | |||
| 396 | ip_cur.ift_iq - ip_old.ift_iq), | |||
| 397 | ip_cur.ift_op - ip_old.ift_op, | |||
| 398 | if_errs->count(ip_cur.ift_oe - ip_old.ift_oe, | |||
| 399 | ip_cur.ift_oq - ip_old.ift_oq), | |||
| 400 | ip_cur.ift_co - ip_old.ift_co); | |||
| 401 | ||||
| 402 | ip_old = ip_cur; | |||
| 403 | ||||
| 404 | if (bflag) { | |||
| 405 | if (hflag) { | |||
| 406 | fmt_scaled(sum_cur.ift_ib - sum_old.ift_ib, ibytes); | |||
| 407 | fmt_scaled(sum_cur.ift_ob - sum_old.ift_ob, obytes); | |||
| 408 | printf("%10s %8.8s %10s %5.5s", | |||
| 409 | ibytes, " ", obytes, " "); | |||
| 410 | } else | |||
| 411 | printf("%10llu %8.8s %10llu %5.5s", | |||
| 412 | sum_cur.ift_ib - sum_old.ift_ib, " ", | |||
| 413 | sum_cur.ift_ob - sum_old.ift_ob, " "); | |||
| 414 | } else | |||
| 415 | printf("%8llu %5llu %8llu %5llu %5llu", | |||
| 416 | sum_cur.ift_ip - sum_old.ift_ip, | |||
| 417 | if_errs->count(sum_cur.ift_ie - sum_old.ift_ie, | |||
| 418 | sum_cur.ift_iq - sum_old.ift_iq), | |||
| 419 | sum_cur.ift_op - sum_old.ift_op, | |||
| 420 | if_errs->count(sum_cur.ift_oe - sum_old.ift_oe, | |||
| 421 | sum_cur.ift_oq - sum_old.ift_oq), | |||
| 422 | sum_cur.ift_co - sum_old.ift_co); | |||
| 423 | ||||
| 424 | sum_old = sum_cur; | |||
| 425 | ||||
| 426 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
| 427 | fflush(stdout(&__sF[1])); | |||
| 428 | if (repeatcount && --repeatcount == 0) | |||
| 429 | return; | |||
| 430 | line++; | |||
| 431 | sigemptyset(&emptyset); | |||
| 432 | if (!signalled) | |||
| 433 | sigsuspend(&emptyset); | |||
| 434 | signalled = 0; | |||
| 435 | (void)alarm(interval); | |||
| 436 | if (line == 21 && isatty(STDOUT_FILENO1)) | |||
| 437 | goto banner; | |||
| 438 | goto loop; | |||
| 439 | } | |||
| 440 | ||||
| 441 | /* | |||
| 442 | * Called if an interval expires before sidewaysintpr has completed a loop. | |||
| 443 | * Sets a flag to not wait for the alarm. | |||
| 444 | */ | |||
| 445 | static void | |||
| 446 | catchalarm(int signo) | |||
| 447 | { | |||
| 448 | signalled = 1; | |||
| 449 | } | |||
| 450 | ||||
| 451 | static void | |||
| 452 | get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) | |||
| 453 | { | |||
| 454 | int i; | |||
| 455 | ||||
| 456 | for (i = 0; i < RTAX_MAX15; i++) { | |||
| 457 | if (addrs & (1 << i)) { | |||
| 458 | rti_info[i] = sa; | |||
| 459 | sa = (struct sockaddr *)((char *)(sa) + | |||
| 460 | roundup(sa->sa_len, sizeof(long))((((sa->sa_len)+((sizeof(long))-1))/(sizeof(long)))*(sizeof (long)))); | |||
| 461 | } else | |||
| 462 | rti_info[i] = NULL((void *)0); | |||
| 463 | } | |||
| 464 | } | |||
| 465 | ||||
| 466 | ||||
| 467 | static int | |||
| 468 | isegress(char *name) | |||
| 469 | { | |||
| 470 | static int s = -1; | |||
| 471 | int len; | |||
| 472 | struct ifgroupreq ifgr; | |||
| 473 | struct ifg_req *ifg; | |||
| 474 | int rv = 0; | |||
| 475 | ||||
| 476 | if (s == -1) { | |||
| 477 | if ((s = socket(AF_INET2, SOCK_DGRAM2, 0)) == -1) | |||
| 478 | return 0; | |||
| 479 | } | |||
| 480 | ||||
| 481 | memset(&ifgr, 0, sizeof(ifgr)); | |||
| 482 | strlcpy(ifgr.ifgr_name, name, IFNAMSIZ16); | |||
| 483 | ||||
| 484 | if (ioctl(s, SIOCGIFGROUP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((136))), (caddr_t)&ifgr) == -1) { | |||
| 485 | return 0; | |||
| 486 | } | |||
| 487 | ||||
| 488 | len = ifgr.ifgr_len; | |||
| 489 | ifgr.ifgr_groupsifgr_ifgru.ifgru_groups = calloc(len, 1); | |||
| 490 | if (ifgr.ifgr_groupsifgr_ifgru.ifgru_groups == NULL((void *)0)) | |||
| 491 | err(1, "getifgroups"); | |||
| 492 | if (ioctl(s, SIOCGIFGROUP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((136))), (caddr_t)&ifgr) == -1) | |||
| 493 | err(1, "SIOCGIFGROUP"); | |||
| 494 | ||||
| 495 | ifg = ifgr.ifgr_groupsifgr_ifgru.ifgru_groups; | |||
| 496 | for (; ifg && len >= sizeof(struct ifg_req); ifg++) { | |||
| 497 | len -= sizeof(struct ifg_req); | |||
| 498 | if (strcmp(ifg->ifgrq_groupifgrq_ifgrqu.ifgrqu_group, IFG_EGRESS"egress") == 0) | |||
| 499 | rv = 1; | |||
| 500 | } | |||
| 501 | ||||
| 502 | free(ifgr.ifgr_groupsifgr_ifgru.ifgru_groups); | |||
| 503 | return rv; | |||
| 504 | } | |||
| 505 | ||||
| 506 | static void | |||
| 507 | fetchifs(void) | |||
| 508 | { | |||
| 509 | struct if_msghdr ifm; | |||
| 510 | int mib[6] = { CTL_NET4, PF_ROUTE17, 0, 0, NET_RT_IFLIST3, 0 }; | |||
| 511 | struct rt_msghdr *rtm; | |||
| 512 | struct if_data *ifd; | |||
| 513 | struct sockaddr *sa, *rti_info[RTAX_MAX15]; | |||
| 514 | struct sockaddr_dl *sdl; | |||
| 515 | char *buf = NULL((void *)0), *next, *lim; | |||
| 516 | char name[IFNAMSIZ16]; | |||
| 517 | size_t len; | |||
| 518 | int takeit = 0; | |||
| 519 | int foundone = 0; | |||
| 520 | ||||
| 521 | len = get_sysctl(mib, 6, &buf); | |||
| 522 | ||||
| 523 | memset(&ip_cur, 0, sizeof(ip_cur)); | |||
| 524 | lim = buf + len; | |||
| 525 | for (next = buf; next < lim; next += rtm->rtm_msglen) { | |||
| 526 | rtm = (struct rt_msghdr *)next; | |||
| 527 | if (rtm->rtm_version != RTM_VERSION5) | |||
| 528 | continue; | |||
| 529 | switch (rtm->rtm_type) { | |||
| 530 | case RTM_IFINFO0xe: | |||
| 531 | bcopy(next, &ifm, sizeof ifm); | |||
| 532 | ifd = &ifm.ifm_data; | |||
| 533 | ||||
| 534 | sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); | |||
| 535 | get_rtaddrs(ifm.ifm_addrs, sa, rti_info); | |||
| 536 | ||||
| 537 | sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP4]; | |||
| 538 | if (sdl == NULL((void *)0) || sdl->sdl_family != AF_LINK18) | |||
| 539 | continue; | |||
| 540 | bzero(name, sizeof(name)); | |||
| 541 | if (sdl->sdl_nlen >= IFNAMSIZ16) | |||
| 542 | memcpy(name, sdl->sdl_data, IFNAMSIZ16 - 1); | |||
| 543 | else if (sdl->sdl_nlen > 0) | |||
| 544 | memcpy(name, sdl->sdl_data, sdl->sdl_nlen); | |||
| 545 | ||||
| 546 | if (interface != NULL((void *)0) && !strcmp(name, interface)) { | |||
| 547 | takeit = 1; | |||
| 548 | } else if (interface == NULL((void *)0) && foundone == 0 && | |||
| 549 | isegress(name)) { | |||
| 550 | takeit = 1; | |||
| 551 | foundone = 1; | |||
| 552 | } else | |||
| 553 | takeit = 0; | |||
| 554 | if (takeit) { | |||
| 555 | strlcpy(ip_cur.ift_name, name, | |||
| 556 | sizeof(ip_cur.ift_name)); | |||
| 557 | ip_cur.ift_ip = ifd->ifi_ipackets; | |||
| 558 | ip_cur.ift_ib = ifd->ifi_ibytes; | |||
| 559 | ip_cur.ift_ie = ifd->ifi_ierrors; | |||
| 560 | ip_cur.ift_iq = ifd->ifi_iqdrops; | |||
| 561 | ip_cur.ift_op = ifd->ifi_opackets; | |||
| 562 | ip_cur.ift_ob = ifd->ifi_obytes; | |||
| 563 | ip_cur.ift_oe = ifd->ifi_oerrors; | |||
| 564 | ip_cur.ift_oq = ifd->ifi_oqdrops; | |||
| 565 | ip_cur.ift_co = ifd->ifi_collisions; | |||
| 566 | } | |||
| 567 | ||||
| 568 | sum_cur.ift_ip += ifd->ifi_ipackets; | |||
| 569 | sum_cur.ift_ib += ifd->ifi_ibytes; | |||
| 570 | sum_cur.ift_ie += ifd->ifi_ierrors; | |||
| 571 | sum_cur.ift_iq += ifd->ifi_iqdrops; | |||
| 572 | sum_cur.ift_op += ifd->ifi_opackets; | |||
| 573 | sum_cur.ift_ob += ifd->ifi_obytes; | |||
| 574 | sum_cur.ift_oe += ifd->ifi_oerrors; | |||
| 575 | sum_cur.ift_oq += ifd->ifi_oqdrops; | |||
| 576 | sum_cur.ift_co += ifd->ifi_collisions; | |||
| 577 | break; | |||
| 578 | } | |||
| 579 | } | |||
| 580 | if (interface == NULL((void *)0) && foundone == 0) { | |||
| 581 | strlcpy(ip_cur.ift_name, name, | |||
| 582 | sizeof(ip_cur.ift_name)); | |||
| 583 | ip_cur.ift_ip = ifd->ifi_ipackets; | |||
| 584 | ip_cur.ift_ib = ifd->ifi_ibytes; | |||
| 585 | ip_cur.ift_ie = ifd->ifi_ierrors; | |||
| 586 | ip_cur.ift_iq = ifd->ifi_iqdrops; | |||
| 587 | ip_cur.ift_op = ifd->ifi_opackets; | |||
| 588 | ip_cur.ift_ob = ifd->ifi_obytes; | |||
| 589 | ip_cur.ift_oe = ifd->ifi_oerrors; | |||
| 590 | ip_cur.ift_oq = ifd->ifi_oqdrops; | |||
| 591 | ip_cur.ift_co = ifd->ifi_collisions; | |||
| 592 | } | |||
| 593 | free(buf); | |||
| 594 | } | |||
| 595 | ||||
| 596 | static uint64_t | |||
| 597 | if_show_fails(uint64_t errors, uint64_t qdrops) | |||
| 598 | { | |||
| 599 | return (errors + qdrops); | |||
| 600 | } | |||
| 601 | ||||
| 602 | static uint64_t | |||
| 603 | if_show_errors(uint64_t errors, uint64_t qdrops) | |||
| 604 | { | |||
| 605 | return (errors); | |||
| 606 | } | |||
| 607 | ||||
| 608 | static uint64_t | |||
| 609 | if_show_qdrops(uint64_t errors, uint64_t qdrops) | |||
| 610 | { | |||
| 611 | return (qdrops); | |||
| 612 | } |