Annotation of src/usr.bin/netstat/ipx.c, Revision 1.18
1.18 ! otto 1: /* $OpenBSD: ipx.c,v 1.17 2005/03/30 06:45:34 deraadt Exp $ */
1.1 mickey 2:
3: /*
4: * Copyright (c) 1996 Michael Shalayeff
5: * Copyright (c) 1983, 1988, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.14 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 mickey 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifndef lint
34: #if 0
35: static char sccsid[] = "from: @(#)ns.c 8.1 (Berkeley) 6/6/93";
36: #else
1.18 ! otto 37: static char *rcsid = "$OpenBSD: ipx.c,v 1.17 2005/03/30 06:45:34 deraadt Exp $";
1.1 mickey 38: #endif
39: #endif /* not lint */
40:
41: #include <sys/param.h>
42: #include <sys/socket.h>
43: #include <sys/socketvar.h>
44: #include <sys/mbuf.h>
45: #include <sys/protosw.h>
46:
47: #include <net/route.h>
48: #include <net/if.h>
49:
50: #include <netinet/tcp_fsm.h>
51:
52: #include <netipx/ipx.h>
53: #include <netipx/ipx_pcb.h>
54: #include <netipx/ipx.h>
55: #include <netipx/ipx_var.h>
1.6 fgsch 56: #ifdef IPXERRORMSGS
1.1 mickey 57: #include <netipx/ipx_error.h>
1.6 fgsch 58: #endif /* IPXERRORMSGS */
1.1 mickey 59: #include <netipx/spx.h>
60: #include <netipx/spx_timer.h>
61: #include <netipx/spx_var.h>
62: #define SANAMES
63: #include <netipx/spx_debug.h>
64:
1.4 millert 65: #include <limits.h>
1.1 mickey 66: #include <errno.h>
67: #include <stdio.h>
68: #include <string.h>
69: #include "netstat.h"
70:
71: struct ipxpcb ipxpcb;
72: struct spxpcb spxpcb;
73: struct socket sockb;
74:
1.10 millert 75: static char *ipx_prpr(struct ipx_addr *);
1.13 deraadt 76: #ifdef IPXERRORMSGS
1.10 millert 77: static void ipx_erputil(int, int);
1.13 deraadt 78: #endif
1.1 mickey 79:
80: static int first = 1;
81:
82: /*
83: * Print a summary of connections related to an IPX
84: * protocol. For SPX, also give state of connection.
85: * Listening processes (aflag) are suppressed unless the
86: * -a (all) flag is specified.
87: */
88:
89: void
1.13 deraadt 90: ipxprotopr(u_long off, char *name)
1.1 mickey 91: {
92: struct ipxpcbtable table;
1.8 mpech 93: struct ipxpcb *head, *prev, *next;
1.1 mickey 94: int isspx;
95:
96: if (off == 0)
97: return;
98: isspx = strcmp(name, "spx") == 0;
1.16 jaredy 99: kread(off, &table, sizeof (table));
1.1 mickey 100: prev = head = (struct ipxpcb *)
1.18 ! otto 101: &CIRCLEQ_FIRST(&((struct ipxpcbtable *)off)->ipxpt_queue);
! 102: next = CIRCLEQ_FIRST(&table.ipxpt_queue);
1.1 mickey 103:
104: while (next != head) {
1.16 jaredy 105: kread((u_long)next, &ipxpcb, sizeof (ipxpcb));
1.18 ! otto 106: if (CIRCLEQ_PREV(&ipxpcb, ipxp_queue) != prev) {
1.1 mickey 107: printf("???\n");
108: break;
109: }
110: prev = next;
1.18 ! otto 111: next = CIRCLEQ_NEXT(&ipxpcb, ipxp_queue);
1.1 mickey 112:
113: if (!aflag && ipx_nullhost(ipxpcb.ipxp_faddr) )
114: continue;
115:
1.16 jaredy 116: kread((u_long)ipxpcb.ipxp_socket, &sockb, sizeof (sockb));
1.1 mickey 117: if (isspx) {
1.16 jaredy 118: kread((u_long)ipxpcb.ipxp_ppcb, &spxpcb,
119: sizeof (spxpcb));
1.1 mickey 120: }
121: if (first) {
122: printf("Active Internetwork Packet Exchange connections");
123: if (aflag)
124: printf(" (including servers)");
125: putchar('\n');
1.9 mickey 126: if (Aflag)
1.4 millert 127: printf("%-*.*s %-5.5s %-6.6s %-6.6s %-*.*s %-*.*s %s\n",
128: PLEN, PLEN, "PCB", "Proto", "Recv-Q",
129: "Send-Q", PLEN, PLEN, "Local Address",
130: PLEN, PLEN, "Foreign Address", "(state)");
131: else
132: printf("%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
133: "Proto", "Recv-Q", "Send-Q",
134: "Local Address", "Foreign Address",
135: "(state)");
1.1 mickey 136: first = 0;
137: }
138: if (Aflag)
1.4 millert 139: printf("%*p ", PLEN, ipxpcb.ipxp_ppcb);
1.2 millert 140: printf("%-5.5s %6ld %6ld ", name, sockb.so_rcv.sb_cc,
1.1 mickey 141: sockb.so_snd.sb_cc);
142: printf(" %-22.22s", ipx_prpr(&ipxpcb.ipxp_laddr));
143: printf(" %-22.22s", ipx_prpr(&ipxpcb.ipxp_faddr));
144: if (isspx) {
145: extern char *tcpstates[];
146: if (spxpcb.s_state >= TCP_NSTATES)
147: printf(" %d", spxpcb.s_state);
148: else
149: printf(" %s", tcpstates[spxpcb.s_state]);
150: }
151: putchar('\n');
152: }
153: }
154: #define ANY(x,y,z) \
1.2 millert 155: ((x) ? printf("\t%ld %s%s%s -- %s\n",x,y,plural(x),z,"x") : 0)
1.1 mickey 156:
157: /*
158: * Dump SPX statistics structure.
159: */
160: void
1.13 deraadt 161: spx_stats(u_long off, char *name)
1.1 mickey 162: {
163: struct spx_istat spx_istat;
164: #define spxstat spx_istat.newstats
165:
166: if (off == 0)
167: return;
1.16 jaredy 168: kread(off, &spx_istat, sizeof (spx_istat));
1.1 mickey 169: printf("%s:\n", name);
1.2 millert 170: ANY((long)spx_istat.nonucn, "connection", " dropped due to no new sockets ");
171: ANY((long)spx_istat.gonawy, "connection", " terminated due to our end dying");
172: ANY((long)spx_istat.nonucn, "connection",
1.1 mickey 173: " dropped due to inability to connect");
1.2 millert 174: ANY((long)spx_istat.noconn, "connection",
1.1 mickey 175: " dropped due to inability to connect");
1.2 millert 176: ANY((long)spx_istat.notme, "connection",
1.1 mickey 177: " incompleted due to mismatched id's");
1.2 millert 178: ANY((long)spx_istat.wrncon, "connection", " dropped due to mismatched id's");
179: ANY((long)spx_istat.bdreas, "packet", " dropped out of sequence");
180: ANY((long)spx_istat.lstdup, "packet", " duplicating the highest packet");
181: ANY((long)spx_istat.notyet, "packet", " refused as exceeding allocation");
1.1 mickey 182: ANY(spxstat.spxs_connattempt, "connection", " initiated");
183: ANY(spxstat.spxs_accepts, "connection", " accepted");
184: ANY(spxstat.spxs_connects, "connection", " established");
185: ANY(spxstat.spxs_drops, "connection", " dropped");
186: ANY(spxstat.spxs_conndrops, "embryonic connection", " dropped");
187: ANY(spxstat.spxs_closed, "connection", " closed (includes drops)");
188: ANY(spxstat.spxs_segstimed, "packet", " where we tried to get rtt");
189: ANY(spxstat.spxs_rttupdated, "time", " we got rtt");
190: ANY(spxstat.spxs_delack, "delayed ack", " sent");
191: ANY(spxstat.spxs_timeoutdrop, "connection", " dropped in rxmt timeout");
192: ANY(spxstat.spxs_rexmttimeo, "retransmit timeout", "");
193: ANY(spxstat.spxs_persisttimeo, "persist timeout", "");
194: ANY(spxstat.spxs_keeptimeo, "keepalive timeout", "");
195: ANY(spxstat.spxs_keepprobe, "keepalive probe", " sent");
196: ANY(spxstat.spxs_keepdrops, "connection", " dropped in keepalive");
197: ANY(spxstat.spxs_sndtotal, "total packet", " sent");
198: ANY(spxstat.spxs_sndpack, "data packet", " sent");
199: ANY(spxstat.spxs_sndbyte, "data byte", " sent");
200: ANY(spxstat.spxs_sndrexmitpack, "data packet", " retransmitted");
201: ANY(spxstat.spxs_sndrexmitbyte, "data byte", " retransmitted");
202: ANY(spxstat.spxs_sndacks, "ack-only packet", " sent");
203: ANY(spxstat.spxs_sndprobe, "window probe", " sent");
204: ANY(spxstat.spxs_sndurg, "packet", " sent with URG only");
205: ANY(spxstat.spxs_sndwinup, "window update-only packet", " sent");
206: ANY(spxstat.spxs_sndctrl, "control (SYN|FIN|RST) packet", " sent");
1.15 jmc 207: ANY(spxstat.spxs_sndvoid, "request", " to send a non-existent packet");
1.1 mickey 208: ANY(spxstat.spxs_rcvtotal, "total packet", " received");
209: ANY(spxstat.spxs_rcvpack, "packet", " received in sequence");
210: ANY(spxstat.spxs_rcvbyte, "byte", " received in sequence");
211: ANY(spxstat.spxs_rcvbadsum, "packet", " received with ccksum errs");
212: ANY(spxstat.spxs_rcvbadoff, "packet", " received with bad offset");
213: ANY(spxstat.spxs_rcvshort, "packet", " received too short");
214: ANY(spxstat.spxs_rcvduppack, "duplicate-only packet", " received");
215: ANY(spxstat.spxs_rcvdupbyte, "duplicate-only byte", " received");
216: ANY(spxstat.spxs_rcvpartduppack, "packet", " with some duplicate data");
1.12 jsyn 217: ANY(spxstat.spxs_rcvpartdupbyte, "duplicate byte", " in part-duplicate packet");
1.1 mickey 218: ANY(spxstat.spxs_rcvoopack, "out-of-order packet", " received");
219: ANY(spxstat.spxs_rcvoobyte, "out-of-order byte", " received");
220: ANY(spxstat.spxs_rcvpackafterwin, "packet", " with data after window");
221: ANY(spxstat.spxs_rcvbyteafterwin, "byte", " rcvd after window");
222: ANY(spxstat.spxs_rcvafterclose, "packet", " rcvd after 'close'");
223: ANY(spxstat.spxs_rcvwinprobe, "rcvd window probe packet", "");
224: ANY(spxstat.spxs_rcvdupack, "rcvd duplicate ack", "");
225: ANY(spxstat.spxs_rcvacktoomuch, "rcvd ack", " for unsent data");
226: ANY(spxstat.spxs_rcvackpack, "rcvd ack packet", "");
227: ANY(spxstat.spxs_rcvackbyte, "byte", " acked by rcvd acks");
228: ANY(spxstat.spxs_rcvwinupd, "rcvd window update packet", "");
229: }
230: #undef ANY
1.11 deraadt 231: #define ANY(x,y,z) ((x) ? printf("\t%ld %s%s%s\n",x,y,plural(x),z) : 0)
1.1 mickey 232:
233: /*
234: * Dump IPX statistics structure.
235: */
236: void
1.13 deraadt 237: ipx_stats(u_long off, char *name)
1.1 mickey 238: {
239: struct ipxstat ipxstat;
240:
241: if (off == 0)
242: return;
1.16 jaredy 243: kread(off, &ipxstat, sizeof (ipxstat));
1.1 mickey 244: printf("%s:\n", name);
245: ANY(ipxstat.ipxs_toosmall, "packet", " smaller than a header");
246: ANY(ipxstat.ipxs_tooshort, "packet", " smaller than advertised");
247: ANY(ipxstat.ipxs_badsum, "packet", " with bad checksums");
248: }
249:
1.6 fgsch 250: #ifdef IPXERRORMSGS
1.1 mickey 251: static struct {
252: u_short code;
253: char *name;
254: char *where;
255: } ipx_errnames[] = {
1.13 deraadt 256: { 0, "Unspecified Error", " at Destination" },
257: { 1, "Bad Checksum", " at Destination" },
258: { 2, "No Listener", " at Socket" },
259: { 3, "Packet", " Refused due to lack of space at Destination" },
260: { 01000, "Unspecified Error", " while gatewayed" },
261: { 01001, "Bad Checksum", " while gatewayed" },
262: { 01002, "Packet", " forwarded too many times" },
263: { 01003, "Packet", " too large to be forwarded" },
264: { -1, 0, 0 },
1.1 mickey 265: };
266:
267: /*
268: * Dump IPX Error statistics structure.
269: */
270: /*ARGSUSED*/
271: void
1.13 deraadt 272: ipxerr_stats(u_long off, char *name)
1.1 mickey 273: {
274: struct ipx_errstat ipx_errstat;
1.8 mpech 275: int j;
276: int histoprint = 1;
1.1 mickey 277: int z;
278:
279: if (off == 0)
280: return;
1.16 jaredy 281: kread(off, &ipx_errstat, sizeof (ipx_errstat));
1.1 mickey 282: printf("IPX error statistics:\n");
283: ANY(ipx_errstat.ipx_es_error, "call", " to ipx_error");
284: ANY(ipx_errstat.ipx_es_oldshort, "error",
285: " ignored due to insufficient addressing");
286: ANY(ipx_errstat.ipx_es_oldipx_err, "error request",
287: " in response to error packets");
288: ANY(ipx_errstat.ipx_es_tooshort, "error packet",
289: " received incomplete");
290: ANY(ipx_errstat.ipx_es_badcode, "error packet",
291: " received of unknown type");
1.11 deraadt 292: for (j = 0; j < IPX_ERR_MAX; j ++) {
1.1 mickey 293: z = ipx_errstat.ipx_es_outhist[j];
294: if (z && histoprint) {
295: printf("Output Error Histogram:\n");
296: histoprint = 0;
297: }
298: ipx_erputil(z, ipx_errstat.ipx_es_codes[j]);
299:
300: }
301: histoprint = 1;
1.11 deraadt 302: for (j = 0; j < IPX_ERR_MAX; j ++) {
1.1 mickey 303: z = ipx_errstat.ipx_es_inhist[j];
304: if (z && histoprint) {
305: printf("Input Error Histogram:\n");
306: histoprint = 0;
307: }
308: ipx_erputil(z, ipx_errstat.ipx_es_codes[j]);
309: }
310: }
311:
312: static void
1.13 deraadt 313: ipx_erputil(int z, int c)
1.1 mickey 314: {
315: int j;
316: char codebuf[30];
317: char *name, *where;
318:
1.11 deraadt 319: for (j = 0;; j ++) {
1.1 mickey 320: if ((name = ipx_errnames[j].name) == 0)
321: break;
322: if (ipx_errnames[j].code == c)
323: break;
324: }
1.11 deraadt 325: if (name == 0) {
1.1 mickey 326: if (c > 01000)
327: where = "in transit";
328: else
329: where = "at destination";
1.5 deraadt 330: snprintf(codebuf, sizeof codebuf,
331: "Unknown IPX error code 0%o", c);
1.1 mickey 332: name = codebuf;
333: } else
1.11 deraadt 334: where = ipx_errnames[j].where;
1.1 mickey 335: ANY(z, name, where);
336: }
1.6 fgsch 337: #endif /* IPXERRORMSGS */
1.1 mickey 338:
1.13 deraadt 339: static struct sockaddr_ipx ssipx = { AF_IPX };
1.1 mickey 340:
341: static char *
1.13 deraadt 342: ipx_prpr(struct ipx_addr *x)
1.1 mickey 343: {
344: struct sockaddr_ipx *sipx = &ssipx;
345:
346: sipx->sipx_addr = *x;
347: return(ipx_print((struct sockaddr *)sipx));
348: }