]> git.saurik.com Git - apple/network_cmds.git/blame - netstat.tproj/if.c
network_cmds-606.100.3.tar.gz
[apple/network_cmds.git] / netstat.tproj / if.c
CommitLineData
9c859447 1/*
e0b07f2d 2 * Copyright (c) 2008-2019 Apple Inc. All rights reserved.
9c859447
A
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
b7080c8e
A
28/*
29 * Copyright (c) 1983, 1988, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 */
60
b7080c8e 61#include <sys/types.h>
b7080c8e 62#include <sys/socket.h>
7ba0088d 63#include <sys/sysctl.h>
7af5ce03 64#include <sys/ioctl.h>
b7080c8e 65#include <sys/time.h>
89c4ed63 66#include <sys/kern_control.h>
b7080c8e
A
67
68#include <net/if.h>
69#include <net/if_var.h>
70#include <net/if_dl.h>
71#include <net/if_types.h>
2b484d24 72#include <net/if_mib.h>
fdfd5971 73#include <net/if_llreach.h>
b7080c8e 74#include <net/ethernet.h>
2b484d24 75#include <net/route.h>
89c4ed63 76#include <net/ntstat.h>
2b484d24 77
7af5ce03
A
78#include <net/pktsched/pktsched.h>
79#include <net/classq/if_classq.h>
80
b7080c8e
A
81#include <netinet/in.h>
82#include <netinet/in_var.h>
83
b7080c8e
A
84#include <arpa/inet.h>
85
86#include <signal.h>
87#include <stdio.h>
88#include <string.h>
89#include <unistd.h>
2b484d24 90#include <stdlib.h>
89c4ed63 91#include <stddef.h>
2b484d24 92#include <err.h>
fdfd5971 93#include <errno.h>
89c4ed63 94#include <fcntl.h>
b7080c8e 95
e0b07f2d
A
96#include <assert.h>
97
b7080c8e
A
98#include "netstat.h"
99
100#define YES 1
101#define NO 0
102
2b484d24
A
103#define ROUNDUP(a, size) (((a) & ((size) - 1)) ? (1 + ((a)|(size - 1))) : (a))
104
105#define NEXT_SA(p) (struct sockaddr *) \
9c859447
A
106 ((caddr_t)p + (p->sa_len ? ROUNDUP(p->sa_len, sizeof(uint32_t)) : \
107 sizeof(uint32_t)))
2b484d24
A
108
109static void sidewaysintpr ();
7ba0088d 110static void catchalarm (int);
fdfd5971
A
111static char *sec2str(time_t);
112static void llreach_sysctl(uint32_t);
7af5ce03 113static char *nsec_to_str(unsigned long long);
7af5ce03 114static char *sched2str(unsigned int);
26c66ce9 115static char *pri2str(unsigned int i);
7af5ce03
A
116
117#define AVGN_MAX 8
118
119struct queue_stats {
120 int avgn;
121 double avg_bytes;
122 double avg_packets;
123 u_int64_t prev_bytes;
124 u_int64_t prev_packets;
7af5ce03
A
125 unsigned int handle;
126};
127
7af5ce03 128static void update_avg(struct if_ifclassq_stats *, struct queue_stats *);
26c66ce9
A
129static void print_fq_codel_stats(int slot, struct fq_codel_classstats *,
130 struct queue_stats *);
7af5ce03
A
131
132struct queue_stats qstats[IFCQ_SC_MAX];
7ba0088d
A
133
134#ifdef INET6
2b484d24 135char *netname6 (struct sockaddr_in6 *, struct sockaddr *);
7ba0088d 136static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */
7ba0088d
A
137#endif
138
7ba0088d
A
139/*
140 * Display a formatted value, or a '-' in the same space.
141 */
142static void
2b484d24 143show_stat(const char *fmt, int width, u_int64_t value, short showvalue)
7ba0088d
A
144{
145 char newfmt[32];
146
147 /* Construct the format string */
148 if (showvalue) {
fdfd5971 149 snprintf(newfmt, sizeof(newfmt), "%%%d%s", width, fmt);
7ba0088d
A
150 printf(newfmt, value);
151 } else {
fdfd5971 152 snprintf(newfmt, sizeof(newfmt), "%%%ds", width);
7ba0088d
A
153 printf(newfmt, "-");
154 }
155}
156
2b484d24
A
157size_t
158get_rti_info(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
159{
160 int i;
161 size_t len = 0;
162
163 for (i = 0; i < RTAX_MAX; i++) {
164 if (addrs & (1 << i)) {
165 rti_info[i] = sa;
166 if (sa->sa_len < sizeof(struct sockaddr))
167 len += sizeof(struct sockaddr);
168 else
169 len += sa->sa_len;
170 sa = NEXT_SA(sa);
171 } else {
172 rti_info[i] = NULL;
173 }
174 }
175 return len;
176}
7ba0088d 177
2b484d24
A
178static void
179multipr(int family, char *buf, char *lim)
180{
181 char *next;
182
183 for (next = buf; next < lim; ) {
184 struct ifma_msghdr2 *ifmam = (struct ifma_msghdr2 *)next;
185 struct sockaddr *rti_info[RTAX_MAX];
186 struct sockaddr *sa;
187 const char *fmt = 0;
a3cc5c72 188
2b484d24
A
189 next += ifmam->ifmam_msglen;
190 if (ifmam->ifmam_type == RTM_IFINFO2)
191 break;
192 else if (ifmam->ifmam_type != RTM_NEWMADDR2)
193 continue;
194 get_rti_info(ifmam->ifmam_addrs, (struct sockaddr*)(ifmam + 1), rti_info);
195 sa = rti_info[RTAX_IFA];
a3cc5c72 196
2b484d24
A
197 if (sa->sa_family != family)
198 continue;
199 switch (sa->sa_family) {
200 case AF_INET: {
201 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
a3cc5c72 202
2b484d24
A
203 fmt = routename(sin->sin_addr.s_addr);
204 break;
205 }
206 #ifdef INET6
207 case AF_INET6: {
b8dff150
A
208 struct sockaddr_in6 sin6;
209
210 memcpy(&sin6, sa, sizeof(struct sockaddr_in6));
211
212 if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
fdfd5971 213 IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr) ||
b8dff150 214 IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) {
9c859447 215 sin6.sin6_scope_id = ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
b8dff150
A
216 sin6.sin6_addr.s6_addr[2] = 0;
217 sin6.sin6_addr.s6_addr[3] = 0;
218 }
2b484d24
A
219
220 printf("%23s %-19.19s(refs: %d)\n", "",
9c859447
A
221 inet_ntop(AF_INET6, &sin6.sin6_addr,
222 ntop_buf, sizeof(ntop_buf)),
2b484d24
A
223 ifmam->ifmam_refcount);
224 break;
225 }
226 #endif /* INET6 */
227 case AF_LINK: {
228 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
a3cc5c72 229
2b484d24
A
230 switch (sdl->sdl_type) {
231 case IFT_ETHER:
232 case IFT_FDDI:
9c859447 233 fmt = ether_ntoa((struct ether_addr *)
2b484d24
A
234 LLADDR(sdl));
235 break;
236 }
237 break;
238 }
239 }
240 if (fmt)
241 printf("%23s %s\n", "", fmt);
242 }
243}
b7080c8e
A
244
245/*
246 * Print a description of the network interfaces.
247 */
248void
2b484d24 249intpr(void (*pfunc)(char *))
b7080c8e 250{
2b484d24
A
251 u_int64_t opackets = 0;
252 u_int64_t ipackets = 0;
253 u_int64_t obytes = 0;
254 u_int64_t ibytes = 0;
255 u_int64_t oerrors = 0;
256 u_int64_t ierrors = 0;
257 u_int64_t collisions = 0;
9dc66a05
A
258 u_int64_t fpackets = 0;
259 u_int64_t fbytes = 0;
9c859447 260 uint32_t mtu = 0;
9dc66a05 261 int timer = 0;
2b484d24 262 int drops = 0;
7ba0088d 263 struct sockaddr *sa = NULL;
2b484d24 264 char name[32];
7ba0088d
A
265 short network_layer;
266 short link_layer;
9dc66a05
A
267 int mib[6];
268 char *buf = NULL, *lim, *next;
2b484d24
A
269 size_t len;
270 struct if_msghdr *ifm;
271 struct sockaddr *rti_info[RTAX_MAX];
272 unsigned int ifindex = 0;
9dc66a05 273
b7080c8e 274 if (interval) {
2b484d24 275 sidewaysintpr();
b7080c8e
A
276 return;
277 }
9dc66a05 278
2b484d24
A
279 if (interface != 0)
280 ifindex = if_nametoindex(interface);
9dc66a05 281
2b484d24
A
282 mib[0] = CTL_NET; // networking subsystem
283 mib[1] = PF_ROUTE; // type of information
284 mib[2] = 0; // protocol (IPPROTO_xxx)
285 mib[3] = 0; // address family
286 mib[4] = NET_RT_IFLIST2; // operation
287 mib[5] = 0;
288 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
b7080c8e 289 return;
2b484d24
A
290 if ((buf = malloc(len)) == NULL) {
291 printf("malloc failed\n");
292 exit(1);
293 }
294 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
295 if (buf)
296 free(buf);
b7080c8e 297 return;
2b484d24 298 }
fdfd5971 299
7ba0088d 300 if (!pfunc) {
e0b07f2d
A
301 if (lflag) {
302 printf("%-10.10s %-5.5s %-39.39s %-39.39s %8.8s %5.5s",
303 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
304 } else {
305 printf("%-10.10s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
306 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
307 }
fdfd5971 308 if (prioflag >= 0)
7af5ce03 309 printf(" %8.8s %8.8s", "Itcpkts", "Ipvpkts");
fdfd5971 310 if (bflag) {
7ba0088d 311 printf(" %10.10s","Ibytes");
fdfd5971 312 if (prioflag >= 0)
7af5ce03 313 printf(" %8.8s %8.8s", "Itcbytes", "Ipvbytes");
fdfd5971 314 }
7ba0088d 315 printf(" %8.8s %5.5s", "Opkts", "Oerrs");
fdfd5971 316 if (prioflag >= 0)
7af5ce03 317 printf(" %8.8s %8.8s", "Otcpkts", "Opvpkts");
fdfd5971 318 if (bflag) {
7ba0088d 319 printf(" %10.10s","Obytes");
fdfd5971 320 if (prioflag >= 0)
7af5ce03 321 printf(" %8.8s %8.8s", "Otcbytes", "Opvbytes");
fdfd5971 322 }
7ba0088d
A
323 printf(" %5s", "Coll");
324 if (tflag)
325 printf(" %s", "Time");
326 if (dflag)
327 printf(" %s", "Drop");
9dc66a05
A
328 if (Fflag) {
329 printf(" %8.8s", "Fpkts");
330 if (bflag)
331 printf(" %10.10s", "Fbytes");
332 }
7ba0088d
A
333 putchar('\n');
334 }
9dc66a05
A
335 lim = buf + len;
336 for (next = buf; next < lim; ) {
2b484d24 337 char *cp;
b7080c8e 338 int n, m;
fdfd5971 339 struct ifmibdata_supplemental ifmsupp;
9dc66a05
A
340 u_int64_t ift_itcp = 0; /* input tc packets */
341 u_int64_t ift_itcb = 0; /* input tc bytes */
342 u_int64_t ift_otcp = 0; /* output tc packets */
343 u_int64_t ift_otcb = 0; /* output tc bytes */
7af5ce03
A
344 u_int64_t ift_ipvp = 0; /* input priv tc packets */
345 u_int64_t ift_ipvb = 0; /* input priv tc bytes */
346 u_int64_t ift_opvp = 0; /* output priv tc packets */
347 u_int64_t ift_opvb = 0; /* output priv tc bytes */
348
fdfd5971 349 bzero(&ifmsupp, sizeof(struct ifmibdata_supplemental));
9dc66a05 350
7ba0088d
A
351 network_layer = 0;
352 link_layer = 0;
9dc66a05 353 ifm = (struct if_msghdr *)next;
2b484d24
A
354 next += ifm->ifm_msglen;
355
9dc66a05 356 if (ifm->ifm_type == RTM_IFINFO2) {
2b484d24 357 struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
9dc66a05
A
358 struct sockaddr_dl *sdl =
359 (struct sockaddr_dl *)(if2m + 1);
360 int mibname[6];
361 size_t miblen = sizeof(struct ifmibdata_supplemental);
7ba0088d 362
2b484d24 363 if (interface != 0 && if2m->ifm_index != ifindex)
b7080c8e 364 continue;
e0b07f2d
A
365
366 /* The interface name is not a zero-ended string */
367 memcpy(name, sdl->sdl_data, MIN(sizeof(name) - 1, sdl->sdl_nlen));
368 name[MIN(sizeof(name) - 1, sdl->sdl_nlen)] = 0;
7ba0088d
A
369
370 if (pfunc) {
371 (*pfunc)(name);
372 continue;
373 }
374
e0b07f2d 375 cp = index(name, '\0');
2b484d24 376 if ((if2m->ifm_flags & IFF_UP) == 0)
b7080c8e
A
377 *cp++ = '*';
378 *cp = '\0';
2b484d24
A
379
380 /*
381 * Get the interface stats. These may get
382 * overriden below on a per-interface basis.
383 */
384 opackets = if2m->ifm_data.ifi_opackets;
385 ipackets = if2m->ifm_data.ifi_ipackets;
386 obytes = if2m->ifm_data.ifi_obytes;
387 ibytes = if2m->ifm_data.ifi_ibytes;
388 oerrors =if2m->ifm_data.ifi_oerrors;
389 ierrors = if2m->ifm_data.ifi_ierrors;
390 collisions = if2m->ifm_data.ifi_collisions;
391 timer = if2m->ifm_timer;
392 drops = if2m->ifm_snd_drops;
393 mtu = if2m->ifm_data.ifi_mtu;
394
9dc66a05
A
395 /* Common OID prefix */
396 mibname[0] = CTL_NET;
397 mibname[1] = PF_LINK;
398 mibname[2] = NETLINK_GENERIC;
399 mibname[3] = IFMIB_IFDATA;
400 mibname[4] = if2m->ifm_index;
401 mibname[5] = IFDATA_SUPPLEMENTAL;
402 if (sysctl(mibname, 6, &ifmsupp, &miblen, NULL, 0) == -1)
403 err(1, "sysctl IFDATA_SUPPLEMENTAL");
fdfd5971 404
9dc66a05
A
405 fpackets = ifmsupp.ifmd_data_extended.ifi_fpackets;
406 fbytes = ifmsupp.ifmd_data_extended.ifi_fbytes;
407
408 if (prioflag >= 0) {
fdfd5971 409 switch (prioflag) {
9dc66a05
A
410 case SO_TC_BE:
411 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibepackets;
412 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibebytes;
413 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_obepackets;
414 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_obebytes;
415 break;
416 case SO_TC_BK:
417 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibkpackets;
418 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibkbytes;
419 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_obkpackets;
420 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_obkbytes;
421 break;
422 case SO_TC_VI:
423 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ivipackets;
424 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ivibytes;
425 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_ovipackets;
426 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_ovibytes;
427 break;
428 case SO_TC_VO:
429 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ivopackets;
430 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ivobytes;
431 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_ovopackets;
432 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_ovobytes;
433 break;
434 default:
435 ift_itcp = 0;
436 ift_itcb = 0;
437 ift_otcp = 0;
438 ift_otcb = 0;
439 ift_ipvp = 0;
440 ift_ipvb = 0;
441 ift_opvp = 0;
442 ift_opvb = 0;
443 break;
fdfd5971 444 }
7af5ce03
A
445 ift_ipvp = ifmsupp.ifmd_traffic_class.ifi_ipvpackets;
446 ift_ipvb = ifmsupp.ifmd_traffic_class.ifi_ipvbytes;
447 ift_opvp = ifmsupp.ifmd_traffic_class.ifi_opvpackets;
448 ift_opvb = ifmsupp.ifmd_traffic_class.ifi_opvbytes;
fdfd5971
A
449 }
450
9dc66a05
A
451 get_rti_info(if2m->ifm_addrs,
452 (struct sockaddr*)(if2m + 1), rti_info);
2b484d24 453 sa = rti_info[RTAX_IFP];
9dc66a05
A
454 } else if (ifm->ifm_type == RTM_NEWADDR) {
455 struct ifa_msghdr *ifam = (struct ifa_msghdr *)ifm;
456
2b484d24
A
457 if (interface != 0 && ifam->ifam_index != ifindex)
458 continue;
9dc66a05
A
459 get_rti_info(ifam->ifam_addrs,
460 (struct sockaddr*)(ifam + 1), rti_info);
2b484d24 461 sa = rti_info[RTAX_IFA];
9c859447 462 } else {
2b484d24 463 continue;
9c859447 464 }
e0b07f2d
A
465 if (lflag) {
466 printf("%-10.10s %-5u ", name, mtu);
467 } else {
468 printf("%-5.5s %-5u ", name, mtu);
469 }
2b484d24
A
470
471 if (sa == 0) {
e0b07f2d
A
472 printf(lflag ? "%-39.39s " : "%-13.13s ", "none");
473 printf(lflag ? "%-39.39s " : "%-15.15s ", "none");
b7080c8e 474 } else {
b7080c8e
A
475 switch (sa->sa_family) {
476 case AF_UNSPEC:
e0b07f2d
A
477 printf(lflag ? "%-39.39s " : "%-13.13s ", "none");
478 printf(lflag ? "%-39.39s " : "%-15.15s ", "none");
b7080c8e 479 break;
9c859447 480
2b484d24 481 case AF_INET: {
9dc66a05
A
482 struct sockaddr_in *sin =
483 (struct sockaddr_in *)sa;
2b484d24 484 struct sockaddr_in mask;
9dc66a05 485
2b484d24 486 mask.sin_addr.s_addr = 0;
9dc66a05
A
487 memcpy(&mask, rti_info[RTAX_NETMASK],
488 ((struct sockaddr_in *)
489 rti_info[RTAX_NETMASK])->sin_len);
490
e0b07f2d 491 printf(lflag ? "%-39.39s " : "%-13.13s ",
9dc66a05
A
492 netname(sin->sin_addr.s_addr &
493 mask.sin_addr.s_addr,
3a228055 494 ntohl(mask.sin_addr.s_addr)));
2b484d24 495
e0b07f2d 496 printf(lflag ? "%-39.39s " : "%-15.15s ",
b7080c8e 497 routename(sin->sin_addr.s_addr));
7ba0088d
A
498
499 network_layer = 1;
b7080c8e 500 break;
2b484d24 501 }
7ba0088d 502#ifdef INET6
2b484d24 503 case AF_INET6: {
9dc66a05
A
504 struct sockaddr_in6 *sin6 =
505 (struct sockaddr_in6 *)sa;
506 struct sockaddr *mask =
507 (struct sockaddr *)rti_info[RTAX_NETMASK];
2b484d24 508
e0b07f2d
A
509 printf(lflag ? "%-39.39s " : "%-11.11s ", netname6(sin6, mask));
510 printf(lflag ? "%-39.39s " : "%-17.17s ", (char *)inet_ntop(AF_INET6,
9dc66a05
A
511 &sin6->sin6_addr, ntop_buf,
512 sizeof(ntop_buf)));
b7080c8e 513
7ba0088d
A
514 network_layer = 1;
515 break;
2b484d24 516 }
7ba0088d 517#endif /*INET6*/
9c859447 518 case AF_LINK: {
b7080c8e 519 struct sockaddr_dl *sdl =
9dc66a05 520 (struct sockaddr_dl *)sa;
7ba0088d
A
521 char linknum[10];
522 cp = (char *)LLADDR(sdl);
523 n = sdl->sdl_alen;
9dc66a05
A
524 snprintf(linknum, sizeof(linknum),
525 "<Link#%d>", sdl->sdl_index);
e0b07f2d 526 m = printf(lflag ? "%-39.39s " : "%-11.11s ", linknum);
b7080c8e 527 goto hexprint;
9c859447
A
528 }
529
b7080c8e
A
530 default:
531 m = printf("(%d)", sa->sa_family);
532 for (cp = sa->sa_len + (char *)sa;
533 --cp > sa->sa_data && (*cp == 0);) {}
534 n = cp - sa->sa_data + 1;
535 cp = sa->sa_data;
536 hexprint:
537 while (--n >= 0)
538 m += printf("%02x%c", *cp++ & 0xff,
7ba0088d 539 n > 0 ? ':' : ' ');
e0b07f2d 540 m = (lflag ? 80 : 30) - m;
b7080c8e
A
541 while (m-- > 0)
542 putchar(' ');
7ba0088d
A
543
544 link_layer = 1;
b7080c8e
A
545 break;
546 }
9dc66a05 547 }
7ba0088d 548
2b484d24 549 show_stat("llu", 8, ipackets, link_layer|network_layer);
7ba0088d 550 printf(" ");
2b484d24 551 show_stat("llu", 5, ierrors, link_layer);
7ba0088d 552 printf(" ");
fdfd5971
A
553 if (prioflag >= 0) {
554 show_stat("llu", 8, ift_itcp, link_layer|network_layer);
555 printf(" ");
7af5ce03
A
556 show_stat("llu", 8, ift_ipvp, link_layer|network_layer);
557 printf(" ");
fdfd5971 558 }
7ba0088d 559 if (bflag) {
2b484d24 560 show_stat("llu", 10, ibytes, link_layer|network_layer);
7ba0088d 561 printf(" ");
fdfd5971
A
562 if (prioflag >= 0) {
563 show_stat("llu", 8, ift_itcb, link_layer|network_layer);
564 printf(" ");
7af5ce03
A
565 show_stat("llu", 8, ift_ipvb, link_layer|network_layer);
566 printf(" ");
fdfd5971 567 }
7ba0088d 568 }
2b484d24 569 show_stat("llu", 8, opackets, link_layer|network_layer);
7ba0088d 570 printf(" ");
2b484d24 571 show_stat("llu", 5, oerrors, link_layer);
7ba0088d 572 printf(" ");
fdfd5971
A
573 if (prioflag >= 0) {
574 show_stat("llu", 8, ift_otcp, link_layer|network_layer);
575 printf(" ");
7af5ce03
A
576 show_stat("llu", 8, ift_opvp, link_layer|network_layer);
577 printf(" ");
fdfd5971 578 }
7ba0088d 579 if (bflag) {
2b484d24 580 show_stat("llu", 10, obytes, link_layer|network_layer);
7ba0088d 581 printf(" ");
fdfd5971
A
582 if (prioflag >= 0) {
583 show_stat("llu", 8, ift_otcb, link_layer|network_layer);
584 printf(" ");
7af5ce03
A
585 show_stat("llu", 8, ift_opvb, link_layer|network_layer);
586 printf(" ");
fdfd5971 587 }
7ba0088d 588 }
2b484d24 589 show_stat("llu", 5, collisions, link_layer);
7ba0088d
A
590 if (tflag) {
591 printf(" ");
9dc66a05 592 show_stat("d", 3, timer, link_layer);
7ba0088d
A
593 }
594 if (dflag) {
595 printf(" ");
9dc66a05
A
596 show_stat("d", 3, drops, link_layer);
597 }
598 if (Fflag) {
599 printf(" ");
600 show_stat("llu", 8, fpackets, link_layer|network_layer);
601 if (bflag) {
602 printf(" ");
603 show_stat("llu", 10, fbytes,
604 link_layer|network_layer);
605 }
b7080c8e 606 }
b7080c8e 607 putchar('\n');
2b484d24 608
9dc66a05 609 if (aflag)
2b484d24 610 multipr(sa->sa_family, next, lim);
b7080c8e 611 }
fdfd5971 612 free(buf);
b7080c8e
A
613}
614
b7080c8e 615struct iftot {
7ba0088d 616 SLIST_ENTRY(iftot) chain;
2b484d24 617 char ift_name[16]; /* interface name */
9dc66a05
A
618 u_int64_t ift_ip; /* input packets */
619 u_int64_t ift_ie; /* input errors */
620 u_int64_t ift_op; /* output packets */
621 u_int64_t ift_oe; /* output errors */
622 u_int64_t ift_co; /* collisions */
623 u_int64_t ift_dr; /* drops */
624 u_int64_t ift_ib; /* input bytes */
625 u_int64_t ift_ob; /* output bytes */
626 u_int64_t ift_itcp; /* input tc packets */
627 u_int64_t ift_itcb; /* input tc bytes */
628 u_int64_t ift_otcp; /* output tc packets */
629 u_int64_t ift_otcb; /* output tc bytes */
630 u_int64_t ift_ipvp; /* input priv tc packets */
631 u_int64_t ift_ipvb; /* input priv tc bytes */
632 u_int64_t ift_opvp; /* output priv tc packets */
633 u_int64_t ift_opvb; /* output priv tc bytes */
634 u_int64_t ift_fp; /* forwarded packets */
635 u_int64_t ift_fb; /* forwarded bytes */
7ba0088d 636};
b7080c8e
A
637
638u_char signalled; /* set if alarm goes off "early" */
639
640/*
641 * Print a running summary of interface statistics.
642 * Repeat display every interval seconds, showing statistics
643 * collected over that interval. Assumes that interval is non-zero.
644 * First line printed at top of screen is always cumulative.
645 * XXX - should be rewritten to use ifmib(4).
646 */
647static void
2b484d24 648sidewaysintpr()
b7080c8e 649{
2b484d24 650 struct iftot *total, *sum, *interesting;
b7080c8e 651 register int line;
b8dff150 652 int first;
2b484d24
A
653 int name[6];
654 size_t len;
655 unsigned int ifcount, i;
656 struct ifmibdata *ifmdall = 0;
657 int interesting_row;
b8dff150
A
658 sigset_t sigset, oldsigset;
659 struct itimerval timer_interval;
660
2b484d24
A
661 /* Common OID prefix */
662 name[0] = CTL_NET;
663 name[1] = PF_LINK;
664 name[2] = NETLINK_GENERIC;
665
666 len = sizeof(int);
667 name[3] = IFMIB_SYSTEM;
668 name[4] = IFMIB_IFCOUNT;
669 if (sysctl(name, 5, &ifcount, &len, 0, 0) == 1)
670 err(1, "sysctl IFMIB_IFCOUNT");
671
672 len = ifcount * sizeof(struct ifmibdata);
673 ifmdall = malloc(len);
674 if (ifmdall == 0)
675 err(1, "malloc failed");
676 name[3] = IFMIB_IFALLDATA;
677 name[4] = 0;
678 name[5] = IFDATA_GENERAL;
679 if (sysctl(name, 6, ifmdall, &len, (void *)0, 0) == -1)
680 err(1, "sysctl IFMIB_IFALLDATA");
9dc66a05 681
b7080c8e 682 interesting = NULL;
2b484d24
A
683 interesting_row = 0;
684 for (i = 0; i < ifcount; i++) {
685 struct ifmibdata *ifmd = ifmdall + i;
9dc66a05 686
2b484d24 687 if (interface && strcmp(ifmd->ifmd_name, interface) == 0) {
9dc66a05
A
688 if ((interesting = calloc(ifcount,
689 sizeof(struct iftot))) == NULL)
2b484d24 690 err(1, "malloc failed");
fdfd5971 691 interesting_row = if_nametoindex(interface);
9dc66a05
A
692 snprintf(interesting->ift_name, 16, "(%s)",
693 ifmd->ifmd_name);;
7ba0088d 694 }
7ba0088d 695 }
2b484d24
A
696 if ((total = calloc(1, sizeof(struct iftot))) == NULL)
697 err(1, "malloc failed");
698
699 if ((sum = calloc(1, sizeof(struct iftot))) == NULL)
700 err(1, "malloc failed");
7ba0088d 701
b8dff150
A
702 /* create a timer that fires repeatedly every interval seconds */
703 timer_interval.it_value.tv_sec = interval;
704 timer_interval.it_value.tv_usec = 0;
705 timer_interval.it_interval.tv_sec = interval;
706 timer_interval.it_interval.tv_usec = 0;
b7080c8e
A
707 (void)signal(SIGALRM, catchalarm);
708 signalled = NO;
b8dff150 709 (void)setitimer(ITIMER_REAL, &timer_interval, NULL);
b7080c8e
A
710 first = 1;
711banner:
9dc66a05
A
712 if (vflag > 0)
713 printf("%9s", " ");
714
fdfd5971 715 if (prioflag >= 0)
7af5ce03 716 printf("%39s %39s %36s", "input",
5902acfc
A
717 interesting ? interesting->ift_name : "(Total)", "output");
718 else
719 printf("%17s %14s %16s", "input",
720 interesting ? interesting->ift_name : "(Total)", "output");
b7080c8e 721 putchar('\n');
9dc66a05
A
722
723 if (vflag > 0)
724 printf("%9s", " ");
725
726 printf("%10s %5s %10s ", "packets", "errs", "bytes");
fdfd5971 727 if (prioflag >= 0)
9dc66a05
A
728 printf(" %10s %10s %10s %10s",
729 "tcpkts", "tcbytes", "pvpkts", "pvbytes");
730 printf("%10s %5s %10s %5s", "packets", "errs", "bytes", "colls");
b7080c8e
A
731 if (dflag)
732 printf(" %5.5s", "drops");
fdfd5971 733 if (prioflag >= 0)
9dc66a05
A
734 printf(" %10s %10s %10s %10s",
735 "tcpkts", "tcbytes", "pvpkts", "pvbytes");
736 if (Fflag)
737 printf(" %10s %10s", "fpackets", "fbytes");
b7080c8e
A
738 putchar('\n');
739 fflush(stdout);
740 line = 0;
741loop:
9dc66a05
A
742 if (vflag && !first)
743 print_time();
744
b7080c8e 745 if (interesting != NULL) {
2b484d24 746 struct ifmibdata ifmd;
5902acfc 747 struct ifmibdata_supplemental ifmsupp;
9dc66a05 748
2b484d24
A
749 len = sizeof(struct ifmibdata);
750 name[3] = IFMIB_IFDATA;
751 name[4] = interesting_row;
752 name[5] = IFDATA_GENERAL;
753 if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) == -1)
754 err(1, "sysctl IFDATA_GENERAL %d", interesting_row);
755
9dc66a05
A
756 len = sizeof(struct ifmibdata_supplemental);
757 name[3] = IFMIB_IFDATA;
758 name[4] = interesting_row;
759 name[5] = IFDATA_SUPPLEMENTAL;
760 if (sysctl(name, 6, &ifmsupp, &len, (void *)0, 0) == -1)
761 err(1, "sysctl IFDATA_SUPPLEMENTAL %d",
762 interesting_row);
7af5ce03 763
b7080c8e 764 if (!first) {
5902acfc 765 printf("%10llu %5llu %10llu ",
9dc66a05
A
766 ifmd.ifmd_data.ifi_ipackets - interesting->ift_ip,
767 ifmd.ifmd_data.ifi_ierrors - interesting->ift_ie,
768 ifmd.ifmd_data.ifi_ibytes - interesting->ift_ib);
5902acfc 769 switch (prioflag) {
9dc66a05
A
770 case SO_TC_BE:
771 printf("%10llu %10llu ",
772 ifmsupp.ifmd_traffic_class.ifi_ibepackets -
773 interesting->ift_itcp,
774 ifmsupp.ifmd_traffic_class.ifi_ibebytes -
775 interesting->ift_itcb);
776 break;
777 case SO_TC_BK:
778 printf("%10llu %10llu ",
779 ifmsupp.ifmd_traffic_class.ifi_ibkpackets -
780 interesting->ift_itcp,
781 ifmsupp.ifmd_traffic_class.ifi_ibkbytes -
782 interesting->ift_itcb);
783 break;
784 case SO_TC_VI:
785 printf("%10llu %10llu ",
786 ifmsupp.ifmd_traffic_class.ifi_ivipackets -
787 interesting->ift_itcp,
788 ifmsupp.ifmd_traffic_class.ifi_ivibytes -
789 interesting->ift_itcb);
790 break;
791 case SO_TC_VO:
792 printf("%10llu %10llu ",
793 ifmsupp.ifmd_traffic_class.ifi_ivopackets -
794 interesting->ift_itcp,
795 ifmsupp.ifmd_traffic_class.ifi_ivobytes -
796 interesting->ift_itcb);
797 break;
798 default:
799 break;
5902acfc 800 }
7af5ce03
A
801 if (prioflag >= 0) {
802 printf("%10llu %10llu ",
9dc66a05
A
803 ifmsupp.ifmd_traffic_class.ifi_ipvpackets -
804 interesting->ift_ipvp,
805 ifmsupp.ifmd_traffic_class.ifi_ipvbytes -
806 interesting->ift_ipvb);
7af5ce03 807 }
5902acfc 808 printf("%10llu %5llu %10llu %5llu",
9dc66a05
A
809 ifmd.ifmd_data.ifi_opackets - interesting->ift_op,
810 ifmd.ifmd_data.ifi_oerrors - interesting->ift_oe,
811 ifmd.ifmd_data.ifi_obytes - interesting->ift_ob,
812 ifmd.ifmd_data.ifi_collisions - interesting->ift_co);
b7080c8e 813 if (dflag)
9dc66a05
A
814 printf(" %5llu",
815 ifmd.ifmd_snd_drops - interesting->ift_dr);
5902acfc 816 switch (prioflag) {
9dc66a05
A
817 case SO_TC_BE:
818 printf(" %10llu %10llu",
819 ifmsupp.ifmd_traffic_class.ifi_obepackets -
820 interesting->ift_otcp,
821 ifmsupp.ifmd_traffic_class.ifi_obebytes -
822 interesting->ift_otcb);
823 break;
824 case SO_TC_BK:
825 printf(" %10llu %10llu",
826 ifmsupp.ifmd_traffic_class.ifi_obkpackets -
827 interesting->ift_otcp,
828 ifmsupp.ifmd_traffic_class.ifi_obkbytes -
829 interesting->ift_otcb);
830 break;
831 case SO_TC_VI:
832 printf(" %10llu %10llu",
833 ifmsupp.ifmd_traffic_class.ifi_ovipackets -
834 interesting->ift_otcp,
835 ifmsupp.ifmd_traffic_class.ifi_ovibytes -
836 interesting->ift_otcb);
837 break;
838 case SO_TC_VO:
839 printf(" %10llu %10llu",
840 ifmsupp.ifmd_traffic_class.ifi_ovopackets -
841 interesting->ift_otcp,
842 ifmsupp.ifmd_traffic_class.ifi_ovobytes -
843 interesting->ift_otcb);
844 break;
845 default:
846 break;
5902acfc 847 }
7af5ce03
A
848 if (prioflag >= 0) {
849 printf("%10llu %10llu ",
9dc66a05
A
850 ifmsupp.ifmd_traffic_class.ifi_opvpackets -
851 interesting->ift_opvp,
852 ifmsupp.ifmd_traffic_class.ifi_opvbytes -
853 interesting->ift_opvb);
854 }
855 if (Fflag) {
856 printf("%10llu %10llu",
857 ifmsupp.ifmd_data_extended.ifi_fpackets -
858 interesting->ift_fp,
859 ifmsupp.ifmd_data_extended.ifi_fbytes -
860 interesting->ift_fb);
7af5ce03 861 }
b7080c8e 862 }
2b484d24
A
863 interesting->ift_ip = ifmd.ifmd_data.ifi_ipackets;
864 interesting->ift_ie = ifmd.ifmd_data.ifi_ierrors;
865 interesting->ift_ib = ifmd.ifmd_data.ifi_ibytes;
866 interesting->ift_op = ifmd.ifmd_data.ifi_opackets;
867 interesting->ift_oe = ifmd.ifmd_data.ifi_oerrors;
868 interesting->ift_ob = ifmd.ifmd_data.ifi_obytes;
869 interesting->ift_co = ifmd.ifmd_data.ifi_collisions;
870 interesting->ift_dr = ifmd.ifmd_snd_drops;
9dc66a05 871
7f5b2e89 872 /* private counters */
5902acfc 873 switch (prioflag) {
9dc66a05
A
874 case SO_TC_BE:
875 interesting->ift_itcp =
876 ifmsupp.ifmd_traffic_class.ifi_ibepackets;
877 interesting->ift_itcb =
878 ifmsupp.ifmd_traffic_class.ifi_ibebytes;
879 interesting->ift_otcp =
880 ifmsupp.ifmd_traffic_class.ifi_obepackets;
881 interesting->ift_otcb =
882 ifmsupp.ifmd_traffic_class.ifi_obebytes;
883 break;
884 case SO_TC_BK:
885 interesting->ift_itcp =
886 ifmsupp.ifmd_traffic_class.ifi_ibkpackets;
887 interesting->ift_itcb =
888 ifmsupp.ifmd_traffic_class.ifi_ibkbytes;
889 interesting->ift_otcp =
890 ifmsupp.ifmd_traffic_class.ifi_obkpackets;
891 interesting->ift_otcb =
892 ifmsupp.ifmd_traffic_class.ifi_obkbytes;
893 break;
894 case SO_TC_VI:
895 interesting->ift_itcp =
896 ifmsupp.ifmd_traffic_class.ifi_ivipackets;
897 interesting->ift_itcb =
898 ifmsupp.ifmd_traffic_class.ifi_ivibytes;
899 interesting->ift_otcp =
900 ifmsupp.ifmd_traffic_class.ifi_ovipackets;
901 interesting->ift_otcb =
902 ifmsupp.ifmd_traffic_class.ifi_ovibytes;
903 break;
904 case SO_TC_VO:
905 interesting->ift_itcp =
906 ifmsupp.ifmd_traffic_class.ifi_ivopackets;
907 interesting->ift_itcb =
908 ifmsupp.ifmd_traffic_class.ifi_ivobytes;
909 interesting->ift_otcp =
910 ifmsupp.ifmd_traffic_class.ifi_ovopackets;
911 interesting->ift_otcb =
912 ifmsupp.ifmd_traffic_class.ifi_ovobytes;
913 break;
914 default:
915 break;
5902acfc 916 }
7af5ce03 917 if (prioflag >= 0) {
9dc66a05
A
918 interesting->ift_ipvp =
919 ifmsupp.ifmd_traffic_class.ifi_ipvpackets;
920 interesting->ift_ipvb =
921 ifmsupp.ifmd_traffic_class.ifi_ipvbytes;
922 interesting->ift_opvp =
923 ifmsupp.ifmd_traffic_class.ifi_opvpackets;
924 interesting->ift_opvb =
925 ifmsupp.ifmd_traffic_class.ifi_opvbytes;
7af5ce03 926 }
9dc66a05
A
927 interesting->ift_fp = ifmsupp.ifmd_data_extended.ifi_fpackets;
928 interesting->ift_fb = ifmsupp.ifmd_data_extended.ifi_fbytes;
b7080c8e 929 } else {
2b484d24 930 unsigned int latest_ifcount;
5902acfc 931 struct ifmibdata_supplemental *ifmsuppall = NULL;
9dc66a05 932
2b484d24
A
933 len = sizeof(int);
934 name[3] = IFMIB_SYSTEM;
935 name[4] = IFMIB_IFCOUNT;
936 if (sysctl(name, 5, &latest_ifcount, &len, 0, 0) == 1)
937 err(1, "sysctl IFMIB_IFCOUNT");
938 if (latest_ifcount > ifcount) {
939 ifcount = latest_ifcount;
940 len = ifcount * sizeof(struct ifmibdata);
941 free(ifmdall);
942 ifmdall = malloc(len);
943 if (ifmdall == 0)
5902acfc 944 err(1, "malloc ifmdall failed");
2b484d24
A
945 } else if (latest_ifcount > ifcount) {
946 ifcount = latest_ifcount;
947 len = ifcount * sizeof(struct ifmibdata);
948 }
949 len = ifcount * sizeof(struct ifmibdata);
950 name[3] = IFMIB_IFALLDATA;
951 name[4] = 0;
952 name[5] = IFDATA_GENERAL;
953 if (sysctl(name, 6, ifmdall, &len, (void *)0, 0) == -1)
954 err(1, "sysctl IFMIB_IFALLDATA");
9dc66a05
A
955
956 len = ifcount * sizeof(struct ifmibdata_supplemental);
957 ifmsuppall = malloc(len);
958 if (ifmsuppall == NULL)
959 err(1, "malloc ifmsuppall failed");
960 name[3] = IFMIB_IFALLDATA;
961 name[4] = 0;
962 name[5] = IFDATA_SUPPLEMENTAL;
963 if (sysctl(name, 6, ifmsuppall, &len, (void *)0, 0) == -1)
964 err(1, "sysctl IFMIB_IFALLDATA SUPPLEMENTAL");
965
b7080c8e
A
966 sum->ift_ip = 0;
967 sum->ift_ie = 0;
968 sum->ift_ib = 0;
969 sum->ift_op = 0;
970 sum->ift_oe = 0;
971 sum->ift_ob = 0;
972 sum->ift_co = 0;
973 sum->ift_dr = 0;
5902acfc
A
974 sum->ift_itcp = 0;
975 sum->ift_itcb = 0;
976 sum->ift_otcp = 0;
977 sum->ift_otcb = 0;
7af5ce03
A
978 sum->ift_ipvp = 0;
979 sum->ift_ipvb = 0;
980 sum->ift_opvp = 0;
981 sum->ift_opvb = 0;
9dc66a05
A
982 sum->ift_fp = 0;
983 sum->ift_fb = 0;
2b484d24
A
984 for (i = 0; i < ifcount; i++) {
985 struct ifmibdata *ifmd = ifmdall + i;
9dc66a05
A
986 struct ifmibdata_supplemental *ifmsupp = ifmsuppall + i;
987
2b484d24
A
988 sum->ift_ip += ifmd->ifmd_data.ifi_ipackets;
989 sum->ift_ie += ifmd->ifmd_data.ifi_ierrors;
990 sum->ift_ib += ifmd->ifmd_data.ifi_ibytes;
991 sum->ift_op += ifmd->ifmd_data.ifi_opackets;
992 sum->ift_oe += ifmd->ifmd_data.ifi_oerrors;
993 sum->ift_ob += ifmd->ifmd_data.ifi_obytes;
994 sum->ift_co += ifmd->ifmd_data.ifi_collisions;
995 sum->ift_dr += ifmd->ifmd_snd_drops;
7f5b2e89 996 /* private counters */
fdfd5971 997 if (prioflag >= 0) {
5902acfc 998 switch (prioflag) {
9dc66a05
A
999 case SO_TC_BE:
1000 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ibepackets;
1001 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ibebytes;
1002 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_obepackets;
1003 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_obebytes;
1004 break;
1005 case SO_TC_BK:
1006 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ibkpackets;
1007 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ibkbytes;
1008 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_obkpackets;
1009 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_obkbytes;
1010 break;
1011 case SO_TC_VI:
1012 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ivipackets;
1013 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ivibytes;
1014 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_ovipackets;
1015 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_ovibytes;
1016 break;
1017 case SO_TC_VO:
1018 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ivopackets;
1019 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ivobytes;
1020 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_ovopackets;
1021 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_ovobytes;
1022 break;
1023 default:
1024 break;
5902acfc 1025 }
7af5ce03
A
1026 sum->ift_ipvp += ifmsupp->ifmd_traffic_class.ifi_ipvpackets;
1027 sum->ift_ipvb += ifmsupp->ifmd_traffic_class.ifi_ipvbytes;
1028 sum->ift_opvp += ifmsupp->ifmd_traffic_class.ifi_opvpackets;
1029 sum->ift_opvb += ifmsupp->ifmd_traffic_class.ifi_opvbytes;
5902acfc 1030 }
9dc66a05
A
1031 sum->ift_fp += ifmsupp->ifmd_data_extended.ifi_fpackets;
1032 sum->ift_fb += ifmsupp->ifmd_data_extended.ifi_fbytes;
b7080c8e
A
1033 }
1034 if (!first) {
5902acfc 1035 printf("%10llu %5llu %10llu ",
b7080c8e
A
1036 sum->ift_ip - total->ift_ip,
1037 sum->ift_ie - total->ift_ie,
5902acfc 1038 sum->ift_ib - total->ift_ib);
fdfd5971 1039 if (prioflag >= 0)
7af5ce03 1040 printf(" %10llu %10llu %10llu %10llu",
5902acfc 1041 sum->ift_itcp - total->ift_itcp,
7af5ce03
A
1042 sum->ift_itcb - total->ift_itcb,
1043 sum->ift_ipvp - total->ift_ipvp,
1044 sum->ift_ipvb - total->ift_ipvb);
5902acfc 1045 printf("%10llu %5llu %10llu %5llu",
b7080c8e
A
1046 sum->ift_op - total->ift_op,
1047 sum->ift_oe - total->ift_oe,
1048 sum->ift_ob - total->ift_ob,
1049 sum->ift_co - total->ift_co);
1050 if (dflag)
2b484d24 1051 printf(" %5llu", sum->ift_dr - total->ift_dr);
fdfd5971 1052 if (prioflag >= 0)
7af5ce03 1053 printf(" %10llu %10llu %10llu %10llu",
5902acfc 1054 sum->ift_otcp - total->ift_otcp,
7af5ce03
A
1055 sum->ift_otcb - total->ift_otcb,
1056 sum->ift_opvp - total->ift_opvp,
1057 sum->ift_opvb - total->ift_opvb);
9dc66a05
A
1058 if (Fflag)
1059 printf(" %10llu %10llu",
1060 sum->ift_fp - total->ift_fp,
1061 sum->ift_fb - total->ift_fb);
b7080c8e
A
1062 }
1063 *total = *sum;
a3cc5c72 1064
26c66ce9 1065 free(ifmsuppall);
b7080c8e
A
1066 }
1067 if (!first)
1068 putchar('\n');
1069 fflush(stdout);
b8dff150
A
1070 sigemptyset(&sigset);
1071 sigaddset(&sigset, SIGALRM);
1072 (void)sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
1073 if (!signalled) {
1074 sigemptyset(&sigset);
1075 sigsuspend(&sigset);
b7080c8e 1076 }
b8dff150
A
1077 (void)sigprocmask(SIG_SETMASK, &oldsigset, NULL);
1078
b7080c8e 1079 signalled = NO;
b7080c8e
A
1080 line++;
1081 first = 0;
1082 if (line == 21)
1083 goto banner;
1084 else
1085 goto loop;
1086 /*NOTREACHED*/
1087}
1088
b8dff150 1089void
9c859447 1090intervalpr(void (*pr)(uint32_t, char *, int), uint32_t off, char *name , int af)
b8dff150
A
1091{
1092 struct itimerval timer_interval;
1093 sigset_t sigset, oldsigset;
1094
1095 /* create a timer that fires repeatedly every interval seconds */
1096 timer_interval.it_value.tv_sec = interval;
1097 timer_interval.it_value.tv_usec = 0;
1098 timer_interval.it_interval.tv_sec = interval;
1099 timer_interval.it_interval.tv_usec = 0;
1100 (void) signal(SIGALRM, catchalarm);
1101 signalled = NO;
1102 (void) setitimer(ITIMER_REAL, &timer_interval, NULL);
1103
1104 for (;;) {
1105 pr(off, name, af);
1106
1107 fflush(stdout);
1108 sigemptyset(&sigset);
1109 sigaddset(&sigset, SIGALRM);
1110 (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
1111 if (!signalled) {
1112 sigemptyset(&sigset);
1113 sigsuspend(&sigset);
1114 }
1115 (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL);
1116 signalled = NO;
1117 }
1118}
1119
b7080c8e
A
1120/*
1121 * Called if an interval expires before sidewaysintpr has completed a loop.
1122 * Sets a flag to not wait for the alarm.
1123 */
1124static void
7ba0088d 1125catchalarm(int signo )
b7080c8e
A
1126{
1127 signalled = YES;
1128}
fdfd5971
A
1129
1130static char *
1131sec2str(total)
1132 time_t total;
1133{
1134 static char result[256];
1135 int days, hours, mins, secs;
1136 int first = 1;
1137 char *p = result;
1138
1139 days = total / 3600 / 24;
1140 hours = (total / 3600) % 24;
1141 mins = (total / 60) % 60;
1142 secs = total % 60;
1143
1144 if (days) {
1145 first = 0;
1146 p += snprintf(p, sizeof(result) - (p - result), "%dd", days);
1147 }
1148 if (!first || hours) {
1149 first = 0;
1150 p += snprintf(p, sizeof(result) - (p - result), "%dh", hours);
1151 }
1152 if (!first || mins) {
1153 first = 0;
1154 p += snprintf(p, sizeof(result) - (p - result), "%dm", mins);
1155 }
1156 snprintf(p, sizeof(result) - (p - result), "%ds", secs);
1157
1158 return(result);
1159}
1160
1161void
1162intpr_ri(void (*pfunc)(char *))
1163{
1164 int mib[6];
1165 char *buf = NULL, *lim, *next;
1166 size_t len;
1167 unsigned int ifindex = 0;
1168 struct if_msghdr2 *if2m;
1169
1170 if (interface != 0) {
1171 ifindex = if_nametoindex(interface);
1172 if (ifindex == 0) {
1173 printf("interface name is not valid: %s\n", interface);
1174 exit(1);
1175 }
1176 }
1177
1178 mib[0] = CTL_NET; /* networking subsystem */
1179 mib[1] = PF_ROUTE; /* type of information */
1180 mib[2] = 0; /* protocol (IPPROTO_xxx) */
1181 mib[3] = 0; /* address family */
1182 mib[4] = NET_RT_IFLIST2; /* operation */
1183 mib[5] = 0;
1184 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
1185 return;
1186 if ((buf = malloc(len)) == NULL) {
1187 printf("malloc failed\n");
1188 exit(1);
1189 }
1190 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
1191 free(buf);
1192 return;
1193 }
1194
7af5ce03
A
1195 printf("%-6s %-17s %8.8s %-9.9s %4s %4s",
1196 "Proto", "Linklayer Address", "Netif", "Expire", "Refs",
1197 "Prbs");
1198 if (xflag)
1199 printf(" %7s %7s %7s", "RSSI", "LQM", "NPM");
1200 printf("\n");
fdfd5971
A
1201
1202 lim = buf + len;
1203 if2m = (struct if_msghdr2 *)buf;
1204
1205 for (next = buf; next < lim; ) {
1206 if2m = (struct if_msghdr2 *)next;
1207 next += if2m->ifm_msglen;
1208
1209 if (if2m->ifm_type != RTM_IFINFO2)
1210 continue;
1211 else if (interface != 0 && if2m->ifm_index != ifindex)
1212 continue;
1213
1214 llreach_sysctl(if2m->ifm_index);
1215 }
1216 free(buf);
1217}
1218
1219static void
1220llreach_sysctl(uint32_t ifindex)
1221{
1222#define MAX_SYSCTL_TRY 5
1223 int mib[6], i, ntry = 0;
1224 size_t mibsize, len, needed, cnt;
1225 struct if_llreach_info *lri;
1226 struct timeval time;
1227 char *buf;
1228 char ifname[IF_NAMESIZE];
1229
1230 bzero(&mib, sizeof (mib));
1231 mibsize = sizeof (mib) / sizeof (mib[0]);
1232 if (sysctlnametomib("net.link.generic.system.llreach_info", mib,
1233 &mibsize) == -1) {
1234 perror("sysctlnametomib");
1235 return;
1236 }
1237
1238 needed = 0;
1239 mib[5] = ifindex;
1240
1241 mibsize = sizeof (mib) / sizeof (mib[0]);
1242 do {
1243 if (sysctl(mib, mibsize, NULL, &needed, NULL, 0) == -1) {
1244 perror("sysctl net.link.generic.system.llreach_info");
1245 return;
1246 }
1247 if ((buf = malloc(needed)) == NULL) {
1248 perror("malloc");
1249 return;
1250 }
1251 if (sysctl(mib, mibsize, buf, &needed, NULL, 0) == -1) {
1252 if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
1253 perror("sysctl");
1254 goto out_free;
1255 }
1256 free(buf);
1257 buf = NULL;
1258 }
1259 } while (buf == NULL);
1260
1261 len = needed;
1262 cnt = len / sizeof (*lri);
1263 lri = (struct if_llreach_info *)buf;
1264
1265 gettimeofday(&time, 0);
1266 if (if_indextoname(ifindex, ifname) == NULL)
1267 snprintf(ifname, sizeof (ifname), "%s", "?");
1268
1269 for (i = 0; i < cnt; i++, lri++) {
1270 printf("0x%-4x %-17s %8.8s ", lri->lri_proto,
1271 ether_ntoa((struct ether_addr *)lri->lri_addr), ifname);
1272
1273 if (lri->lri_expire > time.tv_sec)
1274 printf("%-9.9s", sec2str(lri->lri_expire - time.tv_sec));
1275 else if (lri->lri_expire == 0)
1276 printf("%-9.9s", "permanent");
1277 else
1278 printf("%-9.9s", "expired");
1279
1280 printf(" %4d", lri->lri_refcnt);
1281 if (lri->lri_probes)
1282 printf(" %4d", lri->lri_probes);
7af5ce03
A
1283
1284 if (xflag) {
1285 if (!lri->lri_probes)
1286 printf(" %-4.4s", "none");
1287
1288 if (lri->lri_rssi != IFNET_RSSI_UNKNOWN)
1289 printf(" %7d", lri->lri_rssi);
1290 else
1291 printf(" %-7.7s", "unknown");
1292
1293 switch (lri->lri_lqm)
1294 {
1295 case IFNET_LQM_THRESH_OFF:
1296 printf(" %-7.7s", "off");
1297 break;
1298 case IFNET_LQM_THRESH_UNKNOWN:
1299 printf(" %-7.7s", "unknown");
1300 break;
1301 case IFNET_LQM_THRESH_POOR:
1302 printf(" %-7.7s", "poor");
1303 break;
1304 case IFNET_LQM_THRESH_GOOD:
1305 printf(" %-7.7s", "good");
1306 break;
1307 default:
1308 printf(" %7d", lri->lri_lqm);
1309 break;
1310 }
1311
1312 switch (lri->lri_npm)
1313 {
1314 case IFNET_NPM_THRESH_UNKNOWN:
1315 printf(" %-7.7s", "unknown");
1316 break;
1317 case IFNET_NPM_THRESH_NEAR:
1318 printf(" %-7.7s", "near");
1319 break;
1320 case IFNET_NPM_THRESH_GENERAL:
1321 printf(" %-7.7s", "general");
1322 break;
1323 case IFNET_NPM_THRESH_FAR:
1324 printf(" %-7.7s", "far");
1325 break;
1326 default:
1327 printf(" %7d", lri->lri_npm);
1328 break;
1329 }
1330 }
1331
fdfd5971
A
1332 printf("\n");
1333 len -= sizeof (*lri);
1334 }
7af5ce03 1335
fdfd5971
A
1336 if (len > 0) {
1337 fprintf(stderr, "warning: %u trailing bytes from %s\n",
1338 (unsigned int)len, "net.link.generic.system.llreach_info");
1339 }
1340
1341out_free:
1342 free(buf);
1343#undef MAX_SYSCTL_TRY
1344}
7af5ce03
A
1345
1346void
1347aqstatpr(void)
1348{
1349 unsigned int ifindex;
1350 struct itimerval timer_interval;
1351 struct if_qstatsreq ifqr;
1352 struct if_ifclassq_stats *ifcqs;
1353 sigset_t sigset, oldsigset;
1354 u_int32_t scheduler;
a3cc5c72 1355 int s, n;
7af5ce03
A
1356
1357 if (cq < -1 || cq >= IFCQ_SC_MAX) {
1358 fprintf(stderr, "Invalid classq index (range is 0-%d)\n",
1359 IFCQ_SC_MAX-1);
1360 return;
1361 }
1362 ifindex = if_nametoindex(interface);
1363 if (ifindex == 0) {
1364 fprintf(stderr, "Invalid interface name\n");
1365 return;
1366 }
1367
1368 ifcqs = malloc(sizeof (*ifcqs));
1369 if (ifcqs == NULL) {
1370 fprintf(stderr, "Unable to allocate memory\n");
1371 return;
1372 }
1373
1374 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1375 perror("Warning: socket(AF_INET)");
1376 free(ifcqs);
1377 return;
1378 }
1379
1380 bzero(&ifqr, sizeof (ifqr));
1381 strlcpy(ifqr.ifqr_name, interface, sizeof (ifqr.ifqr_name));
1382 ifqr.ifqr_buf = ifcqs;
1383 ifqr.ifqr_len = sizeof (*ifcqs);
1384
1385loop:
1386 if (interval > 0) {
1387 /* create a timer that fires repeatedly every interval seconds */
1388 timer_interval.it_value.tv_sec = interval;
1389 timer_interval.it_value.tv_usec = 0;
1390 timer_interval.it_interval.tv_sec = interval;
1391 timer_interval.it_interval.tv_usec = 0;
1392 (void) signal(SIGALRM, catchalarm);
1393 signalled = NO;
1394 (void) setitimer(ITIMER_REAL, &timer_interval, NULL);
1395 }
1396
1397 ifqr.ifqr_slot = 0;
1398 if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) {
1399 if (errno == ENXIO) {
1400 printf("Queue statistics are not available on %s\n",
1401 interface);
1402 } else {
1403 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1404 }
1405 goto done;
1406 }
1407 scheduler = ifcqs->ifqs_scheduler;
7af5ce03
A
1408
1409 printf("%s:\n"
a3cc5c72
A
1410 " [ sched: %9s qlength: %3d/%3d ]\n",
1411 interface, sched2str(ifcqs->ifqs_scheduler),
1412 ifcqs->ifqs_len, ifcqs->ifqs_maxlen);
1413 printf(" [ pkts: %10llu bytes: %10llu "
1414 " dropped pkts: %6llu bytes: %6llu ]\n",
1415 ifcqs->ifqs_xmitcnt.packets, ifcqs->ifqs_xmitcnt.bytes,
7af5ce03
A
1416 ifcqs->ifqs_dropcnt.packets, ifcqs->ifqs_dropcnt.bytes);
1417
7af5ce03
A
1418 for (n = 0; n < IFCQ_SC_MAX && scheduler != PKTSCHEDT_NONE; n++) {
1419 if (cq >= 0 && cq != n)
1420 continue;
1421
1422 ifqr.ifqr_slot = n;
1423 if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) {
1424 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1425 goto done;
1426 }
1427
1428 update_avg(ifcqs, &qstats[n]);
1429
1430 switch (scheduler) {
26c66ce9
A
1431 case PKTSCHEDT_FQ_CODEL:
1432 print_fq_codel_stats(n,
1433 &ifcqs->ifqs_fq_codel_stats,
1434 &qstats[n]);
1435 break;
7af5ce03
A
1436 case PKTSCHEDT_NONE:
1437 default:
1438 break;
1439 }
1440 }
1441
1442 fflush(stdout);
1443
1444 if (interval > 0) {
1445 sigemptyset(&sigset);
1446 sigaddset(&sigset, SIGALRM);
1447 (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
1448 if (!signalled) {
1449 sigemptyset(&sigset);
1450 sigsuspend(&sigset);
1451 }
1452 (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL);
1453
1454 signalled = NO;
1455 goto loop;
1456 }
1457
1458done:
1459 free(ifcqs);
1460 close(s);
1461}
1462
26c66ce9
A
1463static void
1464print_fq_codel_stats(int pri, struct fq_codel_classstats *fqst,
1465 struct queue_stats *qs)
1466{
d9520f62
A
1467 int i = 0;
1468
1469 if (fqst->fcls_service_class == 0 && fqst->fcls_pri == 0)
1470 return;
1471 printf("=====================================================\n");
26c66ce9
A
1472 printf(" [ pri: %s (%d)\tsrv_cl: 0x%x\tquantum: %d\tdrr_max: %d ]\n",
1473 pri2str(fqst->fcls_pri), fqst->fcls_pri,
1474 fqst->fcls_service_class, fqst->fcls_quantum,
1475 fqst->fcls_drr_max);
d9520f62
A
1476 printf(" [ queued pkts: %llu\tbytes: %llu ]\n",
1477 fqst->fcls_pkt_cnt, fqst->fcls_byte_cnt);
1478 printf(" [ dequeued pkts: %llu\tbytes: %llu ]\n",
1479 fqst->fcls_dequeue, fqst->fcls_dequeue_bytes);
1480 printf(" [ budget: %lld\ttarget qdelay: %10s\t",
26c66ce9 1481 fqst->fcls_budget, nsec_to_str(fqst->fcls_target_qdelay));
d9520f62
A
1482 printf("update interval:%10s ]\n",
1483 nsec_to_str(fqst->fcls_update_interval));
26c66ce9
A
1484 printf(" [ flow control: %u\tfeedback: %u\tstalls: %u\tfailed: %u ]\n",
1485 fqst->fcls_flow_control, fqst->fcls_flow_feedback,
1486 fqst->fcls_dequeue_stall, fqst->fcls_flow_control_fail);
1487 printf(" [ drop overflow: %llu\tearly: %llu\tmemfail: %u\tduprexmt:%u ]\n",
1488 fqst->fcls_drop_overflow, fqst->fcls_drop_early,
1489 fqst->fcls_drop_memfailure, fqst->fcls_dup_rexmts);
1490 printf(" [ flows total: %u\tnew: %u\told: %u ]\n",
1491 fqst->fcls_flows_cnt,
1492 fqst->fcls_newflows_cnt, fqst->fcls_oldflows_cnt);
26c66ce9
A
1493 printf(" [ throttle on: %u\toff: %u\tdrop: %u ]\n",
1494 fqst->fcls_throttle_on, fqst->fcls_throttle_off,
1495 fqst->fcls_throttle_drops);
a3cc5c72
A
1496 printf(" [ compressible pkts: %u compressed pkts: %u]\n",
1497 fqst->fcls_pkts_compressible, fqst->fcls_pkts_compressed);
d9520f62
A
1498
1499 if (qflag < 2)
1500 return;
1501
1502 if (fqst->fcls_flowstats_cnt > 0) {
1503 printf("Flowhash\tBytes\tMin qdelay\tFlags\t\n");
1504 for (i = 0; i < fqst->fcls_flowstats_cnt; i++) {
1505 printf("%u\t%u\t%14s\t",
1506 fqst->fcls_flowstats[i].fqst_flowhash,
1507 fqst->fcls_flowstats[i].fqst_bytes,
1508 nsec_to_str(fqst->fcls_flowstats[i].fqst_min_qdelay));
1509 if (fqst->fcls_flowstats[i].fqst_flags &
1510 FQ_FLOWSTATS_OLD_FLOW)
1511 printf("O");
1512 if (fqst->fcls_flowstats[i].fqst_flags &
1513 FQ_FLOWSTATS_NEW_FLOW)
1514 printf("N");
1515 if (fqst->fcls_flowstats[i].fqst_flags &
1516 FQ_FLOWSTATS_LARGE_FLOW)
1517 printf("L");
1518 if (fqst->fcls_flowstats[i].fqst_flags &
1519 FQ_FLOWSTATS_DELAY_HIGH)
1520 printf("D");
1521 if (fqst->fcls_flowstats[i].fqst_flags &
1522 FQ_FLOWSTATS_FLOWCTL_ON)
1523 printf("F");
1524 printf("\n");
1525 }
1526 }
26c66ce9
A
1527}
1528
7af5ce03
A
1529static void
1530update_avg(struct if_ifclassq_stats *ifcqs, struct queue_stats *qs)
1531{
1532 u_int64_t b, p;
1533 int n;
1534
1535 n = qs->avgn;
1536
1537 switch (ifcqs->ifqs_scheduler) {
26c66ce9
A
1538 case PKTSCHEDT_FQ_CODEL:
1539 b = ifcqs->ifqs_fq_codel_stats.fcls_dequeue_bytes;
1540 p = ifcqs->ifqs_fq_codel_stats.fcls_dequeue;
1541 break;
7af5ce03
A
1542 default:
1543 b = 0;
1544 p = 0;
1545 break;
1546 }
1547
1548 if (n == 0) {
1549 qs->prev_bytes = b;
1550 qs->prev_packets = p;
1551 qs->avgn++;
1552 return;
1553 }
1554
1555 if (b >= qs->prev_bytes)
1556 qs->avg_bytes = ((qs->avg_bytes * (n - 1)) +
1557 (b - qs->prev_bytes)) / n;
1558
1559 if (p >= qs->prev_packets)
1560 qs->avg_packets = ((qs->avg_packets * (n - 1)) +
1561 (p - qs->prev_packets)) / n;
1562
1563 qs->prev_bytes = b;
1564 qs->prev_packets = p;
1565 if (n < AVGN_MAX)
1566 qs->avgn++;
1567}
1568
7af5ce03 1569#define NSEC_PER_SEC 1000000000 /* nanoseconds per second */
26c66ce9
A
1570#define USEC_PER_SEC 1000000 /* microseconds per second */
1571#define MSEC_PER_SEC 1000 /* milliseconds per second */
7af5ce03
A
1572
1573static char *
1574nsec_to_str(unsigned long long nsec)
1575{
1576 static char buf[32];
1577 const char *u;
1578 long double n = nsec, t;
1579
1580 if (nsec >= NSEC_PER_SEC) {
1581 t = n / NSEC_PER_SEC;
1582 u = "sec ";
1583 } else if (n >= USEC_PER_SEC) {
1584 t = n / USEC_PER_SEC;
1585 u = "msec";
1586 } else if (n >= MSEC_PER_SEC) {
1587 t = n / MSEC_PER_SEC;
1588 u = "usec";
1589 } else {
1590 t = n;
1591 u = "nsec";
1592 }
1593
1594 snprintf(buf, sizeof (buf), "%-4.2Lf %4s", t, u);
1595 return (buf);
1596}
1597
1598static char *
1599sched2str(unsigned int s)
1600{
1601 char *c;
1602
1603 switch (s) {
1604 case PKTSCHEDT_NONE:
1605 c = "NONE";
1606 break;
26c66ce9
A
1607 case PKTSCHEDT_FQ_CODEL:
1608 c = "FQ_CODEL";
1609 break;
7af5ce03
A
1610 default:
1611 c = "UNKNOWN";
1612 break;
1613 }
1614
1615 return (c);
1616}
1617
26c66ce9
A
1618static char *
1619pri2str(unsigned int i)
1620{
1621 char *c;
1622 switch (i) {
1623 case 9:
1624 c = "BK_SYS";
1625 break;
1626 case 8:
1627 c = "BK";
1628 break;
1629 case 7:
1630 c = "BE";
1631 break;
1632 case 6:
1633 c = "RD";
1634 break;
1635 case 5:
1636 c = "OAM";
1637 break;
1638 case 4:
1639 c = "AV";
1640 break;
1641 case 3:
1642 c = "RV";
1643 break;
1644 case 2:
1645 c = "VI";
1646 break;
1647 case 1:
1648 c = "VO";
1649 break;
1650 case 0:
1651 c = "CTL";
1652 break;
1653 default:
1654 c = "?";
1655 break;
1656 }
1657 return (c);
1658}
1659
7af5ce03
A
1660void
1661rxpollstatpr(void)
1662{
1663 struct ifmibdata_supplemental ifmsupp;
1664 size_t miblen = sizeof (ifmsupp);
1665 struct itimerval timer_interval;
1666 struct if_rxpoll_stats *sp;
e0b07f2d 1667 struct if_netif_stats *np;
7af5ce03
A
1668 sigset_t sigset, oldsigset;
1669 unsigned int ifindex;
1670 int name[6];
1671
1672 ifindex = if_nametoindex(interface);
1673 if (ifindex == 0) {
1674 fprintf(stderr, "Invalid interface name\n");
1675 return;
1676 }
1677
1678 bzero(&ifmsupp, sizeof (struct ifmibdata_supplemental));
1679
1680loop:
1681 if (interval > 0) {
1682 /* create a timer that fires repeatedly every interval seconds */
1683 timer_interval.it_value.tv_sec = interval;
1684 timer_interval.it_value.tv_usec = 0;
1685 timer_interval.it_interval.tv_sec = interval;
1686 timer_interval.it_interval.tv_usec = 0;
1687 (void) signal(SIGALRM, catchalarm);
1688 signalled = NO;
1689 (void) setitimer(ITIMER_REAL, &timer_interval, NULL);
1690 }
1691
1692 /* Common OID prefix */
1693 name[0] = CTL_NET;
1694 name[1] = PF_LINK;
1695 name[2] = NETLINK_GENERIC;
1696 name[3] = IFMIB_IFDATA;
1697 name[4] = ifindex;
1698 name[5] = IFDATA_SUPPLEMENTAL;
1699 if (sysctl(name, 6, &ifmsupp, &miblen, NULL, 0) == -1)
1700 err(1, "sysctl IFDATA_SUPPLEMENTAL");
1701
1702 sp = &ifmsupp.ifmd_rxpoll_stats;
1703
1704 printf("%-4s [ poll on requests: %15u errors: %27u ]\n",
1705 interface, sp->ifi_poll_on_req, sp->ifi_poll_on_err);
1706 printf(" [ poll off requests: %15u errors: %27u ]\n",
1707 sp->ifi_poll_off_req, sp->ifi_poll_off_err);
f1dee6ae 1708 printf(" [ polled packets: %18llu per poll limit: %19u ]\n",
e0b07f2d
A
1709 sp->ifi_poll_packets, sp->ifi_poll_packets_limit);
1710 printf(" [ polled bytes: %20llu ]\n", sp->ifi_poll_bytes);
1711 printf(" [ poll interval: %14llu nsec ]\n",
1712 sp->ifi_poll_interval_time);
7af5ce03
A
1713 printf(" [ sampled packets avg/min/max: %12u / %12u / %12u ]\n",
1714 sp->ifi_poll_packets_avg, sp->ifi_poll_packets_min,
1715 sp->ifi_poll_packets_max);
1716 printf(" [ sampled bytes avg/min/max: %12u / %12u / %12u ]\n",
1717 sp->ifi_poll_bytes_avg, sp->ifi_poll_bytes_min,
1718 sp->ifi_poll_bytes_max);
1719 printf(" [ sampled wakeups avg: %12u ]\n",
1720 sp->ifi_poll_wakeups_avg);
1721 printf(" [ packets lowat/hiwat threshold: %10u / %10u ]\n",
1722 sp->ifi_poll_packets_lowat, sp->ifi_poll_packets_hiwat);
1723 printf(" [ bytes lowat/hiwat threshold: %10u / %10u ]\n",
1724 sp->ifi_poll_bytes_lowat, sp->ifi_poll_bytes_hiwat);
1725 printf(" [ wakeups lowat/hiwat threshold: %10u / %10u ]\n",
1726 sp->ifi_poll_wakeups_lowat, sp->ifi_poll_wakeups_hiwat);
1727
e0b07f2d
A
1728 np = &ifmsupp.ifmd_netif_stats;
1729 printf(" [ mit mode: %24U cfg idx: %26u ]\n",
1730 np->ifn_rx_mit_mode, np->ifn_rx_mit_cfg_idx);
1731 printf(" [ cfg packets lo/hi threshold: %12u / %12u ]\n",
1732 np->ifn_rx_mit_cfg_packets_lowat, np->ifn_rx_mit_cfg_packets_hiwat);
1733 printf(" [ cfg bytes lo/hi threshold: %12u / %12u ]\n",
1734 np->ifn_rx_mit_cfg_bytes_lowat, np->ifn_rx_mit_cfg_bytes_hiwat);
f1dee6ae 1735 printf(" [ cfg interval: %15u nsec ]\n",
e0b07f2d
A
1736 np->ifn_rx_mit_cfg_interval);
1737 printf(" [ mit interval: %15llu nsec ]\n",
1738 np->ifn_rx_mit_interval);
1739 printf(" [ mit packets avg/min/max: %12u / %12u / %12u ]\n",
1740 np->ifn_rx_mit_packets_avg, np->ifn_rx_mit_packets_min,
1741 np->ifn_rx_mit_packets_max);
1742 printf(" [ mit bytes avg/min/max: %12u / %12u / %12u ]\n",
1743 np->ifn_rx_mit_bytes_avg, np->ifn_rx_mit_bytes_min,
1744 np->ifn_rx_mit_bytes_max);
1745
7af5ce03
A
1746 fflush(stdout);
1747
1748 if (interval > 0) {
1749 sigemptyset(&sigset);
1750 sigaddset(&sigset, SIGALRM);
1751 (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
1752 if (!signalled) {
1753 sigemptyset(&sigset);
1754 sigsuspend(&sigset);
1755 }
1756 (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL);
1757
1758 signalled = NO;
1759 goto loop;
1760 }
1761}
89c4ed63
A
1762
1763static int
1764create_control_socket(const char *control_name)
1765{
1766 struct sockaddr_ctl sc;
1767 struct ctl_info ctl;
1768 int fd;
1769
1770 fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
1771 if (fd == -1) {
1772 perror("socket(PF_SYSTEM)");
1773 return fd;
1774 }
1775
1776 /* Get the control ID for statistics */
1777 bzero(&ctl, sizeof(ctl));
1778 strlcpy(ctl.ctl_name, control_name, sizeof(ctl.ctl_name));
1779 if (ioctl(fd, CTLIOCGINFO, &ctl) == -1)
1780 {
1781 perror("ioctl(CTLIOCGINFO)");
1782 close(fd);
1783 return -1;
1784 }
1785
1786 /* Connect to the statistics control */
1787 bzero(&sc, sizeof(sc));
1788 sc.sc_len = sizeof(sc);
1789 sc.sc_family = AF_SYSTEM;
1790 sc.ss_sysaddr = SYSPROTO_CONTROL;
1791 sc.sc_id = ctl.ctl_id;
1792 sc.sc_unit = 0;
1793 if (connect(fd, (struct sockaddr*)&sc, sc.sc_len) != 0)
1794 {
1795 perror("connect(SYSPROTO_CONTROL)");
1796 close(fd);
1797 return -1;
1798 }
1799
1800 /* Set socket to non-blocking operation */
1801 if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) == -1) {
1802 perror("fcnt(F_SETFL,O_NONBLOCK)");
1803 close(fd);
1804 return -1;
1805 }
1806 return fd;
1807}
1808
1809static int
1810add_nstat_src(int fd, const nstat_ifnet_add_param *ifparam,
1811 nstat_src_ref_t *outsrc)
1812{
1813 nstat_msg_add_src_req *addreq;
1814 nstat_msg_src_added *addedmsg;
1815 nstat_ifnet_add_param *param;
1816 char buffer[sizeof(*addreq) + sizeof(*param)];
1817 ssize_t result;
1818 const u_int32_t addreqsize =
1819 offsetof(struct nstat_msg_add_src, param) + sizeof(*param);
1820
1821 /* Setup the add source request */
1822 addreq = (nstat_msg_add_src_req *)buffer;
1823 param = (nstat_ifnet_add_param*)addreq->param;
1824 bzero(addreq, addreqsize);
1825 addreq->hdr.context = (uintptr_t)&buffer;
1826 addreq->hdr.type = NSTAT_MSG_TYPE_ADD_SRC;
1827 addreq->provider = NSTAT_PROVIDER_IFNET;
1828 bzero(param, sizeof(*param));
1829 param->ifindex = ifparam->ifindex;
1830 param->threshold = ifparam->threshold;
1831
1832 /* Send the add source request */
1833 result = send(fd, addreq, addreqsize, 0);
1834 if (result != addreqsize)
1835 {
1836 if (result == -1)
1837 perror("send(NSTAT_ADD_SRC_REQ)");
1838 else
1839 fprintf(stderr, "%s: could only sent %ld out of %d\n",
1840 __func__, result, addreqsize);
1841 return -1;
1842 }
1843
1844 /* Receive the response */
1845 addedmsg = (nstat_msg_src_added *)buffer;
1846 result = recv(fd, addedmsg, sizeof(buffer), 0);
1847 if (result < sizeof(*addedmsg))
1848 {
1849 if (result == -1)
1850 perror("recv(NSTAT_ADD_SRC_RSP)");
1851 else
1852 fprintf(stderr, "%s: recv too small, received %ld, "
1853 "expected %lu\n", __func__, result,
1854 sizeof(*addedmsg));
1855 return -1;
1856 }
1857
1858 if (addedmsg->hdr.type != NSTAT_MSG_TYPE_SRC_ADDED)
1859 {
1860 fprintf(stderr, "%s: received wrong message type, received %u "
1861 "expected %u\n", __func__, addedmsg->hdr.type,
1862 NSTAT_MSG_TYPE_SRC_ADDED);
1863 return -1;
1864 }
1865
1866 if (addedmsg->hdr.context != (uintptr_t)&buffer)
1867 {
1868 fprintf(stderr, "%s: received wrong context, received %llu "
1869 "expected %lu\n", __func__, addedmsg->hdr.context,
1870 (uintptr_t)&buffer);
1871 return -1;
1872 }
1873 *outsrc = addedmsg->srcref;
1874 return 0;
1875}
1876
1877static int
1878rem_nstat_src(int fd, nstat_src_ref_t sref)
1879{
1880 nstat_msg_rem_src_req *remreq;
1881 nstat_msg_src_removed *remrsp;
1882 char buffer[sizeof(*remreq)];
1883 ssize_t result;
1884
1885 /* Setup the add source request */
1886 remreq = (nstat_msg_rem_src_req *)buffer;
1887 bzero(remreq, sizeof(*remreq));
1888 remreq->hdr.type = NSTAT_MSG_TYPE_REM_SRC;
1889 remreq->srcref = sref;
1890
1891 /* Send the remove source request */
1892 result = send(fd, remreq, sizeof(*remreq), 0);
1893 if (result != sizeof(*remreq)) {
1894 if (result == -1)
1895 perror("send(NSTAT_REM_SRC_REQ)");
1896 else
1897 fprintf(stderr, "%s: could only sent %ld out of %lu\n",
1898 __func__, result, sizeof(*remreq));
1899 return -1;
1900 }
1901
1902 /* Receive the response */
1903 remrsp = (nstat_msg_src_removed *)buffer;
1904 result = recv(fd, remrsp, sizeof(buffer), 0);
1905 if (result < sizeof(*remrsp)) {
1906 if (result == -1)
1907 perror("recv(NSTAT_REM_SRC_RSP)");
1908 else
1909 fprintf(stderr, "%s: recv too small, received %ld, "
1910 "expected %lu\n", __func__, result,
1911 sizeof(*remrsp));
1912 return -1;
1913 }
1914
1915 if (remrsp->hdr.type != NSTAT_MSG_TYPE_SRC_REMOVED) {
1916 fprintf(stderr, "%s: received wrong message type, received %u "
1917 "expected %u\n", __func__, remrsp->hdr.type,
1918 NSTAT_MSG_TYPE_SRC_REMOVED);
1919 return -1;
1920 }
1921
1922 if (remrsp->srcref != sref) {
26c66ce9
A
1923 fprintf(stderr, "%s: received invalid srcref, received %llu "
1924 "expected %llu\n", __func__, remrsp->srcref, sref);
89c4ed63
A
1925 }
1926 return 0;
1927}
1928
1929static int
1930get_src_decsription(int fd, nstat_src_ref_t srcref,
1931 struct nstat_ifnet_descriptor *ifdesc)
1932{
1933 nstat_msg_get_src_description *dreq;
1934 nstat_msg_src_description *drsp;
1935 char buffer[sizeof(*drsp) + sizeof(*ifdesc)];
1936 ssize_t result;
1937 const u_int32_t descsize =
1938 offsetof(struct nstat_msg_src_description, data) +
1939 sizeof(nstat_ifnet_descriptor);
1940
1941 dreq = (nstat_msg_get_src_description *)buffer;
1942 bzero(dreq, sizeof(*dreq));
1943 dreq->hdr.type = NSTAT_MSG_TYPE_GET_SRC_DESC;
1944 dreq->srcref = srcref;
1945 result = send(fd, dreq, sizeof(*dreq), 0);
1946 if (result != sizeof(*dreq))
1947 {
1948 if (result == -1)
1949 perror("send(NSTAT_GET_SRC_DESC_REQ)");
1950 else
1951 fprintf(stderr, "%s: sent %ld out of %lu\n",
1952 __func__, result, sizeof(*dreq));
1953 return -1;
1954 }
1955
1956 /* Receive the source description response */
1957 drsp = (nstat_msg_src_description *)buffer;
1958 result = recv(fd, drsp, sizeof(buffer), 0);
1959 if (result < descsize)
1960 {
1961 if (result == -1)
1962 perror("recv(NSTAT_GET_SRC_DESC_RSP");
1963 else
1964 fprintf(stderr, "%s: recv too small, received %ld, "
1965 "expected %u\n", __func__, result, descsize);
1966 return -1;
1967 }
1968
1969 if (drsp->hdr.type != NSTAT_MSG_TYPE_SRC_DESC)
1970 {
1971 fprintf(stderr, "%s: received wrong message type, received %u "
1972 "expected %u\n", __func__, drsp->hdr.type,
1973 NSTAT_MSG_TYPE_SRC_DESC);
1974 return -1;
1975 }
1976
1977 if (drsp->srcref != srcref)
1978 {
1979 fprintf(stderr, "%s: received message for wrong source, "
26c66ce9 1980 "received 0x%llx expected 0x%llx\n",
89c4ed63
A
1981 __func__, drsp->srcref, srcref);
1982 return -1;
1983 }
1984
1985 bcopy(drsp->data, ifdesc, sizeof(*ifdesc));
1986 return 0;
1987}
1988
1989static void
1990print_wifi_status(nstat_ifnet_desc_wifi_status *status)
1991{
1992 int tmp;
1993#define val(x, f) \
1994 ((status->valid_bitmask & NSTAT_IFNET_DESC_WIFI_ ## f ## _VALID) ?\
1995 status->x : -1)
1996#define parg(n, un) #n, val(n, un)
1997#define pretxtl(n, un) \
1998 (((tmp = val(n, un)) == -1) ? "(not valid)" : \
1999 ((tmp == NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_NONE) ? "(none)" : \
2000 ((tmp == NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_LOW) ? "(low)" : \
2001 ((tmp == NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_MEDIUM) ? "(medium)" : \
2002 ((tmp == NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_HIGH) ? "(high)" : \
2003 "(?)")))))
2004
2005 printf("\nwifi status:\n");
2006 printf(
2007 "\t%s:\t%d\n"
2008 "\t%s:\t%d\n"
2009 "\t%s:\t%d\n"
2010 "\t%s:\t\t%d\n"
2011 "\t%s:\t%d\n"
2012 "\t%s:\t\t%d\n"
2013 "\t%s:\t\t%d%s\n"
2014 "\t%s:\t\t%d\n"
2015 "\t%s:\t\t%d\n"
2016 "\t%s:\t%d\n"
2017 "\t%s:\t%d\n"
2018 "\t%s:\t\t%d\n"
2019 "\t%s:\t%d\n"
2020 "\t%s:\t\t%d\n"
2021 "\t%s:\t\t%d\n"
2022 "\t%s:\t%d\n"
2023 "\t%s:\t%d\n"
2024 "\t%s:\t\t%d\n"
2025 "\t%s:\t\t%d\n",
2026 parg(link_quality_metric, LINK_QUALITY_METRIC),
2027 parg(ul_effective_bandwidth, UL_EFFECTIVE_BANDWIDTH),
2028 parg(ul_max_bandwidth, UL_MAX_BANDWIDTH),
2029 parg(ul_min_latency, UL_MIN_LATENCY),
2030 parg(ul_effective_latency, UL_EFFECTIVE_LATENCY),
2031 parg(ul_max_latency, UL_MAX_LATENCY),
2032 parg(ul_retxt_level, UL_RETXT_LEVEL),
2033 pretxtl(ul_retxt_level, UL_RETXT_LEVEL),
2034 parg(ul_bytes_lost, UL_BYTES_LOST),
2035 parg(ul_error_rate, UL_ERROR_RATE),
2036 parg(dl_effective_bandwidth, DL_EFFECTIVE_BANDWIDTH),
2037 parg(dl_max_bandwidth, DL_MAX_BANDWIDTH),
2038 parg(dl_min_latency, DL_MIN_LATENCY),
2039 parg(dl_effective_latency, DL_EFFECTIVE_LATENCY),
2040 parg(dl_max_latency, DL_MAX_LATENCY),
2041 parg(dl_error_rate, DL_ERROR_RATE),
2042 parg(config_frequency, CONFIG_FREQUENCY),
2043 parg(config_multicast_rate, CONFIG_MULTICAST_RATE),
2044 parg(scan_count, CONFIG_SCAN_COUNT),
2045 parg(scan_duration, CONFIG_SCAN_DURATION)
2046 );
2047#undef pretxtl
2048#undef parg
2049#undef val
2050}
2051
2052static void
2053print_cellular_status(nstat_ifnet_desc_cellular_status *status)
2054{
26c66ce9 2055 int tmp, tmp_mss;
89c4ed63
A
2056#define val(x, f) \
2057 ((status->valid_bitmask & NSTAT_IFNET_DESC_CELL_ ## f ## _VALID) ?\
2058 status->x : -1)
2059#define parg(n, un) #n, val(n, un)
2060#define pretxtl(n, un) \
2061 (((tmp = val(n, un)) == -1) ? "(not valid)" : \
2062 ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_NONE) ? "(none)" : \
2063 ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_LOW) ? "(low)" : \
2064 ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_MEDIUM) ? "(medium)" : \
2065 ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_HIGH) ? "(high)" : \
2066 "(?)")))))
26c66ce9
A
2067#define pretxtm(n, un) \
2068 (((tmp_mss = val(n,un)) == -1) ? "(not valid)" : \
2069 ((tmp_mss == NSTAT_IFNET_DESC_MSS_RECOMMENDED_NONE) ? "(none)" : \
2070 ((tmp_mss == NSTAT_IFNET_DESC_MSS_RECOMMENDED_MEDIUM) ? "(medium)" : \
2071 ((tmp_mss == NSTAT_IFNET_DESC_MSS_RECOMMENDED_LOW) ? "(low)" : \
2072 "(?)"))))
89c4ed63
A
2073
2074 printf("\ncellular status:\n");
2075 printf(
2076 "\t%s:\t%d\n"
2077 "\t%s:\t%d\n"
2078 "\t%s:\t%d\n"
2079 "\t%s:\t\t%d\n"
2080 "\t%s:\t%d\n"
2081 "\t%s:\t\t%d\n"
2082 "\t%s:\t\t%d%s\n"
2083 "\t%s:\t\t%d\n"
2084 "\t%s:\t%d\n"
2085 "\t%s:\t%d\n"
2086 "\t%s:\t%d\n"
2087 "\t%s:\t%d\n"
2088 "\t%s:\t%d\n"
2089 "\t%s:\t%d\n"
26c66ce9
A
2090 "\t%s:\t%d\n"
2091 "\t%s:\t%d %s\n",
89c4ed63
A
2092 parg(link_quality_metric, LINK_QUALITY_METRIC),
2093 parg(ul_effective_bandwidth, UL_EFFECTIVE_BANDWIDTH),
2094 parg(ul_max_bandwidth, UL_MAX_BANDWIDTH),
2095 parg(ul_min_latency, UL_MIN_LATENCY),
2096 parg(ul_effective_latency, UL_EFFECTIVE_LATENCY),
2097 parg(ul_max_latency, UL_MAX_LATENCY),
2098 parg(ul_retxt_level, UL_RETXT_LEVEL),
2099 pretxtl(ul_retxt_level, UL_RETXT_LEVEL),
2100 parg(ul_bytes_lost, UL_BYTES_LOST),
2101 parg(ul_min_queue_size, UL_MIN_QUEUE_SIZE),
2102 parg(ul_avg_queue_size, UL_AVG_QUEUE_SIZE),
2103 parg(ul_max_queue_size, UL_MAX_QUEUE_SIZE),
2104 parg(dl_effective_bandwidth, DL_EFFECTIVE_BANDWIDTH),
2105 parg(dl_max_bandwidth, DL_MAX_BANDWIDTH),
2106 parg(config_inactivity_time, CONFIG_INACTIVITY_TIME),
26c66ce9
A
2107 parg(config_backoff_time, CONFIG_BACKOFF_TIME),
2108 parg(mss_recommended, MSS_RECOMMENDED),
2109 pretxtm(mss_recommended, MSS_RECOMMENDED)
89c4ed63
A
2110 );
2111#undef pretxtl
2112#undef parg
2113#undef val
2114}
2115
2116static int
2117get_interface_state(int fd, const char *ifname, struct ifreq *ifr)
2118{
2119 bzero(ifr, sizeof(*ifr));
2120 snprintf(ifr->ifr_name, sizeof(ifr->ifr_name), "%s", ifname);
2121
2122 if (ioctl(fd, SIOCGIFINTERFACESTATE, ifr) == -1) {
2123 perror("ioctl(CTLIOCGINFO)");
2124 return -1;
2125 }
2126 return 0;
2127}
2128
2129static void
2130print_interface_state(struct ifreq *ifr)
2131{
2132 int lqm, rrc, avail;
2133
2134 printf("\ninterface state:\n");
2135
2136 if (ifr->ifr_interface_state.valid_bitmask &
2137 IF_INTERFACE_STATE_LQM_STATE_VALID) {
2138 printf("\tlqm: ");
2139 lqm = ifr->ifr_interface_state.lqm_state;
2140 if (lqm == IFNET_LQM_THRESH_GOOD)
2141 printf("\"good\"");
2142 else if (lqm == IFNET_LQM_THRESH_POOR)
2143 printf("\"poor\"");
2144 else if (lqm == IFNET_LQM_THRESH_BAD)
2145 printf("\"bad\"");
2146 else if (lqm == IFNET_LQM_THRESH_UNKNOWN)
2147 printf("\"unknown\"");
2148 else if (lqm == IFNET_LQM_THRESH_OFF)
2149 printf("\"off\"");
2150 else
2151 printf("invalid(%d)", lqm);
2152 }
2153
2154 if (ifr->ifr_interface_state.valid_bitmask &
2155 IF_INTERFACE_STATE_RRC_STATE_VALID) {
2156 printf("\trrc: ");
2157 rrc = ifr->ifr_interface_state.rrc_state;
2158 if (rrc == IF_INTERFACE_STATE_RRC_STATE_CONNECTED)
2159 printf("\"connected\"");
2160 else if (rrc == IF_INTERFACE_STATE_RRC_STATE_IDLE)
2161 printf("\"idle\"");
2162 else
2163 printf("\"invalid(%d)\"", rrc);
2164 }
2165
2166 if (ifr->ifr_interface_state.valid_bitmask &
2167 IF_INTERFACE_STATE_INTERFACE_AVAILABILITY_VALID) {
2168 printf("\tavailability: ");
2169 avail = ifr->ifr_interface_state.interface_availability;
2170 if (avail == IF_INTERFACE_STATE_INTERFACE_AVAILABLE)
2171 printf("\"true\"");
2172 else if (rrc == IF_INTERFACE_STATE_INTERFACE_UNAVAILABLE)
2173 printf("\"false\"");
2174 else
2175 printf("\"invalid(%d)\"", avail);
2176 }
2177}
2178
2179void
2180print_link_status(const char *ifname)
2181{
2182 unsigned int ifindex;
2183 struct itimerval timer_interval;
2184 sigset_t sigset, oldsigset;
2185 struct nstat_ifnet_descriptor ifdesc;
2186 nstat_ifnet_add_param ifparam;
2187 nstat_src_ref_t sref = 0;
2188 struct ifreq ifr;
2189 int ctl_fd;
2190
2191 ifindex = if_nametoindex(ifname);
2192 if (ifindex == 0) {
2193 fprintf(stderr, "Invalid interface name\n");
2194 return;
2195 }
2196
2197 if ((ctl_fd = create_control_socket(NET_STAT_CONTROL_NAME)) < 0)
2198 return;
2199
2200 ifparam.ifindex = ifindex;
2201 ifparam.threshold = UINT64_MAX;
2202 if (add_nstat_src(ctl_fd, &ifparam, &sref))
2203 goto done;
2204loop:
2205 if (interval > 0) {
2206 /* create a timer that fires repeatedly every interval
2207 * seconds */
2208 timer_interval.it_value.tv_sec = interval;
2209 timer_interval.it_value.tv_usec = 0;
2210 timer_interval.it_interval.tv_sec = interval;
2211 timer_interval.it_interval.tv_usec = 0;
2212 (void) signal(SIGALRM, catchalarm);
2213 signalled = NO;
2214 (void) setitimer(ITIMER_REAL, &timer_interval, NULL);
2215 }
2216
2217 /* get interface state */
2218 if (get_interface_state(ctl_fd, ifname, &ifr))
2219 goto done;
2220
2221 /* get ntstat interface description */
2222 if (get_src_decsription(ctl_fd, sref, &ifdesc))
2223 goto done;
2224
2225 /* print time */
2226 printf("\n%s: ", ifname);
2227 print_time();
2228
2229 /* print interface state */
2230 print_interface_state(&ifr);
2231
2232 /* print ntsat interface link status */
2233 if (ifdesc.link_status.link_status_type ==
2234 NSTAT_IFNET_DESC_LINK_STATUS_TYPE_CELLULAR)
2235 print_cellular_status(&ifdesc.link_status.u.cellular);
2236 else if (ifdesc.link_status.link_status_type ==
2237 NSTAT_IFNET_DESC_LINK_STATUS_TYPE_WIFI)
2238 print_wifi_status(&ifdesc.link_status.u.wifi);
2239
2240 fflush(stdout);
2241
2242 if (interval > 0) {
2243 sigemptyset(&sigset);
2244 sigaddset(&sigset, SIGALRM);
2245 (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
2246 if (!signalled) {
2247 sigemptyset(&sigset);
2248 sigsuspend(&sigset);
2249 }
2250 (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL);
2251
2252 signalled = NO;
2253 goto loop;
2254 }
2255done:
2256 if (sref)
2257 rem_nstat_src(ctl_fd, sref);
2258 close(ctl_fd);
2259}