Home | History | Annotate | Line # | Download | only in netstat
inet.c revision 1.1.1.1
      1      1.1      cgd /*
      2  1.1.1.1  mycroft  * Copyright (c) 1983, 1988, 1993
      3  1.1.1.1  mycroft  *	The Regents of the University of California.  All rights reserved.
      4      1.1      cgd  *
      5      1.1      cgd  * Redistribution and use in source and binary forms, with or without
      6      1.1      cgd  * modification, are permitted provided that the following conditions
      7      1.1      cgd  * are met:
      8      1.1      cgd  * 1. Redistributions of source code must retain the above copyright
      9      1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     10      1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     11      1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     12      1.1      cgd  *    documentation and/or other materials provided with the distribution.
     13      1.1      cgd  * 3. All advertising materials mentioning features or use of this software
     14      1.1      cgd  *    must display the following acknowledgement:
     15      1.1      cgd  *	This product includes software developed by the University of
     16      1.1      cgd  *	California, Berkeley and its contributors.
     17      1.1      cgd  * 4. Neither the name of the University nor the names of its contributors
     18      1.1      cgd  *    may be used to endorse or promote products derived from this software
     19      1.1      cgd  *    without specific prior written permission.
     20      1.1      cgd  *
     21      1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22      1.1      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23      1.1      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24      1.1      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25      1.1      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26      1.1      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27      1.1      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28      1.1      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29      1.1      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30      1.1      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31      1.1      cgd  * SUCH DAMAGE.
     32      1.1      cgd  */
     33      1.1      cgd 
     34      1.1      cgd #ifndef lint
     35  1.1.1.1  mycroft static char sccsid[] = "@(#)inet.c	8.4 (Berkeley) 4/20/94";
     36      1.1      cgd #endif /* not lint */
     37      1.1      cgd 
     38      1.1      cgd #include <sys/param.h>
     39      1.1      cgd #include <sys/socket.h>
     40      1.1      cgd #include <sys/socketvar.h>
     41      1.1      cgd #include <sys/mbuf.h>
     42      1.1      cgd #include <sys/protosw.h>
     43      1.1      cgd 
     44      1.1      cgd #include <net/route.h>
     45      1.1      cgd #include <netinet/in.h>
     46      1.1      cgd #include <netinet/in_systm.h>
     47      1.1      cgd #include <netinet/ip.h>
     48      1.1      cgd #include <netinet/in_pcb.h>
     49      1.1      cgd #include <netinet/ip_icmp.h>
     50      1.1      cgd #include <netinet/icmp_var.h>
     51  1.1.1.1  mycroft #include <netinet/igmp_var.h>
     52      1.1      cgd #include <netinet/ip_var.h>
     53      1.1      cgd #include <netinet/tcp.h>
     54      1.1      cgd #include <netinet/tcpip.h>
     55      1.1      cgd #include <netinet/tcp_seq.h>
     56      1.1      cgd #define TCPSTATES
     57      1.1      cgd #include <netinet/tcp_fsm.h>
     58      1.1      cgd #include <netinet/tcp_timer.h>
     59      1.1      cgd #include <netinet/tcp_var.h>
     60      1.1      cgd #include <netinet/tcp_debug.h>
     61      1.1      cgd #include <netinet/udp.h>
     62      1.1      cgd #include <netinet/udp_var.h>
     63      1.1      cgd 
     64  1.1.1.1  mycroft #include <arpa/inet.h>
     65      1.1      cgd #include <netdb.h>
     66      1.1      cgd #include <stdio.h>
     67      1.1      cgd #include <string.h>
     68  1.1.1.1  mycroft #include <unistd.h>
     69  1.1.1.1  mycroft #include "netstat.h"
     70      1.1      cgd 
     71      1.1      cgd struct	inpcb inpcb;
     72      1.1      cgd struct	tcpcb tcpcb;
     73      1.1      cgd struct	socket sockb;
     74      1.1      cgd 
     75  1.1.1.1  mycroft char	*inetname __P((struct in_addr *));
     76  1.1.1.1  mycroft void	inetprint __P((struct in_addr *, int, char *));
     77      1.1      cgd 
     78      1.1      cgd /*
     79      1.1      cgd  * Print a summary of connections related to an Internet
     80      1.1      cgd  * protocol.  For TCP, also give state of connection.
     81      1.1      cgd  * Listening processes (aflag) are suppressed unless the
     82      1.1      cgd  * -a (all) flag is specified.
     83      1.1      cgd  */
     84  1.1.1.1  mycroft void
     85      1.1      cgd protopr(off, name)
     86  1.1.1.1  mycroft 	u_long off;
     87      1.1      cgd 	char *name;
     88      1.1      cgd {
     89      1.1      cgd 	struct inpcb cb;
     90      1.1      cgd 	register struct inpcb *prev, *next;
     91      1.1      cgd 	int istcp;
     92      1.1      cgd 	static int first = 1;
     93      1.1      cgd 
     94      1.1      cgd 	if (off == 0)
     95      1.1      cgd 		return;
     96      1.1      cgd 	istcp = strcmp(name, "tcp") == 0;
     97  1.1.1.1  mycroft 	kread(off, (char *)&cb, sizeof (struct inpcb));
     98      1.1      cgd 	inpcb = cb;
     99      1.1      cgd 	prev = (struct inpcb *)off;
    100      1.1      cgd 	if (inpcb.inp_next == (struct inpcb *)off)
    101      1.1      cgd 		return;
    102      1.1      cgd 	while (inpcb.inp_next != (struct inpcb *)off) {
    103      1.1      cgd 		next = inpcb.inp_next;
    104  1.1.1.1  mycroft 		kread((u_long)next, (char *)&inpcb, sizeof (inpcb));
    105      1.1      cgd 		if (inpcb.inp_prev != prev) {
    106      1.1      cgd 			printf("???\n");
    107      1.1      cgd 			break;
    108      1.1      cgd 		}
    109      1.1      cgd 		if (!aflag &&
    110      1.1      cgd 		  inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) {
    111      1.1      cgd 			prev = next;
    112      1.1      cgd 			continue;
    113      1.1      cgd 		}
    114  1.1.1.1  mycroft 		kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb));
    115      1.1      cgd 		if (istcp) {
    116  1.1.1.1  mycroft 			kread((u_long)inpcb.inp_ppcb,
    117  1.1.1.1  mycroft 			    (char *)&tcpcb, sizeof (tcpcb));
    118      1.1      cgd 		}
    119      1.1      cgd 		if (first) {
    120      1.1      cgd 			printf("Active Internet connections");
    121      1.1      cgd 			if (aflag)
    122      1.1      cgd 				printf(" (including servers)");
    123      1.1      cgd 			putchar('\n');
    124      1.1      cgd 			if (Aflag)
    125      1.1      cgd 				printf("%-8.8s ", "PCB");
    126      1.1      cgd 			printf(Aflag ?
    127      1.1      cgd 				"%-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n" :
    128      1.1      cgd 				"%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
    129      1.1      cgd 				"Proto", "Recv-Q", "Send-Q",
    130      1.1      cgd 				"Local Address", "Foreign Address", "(state)");
    131      1.1      cgd 			first = 0;
    132      1.1      cgd 		}
    133      1.1      cgd 		if (Aflag)
    134      1.1      cgd 			if (istcp)
    135      1.1      cgd 				printf("%8x ", inpcb.inp_ppcb);
    136      1.1      cgd 			else
    137      1.1      cgd 				printf("%8x ", next);
    138      1.1      cgd 		printf("%-5.5s %6d %6d ", name, sockb.so_rcv.sb_cc,
    139      1.1      cgd 			sockb.so_snd.sb_cc);
    140  1.1.1.1  mycroft 		inetprint(&inpcb.inp_laddr, (int)inpcb.inp_lport, name);
    141  1.1.1.1  mycroft 		inetprint(&inpcb.inp_faddr, (int)inpcb.inp_fport, name);
    142      1.1      cgd 		if (istcp) {
    143      1.1      cgd 			if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
    144      1.1      cgd 				printf(" %d", tcpcb.t_state);
    145      1.1      cgd 			else
    146      1.1      cgd 				printf(" %s", tcpstates[tcpcb.t_state]);
    147      1.1      cgd 		}
    148      1.1      cgd 		putchar('\n');
    149      1.1      cgd 		prev = next;
    150      1.1      cgd 	}
    151      1.1      cgd }
    152      1.1      cgd 
    153      1.1      cgd /*
    154      1.1      cgd  * Dump TCP statistics structure.
    155      1.1      cgd  */
    156  1.1.1.1  mycroft void
    157      1.1      cgd tcp_stats(off, name)
    158  1.1.1.1  mycroft 	u_long off;
    159      1.1      cgd 	char *name;
    160      1.1      cgd {
    161      1.1      cgd 	struct tcpstat tcpstat;
    162      1.1      cgd 
    163      1.1      cgd 	if (off == 0)
    164      1.1      cgd 		return;
    165      1.1      cgd 	printf ("%s:\n", name);
    166  1.1.1.1  mycroft 	kread(off, (char *)&tcpstat, sizeof (tcpstat));
    167  1.1.1.1  mycroft 
    168  1.1.1.1  mycroft #define	p(f, m) if (tcpstat.f || sflag <= 1) \
    169  1.1.1.1  mycroft     printf(m, tcpstat.f, plural(tcpstat.f))
    170  1.1.1.1  mycroft #define	p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
    171  1.1.1.1  mycroft     printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
    172  1.1.1.1  mycroft #define	p3(f, m) if (tcpstat.f || sflag <= 1) \
    173  1.1.1.1  mycroft     printf(m, tcpstat.f, plurales(tcpstat.f))
    174      1.1      cgd 
    175      1.1      cgd 	p(tcps_sndtotal, "\t%d packet%s sent\n");
    176      1.1      cgd 	p2(tcps_sndpack,tcps_sndbyte,
    177      1.1      cgd 		"\t\t%d data packet%s (%d byte%s)\n");
    178      1.1      cgd 	p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
    179      1.1      cgd 		"\t\t%d data packet%s (%d byte%s) retransmitted\n");
    180      1.1      cgd 	p2(tcps_sndacks, tcps_delack,
    181      1.1      cgd 		"\t\t%d ack-only packet%s (%d delayed)\n");
    182      1.1      cgd 	p(tcps_sndurg, "\t\t%d URG only packet%s\n");
    183      1.1      cgd 	p(tcps_sndprobe, "\t\t%d window probe packet%s\n");
    184      1.1      cgd 	p(tcps_sndwinup, "\t\t%d window update packet%s\n");
    185      1.1      cgd 	p(tcps_sndctrl, "\t\t%d control packet%s\n");
    186      1.1      cgd 	p(tcps_rcvtotal, "\t%d packet%s received\n");
    187      1.1      cgd 	p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%d ack%s (for %d byte%s)\n");
    188      1.1      cgd 	p(tcps_rcvdupack, "\t\t%d duplicate ack%s\n");
    189      1.1      cgd 	p(tcps_rcvacktoomuch, "\t\t%d ack%s for unsent data\n");
    190      1.1      cgd 	p2(tcps_rcvpack, tcps_rcvbyte,
    191      1.1      cgd 		"\t\t%d packet%s (%d byte%s) received in-sequence\n");
    192      1.1      cgd 	p2(tcps_rcvduppack, tcps_rcvdupbyte,
    193      1.1      cgd 		"\t\t%d completely duplicate packet%s (%d byte%s)\n");
    194  1.1.1.1  mycroft 	p(tcps_pawsdrop, "\t\t%d old duplicate packet%s\n");
    195      1.1      cgd 	p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
    196      1.1      cgd 		"\t\t%d packet%s with some dup. data (%d byte%s duped)\n");
    197      1.1      cgd 	p2(tcps_rcvoopack, tcps_rcvoobyte,
    198      1.1      cgd 		"\t\t%d out-of-order packet%s (%d byte%s)\n");
    199      1.1      cgd 	p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
    200      1.1      cgd 		"\t\t%d packet%s (%d byte%s) of data after window\n");
    201      1.1      cgd 	p(tcps_rcvwinprobe, "\t\t%d window probe%s\n");
    202      1.1      cgd 	p(tcps_rcvwinupd, "\t\t%d window update packet%s\n");
    203      1.1      cgd 	p(tcps_rcvafterclose, "\t\t%d packet%s received after close\n");
    204      1.1      cgd 	p(tcps_rcvbadsum, "\t\t%d discarded for bad checksum%s\n");
    205      1.1      cgd 	p(tcps_rcvbadoff, "\t\t%d discarded for bad header offset field%s\n");
    206      1.1      cgd 	p(tcps_rcvshort, "\t\t%d discarded because packet too short\n");
    207      1.1      cgd 	p(tcps_connattempt, "\t%d connection request%s\n");
    208      1.1      cgd 	p(tcps_accepts, "\t%d connection accept%s\n");
    209      1.1      cgd 	p(tcps_connects, "\t%d connection%s established (including accepts)\n");
    210      1.1      cgd 	p2(tcps_closed, tcps_drops,
    211      1.1      cgd 		"\t%d connection%s closed (including %d drop%s)\n");
    212      1.1      cgd 	p(tcps_conndrops, "\t%d embryonic connection%s dropped\n");
    213      1.1      cgd 	p2(tcps_rttupdated, tcps_segstimed,
    214      1.1      cgd 		"\t%d segment%s updated rtt (of %d attempt%s)\n");
    215      1.1      cgd 	p(tcps_rexmttimeo, "\t%d retransmit timeout%s\n");
    216      1.1      cgd 	p(tcps_timeoutdrop, "\t\t%d connection%s dropped by rexmit timeout\n");
    217      1.1      cgd 	p(tcps_persisttimeo, "\t%d persist timeout%s\n");
    218      1.1      cgd 	p(tcps_keeptimeo, "\t%d keepalive timeout%s\n");
    219      1.1      cgd 	p(tcps_keepprobe, "\t\t%d keepalive probe%s sent\n");
    220      1.1      cgd 	p(tcps_keepdrops, "\t\t%d connection%s dropped by keepalive\n");
    221  1.1.1.1  mycroft 	p(tcps_predack, "\t%d correct ACK header prediction%s\n");
    222  1.1.1.1  mycroft 	p(tcps_preddat, "\t%d correct data packet header prediction%s\n");
    223  1.1.1.1  mycroft 	p3(tcps_pcbcachemiss, "\t%d PCB cache miss%s\n");
    224      1.1      cgd #undef p
    225      1.1      cgd #undef p2
    226  1.1.1.1  mycroft #undef p3
    227      1.1      cgd }
    228      1.1      cgd 
    229      1.1      cgd /*
    230      1.1      cgd  * Dump UDP statistics structure.
    231      1.1      cgd  */
    232  1.1.1.1  mycroft void
    233      1.1      cgd udp_stats(off, name)
    234  1.1.1.1  mycroft 	u_long off;
    235      1.1      cgd 	char *name;
    236      1.1      cgd {
    237      1.1      cgd 	struct udpstat udpstat;
    238  1.1.1.1  mycroft 	u_long delivered;
    239      1.1      cgd 
    240      1.1      cgd 	if (off == 0)
    241      1.1      cgd 		return;
    242  1.1.1.1  mycroft 	kread(off, (char *)&udpstat, sizeof (udpstat));
    243  1.1.1.1  mycroft 	printf("%s:\n", name);
    244  1.1.1.1  mycroft #define	p(f, m) if (udpstat.f || sflag <= 1) \
    245  1.1.1.1  mycroft     printf(m, udpstat.f, plural(udpstat.f))
    246  1.1.1.1  mycroft 	p(udps_ipackets, "\t%u datagram%s received\n");
    247  1.1.1.1  mycroft 	p(udps_hdrops, "\t%u with incomplete header\n");
    248  1.1.1.1  mycroft 	p(udps_badlen, "\t%u with bad data length field\n");
    249  1.1.1.1  mycroft 	p(udps_badsum, "\t%u with bad checksum\n");
    250  1.1.1.1  mycroft 	p(udps_noport, "\t%u dropped due to no socket\n");
    251  1.1.1.1  mycroft 	p(udps_noportbcast, "\t%u broadcast/multicast datagram%s dropped due to no socket\n");
    252  1.1.1.1  mycroft 	p(udps_fullsock, "\t%u dropped due to full socket buffers\n");
    253  1.1.1.1  mycroft 	delivered = udpstat.udps_ipackets -
    254  1.1.1.1  mycroft 		    udpstat.udps_hdrops -
    255  1.1.1.1  mycroft 		    udpstat.udps_badlen -
    256  1.1.1.1  mycroft 		    udpstat.udps_badsum -
    257  1.1.1.1  mycroft 		    udpstat.udps_noport -
    258  1.1.1.1  mycroft 		    udpstat.udps_noportbcast -
    259  1.1.1.1  mycroft 		    udpstat.udps_fullsock;
    260  1.1.1.1  mycroft 	if (delivered || sflag <= 1)
    261  1.1.1.1  mycroft 		printf("\t%u delivered\n", delivered);
    262  1.1.1.1  mycroft 	p(udps_opackets, "\t%u datagram%s output\n");
    263  1.1.1.1  mycroft #undef p
    264      1.1      cgd }
    265      1.1      cgd 
    266      1.1      cgd /*
    267      1.1      cgd  * Dump IP statistics structure.
    268      1.1      cgd  */
    269  1.1.1.1  mycroft void
    270      1.1      cgd ip_stats(off, name)
    271  1.1.1.1  mycroft 	u_long off;
    272      1.1      cgd 	char *name;
    273      1.1      cgd {
    274      1.1      cgd 	struct ipstat ipstat;
    275      1.1      cgd 
    276      1.1      cgd 	if (off == 0)
    277      1.1      cgd 		return;
    278  1.1.1.1  mycroft 	kread(off, (char *)&ipstat, sizeof (ipstat));
    279  1.1.1.1  mycroft 	printf("%s:\n", name);
    280  1.1.1.1  mycroft 
    281  1.1.1.1  mycroft #define	p(f, m) if (ipstat.f || sflag <= 1) \
    282  1.1.1.1  mycroft     printf(m, ipstat.f, plural(ipstat.f))
    283  1.1.1.1  mycroft 
    284  1.1.1.1  mycroft 	p(ips_total, "\t%u total packet%s received\n");
    285  1.1.1.1  mycroft 	p(ips_badsum, "\t%u bad header checksum%s\n");
    286  1.1.1.1  mycroft 	p(ips_toosmall, "\t%u with size smaller than minimum\n");
    287  1.1.1.1  mycroft 	p(ips_tooshort, "\t%u with data size < data length\n");
    288  1.1.1.1  mycroft 	p(ips_badhlen, "\t%u with header length < data size\n");
    289  1.1.1.1  mycroft 	p(ips_badlen, "\t%u with data length < header length\n");
    290  1.1.1.1  mycroft 	p(ips_badoptions, "\t%u with bad options\n");
    291  1.1.1.1  mycroft 	p(ips_badvers, "\t%u with incorrect version number\n");
    292  1.1.1.1  mycroft 	p(ips_fragments, "\t%u fragment%s received\n");
    293  1.1.1.1  mycroft 	p(ips_fragdropped, "\t%u fragment%s dropped (dup or out of space)\n");
    294  1.1.1.1  mycroft 	p(ips_fragtimeout, "\t%u fragment%s dropped after timeout\n");
    295  1.1.1.1  mycroft 	p(ips_reassembled, "\t%u packet%s reassembled ok\n");
    296  1.1.1.1  mycroft 	p(ips_delivered, "\t%u packet%s for this host\n");
    297  1.1.1.1  mycroft 	p(ips_noproto, "\t%u packet%s for unknown/unsupported protocol\n");
    298  1.1.1.1  mycroft 	p(ips_forward, "\t%u packet%s forwarded\n");
    299  1.1.1.1  mycroft 	p(ips_cantforward, "\t%u packet%s not forwardable\n");
    300  1.1.1.1  mycroft 	p(ips_redirectsent, "\t%u redirect%s sent\n");
    301  1.1.1.1  mycroft 	p(ips_localout, "\t%u packet%s sent from this host\n");
    302  1.1.1.1  mycroft 	p(ips_rawout, "\t%u packet%s sent with fabricated ip header\n");
    303  1.1.1.1  mycroft 	p(ips_odropped, "\t%u output packet%s dropped due to no bufs, etc.\n");
    304  1.1.1.1  mycroft 	p(ips_noroute, "\t%u output packet%s discarded due to no route\n");
    305  1.1.1.1  mycroft 	p(ips_fragmented, "\t%u output datagram%s fragmented\n");
    306  1.1.1.1  mycroft 	p(ips_ofragments, "\t%u fragment%s created\n");
    307  1.1.1.1  mycroft 	p(ips_cantfrag, "\t%u datagram%s that can't be fragmented\n");
    308  1.1.1.1  mycroft #undef p
    309      1.1      cgd }
    310      1.1      cgd 
    311      1.1      cgd static	char *icmpnames[] = {
    312      1.1      cgd 	"echo reply",
    313      1.1      cgd 	"#1",
    314      1.1      cgd 	"#2",
    315      1.1      cgd 	"destination unreachable",
    316      1.1      cgd 	"source quench",
    317      1.1      cgd 	"routing redirect",
    318      1.1      cgd 	"#6",
    319      1.1      cgd 	"#7",
    320      1.1      cgd 	"echo",
    321      1.1      cgd 	"#9",
    322      1.1      cgd 	"#10",
    323      1.1      cgd 	"time exceeded",
    324      1.1      cgd 	"parameter problem",
    325      1.1      cgd 	"time stamp",
    326      1.1      cgd 	"time stamp reply",
    327      1.1      cgd 	"information request",
    328      1.1      cgd 	"information request reply",
    329      1.1      cgd 	"address mask request",
    330      1.1      cgd 	"address mask reply",
    331      1.1      cgd };
    332      1.1      cgd 
    333      1.1      cgd /*
    334      1.1      cgd  * Dump ICMP statistics.
    335      1.1      cgd  */
    336  1.1.1.1  mycroft void
    337      1.1      cgd icmp_stats(off, name)
    338  1.1.1.1  mycroft 	u_long off;
    339      1.1      cgd 	char *name;
    340      1.1      cgd {
    341      1.1      cgd 	struct icmpstat icmpstat;
    342      1.1      cgd 	register int i, first;
    343      1.1      cgd 
    344      1.1      cgd 	if (off == 0)
    345      1.1      cgd 		return;
    346  1.1.1.1  mycroft 	kread(off, (char *)&icmpstat, sizeof (icmpstat));
    347  1.1.1.1  mycroft 	printf("%s:\n", name);
    348  1.1.1.1  mycroft 
    349  1.1.1.1  mycroft #define	p(f, m) if (icmpstat.f || sflag <= 1) \
    350  1.1.1.1  mycroft     printf(m, icmpstat.f, plural(icmpstat.f))
    351  1.1.1.1  mycroft 
    352  1.1.1.1  mycroft 	p(icps_error, "\t%u call%s to icmp_error\n");
    353  1.1.1.1  mycroft 	p(icps_oldicmp,
    354  1.1.1.1  mycroft 	    "\t%u error%s not generated 'cuz old message was icmp\n");
    355      1.1      cgd 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
    356      1.1      cgd 		if (icmpstat.icps_outhist[i] != 0) {
    357      1.1      cgd 			if (first) {
    358      1.1      cgd 				printf("\tOutput histogram:\n");
    359      1.1      cgd 				first = 0;
    360      1.1      cgd 			}
    361      1.1      cgd 			printf("\t\t%s: %u\n", icmpnames[i],
    362      1.1      cgd 				icmpstat.icps_outhist[i]);
    363      1.1      cgd 		}
    364  1.1.1.1  mycroft 	p(icps_badcode, "\t%u message%s with bad code fields\n");
    365  1.1.1.1  mycroft 	p(icps_tooshort, "\t%u message%s < minimum length\n");
    366  1.1.1.1  mycroft 	p(icps_checksum, "\t%u bad checksum%s\n");
    367  1.1.1.1  mycroft 	p(icps_badlen, "\t%u message%s with bad length\n");
    368      1.1      cgd 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
    369      1.1      cgd 		if (icmpstat.icps_inhist[i] != 0) {
    370      1.1      cgd 			if (first) {
    371      1.1      cgd 				printf("\tInput histogram:\n");
    372      1.1      cgd 				first = 0;
    373      1.1      cgd 			}
    374      1.1      cgd 			printf("\t\t%s: %u\n", icmpnames[i],
    375      1.1      cgd 				icmpstat.icps_inhist[i]);
    376      1.1      cgd 		}
    377  1.1.1.1  mycroft 	p(icps_reflect, "\t%u message response%s generated\n");
    378  1.1.1.1  mycroft #undef p
    379  1.1.1.1  mycroft }
    380  1.1.1.1  mycroft 
    381  1.1.1.1  mycroft /*
    382  1.1.1.1  mycroft  * Dump IGMP statistics structure.
    383  1.1.1.1  mycroft  */
    384  1.1.1.1  mycroft void
    385  1.1.1.1  mycroft igmp_stats(off, name)
    386  1.1.1.1  mycroft 	u_long off;
    387  1.1.1.1  mycroft 	char *name;
    388  1.1.1.1  mycroft {
    389  1.1.1.1  mycroft 	struct igmpstat igmpstat;
    390  1.1.1.1  mycroft 
    391  1.1.1.1  mycroft 	if (off == 0)
    392  1.1.1.1  mycroft 		return;
    393  1.1.1.1  mycroft 	kread(off, (char *)&igmpstat, sizeof (igmpstat));
    394  1.1.1.1  mycroft 	printf("%s:\n", name);
    395  1.1.1.1  mycroft 
    396  1.1.1.1  mycroft #define	p(f, m) if (igmpstat.f || sflag <= 1) \
    397  1.1.1.1  mycroft     printf(m, igmpstat.f, plural(igmpstat.f))
    398  1.1.1.1  mycroft #define	py(f, m) if (igmpstat.f || sflag <= 1) \
    399  1.1.1.1  mycroft     printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
    400  1.1.1.1  mycroft 	p(igps_rcv_total, "\t%u message%s received\n");
    401  1.1.1.1  mycroft         p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
    402  1.1.1.1  mycroft         p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
    403  1.1.1.1  mycroft         py(igps_rcv_queries, "\t%u membership quer%s received\n");
    404  1.1.1.1  mycroft         py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n");
    405  1.1.1.1  mycroft         p(igps_rcv_reports, "\t%u membership report%s received\n");
    406  1.1.1.1  mycroft         p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n");
    407  1.1.1.1  mycroft         p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n");
    408  1.1.1.1  mycroft         p(igps_snd_reports, "\t%u membership report%s sent\n");
    409  1.1.1.1  mycroft #undef p
    410  1.1.1.1  mycroft #undef py
    411      1.1      cgd }
    412      1.1      cgd 
    413      1.1      cgd /*
    414      1.1      cgd  * Pretty print an Internet address (net address + port).
    415      1.1      cgd  * If the nflag was specified, use numbers instead of names.
    416      1.1      cgd  */
    417  1.1.1.1  mycroft void
    418      1.1      cgd inetprint(in, port, proto)
    419      1.1      cgd 	register struct in_addr *in;
    420  1.1.1.1  mycroft 	int port;
    421      1.1      cgd 	char *proto;
    422      1.1      cgd {
    423      1.1      cgd 	struct servent *sp = 0;
    424  1.1.1.1  mycroft 	char line[80], *cp;
    425      1.1      cgd 	int width;
    426      1.1      cgd 
    427  1.1.1.1  mycroft 	sprintf(line, "%.*s.", (Aflag && !nflag) ? 12 : 16, inetname(in));
    428      1.1      cgd 	cp = index(line, '\0');
    429      1.1      cgd 	if (!nflag && port)
    430      1.1      cgd 		sp = getservbyport((int)port, proto);
    431      1.1      cgd 	if (sp || port == 0)
    432      1.1      cgd 		sprintf(cp, "%.8s", sp ? sp->s_name : "*");
    433      1.1      cgd 	else
    434      1.1      cgd 		sprintf(cp, "%d", ntohs((u_short)port));
    435      1.1      cgd 	width = Aflag ? 18 : 22;
    436      1.1      cgd 	printf(" %-*.*s", width, width, line);
    437      1.1      cgd }
    438      1.1      cgd 
    439      1.1      cgd /*
    440      1.1      cgd  * Construct an Internet address representation.
    441  1.1.1.1  mycroft  * If the nflag has been supplied, give
    442      1.1      cgd  * numeric value, otherwise try for symbolic name.
    443      1.1      cgd  */
    444      1.1      cgd char *
    445  1.1.1.1  mycroft inetname(inp)
    446  1.1.1.1  mycroft 	struct in_addr *inp;
    447      1.1      cgd {
    448      1.1      cgd 	register char *cp;
    449      1.1      cgd 	static char line[50];
    450      1.1      cgd 	struct hostent *hp;
    451      1.1      cgd 	struct netent *np;
    452      1.1      cgd 	static char domain[MAXHOSTNAMELEN + 1];
    453      1.1      cgd 	static int first = 1;
    454      1.1      cgd 
    455      1.1      cgd 	if (first && !nflag) {
    456      1.1      cgd 		first = 0;
    457      1.1      cgd 		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
    458      1.1      cgd 		    (cp = index(domain, '.')))
    459      1.1      cgd 			(void) strcpy(domain, cp + 1);
    460      1.1      cgd 		else
    461      1.1      cgd 			domain[0] = 0;
    462      1.1      cgd 	}
    463      1.1      cgd 	cp = 0;
    464  1.1.1.1  mycroft 	if (!nflag && inp->s_addr != INADDR_ANY) {
    465  1.1.1.1  mycroft 		int net = inet_netof(*inp);
    466  1.1.1.1  mycroft 		int lna = inet_lnaof(*inp);
    467      1.1      cgd 
    468      1.1      cgd 		if (lna == INADDR_ANY) {
    469      1.1      cgd 			np = getnetbyaddr(net, AF_INET);
    470      1.1      cgd 			if (np)
    471      1.1      cgd 				cp = np->n_name;
    472      1.1      cgd 		}
    473      1.1      cgd 		if (cp == 0) {
    474  1.1.1.1  mycroft 			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
    475      1.1      cgd 			if (hp) {
    476      1.1      cgd 				if ((cp = index(hp->h_name, '.')) &&
    477      1.1      cgd 				    !strcmp(cp + 1, domain))
    478      1.1      cgd 					*cp = 0;
    479      1.1      cgd 				cp = hp->h_name;
    480      1.1      cgd 			}
    481      1.1      cgd 		}
    482      1.1      cgd 	}
    483  1.1.1.1  mycroft 	if (inp->s_addr == INADDR_ANY)
    484      1.1      cgd 		strcpy(line, "*");
    485      1.1      cgd 	else if (cp)
    486      1.1      cgd 		strcpy(line, cp);
    487      1.1      cgd 	else {
    488  1.1.1.1  mycroft 		inp->s_addr = ntohl(inp->s_addr);
    489      1.1      cgd #define C(x)	((x) & 0xff)
    490  1.1.1.1  mycroft 		sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
    491  1.1.1.1  mycroft 		    C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
    492      1.1      cgd 	}
    493      1.1      cgd 	return (line);
    494      1.1      cgd }
    495