xref: /freebsd/usr.bin/netstat/inet.c (revision 22694ebad57c49178f28bcc781d8ee9eb5868dd8)
19b50d902SRodney W. Grimes /*
205ddff6eSPeter Wemm  * Copyright (c) 1983, 1988, 1993, 1995
39b50d902SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
49b50d902SRodney W. Grimes  *
59b50d902SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
69b50d902SRodney W. Grimes  * modification, are permitted provided that the following conditions
79b50d902SRodney W. Grimes  * are met:
89b50d902SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
99b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
109b50d902SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
119b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
129b50d902SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
139b50d902SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
149b50d902SRodney W. Grimes  *    must display the following acknowledgement:
159b50d902SRodney W. Grimes  *	This product includes software developed by the University of
169b50d902SRodney W. Grimes  *	California, Berkeley and its contributors.
179b50d902SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
189b50d902SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
199b50d902SRodney W. Grimes  *    without specific prior written permission.
209b50d902SRodney W. Grimes  *
219b50d902SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
229b50d902SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
239b50d902SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
249b50d902SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
259b50d902SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
269b50d902SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
279b50d902SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
289b50d902SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
299b50d902SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
309b50d902SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
319b50d902SRodney W. Grimes  * SUCH DAMAGE.
329b50d902SRodney W. Grimes  */
339b50d902SRodney W. Grimes 
349b50d902SRodney W. Grimes #ifndef lint
3590864998SGarrett Wollman /*
3605ddff6eSPeter Wemm static char sccsid[] = "@(#)inet.c	8.5 (Berkeley) 5/24/95";
3790864998SGarrett Wollman */
3890864998SGarrett Wollman static const char rcsid[] =
3922694ebaSBruce Evans 	"$Id: inet.c,v 1.29 1998/06/09 04:13:01 imp Exp $";
409b50d902SRodney W. Grimes #endif /* not lint */
419b50d902SRodney W. Grimes 
429b50d902SRodney W. Grimes #include <sys/param.h>
43d8d89152SDavid Greenman #include <sys/queue.h>
449b50d902SRodney W. Grimes #include <sys/socket.h>
459b50d902SRodney W. Grimes #include <sys/socketvar.h>
464e00c309SGarrett Wollman #include <sys/sysctl.h>
479b50d902SRodney W. Grimes #include <sys/protosw.h>
489b50d902SRodney W. Grimes 
499b50d902SRodney W. Grimes #include <net/route.h>
509b50d902SRodney W. Grimes #include <netinet/in.h>
519b50d902SRodney W. Grimes #include <netinet/in_systm.h>
529b50d902SRodney W. Grimes #include <netinet/ip.h>
539b50d902SRodney W. Grimes #include <netinet/in_pcb.h>
549b50d902SRodney W. Grimes #include <netinet/ip_icmp.h>
559b50d902SRodney W. Grimes #include <netinet/icmp_var.h>
569b50d902SRodney W. Grimes #include <netinet/igmp_var.h>
579b50d902SRodney W. Grimes #include <netinet/ip_var.h>
589b50d902SRodney W. Grimes #include <netinet/tcp.h>
599b50d902SRodney W. Grimes #include <netinet/tcpip.h>
609b50d902SRodney W. Grimes #include <netinet/tcp_seq.h>
619b50d902SRodney W. Grimes #define TCPSTATES
629b50d902SRodney W. Grimes #include <netinet/tcp_fsm.h>
639b50d902SRodney W. Grimes #include <netinet/tcp_timer.h>
649b50d902SRodney W. Grimes #include <netinet/tcp_var.h>
659b50d902SRodney W. Grimes #include <netinet/tcp_debug.h>
669b50d902SRodney W. Grimes #include <netinet/udp.h>
679b50d902SRodney W. Grimes #include <netinet/udp_var.h>
689b50d902SRodney W. Grimes 
699b50d902SRodney W. Grimes #include <arpa/inet.h>
704f81ef50SGarrett Wollman #include <err.h>
714f81ef50SGarrett Wollman #include <errno.h>
729b50d902SRodney W. Grimes #include <netdb.h>
739b50d902SRodney W. Grimes #include <stdio.h>
744f81ef50SGarrett Wollman #include <stdlib.h>
759b50d902SRodney W. Grimes #include <string.h>
769b50d902SRodney W. Grimes #include <unistd.h>
779b50d902SRodney W. Grimes #include "netstat.h"
789b50d902SRodney W. Grimes 
799b50d902SRodney W. Grimes char	*inetname __P((struct in_addr *));
808d612dd2SPoul-Henning Kamp void	inetprint __P((struct in_addr *, int, char *, int));
819b50d902SRodney W. Grimes 
829b50d902SRodney W. Grimes /*
839b50d902SRodney W. Grimes  * Print a summary of connections related to an Internet
849b50d902SRodney W. Grimes  * protocol.  For TCP, also give state of connection.
859b50d902SRodney W. Grimes  * Listening processes (aflag) are suppressed unless the
869b50d902SRodney W. Grimes  * -a (all) flag is specified.
879b50d902SRodney W. Grimes  */
889b50d902SRodney W. Grimes void
894f81ef50SGarrett Wollman protopr(proto, name)
904f81ef50SGarrett Wollman 	u_long proto;		/* for sysctl version we pass proto # */
919b50d902SRodney W. Grimes 	char *name;
929b50d902SRodney W. Grimes {
939b50d902SRodney W. Grimes 	int istcp;
949b50d902SRodney W. Grimes 	static int first = 1;
954f81ef50SGarrett Wollman 	char *buf;
964f81ef50SGarrett Wollman 	const char *mibvar;
974f81ef50SGarrett Wollman 	struct tcpcb *tp;
984f81ef50SGarrett Wollman 	struct inpcb *inp;
994f81ef50SGarrett Wollman 	struct xinpgen *xig, *oxig;
1004f81ef50SGarrett Wollman 	struct xsocket *so;
1014f81ef50SGarrett Wollman 	size_t len;
1029b50d902SRodney W. Grimes 
1034f81ef50SGarrett Wollman 	istcp = 0;
1044f81ef50SGarrett Wollman 	switch (proto) {
1054f81ef50SGarrett Wollman 	case IPPROTO_TCP:
1064f81ef50SGarrett Wollman 		istcp = 1;
1074f81ef50SGarrett Wollman 		mibvar = "net.inet.tcp.pcblist";
1084f81ef50SGarrett Wollman 		break;
1094f81ef50SGarrett Wollman 	case IPPROTO_UDP:
1104f81ef50SGarrett Wollman 		mibvar = "net.inet.udp.pcblist";
1114f81ef50SGarrett Wollman 		break;
1124f81ef50SGarrett Wollman 	case IPPROTO_DIVERT:
1134f81ef50SGarrett Wollman 		mibvar = "net.inet.divert.pcblist";
1144f81ef50SGarrett Wollman 		break;
1154f81ef50SGarrett Wollman 	default:
1164f81ef50SGarrett Wollman 		mibvar = "net.inet.raw.pcblist";
1174f81ef50SGarrett Wollman 		break;
1184f81ef50SGarrett Wollman 	}
1194f81ef50SGarrett Wollman 	len = 0;
1204f81ef50SGarrett Wollman 	if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
1214f81ef50SGarrett Wollman 		if (errno != ENOENT)
1224f81ef50SGarrett Wollman 			warn("sysctl: %s", mibvar);
1239b50d902SRodney W. Grimes 		return;
1243aa80b1dSDavid Greenman 	}
1254f81ef50SGarrett Wollman 	if ((buf = malloc(len)) == 0) {
1264f81ef50SGarrett Wollman 		warn("malloc %lu bytes", (u_long)len);
1274f81ef50SGarrett Wollman 		return;
1289b50d902SRodney W. Grimes 	}
1294f81ef50SGarrett Wollman 	if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
1304f81ef50SGarrett Wollman 		warn("sysctl: %s", mibvar);
1314f81ef50SGarrett Wollman 		free(buf);
1324f81ef50SGarrett Wollman 		return;
1334f81ef50SGarrett Wollman 	}
1344f81ef50SGarrett Wollman 
1354f81ef50SGarrett Wollman 	oxig = xig = (struct xinpgen *)buf;
1364f81ef50SGarrett Wollman 	for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
1374f81ef50SGarrett Wollman 	     xig->xig_len > sizeof(struct xinpgen);
1384f81ef50SGarrett Wollman 	     xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
1399b50d902SRodney W. Grimes 		if (istcp) {
1404f81ef50SGarrett Wollman 			tp = &((struct xtcpcb *)xig)->xt_tp;
1414f81ef50SGarrett Wollman 			inp = &((struct xtcpcb *)xig)->xt_inp;
1424f81ef50SGarrett Wollman 			so = &((struct xtcpcb *)xig)->xt_socket;
1434f81ef50SGarrett Wollman 		} else {
1444f81ef50SGarrett Wollman 			inp = &((struct xinpcb *)xig)->xi_inp;
1454f81ef50SGarrett Wollman 			so = &((struct xinpcb *)xig)->xi_socket;
1469b50d902SRodney W. Grimes 		}
1474f81ef50SGarrett Wollman 
1484f81ef50SGarrett Wollman 		/* Ignore sockets for protocols other than the desired one. */
1494f81ef50SGarrett Wollman 		if (so->xso_protocol != proto)
1504f81ef50SGarrett Wollman 			continue;
1514f81ef50SGarrett Wollman 
1524f81ef50SGarrett Wollman 		/* Ignore PCBs which were freed during copyout. */
1534f81ef50SGarrett Wollman 		if (inp->inp_gencnt > oxig->xig_gen)
1544f81ef50SGarrett Wollman 			continue;
1554f81ef50SGarrett Wollman 
1564f81ef50SGarrett Wollman 		if (!aflag && inet_lnaof(inp->inp_laddr) == INADDR_ANY)
1574f81ef50SGarrett Wollman 			continue;
1584f81ef50SGarrett Wollman 
1599b50d902SRodney W. Grimes 		if (first) {
1609b50d902SRodney W. Grimes 			printf("Active Internet connections");
1619b50d902SRodney W. Grimes 			if (aflag)
1629b50d902SRodney W. Grimes 				printf(" (including servers)");
1639b50d902SRodney W. Grimes 			putchar('\n');
1649b50d902SRodney W. Grimes 			if (Aflag)
1654f81ef50SGarrett Wollman 				printf("%-8.8s ", "Socket");
1669b50d902SRodney W. Grimes 			printf(Aflag ?
1679b50d902SRodney W. Grimes 				"%-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n" :
1689b50d902SRodney W. Grimes 				"%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
1699b50d902SRodney W. Grimes 				"Proto", "Recv-Q", "Send-Q",
1709b50d902SRodney W. Grimes 				"Local Address", "Foreign Address", "(state)");
1719b50d902SRodney W. Grimes 			first = 0;
1729b50d902SRodney W. Grimes 		}
1739b50d902SRodney W. Grimes 		if (Aflag)
1744f81ef50SGarrett Wollman 			printf("%8lx ", (u_long)so->so_pcb);
1754f81ef50SGarrett Wollman 		printf("%-5.5s %6ld %6ld ", name, so->so_rcv.sb_cc,
1764f81ef50SGarrett Wollman 			so->so_snd.sb_cc);
1778d612dd2SPoul-Henning Kamp 		if (nflag) {
1784f81ef50SGarrett Wollman 			inetprint(&inp->inp_laddr, (int)inp->inp_lport,
1798d612dd2SPoul-Henning Kamp 			    name, 1);
1804f81ef50SGarrett Wollman 			inetprint(&inp->inp_faddr, (int)inp->inp_fport,
1818d612dd2SPoul-Henning Kamp 			    name, 1);
1824f81ef50SGarrett Wollman 		} else if (inp->inp_flags & INP_ANONPORT) {
1834f81ef50SGarrett Wollman 			inetprint(&inp->inp_laddr, (int)inp->inp_lport,
1848d612dd2SPoul-Henning Kamp 			    name, 1);
1854f81ef50SGarrett Wollman 			inetprint(&inp->inp_faddr, (int)inp->inp_fport,
1868d612dd2SPoul-Henning Kamp 			    name, 0);
1878d612dd2SPoul-Henning Kamp 		} else {
1884f81ef50SGarrett Wollman 			inetprint(&inp->inp_laddr, (int)inp->inp_lport,
1898d612dd2SPoul-Henning Kamp 			    name, 0);
1904f81ef50SGarrett Wollman 			inetprint(&inp->inp_faddr, (int)inp->inp_fport,
1914f81ef50SGarrett Wollman 			    name, inp->inp_lport != inp->inp_fport);
1928d612dd2SPoul-Henning Kamp 		}
1939b50d902SRodney W. Grimes 		if (istcp) {
1944f81ef50SGarrett Wollman 			if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
1954f81ef50SGarrett Wollman 				printf(" %d", tp->t_state);
1969a94a597SGarrett Wollman                       else {
1974f81ef50SGarrett Wollman 				printf(" %s", tcpstates[tp->t_state]);
198513822ddSAdam David #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
1999a94a597SGarrett Wollman                               /* Show T/TCP `hidden state' */
2004f81ef50SGarrett Wollman                               if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
2019a94a597SGarrett Wollman                                       putchar('*');
202513822ddSAdam David #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
2039a94a597SGarrett Wollman                       }
2049b50d902SRodney W. Grimes 		}
2059b50d902SRodney W. Grimes 		putchar('\n');
2069b50d902SRodney W. Grimes 	}
2074f81ef50SGarrett Wollman 	if (xig != oxig && xig->xig_gen != oxig->xig_gen) {
2084f81ef50SGarrett Wollman 		if (oxig->xig_count > xig->xig_count) {
2094f81ef50SGarrett Wollman 			printf("Some %s sockets may have been deleted.\n",
2104f81ef50SGarrett Wollman 			       name);
2114f81ef50SGarrett Wollman 		} else if (oxig->xig_count < xig->xig_count) {
2124f81ef50SGarrett Wollman 			printf("Some %s sockets may have been created.\n",
2134f81ef50SGarrett Wollman 			       name);
2144f81ef50SGarrett Wollman 		} else {
2154f81ef50SGarrett Wollman 			printf("Some %s sockets may have been created or deleted",
2164f81ef50SGarrett Wollman 			       name);
2174f81ef50SGarrett Wollman 		}
2184f81ef50SGarrett Wollman 	}
2194f81ef50SGarrett Wollman 	free(buf);
2209b50d902SRodney W. Grimes }
2219b50d902SRodney W. Grimes 
2229b50d902SRodney W. Grimes /*
2239b50d902SRodney W. Grimes  * Dump TCP statistics structure.
2249b50d902SRodney W. Grimes  */
2259b50d902SRodney W. Grimes void
2269b50d902SRodney W. Grimes tcp_stats(off, name)
2279b50d902SRodney W. Grimes 	u_long off;
2289b50d902SRodney W. Grimes 	char *name;
2299b50d902SRodney W. Grimes {
2309b50d902SRodney W. Grimes 	struct tcpstat tcpstat;
2314f81ef50SGarrett Wollman 	size_t len = sizeof tcpstat;
2329b50d902SRodney W. Grimes 
2334f81ef50SGarrett Wollman 	if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) {
2344f81ef50SGarrett Wollman 		warn("sysctl: net.inet.tcp.stats");
2359b50d902SRodney W. Grimes 		return;
2364f81ef50SGarrett Wollman 	}
2374f81ef50SGarrett Wollman 
2389b50d902SRodney W. Grimes 	printf ("%s:\n", name);
2399b50d902SRodney W. Grimes 
2409b50d902SRodney W. Grimes #define	p(f, m) if (tcpstat.f || sflag <= 1) \
2419b50d902SRodney W. Grimes     printf(m, tcpstat.f, plural(tcpstat.f))
24222694ebaSBruce Evans #define	p1a(f, m) if (tcpstat.f || sflag <= 1) \
24322694ebaSBruce Evans     printf(m, tcpstat.f)
2449b50d902SRodney W. Grimes #define	p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
2459b50d902SRodney W. Grimes     printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
24622694ebaSBruce Evans #define	p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
24722694ebaSBruce Evans     printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
2489b50d902SRodney W. Grimes #define	p3(f, m) if (tcpstat.f || sflag <= 1) \
2499b50d902SRodney W. Grimes     printf(m, tcpstat.f, plurales(tcpstat.f))
2509b50d902SRodney W. Grimes 
251e1fb4daaSPaul Traina 	p(tcps_sndtotal, "\t%lu packet%s sent\n");
2529b50d902SRodney W. Grimes 	p2(tcps_sndpack,tcps_sndbyte,
253e1fb4daaSPaul Traina 		"\t\t%lu data packet%s (%lu byte%s)\n");
2549b50d902SRodney W. Grimes 	p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
255e1fb4daaSPaul Traina 		"\t\t%lu data packet%s (%lu byte%s) retransmitted\n");
256e1fb4daaSPaul Traina 	p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n");
25722694ebaSBruce Evans 	p2a(tcps_sndacks, tcps_delack,
258e1fb4daaSPaul Traina 		"\t\t%lu ack-only packet%s (%lu delayed)\n");
259e1fb4daaSPaul Traina 	p(tcps_sndurg, "\t\t%lu URG only packet%s\n");
260e1fb4daaSPaul Traina 	p(tcps_sndprobe, "\t\t%lu window probe packet%s\n");
261e1fb4daaSPaul Traina 	p(tcps_sndwinup, "\t\t%lu window update packet%s\n");
262e1fb4daaSPaul Traina 	p(tcps_sndctrl, "\t\t%lu control packet%s\n");
263e1fb4daaSPaul Traina 	p(tcps_rcvtotal, "\t%lu packet%s received\n");
264e1fb4daaSPaul Traina 	p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n");
265e1fb4daaSPaul Traina 	p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n");
266e1fb4daaSPaul Traina 	p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n");
2679b50d902SRodney W. Grimes 	p2(tcps_rcvpack, tcps_rcvbyte,
268e1fb4daaSPaul Traina 		"\t\t%lu packet%s (%lu byte%s) received in-sequence\n");
2699b50d902SRodney W. Grimes 	p2(tcps_rcvduppack, tcps_rcvdupbyte,
270e1fb4daaSPaul Traina 		"\t\t%lu completely duplicate packet%s (%lu byte%s)\n");
271e1fb4daaSPaul Traina 	p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n");
2729b50d902SRodney W. Grimes 	p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
273e1fb4daaSPaul Traina 		"\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n");
2749b50d902SRodney W. Grimes 	p2(tcps_rcvoopack, tcps_rcvoobyte,
275e1fb4daaSPaul Traina 		"\t\t%lu out-of-order packet%s (%lu byte%s)\n");
2769b50d902SRodney W. Grimes 	p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
277e1fb4daaSPaul Traina 		"\t\t%lu packet%s (%lu byte%s) of data after window\n");
278e1fb4daaSPaul Traina 	p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n");
279e1fb4daaSPaul Traina 	p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n");
280e1fb4daaSPaul Traina 	p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n");
281e1fb4daaSPaul Traina 	p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n");
282e1fb4daaSPaul Traina 	p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n");
28322694ebaSBruce Evans 	p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n");
284e1fb4daaSPaul Traina 	p(tcps_connattempt, "\t%lu connection request%s\n");
285e1fb4daaSPaul Traina 	p(tcps_accepts, "\t%lu connection accept%s\n");
286e1fb4daaSPaul Traina 	p(tcps_badsyn, "\t%lu bad connection attempt%s\n");
287e1fb4daaSPaul Traina 	p(tcps_listendrop, "\t%lu listen queue overflow%s\n");
288e1fb4daaSPaul Traina 	p(tcps_connects, "\t%lu connection%s established (including accepts)\n");
2899b50d902SRodney W. Grimes 	p2(tcps_closed, tcps_drops,
290e1fb4daaSPaul Traina 		"\t%lu connection%s closed (including %lu drop%s)\n");
291e1fb4daaSPaul Traina 	p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n");
292861b1828SGarrett Wollman 	p(tcps_cachedrttvar,
293e1fb4daaSPaul Traina 	  "\t\t%lu connection%s updated cached RTT variance on close\n");
294861b1828SGarrett Wollman 	p(tcps_cachedssthresh,
295e1fb4daaSPaul Traina 	  "\t\t%lu connection%s updated cached ssthresh on close\n");
296e1fb4daaSPaul Traina 	p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n");
2979b50d902SRodney W. Grimes 	p2(tcps_rttupdated, tcps_segstimed,
298e1fb4daaSPaul Traina 		"\t%lu segment%s updated rtt (of %lu attempt%s)\n");
299e1fb4daaSPaul Traina 	p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n");
300e1fb4daaSPaul Traina 	p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n");
301e1fb4daaSPaul Traina 	p(tcps_persisttimeo, "\t%lu persist timeout%s\n");
302e1fb4daaSPaul Traina 	p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n");
303e1fb4daaSPaul Traina 	p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n");
304e1fb4daaSPaul Traina 	p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n");
305e1fb4daaSPaul Traina 	p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n");
306e1fb4daaSPaul Traina 	p(tcps_predack, "\t%lu correct ACK header prediction%s\n");
307e1fb4daaSPaul Traina 	p(tcps_preddat, "\t%lu correct data packet header prediction%s\n");
3089b50d902SRodney W. Grimes #undef p
30922694ebaSBruce Evans #undef p1a
3109b50d902SRodney W. Grimes #undef p2
31122694ebaSBruce Evans #undef p2a
3129b50d902SRodney W. Grimes #undef p3
3139b50d902SRodney W. Grimes }
3149b50d902SRodney W. Grimes 
3159b50d902SRodney W. Grimes /*
3169b50d902SRodney W. Grimes  * Dump UDP statistics structure.
3179b50d902SRodney W. Grimes  */
3189b50d902SRodney W. Grimes void
3199b50d902SRodney W. Grimes udp_stats(off, name)
3209b50d902SRodney W. Grimes 	u_long off;
3219b50d902SRodney W. Grimes 	char *name;
3229b50d902SRodney W. Grimes {
3239b50d902SRodney W. Grimes 	struct udpstat udpstat;
3244f81ef50SGarrett Wollman 	size_t len = sizeof udpstat;
3259b50d902SRodney W. Grimes 	u_long delivered;
3269b50d902SRodney W. Grimes 
3274f81ef50SGarrett Wollman 	if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 0, 0) < 0) {
3284f81ef50SGarrett Wollman 		warn("sysctl: net.inet.udp.stats");
3299b50d902SRodney W. Grimes 		return;
3304f81ef50SGarrett Wollman 	}
3314f81ef50SGarrett Wollman 
3329b50d902SRodney W. Grimes 	printf("%s:\n", name);
3339b50d902SRodney W. Grimes #define	p(f, m) if (udpstat.f || sflag <= 1) \
3349b50d902SRodney W. Grimes     printf(m, udpstat.f, plural(udpstat.f))
33522694ebaSBruce Evans #define	p1a(f, m) if (udpstat.f || sflag <= 1) \
33622694ebaSBruce Evans     printf(m, udpstat.f)
3377d56c0eeSAlexander Langer 	p(udps_ipackets, "\t%lu datagram%s received\n");
33822694ebaSBruce Evans 	p1a(udps_hdrops, "\t%lu with incomplete header\n");
33922694ebaSBruce Evans 	p1a(udps_badlen, "\t%lu with bad data length field\n");
34022694ebaSBruce Evans 	p1a(udps_badsum, "\t%lu with bad checksum\n");
34122694ebaSBruce Evans 	p1a(udps_noport, "\t%lu dropped due to no socket\n");
34222694ebaSBruce Evans 	p(udps_noportbcast,
34322694ebaSBruce Evans 	    "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
34422694ebaSBruce Evans 	p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
34522694ebaSBruce Evans 	p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n");
3469b50d902SRodney W. Grimes 	delivered = udpstat.udps_ipackets -
3479b50d902SRodney W. Grimes 		    udpstat.udps_hdrops -
3489b50d902SRodney W. Grimes 		    udpstat.udps_badlen -
3499b50d902SRodney W. Grimes 		    udpstat.udps_badsum -
3509b50d902SRodney W. Grimes 		    udpstat.udps_noport -
3519b50d902SRodney W. Grimes 		    udpstat.udps_noportbcast -
3529b50d902SRodney W. Grimes 		    udpstat.udps_fullsock;
3539b50d902SRodney W. Grimes 	if (delivered || sflag <= 1)
3547d56c0eeSAlexander Langer 		printf("\t%lu delivered\n", delivered);
3557d56c0eeSAlexander Langer 	p(udps_opackets, "\t%lu datagram%s output\n");
3569b50d902SRodney W. Grimes #undef p
35722694ebaSBruce Evans #undef p1a
3589b50d902SRodney W. Grimes }
3599b50d902SRodney W. Grimes 
3609b50d902SRodney W. Grimes /*
3619b50d902SRodney W. Grimes  * Dump IP statistics structure.
3629b50d902SRodney W. Grimes  */
3639b50d902SRodney W. Grimes void
3649b50d902SRodney W. Grimes ip_stats(off, name)
3659b50d902SRodney W. Grimes 	u_long off;
3669b50d902SRodney W. Grimes 	char *name;
3679b50d902SRodney W. Grimes {
3689b50d902SRodney W. Grimes 	struct ipstat ipstat;
3694f81ef50SGarrett Wollman 	size_t len = sizeof ipstat;
3709b50d902SRodney W. Grimes 
3714f81ef50SGarrett Wollman 	if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, 0, 0) < 0) {
3724f81ef50SGarrett Wollman 		warn("sysctl: net.inet.ip.stats");
3739b50d902SRodney W. Grimes 		return;
3744f81ef50SGarrett Wollman 	}
3754f81ef50SGarrett Wollman 
3769b50d902SRodney W. Grimes 	printf("%s:\n", name);
3779b50d902SRodney W. Grimes 
3789b50d902SRodney W. Grimes #define	p(f, m) if (ipstat.f || sflag <= 1) \
3799b50d902SRodney W. Grimes     printf(m, ipstat.f, plural(ipstat.f))
38022694ebaSBruce Evans #define	p1a(f, m) if (ipstat.f || sflag <= 1) \
38122694ebaSBruce Evans     printf(m, ipstat.f)
3829b50d902SRodney W. Grimes 
3837d56c0eeSAlexander Langer 	p(ips_total, "\t%lu total packet%s received\n");
3847d56c0eeSAlexander Langer 	p(ips_badsum, "\t%lu bad header checksum%s\n");
38522694ebaSBruce Evans 	p1a(ips_toosmall, "\t%lu with size smaller than minimum\n");
38622694ebaSBruce Evans 	p1a(ips_tooshort, "\t%lu with data size < data length\n");
38722694ebaSBruce Evans 	p1a(ips_badhlen, "\t%lu with header length < data size\n");
38822694ebaSBruce Evans 	p1a(ips_badlen, "\t%lu with data length < header length\n");
38922694ebaSBruce Evans 	p1a(ips_badoptions, "\t%lu with bad options\n");
39022694ebaSBruce Evans 	p1a(ips_badvers, "\t%lu with incorrect version number\n");
3917d56c0eeSAlexander Langer 	p(ips_fragments, "\t%lu fragment%s received\n");
3927d56c0eeSAlexander Langer 	p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
3937d56c0eeSAlexander Langer 	p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
3947d56c0eeSAlexander Langer 	p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
3957d56c0eeSAlexander Langer 	p(ips_delivered, "\t%lu packet%s for this host\n");
3967d56c0eeSAlexander Langer 	p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
397958d6f7fSPierre Beyssac 	p(ips_forward, "\t%lu packet%s forwarded");
398958d6f7fSPierre Beyssac 	p(ips_fastforward, " (%lu packet%s fast forwarded)");
399958d6f7fSPierre Beyssac 	if (ipstat.ips_forward || sflag <= 1)
400958d6f7fSPierre Beyssac 		putchar('\n');
4017d56c0eeSAlexander Langer 	p(ips_cantforward, "\t%lu packet%s not forwardable\n");
402a5969f5fSGarrett Wollman 	p(ips_notmember,
403a5969f5fSGarrett Wollman 	  "\t%lu packet%s received for unknown multicast group\n");
4047d56c0eeSAlexander Langer 	p(ips_redirectsent, "\t%lu redirect%s sent\n");
4057d56c0eeSAlexander Langer 	p(ips_localout, "\t%lu packet%s sent from this host\n");
4067d56c0eeSAlexander Langer 	p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
407a5969f5fSGarrett Wollman 	p(ips_odropped,
408a5969f5fSGarrett Wollman 	  "\t%lu output packet%s dropped due to no bufs, etc.\n");
4097d56c0eeSAlexander Langer 	p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
4107d56c0eeSAlexander Langer 	p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
4117d56c0eeSAlexander Langer 	p(ips_ofragments, "\t%lu fragment%s created\n");
4127d56c0eeSAlexander Langer 	p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
4139b50d902SRodney W. Grimes #undef p
41422694ebaSBruce Evans #undef p1a
4159b50d902SRodney W. Grimes }
4169b50d902SRodney W. Grimes 
4179b50d902SRodney W. Grimes static	char *icmpnames[] = {
4189b50d902SRodney W. Grimes 	"echo reply",
4199b50d902SRodney W. Grimes 	"#1",
4209b50d902SRodney W. Grimes 	"#2",
4219b50d902SRodney W. Grimes 	"destination unreachable",
4229b50d902SRodney W. Grimes 	"source quench",
4239b50d902SRodney W. Grimes 	"routing redirect",
4249b50d902SRodney W. Grimes 	"#6",
4259b50d902SRodney W. Grimes 	"#7",
4269b50d902SRodney W. Grimes 	"echo",
4277b46dd00SGarrett Wollman 	"router advertisement",
4287b46dd00SGarrett Wollman 	"router solicitation",
4299b50d902SRodney W. Grimes 	"time exceeded",
4309b50d902SRodney W. Grimes 	"parameter problem",
4319b50d902SRodney W. Grimes 	"time stamp",
4329b50d902SRodney W. Grimes 	"time stamp reply",
4339b50d902SRodney W. Grimes 	"information request",
4349b50d902SRodney W. Grimes 	"information request reply",
4359b50d902SRodney W. Grimes 	"address mask request",
4369b50d902SRodney W. Grimes 	"address mask reply",
4379b50d902SRodney W. Grimes };
4389b50d902SRodney W. Grimes 
4399b50d902SRodney W. Grimes /*
4409b50d902SRodney W. Grimes  * Dump ICMP statistics.
4419b50d902SRodney W. Grimes  */
4429b50d902SRodney W. Grimes void
4439b50d902SRodney W. Grimes icmp_stats(off, name)
4449b50d902SRodney W. Grimes 	u_long off;
4459b50d902SRodney W. Grimes 	char *name;
4469b50d902SRodney W. Grimes {
4479b50d902SRodney W. Grimes 	struct icmpstat icmpstat;
4484e00c309SGarrett Wollman 	int i, first;
4494e00c309SGarrett Wollman 	int mib[4];		/* CTL_NET + PF_INET + IPPROTO_ICMP + req */
4504e00c309SGarrett Wollman 	size_t len;
4519b50d902SRodney W. Grimes 
4524e00c309SGarrett Wollman 	mib[0] = CTL_NET;
4534e00c309SGarrett Wollman 	mib[1] = PF_INET;
4544e00c309SGarrett Wollman 	mib[2] = IPPROTO_ICMP;
4554e00c309SGarrett Wollman 	mib[3] = ICMPCTL_STATS;
4564e00c309SGarrett Wollman 
4574e00c309SGarrett Wollman 	len = sizeof icmpstat;
4584e00c309SGarrett Wollman 	memset(&icmpstat, 0, len);
4594e00c309SGarrett Wollman 	if (sysctl(mib, 4, &icmpstat, &len, (void *)0, 0) < 0)
4604e00c309SGarrett Wollman 		return;		/* XXX should complain, but not traditional */
4614e00c309SGarrett Wollman 
4629b50d902SRodney W. Grimes 	printf("%s:\n", name);
4639b50d902SRodney W. Grimes 
4649b50d902SRodney W. Grimes #define	p(f, m) if (icmpstat.f || sflag <= 1) \
4659b50d902SRodney W. Grimes     printf(m, icmpstat.f, plural(icmpstat.f))
46622694ebaSBruce Evans #define	p1a(f, m) if (icmpstat.f || sflag <= 1) \
46722694ebaSBruce Evans     printf(m, icmpstat.f)
4689b50d902SRodney W. Grimes 
4697d56c0eeSAlexander Langer 	p(icps_error, "\t%lu call%s to icmp_error\n");
4709b50d902SRodney W. Grimes 	p(icps_oldicmp,
4717d56c0eeSAlexander Langer 	    "\t%lu error%s not generated 'cuz old message was icmp\n");
4729b50d902SRodney W. Grimes 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
4739b50d902SRodney W. Grimes 		if (icmpstat.icps_outhist[i] != 0) {
4749b50d902SRodney W. Grimes 			if (first) {
4759b50d902SRodney W. Grimes 				printf("\tOutput histogram:\n");
4769b50d902SRodney W. Grimes 				first = 0;
4779b50d902SRodney W. Grimes 			}
4787d56c0eeSAlexander Langer 			printf("\t\t%s: %lu\n", icmpnames[i],
4799b50d902SRodney W. Grimes 				icmpstat.icps_outhist[i]);
4809b50d902SRodney W. Grimes 		}
4817d56c0eeSAlexander Langer 	p(icps_badcode, "\t%lu message%s with bad code fields\n");
4827d56c0eeSAlexander Langer 	p(icps_tooshort, "\t%lu message%s < minimum length\n");
4837d56c0eeSAlexander Langer 	p(icps_checksum, "\t%lu bad checksum%s\n");
4847d56c0eeSAlexander Langer 	p(icps_badlen, "\t%lu message%s with bad length\n");
48522694ebaSBruce Evans 	p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n");
48622694ebaSBruce Evans 	p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n");
4879b50d902SRodney W. Grimes 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
4889b50d902SRodney W. Grimes 		if (icmpstat.icps_inhist[i] != 0) {
4899b50d902SRodney W. Grimes 			if (first) {
4909b50d902SRodney W. Grimes 				printf("\tInput histogram:\n");
4919b50d902SRodney W. Grimes 				first = 0;
4929b50d902SRodney W. Grimes 			}
4937d56c0eeSAlexander Langer 			printf("\t\t%s: %lu\n", icmpnames[i],
4949b50d902SRodney W. Grimes 				icmpstat.icps_inhist[i]);
4959b50d902SRodney W. Grimes 		}
4967d56c0eeSAlexander Langer 	p(icps_reflect, "\t%lu message response%s generated\n");
4979b50d902SRodney W. Grimes #undef p
49822694ebaSBruce Evans #undef p1a
4994e00c309SGarrett Wollman 	mib[3] = ICMPCTL_MASKREPL;
5004e00c309SGarrett Wollman 	len = sizeof i;
5014e00c309SGarrett Wollman 	if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0)
5024e00c309SGarrett Wollman 		return;
5034e00c309SGarrett Wollman 	printf("\tICMP address mask responses are %sabled\n",
5044e00c309SGarrett Wollman 	       i ? "en" : "dis");
5059b50d902SRodney W. Grimes }
5069b50d902SRodney W. Grimes 
5079b50d902SRodney W. Grimes /*
5089b50d902SRodney W. Grimes  * Dump IGMP statistics structure.
5099b50d902SRodney W. Grimes  */
5109b50d902SRodney W. Grimes void
5119b50d902SRodney W. Grimes igmp_stats(off, name)
5129b50d902SRodney W. Grimes 	u_long off;
5139b50d902SRodney W. Grimes 	char *name;
5149b50d902SRodney W. Grimes {
5159b50d902SRodney W. Grimes 	struct igmpstat igmpstat;
5164f81ef50SGarrett Wollman 	size_t len = sizeof igmpstat;
5179b50d902SRodney W. Grimes 
5184f81ef50SGarrett Wollman 	if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len, 0, 0) < 0) {
5194f81ef50SGarrett Wollman 		warn("sysctl: net.inet.igmp.stats");
5209b50d902SRodney W. Grimes 		return;
5214f81ef50SGarrett Wollman 	}
5224f81ef50SGarrett Wollman 
5239b50d902SRodney W. Grimes 	printf("%s:\n", name);
5249b50d902SRodney W. Grimes 
5259b50d902SRodney W. Grimes #define	p(f, m) if (igmpstat.f || sflag <= 1) \
5269b50d902SRodney W. Grimes     printf(m, igmpstat.f, plural(igmpstat.f))
5279b50d902SRodney W. Grimes #define	py(f, m) if (igmpstat.f || sflag <= 1) \
5289b50d902SRodney W. Grimes     printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
5299b50d902SRodney W. Grimes 	p(igps_rcv_total, "\t%u message%s received\n");
5309b50d902SRodney W. Grimes         p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
5319b50d902SRodney W. Grimes         p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
5329b50d902SRodney W. Grimes         py(igps_rcv_queries, "\t%u membership quer%s received\n");
5339b50d902SRodney W. Grimes         py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
5349b50d902SRodney W. Grimes         p(igps_rcv_reports, "\t%u membership report%s received\n");
5359b50d902SRodney W. Grimes         p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
5369b50d902SRodney W. Grimes         p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
5379b50d902SRodney W. Grimes         p(igps_snd_reports, "\t%u membership report%s sent\n");
5389b50d902SRodney W. Grimes #undef p
5399b50d902SRodney W. Grimes #undef py
5409b50d902SRodney W. Grimes }
5419b50d902SRodney W. Grimes 
5429b50d902SRodney W. Grimes /*
5439b50d902SRodney W. Grimes  * Pretty print an Internet address (net address + port).
5449b50d902SRodney W. Grimes  */
5459b50d902SRodney W. Grimes void
5468d612dd2SPoul-Henning Kamp inetprint(in, port, proto,numeric)
5479b50d902SRodney W. Grimes 	register struct in_addr *in;
5489b50d902SRodney W. Grimes 	int port;
5499b50d902SRodney W. Grimes 	char *proto;
5508d612dd2SPoul-Henning Kamp 	int numeric;
5519b50d902SRodney W. Grimes {
5529b50d902SRodney W. Grimes 	struct servent *sp = 0;
5539b50d902SRodney W. Grimes 	char line[80], *cp;
5549b50d902SRodney W. Grimes 	int width;
5559b50d902SRodney W. Grimes 
5568d612dd2SPoul-Henning Kamp 	sprintf(line, "%.*s.", (Aflag && !numeric) ? 12 : 16, inetname(in));
5579b50d902SRodney W. Grimes 	cp = index(line, '\0');
5588d612dd2SPoul-Henning Kamp 	if (!numeric && port)
5599b50d902SRodney W. Grimes 		sp = getservbyport((int)port, proto);
5609b50d902SRodney W. Grimes 	if (sp || port == 0)
5611ef69972SAndrey A. Chernov 		sprintf(cp, "%.15s", sp ? sp->s_name : "*");
5629b50d902SRodney W. Grimes 	else
5639b50d902SRodney W. Grimes 		sprintf(cp, "%d", ntohs((u_short)port));
5649b50d902SRodney W. Grimes 	width = Aflag ? 18 : 22;
5659b50d902SRodney W. Grimes 	printf(" %-*.*s", width, width, line);
5669b50d902SRodney W. Grimes }
5679b50d902SRodney W. Grimes 
5689b50d902SRodney W. Grimes /*
5699b50d902SRodney W. Grimes  * Construct an Internet address representation.
5709b50d902SRodney W. Grimes  * If the nflag has been supplied, give
5719b50d902SRodney W. Grimes  * numeric value, otherwise try for symbolic name.
5729b50d902SRodney W. Grimes  */
5739b50d902SRodney W. Grimes char *
5749b50d902SRodney W. Grimes inetname(inp)
5759b50d902SRodney W. Grimes 	struct in_addr *inp;
5769b50d902SRodney W. Grimes {
5779b50d902SRodney W. Grimes 	register char *cp;
5789a1f6729SWarner Losh 	static char line[MAXHOSTNAMELEN + 1];
5799b50d902SRodney W. Grimes 	struct hostent *hp;
5809b50d902SRodney W. Grimes 	struct netent *np;
5819b50d902SRodney W. Grimes 
5829b50d902SRodney W. Grimes 	cp = 0;
5839b50d902SRodney W. Grimes 	if (!nflag && inp->s_addr != INADDR_ANY) {
5849b50d902SRodney W. Grimes 		int net = inet_netof(*inp);
5859b50d902SRodney W. Grimes 		int lna = inet_lnaof(*inp);
5869b50d902SRodney W. Grimes 
5879b50d902SRodney W. Grimes 		if (lna == INADDR_ANY) {
5889b50d902SRodney W. Grimes 			np = getnetbyaddr(net, AF_INET);
5899b50d902SRodney W. Grimes 			if (np)
5909b50d902SRodney W. Grimes 				cp = np->n_name;
5919b50d902SRodney W. Grimes 		}
5929b50d902SRodney W. Grimes 		if (cp == 0) {
5939b50d902SRodney W. Grimes 			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
5949b50d902SRodney W. Grimes 			if (hp) {
5959b50d902SRodney W. Grimes 				cp = hp->h_name;
5969c437f50SPeter Wemm 				trimdomain(cp);
5979b50d902SRodney W. Grimes 			}
5989b50d902SRodney W. Grimes 		}
5999b50d902SRodney W. Grimes 	}
6009b50d902SRodney W. Grimes 	if (inp->s_addr == INADDR_ANY)
6019b50d902SRodney W. Grimes 		strcpy(line, "*");
6029a1f6729SWarner Losh 	else if (cp) {
6039a1f6729SWarner Losh 		strncpy(line, cp, sizeof(line) - 1);
6049a1f6729SWarner Losh 		line[sizeof(line) - 1] = '\0';
6059a1f6729SWarner Losh 	} else {
6069b50d902SRodney W. Grimes 		inp->s_addr = ntohl(inp->s_addr);
60722694ebaSBruce Evans #define C(x)	((u_int)((x) & 0xff))
60822694ebaSBruce Evans 		sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
6099b50d902SRodney W. Grimes 		    C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
6109b50d902SRodney W. Grimes 	}
6119b50d902SRodney W. Grimes 	return (line);
6129b50d902SRodney W. Grimes }
613