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