Home | History | Annotate | Line # | Download | only in netstat
inet.c revision 1.8
      1  1.1     cgd /*
      2  1.1     cgd  * Copyright (c) 1983, 1988 Regents of the University of California.
      3  1.1     cgd  * 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.6  brezak /* from: static char sccsid[] = "@(#)inet.c	5.15 (Berkeley) 6/18/90"; */
     36  1.6  brezak static char rcsid[] = "inet.c,v 1.4 1993/05/20 12:03:49 cgd Exp";
     37  1.1     cgd #endif /* not lint */
     38  1.1     cgd 
     39  1.1     cgd #include <sys/param.h>
     40  1.1     cgd #include <sys/socket.h>
     41  1.1     cgd #include <sys/socketvar.h>
     42  1.1     cgd #include <sys/mbuf.h>
     43  1.1     cgd #include <sys/protosw.h>
     44  1.1     cgd 
     45  1.1     cgd #include <net/route.h>
     46  1.1     cgd #include <netinet/in.h>
     47  1.1     cgd #include <netinet/in_systm.h>
     48  1.1     cgd #include <netinet/ip.h>
     49  1.1     cgd #include <netinet/in_pcb.h>
     50  1.1     cgd #include <netinet/ip_icmp.h>
     51  1.1     cgd #include <netinet/icmp_var.h>
     52  1.6  brezak #include <netinet/igmp_var.h>
     53  1.1     cgd #include <netinet/ip_var.h>
     54  1.1     cgd #include <netinet/tcp.h>
     55  1.1     cgd #include <netinet/tcpip.h>
     56  1.1     cgd #include <netinet/tcp_seq.h>
     57  1.1     cgd #define TCPSTATES
     58  1.1     cgd #include <netinet/tcp_fsm.h>
     59  1.1     cgd #include <netinet/tcp_timer.h>
     60  1.1     cgd #include <netinet/tcp_var.h>
     61  1.1     cgd #include <netinet/tcp_debug.h>
     62  1.1     cgd #include <netinet/udp.h>
     63  1.1     cgd #include <netinet/udp_var.h>
     64  1.1     cgd 
     65  1.1     cgd #include <netdb.h>
     66  1.1     cgd 
     67  1.1     cgd #include <stdio.h>
     68  1.1     cgd #include <string.h>
     69  1.7     cgd #include <nlist.h>
     70  1.7     cgd #include <kvm.h>
     71  1.1     cgd 
     72  1.1     cgd struct	inpcb inpcb;
     73  1.1     cgd struct	tcpcb tcpcb;
     74  1.1     cgd struct	socket sockb;
     75  1.1     cgd extern	int Aflag;
     76  1.1     cgd extern	int aflag;
     77  1.1     cgd extern	int nflag;
     78  1.1     cgd extern	char *plural();
     79  1.1     cgd 
     80  1.1     cgd char	*inetname();
     81  1.1     cgd 
     82  1.1     cgd /*
     83  1.1     cgd  * Print a summary of connections related to an Internet
     84  1.1     cgd  * protocol.  For TCP, also give state of connection.
     85  1.1     cgd  * Listening processes (aflag) are suppressed unless the
     86  1.1     cgd  * -a (all) flag is specified.
     87  1.1     cgd  */
     88  1.1     cgd protopr(off, name)
     89  1.8     cgd 	u_long off;
     90  1.1     cgd 	char *name;
     91  1.1     cgd {
     92  1.1     cgd 	struct inpcb cb;
     93  1.1     cgd 	register struct inpcb *prev, *next;
     94  1.1     cgd 	int istcp;
     95  1.1     cgd 	static int first = 1;
     96  1.1     cgd 
     97  1.1     cgd 	if (off == 0)
     98  1.1     cgd 		return;
     99  1.1     cgd 	istcp = strcmp(name, "tcp") == 0;
    100  1.7     cgd 	kvm_read((void *)(long)off, (char *)&cb, sizeof (struct inpcb));
    101  1.1     cgd 	inpcb = cb;
    102  1.7     cgd 	prev = (struct inpcb *)(long)off;
    103  1.7     cgd 	if (inpcb.inp_next == (struct inpcb *)(long)off)
    104  1.1     cgd 		return;
    105  1.7     cgd 	while (inpcb.inp_next != (struct inpcb *)(long)off) {
    106  1.1     cgd 
    107  1.1     cgd 		next = inpcb.inp_next;
    108  1.7     cgd 		kvm_read(next, (char *)&inpcb, sizeof (inpcb));
    109  1.1     cgd 		if (inpcb.inp_prev != prev) {
    110  1.1     cgd 			printf("???\n");
    111  1.1     cgd 			break;
    112  1.1     cgd 		}
    113  1.1     cgd 		if (!aflag &&
    114  1.1     cgd 		  inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) {
    115  1.1     cgd 			prev = next;
    116  1.1     cgd 			continue;
    117  1.1     cgd 		}
    118  1.7     cgd 		kvm_read(inpcb.inp_socket, (char *)&sockb, sizeof (sockb));
    119  1.1     cgd 		if (istcp) {
    120  1.7     cgd 			kvm_read(inpcb.inp_ppcb, (char *)&tcpcb,
    121  1.7     cgd 			    sizeof (tcpcb));
    122  1.1     cgd 		}
    123  1.1     cgd 		if (first) {
    124  1.1     cgd 			printf("Active Internet connections");
    125  1.1     cgd 			if (aflag)
    126  1.1     cgd 				printf(" (including servers)");
    127  1.1     cgd 			putchar('\n');
    128  1.1     cgd 			if (Aflag)
    129  1.1     cgd 				printf("%-8.8s ", "PCB");
    130  1.1     cgd 			printf(Aflag ?
    131  1.1     cgd 				"%-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n" :
    132  1.1     cgd 				"%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
    133  1.1     cgd 				"Proto", "Recv-Q", "Send-Q",
    134  1.1     cgd 				"Local Address", "Foreign Address", "(state)");
    135  1.1     cgd 			first = 0;
    136  1.1     cgd 		}
    137  1.1     cgd 		if (Aflag)
    138  1.1     cgd 			if (istcp)
    139  1.1     cgd 				printf("%8x ", inpcb.inp_ppcb);
    140  1.1     cgd 			else
    141  1.1     cgd 				printf("%8x ", next);
    142  1.1     cgd 		printf("%-5.5s %6d %6d ", name, sockb.so_rcv.sb_cc,
    143  1.1     cgd 			sockb.so_snd.sb_cc);
    144  1.1     cgd 		inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name);
    145  1.1     cgd 		inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name);
    146  1.1     cgd 		if (istcp) {
    147  1.1     cgd 			if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
    148  1.1     cgd 				printf(" %d", tcpcb.t_state);
    149  1.1     cgd 			else
    150  1.1     cgd 				printf(" %s", tcpstates[tcpcb.t_state]);
    151  1.1     cgd 		}
    152  1.1     cgd 		putchar('\n');
    153  1.1     cgd 		prev = next;
    154  1.1     cgd 	}
    155  1.1     cgd }
    156  1.1     cgd 
    157  1.1     cgd /*
    158  1.1     cgd  * Dump TCP statistics structure.
    159  1.1     cgd  */
    160  1.1     cgd tcp_stats(off, name)
    161  1.8     cgd 	u_long off;
    162  1.1     cgd 	char *name;
    163  1.1     cgd {
    164  1.1     cgd 	struct tcpstat tcpstat;
    165  1.1     cgd 
    166  1.1     cgd 	if (off == 0)
    167  1.1     cgd 		return;
    168  1.1     cgd 	printf ("%s:\n", name);
    169  1.7     cgd 	kvm_read((void *)(long)off, (char *)&tcpstat, sizeof (tcpstat));
    170  1.1     cgd 
    171  1.1     cgd #define	p(f, m)		printf(m, tcpstat.f, plural(tcpstat.f))
    172  1.1     cgd #define	p2(f1, f2, m)	printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
    173  1.1     cgd 
    174  1.1     cgd 	p(tcps_sndtotal, "\t%d packet%s sent\n");
    175  1.1     cgd 	p2(tcps_sndpack,tcps_sndbyte,
    176  1.1     cgd 		"\t\t%d data packet%s (%d byte%s)\n");
    177  1.1     cgd 	p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
    178  1.1     cgd 		"\t\t%d data packet%s (%d byte%s) retransmitted\n");
    179  1.1     cgd 	p2(tcps_sndacks, tcps_delack,
    180  1.1     cgd 		"\t\t%d ack-only packet%s (%d delayed)\n");
    181  1.1     cgd 	p(tcps_sndurg, "\t\t%d URG only packet%s\n");
    182  1.1     cgd 	p(tcps_sndprobe, "\t\t%d window probe packet%s\n");
    183  1.1     cgd 	p(tcps_sndwinup, "\t\t%d window update packet%s\n");
    184  1.1     cgd 	p(tcps_sndctrl, "\t\t%d control packet%s\n");
    185  1.1     cgd 	p(tcps_rcvtotal, "\t%d packet%s received\n");
    186  1.1     cgd 	p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%d ack%s (for %d byte%s)\n");
    187  1.1     cgd 	p(tcps_rcvdupack, "\t\t%d duplicate ack%s\n");
    188  1.1     cgd 	p(tcps_rcvacktoomuch, "\t\t%d ack%s for unsent data\n");
    189  1.1     cgd 	p2(tcps_rcvpack, tcps_rcvbyte,
    190  1.1     cgd 		"\t\t%d packet%s (%d byte%s) received in-sequence\n");
    191  1.1     cgd 	p2(tcps_rcvduppack, tcps_rcvdupbyte,
    192  1.1     cgd 		"\t\t%d completely duplicate packet%s (%d byte%s)\n");
    193  1.1     cgd 	p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
    194  1.1     cgd 		"\t\t%d packet%s with some dup. data (%d byte%s duped)\n");
    195  1.1     cgd 	p2(tcps_rcvoopack, tcps_rcvoobyte,
    196  1.1     cgd 		"\t\t%d out-of-order packet%s (%d byte%s)\n");
    197  1.1     cgd 	p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
    198  1.1     cgd 		"\t\t%d packet%s (%d byte%s) of data after window\n");
    199  1.1     cgd 	p(tcps_rcvwinprobe, "\t\t%d window probe%s\n");
    200  1.1     cgd 	p(tcps_rcvwinupd, "\t\t%d window update packet%s\n");
    201  1.1     cgd 	p(tcps_rcvafterclose, "\t\t%d packet%s received after close\n");
    202  1.1     cgd 	p(tcps_rcvbadsum, "\t\t%d discarded for bad checksum%s\n");
    203  1.1     cgd 	p(tcps_rcvbadoff, "\t\t%d discarded for bad header offset field%s\n");
    204  1.1     cgd 	p(tcps_rcvshort, "\t\t%d discarded because packet too short\n");
    205  1.1     cgd 	p(tcps_connattempt, "\t%d connection request%s\n");
    206  1.1     cgd 	p(tcps_accepts, "\t%d connection accept%s\n");
    207  1.1     cgd 	p(tcps_connects, "\t%d connection%s established (including accepts)\n");
    208  1.1     cgd 	p2(tcps_closed, tcps_drops,
    209  1.1     cgd 		"\t%d connection%s closed (including %d drop%s)\n");
    210  1.1     cgd 	p(tcps_conndrops, "\t%d embryonic connection%s dropped\n");
    211  1.1     cgd 	p2(tcps_rttupdated, tcps_segstimed,
    212  1.1     cgd 		"\t%d segment%s updated rtt (of %d attempt%s)\n");
    213  1.1     cgd 	p(tcps_rexmttimeo, "\t%d retransmit timeout%s\n");
    214  1.1     cgd 	p(tcps_timeoutdrop, "\t\t%d connection%s dropped by rexmit timeout\n");
    215  1.1     cgd 	p(tcps_persisttimeo, "\t%d persist timeout%s\n");
    216  1.1     cgd 	p(tcps_keeptimeo, "\t%d keepalive timeout%s\n");
    217  1.1     cgd 	p(tcps_keepprobe, "\t\t%d keepalive probe%s sent\n");
    218  1.1     cgd 	p(tcps_keepdrops, "\t\t%d connection%s dropped by keepalive\n");
    219  1.1     cgd #undef p
    220  1.1     cgd #undef p2
    221  1.1     cgd }
    222  1.1     cgd 
    223  1.1     cgd /*
    224  1.1     cgd  * Dump UDP statistics structure.
    225  1.1     cgd  */
    226  1.1     cgd udp_stats(off, name)
    227  1.8     cgd 	u_long off;
    228  1.1     cgd 	char *name;
    229  1.1     cgd {
    230  1.1     cgd 	struct udpstat udpstat;
    231  1.1     cgd 
    232  1.1     cgd 	if (off == 0)
    233  1.1     cgd 		return;
    234  1.7     cgd 	kvm_read((void *)(long)off, (char *)&udpstat, sizeof (udpstat));
    235  1.2   glass 	printf("%s:\n\t%u packet%s sent\n", name,
    236  1.2   glass 		udpstat.udps_opackets, plural(udpstat.udps_opackets));
    237  1.2   glass 	printf("\t%u packet%s received\n",
    238  1.2   glass 		udpstat.udps_ipackets, plural(udpstat.udps_ipackets));
    239  1.2   glass 	printf("\t%u incomplete header%s\n",
    240  1.1     cgd 		udpstat.udps_hdrops, plural(udpstat.udps_hdrops));
    241  1.1     cgd 	printf("\t%u bad data length field%s\n",
    242  1.1     cgd 		udpstat.udps_badlen, plural(udpstat.udps_badlen));
    243  1.1     cgd 	printf("\t%u bad checksum%s\n",
    244  1.1     cgd 		udpstat.udps_badsum, plural(udpstat.udps_badsum));
    245  1.2   glass 	printf("\t%u packet%s received on unbound ports\n",
    246  1.2   glass 		udpstat.udps_noport, plural(udpstat.udps_noport));
    247  1.2   glass 	printf("\t%u packet%s received (arrived as bcast) on unbound ports\n",
    248  1.2   glass 		udpstat.udps_noportbcast, plural(udpstat.udps_noportbcast));
    249  1.2   glass 	printf("\t%u packet%s dropped, socket full\n",
    250  1.2   glass 	       udpstat.udps_fullsock, plural(udpstat.udps_fullsock));
    251  1.2   glass 	printf("\t%u packet%s missed pcb cache\n",
    252  1.2   glass 	       udpstat.udpps_pcbcachemiss, plural(udpstat.udpps_pcbcachemiss));
    253  1.1     cgd }
    254  1.1     cgd 
    255  1.1     cgd /*
    256  1.1     cgd  * Dump IP statistics structure.
    257  1.1     cgd  */
    258  1.1     cgd ip_stats(off, name)
    259  1.8     cgd 	u_long off;
    260  1.1     cgd 	char *name;
    261  1.1     cgd {
    262  1.1     cgd 	struct ipstat ipstat;
    263  1.1     cgd 
    264  1.1     cgd 	if (off == 0)
    265  1.1     cgd 		return;
    266  1.7     cgd 	kvm_read((void *)(long)off, (char *)&ipstat, sizeof (ipstat));
    267  1.1     cgd 	printf("%s:\n\t%u total packets received\n", name,
    268  1.1     cgd 		ipstat.ips_total);
    269  1.1     cgd 	printf("\t%u bad header checksum%s\n",
    270  1.1     cgd 		ipstat.ips_badsum, plural(ipstat.ips_badsum));
    271  1.1     cgd 	printf("\t%u with size smaller than minimum\n", ipstat.ips_tooshort);
    272  1.1     cgd 	printf("\t%u with data size < data length\n", ipstat.ips_toosmall);
    273  1.1     cgd 	printf("\t%u with header length < data size\n", ipstat.ips_badhlen);
    274  1.1     cgd 	printf("\t%u with data length < header length\n", ipstat.ips_badlen);
    275  1.1     cgd 	printf("\t%u fragment%s received\n",
    276  1.1     cgd 		ipstat.ips_fragments, plural(ipstat.ips_fragments));
    277  1.1     cgd 	printf("\t%u fragment%s dropped (dup or out of space)\n",
    278  1.1     cgd 		ipstat.ips_fragdropped, plural(ipstat.ips_fragdropped));
    279  1.1     cgd 	printf("\t%u fragment%s dropped after timeout\n",
    280  1.1     cgd 		ipstat.ips_fragtimeout, plural(ipstat.ips_fragtimeout));
    281  1.1     cgd 	printf("\t%u packet%s forwarded\n",
    282  1.1     cgd 		ipstat.ips_forward, plural(ipstat.ips_forward));
    283  1.1     cgd 	printf("\t%u packet%s not forwardable\n",
    284  1.1     cgd 		ipstat.ips_cantforward, plural(ipstat.ips_cantforward));
    285  1.1     cgd 	printf("\t%u redirect%s sent\n",
    286  1.1     cgd 		ipstat.ips_redirectsent, plural(ipstat.ips_redirectsent));
    287  1.1     cgd }
    288  1.1     cgd 
    289  1.1     cgd static	char *icmpnames[] = {
    290  1.1     cgd 	"echo reply",
    291  1.1     cgd 	"#1",
    292  1.1     cgd 	"#2",
    293  1.1     cgd 	"destination unreachable",
    294  1.1     cgd 	"source quench",
    295  1.1     cgd 	"routing redirect",
    296  1.1     cgd 	"#6",
    297  1.1     cgd 	"#7",
    298  1.1     cgd 	"echo",
    299  1.1     cgd 	"#9",
    300  1.1     cgd 	"#10",
    301  1.1     cgd 	"time exceeded",
    302  1.1     cgd 	"parameter problem",
    303  1.1     cgd 	"time stamp",
    304  1.1     cgd 	"time stamp reply",
    305  1.1     cgd 	"information request",
    306  1.1     cgd 	"information request reply",
    307  1.1     cgd 	"address mask request",
    308  1.1     cgd 	"address mask reply",
    309  1.1     cgd };
    310  1.1     cgd 
    311  1.1     cgd /*
    312  1.1     cgd  * Dump ICMP statistics.
    313  1.1     cgd  */
    314  1.1     cgd icmp_stats(off, name)
    315  1.8     cgd 	u_long off;
    316  1.1     cgd 	char *name;
    317  1.1     cgd {
    318  1.1     cgd 	struct icmpstat icmpstat;
    319  1.1     cgd 	register int i, first;
    320  1.1     cgd 
    321  1.1     cgd 	if (off == 0)
    322  1.1     cgd 		return;
    323  1.7     cgd 	kvm_read((void *)(long)off, (char *)&icmpstat, sizeof (icmpstat));
    324  1.1     cgd 	printf("%s:\n\t%u call%s to icmp_error\n", name,
    325  1.1     cgd 		icmpstat.icps_error, plural(icmpstat.icps_error));
    326  1.1     cgd 	printf("\t%u error%s not generated 'cuz old message was icmp\n",
    327  1.1     cgd 		icmpstat.icps_oldicmp, plural(icmpstat.icps_oldicmp));
    328  1.1     cgd 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
    329  1.1     cgd 		if (icmpstat.icps_outhist[i] != 0) {
    330  1.1     cgd 			if (first) {
    331  1.1     cgd 				printf("\tOutput histogram:\n");
    332  1.1     cgd 				first = 0;
    333  1.1     cgd 			}
    334  1.1     cgd 			printf("\t\t%s: %u\n", icmpnames[i],
    335  1.1     cgd 				icmpstat.icps_outhist[i]);
    336  1.1     cgd 		}
    337  1.1     cgd 	printf("\t%u message%s with bad code fields\n",
    338  1.1     cgd 		icmpstat.icps_badcode, plural(icmpstat.icps_badcode));
    339  1.1     cgd 	printf("\t%u message%s < minimum length\n",
    340  1.1     cgd 		icmpstat.icps_tooshort, plural(icmpstat.icps_tooshort));
    341  1.1     cgd 	printf("\t%u bad checksum%s\n",
    342  1.1     cgd 		icmpstat.icps_checksum, plural(icmpstat.icps_checksum));
    343  1.1     cgd 	printf("\t%u message%s with bad length\n",
    344  1.1     cgd 		icmpstat.icps_badlen, plural(icmpstat.icps_badlen));
    345  1.1     cgd 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
    346  1.1     cgd 		if (icmpstat.icps_inhist[i] != 0) {
    347  1.1     cgd 			if (first) {
    348  1.1     cgd 				printf("\tInput histogram:\n");
    349  1.1     cgd 				first = 0;
    350  1.1     cgd 			}
    351  1.1     cgd 			printf("\t\t%s: %u\n", icmpnames[i],
    352  1.1     cgd 				icmpstat.icps_inhist[i]);
    353  1.1     cgd 		}
    354  1.1     cgd 	printf("\t%u message response%s generated\n",
    355  1.1     cgd 		icmpstat.icps_reflect, plural(icmpstat.icps_reflect));
    356  1.6  brezak }
    357  1.6  brezak 
    358  1.6  brezak char*
    359  1.6  brezak pluraly(n)
    360  1.6  brezak {
    361  1.6  brezak 	return (n == 1? "y" : "ies");
    362  1.6  brezak }
    363  1.6  brezak 
    364  1.6  brezak /*
    365  1.6  brezak  * Dump IGMP statistics.
    366  1.6  brezak  */
    367  1.6  brezak void
    368  1.6  brezak igmp_stats(off, name)
    369  1.8     cgd 	u_long off;
    370  1.6  brezak 	char *name;
    371  1.6  brezak {
    372  1.6  brezak 	struct igmpstat igmpstat;
    373  1.6  brezak 	register int i, first;
    374  1.6  brezak 
    375  1.6  brezak 	if (off == 0)
    376  1.6  brezak 		return;
    377  1.7     cgd 	kvm_read((void *)(long)off, (char *)&igmpstat, sizeof (igmpstat));
    378  1.6  brezak 	printf("%s:\n", name );
    379  1.6  brezak 	printf("\t%u message%s received\n",
    380  1.6  brezak 	  igmpstat.igps_rcv_total, plural(igmpstat.igps_rcv_total));
    381  1.6  brezak 	printf("\t%u message%s received with too few bytes\n",
    382  1.6  brezak 	  igmpstat.igps_rcv_tooshort, plural(igmpstat.igps_rcv_tooshort));
    383  1.6  brezak 	printf("\t%u message%s received with bad checksum\n",
    384  1.6  brezak  	  igmpstat.igps_rcv_badsum, plural(igmpstat.igps_rcv_badsum));
    385  1.6  brezak 	printf("\t%u membership quer%s received\n",
    386  1.6  brezak 	  igmpstat.igps_rcv_queries, pluraly(igmpstat.igps_rcv_queries));
    387  1.6  brezak 	printf("\t%u membership quer%s received with invalid field(s)\n",
    388  1.6  brezak 	  igmpstat.igps_rcv_badqueries, pluraly(igmpstat.igps_rcv_badqueries));
    389  1.6  brezak 	printf("\t%u membership report%s received\n",
    390  1.6  brezak 	  igmpstat.igps_rcv_reports, plural(igmpstat.igps_rcv_reports));
    391  1.6  brezak 	printf("\t%u membership report%s received with invalid field(s)\n",
    392  1.6  brezak 	  igmpstat.igps_rcv_badreports, plural(igmpstat.igps_rcv_badreports));
    393  1.6  brezak 	printf("\t%u membership report%s received for groups to which we belong\n",
    394  1.6  brezak 	  igmpstat.igps_rcv_ourreports, plural(igmpstat.igps_rcv_ourreports));
    395  1.6  brezak 	printf("\t%u membership report%s sent\n",
    396  1.6  brezak 	  igmpstat.igps_snd_reports, plural(igmpstat.igps_snd_reports));
    397  1.1     cgd }
    398  1.1     cgd 
    399  1.1     cgd /*
    400  1.1     cgd  * Pretty print an Internet address (net address + port).
    401  1.1     cgd  * If the nflag was specified, use numbers instead of names.
    402  1.1     cgd  */
    403  1.1     cgd inetprint(in, port, proto)
    404  1.1     cgd 	register struct in_addr *in;
    405  1.1     cgd 	u_short port;
    406  1.1     cgd 	char *proto;
    407  1.1     cgd {
    408  1.1     cgd 	struct servent *sp = 0;
    409  1.1     cgd 	char line[80], *cp, *index();
    410  1.1     cgd 	int width;
    411  1.1     cgd 
    412  1.1     cgd 	sprintf(line, "%.*s.", (Aflag && !nflag) ? 12 : 16, inetname(*in));
    413  1.1     cgd 	cp = index(line, '\0');
    414  1.1     cgd 	if (!nflag && port)
    415  1.1     cgd 		sp = getservbyport((int)port, proto);
    416  1.1     cgd 	if (sp || port == 0)
    417  1.1     cgd 		sprintf(cp, "%.8s", sp ? sp->s_name : "*");
    418  1.1     cgd 	else
    419  1.1     cgd 		sprintf(cp, "%d", ntohs((u_short)port));
    420  1.1     cgd 	width = Aflag ? 18 : 22;
    421  1.1     cgd 	printf(" %-*.*s", width, width, line);
    422  1.1     cgd }
    423  1.1     cgd 
    424  1.1     cgd /*
    425  1.1     cgd  * Construct an Internet address representation.
    426  1.1     cgd  * If the nflag has been supplied, give
    427  1.1     cgd  * numeric value, otherwise try for symbolic name.
    428  1.1     cgd  */
    429  1.1     cgd char *
    430  1.1     cgd inetname(in)
    431  1.1     cgd 	struct in_addr in;
    432  1.1     cgd {
    433  1.1     cgd 	register char *cp;
    434  1.1     cgd 	static char line[50];
    435  1.1     cgd 	struct hostent *hp;
    436  1.1     cgd 	struct netent *np;
    437  1.1     cgd 	static char domain[MAXHOSTNAMELEN + 1];
    438  1.1     cgd 	static int first = 1;
    439  1.1     cgd 
    440  1.1     cgd 	if (first && !nflag) {
    441  1.1     cgd 		first = 0;
    442  1.1     cgd 		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
    443  1.1     cgd 		    (cp = index(domain, '.')))
    444  1.1     cgd 			(void) strcpy(domain, cp + 1);
    445  1.1     cgd 		else
    446  1.1     cgd 			domain[0] = 0;
    447  1.1     cgd 	}
    448  1.1     cgd 	cp = 0;
    449  1.1     cgd 	if (!nflag && in.s_addr != INADDR_ANY) {
    450  1.1     cgd 		int net = inet_netof(in);
    451  1.1     cgd 		int lna = inet_lnaof(in);
    452  1.1     cgd 
    453  1.1     cgd 		if (lna == INADDR_ANY) {
    454  1.1     cgd 			np = getnetbyaddr(net, AF_INET);
    455  1.1     cgd 			if (np)
    456  1.1     cgd 				cp = np->n_name;
    457  1.1     cgd 		}
    458  1.1     cgd 		if (cp == 0) {
    459  1.1     cgd 			hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
    460  1.1     cgd 			if (hp) {
    461  1.1     cgd 				if ((cp = index(hp->h_name, '.')) &&
    462  1.1     cgd 				    !strcmp(cp + 1, domain))
    463  1.1     cgd 					*cp = 0;
    464  1.1     cgd 				cp = hp->h_name;
    465  1.1     cgd 			}
    466  1.1     cgd 		}
    467  1.1     cgd 	}
    468  1.1     cgd 	if (in.s_addr == INADDR_ANY)
    469  1.1     cgd 		strcpy(line, "*");
    470  1.1     cgd 	else if (cp)
    471  1.1     cgd 		strcpy(line, cp);
    472  1.1     cgd 	else {
    473  1.1     cgd 		in.s_addr = ntohl(in.s_addr);
    474  1.1     cgd #define C(x)	((x) & 0xff)
    475  1.1     cgd 		sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
    476  1.1     cgd 			C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
    477  1.1     cgd 	}
    478  1.1     cgd 	return (line);
    479  1.1     cgd }
    480