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