Pull up CVS idents from FreeBSD to match our current version.
[dragonfly.git] / usr.bin / netstat / inet.c
blobf22548a0e44eb0f584ecb16173b0d17ebb9ec5fe
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, 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 (proto == IPPROTO_TCP && tp->t_state == TCPS_LISTEN) ||
207 (af == AF_INET && inet_lnaof(inp->inp_laddr) == INADDR_ANY)
208 #ifdef INET6
209 || (af == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
210 #endif /* INET6 */
211 || (af == AF_UNSPEC && (((inp->inp_vflag & INP_IPV4) != 0 &&
212 inet_lnaof(inp->inp_laddr) == INADDR_ANY)
213 #ifdef INET6
214 || ((inp->inp_vflag & INP_IPV6) != 0 &&
215 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
216 #endif
218 )) {
219 return;
222 if (ppr_first) {
223 if (!Lflag) {
224 printf("Active Internet connections");
225 if (aflag)
226 printf(" (including servers)");
227 } else {
228 printf("Current listen queue sizes "
229 "(qlen/incqlen/maxqlen)");
231 putchar('\n');
232 if (Aflag)
233 printf("%-8.8s ", "Socket");
234 if (Pflag)
235 printf("%8.8s %8.8s %8.8s ", "TxWin", "Unacked", "RTT/ms");
236 if (Lflag) {
237 printf("%-5.5s %-14.14s %-22.22s\n",
238 "Proto", "Listen", "Local Address");
239 } else {
240 printf((Aflag && !Wflag) ?
241 "%-5.5s %-6.6s %-6.6s %-17.17s %-17.17s %s\n" :
242 "%-5.5s %-6.6s %-6.6s %-21.21s %-21.21s %s\n",
243 "Proto", "Recv-Q", "Send-Q",
244 "Local Address", "Foreign Address",
245 "(state)");
247 ppr_first = 0;
249 if (Lflag && so->so_qlimit == 0)
250 return;
251 if (Aflag) {
252 if (tp)
253 printf("%8lx ", (u_long)inp->inp_ppcb);
254 else
255 printf("%8lx ", (u_long)so->so_pcb);
257 if (Pflag) {
258 if (tp) {
259 int window = MIN(tp->snd_cwnd, tp->snd_bwnd);
260 if (window == 1073725440)
261 printf("%8s ", "max");
262 else
263 printf("%8d ", (int)MIN(tp->snd_cwnd, tp->snd_bwnd));
264 printf("%8d ", (int)(tp->snd_max - tp->snd_una));
265 if (tp->t_srtt == 0)
266 printf("%8s ", "-");
267 else
268 printf("%8.3f ", (double)tp->t_srtt * 1000.0 / TCP_RTT_SCALE / clockinfo.hz);
269 } else {
270 printf("%8s %8s %8s ", "-", "-", "-");
273 #ifdef INET6
274 if ((inp->inp_vflag & INP_IPV6) != 0)
275 vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "46" : "6 ";
276 else
277 #endif
278 vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "4 " : " ";
280 printf("%-3.3s%-2.2s ", name, vchar);
281 if (Lflag) {
282 char buf[15];
284 snprintf(buf, sizeof(buf), "%d/%d/%d", so->so_qlen,
285 so->so_incqlen, so->so_qlimit);
286 printf("%-13.13s ", buf);
287 } else if (Bflag) {
288 printf("%6ld %6ld ",
289 so->so_rcv.sb_hiwat,
290 so->so_snd.sb_hiwat);
291 } else {
292 printf("%6ld %6ld ",
293 so->so_rcv.sb_cc,
294 so->so_snd.sb_cc);
296 if (numeric_port) {
297 if (inp->inp_vflag & INP_IPV4) {
298 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
299 name, 1);
300 if (!Lflag)
301 inetprint(&inp->inp_faddr,
302 (int)inp->inp_fport, name, 1);
304 #ifdef INET6
305 else if (inp->inp_vflag & INP_IPV6) {
306 inet6print(&inp->in6p_laddr,
307 (int)inp->inp_lport, name, 1);
308 if (!Lflag)
309 inet6print(&inp->in6p_faddr,
310 (int)inp->inp_fport, name, 1);
311 } /* else nothing printed now */
312 #endif /* INET6 */
313 } else if (inp->inp_flags & INP_ANONPORT) {
314 if (inp->inp_vflag & INP_IPV4) {
315 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
316 name, 1);
317 if (!Lflag)
318 inetprint(&inp->inp_faddr,
319 (int)inp->inp_fport, name, 0);
321 #ifdef INET6
322 else if (inp->inp_vflag & INP_IPV6) {
323 inet6print(&inp->in6p_laddr,
324 (int)inp->inp_lport, name, 1);
325 if (!Lflag)
326 inet6print(&inp->in6p_faddr,
327 (int)inp->inp_fport, name, 0);
328 } /* else nothing printed now */
329 #endif /* INET6 */
330 } else {
331 if (inp->inp_vflag & INP_IPV4) {
332 inetprint(&inp->inp_laddr, (int)inp->inp_lport,
333 name, 0);
334 if (!Lflag)
335 inetprint(&inp->inp_faddr,
336 (int)inp->inp_fport, name,
337 inp->inp_lport !=
338 inp->inp_fport);
340 #ifdef INET6
341 else if (inp->inp_vflag & INP_IPV6) {
342 inet6print(&inp->in6p_laddr,
343 (int)inp->inp_lport, name, 0);
344 if (!Lflag)
345 inet6print(&inp->in6p_faddr,
346 (int)inp->inp_fport, name,
347 inp->inp_lport !=
348 inp->inp_fport);
349 } /* else nothing printed now */
350 #endif /* INET6 */
352 if (tp && !Lflag) {
353 if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
354 printf("%d", tp->t_state);
355 else {
356 printf("%s", tcpstates[tp->t_state]);
357 #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
358 /* Show T/TCP `hidden state' */
359 if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
360 putchar('*');
361 #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
364 putchar('\n');
369 #define CPU_STATS_FUNC(proto,type) \
370 static void \
371 proto ##_stats_agg(type *ary, type *ttl, int cpucnt) \
373 int i, off, siz; \
374 siz = sizeof(type); \
376 if (!ary && !ttl) \
377 return; \
379 bzero(ttl, siz); \
380 if (cpucnt == 1) { \
381 *ttl = ary[0]; \
382 } else { \
383 for (i = 0; i < cpucnt; ++i) { \
384 for (off = 0; off < siz; off += sizeof(u_long)) { \
385 *(u_long *)((char *)(*(&ttl)) + off) += \
386 *(u_long *)((char *)&ary[i] + off); \
391 CPU_STATS_FUNC(tcp, struct tcp_stats);
392 CPU_STATS_FUNC(ip, struct ip_stats);
395 * Dump TCP statistics structure.
397 void
398 tcp_stats(u_long off __unused, char *name, int af __unused)
400 struct tcp_stats tcpstat, *stattmp;
401 struct tcp_stats zerostat[SMP_MAXCPU];
402 size_t len = sizeof(struct tcp_stats) * SMP_MAXCPU;
403 int cpucnt;
405 if (zflag)
406 memset(zerostat, 0, len);
408 if ((stattmp = malloc(len)) == NULL) {
409 return;
410 } else {
411 if (sysctlbyname("net.inet.tcp.stats", stattmp, &len,
412 zflag ? zerostat : NULL, zflag ? len : 0) < 0) {
413 warn("sysctl: net.inet.tcp.stats");
414 free(stattmp);
415 return;
416 } else {
417 if ((stattmp = realloc(stattmp, len)) == NULL) {
418 warn("tcp_stats");
419 return;
423 cpucnt = len / sizeof(struct tcp_stats);
424 tcp_stats_agg(stattmp, &tcpstat, cpucnt);
426 #ifdef INET6
427 if (tcp_done != 0)
428 return;
429 else
430 tcp_done = 1;
431 #endif
433 printf ("%s:\n", name);
435 #define p(f, m) if (tcpstat.f || sflag <= 1) \
436 printf(m, tcpstat.f, plural(tcpstat.f))
437 #define p1a(f, m) if (tcpstat.f || sflag <= 1) \
438 printf(m, tcpstat.f)
439 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
440 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
441 #define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
442 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
443 #define p3(f, m) if (tcpstat.f || sflag <= 1) \
444 printf(m, tcpstat.f, plurales(tcpstat.f))
446 p(tcps_sndtotal, "\t%lu packet%s sent\n");
447 p2(tcps_sndpack,tcps_sndbyte,
448 "\t\t%lu data packet%s (%lu byte%s)\n");
449 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
450 "\t\t%lu data packet%s (%lu byte%s) retransmitted\n");
451 p2a(tcps_sndfastrexmit, tcps_sndearlyrexmit,
452 "\t\t%lu Fast Retransmit%s (%lu early)\n");
453 p(tcps_sndlimited, "\t\t%lu packet%s sent by Limited Transmit\n");
454 p(tcps_sndrtobad, "\t\t%lu spurious RTO retransmit%s\n");
455 p2a(tcps_sndfastrexmitbad, tcps_sndearlyrexmitbad,
456 "\t\t%lu spurious Fast Retransmit%s (%lu early)\n");
457 p(tcps_eifeldetected, "\t\t%lu Eifel-detected spurious retransmit%s\n");
458 p(tcps_rttdetected, "\t\t%lu RTT-detected spurious retransmit%s\n");
459 p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n");
460 p2a(tcps_sndacks, tcps_delack,
461 "\t\t%lu ack-only packet%s (%lu delayed)\n");
462 p(tcps_sndurg, "\t\t%lu URG only packet%s\n");
463 p(tcps_sndprobe, "\t\t%lu window probe packet%s\n");
464 p(tcps_sndwinup, "\t\t%lu window update packet%s\n");
465 p(tcps_sndctrl, "\t\t%lu control packet%s\n");
466 p(tcps_rcvtotal, "\t%lu packet%s received\n");
467 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n");
468 p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n");
469 p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n");
470 p2(tcps_rcvpack, tcps_rcvbyte,
471 "\t\t%lu packet%s (%lu byte%s) received in-sequence\n");
472 p2(tcps_rcvduppack, tcps_rcvdupbyte,
473 "\t\t%lu completely duplicate packet%s (%lu byte%s)\n");
474 p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n");
475 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
476 "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n");
477 p2(tcps_rcvoopack, tcps_rcvoobyte,
478 "\t\t%lu out-of-order packet%s (%lu byte%s)\n");
479 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
480 "\t\t%lu packet%s (%lu byte%s) of data after window\n");
481 p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n");
482 p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n");
483 p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n");
484 p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n");
485 p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n");
486 p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n");
487 p(tcps_connattempt, "\t%lu connection request%s\n");
488 p(tcps_accepts, "\t%lu connection accept%s\n");
489 p(tcps_badsyn, "\t%lu bad connection attempt%s\n");
490 p(tcps_listendrop, "\t%lu listen queue overflow%s\n");
491 p(tcps_connects, "\t%lu connection%s established (including accepts)\n");
492 p2(tcps_closed, tcps_drops,
493 "\t%lu connection%s closed (including %lu drop%s)\n");
494 p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n");
495 p(tcps_cachedrttvar,
496 "\t\t%lu connection%s updated cached RTT variance on close\n");
497 p(tcps_cachedssthresh,
498 "\t\t%lu connection%s updated cached ssthresh on close\n");
499 p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n");
500 p2(tcps_rttupdated, tcps_segstimed,
501 "\t%lu segment%s updated rtt (of %lu attempt%s)\n");
502 p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n");
503 p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n");
504 p(tcps_persisttimeo, "\t%lu persist timeout%s\n");
505 p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n");
506 p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n");
507 p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n");
508 p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n");
509 p(tcps_predack, "\t%lu correct ACK header prediction%s\n");
510 p(tcps_preddat, "\t%lu correct data packet header prediction%s\n");
512 p1a(tcps_sc_added, "\t%lu syncache entries added\n");
513 p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n");
514 p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n");
515 p1a(tcps_sc_dropped, "\t\t%lu dropped\n");
516 p1a(tcps_sc_completed, "\t\t%lu completed\n");
517 p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n");
518 p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n");
519 p1a(tcps_sc_reset, "\t\t%lu reset\n");
520 p1a(tcps_sc_stale, "\t\t%lu stale\n");
521 p1a(tcps_sc_aborted, "\t\t%lu aborted\n");
522 p1a(tcps_sc_badack, "\t\t%lu badack\n");
523 p1a(tcps_sc_unreach, "\t\t%lu unreach\n");
524 p1a(tcps_sc_zonefail, "\t\t%lu zone failures\n");
525 p1a(tcps_sc_sendcookie, "\t%lu cookies sent\n");
526 p1a(tcps_sc_recvcookie, "\t%lu cookies received\n");
527 free(stattmp);
528 #undef p
529 #undef p1a
530 #undef p2
531 #undef p2a
532 #undef p3
536 * Dump UDP statistics structure.
538 void
539 udp_stats(u_long off __unused, char *name, int af __unused)
541 struct udpstat udpstat, zerostat;
542 size_t len = sizeof udpstat;
543 u_long delivered;
545 if (zflag)
546 memset(&zerostat, 0, len);
547 if (sysctlbyname("net.inet.udp.stats", &udpstat, &len,
548 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
549 warn("sysctl: net.inet.udp.stats");
550 return;
553 #ifdef INET6
554 if (udp_done != 0)
555 return;
556 else
557 udp_done = 1;
558 #endif
560 printf("%s:\n", name);
561 #define p(f, m) if (udpstat.f || sflag <= 1) \
562 printf(m, udpstat.f, plural(udpstat.f))
563 #define p1a(f, m) if (udpstat.f || sflag <= 1) \
564 printf(m, udpstat.f)
565 p(udps_ipackets, "\t%lu datagram%s received\n");
566 p1a(udps_hdrops, "\t%lu with incomplete header\n");
567 p1a(udps_badlen, "\t%lu with bad data length field\n");
568 p1a(udps_badsum, "\t%lu with bad checksum\n");
569 p1a(udps_nosum, "\t%lu with no checksum\n");
570 p1a(udps_noport, "\t%lu dropped due to no socket\n");
571 p(udps_noportbcast,
572 "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
573 p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
574 p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n");
575 delivered = udpstat.udps_ipackets -
576 udpstat.udps_hdrops -
577 udpstat.udps_badlen -
578 udpstat.udps_badsum -
579 udpstat.udps_noport -
580 udpstat.udps_noportbcast -
581 udpstat.udps_fullsock;
582 if (delivered || sflag <= 1)
583 printf("\t%lu delivered\n", delivered);
584 p(udps_opackets, "\t%lu datagram%s output\n");
585 #undef p
586 #undef p1a
590 * Dump CARP statistics structure.
592 void
593 carp_stats(u_long off, const char *name, int af1 __unused)
595 struct carpstats carpstat, zerostat;
596 size_t len = sizeof(struct carpstats);
598 if (zflag)
599 memset(&zerostat, 0, len);
600 if (sysctlbyname("net.inet.carp.stats", &carpstat, &len,
601 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
602 warn("sysctl: net.inet.carp.stats");
603 return;
606 printf("%s:\n", name);
608 #define p(f, m) if (carpstat.f || sflag <= 1) \
609 printf(m, (unsigned long long)carpstat.f, plural((int)carpstat.f))
610 #define p2(f, m) if (carpstat.f || sflag <= 1) \
611 printf(m, (unsigned long long)carpstat.f)
613 p(carps_ipackets, "\t%llu packet%s received (IPv4)\n");
614 p(carps_ipackets6, "\t%llu packet%s received (IPv6)\n");
615 p(carps_badttl, "\t\t%llu packet%s discarded for wrong TTL\n");
616 p(carps_hdrops, "\t\t%llu packet%s shorter than header\n");
617 p(carps_badsum, "\t\t%llu discarded for bad checksum%s\n");
618 p(carps_badver, "\t\t%llu discarded packet%s with a bad version\n");
619 p2(carps_badlen, "\t\t%llu discarded because packet too short\n");
620 p2(carps_badauth, "\t\t%llu discarded for bad authentication\n");
621 p2(carps_badvhid, "\t\t%llu discarded for bad vhid\n");
622 p2(carps_badaddrs, "\t\t%llu discarded because of a bad address list\n");
623 p(carps_opackets, "\t%llu packet%s sent (IPv4)\n");
624 p(carps_opackets6, "\t%llu packet%s sent (IPv6)\n");
625 p2(carps_onomem, "\t\t%llu send failed due to mbuf memory error\n");
626 #if notyet
627 p(carps_ostates, "\t\t%s state update%s sent\n");
628 #endif
629 #undef p
630 #undef p2
634 * Dump IP statistics structure.
636 void
637 ip_stats(u_long off __unused, char *name, int af __unused)
639 struct ip_stats ipstat, *stattmp;
640 struct ip_stats zerostat[SMP_MAXCPU];
641 size_t len = sizeof(struct ip_stats) * SMP_MAXCPU;
642 int cpucnt;
644 if (zflag)
645 memset(zerostat, 0, len);
646 if ((stattmp = malloc(len)) == NULL) {
647 return;
648 } else {
649 if (sysctlbyname("net.inet.ip.stats", stattmp, &len,
650 zflag ? zerostat : NULL, zflag ? len : 0) < 0) {
651 warn("sysctl: net.inet.ip.stats");
652 free(stattmp);
653 return;
654 } else {
655 if ((stattmp = realloc(stattmp, len)) == NULL) {
656 warn("ip_stats");
657 return;
661 cpucnt = len / sizeof(struct ip_stats);
662 ip_stats_agg(stattmp, &ipstat, cpucnt);
664 printf("%s:\n", name);
666 #define p(f, m) if (ipstat.f || sflag <= 1) \
667 printf(m, ipstat.f, plural(ipstat.f))
668 #define p1a(f, m) if (ipstat.f || sflag <= 1) \
669 printf(m, ipstat.f)
671 p(ips_total, "\t%lu total packet%s received\n");
672 p(ips_badsum, "\t%lu bad header checksum%s\n");
673 p1a(ips_toosmall, "\t%lu with size smaller than minimum\n");
674 p1a(ips_tooshort, "\t%lu with data size < data length\n");
675 p1a(ips_toolong, "\t%lu with ip length > max ip packet size\n");
676 p1a(ips_badhlen, "\t%lu with header length < data size\n");
677 p1a(ips_badlen, "\t%lu with data length < header length\n");
678 p1a(ips_badoptions, "\t%lu with bad options\n");
679 p1a(ips_badvers, "\t%lu with incorrect version number\n");
680 p(ips_fragments, "\t%lu fragment%s received\n");
681 p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
682 p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
683 p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
684 p(ips_delivered, "\t%lu packet%s for this host\n");
685 p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
686 p(ips_forward, "\t%lu packet%s forwarded");
687 p(ips_fastforward, " (%lu packet%s fast forwarded)");
688 if (ipstat.ips_forward || sflag <= 1)
689 putchar('\n');
690 p(ips_cantforward, "\t%lu packet%s not forwardable\n");
691 p(ips_notmember,
692 "\t%lu packet%s received for unknown multicast group\n");
693 p(ips_redirectsent, "\t%lu redirect%s sent\n");
694 p(ips_localout, "\t%lu packet%s sent from this host\n");
695 p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
696 p(ips_odropped,
697 "\t%lu output packet%s dropped due to no bufs, etc.\n");
698 p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
699 p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
700 p(ips_ofragments, "\t%lu fragment%s created\n");
701 p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
702 p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n");
703 p(ips_badaddr, "\t%lu datagram%s with bad address in header\n");
704 free(stattmp);
705 #undef p
706 #undef p1a
709 static char *icmpnames[] = {
710 "echo reply",
711 "#1",
712 "#2",
713 "destination unreachable",
714 "source quench",
715 "routing redirect",
716 "#6",
717 "#7",
718 "echo",
719 "router advertisement",
720 "router solicitation",
721 "time exceeded",
722 "parameter problem",
723 "time stamp",
724 "time stamp reply",
725 "information request",
726 "information request reply",
727 "address mask request",
728 "address mask reply",
732 * Dump ICMP statistics.
734 void
735 icmp_stats(u_long off __unused, char *name, int af __unused)
737 struct icmpstat icmpstat, zerostat;
738 int i, first;
739 int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */
740 size_t len;
742 mib[0] = CTL_NET;
743 mib[1] = PF_INET;
744 mib[2] = IPPROTO_ICMP;
745 mib[3] = ICMPCTL_STATS;
747 len = sizeof icmpstat;
748 if (zflag)
749 memset(&zerostat, 0, len);
750 if (sysctl(mib, 4, &icmpstat, &len,
751 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
752 warn("sysctl: net.inet.icmp.stats");
753 return;
756 printf("%s:\n", name);
758 #define p(f, m) if (icmpstat.f || sflag <= 1) \
759 printf(m, icmpstat.f, plural(icmpstat.f))
760 #define p1a(f, m) if (icmpstat.f || sflag <= 1) \
761 printf(m, icmpstat.f)
762 #define p2(f, m) if (icmpstat.f || sflag <= 1) \
763 printf(m, icmpstat.f, plurales(icmpstat.f))
765 p(icps_error, "\t%lu call%s to icmp_error\n");
766 p(icps_oldicmp,
767 "\t%lu error%s not generated 'cuz old message was icmp\n");
768 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
769 if (icmpstat.icps_outhist[i] != 0) {
770 if (first) {
771 printf("\tOutput histogram:\n");
772 first = 0;
774 printf("\t\t%s: %lu\n", icmpnames[i],
775 icmpstat.icps_outhist[i]);
777 p(icps_badcode, "\t%lu message%s with bad code fields\n");
778 p(icps_tooshort, "\t%lu message%s < minimum length\n");
779 p(icps_checksum, "\t%lu bad checksum%s\n");
780 p(icps_badlen, "\t%lu message%s with bad length\n");
781 p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n");
782 p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n");
783 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
784 if (icmpstat.icps_inhist[i] != 0) {
785 if (first) {
786 printf("\tInput histogram:\n");
787 first = 0;
789 printf("\t\t%s: %lu\n", icmpnames[i],
790 icmpstat.icps_inhist[i]);
792 p(icps_reflect, "\t%lu message response%s generated\n");
793 p2(icps_badaddr, "\t%lu invalid return address%s\n");
794 p(icps_noroute, "\t%lu no return route%s\n");
795 #undef p
796 #undef p1a
797 #undef p2
798 mib[3] = ICMPCTL_MASKREPL;
799 len = sizeof i;
800 if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0)
801 return;
802 printf("\tICMP address mask responses are %sabled\n",
803 i ? "en" : "dis");
807 * Dump IGMP statistics structure.
809 void
810 igmp_stats(u_long off __unused, char *name, int af __unused)
812 struct igmpstat igmpstat, zerostat;
813 size_t len = sizeof igmpstat;
815 if (zflag)
816 memset(&zerostat, 0, len);
817 if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len,
818 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
819 warn("sysctl: net.inet.igmp.stats");
820 return;
823 printf("%s:\n", name);
825 #define p(f, m) if (igmpstat.f || sflag <= 1) \
826 printf(m, igmpstat.f, plural(igmpstat.f))
827 #define py(f, m) if (igmpstat.f || sflag <= 1) \
828 printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
829 p(igps_rcv_total, "\t%u message%s received\n");
830 p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
831 p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
832 py(igps_rcv_queries, "\t%u membership quer%s received\n");
833 py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
834 p(igps_rcv_reports, "\t%u membership report%s received\n");
835 p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
836 p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
837 p(igps_snd_reports, "\t%u membership report%s sent\n");
838 #undef p
839 #undef py
843 * Dump PIM statistics structure.
845 void
846 pim_stats(u_long off __unused, char *name, int af1 __unused)
848 struct pimstat pimstat, zerostat;
849 size_t len = sizeof pimstat;
851 if (zflag)
852 memset(&zerostat, 0, len);
853 if (sysctlbyname("net.inet.pim.stats", &pimstat, &len,
854 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
855 if (errno != ENOENT)
856 warn("sysctl: net.inet.pim.stats");
857 return;
860 printf("%s:\n", name);
862 #define p(f, m) if (pimstat.f || sflag <= 1) \
863 printf(m, pimstat.f, plural(pimstat.f))
864 #define py(f, m) if (pimstat.f || sflag <= 1) \
865 printf(m, pimstat.f, pimstat.f != 1 ? "ies" : "y")
866 p(pims_rcv_total_msgs, "\t%llu message%s received\n");
867 p(pims_rcv_total_bytes, "\t%llu byte%s received\n");
868 p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
869 p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n");
870 p(pims_rcv_badversion, "\t%llu message%s received with bad version\n");
871 p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n");
872 p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n");
873 p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n");
874 p(pims_rcv_badregisters, "\t%llu bad register%s received\n");
875 p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n");
876 p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n");
877 #undef p
878 #undef py
882 * Pretty print an Internet address (net address + port).
884 void
885 inetprint(struct in_addr *in, int port, const char *proto, int numeric_port)
887 struct servent *sp = 0;
888 char line[80], *cp;
889 int width;
891 if (Wflag)
892 sprintf(line, "%s.", inetname(in));
893 else
894 sprintf(line, "%.*s.", (Aflag && !numeric_port) ? 12 : 16, inetname(in));
895 cp = strchr(line, '\0');
896 if (!numeric_port && port)
897 sp = getservbyport((int)port, proto);
898 if (sp || port == 0)
899 sprintf(cp, "%.15s ", sp ? sp->s_name : "*");
900 else
901 sprintf(cp, "%d ", ntohs((u_short)port));
902 width = (Aflag && !Wflag) ? 17 : 21;
903 if (Wflag)
904 printf("%-*s ", width, line);
905 else
906 printf("%-*.*s ", width, width, line);
910 * Construct an Internet address representation.
911 * If numeric_addr has been supplied, give
912 * numeric value, otherwise try for symbolic name.
914 char *
915 inetname(struct in_addr *inp)
917 char *cp;
918 static char line[MAXHOSTNAMELEN];
919 struct hostent *hp;
920 struct netent *np;
922 cp = 0;
923 if (!numeric_addr && inp->s_addr != INADDR_ANY) {
924 int net = inet_netof(*inp);
925 int lna = inet_lnaof(*inp);
927 if (lna == INADDR_ANY) {
928 np = getnetbyaddr(net, AF_INET);
929 if (np)
930 cp = np->n_name;
932 if (cp == 0) {
933 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
934 if (hp) {
935 cp = hp->h_name;
936 trimdomain(cp, strlen(cp));
940 if (inp->s_addr == INADDR_ANY)
941 strcpy(line, "*");
942 else if (cp) {
943 strncpy(line, cp, sizeof(line) - 1);
944 line[sizeof(line) - 1] = '\0';
945 } else {
946 inp->s_addr = ntohl(inp->s_addr);
947 #define C(x) ((u_int)((x) & 0xff))
948 sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
949 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
951 return (line);