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