Annotation of src/usr.bin/netstat/iso.c, Revision 1.1.1.1
1.1 deraadt 1: /* $NetBSD: iso.c,v 1.12 1995/10/03 21:42:38 thorpej Exp $ */
2:
3: /*
4: * Copyright (c) 1983, 1988, 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #ifndef lint
37: #if 0
38: static char sccsid[] = "from: @(#)iso.c 8.1 (Berkeley) 6/6/93";
39: #else
40: static char *rcsid = "$NetBSD: iso.c,v 1.12 1995/10/03 21:42:38 thorpej Exp $";
41: #endif
42: #endif /* not lint */
43:
44: /*******************************************************************************
45: Copyright IBM Corporation 1987
46:
47: All Rights Reserved
48:
49: Permission to use, copy, modify, and distribute this software and its
50: documentation for any purpose and without fee is hereby granted,
51: provided that the above copyright notice appear in all copies and that
52: both that copyright notice and this permission notice appear in
53: supporting documentation, and that the name of IBM not be
54: used in advertising or publicity pertaining to distribution of the
55: software without specific, written prior permission.
56:
57: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
58: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
59: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
60: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
61: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
62: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
63: SOFTWARE.
64:
65: *******************************************************************************/
66:
67: /*
68: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
69: */
70:
71: #include <sys/param.h>
72: #include <sys/queue.h>
73: #include <sys/mbuf.h>
74: #include <sys/time.h>
75: #include <sys/domain.h>
76: #include <sys/protosw.h>
77: #include <sys/socket.h>
78: #include <sys/socketvar.h>
79: #include <errno.h>
80: #include <net/if.h>
81: #include <net/route.h>
82: #include <netinet/in.h>
83: #include <netinet/in_systm.h>
84: #include <netinet/ip.h>
85: #include <netinet/in_pcb.h>
86: #include <netinet/ip_var.h>
87: #include <netiso/iso.h>
88: #include <netiso/iso_errno.h>
89: #include <netiso/clnp.h>
90: #include <netiso/esis.h>
91: #include <netiso/clnp_stat.h>
92: #include <netiso/argo_debug.h>
93: #undef satosiso
94: #include <netiso/tp_param.h>
95: #include <netiso/tp_states.h>
96: #include <netiso/tp_pcb.h>
97: #include <netiso/tp_stat.h>
98: #include <netiso/iso_pcb.h>
99: #include <netiso/cltp_var.h>
100: #include <netiso/cons.h>
101: #ifdef IncStat
102: #undef IncStat
103: #endif
104: #include <netiso/cons_pcb.h>
105: #include <arpa/inet.h>
106: #include <netdb.h>
107: #include <string.h>
108: #include <stdio.h>
109: #include <stdlib.h>
110: #include "netstat.h"
111:
112: static void tprintstat __P((struct tp_stat *, int));
113: static void isonetprint __P((struct sockaddr_iso *, int));
114: static void hexprint __P((int, char *, char *));
115: extern void inetprint __P((struct in_addr *, int, char *));
116:
117: /*
118: * Dump esis stats
119: */
120: void
121: esis_stats(off, name)
122: u_long off;
123: char *name;
124: {
125: struct esis_stat esis_stat;
126:
127: if (off == 0 ||
128: kread(off, (char *)&esis_stat, sizeof (struct esis_stat)))
129: return;
130: printf("%s:\n", name);
131: printf("\t%d esh sent, %d esh received\n", esis_stat.es_eshsent,
132: esis_stat.es_eshrcvd);
133: printf("\t%d ish sent, %d ish received\n", esis_stat.es_ishsent,
134: esis_stat.es_ishrcvd);
135: printf("\t%d rd sent, %d rd received\n", esis_stat.es_rdsent,
136: esis_stat.es_rdrcvd);
137: printf("\t%d pdus not sent due to insufficient memory\n",
138: esis_stat.es_nomem);
139: printf("\t%d pdus received with bad checksum\n", esis_stat.es_badcsum);
140: printf("\t%d pdus received with bad version number\n",
141: esis_stat.es_badvers);
142: printf("\t%d pdus received with bad type field\n", esis_stat.es_badtype);
143: printf("\t%d short pdus received\n", esis_stat.es_toosmall);
144: }
145:
146: /*
147: * Dump clnp statistics structure.
148: */
149: void
150: clnp_stats(off, name)
151: u_long off;
152: char *name;
153: {
154: struct clnp_stat clnp_stat;
155:
156: if (off == 0 ||
157: kread(off, (char *)&clnp_stat, sizeof (clnp_stat)))
158: return;
159:
160: printf("%s:\n\t%d total packets sent\n", name, clnp_stat.cns_sent);
161: printf("\t%d total fragments sent\n", clnp_stat.cns_fragments);
162: printf("\t%d total packets received\n", clnp_stat.cns_total);
163: printf("\t%d with fixed part of header too small\n",
164: clnp_stat.cns_toosmall);
165: printf("\t%d with header length not reasonable\n", clnp_stat.cns_badhlen);
166: printf("\t%d incorrect checksum%s\n",
167: clnp_stat.cns_badcsum, plural(clnp_stat.cns_badcsum));
168: printf("\t%d with unreasonable address lengths\n", clnp_stat.cns_badaddr);
169: printf("\t%d with forgotten segmentation information\n",
170: clnp_stat.cns_noseg);
171: printf("\t%d with an incorrect protocol identifier\n", clnp_stat.cns_noproto);
172: printf("\t%d with an incorrect version\n", clnp_stat.cns_badvers);
173: printf("\t%d dropped because the ttl has expired\n",
174: clnp_stat.cns_ttlexpired);
175: printf("\t%d clnp cache misses\n", clnp_stat.cns_cachemiss);
176: printf("\t%d clnp congestion experience bits set\n",
177: clnp_stat.cns_congest_set);
178: printf("\t%d clnp congestion experience bits received\n",
179: clnp_stat.cns_congest_rcvd);
180: }
181: /*
182: * Dump CLTP statistics structure.
183: */
184: void
185: cltp_stats(off, name)
186: u_long off;
187: char *name;
188: {
189: struct cltpstat cltpstat;
190:
191: if (off == 0 ||
192: kread(off, (char *)&cltpstat, sizeof (cltpstat)))
193: return;
194: printf("%s:\n\t%u incomplete header%s\n", name,
195: cltpstat.cltps_hdrops, plural(cltpstat.cltps_hdrops));
196: printf("\t%u bad data length field%s\n",
197: cltpstat.cltps_badlen, plural(cltpstat.cltps_badlen));
198: printf("\t%u bad checksum%s\n",
199: cltpstat.cltps_badsum, plural(cltpstat.cltps_badsum));
200: }
201:
202: struct tp_pcb tpcb;
203: struct isopcb isopcb;
204: struct socket sockb;
205: union {
206: struct sockaddr_iso siso;
207: char data[128];
208: } laddr, faddr;
209: #define kget(o, p) \
210: (kread((u_long)(o), (char *)&p, sizeof (p)))
211:
212: static int first = 1;
213:
214: /*
215: * Print a summary of connections related to an Internet
216: * protocol. For TP, also give state of connection.
217: * Listening processes (aflag) are suppressed unless the
218: * -a (all) flag is specified.
219: */
220: void
221: iso_protopr(off, name)
222: u_long off;
223: char *name;
224: {
225: struct isopcb cb;
226: register struct isopcb *prev, *next;
227:
228: if (off == 0) {
229: printf("%s control block: symbol not in namelist\n", name);
230: return;
231: }
232: if (strcmp(name, "tp") == 0) {
233: tp_protopr(off, name);
234: return;
235: }
236: if (kread(off, (char *)&cb, sizeof(cb)))
237: return;
238: isopcb = cb;
239: prev = (struct isopcb *)off;
240: if (isopcb.isop_next == (struct isopcb *)off)
241: return;
242: while (isopcb.isop_next != (struct isopcb *)off) {
243: next = isopcb.isop_next;
244: kget(next, isopcb);
245: if (isopcb.isop_prev != prev) {
246: printf("prev 0x%x next 0x%x isop_prev 0x%x isop_next 0x%x???\n",
247: prev, next, isopcb.isop_prev, isopcb.isop_next);
248: break;
249: }
250: kget(isopcb.isop_socket, sockb);
251: iso_protopr1((u_long)next, 0);
252: putchar('\n');
253: prev = next;
254: }
255: }
256:
257: void
258: iso_protopr1(kern_addr, istp)
259: u_long kern_addr;
260: int istp;
261: {
262: if (first) {
263: printf("Active ISO net connections");
264: if (aflag)
265: printf(" (including servers)");
266: putchar('\n');
267: if (Aflag)
268: printf("%-8.8s ", "PCB");
269: printf(Aflag ?
270: "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
271: "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
272: "Proto", "Recv-Q", "Send-Q",
273: "Local Address", "Foreign Address", "(state)");
274: first = 0;
275: }
276: if (Aflag)
277: printf("%8x ",
278: (sockb.so_pcb ? (void *)sockb.so_pcb : (void *)kern_addr));
279: printf("%-5.5s %6d %6d ", "tp", sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc);
280: if (istp && tpcb.tp_lsuffixlen) {
281: hexprint(tpcb.tp_lsuffixlen, tpcb.tp_lsuffix, "()");
282: printf("\t");
283: } else if (isopcb.isop_laddr == 0)
284: printf("*.*\t");
285: else {
286: if ((char *)isopcb.isop_laddr == ((char *)kern_addr) +
287: _offsetof(struct isopcb, isop_sladdr))
288: laddr.siso = isopcb.isop_sladdr;
289: else
290: kget(isopcb.isop_laddr, laddr);
291: isonetprint((struct sockaddr_iso *)&laddr, 1);
292: }
293: if (istp && tpcb.tp_fsuffixlen) {
294: hexprint(tpcb.tp_fsuffixlen, tpcb.tp_fsuffix, "()");
295: printf("\t");
296: } else if (isopcb.isop_faddr == 0)
297: printf("*.*\t");
298: else {
299: if ((char *)isopcb.isop_faddr == ((char *)kern_addr) +
300: _offsetof(struct isopcb, isop_sfaddr))
301: faddr.siso = isopcb.isop_sfaddr;
302: else
303: kget(isopcb.isop_faddr, faddr);
304: isonetprint((struct sockaddr_iso *)&faddr, 0);
305: }
306: }
307:
308: void
309: tp_protopr(off, name)
310: u_long off;
311: char *name;
312: {
313: extern char *tp_sstring[];
314: struct tp_ref *tpr, *tpr_base;
315: struct tp_refinfo tpkerninfo;
316: int size;
317:
318: kget(off, tpkerninfo);
319: size = tpkerninfo.tpr_size * sizeof (*tpr);
320: tpr_base = (struct tp_ref *)malloc(size);
321: if (tpr_base == 0)
322: return;
323: kread((u_long)(tpkerninfo.tpr_base), (char *)tpr_base, size);
324: for (tpr = tpr_base; tpr < tpr_base + tpkerninfo.tpr_size; tpr++) {
325: if (tpr->tpr_pcb == 0)
326: continue;
327: kget(tpr->tpr_pcb, tpcb);
328: if (tpcb.tp_state == ST_ERROR)
329: printf("undefined tpcb state: 0x%x\n", tpr->tpr_pcb);
330: if (!aflag &&
331: (tpcb.tp_state == TP_LISTENING ||
332: tpcb.tp_state == TP_CLOSED ||
333: tpcb.tp_state == TP_REFWAIT)) {
334: continue;
335: }
336: kget(tpcb.tp_sock, sockb);
337: if (tpcb.tp_npcb) switch(tpcb.tp_netservice) {
338: case IN_CLNS:
339: tp_inproto((u_long)tpkerninfo.tpr_base);
340: break;
341: default:
342: kget(tpcb.tp_npcb, isopcb);
343: iso_protopr1((u_long)tpcb.tp_npcb, 1);
344: break;
345: }
346: if (tpcb.tp_state >= tp_NSTATES)
347: printf(" %d", tpcb.tp_state);
348: else
349: printf(" %-12.12s", tp_sstring[tpcb.tp_state]);
350: putchar('\n');
351: }
352: }
353:
354: void
355: tp_inproto(pcb)
356: u_long pcb;
357: {
358: struct inpcb inpcb;
359: kget(tpcb.tp_npcb, inpcb);
360: if (!aflag && inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
361: return;
362: if (Aflag)
363: printf("%8x ", pcb);
364: printf("%-5.5s %6d %6d ", "tpip",
365: sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc);
366: inetprint(&inpcb.inp_laddr, inpcb.inp_lport, "tp");
367: inetprint(&inpcb.inp_faddr, inpcb.inp_fport, "tp");
368: }
369:
370: /*
371: * Pretty print an iso address (net address + port).
372: * If the nflag was specified, use numbers instead of names.
373: */
374:
375: #ifdef notdef
376: char *
377: isonetname(iso)
378: register struct iso_addr *iso;
379: {
380: struct sockaddr_iso sa;
381: struct iso_hostent *ihe = 0;
382: struct iso_hostent *iso_gethostentrybyaddr();
383: struct iso_hostent *iso_getserventrybytsel();
384: struct iso_hostent Ihe;
385: static char line[80];
386:
387: bzero(line, sizeof(line));
388: if( iso->isoa_afi ) {
389: sa.siso_family = AF_ISO;
390: sa.siso_addr = *iso;
391: sa.siso_tsuffix = 0;
392:
393: if (!nflag )
394: ihe = iso_gethostentrybyaddr( &sa, 0, 0 );
395: if( ihe ) {
396: Ihe = *ihe;
397: ihe = &Ihe;
398: sprintf(line, "%s", ihe->isoh_hname);
399: } else {
400: sprintf(line, "%s", iso_ntoa(iso));
401: }
402: } else {
403: sprintf(line, "*");
404: }
405: return line;
406: }
407:
408: static void
409: isonetprint(iso, sufx, sufxlen, islocal)
410: register struct iso_addr *iso;
411: char *sufx;
412: u_short sufxlen;
413: int islocal;
414: {
415: struct iso_hostent *iso_getserventrybytsel(), *ihe;
416: struct iso_hostent Ihe;
417: char *line, *cp;
418: int Alen = Aflag?18:22;
419:
420: line = isonetname(iso);
421: cp = index(line, '\0');
422: ihe = (struct iso_hostent *)0;
423:
424: if( islocal )
425: islocal = 20;
426: else
427: islocal = 22 + Alen;
428:
429: if(Aflag)
430: islocal += 10 ;
431:
432: if(!nflag) {
433: if( (cp -line)>10 ) {
434: cp = line+10;
435: bzero(cp, sizeof(line)-10);
436: }
437: }
438:
439: *cp++ = '.';
440: if(sufxlen) {
441: if( !Aflag && !nflag && (ihe=iso_getserventrybytsel(sufx, sufxlen))) {
442: Ihe = *ihe;
443: ihe = &Ihe;
444: }
445: if( ihe && (strlen(ihe->isoh_aname)>0) ) {
446: sprintf(cp, "%s", ihe->isoh_aname);
447: } else {
448: iso_sprinttsel(cp, sufx, sufxlen);
449: }
450: } else
451: sprintf(cp, "*");
452: /*
453: fprintf(stdout, Aflag?" %-18.18s":" %-22.22s", line);
454: */
455:
456: if( strlen(line) > Alen ) {
457: fprintf(stdout, " %s", line);
458: fprintf(stdout, "\n %*.s", islocal+Alen," ");
459: } else {
460: fprintf(stdout, " %-*.*s", Alen, Alen,line);
461: }
462: }
463: #endif
464:
465: #ifdef notdef
466: static void
467: x25_protopr(off, name)
468: u_long off;
469: char *name;
470: {
471: static char *xpcb_states[] = {
472: "CLOSED",
473: "LISTENING",
474: "CLOSING",
475: "CONNECTING",
476: "ACKWAIT",
477: "OPEN",
478: };
479: register struct isopcb *prev, *next;
480: struct x25_pcb xpcb;
481:
482: if (off == 0) {
483: printf("%s control block: symbol not in namelist\n", name);
484: return;
485: }
486: kread(off, &xpcb, sizeof (struct x25_pcb));
487: prev = (struct isopcb *)off;
488: if (xpcb.x_next == (struct isopcb *)off)
489: return;
490: while (xpcb.x_next != (struct isopcb *)off) {
491: next = isopcb.isop_next;
492: kread((u_long)next, &xpcb, sizeof (struct x25_pcb));
493: if (xpcb.x_prev != prev) {
494: printf("???\n");
495: break;
496: }
497: kread((u_long)xpcb.x_socket, &sockb, sizeof (sockb));
498:
499: if (!aflag &&
500: xpcb.x_state == LISTENING ||
501: xpcb.x_state == TP_CLOSED ) {
502: prev = next;
503: continue;
504: }
505: if (first) {
506: printf("Active X25 net connections");
507: if (aflag)
508: printf(" (including servers)");
509: putchar('\n');
510: if (Aflag)
511: printf("%-8.8s ", "PCB");
512: printf(Aflag ?
513: "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
514: "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
515: "Proto", "Recv-Q", "Send-Q",
516: "Local Address", "Foreign Address", "(state)");
517: first = 0;
518: }
519: printf("%-5.5s %6d %6d ", name, sockb.so_rcv.sb_cc,
520: sockb.so_snd.sb_cc);
521: isonetprint(&xpcb.x_laddr.siso_addr, &xpcb.x_lport,
522: sizeof(xpcb.x_lport), 1);
523: isonetprint(&xpcb.x_faddr.siso_addr, &xpcb.x_fport,
524: sizeof(xpcb.x_lport), 0);
525: if (xpcb.x_state < 0 || xpcb.x_state >= x25_NSTATES)
526: printf(" 0x0x0x0x0x0x0x0x0x%x", xpcb.x_state);
527: else
528: printf(" %-12.12s", xpcb_states[xpcb.x_state]);
529: putchar('\n');
530: prev = next;
531: }
532: }
533: #endif
534:
535: struct tp_stat tp_stat;
536:
537: void
538: tp_stats(off, name)
539: caddr_t off, name;
540: {
541: if (off == 0) {
542: printf("TP not configured\n\n");
543: return;
544: }
545: printf("%s:\n", name);
546: kget(off, tp_stat);
547: tprintstat(&tp_stat, 8);
548: }
549:
550: #define OUT stdout
551:
552: static void
553: tprintstat(s, indent)
554: register struct tp_stat *s;
555: int indent;
556: {
557: fprintf(OUT,
558: "%*sReceiving:\n",indent," ");
559: fprintf(OUT,
560: "\t%*s%d variable parameter%s ignored\n", indent," ",
561: s->ts_param_ignored ,plural(s->ts_param_ignored));
562: fprintf(OUT,
563: "\t%*s%d invalid parameter code%s\n", indent, " ",
564: s->ts_inv_pcode ,plural(s->ts_inv_pcode));
565: fprintf(OUT,
566: "\t%*s%d invalid parameter value%s\n", indent, " ",
567: s->ts_inv_pval ,plural(s->ts_inv_pval));
568: fprintf(OUT,
569: "\t%*s%d invalid dutype%s\n", indent, " ",
570: s->ts_inv_dutype ,plural(s->ts_inv_dutype));
571: fprintf(OUT,
572: "\t%*s%d negotiation failure%s\n", indent, " ",
573: s->ts_negotfailed ,plural(s->ts_negotfailed));
574: fprintf(OUT,
575: "\t%*s%d invalid destination reference%s\n", indent, " ",
576: s->ts_inv_dref ,plural(s->ts_inv_dref));
577: fprintf(OUT,
578: "\t%*s%d invalid suffix parameter%s\n", indent, " ",
579: s->ts_inv_sufx ,plural(s->ts_inv_sufx));
580: fprintf(OUT,
581: "\t%*s%d invalid length\n",indent, " ", s->ts_inv_length);
582: fprintf(OUT,
583: "\t%*s%d invalid checksum%s\n", indent, " ",
584: s->ts_bad_csum ,plural(s->ts_bad_csum));
585: fprintf(OUT,
586: "\t%*s%d DT%s out of order\n", indent, " ",
587: s->ts_dt_ooo ,plural(s->ts_dt_ooo));
588: fprintf(OUT,
589: "\t%*s%d DT%s not in window\n", indent, " ",
590: s->ts_dt_niw ,plural(s->ts_dt_niw));
591: fprintf(OUT,
592: "\t%*s%d duplicate DT%s\n", indent, " ",
593: s->ts_dt_dup ,plural(s->ts_dt_dup));
594: fprintf(OUT,
595: "\t%*s%d XPD%s not in window\n", indent, " ",
596: s->ts_xpd_niw ,plural(s->ts_xpd_niw));
597: fprintf(OUT,
598: "\t%*s%d XPD%s w/o credit to stash\n", indent, " ",
599: s->ts_xpd_dup ,plural(s->ts_xpd_dup));
600: fprintf(OUT,
601: "\t%*s%d time%s local credit reneged\n", indent, " ",
602: s->ts_lcdt_reduced ,plural(s->ts_lcdt_reduced));
603: fprintf(OUT,
604: "\t%*s%d concatenated TPDU%s\n", indent, " ",
605: s->ts_concat_rcvd ,plural(s->ts_concat_rcvd));
606: fprintf(OUT,
607: "%*sSending:\n", indent, " ");
608: fprintf(OUT,
609: "\t%*s%d XPD mark%s discarded\n", indent, " ",
610: s->ts_xpdmark_del ,plural(s->ts_xpdmark_del));
611: fprintf(OUT,
612: "\t%*sXPD stopped data flow %d time%s\n", indent, " ",
613: s->ts_xpd_intheway ,plural(s->ts_xpd_intheway));
614: fprintf(OUT,
615: "\t%*s%d time%s foreign window closed\n", indent, " ",
616: s->ts_zfcdt ,plural(s->ts_zfcdt));
617: fprintf(OUT,
618: "%*sMiscellaneous:\n", indent, " ");
619: fprintf(OUT,
620: "\t%*s%d small mbuf%s\n", indent, " ",
621: s->ts_mb_small ,plural(s->ts_mb_small));
622: fprintf(OUT,
623: "\t%*s%d cluster%s\n", indent, " ",
624: s->ts_mb_cluster, plural(s->ts_mb_cluster));
625: fprintf(OUT,
626: "\t%*s%d source quench \n",indent, " ",
627: s->ts_quench);
628: fprintf(OUT,
629: "\t%*s%d dec bit%s\n", indent, " ",
630: s->ts_rcvdecbit, plural(s->ts_rcvdecbit));
631: fprintf(OUT,
632: "\t%*sM:L ( M mbuf chains of length L)\n", indent, " ");
633: {
634: register int j;
635:
636: fprintf(OUT, "\t%*s%d: over 16\n", indent, " ",
637: s->ts_mb_len_distr[0]);
638: for( j=1; j<=8; j++) {
639: fprintf(OUT,
640: "\t%*s%d: %d\t\t%d: %d\n", indent, " ",
641: s->ts_mb_len_distr[j],j,
642: s->ts_mb_len_distr[j<<1],j<<1
643: );
644: }
645: }
646: fprintf(OUT,
647: "\t%*s%d EOT rcvd\n", indent, " ", s->ts_eot_input);
648: fprintf(OUT,
649: "\t%*s%d EOT sent\n", indent, " ", s->ts_EOT_sent);
650: fprintf(OUT,
651: "\t%*s%d EOT indication%s\n", indent, " ",
652: s->ts_eot_user ,plural(s->ts_eot_user));
653:
654: fprintf(OUT,
655: "%*sConnections:\n", indent, " ");
656: fprintf(OUT,
657: "\t%*s%d connection%s used extended format\n", indent, " ",
658: s->ts_xtd_fmt ,plural(s->ts_xtd_fmt));
659: fprintf(OUT,
660: "\t%*s%d connection%s allowed transport expedited data\n", indent, " ",
661: s->ts_use_txpd ,plural(s->ts_use_txpd));
662: fprintf(OUT,
663: "\t%*s%d connection%s turned off checksumming\n", indent, " ",
664: s->ts_csum_off ,plural(s->ts_csum_off));
665: fprintf(OUT,
666: "\t%*s%d connection%s dropped due to retrans limit\n", indent, " ",
667: s->ts_conn_gaveup ,plural(s->ts_conn_gaveup));
668: fprintf(OUT,
669: "\t%*s%d tp 4 connection%s\n", indent, " ",
670: s->ts_tp4_conn ,plural(s->ts_tp4_conn));
671: fprintf(OUT,
672: "\t%*s%d tp 0 connection%s\n", indent, " ",
673: s->ts_tp0_conn ,plural(s->ts_tp0_conn));
674: {
675: register int j;
676: static char *name[]= {
677: "~LOCAL, PDN",
678: "~LOCAL,~PDN",
679: " LOCAL,~PDN",
680: " LOCAL, PDN"
681: };
682:
683: fprintf(OUT,
684: "\n%*sRound trip times, listed in ticks:\n", indent, " ");
685: fprintf(OUT,
686: "\t%*s%11.11s %12.12s | %12.12s | %s\n", indent, " ",
687: "Category",
688: "Smoothed avg", "Deviation", "Deviation/Avg");
689: for (j = 0; j <= 3; j++) {
690: fprintf(OUT,
691: "\t%*s%11.11s: %-11d | %-11d | %-11d | %-11d\n", indent, " ",
692: name[j],
693: s->ts_rtt[j],
694: s->ts_rtt[j],
695: s->ts_rtv[j],
696: s->ts_rtv[j]);
697: }
698: }
699: fprintf(OUT,
700: "\n%*sTpdus RECVD [%d valid, %3.6f %% of total (%d); %d dropped]\n",indent," ",
701: s->ts_tpdu_rcvd ,
702: ((s->ts_pkt_rcvd > 0) ?
703: ((100 * (float)s->ts_tpdu_rcvd)/(float)s->ts_pkt_rcvd)
704: : 0),
705: s->ts_pkt_rcvd,
706: s->ts_recv_drop );
707:
708: fprintf(OUT,
709: "\t%*sDT %6d AK %6d DR %4d CR %4d \n", indent, " ",
710: s->ts_DT_rcvd, s->ts_AK_rcvd, s->ts_DR_rcvd, s->ts_CR_rcvd);
711: fprintf(OUT,
712: "\t%*sXPD %6d XAK %6d DC %4d CC %4d ER %4d\n", indent, " ",
713: s->ts_XPD_rcvd, s->ts_XAK_rcvd, s->ts_DC_rcvd, s->ts_CC_rcvd,
714: s->ts_ER_rcvd);
715: fprintf(OUT,
716: "\n%*sTpdus SENT [%d total, %d dropped]\n", indent, " ",
717: s->ts_tpdu_sent, s->ts_send_drop);
718:
719: fprintf(OUT,
720: "\t%*sDT %6d AK %6d DR %4d CR %4d \n", indent, " ",
721: s->ts_DT_sent, s->ts_AK_sent, s->ts_DR_sent, s->ts_CR_sent);
722: fprintf(OUT,
723: "\t%*sXPD %6d XAK %6d DC %4d CC %4d ER %4d\n", indent, " ",
724: s->ts_XPD_sent, s->ts_XAK_sent, s->ts_DC_sent, s->ts_CC_sent,
725: s->ts_ER_sent);
726:
727: fprintf(OUT,
728: "\n%*sRetransmissions:\n", indent, " ");
729: #define PERCENT(X,Y) (((Y)>0)?((100 *(float)(X)) / (float) (Y)):0)
730:
731: fprintf(OUT,
732: "\t%*sCR %6d CC %6d DR %6d \n", indent, " ",
733: s->ts_retrans_cr, s->ts_retrans_cc, s->ts_retrans_dr);
734: fprintf(OUT,
735: "\t%*sDT %6d (%5.2f%%)\n", indent, " ",
736: s->ts_retrans_dt,
737: PERCENT(s->ts_retrans_dt, s->ts_DT_sent));
738: fprintf(OUT,
739: "\t%*sXPD %6d (%5.2f%%)\n", indent, " ",
740: s->ts_retrans_xpd,
741: PERCENT(s->ts_retrans_xpd, s->ts_XPD_sent));
742:
743:
744: fprintf(OUT,
745: "\n%*sE Timers: [%6d ticks]\n", indent, " ", s->ts_Eticks);
746: fprintf(OUT,
747: "%*s%6d timer%s set \t%6d timer%s expired \t%6d timer%s cancelled\n",indent, " ",
748: s->ts_Eset ,plural(s->ts_Eset),
749: s->ts_Eexpired ,plural(s->ts_Eexpired),
750: s->ts_Ecan_act ,plural(s->ts_Ecan_act));
751:
752: fprintf(OUT,
753: "\n%*sC Timers: [%6d ticks]\n", indent, " ",s->ts_Cticks);
754: fprintf(OUT,
755: "%*s%6d timer%s set \t%6d timer%s expired \t%6d timer%s cancelled\n",
756: indent, " ",
757: s->ts_Cset ,plural(s->ts_Cset),
758: s->ts_Cexpired ,plural(s->ts_Cexpired),
759: s->ts_Ccan_act ,plural(s->ts_Ccan_act));
760: fprintf(OUT,
761: "%*s%6d inactive timer%s cancelled\n", indent, " ",
762: s->ts_Ccan_inact ,plural(s->ts_Ccan_inact));
763:
764: fprintf(OUT,
765: "\n%*sPathological debugging activity:\n", indent, " ");
766: fprintf(OUT,
767: "\t%*s%6d CC%s sent to zero dref\n", indent, " ",
768: s->ts_zdebug ,plural(s->ts_zdebug));
769: /* SAME LINE AS ABOVE */
770: fprintf(OUT,
771: "\t%*s%6d random DT%s dropped\n", indent, " ",
772: s->ts_ydebug ,plural(s->ts_ydebug));
773: fprintf(OUT,
774: "\t%*s%6d illegally large XPD TPDU%s\n", indent, " ",
775: s->ts_vdebug ,plural(s->ts_vdebug));
776: fprintf(OUT,
777: "\t%*s%6d faked reneging of cdt\n", indent, " ",
778: s->ts_ldebug );
779:
780: fprintf(OUT,
781: "\n%*sACK reasons:\n", indent, " ");
782: fprintf(OUT, "\t%*s%6d not acked immediately\n", indent, " ",
783: s->ts_ackreason[_ACK_DONT_] );
784: fprintf(OUT, "\t%*s%6d strategy==each\n", indent, " ",
785: s->ts_ackreason[_ACK_STRAT_EACH_] );
786: fprintf(OUT, "\t%*s%6d strategy==fullwindow\n", indent, " ",
787: s->ts_ackreason[_ACK_STRAT_FULLWIN_] );
788: fprintf(OUT, "\t%*s%6d duplicate DT\n", indent, " ",
789: s->ts_ackreason[_ACK_DUP_] );
790: fprintf(OUT, "\t%*s%6d EOTSDU\n", indent, " ",
791: s->ts_ackreason[_ACK_EOT_] );
792: fprintf(OUT, "\t%*s%6d reordered DT\n", indent, " ",
793: s->ts_ackreason[_ACK_REORDER_] );
794: fprintf(OUT, "\t%*s%6d user rcvd\n", indent, " ",
795: s->ts_ackreason[_ACK_USRRCV_] );
796: fprintf(OUT, "\t%*s%6d fcc reqd\n", indent, " ",
797: s->ts_ackreason[_ACK_FCC_] );
798: }
799: #ifndef SSEL
800: #define SSEL(s) ((s)->siso_tlen + TSEL(s))
801: #define PSEL(s) ((s)->siso_slen + SSEL(s))
802: #endif
803:
804: static void
805: isonetprint(siso, islocal)
806: register struct sockaddr_iso *siso;
807: int islocal;
808: {
809: hexprint(siso->siso_nlen, siso->siso_addr.isoa_genaddr, "{}");
810: if (siso->siso_tlen || siso->siso_slen || siso->siso_plen)
811: hexprint(siso->siso_tlen, TSEL(siso), "()");
812: if (siso->siso_slen || siso->siso_plen)
813: hexprint(siso->siso_slen, SSEL(siso), "[]");
814: if (siso->siso_plen)
815: hexprint(siso->siso_plen, PSEL(siso), "<>");
816: putchar(' ');
817: }
818:
819: static char hexlist[] = "0123456789abcdef", obuf[128];
820:
821: static void
822: hexprint(n, buf, delim)
823: int n;
824: char *buf, *delim;
825: {
826: register u_char *in = (u_char *)buf, *top = in + n;
827: register char *out = obuf;
828: register int i;
829:
830: if (n == 0)
831: return;
832: while (in < top) {
833: i = *in++;
834: *out++ = '.';
835: if (i > 0xf) {
836: out[1] = hexlist[i & 0xf];
837: i >>= 4;
838: out[0] = hexlist[i];
839: out += 2;
840: } else
841: *out++ = hexlist[i];
842: }
843: *obuf = *delim; *out++ = delim[1]; *out = 0;
844: printf("%s", obuf);
845: }