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