Bug Summary

File:src/usr.bin/netstat/if.c
Warning:line 193, column 31
Access to field 'ifi_mtu' results in a dereference of an undefined pointer value (loaded from variable 'ifd')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name if.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/netstat/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/netstat/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/netstat/if.c
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)) ((((x)+((y)-1))/(y))*(y))
58
59#include "netstat.h"
60
61static void print_addr(struct sockaddr *, struct sockaddr **, struct if_data *);
62static void sidewaysintpr(u_int, int);
63static void catchalarm(int);
64static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
65static void fetchifs(void);
66
67struct iftot;
68
69struct 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
76static uint64_t if_show_fails(uint64_t, uint64_t);
77static uint64_t if_show_errors(uint64_t, uint64_t);
78static uint64_t if_show_qdrops(uint64_t, uint64_t);
79
80static 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};
85static 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 */
92void
93intpr(int interval, int repeatcount)
94{
95 struct if_msghdr ifm;
96 int mib[6] = { CTL_NET4, PF_ROUTE17, 0, 0, NET_RT_IFLIST3, 0 };
97 char name[IFNAMSIZ16 + 1]; /* + 1 for the '*' */
98 char *buf = NULL((void *)0), *next, *lim, *cp;
99 struct rt_msghdr *rtm;
100 struct ifa_msghdr *ifam;
101 struct if_data *ifd;
1
'ifd' declared without an initial value
102 struct sockaddr *sa, *rti_info[RTAX_MAX15];
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) {
2
Assuming 'interval' is 0
3
Taking false branch
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)
4
Assuming 'bflag' is not equal to 0
5
Taking true branch
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)
6
Assuming 'tflag' is not equal to 0
7
Taking true branch
126 printf(" %s", "Time");
127 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
8
Assuming '__isthreaded' is not equal to 0
9
'?' condition is false
128
129 lim = buf + len;
130 for (next = buf; next < lim; next += rtm->rtm_msglen) {
10
Loop condition is true. Entering loop body
131 rtm = (struct rt_msghdr *)next;
132 if (rtm->rtm_version != RTM_VERSION5)
11
Assuming field 'rtm_version' is equal to RTM_VERSION
12
Taking false branch
133 continue;
134 switch (rtm->rtm_type) {
13
Control jumps to 'case 12:' at line 179
135 case RTM_IFINFO0xe:
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_IFP4];
144 if (sdl == NULL((void *)0) || sdl->sdl_family != AF_LINK18)
145 continue;
146 bzero(name, sizeof(name));
147 if (sdl->sdl_nlen >= IFNAMSIZ16)
148 memcpy(name, sdl->sdl_data, IFNAMSIZ16 - 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_UP0x1) == 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_IFP4], rti_info, ifd);
178 break;
179 case RTM_NEWADDR0xc:
180 if (qflag && total == 0)
14
Assuming 'qflag' is 0
181 continue;
182 if (interface != 0 && strcmp(name, interface) != 0)
15
Assuming 'interface' is equal to null
183 continue;
184
185 ifam = (struct ifa_msghdr *)next;
186 if ((ifam->ifam_addrs & (RTA_NETMASK0x4 | RTA_IFA0x20 |
16
Assuming the condition is false
17
Taking false branch
187 RTA_BRD0x80)) == 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);
18
Access to field 'ifi_mtu' results in a dereference of an undefined pointer value (loaded from variable 'ifd')
194 print_addr(rti_info[RTAX_IFA5], rti_info, ifd);
195 break;
196 }
197 }
198 free(buf);
199}
200
201static void
202print_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_UNSPEC0:
212 printf("%-11.11s ", "none");
213 printf("%-17.17s ", "none");
214 break;
215 case AF_INET2:
216 sin = (struct sockaddr_in *)sa;
217 cp = netname4(sin->sin_addr.s_addr,
218 ((struct sockaddr_in *)rtinfo[RTAX_NETMASK2])->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_INET624:
233 sin6 = (struct sockaddr_in6 *)sa;
234#ifdef __KAME__
235 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))
&&
236 sin6->sin6_scope_id == 0) {
237 sin6->sin6_scope_id =
238 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]))
239 &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]))
;
240 sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[2] = 0;
241 sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[3] = 0;
242 }
243#endif
244 cp = netname6(sin6,
245 (struct sockaddr_in6 *)rtinfo[RTAX_NETMASK2]);
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_LINK18:
259 sdl = (struct sockaddr_dl *)sa;
260 m = printf("%-11.11s ", "<Link>");
261 if (sdl->sdl_type == IFT_ETHER0x06 ||
262 sdl->sdl_type == IFT_CARP0xf7 ||
263 sdl->sdl_type == IFT_FDDI0x0f ||
264 sdl->sdl_type == IFT_ISO880250x09)
265 printf("%-17.17s ",
266 ether_ntoa((struct ether_addr *)LLADDR(sdl)((caddr_t)((sdl)->sdl_data + (sdl)->sdl_nlen))));
267 else {
268 cp = (char *)LLADDR(sdl)((caddr_t)((sdl)->sdl_data + (sdl)->sdl_nlen));
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;
279hexprint:
280 while (--n >= 0)
281 m += printf("%x%c", *cp++ & 0xff,
282 n > 0 ? '.' : ' ');
283 m = 30 - m;
284 while (m-- > 0)
285 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
286 break;
287 }
288 if (bflag) {
289 if (hflag) {
290 char ibytes[FMT_SCALED_STRSIZE7];
291 char obytes[FMT_SCALED_STRSIZE7];
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')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
308}
309
310struct iftot {
311 char ift_name[IFNAMSIZ16]; /* 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
323volatile 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 */
331static void
332sidewaysintpr(unsigned int interval, int repeatcount)
333{
334 sigset_t emptyset;
335 int line;
336 char ibytes[FMT_SCALED_STRSIZE7];
337 char obytes[FMT_SCALED_STRSIZE7];
338
339 fetchifs();
340 if (ip_cur.ift_name[0] == '\0') {
341 fprintf(stderr(&__sF[2]), "%s: %s: unknown interface\n",
342 __progname, interface);
343 exit(1);
344 }
345
346 (void)signal(SIGALRM14, catchalarm);
347 signalled = 0;
348 (void)alarm(interval);
349banner:
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')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
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')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
381 fflush(stdout(&__sF[1]));
382 line = 0;
383 bzero(&ip_old, sizeof(ip_old));
384 bzero(&sum_old, sizeof(sum_old));
385loop:
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')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
435 fflush(stdout(&__sF[1]));
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_FILENO1))
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 */
454static void
455catchalarm(int signo)
456{
457 signalled = 1;
458}
459
460static void
461get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
462{
463 int i;
464
465 for (i = 0; i < RTAX_MAX15; i++) {
466 if (addrs & (1 << i)) {
467 rti_info[i] = sa;
468 sa = (struct sockaddr *)((char *)(sa) +
469 roundup(sa->sa_len, sizeof(long))((((sa->sa_len)+((sizeof(long))-1))/(sizeof(long)))*(sizeof
(long)))
);
470 } else
471 rti_info[i] = NULL((void *)0);
472 }
473}
474
475
476static int
477isegress(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_INET2, SOCK_DGRAM2, 0)) == -1)
487 return 0;
488 }
489
490 memset(&ifgr, 0, sizeof(ifgr));
491 strlcpy(ifgr.ifgr_name, name, IFNAMSIZ16);
492
493 if (ioctl(s, SIOCGIFGROUP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifgroupreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((136)))
, (caddr_t)&ifgr) == -1) {
494 return 0;
495 }
496
497 len = ifgr.ifgr_len;
498 ifgr.ifgr_groupsifgr_ifgru.ifgru_groups = calloc(len, 1);
499 if (ifgr.ifgr_groupsifgr_ifgru.ifgru_groups == NULL((void *)0))
500 err(1, "getifgroups");
501 if (ioctl(s, SIOCGIFGROUP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifgroupreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((136)))
, (caddr_t)&ifgr) == -1)
502 err(1, "SIOCGIFGROUP");
503
504 ifg = ifgr.ifgr_groupsifgr_ifgru.ifgru_groups;
505 for (; ifg && len >= sizeof(struct ifg_req); ifg++) {
506 len -= sizeof(struct ifg_req);
507 if (strcmp(ifg->ifgrq_groupifgrq_ifgrqu.ifgrqu_group, IFG_EGRESS"egress") == 0)
508 rv = 1;
509 }
510
511 free(ifgr.ifgr_groupsifgr_ifgru.ifgru_groups);
512 return rv;
513}
514
515static void
516fetchifs(void)
517{
518 struct if_msghdr ifm;
519 int mib[6] = { CTL_NET4, PF_ROUTE17, 0, 0, NET_RT_IFLIST3, 0 };
520 struct rt_msghdr *rtm;
521 struct if_data *ifd;
522 struct sockaddr *sa, *rti_info[RTAX_MAX15];
523 struct sockaddr_dl *sdl;
524 char *buf = NULL((void *)0), *next, *lim;
525 char name[IFNAMSIZ16];
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_VERSION5)
537 continue;
538 switch (rtm->rtm_type) {
539 case RTM_IFINFO0xe:
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_IFP4];
547 if (sdl == NULL((void *)0) || sdl->sdl_family != AF_LINK18)
548 continue;
549 bzero(name, sizeof(name));
550 if (sdl->sdl_nlen >= IFNAMSIZ16)
551 memcpy(name, sdl->sdl_data, IFNAMSIZ16 - 1);
552 else if (sdl->sdl_nlen > 0)
553 memcpy(name, sdl->sdl_data, sdl->sdl_nlen);
554
555 if (interface != NULL((void *)0) && !strcmp(name, interface)) {
556 takeit = 1;
557 } else if (interface == NULL((void *)0) && 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((void *)0) && 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
605static uint64_t
606if_show_fails(uint64_t errors, uint64_t qdrops)
607{
608 return (errors + qdrops);
609}
610
611static uint64_t
612if_show_errors(uint64_t errors, uint64_t qdrops)
613{
614 return (errors);
615}
616
617static uint64_t
618if_show_qdrops(uint64_t errors, uint64_t qdrops)
619{
620 return (qdrops);
621}