xref: /freebsd/usr.bin/netstat/inet.c (revision 4f81ef5056fc1a979f29a160f2a04a3a377dd681)
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[] =
394f81ef50SGarrett Wollman 	"$Id: inet.c,v 1.26 1997/08/25 16:57:05 wollman 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))
2429b50d902SRodney W. Grimes #define	p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
2439b50d902SRodney W. Grimes     printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
2449b50d902SRodney W. Grimes #define	p3(f, m) if (tcpstat.f || sflag <= 1) \
2459b50d902SRodney W. Grimes     printf(m, tcpstat.f, plurales(tcpstat.f))
2469b50d902SRodney W. Grimes 
247e1fb4daaSPaul Traina 	p(tcps_sndtotal, "\t%lu packet%s sent\n");
2489b50d902SRodney W. Grimes 	p2(tcps_sndpack,tcps_sndbyte,
249e1fb4daaSPaul Traina 		"\t\t%lu data packet%s (%lu byte%s)\n");
2509b50d902SRodney W. Grimes 	p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
251e1fb4daaSPaul Traina 		"\t\t%lu data packet%s (%lu byte%s) retransmitted\n");
252e1fb4daaSPaul Traina 	p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n");
2539b50d902SRodney W. Grimes 	p2(tcps_sndacks, tcps_delack,
254e1fb4daaSPaul Traina 		"\t\t%lu ack-only packet%s (%lu delayed)\n");
255e1fb4daaSPaul Traina 	p(tcps_sndurg, "\t\t%lu URG only packet%s\n");
256e1fb4daaSPaul Traina 	p(tcps_sndprobe, "\t\t%lu window probe packet%s\n");
257e1fb4daaSPaul Traina 	p(tcps_sndwinup, "\t\t%lu window update packet%s\n");
258e1fb4daaSPaul Traina 	p(tcps_sndctrl, "\t\t%lu control packet%s\n");
259e1fb4daaSPaul Traina 	p(tcps_rcvtotal, "\t%lu packet%s received\n");
260e1fb4daaSPaul Traina 	p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n");
261e1fb4daaSPaul Traina 	p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n");
262e1fb4daaSPaul Traina 	p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n");
2639b50d902SRodney W. Grimes 	p2(tcps_rcvpack, tcps_rcvbyte,
264e1fb4daaSPaul Traina 		"\t\t%lu packet%s (%lu byte%s) received in-sequence\n");
2659b50d902SRodney W. Grimes 	p2(tcps_rcvduppack, tcps_rcvdupbyte,
266e1fb4daaSPaul Traina 		"\t\t%lu completely duplicate packet%s (%lu byte%s)\n");
267e1fb4daaSPaul Traina 	p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n");
2689b50d902SRodney W. Grimes 	p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
269e1fb4daaSPaul Traina 		"\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n");
2709b50d902SRodney W. Grimes 	p2(tcps_rcvoopack, tcps_rcvoobyte,
271e1fb4daaSPaul Traina 		"\t\t%lu out-of-order packet%s (%lu byte%s)\n");
2729b50d902SRodney W. Grimes 	p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
273e1fb4daaSPaul Traina 		"\t\t%lu packet%s (%lu byte%s) of data after window\n");
274e1fb4daaSPaul Traina 	p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n");
275e1fb4daaSPaul Traina 	p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n");
276e1fb4daaSPaul Traina 	p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n");
277e1fb4daaSPaul Traina 	p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n");
278e1fb4daaSPaul Traina 	p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n");
279e1fb4daaSPaul Traina 	p(tcps_rcvshort, "\t\t%lu discarded because packet too short\n");
280e1fb4daaSPaul Traina 	p(tcps_connattempt, "\t%lu connection request%s\n");
281e1fb4daaSPaul Traina 	p(tcps_accepts, "\t%lu connection accept%s\n");
282e1fb4daaSPaul Traina 	p(tcps_badsyn, "\t%lu bad connection attempt%s\n");
283e1fb4daaSPaul Traina 	p(tcps_listendrop, "\t%lu listen queue overflow%s\n");
284e1fb4daaSPaul Traina 	p(tcps_connects, "\t%lu connection%s established (including accepts)\n");
2859b50d902SRodney W. Grimes 	p2(tcps_closed, tcps_drops,
286e1fb4daaSPaul Traina 		"\t%lu connection%s closed (including %lu drop%s)\n");
287e1fb4daaSPaul Traina 	p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n");
288861b1828SGarrett Wollman 	p(tcps_cachedrttvar,
289e1fb4daaSPaul Traina 	  "\t\t%lu connection%s updated cached RTT variance on close\n");
290861b1828SGarrett Wollman 	p(tcps_cachedssthresh,
291e1fb4daaSPaul Traina 	  "\t\t%lu connection%s updated cached ssthresh on close\n");
292e1fb4daaSPaul Traina 	p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n");
2939b50d902SRodney W. Grimes 	p2(tcps_rttupdated, tcps_segstimed,
294e1fb4daaSPaul Traina 		"\t%lu segment%s updated rtt (of %lu attempt%s)\n");
295e1fb4daaSPaul Traina 	p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n");
296e1fb4daaSPaul Traina 	p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n");
297e1fb4daaSPaul Traina 	p(tcps_persisttimeo, "\t%lu persist timeout%s\n");
298e1fb4daaSPaul Traina 	p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n");
299e1fb4daaSPaul Traina 	p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n");
300e1fb4daaSPaul Traina 	p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n");
301e1fb4daaSPaul Traina 	p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n");
302e1fb4daaSPaul Traina 	p(tcps_predack, "\t%lu correct ACK header prediction%s\n");
303e1fb4daaSPaul Traina 	p(tcps_preddat, "\t%lu correct data packet header prediction%s\n");
3049b50d902SRodney W. Grimes #undef p
3059b50d902SRodney W. Grimes #undef p2
3069b50d902SRodney W. Grimes #undef p3
3079b50d902SRodney W. Grimes }
3089b50d902SRodney W. Grimes 
3099b50d902SRodney W. Grimes /*
3109b50d902SRodney W. Grimes  * Dump UDP statistics structure.
3119b50d902SRodney W. Grimes  */
3129b50d902SRodney W. Grimes void
3139b50d902SRodney W. Grimes udp_stats(off, name)
3149b50d902SRodney W. Grimes 	u_long off;
3159b50d902SRodney W. Grimes 	char *name;
3169b50d902SRodney W. Grimes {
3179b50d902SRodney W. Grimes 	struct udpstat udpstat;
3184f81ef50SGarrett Wollman 	size_t len = sizeof udpstat;
3199b50d902SRodney W. Grimes 	u_long delivered;
3209b50d902SRodney W. Grimes 
3214f81ef50SGarrett Wollman 	if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 0, 0) < 0) {
3224f81ef50SGarrett Wollman 		warn("sysctl: net.inet.udp.stats");
3239b50d902SRodney W. Grimes 		return;
3244f81ef50SGarrett Wollman 	}
3254f81ef50SGarrett Wollman 
3269b50d902SRodney W. Grimes 	printf("%s:\n", name);
3279b50d902SRodney W. Grimes #define	p(f, m) if (udpstat.f || sflag <= 1) \
3289b50d902SRodney W. Grimes     printf(m, udpstat.f, plural(udpstat.f))
3297d56c0eeSAlexander Langer 	p(udps_ipackets, "\t%lu datagram%s received\n");
3307d56c0eeSAlexander Langer 	p(udps_hdrops, "\t%lu with incomplete header\n");
3317d56c0eeSAlexander Langer 	p(udps_badlen, "\t%lu with bad data length field\n");
3327d56c0eeSAlexander Langer 	p(udps_badsum, "\t%lu with bad checksum\n");
3337d56c0eeSAlexander Langer 	p(udps_noport, "\t%lu dropped due to no socket\n");
3347d56c0eeSAlexander Langer 	p(udps_noportbcast, "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
3357d56c0eeSAlexander Langer 	p(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
336759b7d75SGarrett Wollman 	p(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n");
3379b50d902SRodney W. Grimes 	delivered = udpstat.udps_ipackets -
3389b50d902SRodney W. Grimes 		    udpstat.udps_hdrops -
3399b50d902SRodney W. Grimes 		    udpstat.udps_badlen -
3409b50d902SRodney W. Grimes 		    udpstat.udps_badsum -
3419b50d902SRodney W. Grimes 		    udpstat.udps_noport -
3429b50d902SRodney W. Grimes 		    udpstat.udps_noportbcast -
3439b50d902SRodney W. Grimes 		    udpstat.udps_fullsock;
3449b50d902SRodney W. Grimes 	if (delivered || sflag <= 1)
3457d56c0eeSAlexander Langer 		printf("\t%lu delivered\n", delivered);
3467d56c0eeSAlexander Langer 	p(udps_opackets, "\t%lu datagram%s output\n");
3479b50d902SRodney W. Grimes #undef p
3489b50d902SRodney W. Grimes }
3499b50d902SRodney W. Grimes 
3509b50d902SRodney W. Grimes /*
3519b50d902SRodney W. Grimes  * Dump IP statistics structure.
3529b50d902SRodney W. Grimes  */
3539b50d902SRodney W. Grimes void
3549b50d902SRodney W. Grimes ip_stats(off, name)
3559b50d902SRodney W. Grimes 	u_long off;
3569b50d902SRodney W. Grimes 	char *name;
3579b50d902SRodney W. Grimes {
3589b50d902SRodney W. Grimes 	struct ipstat ipstat;
3594f81ef50SGarrett Wollman 	size_t len = sizeof ipstat;
3609b50d902SRodney W. Grimes 
3614f81ef50SGarrett Wollman 	if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, 0, 0) < 0) {
3624f81ef50SGarrett Wollman 		warn("sysctl: net.inet.ip.stats");
3639b50d902SRodney W. Grimes 		return;
3644f81ef50SGarrett Wollman 	}
3654f81ef50SGarrett Wollman 
3669b50d902SRodney W. Grimes 	printf("%s:\n", name);
3679b50d902SRodney W. Grimes 
3689b50d902SRodney W. Grimes #define	p(f, m) if (ipstat.f || sflag <= 1) \
3699b50d902SRodney W. Grimes     printf(m, ipstat.f, plural(ipstat.f))
3709b50d902SRodney W. Grimes 
3717d56c0eeSAlexander Langer 	p(ips_total, "\t%lu total packet%s received\n");
3727d56c0eeSAlexander Langer 	p(ips_badsum, "\t%lu bad header checksum%s\n");
3737d56c0eeSAlexander Langer 	p(ips_toosmall, "\t%lu with size smaller than minimum\n");
3747d56c0eeSAlexander Langer 	p(ips_tooshort, "\t%lu with data size < data length\n");
3757d56c0eeSAlexander Langer 	p(ips_badhlen, "\t%lu with header length < data size\n");
3767d56c0eeSAlexander Langer 	p(ips_badlen, "\t%lu with data length < header length\n");
3777d56c0eeSAlexander Langer 	p(ips_badoptions, "\t%lu with bad options\n");
3787d56c0eeSAlexander Langer 	p(ips_badvers, "\t%lu with incorrect version number\n");
3797d56c0eeSAlexander Langer 	p(ips_fragments, "\t%lu fragment%s received\n");
3807d56c0eeSAlexander Langer 	p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
3817d56c0eeSAlexander Langer 	p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
3827d56c0eeSAlexander Langer 	p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
3837d56c0eeSAlexander Langer 	p(ips_delivered, "\t%lu packet%s for this host\n");
3847d56c0eeSAlexander Langer 	p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
3857d56c0eeSAlexander Langer 	p(ips_forward, "\t%lu packet%s forwarded\n");
3867d56c0eeSAlexander Langer 	p(ips_cantforward, "\t%lu packet%s not forwardable\n");
387a5969f5fSGarrett Wollman 	p(ips_notmember,
388a5969f5fSGarrett Wollman 	  "\t%lu packet%s received for unknown multicast group\n");
3897d56c0eeSAlexander Langer 	p(ips_redirectsent, "\t%lu redirect%s sent\n");
3907d56c0eeSAlexander Langer 	p(ips_localout, "\t%lu packet%s sent from this host\n");
3917d56c0eeSAlexander Langer 	p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
392a5969f5fSGarrett Wollman 	p(ips_odropped,
393a5969f5fSGarrett Wollman 	  "\t%lu output packet%s dropped due to no bufs, etc.\n");
3947d56c0eeSAlexander Langer 	p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
3957d56c0eeSAlexander Langer 	p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
3967d56c0eeSAlexander Langer 	p(ips_ofragments, "\t%lu fragment%s created\n");
3977d56c0eeSAlexander Langer 	p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
3989b50d902SRodney W. Grimes #undef p
3999b50d902SRodney W. Grimes }
4009b50d902SRodney W. Grimes 
4019b50d902SRodney W. Grimes static	char *icmpnames[] = {
4029b50d902SRodney W. Grimes 	"echo reply",
4039b50d902SRodney W. Grimes 	"#1",
4049b50d902SRodney W. Grimes 	"#2",
4059b50d902SRodney W. Grimes 	"destination unreachable",
4069b50d902SRodney W. Grimes 	"source quench",
4079b50d902SRodney W. Grimes 	"routing redirect",
4089b50d902SRodney W. Grimes 	"#6",
4099b50d902SRodney W. Grimes 	"#7",
4109b50d902SRodney W. Grimes 	"echo",
4117b46dd00SGarrett Wollman 	"router advertisement",
4127b46dd00SGarrett Wollman 	"router solicitation",
4139b50d902SRodney W. Grimes 	"time exceeded",
4149b50d902SRodney W. Grimes 	"parameter problem",
4159b50d902SRodney W. Grimes 	"time stamp",
4169b50d902SRodney W. Grimes 	"time stamp reply",
4179b50d902SRodney W. Grimes 	"information request",
4189b50d902SRodney W. Grimes 	"information request reply",
4199b50d902SRodney W. Grimes 	"address mask request",
4209b50d902SRodney W. Grimes 	"address mask reply",
4219b50d902SRodney W. Grimes };
4229b50d902SRodney W. Grimes 
4239b50d902SRodney W. Grimes /*
4249b50d902SRodney W. Grimes  * Dump ICMP statistics.
4259b50d902SRodney W. Grimes  */
4269b50d902SRodney W. Grimes void
4279b50d902SRodney W. Grimes icmp_stats(off, name)
4289b50d902SRodney W. Grimes 	u_long off;
4299b50d902SRodney W. Grimes 	char *name;
4309b50d902SRodney W. Grimes {
4319b50d902SRodney W. Grimes 	struct icmpstat icmpstat;
4324e00c309SGarrett Wollman 	int i, first;
4334e00c309SGarrett Wollman 	int mib[4];		/* CTL_NET + PF_INET + IPPROTO_ICMP + req */
4344e00c309SGarrett Wollman 	size_t len;
4359b50d902SRodney W. Grimes 
4364e00c309SGarrett Wollman 	mib[0] = CTL_NET;
4374e00c309SGarrett Wollman 	mib[1] = PF_INET;
4384e00c309SGarrett Wollman 	mib[2] = IPPROTO_ICMP;
4394e00c309SGarrett Wollman 	mib[3] = ICMPCTL_STATS;
4404e00c309SGarrett Wollman 
4414e00c309SGarrett Wollman 	len = sizeof icmpstat;
4424e00c309SGarrett Wollman 	memset(&icmpstat, 0, len);
4434e00c309SGarrett Wollman 	if (sysctl(mib, 4, &icmpstat, &len, (void *)0, 0) < 0)
4444e00c309SGarrett Wollman 		return;		/* XXX should complain, but not traditional */
4454e00c309SGarrett Wollman 
4469b50d902SRodney W. Grimes 	printf("%s:\n", name);
4479b50d902SRodney W. Grimes 
4489b50d902SRodney W. Grimes #define	p(f, m) if (icmpstat.f || sflag <= 1) \
4499b50d902SRodney W. Grimes     printf(m, icmpstat.f, plural(icmpstat.f))
4509b50d902SRodney W. Grimes 
4517d56c0eeSAlexander Langer 	p(icps_error, "\t%lu call%s to icmp_error\n");
4529b50d902SRodney W. Grimes 	p(icps_oldicmp,
4537d56c0eeSAlexander Langer 	    "\t%lu error%s not generated 'cuz old message was icmp\n");
4549b50d902SRodney W. Grimes 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
4559b50d902SRodney W. Grimes 		if (icmpstat.icps_outhist[i] != 0) {
4569b50d902SRodney W. Grimes 			if (first) {
4579b50d902SRodney W. Grimes 				printf("\tOutput histogram:\n");
4589b50d902SRodney W. Grimes 				first = 0;
4599b50d902SRodney W. Grimes 			}
4607d56c0eeSAlexander Langer 			printf("\t\t%s: %lu\n", icmpnames[i],
4619b50d902SRodney W. Grimes 				icmpstat.icps_outhist[i]);
4629b50d902SRodney W. Grimes 		}
4637d56c0eeSAlexander Langer 	p(icps_badcode, "\t%lu message%s with bad code fields\n");
4647d56c0eeSAlexander Langer 	p(icps_tooshort, "\t%lu message%s < minimum length\n");
4657d56c0eeSAlexander Langer 	p(icps_checksum, "\t%lu bad checksum%s\n");
4667d56c0eeSAlexander Langer 	p(icps_badlen, "\t%lu message%s with bad length\n");
4674e00c309SGarrett Wollman 	p(icps_bmcastecho, "\t%lu multicast echo requests ignored\n");
4684e00c309SGarrett Wollman 	p(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n");
4699b50d902SRodney W. Grimes 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
4709b50d902SRodney W. Grimes 		if (icmpstat.icps_inhist[i] != 0) {
4719b50d902SRodney W. Grimes 			if (first) {
4729b50d902SRodney W. Grimes 				printf("\tInput histogram:\n");
4739b50d902SRodney W. Grimes 				first = 0;
4749b50d902SRodney W. Grimes 			}
4757d56c0eeSAlexander Langer 			printf("\t\t%s: %lu\n", icmpnames[i],
4769b50d902SRodney W. Grimes 				icmpstat.icps_inhist[i]);
4779b50d902SRodney W. Grimes 		}
4787d56c0eeSAlexander Langer 	p(icps_reflect, "\t%lu message response%s generated\n");
4799b50d902SRodney W. Grimes #undef p
4804e00c309SGarrett Wollman 	mib[3] = ICMPCTL_MASKREPL;
4814e00c309SGarrett Wollman 	len = sizeof i;
4824e00c309SGarrett Wollman 	if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0)
4834e00c309SGarrett Wollman 		return;
4844e00c309SGarrett Wollman 	printf("\tICMP address mask responses are %sabled\n",
4854e00c309SGarrett Wollman 	       i ? "en" : "dis");
4869b50d902SRodney W. Grimes }
4879b50d902SRodney W. Grimes 
4889b50d902SRodney W. Grimes /*
4899b50d902SRodney W. Grimes  * Dump IGMP statistics structure.
4909b50d902SRodney W. Grimes  */
4919b50d902SRodney W. Grimes void
4929b50d902SRodney W. Grimes igmp_stats(off, name)
4939b50d902SRodney W. Grimes 	u_long off;
4949b50d902SRodney W. Grimes 	char *name;
4959b50d902SRodney W. Grimes {
4969b50d902SRodney W. Grimes 	struct igmpstat igmpstat;
4974f81ef50SGarrett Wollman 	size_t len = sizeof igmpstat;
4989b50d902SRodney W. Grimes 
4994f81ef50SGarrett Wollman 	if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len, 0, 0) < 0) {
5004f81ef50SGarrett Wollman 		warn("sysctl: net.inet.igmp.stats");
5019b50d902SRodney W. Grimes 		return;
5024f81ef50SGarrett Wollman 	}
5034f81ef50SGarrett Wollman 
5049b50d902SRodney W. Grimes 	printf("%s:\n", name);
5059b50d902SRodney W. Grimes 
5069b50d902SRodney W. Grimes #define	p(f, m) if (igmpstat.f || sflag <= 1) \
5079b50d902SRodney W. Grimes     printf(m, igmpstat.f, plural(igmpstat.f))
5089b50d902SRodney W. Grimes #define	py(f, m) if (igmpstat.f || sflag <= 1) \
5099b50d902SRodney W. Grimes     printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
5109b50d902SRodney W. Grimes 	p(igps_rcv_total, "\t%u message%s received\n");
5119b50d902SRodney W. Grimes         p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
5129b50d902SRodney W. Grimes         p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
5139b50d902SRodney W. Grimes         py(igps_rcv_queries, "\t%u membership quer%s received\n");
5149b50d902SRodney W. Grimes         py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
5159b50d902SRodney W. Grimes         p(igps_rcv_reports, "\t%u membership report%s received\n");
5169b50d902SRodney W. Grimes         p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
5179b50d902SRodney W. Grimes         p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
5189b50d902SRodney W. Grimes         p(igps_snd_reports, "\t%u membership report%s sent\n");
5199b50d902SRodney W. Grimes #undef p
5209b50d902SRodney W. Grimes #undef py
5219b50d902SRodney W. Grimes }
5229b50d902SRodney W. Grimes 
5239b50d902SRodney W. Grimes /*
5249b50d902SRodney W. Grimes  * Pretty print an Internet address (net address + port).
5259b50d902SRodney W. Grimes  */
5269b50d902SRodney W. Grimes void
5278d612dd2SPoul-Henning Kamp inetprint(in, port, proto,numeric)
5289b50d902SRodney W. Grimes 	register struct in_addr *in;
5299b50d902SRodney W. Grimes 	int port;
5309b50d902SRodney W. Grimes 	char *proto;
5318d612dd2SPoul-Henning Kamp 	int numeric;
5329b50d902SRodney W. Grimes {
5339b50d902SRodney W. Grimes 	struct servent *sp = 0;
5349b50d902SRodney W. Grimes 	char line[80], *cp;
5359b50d902SRodney W. Grimes 	int width;
5369b50d902SRodney W. Grimes 
5378d612dd2SPoul-Henning Kamp 	sprintf(line, "%.*s.", (Aflag && !numeric) ? 12 : 16, inetname(in));
5389b50d902SRodney W. Grimes 	cp = index(line, '\0');
5398d612dd2SPoul-Henning Kamp 	if (!numeric && port)
5409b50d902SRodney W. Grimes 		sp = getservbyport((int)port, proto);
5419b50d902SRodney W. Grimes 	if (sp || port == 0)
5421ef69972SAndrey A. Chernov 		sprintf(cp, "%.15s", sp ? sp->s_name : "*");
5439b50d902SRodney W. Grimes 	else
5449b50d902SRodney W. Grimes 		sprintf(cp, "%d", ntohs((u_short)port));
5459b50d902SRodney W. Grimes 	width = Aflag ? 18 : 22;
5469b50d902SRodney W. Grimes 	printf(" %-*.*s", width, width, line);
5479b50d902SRodney W. Grimes }
5489b50d902SRodney W. Grimes 
5499b50d902SRodney W. Grimes /*
5509b50d902SRodney W. Grimes  * Construct an Internet address representation.
5519b50d902SRodney W. Grimes  * If the nflag has been supplied, give
5529b50d902SRodney W. Grimes  * numeric value, otherwise try for symbolic name.
5539b50d902SRodney W. Grimes  */
5549b50d902SRodney W. Grimes char *
5559b50d902SRodney W. Grimes inetname(inp)
5569b50d902SRodney W. Grimes 	struct in_addr *inp;
5579b50d902SRodney W. Grimes {
5589b50d902SRodney W. Grimes 	register char *cp;
5599b50d902SRodney W. Grimes 	static char line[50];
5609b50d902SRodney W. Grimes 	struct hostent *hp;
5619b50d902SRodney W. Grimes 	struct netent *np;
5629b50d902SRodney W. Grimes 
5639b50d902SRodney W. Grimes 	cp = 0;
5649b50d902SRodney W. Grimes 	if (!nflag && inp->s_addr != INADDR_ANY) {
5659b50d902SRodney W. Grimes 		int net = inet_netof(*inp);
5669b50d902SRodney W. Grimes 		int lna = inet_lnaof(*inp);
5679b50d902SRodney W. Grimes 
5689b50d902SRodney W. Grimes 		if (lna == INADDR_ANY) {
5699b50d902SRodney W. Grimes 			np = getnetbyaddr(net, AF_INET);
5709b50d902SRodney W. Grimes 			if (np)
5719b50d902SRodney W. Grimes 				cp = np->n_name;
5729b50d902SRodney W. Grimes 		}
5739b50d902SRodney W. Grimes 		if (cp == 0) {
5749b50d902SRodney W. Grimes 			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
5759b50d902SRodney W. Grimes 			if (hp) {
5769b50d902SRodney W. Grimes 				cp = hp->h_name;
5779c437f50SPeter Wemm 				trimdomain(cp);
5789b50d902SRodney W. Grimes 			}
5799b50d902SRodney W. Grimes 		}
5809b50d902SRodney W. Grimes 	}
5819b50d902SRodney W. Grimes 	if (inp->s_addr == INADDR_ANY)
5829b50d902SRodney W. Grimes 		strcpy(line, "*");
5839b50d902SRodney W. Grimes 	else if (cp)
5849b50d902SRodney W. Grimes 		strcpy(line, cp);
5859b50d902SRodney W. Grimes 	else {
5869b50d902SRodney W. Grimes 		inp->s_addr = ntohl(inp->s_addr);
5879b50d902SRodney W. Grimes #define C(x)	((x) & 0xff)
5887d56c0eeSAlexander Langer 		sprintf(line, "%lu.%lu.%lu.%lu", C(inp->s_addr >> 24),
5899b50d902SRodney W. Grimes 		    C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
5909b50d902SRodney W. Grimes 	}
5919b50d902SRodney W. Grimes 	return (line);
5929b50d902SRodney W. Grimes }
593