Add reference to the LWP "counterpart".
[dragonfly.git] / usr.bin / netstat / inet.c
blobd3dd8ddc9c7b3e1ab755cbbaa47a8cfe9786ef77
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.20 2007/08/16 20:03:58 dillon 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 #include <netinet/ip_carp.h>
51 #ifdef INET6
52 #include <netinet/ip6.h>
53 #endif /* INET6 */
54 #include <netinet/in_pcb.h>
55 #include <netinet/ip_icmp.h>
56 #include <netinet/icmp_var.h>
57 #include <netinet/igmp_var.h>
58 #include <netinet/ip_var.h>
59 #include <netinet/pim_var.h>
60 #include <netinet/tcp.h>
61 #include <netinet/tcpip.h>
62 #include <netinet/tcp_seq.h>
63 #define TCPSTATES
64 #include <netinet/tcp_fsm.h>
65 #include <netinet/tcp_timer.h>
66 #include <netinet/tcp_var.h>
67 #include <netinet/tcp_debug.h>
68 #include <netinet/udp.h>
69 #include <netinet/udp_var.h>
71 #include <arpa/inet.h>
72 #include <err.h>
73 #include <errno.h>
74 #include <libutil.h>
75 #include <netdb.h>
76 #include <stdio.h>
77 #include <stdlib.h>
78 #include <string.h>
79 #include <unistd.h>
80 #include "netstat.h"
82 char *inetname (struct in_addr *);
83 void inetprint (struct in_addr *, int, const char *, int);
84 #ifdef INET6
85 extern void inet6print (struct in6_addr *, int, const char *, int);
86 static int udp_done, tcp_done;
87 #endif /* INET6 */
90 * Print a summary of connections related to an Internet
91 * protocol. For TCP, also give state of connection.
92 * Listening processes (aflag) are suppressed unless the
93 * -a (all) flag is specified.
96 static int ppr_first = 1;
97 static void outputpcb(int proto, const char *name, struct inpcb *inp, struct xsocket *so, struct tcpcb *tp);
99 void
100 protopr(u_long proto, char *name, int af)
102 int istcp;
103 int i;
104 void *buf;
105 const char *mibvar;
106 size_t len;
108 istcp = 0;
109 switch (proto) {
110 case IPPROTO_TCP:
111 #ifdef INET6
112 if (tcp_done != 0)
113 return;
114 else
115 tcp_done = 1;
116 #endif
117 istcp = 1;
118 mibvar = "net.inet.tcp.pcblist";
119 break;
120 case IPPROTO_UDP:
121 #ifdef INET6
122 if (udp_done != 0)
123 return;
124 else
125 udp_done = 1;
126 #endif
127 mibvar = "net.inet.udp.pcblist";
128 break;
129 case IPPROTO_DIVERT:
130 mibvar = "net.inet.divert.pcblist";
131 break;
132 default:
133 mibvar = "net.inet.raw.pcblist";
134 break;
136 len = 0;
137 if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
138 if (errno != ENOENT)
139 warn("sysctl: %s", mibvar);
140 return;
142 if (len == 0)
143 return;
144 if ((buf = malloc(len)) == 0) {
145 warn("malloc %lu bytes", (u_long)len);
146 return;
148 if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
149 warn("sysctl: %s", mibvar);
150 free(buf);
151 return;
154 if (istcp) {
155 struct xtcpcb *tcp = buf;
156 len /= sizeof(*tcp);
157 for (i = 0; i < len; i++) {
158 if (tcp[i].xt_len != sizeof(*tcp))
159 break;
160 outputpcb(proto, name, &tcp[i].xt_inp,
161 &tcp[i].xt_socket, &tcp[i].xt_tp);
163 } else {
164 struct xinpcb *in = buf;
165 len /= sizeof(*in);
166 for (i = 0; i < len; i++) {
167 if (in[i].xi_len != sizeof(*in))
168 break;
169 outputpcb(proto, name, &in[i].xi_inp,
170 &in[i].xi_socket, NULL);
173 free(buf);
176 static void
177 outputpcb(int proto, const char *name, struct inpcb *inp, struct xsocket *so, struct tcpcb *tp)
179 const char *vchar;
180 static struct clockinfo clockinfo;
182 if (clockinfo.hz == 0) {
183 int size = sizeof(clockinfo);
184 sysctlbyname("kern.clockrate", &clockinfo, &size, NULL, 0);
185 if (clockinfo.hz == 0)
186 clockinfo.hz = 100;
189 /* Ignore sockets for protocols other than the desired one. */
190 if (so->xso_protocol != (int)proto)
191 return;
193 if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
194 #ifdef INET6
195 || (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
196 #endif /* INET6 */
197 || (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
198 #ifdef INET6
199 && (inp->inp_vflag & INP_IPV6) == 0
200 #endif /* INET6 */
203 return;
205 if (!aflag && (
206 (af == AF_INET && inet_lnaof(inp->inp_laddr) == INADDR_ANY)
207 #ifdef INET6
208 || (af == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
209 #endif /* INET6 */
210 || (af == AF_UNSPEC && (((inp->inp_vflag & INP_IPV4) != 0 &&
211 inet_lnaof(inp->inp_laddr) == INADDR_ANY)
212 #ifdef INET6
213 || ((inp->inp_vflag & INP_IPV6) != 0 &&
214 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
215 #endif
217 )) {
218 return;
221 if (ppr_first) {
222 if (!Lflag) {
223 printf("Active Internet connections");
224 if (aflag)
225 printf(" (including servers)");
226 } else {
227 printf("Current listen queue sizes "
228 "(qlen/incqlen/maxqlen)");
230 putchar('\n');
231 if (Aflag)
232 printf("%-8.8s ", "Socket");
233 if (Pflag)
234 printf("%8.8s %8.8s %8.8s ", "TxWin", "Unacked", "RTT/ms");
235 if (Lflag) {
236 printf("%-5.5s %-14.14s %-22.22s\n",
237 "Proto", "Listen", "Local Address");
238 } else {
239 printf((Aflag && !Wflag) ?
240 "%-5.5s %-6.6s %-6.6s %-17.17s %-17.17s %s\n" :
241 "%-5.5s %-6.6s %-6.6s %-21.21s %-21.21s %s\n",
242 "Proto", "Recv-Q", "Send-Q",
243 "Local Address", "Foreign Address",
244 "(state)");
246 ppr_first = 0;
248 if (Lflag && so->so_qlimit == 0)
249 return;
250 if (Aflag) {
251 if (tp)
252 printf("%8lx ", (u_long)inp->inp_ppcb);
253 else
254 printf("%8lx ", (u_long)so->so_pcb);
256 if (Pflag) {
257 if (tp) {
258 int window = MIN(tp->snd_cwnd, tp->snd_bwnd);
259 if (window == 1073725440)
260 printf("%8s ", "max");
261 else
262 printf("%8d ", (int)MIN(tp->snd_cwnd, tp->snd_bwnd));
263 printf("%8d ", (int)(tp->snd_max - tp->snd_una));
264 if (tp->t_srtt == 0)
265 printf("%8s ", "-");
266 else
267 printf("%8.3f ", (double)tp->t_srtt * 1000.0 / TCP_RTT_SCALE / clockinfo.hz);
268 } else {
269 printf("%8s %8s %8s ", "-", "-", "-");
272 #ifdef INET6
273 if ((inp->inp_vflag & INP_IPV6) != 0)
274 vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "46" : "6 ";
275 else
276 #endif
277 vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "4 " : " ";
279 printf("%-3.3s%-2.2s ", name, vchar);
280 if (Lflag) {
281 char buf[15];
283 snprintf(buf, sizeof(buf), "%d/%d/%d", so->so_qlen,
284 so->so_incqlen, so->so_qlimit);
285 printf("%-13.13s ", buf);
286 } else if (Bflag) {
287 printf("%6ld %6ld ",
288 so->so_rcv.sb_hiwat,
289 so->so_snd.sb_hiwat);
290 } else {
291 printf("%6ld %6ld ",
292 so->so_rcv.sb_cc,
293 so->so_snd.sb_cc);
295 if (numeric_port) {
296 if (inp->inp_vflag & INP_IPV4) {
297 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
298 name, 1);
299 if (!Lflag)
300 inetprint(&inp->inp_faddr,
301 (int)inp->inp_fport, name, 1);
303 #ifdef INET6
304 else if (inp->inp_vflag & INP_IPV6) {
305 inet6print(&inp->in6p_laddr,
306 (int)inp->inp_lport, name, 1);
307 if (!Lflag)
308 inet6print(&inp->in6p_faddr,
309 (int)inp->inp_fport, name, 1);
310 } /* else nothing printed now */
311 #endif /* INET6 */
312 } else if (inp->inp_flags & INP_ANONPORT) {
313 if (inp->inp_vflag & INP_IPV4) {
314 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
315 name, 1);
316 if (!Lflag)
317 inetprint(&inp->inp_faddr,
318 (int)inp->inp_fport, name, 0);
320 #ifdef INET6
321 else if (inp->inp_vflag & INP_IPV6) {
322 inet6print(&inp->in6p_laddr,
323 (int)inp->inp_lport, name, 1);
324 if (!Lflag)
325 inet6print(&inp->in6p_faddr,
326 (int)inp->inp_fport, name, 0);
327 } /* else nothing printed now */
328 #endif /* INET6 */
329 } else {
330 if (inp->inp_vflag & INP_IPV4) {
331 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
332 name, 0);
333 if (!Lflag)
334 inetprint(&inp->inp_faddr,
335 (int)inp->inp_fport, name,
336 inp->inp_lport !=
337 inp->inp_fport);
339 #ifdef INET6
340 else if (inp->inp_vflag & INP_IPV6) {
341 inet6print(&inp->in6p_laddr,
342 (int)inp->inp_lport, name, 0);
343 if (!Lflag)
344 inet6print(&inp->in6p_faddr,
345 (int)inp->inp_fport, name,
346 inp->inp_lport !=
347 inp->inp_fport);
348 } /* else nothing printed now */
349 #endif /* INET6 */
351 if (tp && !Lflag) {
352 if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
353 printf("%d", tp->t_state);
354 else {
355 printf("%s", tcpstates[tp->t_state]);
356 #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
357 /* Show T/TCP `hidden state' */
358 if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
359 putchar('*');
360 #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
363 putchar('\n');
368 #define CPU_STATS_FUNC(proto,type) \
369 static void \
370 proto ##_stats_agg(type *ary, type *ttl, int cpucnt) \
372 int i, off, siz; \
373 siz = sizeof(type); \
375 if (!ary && !ttl) \
376 return; \
378 bzero(ttl, siz); \
379 if (cpucnt == 1) { \
380 *ttl = ary[0]; \
381 } else { \
382 for (i = 0; i < cpucnt; ++i) { \
383 for (off = 0; off < siz; off += sizeof(u_long)) { \
384 *(u_long *)((char *)(*(&ttl)) + off) += \
385 *(u_long *)((char *)&ary[i] + off); \
390 CPU_STATS_FUNC(tcp, struct tcp_stats);
391 CPU_STATS_FUNC(ip, struct ip_stats);
394 * Dump TCP statistics structure.
396 void
397 tcp_stats(u_long off __unused, char *name, int af __unused)
399 struct tcp_stats tcpstat, *stattmp;
400 struct tcp_stats zerostat[SMP_MAXCPU];
401 size_t len = sizeof(struct tcp_stats) * SMP_MAXCPU;
402 int cpucnt;
404 if (zflag)
405 memset(zerostat, 0, len);
407 if ((stattmp = malloc(len)) == NULL) {
408 return;
409 } else {
410 if (sysctlbyname("net.inet.tcp.stats", stattmp, &len,
411 zflag ? zerostat : NULL, zflag ? len : 0) < 0) {
412 warn("sysctl: net.inet.tcp.stats");
413 free(stattmp);
414 return;
415 } else {
416 if ((stattmp = realloc(stattmp, len)) == NULL) {
417 warn("tcp_stats");
418 return;
422 cpucnt = len / sizeof(struct tcp_stats);
423 tcp_stats_agg(stattmp, &tcpstat, cpucnt);
425 #ifdef INET6
426 if (tcp_done != 0)
427 return;
428 else
429 tcp_done = 1;
430 #endif
432 printf ("%s:\n", name);
434 #define p(f, m) if (tcpstat.f || sflag <= 1) \
435 printf(m, tcpstat.f, plural(tcpstat.f))
436 #define p1a(f, m) if (tcpstat.f || sflag <= 1) \
437 printf(m, tcpstat.f)
438 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
439 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
440 #define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
441 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
442 #define p3(f, m) if (tcpstat.f || sflag <= 1) \
443 printf(m, tcpstat.f, plurales(tcpstat.f))
445 p(tcps_sndtotal, "\t%lu packet%s sent\n");
446 p2(tcps_sndpack,tcps_sndbyte,
447 "\t\t%lu data packet%s (%lu byte%s)\n");
448 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
449 "\t\t%lu data packet%s (%lu byte%s) retransmitted\n");
450 p2a(tcps_sndfastrexmit, tcps_sndearlyrexmit,
451 "\t\t%lu Fast Retransmit%s (%lu early)\n");
452 p(tcps_sndlimited, "\t\t%lu packet%s sent by Limited Transmit\n");
453 p(tcps_sndrtobad, "\t\t%lu spurious RTO retransmit%s\n");
454 p2a(tcps_sndfastrexmitbad, tcps_sndearlyrexmitbad,
455 "\t\t%lu spurious Fast Retransmit%s (%lu early)\n");
456 p(tcps_eifeldetected, "\t\t%lu Eifel-detected spurious retransmit%s\n");
457 p(tcps_rttdetected, "\t\t%lu RTT-detected spurious retransmit%s\n");
458 p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n");
459 p2a(tcps_sndacks, tcps_delack,
460 "\t\t%lu ack-only packet%s (%lu delayed)\n");
461 p(tcps_sndurg, "\t\t%lu URG only packet%s\n");
462 p(tcps_sndprobe, "\t\t%lu window probe packet%s\n");
463 p(tcps_sndwinup, "\t\t%lu window update packet%s\n");
464 p(tcps_sndctrl, "\t\t%lu control packet%s\n");
465 p(tcps_rcvtotal, "\t%lu packet%s received\n");
466 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n");
467 p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n");
468 p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n");
469 p2(tcps_rcvpack, tcps_rcvbyte,
470 "\t\t%lu packet%s (%lu byte%s) received in-sequence\n");
471 p2(tcps_rcvduppack, tcps_rcvdupbyte,
472 "\t\t%lu completely duplicate packet%s (%lu byte%s)\n");
473 p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n");
474 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
475 "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n");
476 p2(tcps_rcvoopack, tcps_rcvoobyte,
477 "\t\t%lu out-of-order packet%s (%lu byte%s)\n");
478 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
479 "\t\t%lu packet%s (%lu byte%s) of data after window\n");
480 p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n");
481 p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n");
482 p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n");
483 p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n");
484 p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n");
485 p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n");
486 p(tcps_connattempt, "\t%lu connection request%s\n");
487 p(tcps_accepts, "\t%lu connection accept%s\n");
488 p(tcps_badsyn, "\t%lu bad connection attempt%s\n");
489 p(tcps_listendrop, "\t%lu listen queue overflow%s\n");
490 p(tcps_connects, "\t%lu connection%s established (including accepts)\n");
491 p2(tcps_closed, tcps_drops,
492 "\t%lu connection%s closed (including %lu drop%s)\n");
493 p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n");
494 p(tcps_cachedrttvar,
495 "\t\t%lu connection%s updated cached RTT variance on close\n");
496 p(tcps_cachedssthresh,
497 "\t\t%lu connection%s updated cached ssthresh on close\n");
498 p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n");
499 p2(tcps_rttupdated, tcps_segstimed,
500 "\t%lu segment%s updated rtt (of %lu attempt%s)\n");
501 p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n");
502 p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n");
503 p(tcps_persisttimeo, "\t%lu persist timeout%s\n");
504 p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n");
505 p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n");
506 p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n");
507 p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n");
508 p(tcps_predack, "\t%lu correct ACK header prediction%s\n");
509 p(tcps_preddat, "\t%lu correct data packet header prediction%s\n");
511 p1a(tcps_sc_added, "\t%lu syncache entries added\n");
512 p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n");
513 p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n");
514 p1a(tcps_sc_dropped, "\t\t%lu dropped\n");
515 p1a(tcps_sc_completed, "\t\t%lu completed\n");
516 p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n");
517 p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n");
518 p1a(tcps_sc_reset, "\t\t%lu reset\n");
519 p1a(tcps_sc_stale, "\t\t%lu stale\n");
520 p1a(tcps_sc_aborted, "\t\t%lu aborted\n");
521 p1a(tcps_sc_badack, "\t\t%lu badack\n");
522 p1a(tcps_sc_unreach, "\t\t%lu unreach\n");
523 p1a(tcps_sc_zonefail, "\t\t%lu zone failures\n");
524 p1a(tcps_sc_sendcookie, "\t%lu cookies sent\n");
525 p1a(tcps_sc_recvcookie, "\t%lu cookies received\n");
526 free(stattmp);
527 #undef p
528 #undef p1a
529 #undef p2
530 #undef p2a
531 #undef p3
535 * Dump UDP statistics structure.
537 void
538 udp_stats(u_long off __unused, char *name, int af __unused)
540 struct udpstat udpstat, zerostat;
541 size_t len = sizeof udpstat;
542 u_long delivered;
544 if (zflag)
545 memset(&zerostat, 0, len);
546 if (sysctlbyname("net.inet.udp.stats", &udpstat, &len,
547 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
548 warn("sysctl: net.inet.udp.stats");
549 return;
552 #ifdef INET6
553 if (udp_done != 0)
554 return;
555 else
556 udp_done = 1;
557 #endif
559 printf("%s:\n", name);
560 #define p(f, m) if (udpstat.f || sflag <= 1) \
561 printf(m, udpstat.f, plural(udpstat.f))
562 #define p1a(f, m) if (udpstat.f || sflag <= 1) \
563 printf(m, udpstat.f)
564 p(udps_ipackets, "\t%lu datagram%s received\n");
565 p1a(udps_hdrops, "\t%lu with incomplete header\n");
566 p1a(udps_badlen, "\t%lu with bad data length field\n");
567 p1a(udps_badsum, "\t%lu with bad checksum\n");
568 p1a(udps_nosum, "\t%lu with no checksum\n");
569 p1a(udps_noport, "\t%lu dropped due to no socket\n");
570 p(udps_noportbcast,
571 "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
572 p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
573 p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n");
574 delivered = udpstat.udps_ipackets -
575 udpstat.udps_hdrops -
576 udpstat.udps_badlen -
577 udpstat.udps_badsum -
578 udpstat.udps_noport -
579 udpstat.udps_noportbcast -
580 udpstat.udps_fullsock;
581 if (delivered || sflag <= 1)
582 printf("\t%lu delivered\n", delivered);
583 p(udps_opackets, "\t%lu datagram%s output\n");
584 #undef p
585 #undef p1a
589 * Dump CARP statistics structure.
591 void
592 carp_stats(u_long off, const char *name, int af1 __unused)
594 struct carpstats carpstat, zerostat;
595 size_t len = sizeof(struct carpstats);
597 if (zflag)
598 memset(&zerostat, 0, len);
599 if (sysctlbyname("net.inet.carp.stats", &carpstat, &len,
600 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
601 warn("sysctl: net.inet.carp.stats");
602 return;
605 printf("%s:\n", name);
607 #define p(f, m) if (carpstat.f || sflag <= 1) \
608 printf(m, (unsigned long long)carpstat.f, plural((int)carpstat.f))
609 #define p2(f, m) if (carpstat.f || sflag <= 1) \
610 printf(m, (unsigned long long)carpstat.f)
612 p(carps_ipackets, "\t%llu packet%s received (IPv4)\n");
613 p(carps_ipackets6, "\t%llu packet%s received (IPv6)\n");
614 p(carps_badttl, "\t\t%llu packet%s discarded for wrong TTL\n");
615 p(carps_hdrops, "\t\t%llu packet%s shorter than header\n");
616 p(carps_badsum, "\t\t%llu discarded for bad checksum%s\n");
617 p(carps_badver, "\t\t%llu discarded packet%s with a bad version\n");
618 p2(carps_badlen, "\t\t%llu discarded because packet too short\n");
619 p2(carps_badauth, "\t\t%llu discarded for bad authentication\n");
620 p2(carps_badvhid, "\t\t%llu discarded for bad vhid\n");
621 p2(carps_badaddrs, "\t\t%llu discarded because of a bad address list\n");
622 p(carps_opackets, "\t%llu packet%s sent (IPv4)\n");
623 p(carps_opackets6, "\t%llu packet%s sent (IPv6)\n");
624 p2(carps_onomem, "\t\t%llu send failed due to mbuf memory error\n");
625 #if notyet
626 p(carps_ostates, "\t\t%s state update%s sent\n");
627 #endif
628 #undef p
629 #undef p2
633 * Dump IP statistics structure.
635 void
636 ip_stats(u_long off __unused, char *name, int af __unused)
638 struct ip_stats ipstat, *stattmp;
639 struct ip_stats zerostat[SMP_MAXCPU];
640 size_t len = sizeof(struct ip_stats) * SMP_MAXCPU;
641 int cpucnt;
643 if (zflag)
644 memset(zerostat, 0, len);
645 if ((stattmp = malloc(len)) == NULL) {
646 return;
647 } else {
648 if (sysctlbyname("net.inet.ip.stats", stattmp, &len,
649 zflag ? zerostat : NULL, zflag ? len : 0) < 0) {
650 warn("sysctl: net.inet.ip.stats");
651 free(stattmp);
652 return;
653 } else {
654 if ((stattmp = realloc(stattmp, len)) == NULL) {
655 warn("ip_stats");
656 return;
660 cpucnt = len / sizeof(struct ip_stats);
661 ip_stats_agg(stattmp, &ipstat, cpucnt);
663 printf("%s:\n", name);
665 #define p(f, m) if (ipstat.f || sflag <= 1) \
666 printf(m, ipstat.f, plural(ipstat.f))
667 #define p1a(f, m) if (ipstat.f || sflag <= 1) \
668 printf(m, ipstat.f)
670 p(ips_total, "\t%lu total packet%s received\n");
671 p(ips_badsum, "\t%lu bad header checksum%s\n");
672 p1a(ips_toosmall, "\t%lu with size smaller than minimum\n");
673 p1a(ips_tooshort, "\t%lu with data size < data length\n");
674 p1a(ips_toolong, "\t%lu with ip length > max ip packet size\n");
675 p1a(ips_badhlen, "\t%lu with header length < data size\n");
676 p1a(ips_badlen, "\t%lu with data length < header length\n");
677 p1a(ips_badoptions, "\t%lu with bad options\n");
678 p1a(ips_badvers, "\t%lu with incorrect version number\n");
679 p(ips_fragments, "\t%lu fragment%s received\n");
680 p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
681 p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
682 p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
683 p(ips_delivered, "\t%lu packet%s for this host\n");
684 p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
685 p(ips_forward, "\t%lu packet%s forwarded");
686 p(ips_fastforward, " (%lu packet%s fast forwarded)");
687 if (ipstat.ips_forward || sflag <= 1)
688 putchar('\n');
689 p(ips_cantforward, "\t%lu packet%s not forwardable\n");
690 p(ips_notmember,
691 "\t%lu packet%s received for unknown multicast group\n");
692 p(ips_redirectsent, "\t%lu redirect%s sent\n");
693 p(ips_localout, "\t%lu packet%s sent from this host\n");
694 p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
695 p(ips_odropped,
696 "\t%lu output packet%s dropped due to no bufs, etc.\n");
697 p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
698 p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
699 p(ips_ofragments, "\t%lu fragment%s created\n");
700 p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
701 p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n");
702 p(ips_badaddr, "\t%lu datagram%s with bad address in header\n");
703 free(stattmp);
704 #undef p
705 #undef p1a
708 static char *icmpnames[] = {
709 "echo reply",
710 "#1",
711 "#2",
712 "destination unreachable",
713 "source quench",
714 "routing redirect",
715 "#6",
716 "#7",
717 "echo",
718 "router advertisement",
719 "router solicitation",
720 "time exceeded",
721 "parameter problem",
722 "time stamp",
723 "time stamp reply",
724 "information request",
725 "information request reply",
726 "address mask request",
727 "address mask reply",
731 * Dump ICMP statistics.
733 void
734 icmp_stats(u_long off __unused, char *name, int af __unused)
736 struct icmpstat icmpstat, zerostat;
737 int i, first;
738 int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */
739 size_t len;
741 mib[0] = CTL_NET;
742 mib[1] = PF_INET;
743 mib[2] = IPPROTO_ICMP;
744 mib[3] = ICMPCTL_STATS;
746 len = sizeof icmpstat;
747 if (zflag)
748 memset(&zerostat, 0, len);
749 if (sysctl(mib, 4, &icmpstat, &len,
750 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
751 warn("sysctl: net.inet.icmp.stats");
752 return;
755 printf("%s:\n", name);
757 #define p(f, m) if (icmpstat.f || sflag <= 1) \
758 printf(m, icmpstat.f, plural(icmpstat.f))
759 #define p1a(f, m) if (icmpstat.f || sflag <= 1) \
760 printf(m, icmpstat.f)
761 #define p2(f, m) if (icmpstat.f || sflag <= 1) \
762 printf(m, icmpstat.f, plurales(icmpstat.f))
764 p(icps_error, "\t%lu call%s to icmp_error\n");
765 p(icps_oldicmp,
766 "\t%lu error%s not generated 'cuz old message was icmp\n");
767 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
768 if (icmpstat.icps_outhist[i] != 0) {
769 if (first) {
770 printf("\tOutput histogram:\n");
771 first = 0;
773 printf("\t\t%s: %lu\n", icmpnames[i],
774 icmpstat.icps_outhist[i]);
776 p(icps_badcode, "\t%lu message%s with bad code fields\n");
777 p(icps_tooshort, "\t%lu message%s < minimum length\n");
778 p(icps_checksum, "\t%lu bad checksum%s\n");
779 p(icps_badlen, "\t%lu message%s with bad length\n");
780 p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n");
781 p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n");
782 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
783 if (icmpstat.icps_inhist[i] != 0) {
784 if (first) {
785 printf("\tInput histogram:\n");
786 first = 0;
788 printf("\t\t%s: %lu\n", icmpnames[i],
789 icmpstat.icps_inhist[i]);
791 p(icps_reflect, "\t%lu message response%s generated\n");
792 p2(icps_badaddr, "\t%lu invalid return address%s\n");
793 p(icps_noroute, "\t%lu no return route%s\n");
794 #undef p
795 #undef p1a
796 #undef p2
797 mib[3] = ICMPCTL_MASKREPL;
798 len = sizeof i;
799 if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0)
800 return;
801 printf("\tICMP address mask responses are %sabled\n",
802 i ? "en" : "dis");
806 * Dump IGMP statistics structure.
808 void
809 igmp_stats(u_long off __unused, char *name, int af __unused)
811 struct igmpstat igmpstat, zerostat;
812 size_t len = sizeof igmpstat;
814 if (zflag)
815 memset(&zerostat, 0, len);
816 if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len,
817 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
818 warn("sysctl: net.inet.igmp.stats");
819 return;
822 printf("%s:\n", name);
824 #define p(f, m) if (igmpstat.f || sflag <= 1) \
825 printf(m, igmpstat.f, plural(igmpstat.f))
826 #define py(f, m) if (igmpstat.f || sflag <= 1) \
827 printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
828 p(igps_rcv_total, "\t%u message%s received\n");
829 p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
830 p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
831 py(igps_rcv_queries, "\t%u membership quer%s received\n");
832 py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
833 p(igps_rcv_reports, "\t%u membership report%s received\n");
834 p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
835 p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
836 p(igps_snd_reports, "\t%u membership report%s sent\n");
837 #undef p
838 #undef py
842 * Dump PIM statistics structure.
844 void
845 pim_stats(u_long off __unused, char *name, int af1 __unused)
847 struct pimstat pimstat, zerostat;
848 size_t len = sizeof pimstat;
850 if (zflag)
851 memset(&zerostat, 0, len);
852 if (sysctlbyname("net.inet.pim.stats", &pimstat, &len,
853 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
854 if (errno != ENOENT)
855 warn("sysctl: net.inet.pim.stats");
856 return;
859 printf("%s:\n", name);
861 #define p(f, m) if (pimstat.f || sflag <= 1) \
862 printf(m, pimstat.f, plural(pimstat.f))
863 #define py(f, m) if (pimstat.f || sflag <= 1) \
864 printf(m, pimstat.f, pimstat.f != 1 ? "ies" : "y")
865 p(pims_rcv_total_msgs, "\t%llu message%s received\n");
866 p(pims_rcv_total_bytes, "\t%llu byte%s received\n");
867 p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
868 p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n");
869 p(pims_rcv_badversion, "\t%llu message%s received with bad version\n");
870 p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n");
871 p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n");
872 p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n");
873 p(pims_rcv_badregisters, "\t%llu bad register%s received\n");
874 p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n");
875 p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n");
876 #undef p
877 #undef py
881 * Pretty print an Internet address (net address + port).
883 void
884 inetprint(struct in_addr *in, int port, const char *proto, int numeric_port)
886 struct servent *sp = 0;
887 char line[80], *cp;
888 int width;
890 if (Wflag)
891 sprintf(line, "%s.", inetname(in));
892 else
893 sprintf(line, "%.*s.", (Aflag && !numeric_port) ? 12 : 16, inetname(in));
894 cp = strchr(line, '\0');
895 if (!numeric_port && port)
896 sp = getservbyport((int)port, proto);
897 if (sp || port == 0)
898 sprintf(cp, "%.15s ", sp ? sp->s_name : "*");
899 else
900 sprintf(cp, "%d ", ntohs((u_short)port));
901 width = (Aflag && !Wflag) ? 17 : 21;
902 if (Wflag)
903 printf("%-*s ", width, line);
904 else
905 printf("%-*.*s ", width, width, line);
909 * Construct an Internet address representation.
910 * If numeric_addr has been supplied, give
911 * numeric value, otherwise try for symbolic name.
913 char *
914 inetname(struct in_addr *inp)
916 char *cp;
917 static char line[MAXHOSTNAMELEN];
918 struct hostent *hp;
919 struct netent *np;
921 cp = 0;
922 if (!numeric_addr && inp->s_addr != INADDR_ANY) {
923 int net = inet_netof(*inp);
924 int lna = inet_lnaof(*inp);
926 if (lna == INADDR_ANY) {
927 np = getnetbyaddr(net, AF_INET);
928 if (np)
929 cp = np->n_name;
931 if (cp == 0) {
932 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
933 if (hp) {
934 cp = hp->h_name;
935 trimdomain(cp, strlen(cp));
939 if (inp->s_addr == INADDR_ANY)
940 strcpy(line, "*");
941 else if (cp) {
942 strncpy(line, cp, sizeof(line) - 1);
943 line[sizeof(line) - 1] = '\0';
944 } else {
945 inp->s_addr = ntohl(inp->s_addr);
946 #define C(x) ((u_int)((x) & 0xff))
947 sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
948 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
950 return (line);