xref: /freebsd/usr.bin/netstat/inet.c (revision 4cf49a43559ed9fdad601bdcccd2c55963008675)
1 /*
2  * Copyright (c) 1983, 1988, 1993, 1995
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifndef lint
35 /*
36 static char sccsid[] = "@(#)inet.c	8.5 (Berkeley) 5/24/95";
37 */
38 static const char rcsid[] =
39   "$FreeBSD$";
40 #endif /* not lint */
41 
42 #include <sys/param.h>
43 #include <sys/queue.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
46 #include <sys/sysctl.h>
47 #include <sys/protosw.h>
48 
49 #include <net/route.h>
50 #include <netinet/in.h>
51 #include <netinet/in_systm.h>
52 #include <netinet/ip.h>
53 #include <netinet/in_pcb.h>
54 #include <netinet/ip_icmp.h>
55 #include <netinet/icmp_var.h>
56 #include <netinet/igmp_var.h>
57 #include <netinet/ip_var.h>
58 #include <netinet/tcp.h>
59 #include <netinet/tcpip.h>
60 #include <netinet/tcp_seq.h>
61 #define TCPSTATES
62 #include <netinet/tcp_fsm.h>
63 #include <netinet/tcp_timer.h>
64 #include <netinet/tcp_var.h>
65 #include <netinet/tcp_debug.h>
66 #include <netinet/udp.h>
67 #include <netinet/udp_var.h>
68 
69 #include <arpa/inet.h>
70 #include <err.h>
71 #include <errno.h>
72 #include <netdb.h>
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76 #include <unistd.h>
77 #include "netstat.h"
78 
79 char	*inetname __P((struct in_addr *));
80 void	inetprint __P((struct in_addr *, int, char *, int));
81 
82 /*
83  * Print a summary of connections related to an Internet
84  * protocol.  For TCP, also give state of connection.
85  * Listening processes (aflag) are suppressed unless the
86  * -a (all) flag is specified.
87  */
88 void
89 protopr(proto, name)
90 	u_long proto;		/* for sysctl version we pass proto # */
91 	char *name;
92 {
93 	int istcp;
94 	static int first = 1;
95 	char *buf;
96 	const char *mibvar;
97 	struct tcpcb *tp = NULL;
98 	struct inpcb *inp;
99 	struct xinpgen *xig, *oxig;
100 	struct xsocket *so;
101 	size_t len;
102 
103 	istcp = 0;
104 	switch (proto) {
105 	case IPPROTO_TCP:
106 		istcp = 1;
107 		mibvar = "net.inet.tcp.pcblist";
108 		break;
109 	case IPPROTO_UDP:
110 		mibvar = "net.inet.udp.pcblist";
111 		break;
112 	case IPPROTO_DIVERT:
113 		mibvar = "net.inet.divert.pcblist";
114 		break;
115 	default:
116 		mibvar = "net.inet.raw.pcblist";
117 		break;
118 	}
119 	len = 0;
120 	if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
121 		if (errno != ENOENT)
122 			warn("sysctl: %s", mibvar);
123 		return;
124 	}
125 	if ((buf = malloc(len)) == 0) {
126 		warn("malloc %lu bytes", (u_long)len);
127 		return;
128 	}
129 	if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
130 		warn("sysctl: %s", mibvar);
131 		free(buf);
132 		return;
133 	}
134 
135 	oxig = xig = (struct xinpgen *)buf;
136 	for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
137 	     xig->xig_len > sizeof(struct xinpgen);
138 	     xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
139 		if (istcp) {
140 			tp = &((struct xtcpcb *)xig)->xt_tp;
141 			inp = &((struct xtcpcb *)xig)->xt_inp;
142 			so = &((struct xtcpcb *)xig)->xt_socket;
143 		} else {
144 			inp = &((struct xinpcb *)xig)->xi_inp;
145 			so = &((struct xinpcb *)xig)->xi_socket;
146 		}
147 
148 		/* Ignore sockets for protocols other than the desired one. */
149 		if (so->xso_protocol != proto)
150 			continue;
151 
152 		/* Ignore PCBs which were freed during copyout. */
153 		if (inp->inp_gencnt > oxig->xig_gen)
154 			continue;
155 
156 		if (!aflag && inet_lnaof(inp->inp_laddr) == INADDR_ANY)
157 			continue;
158 
159 		if (first) {
160 			printf("Active Internet connections");
161 			if (aflag)
162 				printf(" (including servers)");
163 			putchar('\n');
164 			if (Aflag)
165 				printf("%-8.8s ", "Socket");
166 			printf("%-5.5s %-6.6s %-6.6s %-21.21s %-21.21s %s\n",
167 				"Proto", "Recv-Q", "Send-Q",
168 				"Local Address", "Foreign Address", "(state)");
169 			first = 0;
170 		}
171 		if (Aflag) {
172 			if (istcp)
173 				printf("%8lx ", (u_long)inp->inp_ppcb);
174 			else
175 				printf("%8lx ", (u_long)so->so_pcb);
176 		}
177 		printf("%-5.5s %6ld %6ld ", name, so->so_rcv.sb_cc,
178 			so->so_snd.sb_cc);
179 		if (nflag) {
180 			inetprint(&inp->inp_laddr, (int)inp->inp_lport,
181 			    name, 1);
182 			inetprint(&inp->inp_faddr, (int)inp->inp_fport,
183 			    name, 1);
184 		} else if (inp->inp_flags & INP_ANONPORT) {
185 			inetprint(&inp->inp_laddr, (int)inp->inp_lport,
186 			    name, 1);
187 			inetprint(&inp->inp_faddr, (int)inp->inp_fport,
188 			    name, 0);
189 		} else {
190 			inetprint(&inp->inp_laddr, (int)inp->inp_lport,
191 			    name, 0);
192 			inetprint(&inp->inp_faddr, (int)inp->inp_fport,
193 			    name, inp->inp_lport != inp->inp_fport);
194 		}
195 		if (istcp) {
196 			if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
197 				printf("%d", tp->t_state);
198                       else {
199 				printf("%s", tcpstates[tp->t_state]);
200 #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
201                               /* Show T/TCP `hidden state' */
202                               if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
203                                       putchar('*');
204 #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
205                       }
206 		}
207 		putchar('\n');
208 	}
209 	if (xig != oxig && xig->xig_gen != oxig->xig_gen) {
210 		if (oxig->xig_count > xig->xig_count) {
211 			printf("Some %s sockets may have been deleted.\n",
212 			       name);
213 		} else if (oxig->xig_count < xig->xig_count) {
214 			printf("Some %s sockets may have been created.\n",
215 			       name);
216 		} else {
217 			printf("Some %s sockets may have been created or deleted",
218 			       name);
219 		}
220 	}
221 	free(buf);
222 }
223 
224 /*
225  * Dump TCP statistics structure.
226  */
227 void
228 tcp_stats(off, name)
229 	u_long off;
230 	char *name;
231 {
232 	struct tcpstat tcpstat;
233 	size_t len = sizeof tcpstat;
234 
235 	if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) {
236 		warn("sysctl: net.inet.tcp.stats");
237 		return;
238 	}
239 
240 	printf ("%s:\n", name);
241 
242 #define	p(f, m) if (tcpstat.f || sflag <= 1) \
243     printf(m, tcpstat.f, plural(tcpstat.f))
244 #define	p1a(f, m) if (tcpstat.f || sflag <= 1) \
245     printf(m, tcpstat.f)
246 #define	p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
247     printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
248 #define	p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
249     printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
250 #define	p3(f, m) if (tcpstat.f || sflag <= 1) \
251     printf(m, tcpstat.f, plurales(tcpstat.f))
252 
253 	p(tcps_sndtotal, "\t%lu packet%s sent\n");
254 	p2(tcps_sndpack,tcps_sndbyte,
255 		"\t\t%lu data packet%s (%lu byte%s)\n");
256 	p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
257 		"\t\t%lu data packet%s (%lu byte%s) retransmitted\n");
258 	p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n");
259 	p2a(tcps_sndacks, tcps_delack,
260 		"\t\t%lu ack-only packet%s (%lu delayed)\n");
261 	p(tcps_sndurg, "\t\t%lu URG only packet%s\n");
262 	p(tcps_sndprobe, "\t\t%lu window probe packet%s\n");
263 	p(tcps_sndwinup, "\t\t%lu window update packet%s\n");
264 	p(tcps_sndctrl, "\t\t%lu control packet%s\n");
265 	p(tcps_rcvtotal, "\t%lu packet%s received\n");
266 	p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n");
267 	p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n");
268 	p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n");
269 	p2(tcps_rcvpack, tcps_rcvbyte,
270 		"\t\t%lu packet%s (%lu byte%s) received in-sequence\n");
271 	p2(tcps_rcvduppack, tcps_rcvdupbyte,
272 		"\t\t%lu completely duplicate packet%s (%lu byte%s)\n");
273 	p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n");
274 	p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
275 		"\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n");
276 	p2(tcps_rcvoopack, tcps_rcvoobyte,
277 		"\t\t%lu out-of-order packet%s (%lu byte%s)\n");
278 	p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
279 		"\t\t%lu packet%s (%lu byte%s) of data after window\n");
280 	p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n");
281 	p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n");
282 	p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n");
283 	p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n");
284 	p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n");
285 	p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n");
286 	p(tcps_connattempt, "\t%lu connection request%s\n");
287 	p(tcps_accepts, "\t%lu connection accept%s\n");
288 	p(tcps_badsyn, "\t%lu bad connection attempt%s\n");
289 	p(tcps_listendrop, "\t%lu listen queue overflow%s\n");
290 	p(tcps_connects, "\t%lu connection%s established (including accepts)\n");
291 	p2(tcps_closed, tcps_drops,
292 		"\t%lu connection%s closed (including %lu drop%s)\n");
293 	p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n");
294 	p(tcps_cachedrttvar,
295 	  "\t\t%lu connection%s updated cached RTT variance on close\n");
296 	p(tcps_cachedssthresh,
297 	  "\t\t%lu connection%s updated cached ssthresh on close\n");
298 	p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n");
299 	p2(tcps_rttupdated, tcps_segstimed,
300 		"\t%lu segment%s updated rtt (of %lu attempt%s)\n");
301 	p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n");
302 	p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n");
303 	p(tcps_persisttimeo, "\t%lu persist timeout%s\n");
304 	p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n");
305 	p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n");
306 	p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n");
307 	p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n");
308 	p(tcps_predack, "\t%lu correct ACK header prediction%s\n");
309 	p(tcps_preddat, "\t%lu correct data packet header prediction%s\n");
310 #undef p
311 #undef p1a
312 #undef p2
313 #undef p2a
314 #undef p3
315 }
316 
317 /*
318  * Dump UDP statistics structure.
319  */
320 void
321 udp_stats(off, name)
322 	u_long off;
323 	char *name;
324 {
325 	struct udpstat udpstat;
326 	size_t len = sizeof udpstat;
327 	u_long delivered;
328 
329 	if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 0, 0) < 0) {
330 		warn("sysctl: net.inet.udp.stats");
331 		return;
332 	}
333 
334 	printf("%s:\n", name);
335 #define	p(f, m) if (udpstat.f || sflag <= 1) \
336     printf(m, udpstat.f, plural(udpstat.f))
337 #define	p1a(f, m) if (udpstat.f || sflag <= 1) \
338     printf(m, udpstat.f)
339 	p(udps_ipackets, "\t%lu datagram%s received\n");
340 	p1a(udps_hdrops, "\t%lu with incomplete header\n");
341 	p1a(udps_badlen, "\t%lu with bad data length field\n");
342 	p1a(udps_badsum, "\t%lu with bad checksum\n");
343 	p1a(udps_noport, "\t%lu dropped due to no socket\n");
344 	p(udps_noportbcast,
345 	    "\t%lu broadcast/multicast datagram%s dropped due to no socket\n");
346 	p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
347 	p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n");
348 	delivered = udpstat.udps_ipackets -
349 		    udpstat.udps_hdrops -
350 		    udpstat.udps_badlen -
351 		    udpstat.udps_badsum -
352 		    udpstat.udps_noport -
353 		    udpstat.udps_noportbcast -
354 		    udpstat.udps_fullsock;
355 	if (delivered || sflag <= 1)
356 		printf("\t%lu delivered\n", delivered);
357 	p(udps_opackets, "\t%lu datagram%s output\n");
358 #undef p
359 #undef p1a
360 }
361 
362 /*
363  * Dump IP statistics structure.
364  */
365 void
366 ip_stats(off, name)
367 	u_long off;
368 	char *name;
369 {
370 	struct ipstat ipstat;
371 	size_t len = sizeof ipstat;
372 
373 	if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, 0, 0) < 0) {
374 		warn("sysctl: net.inet.ip.stats");
375 		return;
376 	}
377 
378 	printf("%s:\n", name);
379 
380 #define	p(f, m) if (ipstat.f || sflag <= 1) \
381     printf(m, ipstat.f, plural(ipstat.f))
382 #define	p1a(f, m) if (ipstat.f || sflag <= 1) \
383     printf(m, ipstat.f)
384 
385 	p(ips_total, "\t%lu total packet%s received\n");
386 	p(ips_badsum, "\t%lu bad header checksum%s\n");
387 	p1a(ips_toosmall, "\t%lu with size smaller than minimum\n");
388 	p1a(ips_tooshort, "\t%lu with data size < data length\n");
389 	p1a(ips_badhlen, "\t%lu with header length < data size\n");
390 	p1a(ips_badlen, "\t%lu with data length < header length\n");
391 	p1a(ips_badoptions, "\t%lu with bad options\n");
392 	p1a(ips_badvers, "\t%lu with incorrect version number\n");
393 	p(ips_fragments, "\t%lu fragment%s received\n");
394 	p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
395 	p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
396 	p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
397 	p(ips_delivered, "\t%lu packet%s for this host\n");
398 	p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
399 	p(ips_forward, "\t%lu packet%s forwarded");
400 	p(ips_fastforward, " (%lu packet%s fast forwarded)");
401 	if (ipstat.ips_forward || sflag <= 1)
402 		putchar('\n');
403 	p(ips_cantforward, "\t%lu packet%s not forwardable\n");
404 	p(ips_notmember,
405 	  "\t%lu packet%s received for unknown multicast group\n");
406 	p(ips_redirectsent, "\t%lu redirect%s sent\n");
407 	p(ips_localout, "\t%lu packet%s sent from this host\n");
408 	p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
409 	p(ips_odropped,
410 	  "\t%lu output packet%s dropped due to no bufs, etc.\n");
411 	p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
412 	p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
413 	p(ips_ofragments, "\t%lu fragment%s created\n");
414 	p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
415 #undef p
416 #undef p1a
417 }
418 
419 static	char *icmpnames[] = {
420 	"echo reply",
421 	"#1",
422 	"#2",
423 	"destination unreachable",
424 	"source quench",
425 	"routing redirect",
426 	"#6",
427 	"#7",
428 	"echo",
429 	"router advertisement",
430 	"router solicitation",
431 	"time exceeded",
432 	"parameter problem",
433 	"time stamp",
434 	"time stamp reply",
435 	"information request",
436 	"information request reply",
437 	"address mask request",
438 	"address mask reply",
439 };
440 
441 /*
442  * Dump ICMP statistics.
443  */
444 void
445 icmp_stats(off, name)
446 	u_long off;
447 	char *name;
448 {
449 	struct icmpstat icmpstat;
450 	int i, first;
451 	int mib[4];		/* CTL_NET + PF_INET + IPPROTO_ICMP + req */
452 	size_t len;
453 
454 	mib[0] = CTL_NET;
455 	mib[1] = PF_INET;
456 	mib[2] = IPPROTO_ICMP;
457 	mib[3] = ICMPCTL_STATS;
458 
459 	len = sizeof icmpstat;
460 	memset(&icmpstat, 0, len);
461 	if (sysctl(mib, 4, &icmpstat, &len, (void *)0, 0) < 0)
462 		return;		/* XXX should complain, but not traditional */
463 
464 	printf("%s:\n", name);
465 
466 #define	p(f, m) if (icmpstat.f || sflag <= 1) \
467     printf(m, icmpstat.f, plural(icmpstat.f))
468 #define	p1a(f, m) if (icmpstat.f || sflag <= 1) \
469     printf(m, icmpstat.f)
470 
471 	p(icps_error, "\t%lu call%s to icmp_error\n");
472 	p(icps_oldicmp,
473 	    "\t%lu error%s not generated 'cuz old message was icmp\n");
474 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
475 		if (icmpstat.icps_outhist[i] != 0) {
476 			if (first) {
477 				printf("\tOutput histogram:\n");
478 				first = 0;
479 			}
480 			printf("\t\t%s: %lu\n", icmpnames[i],
481 				icmpstat.icps_outhist[i]);
482 		}
483 	p(icps_badcode, "\t%lu message%s with bad code fields\n");
484 	p(icps_tooshort, "\t%lu message%s < minimum length\n");
485 	p(icps_checksum, "\t%lu bad checksum%s\n");
486 	p(icps_badlen, "\t%lu message%s with bad length\n");
487 	p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n");
488 	p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n");
489 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
490 		if (icmpstat.icps_inhist[i] != 0) {
491 			if (first) {
492 				printf("\tInput histogram:\n");
493 				first = 0;
494 			}
495 			printf("\t\t%s: %lu\n", icmpnames[i],
496 				icmpstat.icps_inhist[i]);
497 		}
498 	p(icps_reflect, "\t%lu message response%s generated\n");
499 #undef p
500 #undef p1a
501 	mib[3] = ICMPCTL_MASKREPL;
502 	len = sizeof i;
503 	if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0)
504 		return;
505 	printf("\tICMP address mask responses are %sabled\n",
506 	       i ? "en" : "dis");
507 }
508 
509 /*
510  * Dump IGMP statistics structure.
511  */
512 void
513 igmp_stats(off, name)
514 	u_long off;
515 	char *name;
516 {
517 	struct igmpstat igmpstat;
518 	size_t len = sizeof igmpstat;
519 
520 	if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len, 0, 0) < 0) {
521 		warn("sysctl: net.inet.igmp.stats");
522 		return;
523 	}
524 
525 	printf("%s:\n", name);
526 
527 #define	p(f, m) if (igmpstat.f || sflag <= 1) \
528     printf(m, igmpstat.f, plural(igmpstat.f))
529 #define	py(f, m) if (igmpstat.f || sflag <= 1) \
530     printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
531 	p(igps_rcv_total, "\t%u message%s received\n");
532         p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
533         p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
534         py(igps_rcv_queries, "\t%u membership quer%s received\n");
535         py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
536         p(igps_rcv_reports, "\t%u membership report%s received\n");
537         p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
538         p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
539         p(igps_snd_reports, "\t%u membership report%s sent\n");
540 #undef p
541 #undef py
542 }
543 
544 /*
545  * Pretty print an Internet address (net address + port).
546  */
547 void
548 inetprint(in, port, proto,numeric)
549 	register struct in_addr *in;
550 	int port;
551 	char *proto;
552 	int numeric;
553 {
554 	struct servent *sp = 0;
555 	char line[80], *cp;
556 
557 	sprintf(line, "%.*s.", (Aflag && !numeric) ? 12 : 16, inetname(in));
558 	cp = index(line, '\0');
559 	if (!numeric && port)
560 		sp = getservbyport((int)port, proto);
561 	if (sp || port == 0)
562 		sprintf(cp, "%.15s", sp ? sp->s_name : "*");
563 	else
564 		sprintf(cp, "%d", ntohs((u_short)port));
565 	printf("%-21.21s ", line);
566 }
567 
568 /*
569  * Construct an Internet address representation.
570  * If the nflag has been supplied, give
571  * numeric value, otherwise try for symbolic name.
572  */
573 char *
574 inetname(inp)
575 	struct in_addr *inp;
576 {
577 	register char *cp;
578 	static char line[MAXHOSTNAMELEN + 1];
579 	struct hostent *hp;
580 	struct netent *np;
581 
582 	cp = 0;
583 	if (!nflag && inp->s_addr != INADDR_ANY) {
584 		int net = inet_netof(*inp);
585 		int lna = inet_lnaof(*inp);
586 
587 		if (lna == INADDR_ANY) {
588 			np = getnetbyaddr(net, AF_INET);
589 			if (np)
590 				cp = np->n_name;
591 		}
592 		if (cp == 0) {
593 			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
594 			if (hp) {
595 				cp = hp->h_name;
596 				trimdomain(cp);
597 			}
598 		}
599 	}
600 	if (inp->s_addr == INADDR_ANY)
601 		strcpy(line, "*");
602 	else if (cp) {
603 		strncpy(line, cp, sizeof(line) - 1);
604 		line[sizeof(line) - 1] = '\0';
605 	} else {
606 		inp->s_addr = ntohl(inp->s_addr);
607 #define C(x)	((u_int)((x) & 0xff))
608 		sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
609 		    C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
610 	}
611 	return (line);
612 }
613