xref: /freebsd/usr.bin/netstat/inet.c (revision 05ddff6e303e3257a7ea77f89fe5f04e861d29d4)
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
3505ddff6eSPeter Wemm static char sccsid[] = "@(#)inet.c	8.5 (Berkeley) 5/24/95";
369b50d902SRodney W. Grimes #endif /* not lint */
379b50d902SRodney W. Grimes 
389b50d902SRodney W. Grimes #include <sys/param.h>
399b50d902SRodney W. Grimes #include <sys/socket.h>
409b50d902SRodney W. Grimes #include <sys/socketvar.h>
419b50d902SRodney W. Grimes #include <sys/mbuf.h>
429b50d902SRodney W. Grimes #include <sys/protosw.h>
437452c2a5SDavid Greenman #include <sys/queue.h>
449b50d902SRodney W. Grimes 
459b50d902SRodney W. Grimes #include <net/route.h>
469b50d902SRodney W. Grimes #include <netinet/in.h>
479b50d902SRodney W. Grimes #include <netinet/in_systm.h>
489b50d902SRodney W. Grimes #include <netinet/ip.h>
499b50d902SRodney W. Grimes #include <netinet/in_pcb.h>
509b50d902SRodney W. Grimes #include <netinet/ip_icmp.h>
519b50d902SRodney W. Grimes #include <netinet/icmp_var.h>
529b50d902SRodney W. Grimes #include <netinet/igmp_var.h>
539b50d902SRodney W. Grimes #include <netinet/ip_var.h>
549b50d902SRodney W. Grimes #include <netinet/tcp.h>
559b50d902SRodney W. Grimes #include <netinet/tcpip.h>
569b50d902SRodney W. Grimes #include <netinet/tcp_seq.h>
579b50d902SRodney W. Grimes #define TCPSTATES
589b50d902SRodney W. Grimes #include <netinet/tcp_fsm.h>
599b50d902SRodney W. Grimes #include <netinet/tcp_timer.h>
609b50d902SRodney W. Grimes #include <netinet/tcp_var.h>
619b50d902SRodney W. Grimes #include <netinet/tcp_debug.h>
629b50d902SRodney W. Grimes #include <netinet/udp.h>
639b50d902SRodney W. Grimes #include <netinet/udp_var.h>
649b50d902SRodney W. Grimes 
659b50d902SRodney W. Grimes #include <arpa/inet.h>
669b50d902SRodney W. Grimes #include <netdb.h>
679b50d902SRodney W. Grimes #include <stdio.h>
689b50d902SRodney W. Grimes #include <string.h>
699b50d902SRodney W. Grimes #include <unistd.h>
709b50d902SRodney W. Grimes #include "netstat.h"
719b50d902SRodney W. Grimes 
729b50d902SRodney W. Grimes struct	inpcb inpcb;
739b50d902SRodney W. Grimes struct	tcpcb tcpcb;
749b50d902SRodney W. Grimes struct	socket sockb;
759b50d902SRodney W. Grimes 
769b50d902SRodney W. Grimes char	*inetname __P((struct in_addr *));
779b50d902SRodney W. Grimes void	inetprint __P((struct in_addr *, int, char *));
789b50d902SRodney W. Grimes 
799b50d902SRodney W. Grimes /*
809b50d902SRodney W. Grimes  * Print a summary of connections related to an Internet
819b50d902SRodney W. Grimes  * protocol.  For TCP, also give state of connection.
829b50d902SRodney W. Grimes  * Listening processes (aflag) are suppressed unless the
839b50d902SRodney W. Grimes  * -a (all) flag is specified.
849b50d902SRodney W. Grimes  */
859b50d902SRodney W. Grimes void
869b50d902SRodney W. Grimes protopr(off, name)
879b50d902SRodney W. Grimes 	u_long off;
889b50d902SRodney W. Grimes 	char *name;
899b50d902SRodney W. Grimes {
907452c2a5SDavid Greenman 	struct inpcbhead head;
919b50d902SRodney W. Grimes 	register struct inpcb *prev, *next;
929b50d902SRodney W. Grimes 	int istcp;
939b50d902SRodney W. Grimes 	static int first = 1;
949b50d902SRodney W. Grimes 
959b50d902SRodney W. Grimes 	if (off == 0)
969b50d902SRodney W. Grimes 		return;
977452c2a5SDavid Greenman 
989b50d902SRodney W. Grimes 	istcp = strcmp(name, "tcp") == 0;
997452c2a5SDavid Greenman 	kread(off, (char *)&head, sizeof (struct inpcbhead));
1009b50d902SRodney W. Grimes 	prev = (struct inpcb *)off;
1017452c2a5SDavid Greenman 
102a9d6f1a7SDavid Greenman 	for (next = head.lh_first; next != NULL; next = inpcb.inp_list.le_next) {
1033aa80b1dSDavid Greenman 		if (kread((u_long)next, (char *)&inpcb, sizeof (inpcb))) {
1043aa80b1dSDavid Greenman 			printf("???\n");
1053aa80b1dSDavid Greenman 			break;
1063aa80b1dSDavid Greenman 		}
1079b50d902SRodney W. Grimes 		if (!aflag &&
1089b50d902SRodney W. Grimes 		  inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) {
1099b50d902SRodney W. Grimes 			prev = next;
1109b50d902SRodney W. Grimes 			continue;
1119b50d902SRodney W. Grimes 		}
1123aa80b1dSDavid Greenman 		if (kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb))) {
1133aa80b1dSDavid Greenman 			printf("???\n");
1143aa80b1dSDavid Greenman 			break;
1153aa80b1dSDavid Greenman 		};
1169b50d902SRodney W. Grimes 		if (istcp) {
1173aa80b1dSDavid Greenman 			if (kread((u_long)inpcb.inp_ppcb,
1183aa80b1dSDavid Greenman 			    (char *)&tcpcb, sizeof (tcpcb))) {
1193aa80b1dSDavid Greenman 				printf("???\n");
1203aa80b1dSDavid Greenman 				break;
1213aa80b1dSDavid Greenman 			};
1229b50d902SRodney W. Grimes 		}
1239b50d902SRodney W. Grimes 		if (first) {
1249b50d902SRodney W. Grimes 			printf("Active Internet connections");
1259b50d902SRodney W. Grimes 			if (aflag)
1269b50d902SRodney W. Grimes 				printf(" (including servers)");
1279b50d902SRodney W. Grimes 			putchar('\n');
1289b50d902SRodney W. Grimes 			if (Aflag)
1299b50d902SRodney W. Grimes 				printf("%-8.8s ", "PCB");
1309b50d902SRodney W. Grimes 			printf(Aflag ?
1319b50d902SRodney W. Grimes 				"%-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n" :
1329b50d902SRodney W. Grimes 				"%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
1339b50d902SRodney W. Grimes 				"Proto", "Recv-Q", "Send-Q",
1349b50d902SRodney W. Grimes 				"Local Address", "Foreign Address", "(state)");
1359b50d902SRodney W. Grimes 			first = 0;
1369b50d902SRodney W. Grimes 		}
1379b50d902SRodney W. Grimes 		if (Aflag)
1389b50d902SRodney W. Grimes 			if (istcp)
1399b50d902SRodney W. Grimes 				printf("%8x ", inpcb.inp_ppcb);
1409b50d902SRodney W. Grimes 			else
1419b50d902SRodney W. Grimes 				printf("%8x ", next);
1429b50d902SRodney W. Grimes 		printf("%-5.5s %6d %6d ", name, sockb.so_rcv.sb_cc,
1439b50d902SRodney W. Grimes 			sockb.so_snd.sb_cc);
1449b50d902SRodney W. Grimes 		inetprint(&inpcb.inp_laddr, (int)inpcb.inp_lport, name);
1459b50d902SRodney W. Grimes 		inetprint(&inpcb.inp_faddr, (int)inpcb.inp_fport, name);
1469b50d902SRodney W. Grimes 		if (istcp) {
1479b50d902SRodney W. Grimes 			if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
1489b50d902SRodney W. Grimes 				printf(" %d", tcpcb.t_state);
1499a94a597SGarrett Wollman                       else {
1509b50d902SRodney W. Grimes 				printf(" %s", tcpstates[tcpcb.t_state]);
151513822ddSAdam David #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
1529a94a597SGarrett Wollman                               /* Show T/TCP `hidden state' */
1539a94a597SGarrett Wollman                               if (tcpcb.t_flags & (TF_NEEDSYN|TF_NEEDFIN))
1549a94a597SGarrett Wollman                                       putchar('*');
155513822ddSAdam David #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
1569a94a597SGarrett Wollman                       }
1579b50d902SRodney W. Grimes 		}
1589b50d902SRodney W. Grimes 		putchar('\n');
1599b50d902SRodney W. Grimes 		prev = next;
1609b50d902SRodney W. Grimes 	}
1619b50d902SRodney W. Grimes }
1629b50d902SRodney W. Grimes 
1639b50d902SRodney W. Grimes /*
1649b50d902SRodney W. Grimes  * Dump TCP statistics structure.
1659b50d902SRodney W. Grimes  */
1669b50d902SRodney W. Grimes void
1679b50d902SRodney W. Grimes tcp_stats(off, name)
1689b50d902SRodney W. Grimes 	u_long off;
1699b50d902SRodney W. Grimes 	char *name;
1709b50d902SRodney W. Grimes {
1719b50d902SRodney W. Grimes 	struct tcpstat tcpstat;
1729b50d902SRodney W. Grimes 
1739b50d902SRodney W. Grimes 	if (off == 0)
1749b50d902SRodney W. Grimes 		return;
1759b50d902SRodney W. Grimes 	printf ("%s:\n", name);
1769b50d902SRodney W. Grimes 	kread(off, (char *)&tcpstat, sizeof (tcpstat));
1779b50d902SRodney W. Grimes 
1789b50d902SRodney W. Grimes #define	p(f, m) if (tcpstat.f || sflag <= 1) \
1799b50d902SRodney W. Grimes     printf(m, tcpstat.f, plural(tcpstat.f))
1809b50d902SRodney W. Grimes #define	p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
1819b50d902SRodney W. Grimes     printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
1829b50d902SRodney W. Grimes #define	p3(f, m) if (tcpstat.f || sflag <= 1) \
1839b50d902SRodney W. Grimes     printf(m, tcpstat.f, plurales(tcpstat.f))
1849b50d902SRodney W. Grimes 
1859b50d902SRodney W. Grimes 	p(tcps_sndtotal, "\t%d packet%s sent\n");
1869b50d902SRodney W. Grimes 	p2(tcps_sndpack,tcps_sndbyte,
1879b50d902SRodney W. Grimes 		"\t\t%d data packet%s (%d byte%s)\n");
1889b50d902SRodney W. Grimes 	p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
1899b50d902SRodney W. Grimes 		"\t\t%d data packet%s (%d byte%s) retransmitted\n");
190231bfb09SGarrett Wollman 	p(tcps_mturesent, "\t\t%d resend%s initiated by MTU discovery\n");
1919b50d902SRodney W. Grimes 	p2(tcps_sndacks, tcps_delack,
1929b50d902SRodney W. Grimes 		"\t\t%d ack-only packet%s (%d delayed)\n");
1939b50d902SRodney W. Grimes 	p(tcps_sndurg, "\t\t%d URG only packet%s\n");
1949b50d902SRodney W. Grimes 	p(tcps_sndprobe, "\t\t%d window probe packet%s\n");
1959b50d902SRodney W. Grimes 	p(tcps_sndwinup, "\t\t%d window update packet%s\n");
1969b50d902SRodney W. Grimes 	p(tcps_sndctrl, "\t\t%d control packet%s\n");
1979b50d902SRodney W. Grimes 	p(tcps_rcvtotal, "\t%d packet%s received\n");
1989b50d902SRodney W. Grimes 	p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%d ack%s (for %d byte%s)\n");
1999b50d902SRodney W. Grimes 	p(tcps_rcvdupack, "\t\t%d duplicate ack%s\n");
2009b50d902SRodney W. Grimes 	p(tcps_rcvacktoomuch, "\t\t%d ack%s for unsent data\n");
2019b50d902SRodney W. Grimes 	p2(tcps_rcvpack, tcps_rcvbyte,
2029b50d902SRodney W. Grimes 		"\t\t%d packet%s (%d byte%s) received in-sequence\n");
2039b50d902SRodney W. Grimes 	p2(tcps_rcvduppack, tcps_rcvdupbyte,
2049b50d902SRodney W. Grimes 		"\t\t%d completely duplicate packet%s (%d byte%s)\n");
2059b50d902SRodney W. Grimes 	p(tcps_pawsdrop, "\t\t%d old duplicate packet%s\n");
2069b50d902SRodney W. Grimes 	p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
2079b50d902SRodney W. Grimes 		"\t\t%d packet%s with some dup. data (%d byte%s duped)\n");
2089b50d902SRodney W. Grimes 	p2(tcps_rcvoopack, tcps_rcvoobyte,
2099b50d902SRodney W. Grimes 		"\t\t%d out-of-order packet%s (%d byte%s)\n");
2109b50d902SRodney W. Grimes 	p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
2119b50d902SRodney W. Grimes 		"\t\t%d packet%s (%d byte%s) of data after window\n");
2129b50d902SRodney W. Grimes 	p(tcps_rcvwinprobe, "\t\t%d window probe%s\n");
2139b50d902SRodney W. Grimes 	p(tcps_rcvwinupd, "\t\t%d window update packet%s\n");
2149b50d902SRodney W. Grimes 	p(tcps_rcvafterclose, "\t\t%d packet%s received after close\n");
2159b50d902SRodney W. Grimes 	p(tcps_rcvbadsum, "\t\t%d discarded for bad checksum%s\n");
2169b50d902SRodney W. Grimes 	p(tcps_rcvbadoff, "\t\t%d discarded for bad header offset field%s\n");
2179b50d902SRodney W. Grimes 	p(tcps_rcvshort, "\t\t%d discarded because packet too short\n");
2189b50d902SRodney W. Grimes 	p(tcps_connattempt, "\t%d connection request%s\n");
2199b50d902SRodney W. Grimes 	p(tcps_accepts, "\t%d connection accept%s\n");
22005ddff6eSPeter Wemm 	p(tcps_badsyn, "\t%d bad connection attempt%s\n");
2219b50d902SRodney W. Grimes 	p(tcps_connects, "\t%d connection%s established (including accepts)\n");
2229b50d902SRodney W. Grimes 	p2(tcps_closed, tcps_drops,
2239b50d902SRodney W. Grimes 		"\t%d connection%s closed (including %d drop%s)\n");
2247b4315a7SGarrett Wollman 	p(tcps_cachedrtt, "\t\t%d connection%s updated cached RTT on close\n");
225861b1828SGarrett Wollman 	p(tcps_cachedrttvar,
2267b4315a7SGarrett Wollman 	  "\t\t%d connection%s updated cached RTT variance on close\n");
227861b1828SGarrett Wollman 	p(tcps_cachedssthresh,
228861b1828SGarrett Wollman 	  "\t\t%d connection%s updated cached ssthresh on close\n");
2299b50d902SRodney W. Grimes 	p(tcps_conndrops, "\t%d embryonic connection%s dropped\n");
2309b50d902SRodney W. Grimes 	p2(tcps_rttupdated, tcps_segstimed,
2319b50d902SRodney W. Grimes 		"\t%d segment%s updated rtt (of %d attempt%s)\n");
2329b50d902SRodney W. Grimes 	p(tcps_rexmttimeo, "\t%d retransmit timeout%s\n");
2339b50d902SRodney W. Grimes 	p(tcps_timeoutdrop, "\t\t%d connection%s dropped by rexmit timeout\n");
2349b50d902SRodney W. Grimes 	p(tcps_persisttimeo, "\t%d persist timeout%s\n");
23589d7f49aSDavid Greenman 	p(tcps_persistdrop, "\t\t%d connection%s dropped by persist timeout\n");
2369b50d902SRodney W. Grimes 	p(tcps_keeptimeo, "\t%d keepalive timeout%s\n");
2379b50d902SRodney W. Grimes 	p(tcps_keepprobe, "\t\t%d keepalive probe%s sent\n");
2389b50d902SRodney W. Grimes 	p(tcps_keepdrops, "\t\t%d connection%s dropped by keepalive\n");
2399b50d902SRodney W. Grimes 	p(tcps_predack, "\t%d correct ACK header prediction%s\n");
2409b50d902SRodney W. Grimes 	p(tcps_preddat, "\t%d correct data packet header prediction%s\n");
2419b50d902SRodney W. Grimes #undef p
2429b50d902SRodney W. Grimes #undef p2
2439b50d902SRodney W. Grimes #undef p3
2449b50d902SRodney W. Grimes }
2459b50d902SRodney W. Grimes 
2469b50d902SRodney W. Grimes /*
2479b50d902SRodney W. Grimes  * Dump UDP statistics structure.
2489b50d902SRodney W. Grimes  */
2499b50d902SRodney W. Grimes void
2509b50d902SRodney W. Grimes udp_stats(off, name)
2519b50d902SRodney W. Grimes 	u_long off;
2529b50d902SRodney W. Grimes 	char *name;
2539b50d902SRodney W. Grimes {
2549b50d902SRodney W. Grimes 	struct udpstat udpstat;
2559b50d902SRodney W. Grimes 	u_long delivered;
2569b50d902SRodney W. Grimes 
2579b50d902SRodney W. Grimes 	if (off == 0)
2589b50d902SRodney W. Grimes 		return;
2599b50d902SRodney W. Grimes 	kread(off, (char *)&udpstat, sizeof (udpstat));
2609b50d902SRodney W. Grimes 	printf("%s:\n", name);
2619b50d902SRodney W. Grimes #define	p(f, m) if (udpstat.f || sflag <= 1) \
2629b50d902SRodney W. Grimes     printf(m, udpstat.f, plural(udpstat.f))
2639b50d902SRodney W. Grimes 	p(udps_ipackets, "\t%u datagram%s received\n");
2649b50d902SRodney W. Grimes 	p(udps_hdrops, "\t%u with incomplete header\n");
2659b50d902SRodney W. Grimes 	p(udps_badlen, "\t%u with bad data length field\n");
2669b50d902SRodney W. Grimes 	p(udps_badsum, "\t%u with bad checksum\n");
2679b50d902SRodney W. Grimes 	p(udps_noport, "\t%u dropped due to no socket\n");
2689b50d902SRodney W. Grimes 	p(udps_noportbcast, "\t%u broadcast/multicast datagram%s dropped due to no socket\n");
2699b50d902SRodney W. Grimes 	p(udps_fullsock, "\t%u dropped due to full socket buffers\n");
2709b50d902SRodney W. Grimes 	delivered = udpstat.udps_ipackets -
2719b50d902SRodney W. Grimes 		    udpstat.udps_hdrops -
2729b50d902SRodney W. Grimes 		    udpstat.udps_badlen -
2739b50d902SRodney W. Grimes 		    udpstat.udps_badsum -
2749b50d902SRodney W. Grimes 		    udpstat.udps_noport -
2759b50d902SRodney W. Grimes 		    udpstat.udps_noportbcast -
2769b50d902SRodney W. Grimes 		    udpstat.udps_fullsock;
2779b50d902SRodney W. Grimes 	if (delivered || sflag <= 1)
2789b50d902SRodney W. Grimes 		printf("\t%u delivered\n", delivered);
2799b50d902SRodney W. Grimes 	p(udps_opackets, "\t%u datagram%s output\n");
2809b50d902SRodney W. Grimes #undef p
2819b50d902SRodney W. Grimes }
2829b50d902SRodney W. Grimes 
2839b50d902SRodney W. Grimes /*
2849b50d902SRodney W. Grimes  * Dump IP statistics structure.
2859b50d902SRodney W. Grimes  */
2869b50d902SRodney W. Grimes void
2879b50d902SRodney W. Grimes ip_stats(off, name)
2889b50d902SRodney W. Grimes 	u_long off;
2899b50d902SRodney W. Grimes 	char *name;
2909b50d902SRodney W. Grimes {
2919b50d902SRodney W. Grimes 	struct ipstat ipstat;
2929b50d902SRodney W. Grimes 
2939b50d902SRodney W. Grimes 	if (off == 0)
2949b50d902SRodney W. Grimes 		return;
2959b50d902SRodney W. Grimes 	kread(off, (char *)&ipstat, sizeof (ipstat));
2969b50d902SRodney W. Grimes 	printf("%s:\n", name);
2979b50d902SRodney W. Grimes 
2989b50d902SRodney W. Grimes #define	p(f, m) if (ipstat.f || sflag <= 1) \
2999b50d902SRodney W. Grimes     printf(m, ipstat.f, plural(ipstat.f))
3009b50d902SRodney W. Grimes 
3019b50d902SRodney W. Grimes 	p(ips_total, "\t%u total packet%s received\n");
3029b50d902SRodney W. Grimes 	p(ips_badsum, "\t%u bad header checksum%s\n");
3039b50d902SRodney W. Grimes 	p(ips_toosmall, "\t%u with size smaller than minimum\n");
3049b50d902SRodney W. Grimes 	p(ips_tooshort, "\t%u with data size < data length\n");
3059b50d902SRodney W. Grimes 	p(ips_badhlen, "\t%u with header length < data size\n");
3069b50d902SRodney W. Grimes 	p(ips_badlen, "\t%u with data length < header length\n");
3079b50d902SRodney W. Grimes 	p(ips_badoptions, "\t%u with bad options\n");
3089b50d902SRodney W. Grimes 	p(ips_badvers, "\t%u with incorrect version number\n");
3099b50d902SRodney W. Grimes 	p(ips_fragments, "\t%u fragment%s received\n");
3109b50d902SRodney W. Grimes 	p(ips_fragdropped, "\t%u fragment%s dropped (dup or out of space)\n");
3119b50d902SRodney W. Grimes 	p(ips_fragtimeout, "\t%u fragment%s dropped after timeout\n");
3129b50d902SRodney W. Grimes 	p(ips_reassembled, "\t%u packet%s reassembled ok\n");
3139b50d902SRodney W. Grimes 	p(ips_delivered, "\t%u packet%s for this host\n");
3149b50d902SRodney W. Grimes 	p(ips_noproto, "\t%u packet%s for unknown/unsupported protocol\n");
3159b50d902SRodney W. Grimes 	p(ips_forward, "\t%u packet%s forwarded\n");
3169b50d902SRodney W. Grimes 	p(ips_cantforward, "\t%u packet%s not forwardable\n");
3179b50d902SRodney W. Grimes 	p(ips_redirectsent, "\t%u redirect%s sent\n");
3189b50d902SRodney W. Grimes 	p(ips_localout, "\t%u packet%s sent from this host\n");
3199b50d902SRodney W. Grimes 	p(ips_rawout, "\t%u packet%s sent with fabricated ip header\n");
3209b50d902SRodney W. Grimes 	p(ips_odropped, "\t%u output packet%s dropped due to no bufs, etc.\n");
3219b50d902SRodney W. Grimes 	p(ips_noroute, "\t%u output packet%s discarded due to no route\n");
3229b50d902SRodney W. Grimes 	p(ips_fragmented, "\t%u output datagram%s fragmented\n");
3239b50d902SRodney W. Grimes 	p(ips_ofragments, "\t%u fragment%s created\n");
3249b50d902SRodney W. Grimes 	p(ips_cantfrag, "\t%u datagram%s that can't be fragmented\n");
3259b50d902SRodney W. Grimes #undef p
3269b50d902SRodney W. Grimes }
3279b50d902SRodney W. Grimes 
3289b50d902SRodney W. Grimes static	char *icmpnames[] = {
3299b50d902SRodney W. Grimes 	"echo reply",
3309b50d902SRodney W. Grimes 	"#1",
3319b50d902SRodney W. Grimes 	"#2",
3329b50d902SRodney W. Grimes 	"destination unreachable",
3339b50d902SRodney W. Grimes 	"source quench",
3349b50d902SRodney W. Grimes 	"routing redirect",
3359b50d902SRodney W. Grimes 	"#6",
3369b50d902SRodney W. Grimes 	"#7",
3379b50d902SRodney W. Grimes 	"echo",
3387b46dd00SGarrett Wollman 	"router advertisement",
3397b46dd00SGarrett Wollman 	"router solicitation",
3409b50d902SRodney W. Grimes 	"time exceeded",
3419b50d902SRodney W. Grimes 	"parameter problem",
3429b50d902SRodney W. Grimes 	"time stamp",
3439b50d902SRodney W. Grimes 	"time stamp reply",
3449b50d902SRodney W. Grimes 	"information request",
3459b50d902SRodney W. Grimes 	"information request reply",
3469b50d902SRodney W. Grimes 	"address mask request",
3479b50d902SRodney W. Grimes 	"address mask reply",
3489b50d902SRodney W. Grimes };
3499b50d902SRodney W. Grimes 
3509b50d902SRodney W. Grimes /*
3519b50d902SRodney W. Grimes  * Dump ICMP statistics.
3529b50d902SRodney W. Grimes  */
3539b50d902SRodney W. Grimes void
3549b50d902SRodney W. Grimes icmp_stats(off, name)
3559b50d902SRodney W. Grimes 	u_long off;
3569b50d902SRodney W. Grimes 	char *name;
3579b50d902SRodney W. Grimes {
3589b50d902SRodney W. Grimes 	struct icmpstat icmpstat;
3599b50d902SRodney W. Grimes 	register int i, first;
3609b50d902SRodney W. Grimes 
3619b50d902SRodney W. Grimes 	if (off == 0)
3629b50d902SRodney W. Grimes 		return;
3639b50d902SRodney W. Grimes 	kread(off, (char *)&icmpstat, sizeof (icmpstat));
3649b50d902SRodney W. Grimes 	printf("%s:\n", name);
3659b50d902SRodney W. Grimes 
3669b50d902SRodney W. Grimes #define	p(f, m) if (icmpstat.f || sflag <= 1) \
3679b50d902SRodney W. Grimes     printf(m, icmpstat.f, plural(icmpstat.f))
3689b50d902SRodney W. Grimes 
3699b50d902SRodney W. Grimes 	p(icps_error, "\t%u call%s to icmp_error\n");
3709b50d902SRodney W. Grimes 	p(icps_oldicmp,
3719b50d902SRodney W. Grimes 	    "\t%u error%s not generated 'cuz old message was icmp\n");
3729b50d902SRodney W. Grimes 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
3739b50d902SRodney W. Grimes 		if (icmpstat.icps_outhist[i] != 0) {
3749b50d902SRodney W. Grimes 			if (first) {
3759b50d902SRodney W. Grimes 				printf("\tOutput histogram:\n");
3769b50d902SRodney W. Grimes 				first = 0;
3779b50d902SRodney W. Grimes 			}
3789b50d902SRodney W. Grimes 			printf("\t\t%s: %u\n", icmpnames[i],
3799b50d902SRodney W. Grimes 				icmpstat.icps_outhist[i]);
3809b50d902SRodney W. Grimes 		}
3819b50d902SRodney W. Grimes 	p(icps_badcode, "\t%u message%s with bad code fields\n");
3829b50d902SRodney W. Grimes 	p(icps_tooshort, "\t%u message%s < minimum length\n");
3839b50d902SRodney W. Grimes 	p(icps_checksum, "\t%u bad checksum%s\n");
3849b50d902SRodney W. Grimes 	p(icps_badlen, "\t%u message%s with bad length\n");
3859b50d902SRodney W. Grimes 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
3869b50d902SRodney W. Grimes 		if (icmpstat.icps_inhist[i] != 0) {
3879b50d902SRodney W. Grimes 			if (first) {
3889b50d902SRodney W. Grimes 				printf("\tInput histogram:\n");
3899b50d902SRodney W. Grimes 				first = 0;
3909b50d902SRodney W. Grimes 			}
3919b50d902SRodney W. Grimes 			printf("\t\t%s: %u\n", icmpnames[i],
3929b50d902SRodney W. Grimes 				icmpstat.icps_inhist[i]);
3939b50d902SRodney W. Grimes 		}
3949b50d902SRodney W. Grimes 	p(icps_reflect, "\t%u message response%s generated\n");
3959b50d902SRodney W. Grimes #undef p
3969b50d902SRodney W. Grimes }
3979b50d902SRodney W. Grimes 
3989b50d902SRodney W. Grimes /*
3999b50d902SRodney W. Grimes  * Dump IGMP statistics structure.
4009b50d902SRodney W. Grimes  */
4019b50d902SRodney W. Grimes void
4029b50d902SRodney W. Grimes igmp_stats(off, name)
4039b50d902SRodney W. Grimes 	u_long off;
4049b50d902SRodney W. Grimes 	char *name;
4059b50d902SRodney W. Grimes {
4069b50d902SRodney W. Grimes 	struct igmpstat igmpstat;
4079b50d902SRodney W. Grimes 
4089b50d902SRodney W. Grimes 	if (off == 0)
4099b50d902SRodney W. Grimes 		return;
4109b50d902SRodney W. Grimes 	kread(off, (char *)&igmpstat, sizeof (igmpstat));
4119b50d902SRodney W. Grimes 	printf("%s:\n", name);
4129b50d902SRodney W. Grimes 
4139b50d902SRodney W. Grimes #define	p(f, m) if (igmpstat.f || sflag <= 1) \
4149b50d902SRodney W. Grimes     printf(m, igmpstat.f, plural(igmpstat.f))
4159b50d902SRodney W. Grimes #define	py(f, m) if (igmpstat.f || sflag <= 1) \
4169b50d902SRodney W. Grimes     printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
4179b50d902SRodney W. Grimes 	p(igps_rcv_total, "\t%u message%s received\n");
4189b50d902SRodney W. Grimes         p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
4199b50d902SRodney W. Grimes         p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
4209b50d902SRodney W. Grimes         py(igps_rcv_queries, "\t%u membership quer%s received\n");
4219b50d902SRodney W. Grimes         py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
4229b50d902SRodney W. Grimes         p(igps_rcv_reports, "\t%u membership report%s received\n");
4239b50d902SRodney W. Grimes         p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
4249b50d902SRodney W. Grimes         p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
4259b50d902SRodney W. Grimes         p(igps_snd_reports, "\t%u membership report%s sent\n");
4269b50d902SRodney W. Grimes #undef p
4279b50d902SRodney W. Grimes #undef py
4289b50d902SRodney W. Grimes }
4299b50d902SRodney W. Grimes 
4309b50d902SRodney W. Grimes /*
4319b50d902SRodney W. Grimes  * Pretty print an Internet address (net address + port).
4329b50d902SRodney W. Grimes  * If the nflag was specified, use numbers instead of names.
4339b50d902SRodney W. Grimes  */
4349b50d902SRodney W. Grimes void
4359b50d902SRodney W. Grimes inetprint(in, port, proto)
4369b50d902SRodney W. Grimes 	register struct in_addr *in;
4379b50d902SRodney W. Grimes 	int port;
4389b50d902SRodney W. Grimes 	char *proto;
4399b50d902SRodney W. Grimes {
4409b50d902SRodney W. Grimes 	struct servent *sp = 0;
4419b50d902SRodney W. Grimes 	char line[80], *cp;
4429b50d902SRodney W. Grimes 	int width;
4439b50d902SRodney W. Grimes 
4449b50d902SRodney W. Grimes 	sprintf(line, "%.*s.", (Aflag && !nflag) ? 12 : 16, inetname(in));
4459b50d902SRodney W. Grimes 	cp = index(line, '\0');
4469b50d902SRodney W. Grimes 	if (!nflag && port)
4479b50d902SRodney W. Grimes 		sp = getservbyport((int)port, proto);
4489b50d902SRodney W. Grimes 	if (sp || port == 0)
4491ef69972SAndrey A. Chernov 		sprintf(cp, "%.15s", sp ? sp->s_name : "*");
4509b50d902SRodney W. Grimes 	else
4519b50d902SRodney W. Grimes 		sprintf(cp, "%d", ntohs((u_short)port));
4529b50d902SRodney W. Grimes 	width = Aflag ? 18 : 22;
4539b50d902SRodney W. Grimes 	printf(" %-*.*s", width, width, line);
4549b50d902SRodney W. Grimes }
4559b50d902SRodney W. Grimes 
4569b50d902SRodney W. Grimes /*
4579b50d902SRodney W. Grimes  * Construct an Internet address representation.
4589b50d902SRodney W. Grimes  * If the nflag has been supplied, give
4599b50d902SRodney W. Grimes  * numeric value, otherwise try for symbolic name.
4609b50d902SRodney W. Grimes  */
4619b50d902SRodney W. Grimes char *
4629b50d902SRodney W. Grimes inetname(inp)
4639b50d902SRodney W. Grimes 	struct in_addr *inp;
4649b50d902SRodney W. Grimes {
4659b50d902SRodney W. Grimes 	register char *cp;
4669b50d902SRodney W. Grimes 	static char line[50];
4679b50d902SRodney W. Grimes 	struct hostent *hp;
4689b50d902SRodney W. Grimes 	struct netent *np;
4699b50d902SRodney W. Grimes 	static char domain[MAXHOSTNAMELEN + 1];
4709b50d902SRodney W. Grimes 	static int first = 1;
4719b50d902SRodney W. Grimes 
4729b50d902SRodney W. Grimes 	if (first && !nflag) {
4739b50d902SRodney W. Grimes 		first = 0;
4749b50d902SRodney W. Grimes 		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
4759b50d902SRodney W. Grimes 		    (cp = index(domain, '.')))
4769b50d902SRodney W. Grimes 			(void) strcpy(domain, cp + 1);
4779b50d902SRodney W. Grimes 		else
4789b50d902SRodney W. Grimes 			domain[0] = 0;
4799b50d902SRodney W. Grimes 	}
4809b50d902SRodney W. Grimes 	cp = 0;
4819b50d902SRodney W. Grimes 	if (!nflag && inp->s_addr != INADDR_ANY) {
4829b50d902SRodney W. Grimes 		int net = inet_netof(*inp);
4839b50d902SRodney W. Grimes 		int lna = inet_lnaof(*inp);
4849b50d902SRodney W. Grimes 
4859b50d902SRodney W. Grimes 		if (lna == INADDR_ANY) {
4869b50d902SRodney W. Grimes 			np = getnetbyaddr(net, AF_INET);
4879b50d902SRodney W. Grimes 			if (np)
4889b50d902SRodney W. Grimes 				cp = np->n_name;
4899b50d902SRodney W. Grimes 		}
4909b50d902SRodney W. Grimes 		if (cp == 0) {
4919b50d902SRodney W. Grimes 			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
4929b50d902SRodney W. Grimes 			if (hp) {
4939b50d902SRodney W. Grimes 				if ((cp = index(hp->h_name, '.')) &&
4949b50d902SRodney W. Grimes 				    !strcmp(cp + 1, domain))
4959b50d902SRodney W. Grimes 					*cp = 0;
4969b50d902SRodney W. Grimes 				cp = hp->h_name;
4979b50d902SRodney W. Grimes 			}
4989b50d902SRodney W. Grimes 		}
4999b50d902SRodney W. Grimes 	}
5009b50d902SRodney W. Grimes 	if (inp->s_addr == INADDR_ANY)
5019b50d902SRodney W. Grimes 		strcpy(line, "*");
5029b50d902SRodney W. Grimes 	else if (cp)
5039b50d902SRodney W. Grimes 		strcpy(line, cp);
5049b50d902SRodney W. Grimes 	else {
5059b50d902SRodney W. Grimes 		inp->s_addr = ntohl(inp->s_addr);
5069b50d902SRodney W. Grimes #define C(x)	((x) & 0xff)
5079b50d902SRodney W. Grimes 		sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
5089b50d902SRodney W. Grimes 		    C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
5099b50d902SRodney W. Grimes 	}
5109b50d902SRodney W. Grimes 	return (line);
5119b50d902SRodney W. Grimes }
512