inet.c revision 9264
188449Sbmilekic/*
21541Srgrimes * Copyright (c) 1983, 1988, 1993
3167870Srwatson *	The Regents of the University of California.  All rights reserved.
4167870Srwatson *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes * 3. All advertising materials mentioning features or use of this software
14129906Sbmilekic *    must display the following acknowledgement:
151541Srgrimes *	This product includes software developed by the University of
161541Srgrimes *	California, Berkeley and its contributors.
171541Srgrimes * 4. Neither the name of the University nor the names of its contributors
181541Srgrimes *    may be used to endorse or promote products derived from this software
191541Srgrimes *    without specific prior written permission.
201541Srgrimes *
211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3014491Shsu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3150477Speter * SUCH DAMAGE.
321541Srgrimes */
331541Srgrimes
342197Spaul#ifndef lint
3554781Sgreenstatic char sccsid[] = "@(#)inet.c	8.4 (Berkeley) 4/20/94";
362165Spaul#endif /* not lint */
37129906Sbmilekic
38105194Ssam#include <sys/param.h>
39129906Sbmilekic#include <sys/socket.h>
40129906Sbmilekic#include <sys/socketvar.h>
41129906Sbmilekic#include <sys/mbuf.h>
42132488Salfred#include <sys/protosw.h>
43132488Salfred#include <sys/queue.h>
44129906Sbmilekic
45132488Salfred#include <net/route.h>
46100981Srwatson#include <netinet/in.h>
47100981Srwatson#include <netinet/in_systm.h>
48167870Srwatson#include <netinet/ip.h>
49167870Srwatson#include <netinet/in_pcb.h>
50167870Srwatson#include <netinet/ip_icmp.h>
51167870Srwatson#include <netinet/icmp_var.h>
52167870Srwatson#include <netinet/igmp_var.h>
53167870Srwatson#include <netinet/ip_var.h>
54167870Srwatson#include <netinet/tcp.h>
551541Srgrimes#include <netinet/tcpip.h>
561541Srgrimes#include <netinet/tcp_seq.h>
571541Srgrimes#define TCPSTATES
5852904Sshin#include <netinet/tcp_fsm.h>
591541Srgrimes#include <netinet/tcp_timer.h>
601541Srgrimes#include <netinet/tcp_var.h>
6175216Sbmilekic#include <netinet/tcp_debug.h>
62210226Strasz#include <netinet/udp.h>
63194549Srwatson#include <netinet/udp_var.h>
64194549Srwatson
65194549Srwatson#include <arpa/inet.h>
6688449Sbmilekic#include <netdb.h>
671541Srgrimes#include <stdio.h>
6854798Sgreen#include <string.h>
69129906Sbmilekic#include <unistd.h>
70129906Sbmilekic#include "netstat.h"
71129906Sbmilekic
72129906Sbmilekicstruct	inpcb inpcb;
73129906Sbmilekicstruct	tcpcb tcpcb;
74129906Sbmilekicstruct	socket sockb;
75129906Sbmilekic
76129906Sbmilekicchar	*inetname __P((struct in_addr *));
77129906Sbmilekicvoid	inetprint __P((struct in_addr *, int, char *));
7875216Sbmilekic
791541Srgrimes/*
80168732Skmacy * Print a summary of connections related to an Internet
81168732Skmacy * protocol.  For TCP, also give state of connection.
82168732Skmacy * Listening processes (aflag) are suppressed unless the
83168732Skmacy * -a (all) flag is specified.
84168732Skmacy */
85168732Skmacyvoid
8678592Sbmilekicprotopr(off, name)
8778592Sbmilekic	u_long off;
8878592Sbmilekic	char *name;
891541Srgrimes{
90167870Srwatson	struct inpcbhead head;
91167870Srwatson	register struct inpcb *prev, *next;
92167870Srwatson	int istcp;
93167870Srwatson	static int first = 1;
94167870Srwatson
95167870Srwatson	if (off == 0)
96168732Skmacy		return;
971541Srgrimes
981541Srgrimes	istcp = strcmp(name, "tcp") == 0;
9978592Sbmilekic	kread(off, (char *)&head, sizeof (struct inpcbhead));
100105194Ssam	prev = (struct inpcb *)off;
101105194Ssam
102105194Ssam	for (next = head.lh_first; next != NULL; next = inpcb.inp_list.le_next) {
103105194Ssam		kread((u_long)next, (char *)&inpcb, sizeof (inpcb));
104105194Ssam		if (!aflag &&
105105194Ssam		  inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) {
106105194Ssam			prev = next;
107124077Ssam			continue;
108105194Ssam		}
109105194Ssam		kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb));
110105194Ssam		if (istcp) {
11178592Sbmilekic			kread((u_long)inpcb.inp_ppcb,
11278592Sbmilekic			    (char *)&tcpcb, sizeof (tcpcb));
11354781Sgreen		}
114167870Srwatson		if (first) {
11538513Sdfr			printf("Active Internet connections");
116167870Srwatson			if (aflag)
117168732Skmacy				printf(" (including servers)");
118238250Stuexen			putchar('\n');
119185166Skmacy			if (Aflag)
120185166Skmacy				printf("%-8.8s ", "PCB");
12158698Sjlemon			printf(Aflag ?
122167870Srwatson				"%-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n" :
123167870Srwatson				"%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
124167870Srwatson				"Proto", "Recv-Q", "Send-Q",
125189345Sbms				"Local Address", "Foreign Address", "(state)");
126189345Sbms			first = 0;
127189345Sbms		}
128189345Sbms		if (Aflag)
129105194Ssam			if (istcp)
1301541Srgrimes				printf("%8x ", inpcb.inp_ppcb);
131189345Sbms			else
1321541Srgrimes				printf("%8x ", next);
13378592Sbmilekic		printf("%-5.5s %6d %6d ", name, sockb.so_rcv.sb_cc,
134167870Srwatson			sockb.so_snd.sb_cc);
135167870Srwatson		inetprint(&inpcb.inp_laddr, (int)inpcb.inp_lport, name);
13678592Sbmilekic		inetprint(&inpcb.inp_faddr, (int)inpcb.inp_fport, name);
1371541Srgrimes		if (istcp) {
138167870Srwatson			if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
139167870Srwatson				printf(" %d", tcpcb.t_state);
140167870Srwatson                      else {
141175872Sphk				printf(" %s", tcpstates[tcpcb.t_state]);
142175872Sphk#if defined(TF_NEEDSYN) && defined(TF_NEEDSYN)
143167870Srwatson                              /* Show T/TCP `hidden state' */
144167870Srwatson                              if (tcpcb.t_flags & (TF_NEEDSYN|TF_NEEDFIN))
145167870Srwatson                                      putchar('*');
1461541Srgrimes#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDSYN) */
1471541Srgrimes                      }
14878592Sbmilekic		}
149167870Srwatson		putchar('\n');
150167870Srwatson		prev = next;
15178592Sbmilekic	}
1521541Srgrimes}
153167870Srwatson
1541541Srgrimes/*
1551541Srgrimes * Dump TCP statistics structure.
156167870Srwatson */
1571541Srgrimesvoid
158167870Srwatsontcp_stats(off, name)
159167870Srwatson	u_long off;
1601541Srgrimes	char *name;
1611541Srgrimes{
1621541Srgrimes	struct tcpstat tcpstat;
1631541Srgrimes
1641541Srgrimes	if (off == 0)
1651541Srgrimes		return;
1661541Srgrimes	printf ("%s:\n", name);
1671541Srgrimes	kread(off, (char *)&tcpstat, sizeof (tcpstat));
1681541Srgrimes
1691541Srgrimes#define	p(f, m) if (tcpstat.f || sflag <= 1) \
1701541Srgrimes    printf(m, tcpstat.f, plural(tcpstat.f))
1711541Srgrimes#define	p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
1721541Srgrimes    printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
1731541Srgrimes#define	p3(f, m) if (tcpstat.f || sflag <= 1) \
1741541Srgrimes    printf(m, tcpstat.f, plurales(tcpstat.f))
1751541Srgrimes
1761541Srgrimes	p(tcps_sndtotal, "\t%d packet%s sent\n");
17778592Sbmilekic	p2(tcps_sndpack,tcps_sndbyte,
17888449Sbmilekic		"\t\t%d data packet%s (%d byte%s)\n");
17978592Sbmilekic	p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
180177566Ssam		"\t\t%d data packet%s (%d byte%s) retransmitted\n");
181177566Ssam	p2(tcps_sndacks, tcps_delack,
182177566Ssam		"\t\t%d ack-only packet%s (%d delayed)\n");
183177566Ssam	p(tcps_sndurg, "\t\t%d URG only packet%s\n");
184177566Ssam	p(tcps_sndprobe, "\t\t%d window probe packet%s\n");
185177566Ssam	p(tcps_sndwinup, "\t\t%d window update packet%s\n");
186177566Ssam	p(tcps_sndctrl, "\t\t%d control packet%s\n");
187177566Ssam	p(tcps_rcvtotal, "\t%d packet%s received\n");
188177566Ssam	p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%d ack%s (for %d byte%s)\n");
189177566Ssam	p(tcps_rcvdupack, "\t\t%d duplicate ack%s\n");
190177566Ssam	p(tcps_rcvacktoomuch, "\t\t%d ack%s for unsent data\n");
191177566Ssam	p2(tcps_rcvpack, tcps_rcvbyte,
192177566Ssam		"\t\t%d packet%s (%d byte%s) received in-sequence\n");
193177566Ssam	p2(tcps_rcvduppack, tcps_rcvdupbyte,
194177566Ssam		"\t\t%d completely duplicate packet%s (%d byte%s)\n");
195177566Ssam	p(tcps_pawsdrop, "\t\t%d old duplicate packet%s\n");
196177566Ssam	p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
197177566Ssam		"\t\t%d packet%s with some dup. data (%d byte%s duped)\n");
198177566Ssam	p2(tcps_rcvoopack, tcps_rcvoobyte,
199177566Ssam		"\t\t%d out-of-order packet%s (%d byte%s)\n");
200177566Ssam	p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
201177566Ssam		"\t\t%d packet%s (%d byte%s) of data after window\n");
202222702Srwatson	p(tcps_rcvwinprobe, "\t\t%d window probe%s\n");
203222702Srwatson	p(tcps_rcvwinupd, "\t\t%d window update packet%s\n");
204222702Srwatson	p(tcps_rcvafterclose, "\t\t%d packet%s received after close\n");
205178888Sjulian	p(tcps_rcvbadsum, "\t\t%d discarded for bad checksum%s\n");
206178888Sjulian	p(tcps_rcvbadoff, "\t\t%d discarded for bad header offset field%s\n");
207178888Sjulian	p(tcps_rcvshort, "\t\t%d discarded because packet too short\n");
208178888Sjulian	p(tcps_connattempt, "\t%d connection request%s\n");
209178888Sjulian	p(tcps_accepts, "\t%d connection accept%s\n");
2101541Srgrimes	p(tcps_connects, "\t%d connection%s established (including accepts)\n");
211177566Ssam	p2(tcps_closed, tcps_drops,
212177566Ssam		"\t%d connection%s closed (including %d drop%s)\n");
21378592Sbmilekic	p(tcps_cachedrtt, "\t\t%d connection%s upcated cached RTT on close\n");
214177566Ssam	p(tcps_cachedrttvar,
21578592Sbmilekic	  "\t\t%d connection%s upcated cached RTT variance on close\n");
216177566Ssam	p(tcps_cachedssthresh,
217177566Ssam	  "\t\t%d connection%s updated cached ssthresh on close\n");
2181541Srgrimes	p(tcps_conndrops, "\t%d embryonic connection%s dropped\n");
21978592Sbmilekic	p2(tcps_rttupdated, tcps_segstimed,
220222702Srwatson		"\t%d segment%s updated rtt (of %d attempt%s)\n");
221222702Srwatson	p(tcps_rexmttimeo, "\t%d retransmit timeout%s\n");
222222702Srwatson	p(tcps_timeoutdrop, "\t\t%d connection%s dropped by rexmit timeout\n");
223222702Srwatson	p(tcps_persisttimeo, "\t%d persist timeout%s\n");
224222702Srwatson	p(tcps_keeptimeo, "\t%d keepalive timeout%s\n");
225222702Srwatson	p(tcps_keepprobe, "\t\t%d keepalive probe%s sent\n");
226222702Srwatson	p(tcps_keepdrops, "\t\t%d connection%s dropped by keepalive\n");
227222702Srwatson	p(tcps_predack, "\t%d correct ACK header prediction%s\n");
228222702Srwatson	p(tcps_preddat, "\t%d correct data packet header prediction%s\n");
229222702Srwatson	p3(tcps_pcbcachemiss, "\t%d PCB cache miss%s\n");
230222702Srwatson#undef p
231222702Srwatson#undef p2
232222702Srwatson#undef p3
233222702Srwatson}
234222702Srwatson
235222702Srwatson/*
236222702Srwatson * Dump UDP statistics structure.
237222702Srwatson */
238222702Srwatsonvoid
239222702Srwatsonudp_stats(off, name)
240222702Srwatson	u_long off;
241222702Srwatson	char *name;
242222702Srwatson{
243222702Srwatson	struct udpstat udpstat;
244222702Srwatson	u_long delivered;
245222702Srwatson
246222702Srwatson	if (off == 0)
247222702Srwatson		return;
248222702Srwatson	kread(off, (char *)&udpstat, sizeof (udpstat));
249222702Srwatson	printf("%s:\n", name);
250222709Srwatson#define	p(f, m) if (udpstat.f || sflag <= 1) \
251222702Srwatson    printf(m, udpstat.f, plural(udpstat.f))
252222702Srwatson	p(udps_ipackets, "\t%u datagram%s received\n");
253222702Srwatson	p(udps_hdrops, "\t%u with incomplete header\n");
254177566Ssam	p(udps_badlen, "\t%u with bad data length field\n");
255177566Ssam	p(udps_badsum, "\t%u with bad checksum\n");
256177566Ssam	p(udps_noport, "\t%u dropped due to no socket\n");
257177566Ssam	p(udps_noportbcast, "\t%u broadcast/multicast datagram%s dropped due to no socket\n");
258222702Srwatson	p(udps_fullsock, "\t%u dropped due to full socket buffers\n");
259177566Ssam	delivered = udpstat.udps_ipackets -
260177566Ssam		    udpstat.udps_hdrops -
26188449Sbmilekic		    udpstat.udps_badlen -
26278592Sbmilekic		    udpstat.udps_badsum -
26368622Sbmilekic		    udpstat.udps_noport -
26468622Sbmilekic		    udpstat.udps_noportbcast -
265155780Sandre		    udpstat.udps_fullsock;
266153232Sandre	if (delivered || sflag <= 1)
267153232Sandre		printf("\t%u delivered\n", delivered);
268153232Sandre	p(udps_opackets, "\t%u datagram%s output\n");
269168335Skmacy#undef p
27068622Sbmilekic}
27168656Sbmilekic
27298849Sken/*
273129810Smaxim * Dump IP statistics structure.
27468622Sbmilekic */
27578592Sbmilekicvoid
276167870Srwatsonip_stats(off, name)
277167870Srwatson	u_long off;
27878592Sbmilekic	char *name;
27988449Sbmilekic{
28088449Sbmilekic	struct ipstat ipstat;
28188449Sbmilekic
282252828Sandre	if (off == 0)
28388449Sbmilekic		return;
284162084Sandre	kread(off, (char *)&ipstat, sizeof (ipstat));
285186815Srrs	printf("%s:\n", name);
286238250Stuexen
28758698Sjlemon#define	p(f, m) if (ipstat.f || sflag <= 1) \
28888449Sbmilekic    printf(m, ipstat.f, plural(ipstat.f))
28988449Sbmilekic
29088449Sbmilekic	p(ips_total, "\t%u total packet%s received\n");
29188449Sbmilekic	p(ips_badsum, "\t%u bad header checksum%s\n");
292186815Srrs	p(ips_toosmall, "\t%u with size smaller than minimum\n");
293238247Sbz	p(ips_tooshort, "\t%u with data size < data length\n");
294238247Sbz	p(ips_badhlen, "\t%u with header length < data size\n");
295238247Sbz	p(ips_badlen, "\t%u with data length < header length\n");
29658698Sjlemon	p(ips_badoptions, "\t%u with bad options\n");
297238247Sbz	p(ips_badvers, "\t%u with incorrect version number\n");
298238247Sbz	p(ips_fragments, "\t%u fragment%s received\n");
299238247Sbz	p(ips_fragdropped, "\t%u fragment%s dropped (dup or out of space)\n");
300238247Sbz	p(ips_fragtimeout, "\t%u fragment%s dropped after timeout\n");
301238247Sbz	p(ips_reassembled, "\t%u packet%s reassembled ok\n");
30288449Sbmilekic	p(ips_delivered, "\t%u packet%s for this host\n");
303238247Sbz	p(ips_noproto, "\t%u packet%s for unknown/unsupported protocol\n");
30458698Sjlemon	p(ips_forward, "\t%u packet%s forwarded\n");
30578592Sbmilekic	p(ips_cantforward, "\t%u packet%s not forwardable\n");
30688449Sbmilekic	p(ips_redirectsent, "\t%u redirect%s sent\n");
30778592Sbmilekic	p(ips_localout, "\t%u packet%s sent from this host\n");
30884153Sbmilekic	p(ips_rawout, "\t%u packet%s sent with fabricated ip header\n");
3091541Srgrimes	p(ips_odropped, "\t%u output packet%s dropped due to no bufs, etc.\n");
310151967Sandre	p(ips_noroute, "\t%u output packet%s discarded due to no route\n");
3111541Srgrimes	p(ips_fragmented, "\t%u output datagram%s fragmented\n");
31254781Sgreen	p(ips_ofragments, "\t%u fragment%s created\n");
31354781Sgreen	p(ips_cantfrag, "\t%u datagram%s that can't be fragmented\n");
31463203Salfred#undef p
31563203Salfred}
316151976Sandre
317151976Sandrestatic	char *icmpnames[] = {
318151976Sandre	"echo reply",
319172462Skmacy	"#1",
320172462Skmacy	"#2",
32154584Sgreen	"destination unreachable",
32284153Sbmilekic	"source quench",
323160608Srwatson	"routing redirect",
324160608Srwatson	"#6",
325160608Srwatson	"#7",
32678592Sbmilekic	"echo",
32754584Sgreen	"router advertisement",
328129906Sbmilekic	"router solicitation",
329129906Sbmilekic	"time exceeded",
330129906Sbmilekic	"parameter problem",
33154584Sgreen	"time stamp",
33284153Sbmilekic	"time stamp reply",
33384153Sbmilekic	"information request",
33454584Sgreen	"information request reply",
33554584Sgreen	"address mask request",
33654584Sgreen	"address mask reply",
33754584Sgreen};
33854584Sgreen
339129906Sbmilekic/*
340178888Sjulian * Dump ICMP statistics.
34188449Sbmilekic */
342129906Sbmilekicvoid
343123929Ssilbyicmp_stats(off, name)
344123929Ssilby	u_long off;
345123929Ssilby	char *name;
346123929Ssilby{
34754584Sgreen	struct icmpstat icmpstat;
3481541Srgrimes	register int i, first;
34978592Sbmilekic
35078592Sbmilekic	if (off == 0)
351129906Sbmilekic		return;
352129906Sbmilekic	kread(off, (char *)&icmpstat, sizeof (icmpstat));
353252823Sandre	printf("%s:\n", name);
354252823Sandre
355129906Sbmilekic#define	p(f, m) if (icmpstat.f || sflag <= 1) \
356167870Srwatson    printf(m, icmpstat.f, plural(icmpstat.f))
357167870Srwatson
358177599Sru	p(icps_error, "\t%u call%s to icmp_error\n");
359167870Srwatson	p(icps_oldicmp,
360129906Sbmilekic	    "\t%u error%s not generated 'cuz old message was icmp\n");
361129906Sbmilekic	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
36278592Sbmilekic		if (icmpstat.icps_outhist[i] != 0) {
363129906Sbmilekic			if (first) {
364129906Sbmilekic				printf("\tOutput histogram:\n");
365129906Sbmilekic				first = 0;
366129906Sbmilekic			}
36754478Sgreen			printf("\t\t%s: %u\n", icmpnames[i],
368148095Srwatson				icmpstat.icps_outhist[i]);
369148095Srwatson		}
370148095Srwatson	p(icps_badcode, "\t%u message%s with bad code fields\n");
371148095Srwatson	p(icps_tooshort, "\t%u message%s < minimum length\n");
372148095Srwatson	p(icps_checksum, "\t%u bad checksum%s\n");
373148095Srwatson	p(icps_badlen, "\t%u message%s with bad length\n");
374148095Srwatson	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
375148095Srwatson		if (icmpstat.icps_inhist[i] != 0) {
376174896Swkoszek			if (first) {
377151976Sandre				printf("\tInput histogram:\n");
378151976Sandre				first = 0;
379148095Srwatson			}
380151976Sandre			printf("\t\t%s: %u\n", icmpnames[i],
381148095Srwatson				icmpstat.icps_inhist[i]);
38275216Sbmilekic		}
38364837Sdwmalone	p(icps_reflect, "\t%u message response%s generated\n");
384132504Salfred#undef p
385167870Srwatson}
386132488Salfred
387132488Salfred/*
388132488Salfred * Dump IGMP statistics structure.
389151976Sandre */
390132504Salfredvoid
391167870Srwatsonigmp_stats(off, name)
392132504Salfred	u_long off;
393132488Salfred	char *name;
39464837Sdwmalone{
395129906Sbmilekic	struct igmpstat igmpstat;
396129906Sbmilekic
397136451Sglebius	if (off == 0)
398129906Sbmilekic		return;
399129906Sbmilekic	kread(off, (char *)&igmpstat, sizeof (igmpstat));
400129906Sbmilekic	printf("%s:\n", name);
401129906Sbmilekic
402155780Sandre#define	p(f, m) if (igmpstat.f || sflag <= 1) \
403151976Sandre    printf(m, igmpstat.f, plural(igmpstat.f))
404151976Sandre#define	py(f, m) if (igmpstat.f || sflag <= 1) \
405151976Sandre    printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
406129906Sbmilekic	p(igps_rcv_total, "\t%u message%s received\n");
407168735Skmacy        p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
408129906Sbmilekic        p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
409129906Sbmilekic        py(igps_rcv_queries, "\t%u membership quer%s received\n");
410167870Srwatson        py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
411167870Srwatson        p(igps_rcv_reports, "\t%u membership report%s received\n");
412129906Sbmilekic        p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
413194515Skmacy        p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
414194515Skmacy        p(igps_snd_reports, "\t%u membership report%s sent\n");
415129906Sbmilekic#undef p
416129906Sbmilekic#undef py
417153232Sandre}
418129906Sbmilekic
419129906Sbmilekic/*
420168638Sandre * Pretty print an Internet address (net address + port).
421194515Skmacy * If the nflag was specified, use numbers instead of names.
422129906Sbmilekic */
423168335Skmacyvoid
424168335Skmacyinetprint(in, port, proto)
425168335Skmacy	register struct in_addr *in;
426168335Skmacy	int port;
427238250Stuexen	char *proto;
428168335Skmacy{
429168335Skmacy	struct servent *sp = 0;
430168335Skmacy	char line[80], *cp;
431168335Skmacy	int width;
432168335Skmacy
433168335Skmacy	sprintf(line, "%.*s.", (Aflag && !nflag) ? 12 : 16, inetname(in));
434168335Skmacy	cp = index(line, '\0');
435168335Skmacy	if (!nflag && port)
436168335Skmacy		sp = getservbyport((int)port, proto);
437168335Skmacy	if (sp || port == 0)
438168335Skmacy		sprintf(cp, "%.8s", sp ? sp->s_name : "*");
439168335Skmacy	else
440168335Skmacy		sprintf(cp, "%d", ntohs((u_short)port));
441168335Skmacy	width = Aflag ? 18 : 22;
442168335Skmacy	printf(" %-*.*s", width, width, line);
443168335Skmacy}
444168335Skmacy
445168335Skmacy/*
446168335Skmacy * Construct an Internet address representation.
447168335Skmacy * If the nflag has been supplied, give
448168335Skmacy * numeric value, otherwise try for symbolic name.
449168335Skmacy */
450168335Skmacychar *
451168335Skmacyinetname(inp)
452168335Skmacy	struct in_addr *inp;
453265479Snp{
454265479Snp	register char *cp;
455265479Snp	static char line[50];
456265479Snp	struct hostent *hp;
457265479Snp	struct netent *np;
458265479Snp	static char domain[MAXHOSTNAMELEN + 1];
459265479Snp	static int first = 1;
460265479Snp
461265479Snp	if (first && !nflag) {
462265479Snp		first = 0;
463265479Snp		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
464265479Snp		    (cp = index(domain, '.')))
465265479Snp			(void) strcpy(domain, cp + 1);
466265479Snp		else
467265479Snp			domain[0] = 0;
468265479Snp	}
469265479Snp	cp = 0;
470265479Snp	if (!nflag && inp->s_addr != INADDR_ANY) {
471265479Snp		int net = inet_netof(*inp);
472265479Snp		int lna = inet_lnaof(*inp);
473265479Snp
474265479Snp		if (lna == INADDR_ANY) {
475168335Skmacy			np = getnetbyaddr(net, AF_INET);
476168335Skmacy			if (np)
477168335Skmacy				cp = np->n_name;
478168335Skmacy		}
479238250Stuexen		if (cp == 0) {
480168335Skmacy			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
481168335Skmacy			if (hp) {
482168335Skmacy				if ((cp = index(hp->h_name, '.')) &&
483168335Skmacy				    !strcmp(cp + 1, domain))
484168335Skmacy					*cp = 0;
485168335Skmacy				cp = hp->h_name;
486168335Skmacy			}
487168335Skmacy		}
488168335Skmacy	}
489168335Skmacy	if (inp->s_addr == INADDR_ANY)
490168335Skmacy		strcpy(line, "*");
491168335Skmacy	else if (cp)
492168335Skmacy		strcpy(line, cp);
493168335Skmacy	else {
494168335Skmacy		inp->s_addr = ntohl(inp->s_addr);
495168335Skmacy#define C(x)	((x) & 0xff)
496168335Skmacy		sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
497168335Skmacy		    C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
498168335Skmacy	}
499168335Skmacy	return (line);
500168335Skmacy}
501168335Skmacy