HAMMER - Add hammer dedup directive and support
[dragonfly.git] / usr.bin / netstat / inet.c
blob1f7fc36117738be9bc938df73cea4b9ec054f7b6
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.21 2007/12/29 22:15:06 hasso 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, const char *name, int af1 __unused)
102 int istcp;
103 void *buf;
104 const char *mibvar;
105 size_t i, 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 size_t 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 (proto == IPPROTO_TCP && tp->t_state == TCPS_LISTEN) ||
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, const char *name, int af1 __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, const char *name, int af1 __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 __unused, 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, (uintmax_t)carpstat.f, plural((int)carpstat.f))
609 #define p2(f, m) if (carpstat.f || sflag <= 1) \
610 printf(m, (uintmax_t)carpstat.f)
612 p(carps_ipackets, "\t%ju packet%s received (IPv4)\n");
613 p(carps_ipackets6, "\t%ju packet%s received (IPv6)\n");
614 p(carps_badttl, "\t\t%ju packet%s discarded for wrong TTL\n");
615 p(carps_hdrops, "\t\t%ju packet%s shorter than header\n");
616 p(carps_badsum, "\t\t%ju discarded for bad checksum%s\n");
617 p(carps_badver, "\t\t%ju discarded packet%s with a bad version\n");
618 p2(carps_badlen, "\t\t%ju discarded because packet too short\n");
619 p2(carps_badauth, "\t\t%ju discarded for bad authentication\n");
620 p2(carps_badvhid, "\t\t%ju discarded for bad vhid\n");
621 p2(carps_badaddrs, "\t\t%ju discarded because of a bad address list\n");
622 p(carps_opackets, "\t%ju packet%s sent (IPv4)\n");
623 p(carps_opackets6, "\t%ju packet%s sent (IPv6)\n");
624 p2(carps_onomem, "\t\t%ju 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, const char *name, int af1 __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 const 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, const char *name, int af1 __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, NULL, 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, const char *name, int af1 __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, const 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, (uintmax_t)pimstat.f, plural(pimstat.f))
863 #define py(f, m) if (pimstat.f || sflag <= 1) \
864 printf(m, (uintmax_t)pimstat.f, pimstat.f != 1 ? "ies" : "y")
865 p(pims_rcv_total_msgs, "\t%ju message%s received\n");
866 p(pims_rcv_total_bytes, "\t%ju byte%s received\n");
867 p(pims_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
868 p(pims_rcv_badsum, "\t%ju message%s received with bad checksum\n");
869 p(pims_rcv_badversion, "\t%ju message%s received with bad version\n");
870 p(pims_rcv_registers_msgs, "\t%ju data register message%s received\n");
871 p(pims_rcv_registers_bytes, "\t%ju data register byte%s received\n");
872 p(pims_rcv_registers_wrongiif, "\t%ju data register message%s received on wrong iif\n");
873 p(pims_rcv_badregisters, "\t%ju bad register%s received\n");
874 p(pims_snd_registers_msgs, "\t%ju data register message%s sent\n");
875 p(pims_snd_registers_bytes, "\t%ju 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 num_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 && !num_port) ? 12 : 16, inetname(in));
894 cp = strchr(line, '\0');
895 if (!num_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(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);