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