]> git.saurik.com Git - apple/network_cmds.git/blob - netstat.tproj/systm.c
a3c170e1caeb60b6de059640611cde94ac5b7560
[apple/network_cmds.git] / netstat.tproj / systm.c
1 /*
2 * Copyright (c) 2014-2015 Apple Inc. All rights reserved.
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 */
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
61 #include <sys/param.h>
62 #include <sys/queue.h>
63 #include <sys/socket.h>
64 #include <sys/socketvar.h>
65 #include <sys/sysctl.h>
66 #include <sys/sys_domain.h>
67 #include <sys/kern_control.h>
68 #include <sys/kern_event.h>
69 #include <net/ntstat.h>
70
71 #include <errno.h>
72 #include <err.h>
73 #include <stddef.h>
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <strings.h>
77
78 #include "netstat.h"
79
80 #define ROUNDUP64(a) \
81 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint64_t) - 1))) : sizeof(uint64_t))
82 #define ADVANCE64(x, n) (((char *)x) += ROUNDUP64(n))
83
84 struct xgen_n {
85 u_int32_t xgn_len; /* length of this structure */
86 u_int32_t xgn_kind; /* number of PCBs at this time */
87 };
88
89 #define ALL_XGN_KIND_KCREG (XSO_KCREG)
90 #define ALL_XGN_KIND_EVT (XSO_SOCKET | XSO_RCVBUF | XSO_SNDBUF | XSO_STATS | XSO_EVT)
91 #define ALL_XGN_KIND_KCB (XSO_SOCKET | XSO_RCVBUF | XSO_SNDBUF | XSO_STATS | XSO_KCB)
92
93 void
94 systmpr(uint32_t proto,
95 char *name, int af)
96 {
97 const char *mibvar;
98 size_t len;
99 char *buf, *next;
100 struct xsystmgen *xig, *oxig;
101 struct xgen_n *xgn;
102 int which = 0;
103 struct xsocket_n *so = NULL;
104 struct xsockbuf_n *so_rcv = NULL;
105 struct xsockbuf_n *so_snd = NULL;
106 struct xsockstat_n *so_stat = NULL;
107 struct xkctl_reg *kctl = NULL;
108 struct xkctlpcb *kcb = NULL;
109 struct xkevtpcb *kevb = NULL;
110 int first = 1;
111
112 switch (proto) {
113 case SYSPROTO_EVENT:
114 mibvar = "net.systm.kevt.pcblist";
115 break;
116 case SYSPROTO_CONTROL:
117 mibvar = "net.systm.kctl.pcblist";
118 break;
119 case 0:
120 mibvar = "net.systm.kctl.reg_list";
121 break;
122 default:
123 mibvar = NULL;
124 break;
125 }
126 if (mibvar == NULL)
127 return;
128 len = 0;
129 if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
130 if (errno != ENOENT)
131 warn("sysctl: %s", mibvar);
132 return;
133 }
134 if ((buf = malloc(len)) == 0) {
135 warn("malloc %lu bytes", (u_long)len);
136 return;
137 }
138 if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
139 warn("sysctl: %s", mibvar);
140 free(buf);
141 return;
142 }
143 /*
144 * Bail-out to avoid logic error in the loop below when
145 * there is in fact no more control block to process
146 */
147 if (len <= sizeof(struct xsystmgen)) {
148 free(buf);
149 return;
150 }
151 oxig = xig = (struct xsystmgen *)buf;
152 for (next = buf + ROUNDUP64(xig->xg_len); next < buf + len;
153 next += ROUNDUP64(xgn->xgn_len)) {
154 xgn = (struct xgen_n*)next;
155 if (xgn->xgn_len <= sizeof(struct xsystmgen))
156 break;
157
158 if ((which & xgn->xgn_kind) == 0) {
159 which |= xgn->xgn_kind;
160 switch (xgn->xgn_kind) {
161 case XSO_SOCKET:
162 so = (struct xsocket_n *)xgn;
163 break;
164 case XSO_RCVBUF:
165 so_rcv = (struct xsockbuf_n *)xgn;
166 break;
167 case XSO_SNDBUF:
168 so_snd = (struct xsockbuf_n *)xgn;
169 break;
170 case XSO_STATS:
171 so_stat = (struct xsockstat_n *)xgn;
172 break;
173 case XSO_KCREG:
174 kctl = (struct xkctl_reg *)xgn;
175 break;
176 case XSO_KCB:
177 kcb = (struct xkctlpcb *)xgn;
178 break;
179 case XSO_EVT:
180 kevb = (struct xkevtpcb *)xgn;
181 break;
182 default:
183 printf("unexpected kind %d\n", xgn->xgn_kind);
184 break;
185 }
186 } else {
187 if (vflag)
188 printf("got %d twice\n", xgn->xgn_kind);
189 }
190
191 if (which == ALL_XGN_KIND_KCREG) {
192 which = 0;
193
194 if (first) {
195 printf("Registered kernel control modules\n");
196 if (Aflag)
197 printf("%-16.16s ", "kctlref");
198 printf("%-8.8s ", "id");
199 if (Aflag)
200 printf("%-8.8s ", "unit");
201 printf("%-8.8s ", "flags");
202 printf("%-8.8s ", "pcbcount");
203 printf("%-8.8s ", "rcvbuf");
204 printf("%-8.8s ", "sndbuf");
205 printf("%s ", "name");
206 printf("\n");
207 first = 0;
208 }
209 if (Aflag)
210 printf("%16llx ", kctl->xkr_kctlref);
211 printf("%8x ", kctl->xkr_id);
212 if (Aflag)
213 printf("%8d ", kctl->xkr_reg_unit);
214 printf("%8x ", kctl->xkr_flags);
215 printf("%8d ", kctl->xkr_pcbcount);
216 printf("%8d ", kctl->xkr_recvbufsize);
217 printf("%8d ", kctl->xkr_sendbufsize);
218 printf("%s ", kctl->xkr_name);
219 printf("\n");
220 } else if (which == ALL_XGN_KIND_KCB) {
221 which = 0;
222
223 if (first) {
224 printf("Active kernel control sockets\n");
225 if (Aflag)
226 printf("%16.16s ", "pcb");
227 printf("%-5.5s %-6.6s %-6.6s ",
228 "Proto", "Recv-Q", "Send-Q");
229 if (bflag > 0)
230 printf("%10.10s %10.10s ",
231 "rxbytes", "txbytes");
232 if (vflag > 0)
233 printf("%6.6s %6.6s %6.6s %6.6s ",
234 "rhiwat", "shiwat", "pid", "epid");
235 printf("%6.6s ", "unit");
236 printf("%6.6s ", "id");
237 printf("%s", "name");
238 printf("\n");
239 first = 0;
240 }
241 if (Aflag)
242 printf("%16llx ", kcb->xkp_kctpcb);
243 printf("%-5.5s %6u %6u ", name,
244 so_rcv->sb_cc,
245 so_snd->sb_cc);
246 if (bflag > 0) {
247 int i;
248 u_int64_t rxbytes = 0;
249 u_int64_t txbytes = 0;
250
251 for (i = 0; i < SO_TC_STATS_MAX; i++) {
252 rxbytes += so_stat->xst_tc_stats[i].rxbytes;
253 txbytes += so_stat->xst_tc_stats[i].txbytes;
254 }
255 printf("%10llu %10llu ", rxbytes, txbytes);
256 }
257 if (vflag > 0) {
258 printf("%6u %6u %6u %6u ",
259 so_rcv->sb_hiwat,
260 so_snd->sb_hiwat,
261 so->so_last_pid,
262 so->so_e_pid);
263 }
264 printf("%6d ", kcb->xkp_unit);
265 printf("%6d ", kcb->xkp_kctlid);
266 printf("%s", kcb->xkp_kctlname);
267 printf("\n");
268
269 } else if (which == ALL_XGN_KIND_EVT) {
270 which = 0;
271 if (first) {
272 printf("Active kernel event sockets\n");
273 if (Aflag)
274 printf("%16.16s ", "pcb");
275 printf("%-5.5s %-6.6s %-6.6s ",
276 "Proto", "Recv-Q", "Send-Q");
277 printf("%6.6s ", "vendor");
278 printf("%6.6s ", "class");
279 printf("%6.6s", "subclass");
280 if (bflag > 0)
281 printf("%10.10s %10.10s ",
282 "rxbytes", "txbytes");
283 if (vflag > 0)
284 printf("%6.6s %6.6s %6.6s %6.6s",
285 "rhiwat", "shiwat", "pid", "epid");
286 printf("\n");
287 first = 0;
288 }
289 if (Aflag)
290 printf("%16llx ", kevb->kep_evtpcb);
291 printf("%-5.5s %6u %6u ", name,
292 so_rcv->sb_cc,
293 so_snd->sb_cc);
294 printf("%6d ", kevb->kep_vendor_code_filter);
295 printf("%6d ", kevb->kep_class_filter);
296 printf("%6d", kevb->kep_subclass_filter);
297 if (bflag > 0) {
298 int i;
299 u_int64_t rxbytes = 0;
300 u_int64_t txbytes = 0;
301
302 for (i = 0; i < SO_TC_STATS_MAX; i++) {
303 rxbytes += so_stat->xst_tc_stats[i].rxbytes;
304 txbytes += so_stat->xst_tc_stats[i].txbytes;
305 }
306 printf("%10llu %10llu ", rxbytes, txbytes);
307 }
308 if (vflag > 0) {
309 printf("%6u %6u %6u %6u",
310 so_rcv->sb_hiwat,
311 so_snd->sb_hiwat,
312 so->so_last_pid,
313 so->so_e_pid);
314 }
315 printf("\n");
316 }
317
318 }
319 if (xig != oxig && xig->xg_gen != oxig->xg_gen) {
320 if (oxig->xg_count > xig->xg_count) {
321 printf("Some %s sockets may have been deleted.\n",
322 name);
323 } else if (oxig->xg_count < xig->xg_count) {
324 printf("Some %s sockets may have been created.\n",
325 name);
326 } else {
327 printf("Some %s sockets may have been created or deleted",
328 name);
329 }
330 }
331 free(buf);
332 }
333
334 void
335 kctl_stats(uint32_t off __unused, char *name, int af __unused)
336 {
337 static struct kctlstat pkctlstat;
338 struct kctlstat kctlstat;
339 size_t len = sizeof(struct kctlstat);
340 const char *mibvar = "net.systm.kctl.stats";
341
342 if (sysctlbyname(mibvar, &kctlstat, &len, 0, 0) < 0) {
343 warn("sysctl: %s", mibvar);
344 return;
345 }
346 if (interval && vflag > 0)
347 print_time();
348 printf ("%s:\n", name);
349
350 #define STATDIFF(f) (kctlstat.f - pkctlstat.f)
351 #define p(f, m) if (STATDIFF(f) || sflag <= 1) \
352 printf(m, STATDIFF(f), plural(STATDIFF(f)))
353 #define p1a(f, m) if (STATDIFF(f) || sflag <= 1) \
354 printf(m, STATDIFF(f))
355
356 p(kcs_reg_total, "\t%llu total kernel control module%s registered\n");
357 p(kcs_reg_count, "\t%llu current kernel control module%s registered\n");
358 p(kcs_pcbcount, "\t%llu current kernel control socket%s\n");
359 p1a(kcs_gencnt, "\t%llu kernel control generation count\n");
360 p(kcs_connections, "\t%llu connection attempt%s\n");
361 p(kcs_conn_fail, "\t%llu connection failure%s\n");
362 p(kcs_send_fail, "\t%llu send failure%s\n");
363 p(kcs_send_list_fail, "\t%llu send list failure%s\n");
364 p(kcs_enqueue_fail, "\t%llu enqueue failure%s\n");
365 p(kcs_enqueue_fullsock, "\t%llu packet%s dropped due to full socket buffers\n");
366
367 #undef STATDIFF
368 #undef p
369 #undef p1a
370
371 if (interval > 0)
372 bcopy(&kctlstat, &pkctlstat, len);
373 }
374
375 void
376 kevt_stats(uint32_t off __unused, char *name, int af __unused)
377 {
378 static struct kevtstat pkevtstat;
379 struct kevtstat kevtstat;
380 size_t len = sizeof(struct kctlstat);
381 const char *mibvar = "net.systm.kevt.stats";
382
383 if (sysctlbyname(mibvar, &kevtstat, &len, 0, 0) < 0) {
384 warn("sysctl: %s", mibvar);
385 return;
386 }
387 if (interval && vflag > 0)
388 print_time();
389 printf ("%s:\n", name);
390
391 #define STATDIFF(f) (kevtstat.f - pkevtstat.f)
392 #define p(f, m) if (STATDIFF(f) || sflag <= 1) \
393 printf(m, STATDIFF(f), plural(STATDIFF(f)))
394 #define p1a(f, m) if (STATDIFF(f) || sflag <= 1) \
395 printf(m, STATDIFF(f))
396
397 p(kes_pcbcount, "\t%llu current kernel control socket%s\n");
398 p1a(kes_gencnt, "\t%llu kernel control generation count\n");
399 p(kes_badvendor, "\t%llu bad vendor failure%s\n");
400 p(kes_toobig, "\t%llu message too big failure%s\n");
401 p(kes_nomem, "\t%llu out of memory failure%s\n");
402 p(kes_fullsock, "\t%llu message%s dropped due to full socket buffers\n");
403 p(kes_posted, "\t%llu message%s posted\n");
404
405 #undef STATDIFF
406 #undef p
407 #undef p1a
408
409 if (interval > 0)
410 bcopy(&kevtstat, &pkevtstat, len);
411 }
412
413 void
414 print_extbkidle_stats(uint32_t off __unused, char *name, int af __unused)
415 {
416 static struct soextbkidlestat psoextbkidlestat;
417 struct soextbkidlestat soextbkidlestat;
418 size_t len = sizeof(struct soextbkidlestat);
419 const char *mibvar = "kern.ipc.extbkidlestat";
420
421 if (sysctlbyname(mibvar, &soextbkidlestat, &len, 0, 0) < 0) {
422 warn("sysctl: %s", mibvar);
423 return;
424 }
425
426 #define STATDIFF(f) (soextbkidlestat.f - psoextbkidlestat.f)
427 #define p(f, m) if (STATDIFF(f) || sflag <= 1) \
428 printf(m, STATDIFF(f), plural(STATDIFF(f)))
429 #define p1a(f, m) if (STATDIFF(f) || sflag <= 1) \
430 printf(m, STATDIFF(f))
431
432 if (interval && vflag > 0)
433 print_time();
434 printf ("%s:\n", name);
435
436 p1a(so_xbkidle_maxperproc, "\t%u max per process\n");
437 p1a(so_xbkidle_time, "\t%u maximum time (seconds)\n");
438 p1a(so_xbkidle_rcvhiwat, "\t%u high water mark\n");
439 p(so_xbkidle_notsupp, "\t%u socket option not supported failure%s\n");
440 p(so_xbkidle_toomany, "\t%u too many sockets failure%s\n");
441 p(so_xbkidle_wantok, "\t%u total socket%s requested OK\n");
442 p(so_xbkidle_active, "\t%u extended bk idle socket%s\n");
443 p(so_xbkidle_nocell, "\t%u no cellular failure%s\n");
444 p(so_xbkidle_notime, "\t%u no time failures%s\n");
445 p(so_xbkidle_forced, "\t%u forced defunct socket%s\n");
446 p(so_xbkidle_resumed, "\t%u resumed socket%s\n");
447 p(so_xbkidle_expired, "\t%u timeout expired failure%s\n");
448 p1a(so_xbkidle_expired, "\t%u timer rescheduled\n");
449 p(so_xbkidle_nodlgtd, "\t%u no delegated failure%s\n");
450
451 #undef STATDIFF
452 #undef p
453 #undef p1a
454 }
455
456 void
457 print_nstat_stats(uint32_t off __unused, char *name, int af __unused)
458 {
459 static struct nstat_stats pnstat_stats;
460 struct nstat_stats nstat_stats;
461 size_t len = sizeof(struct nstat_stats);
462 const char *mibvar = "net.stats.stats";
463
464 if (sysctlbyname(mibvar, &nstat_stats, &len, 0, 0) < 0) {
465 warn("sysctl: %s", mibvar);
466 return;
467 }
468
469 #define STATDIFF(f) (nstat_stats.f - pnstat_stats.f)
470 #define p(f, m) if (STATDIFF(f) || sflag <= 1) \
471 printf(m, STATDIFF(f), plural(STATDIFF(f)))
472 #define p1a(f, m) if (STATDIFF(f) || sflag <= 1) \
473 printf(m, STATDIFF(f))
474
475 if (interval && vflag > 0)
476 print_time();
477 printf ("%s:\n", name);
478
479 p(nstat_successmsgfailures, "\t%u enqueue success message failure%s\n");
480 p(nstat_sendcountfailures, "\t%u enqueue source counts message failure%s\n");
481 p(nstat_sysinfofailures, "\t%u enqueue sysinfo message failure%s\n");
482 p(nstat_srcupatefailures, "\t%u enqueue source udpate message failure%s\n");
483 p(nstat_descriptionfailures, "\t%u enqueue description message failure%s\n");
484 p(nstat_msgremovedfailures, "\t%u enqueue remove message failure%s\n");
485 p(nstat_srcaddedfailures, "\t%u enqueue source added message failure%s\n");
486 p(nstat_msgerrorfailures, "\t%u enqueue error message failure%s\n");
487 p(nstat_copy_descriptor_failures, "\t%u copy descriptor failure%s\n");
488 p(nstat_provider_counts_failures, "\t%u provider counts failure%s\n");
489 p(nstat_control_send_description_failures, "\t%u control send description failure%s\n");
490 p(nstat_control_send_goodbye_failures, "\t%u control send goodbye failure%s\n");
491 p(nstat_flush_accumulated_msgs_failures, "\t%u flush accumulated messages failure%s\n");
492 p(nstat_accumulate_msg_failures, "\t%u accumulated message failure%s\n");
493 p(nstat_control_cleanup_source_failures, "\t%u control cleanup source failure%s\n");
494 p(nstat_handle_msg_failures, "\t%u handle message failure%s\n");
495
496 #undef STATDIFF
497 #undef p
498 #undef p1a
499 }