More -Wwrite-strings cleanup and make sure you can actually play it.
[dragonfly.git] / usr.bin / netstat / inet.c
blob33ee9a98919e5521fb19e50a4c9b1b6ceab1d0cd
1 /*
2 * Copyright (c) 1983, 1988, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
33 * @(#)inet.c 8.5 (Berkeley) 5/24/95
34 * $FreeBSD: src/usr.bin/netstat/inet.c,v 1.37.2.11 2003/11/27 14:46:49 ru Exp $
35 * $DragonFly: src/usr.bin/netstat/inet.c,v 1.18 2005/04/11 14:51:38 hmp Exp $
38 #include <sys/param.h>
39 #include <sys/queue.h>
40 #include <sys/socket.h>
41 #include <sys/socketvar.h>
42 #include <sys/sysctl.h>
43 #include <sys/protosw.h>
44 #include <sys/time.h>
46 #include <net/route.h>
47 #include <netinet/in.h>
48 #include <netinet/in_systm.h>
49 #include <netinet/ip.h>
50 #ifdef INET6
51 #include <netinet/ip6.h>
52 #endif /* INET6 */
53 #include <netinet/in_pcb.h>
54 #include <netinet/ip_icmp.h>
55 #include <netinet/icmp_var.h>
56 #include <netinet/igmp_var.h>
57 #include <netinet/ip_var.h>
58 #include <netinet/pim_var.h>
59 #include <netinet/tcp.h>
60 #include <netinet/tcpip.h>
61 #include <netinet/tcp_seq.h>
62 #define TCPSTATES
63 #include <netinet/tcp_fsm.h>
64 #include <netinet/tcp_timer.h>
65 #include <netinet/tcp_var.h>
66 #include <netinet/tcp_debug.h>
67 #include <netinet/udp.h>
68 #include <netinet/udp_var.h>
70 #include <arpa/inet.h>
71 #include <err.h>
72 #include <errno.h>
73 #include <libutil.h>
74 #include <netdb.h>
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <string.h>
78 #include <unistd.h>
79 #include "netstat.h"
81 char *inetname (struct in_addr *);
82 void inetprint (struct in_addr *, int, const char *, int);
83 #ifdef INET6
84 extern void inet6print (struct in6_addr *, int, const char *, int);
85 static int udp_done, tcp_done;
86 #endif /* INET6 */
89 * Print a summary of connections related to an Internet
90 * protocol. For TCP, also give state of connection.
91 * Listening processes (aflag) are suppressed unless the
92 * -a (all) flag is specified.
95 static int ppr_first = 1;
96 static void outputpcb(int proto, const char *name, struct inpcb *inp, struct xsocket *so, struct tcpcb *tp);
98 void
99 protopr(u_long proto, char *name, int af)
101 int istcp;
102 int i;
103 void *buf;
104 const char *mibvar;
105 size_t len;
107 istcp = 0;
108 switch (proto) {
109 case IPPROTO_TCP:
110 #ifdef INET6
111 if (tcp_done != 0)
112 return;
113 else
114 tcp_done = 1;
115 #endif
116 istcp = 1;
117 mibvar = "net.inet.tcp.pcblist";
118 break;
119 case IPPROTO_UDP:
120 #ifdef INET6
121 if (udp_done != 0)
122 return;
123 else
124 udp_done = 1;
125 #endif
126 mibvar = "net.inet.udp.pcblist";
127 break;
128 case IPPROTO_DIVERT:
129 mibvar = "net.inet.divert.pcblist";
130 break;
131 default:
132 mibvar = "net.inet.raw.pcblist";
133 break;
135 len = 0;
136 if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
137 if (errno != ENOENT)
138 warn("sysctl: %s", mibvar);
139 return;
141 if (len == 0)
142 return;
143 if ((buf = malloc(len)) == 0) {
144 warn("malloc %lu bytes", (u_long)len);
145 return;
147 if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
148 warn("sysctl: %s", mibvar);
149 free(buf);
150 return;
153 if (istcp) {
154 struct xtcpcb *tcp = buf;
155 len /= sizeof(*tcp);
156 for (i = 0; i < len; i++) {
157 if (tcp[i].xt_len != sizeof(*tcp))
158 break;
159 outputpcb(proto, name, &tcp[i].xt_inp,
160 &tcp[i].xt_socket, &tcp[i].xt_tp);
162 } else {
163 struct xinpcb *in = buf;
164 len /= sizeof(*in);
165 for (i = 0; i < len; i++) {
166 if (in[i].xi_len != sizeof(*in))
167 break;
168 outputpcb(proto, name, &in[i].xi_inp,
169 &in[i].xi_socket, NULL);
172 free(buf);
175 static void
176 outputpcb(int proto, const char *name, struct inpcb *inp, struct xsocket *so, struct tcpcb *tp)
178 const char *vchar;
179 static struct clockinfo clockinfo;
181 if (clockinfo.hz == 0) {
182 int size = sizeof(clockinfo);
183 sysctlbyname("kern.clockrate", &clockinfo, &size, NULL, 0);
184 if (clockinfo.hz == 0)
185 clockinfo.hz = 100;
188 /* Ignore sockets for protocols other than the desired one. */
189 if (so->xso_protocol != (int)proto)
190 return;
192 if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
193 #ifdef INET6
194 || (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
195 #endif /* INET6 */
196 || (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
197 #ifdef INET6
198 && (inp->inp_vflag & INP_IPV6) == 0
199 #endif /* INET6 */
202 return;
204 if (!aflag && (
205 (af == AF_INET && inet_lnaof(inp->inp_laddr) == INADDR_ANY)
206 #ifdef INET6
207 || (af == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
208 #endif /* INET6 */
209 || (af == AF_UNSPEC && (((inp->inp_vflag & INP_IPV4) != 0 &&
210 inet_lnaof(inp->inp_laddr) == INADDR_ANY)
211 #ifdef INET6
212 || ((inp->inp_vflag & INP_IPV6) != 0 &&
213 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
214 #endif
216 )) {
217 return;
220 if (ppr_first) {
221 if (!Lflag) {
222 printf("Active Internet connections");
223 if (aflag)
224 printf(" (including servers)");
225 } else {
226 printf("Current listen queue sizes "
227 "(qlen/incqlen/maxqlen)");
229 putchar('\n');
230 if (Aflag)
231 printf("%-8.8s ", "Socket");
232 if (Pflag)
233 printf("%8.8s %8.8s %8.8s ", "TxWin", "Unacked", "RTT/ms");
234 if (Lflag) {
235 printf("%-5.5s %-14.14s %-22.22s\n",
236 "Proto", "Listen", "Local Address");
237 } else {
238 printf((Aflag && !Wflag) ?
239 "%-5.5s %-6.6s %-6.6s %-17.17s %-17.17s %s\n" :
240 "%-5.5s %-6.6s %-6.6s %-21.21s %-21.21s %s\n",
241 "Proto", "Recv-Q", "Send-Q",
242 "Local Address", "Foreign Address",
243 "(state)");
245 ppr_first = 0;
247 if (Lflag && so->so_qlimit == 0)
248 return;
249 if (Aflag) {
250 if (tp)
251 printf("%8lx ", (u_long)inp->inp_ppcb);
252 else
253 printf("%8lx ", (u_long)so->so_pcb);
255 if (Pflag) {
256 if (tp) {
257 int window = MIN(tp->snd_cwnd, tp->snd_bwnd);
258 if (window == 1073725440)
259 printf("%8s ", "max");
260 else
261 printf("%8d ", (int)MIN(tp->snd_cwnd, tp->snd_bwnd));
262 printf("%8d ", (int)(tp->snd_max - tp->snd_una));
263 if (tp->t_srtt == 0)
264 printf("%8s ", "-");
265 else
266 printf("%8.3f ", (double)tp->t_srtt * 1000.0 / TCP_RTT_SCALE / clockinfo.hz);
267 } else {
268 printf("%8s %8s %8s ", "-", "-", "-");
271 #ifdef INET6
272 if ((inp->inp_vflag & INP_IPV6) != 0)
273 vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "46" : "6 ";
274 else
275 #endif
276 vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "4 " : " ";
278 printf("%-3.3s%-2.2s ", name, vchar);
279 if (Lflag) {
280 char buf[15];
282 snprintf(buf, sizeof(buf), "%d/%d/%d", so->so_qlen,
283 so->so_incqlen, so->so_qlimit);
284 printf("%-13.13s ", buf);
285 } else if (Bflag) {
286 printf("%6ld %6ld ",
287 so->so_rcv.sb_hiwat,
288 so->so_snd.sb_hiwat);
289 } else {
290 printf("%6ld %6ld ",
291 so->so_rcv.sb_cc,
292 so->so_snd.sb_cc);
294 if (numeric_port) {
295 if (inp->inp_vflag & INP_IPV4) {
296 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
297 name, 1);
298 if (!Lflag)
299 inetprint(&inp->inp_faddr,
300 (int)inp->inp_fport, name, 1);
302 #ifdef INET6
303 else if (inp->inp_vflag & INP_IPV6) {
304 inet6print(&inp->in6p_laddr,
305 (int)inp->inp_lport, name, 1);
306 if (!Lflag)
307 inet6print(&inp->in6p_faddr,
308 (int)inp->inp_fport, name, 1);
309 } /* else nothing printed now */
310 #endif /* INET6 */
311 } else if (inp->inp_flags & INP_ANONPORT) {
312 if (inp->inp_vflag & INP_IPV4) {
313 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
314 name, 1);
315 if (!Lflag)
316 inetprint(&inp->inp_faddr,
317 (int)inp->inp_fport, name, 0);
319 #ifdef INET6
320 else if (inp->inp_vflag & INP_IPV6) {
321 inet6print(&inp->in6p_laddr,
322 (int)inp->inp_lport, name, 1);
323 if (!Lflag)
324 inet6print(&inp->in6p_faddr,
325 (int)inp->inp_fport, name, 0);
326 } /* else nothing printed now */
327 #endif /* INET6 */
328 } else {
329 if (inp->inp_vflag & INP_IPV4) {
330 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
331 name, 0);
332 if (!Lflag)
333 inetprint(&inp->inp_faddr,
334 (int)inp->inp_fport, name,
335 inp->inp_lport !=
336 inp->inp_fport);
338 #ifdef INET6
339 else if (inp->inp_vflag & INP_IPV6) {
340 inet6print(&inp->in6p_laddr,
341 (int)inp->inp_lport, name, 0);
342 if (!Lflag)
343 inet6print(&inp->in6p_faddr,
344 (int)inp->inp_fport, name,
345 inp->inp_lport !=
346 inp->inp_fport);
347 } /* else nothing printed now */
348 #endif /* INET6 */
350 if (tp && !Lflag) {
351 if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
352 printf("%d", tp->t_state);
353 else {
354 printf("%s", tcpstates[tp->t_state]);
355 #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
356 /* Show T/TCP `hidden state' */
357 if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
358 putchar('*');
359 #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
362 putchar('\n');
367 #define CPU_STATS_FUNC(proto,type) \
368 static void \
369 proto ##_stats_agg(type *ary, type *ttl, int cpucnt) \
371 int i, off, siz; \
372 siz = sizeof(type); \
374 if (!ary && !ttl) \
375 return; \
377 bzero(ttl, siz); \
378 if (cpucnt == 1) { \
379 *ttl = ary[0]; \
380 } else { \
381 for (i = 0; i < cpucnt; ++i) { \
382 for (off = 0; off < siz; off += sizeof(u_long)) { \
383 *(u_long *)((char *)(*(&ttl)) + off) += \
384 *(u_long *)((char *)&ary[i] + off); \
389 CPU_STATS_FUNC(tcp, struct tcp_stats);
390 CPU_STATS_FUNC(ip, struct ip_stats);
393 * Dump TCP statistics structure.
395 void
396 tcp_stats(u_long off __unused, char *name, int af __unused)
398 struct tcp_stats tcpstat, *stattmp;
399 struct tcp_stats zerostat[SMP_MAXCPU];
400 size_t len = sizeof(struct tcp_stats) * SMP_MAXCPU;
401 int cpucnt;
403 if (zflag)
404 memset(zerostat, 0, len);
406 if ((stattmp = malloc(len)) == NULL) {
407 return;
408 } else {
409 if (sysctlbyname("net.inet.tcp.stats", stattmp, &len,
410 zflag ? zerostat : NULL, zflag ? len : 0) < 0) {
411 warn("sysctl: net.inet.tcp.stats");
412 free(stattmp);
413 return;
414 } else {
415 if ((stattmp = realloc(stattmp, len)) == NULL) {
416 warn("tcp_stats");
417 return;
421 cpucnt = len / sizeof(struct tcp_stats);
422 tcp_stats_agg(stattmp, &tcpstat, cpucnt);
424 #ifdef INET6
425 if (tcp_done != 0)
426 return;
427 else
428 tcp_done = 1;
429 #endif
431 printf ("%s:\n", name);
433 #define p(f, m) if (tcpstat.f || sflag <= 1) \
434 printf(m, tcpstat.f, plural(tcpstat.f))
435 #define p1a(f, m) if (tcpstat.f || sflag <= 1) \
436 printf(m, tcpstat.f)
437 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
438 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
439 #define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
440 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
441 #define p3(f, m) if (tcpstat.f || sflag <= 1) \
442 printf(m, tcpstat.f, plurales(tcpstat.f))
444 p(tcps_sndtotal, "\t%lu packet%s sent\n");
445 p2(tcps_sndpack,tcps_sndbyte,
446 "\t\t%lu data packet%s (%lu byte%s)\n");
447 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
448 "\t\t%lu data packet%s (%lu byte%s) retransmitted\n");
449 p2a(tcps_sndfastrexmit, tcps_sndearlyrexmit,
450 "\t\t%lu Fast Retransmit%s (%lu early)\n");
451 p(tcps_sndlimited, "\t\t%lu packet%s sent by Limited Transmit\n");
452 p(tcps_sndrtobad, "\t\t%lu spurious RTO retransmit%s\n");
453 p2a(tcps_sndfastrexmitbad, tcps_sndearlyrexmitbad,
454 "\t\t%lu spurious Fast Retransmit%s (%lu early)\n");
455 p(tcps_eifeldetected, "\t\t%lu Eifel-detected spurious retransmit%s\n");
456 p(tcps_rttdetected, "\t\t%lu RTT-detected spurious retransmit%s\n");
457 p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n");
458 p2a(tcps_sndacks, tcps_delack,
459 "\t\t%lu ack-only packet%s (%lu delayed)\n");
460 p(tcps_sndurg, "\t\t%lu URG only packet%s\n");
461 p(tcps_sndprobe, "\t\t%lu window probe packet%s\n");
462 p(tcps_sndwinup, "\t\t%lu window update packet%s\n");
463 p(tcps_sndctrl, "\t\t%lu control packet%s\n");
464 p(tcps_rcvtotal, "\t%lu packet%s received\n");
465 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n");
466 p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n");
467 p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n");
468 p2(tcps_rcvpack, tcps_rcvbyte,
469 "\t\t%lu packet%s (%lu byte%s) received in-sequence\n");
470 p2(tcps_rcvduppack, tcps_rcvdupbyte,
471 "\t\t%lu completely duplicate packet%s (%lu byte%s)\n");
472 p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n");
473 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
474 "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n");
475 p2(tcps_rcvoopack, tcps_rcvoobyte,
476 "\t\t%lu out-of-order packet%s (%lu byte%s)\n");
477 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
478 "\t\t%lu packet%s (%lu byte%s) of data after window\n");
479 p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n");
480 p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n");
481 p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n");
482 p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n");
483 p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n");
484 p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n");
485 p(tcps_connattempt, "\t%lu connection request%s\n");
486 p(tcps_accepts, "\t%lu connection accept%s\n");
487 p(tcps_badsyn, "\t%lu bad connection attempt%s\n");
488 p(tcps_listendrop, "\t%lu listen queue overflow%s\n");
489 p(tcps_connects, "\t%lu connection%s established (including accepts)\n");
490 p2(tcps_closed, tcps_drops,
491 "\t%lu connection%s closed (including %lu drop%s)\n");
492 p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n");
493 p(tcps_cachedrttvar,
494 "\t\t%lu connection%s updated cached RTT variance on close\n");
495 p(tcps_cachedssthresh,
496 "\t\t%lu connection%s updated cached ssthresh on close\n");
497 p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n");
498 p2(tcps_rttupdated, tcps_segstimed,
499 "\t%lu segment%s updated rtt (of %lu attempt%s)\n");
500 p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n");
501 p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n");
502 p(tcps_persisttimeo, "\t%lu persist timeout%s\n");
503 p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n");
504 p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n");
505 p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n");
506 p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n");
507 p(tcps_predack, "\t%lu correct ACK header prediction%s\n");
508 p(tcps_preddat, "\t%lu correct data packet header prediction%s\n");
510 p1a(tcps_sc_added, "\t%lu syncache entries added\n");
511 p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n");
512 p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n");
513 p1a(tcps_sc_dropped, "\t\t%lu dropped\n");
514 p1a(tcps_sc_completed, "\t\t%lu completed\n");
515 p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n");
516 p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n");
517 p1a(tcps_sc_reset, "\t\t%lu reset\n");
518 p1a(tcps_sc_stale, "\t\t%lu stale\n");
519 p1a(tcps_sc_aborted, "\t\t%lu aborted\n");
520 p1a(tcps_sc_badack, "\t\t%lu badack\n");
521 p1a(tcps_sc_unreach, "\t\t%lu unreach\n");
522 p1a(tcps_sc_zonefail, "\t\t%lu zone failures\n");
523 p1a(tcps_sc_sendcookie, "\t%lu cookies sent\n");
524 p1a(tcps_sc_recvcookie, "\t%lu cookies received\n");
525 free(stattmp);
526 #undef p
527 #undef p1a
528 #undef p2
529 #undef p2a
530 #undef p3
534 * Dump UDP statistics structure.
536 void
537 udp_stats(u_long off __unused, char *name, int af __unused)
539 struct udpstat udpstat, zerostat;
540 size_t len = sizeof udpstat;
541 u_long delivered;
543 if (zflag)
544 memset(&zerostat, 0, len);
545 if (sysctlbyname("net.inet.udp.stats", &udpstat, &len,
546 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
547 warn("sysctl: net.inet.udp.stats");
548 return;
551 #ifdef INET6
552 if (udp_done != 0)
553 return;
554 else
555 udp_done = 1;
556 #endif
558 printf("%s:\n", name);
559 #define p(f, m) if (udpstat.f || sflag <= 1) \
560 printf(m, udpstat.f, plural(udpstat.f))
561 #define p1a(f, m) if (udpstat.f || sflag <= 1) \
562 printf(m, udpstat.f)
563 p(udps_ipackets, "\t%lu datagram%s received\n");
564 p1a(udps_hdrops, "\t%lu with incomplete header\n");
565 p1a(udps_badlen, "\t%lu with bad data length field\n");
566 p1a(udps_badsum, "\t%lu with bad checksum\n");
567 p1a(udps_nosum, "\t%lu with no checksum\n");
568 p1a(udps_noport, "\t%lu dropped due to no socket\n");
569 p(udps_noportbcast,
570 "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
571 p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
572 p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n");
573 delivered = udpstat.udps_ipackets -
574 udpstat.udps_hdrops -
575 udpstat.udps_badlen -
576 udpstat.udps_badsum -
577 udpstat.udps_noport -
578 udpstat.udps_noportbcast -
579 udpstat.udps_fullsock;
580 if (delivered || sflag <= 1)
581 printf("\t%lu delivered\n", delivered);
582 p(udps_opackets, "\t%lu datagram%s output\n");
583 #undef p
584 #undef p1a
588 * Dump IP statistics structure.
590 void
591 ip_stats(u_long off __unused, char *name, int af __unused)
593 struct ip_stats ipstat, *stattmp;
594 struct ip_stats zerostat[SMP_MAXCPU];
595 size_t len = sizeof(struct ip_stats) * SMP_MAXCPU;
596 int cpucnt;
598 if (zflag)
599 memset(zerostat, 0, len);
600 if ((stattmp = malloc(len)) == NULL) {
601 return;
602 } else {
603 if (sysctlbyname("net.inet.ip.stats", stattmp, &len,
604 zflag ? zerostat : NULL, zflag ? len : 0) < 0) {
605 warn("sysctl: net.inet.ip.stats");
606 free(stattmp);
607 return;
608 } else {
609 if ((stattmp = realloc(stattmp, len)) == NULL) {
610 warn("ip_stats");
611 return;
615 cpucnt = len / sizeof(struct ip_stats);
616 ip_stats_agg(stattmp, &ipstat, cpucnt);
618 printf("%s:\n", name);
620 #define p(f, m) if (ipstat.f || sflag <= 1) \
621 printf(m, ipstat.f, plural(ipstat.f))
622 #define p1a(f, m) if (ipstat.f || sflag <= 1) \
623 printf(m, ipstat.f)
625 p(ips_total, "\t%lu total packet%s received\n");
626 p(ips_badsum, "\t%lu bad header checksum%s\n");
627 p1a(ips_toosmall, "\t%lu with size smaller than minimum\n");
628 p1a(ips_tooshort, "\t%lu with data size < data length\n");
629 p1a(ips_toolong, "\t%lu with ip length > max ip packet size\n");
630 p1a(ips_badhlen, "\t%lu with header length < data size\n");
631 p1a(ips_badlen, "\t%lu with data length < header length\n");
632 p1a(ips_badoptions, "\t%lu with bad options\n");
633 p1a(ips_badvers, "\t%lu with incorrect version number\n");
634 p(ips_fragments, "\t%lu fragment%s received\n");
635 p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
636 p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
637 p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
638 p(ips_delivered, "\t%lu packet%s for this host\n");
639 p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
640 p(ips_forward, "\t%lu packet%s forwarded");
641 p(ips_fastforward, " (%lu packet%s fast forwarded)");
642 if (ipstat.ips_forward || sflag <= 1)
643 putchar('\n');
644 p(ips_cantforward, "\t%lu packet%s not forwardable\n");
645 p(ips_notmember,
646 "\t%lu packet%s received for unknown multicast group\n");
647 p(ips_redirectsent, "\t%lu redirect%s sent\n");
648 p(ips_localout, "\t%lu packet%s sent from this host\n");
649 p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
650 p(ips_odropped,
651 "\t%lu output packet%s dropped due to no bufs, etc.\n");
652 p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
653 p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
654 p(ips_ofragments, "\t%lu fragment%s created\n");
655 p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
656 p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n");
657 p(ips_badaddr, "\t%lu datagram%s with bad address in header\n");
658 free(stattmp);
659 #undef p
660 #undef p1a
663 static char *icmpnames[] = {
664 "echo reply",
665 "#1",
666 "#2",
667 "destination unreachable",
668 "source quench",
669 "routing redirect",
670 "#6",
671 "#7",
672 "echo",
673 "router advertisement",
674 "router solicitation",
675 "time exceeded",
676 "parameter problem",
677 "time stamp",
678 "time stamp reply",
679 "information request",
680 "information request reply",
681 "address mask request",
682 "address mask reply",
686 * Dump ICMP statistics.
688 void
689 icmp_stats(u_long off __unused, char *name, int af __unused)
691 struct icmpstat icmpstat, zerostat;
692 int i, first;
693 int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */
694 size_t len;
696 mib[0] = CTL_NET;
697 mib[1] = PF_INET;
698 mib[2] = IPPROTO_ICMP;
699 mib[3] = ICMPCTL_STATS;
701 len = sizeof icmpstat;
702 if (zflag)
703 memset(&zerostat, 0, len);
704 if (sysctl(mib, 4, &icmpstat, &len,
705 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
706 warn("sysctl: net.inet.icmp.stats");
707 return;
710 printf("%s:\n", name);
712 #define p(f, m) if (icmpstat.f || sflag <= 1) \
713 printf(m, icmpstat.f, plural(icmpstat.f))
714 #define p1a(f, m) if (icmpstat.f || sflag <= 1) \
715 printf(m, icmpstat.f)
716 #define p2(f, m) if (icmpstat.f || sflag <= 1) \
717 printf(m, icmpstat.f, plurales(icmpstat.f))
719 p(icps_error, "\t%lu call%s to icmp_error\n");
720 p(icps_oldicmp,
721 "\t%lu error%s not generated 'cuz old message was icmp\n");
722 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
723 if (icmpstat.icps_outhist[i] != 0) {
724 if (first) {
725 printf("\tOutput histogram:\n");
726 first = 0;
728 printf("\t\t%s: %lu\n", icmpnames[i],
729 icmpstat.icps_outhist[i]);
731 p(icps_badcode, "\t%lu message%s with bad code fields\n");
732 p(icps_tooshort, "\t%lu message%s < minimum length\n");
733 p(icps_checksum, "\t%lu bad checksum%s\n");
734 p(icps_badlen, "\t%lu message%s with bad length\n");
735 p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n");
736 p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n");
737 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
738 if (icmpstat.icps_inhist[i] != 0) {
739 if (first) {
740 printf("\tInput histogram:\n");
741 first = 0;
743 printf("\t\t%s: %lu\n", icmpnames[i],
744 icmpstat.icps_inhist[i]);
746 p(icps_reflect, "\t%lu message response%s generated\n");
747 p2(icps_badaddr, "\t%lu invalid return address%s\n");
748 p(icps_noroute, "\t%lu no return route%s\n");
749 #undef p
750 #undef p1a
751 #undef p2
752 mib[3] = ICMPCTL_MASKREPL;
753 len = sizeof i;
754 if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0)
755 return;
756 printf("\tICMP address mask responses are %sabled\n",
757 i ? "en" : "dis");
761 * Dump IGMP statistics structure.
763 void
764 igmp_stats(u_long off __unused, char *name, int af __unused)
766 struct igmpstat igmpstat, zerostat;
767 size_t len = sizeof igmpstat;
769 if (zflag)
770 memset(&zerostat, 0, len);
771 if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len,
772 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
773 warn("sysctl: net.inet.igmp.stats");
774 return;
777 printf("%s:\n", name);
779 #define p(f, m) if (igmpstat.f || sflag <= 1) \
780 printf(m, igmpstat.f, plural(igmpstat.f))
781 #define py(f, m) if (igmpstat.f || sflag <= 1) \
782 printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
783 p(igps_rcv_total, "\t%u message%s received\n");
784 p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
785 p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
786 py(igps_rcv_queries, "\t%u membership quer%s received\n");
787 py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
788 p(igps_rcv_reports, "\t%u membership report%s received\n");
789 p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
790 p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
791 p(igps_snd_reports, "\t%u membership report%s sent\n");
792 #undef p
793 #undef py
797 * Dump PIM statistics structure.
799 void
800 pim_stats(u_long off __unused, char *name, int af1 __unused)
802 struct pimstat pimstat, zerostat;
803 size_t len = sizeof pimstat;
805 if (zflag)
806 memset(&zerostat, 0, len);
807 if (sysctlbyname("net.inet.pim.stats", &pimstat, &len,
808 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
809 if (errno != ENOENT)
810 warn("sysctl: net.inet.pim.stats");
811 return;
814 printf("%s:\n", name);
816 #define p(f, m) if (pimstat.f || sflag <= 1) \
817 printf(m, pimstat.f, plural(pimstat.f))
818 #define py(f, m) if (pimstat.f || sflag <= 1) \
819 printf(m, pimstat.f, pimstat.f != 1 ? "ies" : "y")
820 p(pims_rcv_total_msgs, "\t%llu message%s received\n");
821 p(pims_rcv_total_bytes, "\t%llu byte%s received\n");
822 p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
823 p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n");
824 p(pims_rcv_badversion, "\t%llu message%s received with bad version\n");
825 p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n");
826 p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n");
827 p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n");
828 p(pims_rcv_badregisters, "\t%llu bad register%s received\n");
829 p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n");
830 p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n");
831 #undef p
832 #undef py
836 * Pretty print an Internet address (net address + port).
838 void
839 inetprint(struct in_addr *in, int port, const char *proto, int numeric_port)
841 struct servent *sp = 0;
842 char line[80], *cp;
843 int width;
845 if (Wflag)
846 sprintf(line, "%s.", inetname(in));
847 else
848 sprintf(line, "%.*s.", (Aflag && !numeric_port) ? 12 : 16, inetname(in));
849 cp = strchr(line, '\0');
850 if (!numeric_port && port)
851 sp = getservbyport((int)port, proto);
852 if (sp || port == 0)
853 sprintf(cp, "%.15s ", sp ? sp->s_name : "*");
854 else
855 sprintf(cp, "%d ", ntohs((u_short)port));
856 width = (Aflag && !Wflag) ? 17 : 21;
857 if (Wflag)
858 printf("%-*s ", width, line);
859 else
860 printf("%-*.*s ", width, width, line);
864 * Construct an Internet address representation.
865 * If numeric_addr has been supplied, give
866 * numeric value, otherwise try for symbolic name.
868 char *
869 inetname(struct in_addr *inp)
871 register char *cp;
872 static char line[MAXHOSTNAMELEN];
873 struct hostent *hp;
874 struct netent *np;
876 cp = 0;
877 if (!numeric_addr && inp->s_addr != INADDR_ANY) {
878 int net = inet_netof(*inp);
879 int lna = inet_lnaof(*inp);
881 if (lna == INADDR_ANY) {
882 np = getnetbyaddr(net, AF_INET);
883 if (np)
884 cp = np->n_name;
886 if (cp == 0) {
887 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
888 if (hp) {
889 cp = hp->h_name;
890 trimdomain(cp, strlen(cp));
894 if (inp->s_addr == INADDR_ANY)
895 strcpy(line, "*");
896 else if (cp) {
897 strncpy(line, cp, sizeof(line) - 1);
898 line[sizeof(line) - 1] = '\0';
899 } else {
900 inp->s_addr = ntohl(inp->s_addr);
901 #define C(x) ((u_int)((x) & 0xff))
902 sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
903 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
905 return (line);