1175061Sobrien/*-
2139463Srwatson * Copyright (c) 2004, Robert N. M. Watson
311848Sjulian * Copyright (c) 1983, 1988, 1993
411848Sjulian *	The Regents of the University of California.  All rights reserved.
511848Sjulian *
611848Sjulian * Redistribution and use in source and binary forms, with or without
711848Sjulian * modification, are permitted provided that the following conditions
811848Sjulian * are met:
911848Sjulian * 1. Redistributions of source code must retain the above copyright
1011848Sjulian *    notice, this list of conditions and the following disclaimer.
1111848Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1211848Sjulian *    notice, this list of conditions and the following disclaimer in the
1311848Sjulian *    documentation and/or other materials provided with the distribution.
1411848Sjulian * 3. All advertising materials mentioning features or use of this software
1511848Sjulian *    must display the following acknowledgement:
1611848Sjulian *	This product includes software developed by the University of
1711848Sjulian *	California, Berkeley and its contributors.
1811848Sjulian * 4. Neither the name of the University nor the names of its contributors
1911848Sjulian *    may be used to endorse or promote products derived from this software
2011848Sjulian *    without specific prior written permission.
2111848Sjulian *
2211848Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2311848Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2411848Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2511848Sjulian * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2611848Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2711848Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2811848Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2911848Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3011848Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3111848Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3211848Sjulian * SUCH DAMAGE.
3311848Sjulian */
3411848Sjulian
35132671Scharnier#if 0
3611848Sjulian#ifndef lint
3711848Sjulianstatic char sccsid[] = "@(#)ns.c	8.1 (Berkeley) 6/6/93";
3811848Sjulian#endif /* not lint */
39132671Scharnier#endif
4011848Sjulian
41132671Scharnier#include <sys/cdefs.h>
42132671Scharnier__FBSDID("$FreeBSD$");
43132671Scharnier
4411848Sjulian#include <sys/param.h>
4514543Sdg#include <sys/queue.h>
4611848Sjulian#include <sys/socket.h>
4711848Sjulian#include <sys/socketvar.h>
4811848Sjulian#include <sys/protosw.h>
4911848Sjulian
5011848Sjulian#include <net/route.h>
5111848Sjulian
52175061Sobrien#define	TCPSTATES
5311848Sjulian#include <netinet/tcp_fsm.h>
5411848Sjulian
5511848Sjulian#include <netipx/ipx.h>
5611848Sjulian#include <netipx/ipx_pcb.h>
5711848Sjulian#include <netipx/ipx_var.h>
5825654Sjhay#ifdef IPXERRORMSGS
5911848Sjulian#include <netipx/ipx_error.h>
6025654Sjhay#endif
6111848Sjulian#include <netipx/spx.h>
6211848Sjulian#include <netipx/spx_timer.h>
6311848Sjulian#include <netipx/spx_var.h>
64175061Sobrien#define	SANAMES
6511848Sjulian#include <netipx/spx_debug.h>
6611848Sjulian
67200462Sdelphij#include <nlist.h>
68200462Sdelphij#include <errno.h>
69160787Syar#include <stdint.h>
7011848Sjulian#include <stdio.h>
7111848Sjulian#include <string.h>
7211848Sjulian#include "netstat.h"
7311848Sjulian
74175061Sobrienstatic char *ipx_prpr(struct ipx_addr *);
7511848Sjulian
7611848Sjulian/*
7711848Sjulian * Print a summary of connections related to a Network Systems
7811848Sjulian * protocol.  For SPX, also give state of connection.
7911848Sjulian * Listening processes (aflag) are suppressed unless the
8011848Sjulian * -a (all) flag is specified.
8111848Sjulian */
8211848Sjulian
8311848Sjulianvoid
84171465Sjhbipxprotopr(u_long off, const char *name, int af1 __unused, int proto __unused)
8511848Sjulian{
86139480Srwatson	struct ipxpcbhead cb;
87139594Srwatson	struct ipxpcb *ipxp;
88139480Srwatson	struct ipxpcb ipxpcb;
89139480Srwatson	struct spxpcb spxpcb;
90139480Srwatson	struct socket sockb;
91139480Srwatson	static int first = 1;
9211848Sjulian	int isspx;
9311848Sjulian
9411848Sjulian	if (off == 0)
9511848Sjulian		return;
96139463Srwatson
9711848Sjulian	isspx = strcmp(name, "spx") == 0;
98139480Srwatson	kread(off, (char *)&cb, sizeof (struct ipxpcbhead));
99139594Srwatson	ipxp = LIST_FIRST(&cb);
100139594Srwatson	while (ipxp != NULL) {
10111848Sjulian		u_long ppcb;
10211848Sjulian
103139594Srwatson		kread((u_long)ipxp, (char *)&ipxpcb, sizeof (ipxpcb));
104139594Srwatson		ipxp = LIST_NEXT(&ipxpcb, ipxp_list);
105139480Srwatson
10611848Sjulian		if (!aflag && ipx_nullhost(ipxpcb.ipxp_faddr) ) {
10711848Sjulian			continue;
10811848Sjulian		}
10911848Sjulian		kread((u_long)ipxpcb.ipxp_socket,
11011848Sjulian				(char *)&sockb, sizeof (sockb));
11111848Sjulian		ppcb = (u_long) ipxpcb.ipxp_pcb;
11211848Sjulian		if (ppcb) {
11311848Sjulian			if (isspx) {
11411848Sjulian				kread(ppcb, (char *)&spxpcb, sizeof (spxpcb));
11511848Sjulian			} else continue;
11611848Sjulian		} else
11711848Sjulian			if (isspx) continue;
11811848Sjulian		if (first) {
11911848Sjulian			printf("Active IPX connections");
12011848Sjulian			if (aflag)
12111848Sjulian				printf(" (including servers)");
12211848Sjulian			putchar('\n');
12311848Sjulian			if (Aflag)
12411848Sjulian				printf("%-8.8s ", "PCB");
12511848Sjulian			printf(Aflag ?
12611848Sjulian				"%-5.5s %-6.6s %-6.6s  %-18.18s %-18.18s %s\n" :
12711848Sjulian				"%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s %s\n",
12811848Sjulian				"Proto", "Recv-Q", "Send-Q",
12911848Sjulian				"Local Address", "Foreign Address", "(state)");
13011848Sjulian			first = 0;
13111848Sjulian		}
13211848Sjulian		if (Aflag)
13316080Salex			printf("%8lx ", ppcb);
134100591Sjdp		printf("%-5.5s %6u %6u ", name, sockb.so_rcv.sb_cc,
13511848Sjulian			sockb.so_snd.sb_cc);
13611848Sjulian		printf(Aflag?" %-18.18s":" %-22.22s", ipx_prpr(&ipxpcb.ipxp_laddr));
13711848Sjulian		printf(Aflag?" %-18.18s":" %-22.22s", ipx_prpr(&ipxpcb.ipxp_faddr));
13811848Sjulian		if (isspx) {
13911848Sjulian			if (spxpcb.s_state >= TCP_NSTATES)
14011848Sjulian				printf(" %d", spxpcb.s_state);
14111848Sjulian			else
14211848Sjulian				printf(" %s", tcpstates[spxpcb.s_state]);
14311848Sjulian		}
14411848Sjulian		putchar('\n');
14511848Sjulian	}
14611848Sjulian}
14711848Sjulian
148175061Sobrien#define	ANY(x,y,z) \
14952376Sbp	    if (x || sflag <= 1) printf("\t%u %s%s%s\n", x, y, plural(x), z)
150175061Sobrien#define	ANYl(x,y,z) \
15152376Sbp	    if (x || sflag <= 1) printf("\t%lu %s%s%s\n", x, y, plural(x), z)
15225654Sjhay
15311848Sjulian/*
15411848Sjulian * Dump SPX statistics structure.
15511848Sjulian */
15611848Sjulianvoid
157171465Sjhbspx_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
15811848Sjulian{
15911848Sjulian	struct spx_istat spx_istat;
160175061Sobrien#define	spxstat spx_istat.newstats
16111848Sjulian
16211848Sjulian	if (off == 0)
16311848Sjulian		return;
16411848Sjulian	kread(off, (char *)&spx_istat, sizeof (spx_istat));
16511848Sjulian	printf("%s:\n", name);
16611848Sjulian	ANY(spx_istat.nonucn, "connection", " dropped due to no new sockets ");
16711848Sjulian	ANY(spx_istat.gonawy, "connection", " terminated due to our end dying");
16811848Sjulian	ANY(spx_istat.nonucn, "connection",
16911848Sjulian	    " dropped due to inability to connect");
17011848Sjulian	ANY(spx_istat.noconn, "connection",
17111848Sjulian	    " dropped due to inability to connect");
17211848Sjulian	ANY(spx_istat.notme, "connection",
17311848Sjulian	    " incompleted due to mismatched id's");
17411848Sjulian	ANY(spx_istat.wrncon, "connection", " dropped due to mismatched id's");
17511848Sjulian	ANY(spx_istat.bdreas, "packet", " dropped out of sequence");
17611848Sjulian	ANY(spx_istat.lstdup, "packet", " duplicating the highest packet");
17711848Sjulian	ANY(spx_istat.notyet, "packet", " refused as exceeding allocation");
17837453Sbde	ANYl(spxstat.spxs_connattempt, "connection", " initiated");
17937453Sbde	ANYl(spxstat.spxs_accepts, "connection", " accepted");
18037453Sbde	ANYl(spxstat.spxs_connects, "connection", " established");
18137453Sbde	ANYl(spxstat.spxs_drops, "connection", " dropped");
18237453Sbde	ANYl(spxstat.spxs_conndrops, "embryonic connection", " dropped");
18337453Sbde	ANYl(spxstat.spxs_closed, "connection", " closed (includes drops)");
18437453Sbde	ANYl(spxstat.spxs_segstimed, "packet", " where we tried to get rtt");
18537453Sbde	ANYl(spxstat.spxs_rttupdated, "time", " we got rtt");
18637453Sbde	ANYl(spxstat.spxs_delack, "delayed ack", " sent");
18737453Sbde	ANYl(spxstat.spxs_timeoutdrop, "connection",
18837453Sbde	    " dropped in rxmt timeout");
18937453Sbde	ANYl(spxstat.spxs_rexmttimeo, "retransmit timeout", "");
19037453Sbde	ANYl(spxstat.spxs_persisttimeo, "persist timeout", "");
19137453Sbde	ANYl(spxstat.spxs_keeptimeo, "keepalive timeout", "");
19237453Sbde	ANYl(spxstat.spxs_keepprobe, "keepalive probe", " sent");
19337453Sbde	ANYl(spxstat.spxs_keepdrops, "connection", " dropped in keepalive");
19437453Sbde	ANYl(spxstat.spxs_sndtotal, "total packet", " sent");
19537453Sbde	ANYl(spxstat.spxs_sndpack, "data packet", " sent");
19637453Sbde	ANYl(spxstat.spxs_sndbyte, "data byte", " sent");
19737453Sbde	ANYl(spxstat.spxs_sndrexmitpack, "data packet", " retransmitted");
19837453Sbde	ANYl(spxstat.spxs_sndrexmitbyte, "data byte", " retransmitted");
19937453Sbde	ANYl(spxstat.spxs_sndacks, "ack-only packet", " sent");
20037453Sbde	ANYl(spxstat.spxs_sndprobe, "window probe", " sent");
20137453Sbde	ANYl(spxstat.spxs_sndurg, "packet", " sent with URG only");
20237453Sbde	ANYl(spxstat.spxs_sndwinup, "window update-only packet", " sent");
20337453Sbde	ANYl(spxstat.spxs_sndctrl, "control (SYN|FIN|RST) packet", " sent");
204228992Suqs	ANYl(spxstat.spxs_sndvoid, "request", " to send a non-existent packet");
20537453Sbde	ANYl(spxstat.spxs_rcvtotal, "total packet", " received");
20637453Sbde	ANYl(spxstat.spxs_rcvpack, "packet", " received in sequence");
20737453Sbde	ANYl(spxstat.spxs_rcvbyte, "byte", " received in sequence");
20837453Sbde	ANYl(spxstat.spxs_rcvbadsum, "packet", " received with ccksum errs");
20937453Sbde	ANYl(spxstat.spxs_rcvbadoff, "packet", " received with bad offset");
21037453Sbde	ANYl(spxstat.spxs_rcvshort, "packet", " received too short");
21137453Sbde	ANYl(spxstat.spxs_rcvduppack, "duplicate-only packet", " received");
21237453Sbde	ANYl(spxstat.spxs_rcvdupbyte, "duplicate-only byte", " received");
21337453Sbde	ANYl(spxstat.spxs_rcvpartduppack, "packet",
21437453Sbde	    " with some duplicate data");
21537453Sbde	ANYl(spxstat.spxs_rcvpartdupbyte, "dup. byte", " in part-dup. packet");
21637453Sbde	ANYl(spxstat.spxs_rcvoopack, "out-of-order packet", " received");
21737453Sbde	ANYl(spxstat.spxs_rcvoobyte, "out-of-order byte", " received");
21837453Sbde	ANYl(spxstat.spxs_rcvpackafterwin, "packet", " with data after window");
21937453Sbde	ANYl(spxstat.spxs_rcvbyteafterwin, "byte", " rcvd after window");
22037453Sbde	ANYl(spxstat.spxs_rcvafterclose, "packet", " rcvd after 'close'");
22137453Sbde	ANYl(spxstat.spxs_rcvwinprobe, "rcvd window probe packet", "");
22237453Sbde	ANYl(spxstat.spxs_rcvdupack, "rcvd duplicate ack", "");
22337453Sbde	ANYl(spxstat.spxs_rcvacktoomuch, "rcvd ack", " for unsent data");
22437453Sbde	ANYl(spxstat.spxs_rcvackpack, "rcvd ack packet", "");
22537453Sbde	ANYl(spxstat.spxs_rcvackbyte, "byte", " acked by rcvd acks");
22637453Sbde	ANYl(spxstat.spxs_rcvwinupd, "rcvd window update packet", "");
22711848Sjulian}
22825654Sjhay
22911848Sjulian/*
23011848Sjulian * Dump IPX statistics structure.
23111848Sjulian */
23211848Sjulianvoid
233171465Sjhbipx_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
23411848Sjulian{
23511848Sjulian	struct ipxstat ipxstat;
23611848Sjulian
23711848Sjulian	if (off == 0)
23811848Sjulian		return;
23911848Sjulian	kread(off, (char *)&ipxstat, sizeof (ipxstat));
24011848Sjulian	printf("%s:\n", name);
24137453Sbde	ANYl(ipxstat.ipxs_total, "total packet", " received");
24237453Sbde	ANYl(ipxstat.ipxs_badsum, "packet", " with bad checksums");
24337453Sbde	ANYl(ipxstat.ipxs_tooshort, "packet", " smaller than advertised");
24437453Sbde	ANYl(ipxstat.ipxs_toosmall, "packet", " smaller than a header");
24537453Sbde	ANYl(ipxstat.ipxs_forward, "packet", " forwarded");
24637453Sbde	ANYl(ipxstat.ipxs_cantforward, "packet", " not forwardable");
24737453Sbde	ANYl(ipxstat.ipxs_delivered, "packet", " for this host");
24837453Sbde	ANYl(ipxstat.ipxs_localout, "packet", " sent from this host");
24937453Sbde	ANYl(ipxstat.ipxs_odropped, "packet", " dropped due to no bufs, etc.");
25037453Sbde	ANYl(ipxstat.ipxs_noroute, "packet", " discarded due to no route");
25137453Sbde	ANYl(ipxstat.ipxs_mtutoosmall, "packet", " too big");
25211848Sjulian}
25311848Sjulian
25452415Sjulian#ifdef IPXERRORMSGS
25511848Sjulianstatic	struct {
25611848Sjulian	u_short code;
25711848Sjulian	char *name;
25811848Sjulian	char *where;
25911848Sjulian} ipx_errnames[] = {
26011848Sjulian	{0, "Unspecified Error", " at Destination"},
26111848Sjulian	{1, "Bad Checksum", " at Destination"},
26211848Sjulian	{2, "No Listener", " at Socket"},
26311848Sjulian	{3, "Packet", " Refused due to lack of space at Destination"},
26411848Sjulian	{01000, "Unspecified Error", " while gatewayed"},
26511848Sjulian	{01001, "Bad Checksum", " while gatewayed"},
26611848Sjulian	{01002, "Packet", " forwarded too many times"},
26711848Sjulian	{01003, "Packet", " too large to be forwarded"},
26811848Sjulian	{-1, 0, 0},
26911848Sjulian};
27011848Sjulian
27111848Sjulian/*
27211848Sjulian * Dump IPX Error statistics structure.
27311848Sjulian */
27411848Sjulian/*ARGSUSED*/
27511848Sjulianvoid
276171465Sjhbipxerr_stats(u_long off, const char *name, int af __unused, int proto __unused)
27711848Sjulian{
27811848Sjulian	struct ipx_errstat ipx_errstat;
279102975Sdwmalone	int j;
280102975Sdwmalone	int histoprint = 1;
28111848Sjulian	int z;
28211848Sjulian
28311848Sjulian	if (off == 0)
28411848Sjulian		return;
28511848Sjulian	kread(off, (char *)&ipx_errstat, sizeof (ipx_errstat));
28611848Sjulian	printf("IPX error statistics:\n");
28711848Sjulian	ANY(ipx_errstat.ipx_es_error, "call", " to ipx_error");
28811848Sjulian	ANY(ipx_errstat.ipx_es_oldshort, "error",
28911848Sjulian		" ignored due to insufficient addressing");
29011848Sjulian	ANY(ipx_errstat.ipx_es_oldipx_err, "error request",
29111848Sjulian		" in response to error packets");
29211848Sjulian	ANY(ipx_errstat.ipx_es_tooshort, "error packet",
29311848Sjulian		" received incomplete");
29411848Sjulian	ANY(ipx_errstat.ipx_es_badcode, "error packet",
29511848Sjulian		" received of unknown type");
29611848Sjulian	for(j = 0; j < IPX_ERR_MAX; j ++) {
29711848Sjulian		z = ipx_errstat.ipx_es_outhist[j];
29811848Sjulian		if (z && histoprint) {
29911848Sjulian			printf("Output Error Histogram:\n");
30011848Sjulian			histoprint = 0;
30111848Sjulian		}
30211848Sjulian		ipx_erputil(z, ipx_errstat.ipx_es_codes[j]);
30311848Sjulian	}
30411848Sjulian	histoprint = 1;
30511848Sjulian	for(j = 0; j < IPX_ERR_MAX; j ++) {
30611848Sjulian		z = ipx_errstat.ipx_es_inhist[j];
30711848Sjulian		if (z && histoprint) {
30811848Sjulian			printf("Input Error Histogram:\n");
30911848Sjulian			histoprint = 0;
31011848Sjulian		}
31111848Sjulian		ipx_erputil(z, ipx_errstat.ipx_es_codes[j]);
31211848Sjulian	}
31311848Sjulian}
31411848Sjulian
31511848Sjulianstatic void
31678314Sassaripx_erputil(int z, int c)
31711848Sjulian{
31811848Sjulian	int j;
31911848Sjulian	char codebuf[30];
32011848Sjulian	char *name, *where;
32111848Sjulian
32211848Sjulian	for(j = 0;; j ++) {
32311848Sjulian		if ((name = ipx_errnames[j].name) == 0)
32411848Sjulian			break;
32511848Sjulian		if (ipx_errnames[j].code == c)
32611848Sjulian			break;
32711848Sjulian	}
32811848Sjulian	if (name == 0)  {
32911848Sjulian		if (c > 01000)
33011848Sjulian			where = "in transit";
33111848Sjulian		else
33211848Sjulian			where = "at destination";
33311848Sjulian		sprintf(codebuf, "Unknown IPX error code 0%o", c);
33411848Sjulian		name = codebuf;
33511848Sjulian	} else
33611848Sjulian		where =  ipx_errnames[j].where;
33711848Sjulian	ANY(z, name, where);
33811848Sjulian}
33925654Sjhay#endif /* IPXERRORMSGS */
34011848Sjulian
341160789Syarstatic struct sockaddr_ipx ssipx = { .sipx_family = AF_IPX };
34211848Sjulian
34311848Sjulianstatic
34478314Sassarchar *ipx_prpr(struct ipx_addr *x)
34511848Sjulian{
34611848Sjulian	struct sockaddr_ipx *sipx = &ssipx;
34711848Sjulian
34811848Sjulian	sipx->sipx_addr = *x;
34911848Sjulian	return(ipx_print((struct sockaddr *)sipx));
35011848Sjulian}
351