No empty .Rs/.Re
[netbsd-mini2440.git] / usr.bin / netstat / iso.c
blobba367addaac2dc25fec6781d88ca73d34b80e7e5
1 /* $NetBSD: iso.c,v 1.31 2009/02/22 07:43:01 dholland Exp $ */
3 /*
4 * Copyright (c) 1983, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "from: @(#)iso.c 8.1 (Berkeley) 6/6/93";
36 #else
37 __RCSID("$NetBSD: iso.c,v 1.31 2009/02/22 07:43:01 dholland Exp $");
38 #endif
39 #endif /* not lint */
41 /*******************************************************************************
42 Copyright IBM Corporation 1987
44 All Rights Reserved
46 Permission to use, copy, modify, and distribute this software and its
47 documentation for any purpose and without fee is hereby granted,
48 provided that the above copyright notice appear in all copies and that
49 both that copyright notice and this permission notice appear in
50 supporting documentation, and that the name of IBM not be
51 used in advertising or publicity pertaining to distribution of the
52 software without specific, written prior permission.
54 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
55 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
56 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
57 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
58 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
59 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
60 SOFTWARE.
62 *******************************************************************************/
65 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
68 #include <sys/param.h>
69 #include <sys/queue.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 <netinet/in.h>
80 #include <netinet/in_systm.h>
81 #include <netinet/ip.h>
82 #include <netinet/in_pcb.h>
83 #include <netinet/ip_var.h>
84 #include <netiso/iso.h>
85 #include <netiso/iso_errno.h>
86 #include <netiso/clnp.h>
87 #include <netiso/esis.h>
88 #include <netiso/clnp_stat.h>
89 #include <netiso/argo_debug.h>
90 #undef satosiso
91 #include <netiso/tp_param.h>
92 #include <netiso/tp_states.h>
93 #include <netiso/tp_pcb.h>
94 #include <netiso/tp_stat.h>
95 #include <netiso/iso_pcb.h>
96 #include <netiso/cltp_var.h>
97 #include <netiso/cons.h>
98 #include <arpa/inet.h>
99 #include <netdb.h>
100 #include <kvm.h>
101 #include <string.h>
102 #include <stddef.h>
103 #include <stdio.h>
104 #include <stdlib.h>
105 #include "netstat.h"
107 static void tprintstat __P((struct tp_stat *, int));
108 static void isonetprint __P((struct sockaddr_iso *, int));
109 static void hexprint __P((int, const char *, const char *));
110 extern void inetprint __P((struct in_addr *, u_int16_t, const char *, int));
113 * Dump esis stats
115 void
116 esis_stats(off, name)
117 u_long off;
118 const char *name;
120 struct esis_stat esis_stat;
122 if (off == 0 ||
123 kread(off, (char *)&esis_stat, sizeof (struct esis_stat)))
124 return;
125 printf("%s:\n", name);
127 #define ps(f, m) if (esis_stat.f || sflag <= 1) \
128 printf(m, (unsigned long long)esis_stat.f)
129 #define ps2(f1, f2, m) if (esis_stat.f1 || esis_stat.f2 || sflag <= 1) \
130 printf(m, (unsigned long long)esis_stat.f1, (unsigned long long)esis_stat.f2)
132 ps2(es_eshsent, es_eshrcvd, "\t%llu esh sent, %llu esh received\n");
133 ps2(es_ishsent, es_ishrcvd, "\t%llu ish sent, %llu ish received\n");
134 ps2(es_rdsent, es_rdrcvd, "\t%llu rd sent, %llu rd received\n");
135 ps(es_nomem, "\t%llu pdus not sent due to insufficient memory\n");
136 ps(es_badcsum, "\t%llu pdus received with bad checksum\n");
137 ps(es_badvers, "\t%llu pdus received with bad version number\n");
138 ps(es_badtype, "\t%llu pdus received with bad type field\n");
139 ps(es_toosmall, "\t%llu short pdus received\n");
141 #undef ps
142 #undef ps2
146 * Dump clnp statistics structure.
148 void
149 clnp_stats(off, name)
150 u_long off;
151 const char *name;
153 struct clnp_stat clnp_stat;
155 if (off == 0 ||
156 kread(off, (char *)&clnp_stat, sizeof (clnp_stat)))
157 return;
159 printf("%s:\n", name);
161 #define ps(f, m) if (clnp_stat.f || sflag <= 1) \
162 printf(m, (unsigned long long)clnp_stat.f)
163 #define p(f, m) if (clnp_stat.f || sflag <= 1) \
164 printf(m, (unsigned long long)clnp_stat.f, plural(clnp_stat.f))
166 ps(cns_sent, "\t%llu total packets sent\n");
167 ps(cns_fragments, "\t%llu total fragments sent\n");
168 ps(cns_total, "\t%llu total packets received\n");
169 ps(cns_toosmall, "\t%llu with fixed part of header too small\n");
170 ps(cns_badhlen, "\t%llu with header length not reasonable\n");
171 p(cns_badcsum, "\t%llu incorrect checksum%s\n");
172 ps(cns_badaddr, "\t%llu with unreasonable address lengths\n");
173 ps(cns_noseg, "\t%llu with forgotten segmentation information\n");
174 ps(cns_noproto, "\t%llu with an incorrect protocol identifier\n");
175 ps(cns_badvers, "\t%llu with an incorrect version\n");
176 ps(cns_ttlexpired, "\t%llu dropped because the ttl has expired\n");
177 ps(cns_cachemiss, "\t%llu clnp cache misses\n");
178 ps(cns_congest_set, "\t%llu clnp congestion experience bits set\n");
179 ps(cns_congest_rcvd,
180 "\t%llu clnp congestion experience bits received\n");
182 #undef ps
183 #undef p
186 * Dump CLTP statistics structure.
188 void
189 cltp_stats(off, name)
190 u_long off;
191 const char *name;
193 struct cltpstat cltpstat;
195 if (off == 0 ||
196 kread(off, (char *)&cltpstat, sizeof (cltpstat)))
197 return;
200 printf("%s:\n", name);
202 #define p(f, m) if (cltpstat.f || sflag <= 1) \
203 printf(m, (unsigned long long)cltpstat.f, plural(cltpstat.f))
205 p(cltps_hdrops, "\t%llu incomplete header%s\n");
206 p(cltps_badlen,"\t%llu bad data length field%s\n");
207 p(cltps_badsum,"\t%llu bad checksum%s\n");
209 #undef p
212 struct tp_pcb tpcb;
213 struct isopcb isopcb;
214 struct socket sockb;
215 union {
216 struct sockaddr_iso siso;
217 char data[128];
218 } laddr, faddr;
219 #define kget(o, p) \
220 (kread((u_long)(o), (char *)&p, sizeof (p)))
222 static int first = 1;
225 * Print a summary of connections related to an Internet
226 * protocol. For TP, also give state of connection.
227 * Listening processes (aflag) are suppressed unless the
228 * -a (all) flag is specified.
230 void
231 iso_protopr(off, name)
232 u_long off;
233 const char *name;
235 struct isopcb cb;
236 struct isopcb *prev, *next;
238 if (off == 0) {
239 return;
241 if (strcmp(name, "tp") == 0) {
242 tp_protopr(off, name);
243 return;
245 if (kread(off, (char *)&cb, sizeof(cb)))
246 return;
247 isopcb = cb;
248 prev = (struct isopcb *)off;
249 if (isopcb.isop_next == (struct isopcb *)off)
250 return;
251 while (isopcb.isop_next != (struct isopcb *)off) {
252 next = isopcb.isop_next;
253 kget(next, isopcb);
254 if (isopcb.isop_prev != prev) {
255 printf("prev %p next %p isop_prev %p isop_next %p???\n",
256 prev, next, isopcb.isop_prev, isopcb.isop_next);
257 break;
259 kget(isopcb.isop_socket, sockb);
260 iso_protopr1((u_long)next, 0);
261 putchar('\n');
262 prev = next;
266 void
267 iso_protopr1(kern_addr, istp)
268 u_long kern_addr;
269 int istp;
271 int width = 22;
272 if (first) {
273 printf("Active ISO net connections");
274 if (aflag)
275 printf(" (including servers)");
276 putchar('\n');
277 if (Aflag) {
278 width = 18;
279 printf("%-8.8s ", "PCB");
281 printf( "%-5.5s %-6.6s %-6.6s %-*.*s %-*.*s %s\n",
282 "Proto", "Recv-Q", "Send-Q",
283 width, width, "Local Address",
284 width, width, "Foreign Address", "(state)");
285 first = 0;
287 if (Aflag)
288 printf("%8lx ",
289 (u_long) (sockb.so_pcb ? (void *)sockb.so_pcb :
290 (void *)kern_addr));
291 printf("%-5.5s %6ld %6ld ", "tp",
292 sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc);
293 if (istp && tpcb.tp_lsuffixlen) {
294 hexprint(tpcb.tp_lsuffixlen, tpcb.tp_lsuffix, "()");
295 printf("\t");
296 } else if (isopcb.isop_laddr == 0)
297 printf("*.*\t");
298 else {
299 if ((char *)isopcb.isop_laddr == ((char *)kern_addr) +
300 offsetof(struct isopcb, isop_sladdr))
301 laddr.siso = isopcb.isop_sladdr;
302 else
303 kget(isopcb.isop_laddr, laddr);
304 isonetprint((struct sockaddr_iso *)&laddr, 1);
306 if (istp && tpcb.tp_fsuffixlen) {
307 hexprint(tpcb.tp_fsuffixlen, tpcb.tp_fsuffix, "()");
308 printf("\t");
309 } else if (isopcb.isop_faddr == 0)
310 printf("*.*\t");
311 else {
312 if ((char *)isopcb.isop_faddr == ((char *)kern_addr) +
313 offsetof(struct isopcb, isop_sfaddr))
314 faddr.siso = isopcb.isop_sfaddr;
315 else
316 kget(isopcb.isop_faddr, faddr);
317 isonetprint((struct sockaddr_iso *)&faddr, 0);
321 void
322 tp_protopr(off, name)
323 u_long off;
324 const char *name;
326 extern const char * const tp_sstring[]; /* from sys/netiso/tp_astring.c */
327 struct tp_ref *tpr, *tpr_base;
328 struct tp_refinfo tpkerninfo;
329 int size;
331 kget(off, tpkerninfo);
332 size = tpkerninfo.tpr_size * sizeof (*tpr);
333 tpr_base = (struct tp_ref *)malloc(size);
334 if (tpr_base == 0)
335 return;
336 kread((u_long)(tpkerninfo.tpr_base), (char *)tpr_base, size);
337 for (tpr = tpr_base; tpr < tpr_base + tpkerninfo.tpr_size; tpr++) {
338 if (tpr->tpr_pcb == 0)
339 continue;
340 kget(tpr->tpr_pcb, tpcb);
341 if (tpcb.tp_state == ST_ERROR)
342 printf("undefined tpcb state: %p\n", tpr->tpr_pcb);
343 if (!aflag &&
344 (tpcb.tp_state == TP_LISTENING ||
345 tpcb.tp_state == TP_CLOSED ||
346 tpcb.tp_state == TP_REFWAIT)) {
347 continue;
349 kget(tpcb.tp_sock, sockb);
350 if (tpcb.tp_npcb) switch(tpcb.tp_netservice) {
351 case IN_CLNS:
352 tp_inproto((u_long)tpkerninfo.tpr_base);
353 break;
354 default:
355 kget(tpcb.tp_npcb, isopcb);
356 iso_protopr1((u_long)tpcb.tp_npcb, 1);
357 break;
359 if (tpcb.tp_state >= tp_NSTATES)
360 printf(" %d", tpcb.tp_state);
361 else
362 printf(" %-12.12s", tp_sstring[tpcb.tp_state]);
363 putchar('\n');
365 free(tpr_base);
368 void
369 tp_inproto(pcb)
370 u_long pcb;
372 struct inpcb inpcb;
374 kget(tpcb.tp_npcb, inpcb);
375 if (!aflag && inet_lnaof(inpcb.inp_faddr) == INADDR_ANY)
376 return;
377 if (Aflag)
378 printf("%8lx ", pcb);
379 printf("%-5.5s %6ld %6ld ", "tpip",
380 sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc);
381 inetprint(&inpcb.inp_laddr, inpcb.inp_lport, "tp", 1);
382 inetprint(&inpcb.inp_faddr, inpcb.inp_fport, "tp", 1);
386 * Pretty print an iso address (net address + port).
387 * If the numeric_addr or numeric_port were specified,
388 * use numbers instead of names.
391 #ifdef notdef
392 char *
393 isonetname(iso)
394 struct iso_addr *iso;
396 struct sockaddr_iso sa;
397 struct iso_hostent *ihe = 0;
398 struct iso_hostent *iso_gethostentrybyaddr();
399 struct iso_hostent *iso_getserventrybytsel();
400 struct iso_hostent Ihe;
401 static char line[80];
403 memset(line, 0, sizeof(line));
404 if (iso->isoa_afi) {
405 sa.siso_family = AF_ISO;
406 sa.siso_addr = *iso;
407 sa.siso_tsuffix = 0;
409 if (!numeric_addr)
410 ihe = iso_gethostentrybyaddr(&sa, 0, 0);
411 if (ihe) {
412 Ihe = *ihe;
413 ihe = &Ihe;
414 (void)snprintf(line, sizeof line, "%s", ihe->isoh_hname);
415 } else {
416 (void)snprintf(line, sizeof line, "%s", iso_ntoa(iso));
418 } else {
419 (void)snprintf(line, sizeof line, "*");
421 return (line);
424 static void
425 isonetprint(iso, sufx, sufxlen, islocal)
426 struct iso_addr *iso;
427 char *sufx;
428 u_short sufxlen;
429 int islocal;
431 struct iso_hostent *iso_getserventrybytsel(), *ihe;
432 struct iso_hostent Ihe;
433 char *line, *cp;
434 int Alen = Aflag ? 18 : 22;
436 line = isonetname(iso);
437 cp = strchr(line, '\0');
438 ihe = (struct iso_hostent *)0;
440 if (islocal)
441 islocal = 20;
442 else
443 islocal = 22 + Alen;
445 if (Aflag)
446 islocal += 10 ;
448 if (!numeric_addr) {
449 if ((cp - line) > 10) {
450 cp = line + 10;
451 memset(cp, 0, sizeof(line)-10);
455 *cp++ = '.';
456 if (sufxlen) {
457 if (!Aflag && !numeric_port &&
458 (ihe = iso_getserventrybytsel(sufx, sufxlen))) {
459 Ihe = *ihe;
460 ihe = &Ihe;
462 if (ihe && (strlen(ihe->isoh_aname) > 0)) {
463 sprintf(cp, "%s", ihe->isoh_aname); /* XXX */
464 } else {
465 iso_sprinttsel(cp, sufx, sufxlen);
467 } else
468 sprintf(cp, "*");
470 fprintf(stdout, Aflag?" %-18.18s":" %-22.22s", line);
473 if( strlen(line) > Alen ) {
474 fprintf(stdout, " %s", line);
475 fprintf(stdout, "\n %*.s", islocal+Alen," ");
476 } else {
477 fprintf(stdout, " %-*.*s", Alen, Alen,line);
480 #endif
482 #ifdef notdef
483 static void
484 x25_protopr(off, name)
485 u_long off;
486 char *name;
488 static char *xpcb_states[] = {
489 "CLOSED",
490 "LISTENING",
491 "CLOSING",
492 "CONNECTING",
493 "ACKWAIT",
494 "OPEN",
496 struct isopcb *prev, *next;
497 struct x25_pcb xpcb;
499 if (off == 0) {
500 return;
502 kread(off, &xpcb, sizeof (struct x25_pcb));
503 prev = (struct isopcb *)off;
504 if (xpcb.x_next == (struct isopcb *)off)
505 return;
506 while (xpcb.x_next != (struct isopcb *)off) {
507 next = isopcb.isop_next;
508 kread((u_long)next, &xpcb, sizeof (struct x25_pcb));
509 if (xpcb.x_prev != prev) {
510 printf("???\n");
511 break;
513 kread((u_long)xpcb.x_socket, &sockb, sizeof (sockb));
515 if (!aflag &&
516 xpcb.x_state == LISTENING ||
517 xpcb.x_state == TP_CLOSED ) {
518 prev = next;
519 continue;
521 if (first) {
522 printf("Active X25 net connections");
523 if (aflag)
524 printf(" (including servers)");
525 putchar('\n');
526 if (Aflag)
527 printf("%-8.8s ", "PCB");
528 printf(Aflag ?
529 "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
530 "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
531 "Proto", "Recv-Q", "Send-Q",
532 "Local Address", "Foreign Address", "(state)");
533 first = 0;
535 printf("%-5.5s %6d %6d ", name, sockb.so_rcv.sb_cc,
536 sockb.so_snd.sb_cc);
537 isonetprint(&xpcb.x_laddr.siso_addr, &xpcb.x_lport,
538 sizeof(xpcb.x_lport), 1);
539 isonetprint(&xpcb.x_faddr.siso_addr, &xpcb.x_fport,
540 sizeof(xpcb.x_lport), 0);
541 if (xpcb.x_state < 0 || xpcb.x_state >= x25_NSTATES)
542 printf(" 0x0x0x0x0x0x0x0x0x%x", xpcb.x_state);
543 else
544 printf(" %-12.12s", xpcb_states[xpcb.x_state]);
545 putchar('\n');
546 prev = next;
549 #endif
551 struct tp_stat tp_stat;
553 void
554 tp_stats(off, name)
555 u_long off;
556 const char *name;
559 if (off == 0) {
560 printf("TP not configured\n\n");
561 return;
563 printf("%s:\n", name);
564 kget(off, tp_stat);
565 tprintstat(&tp_stat, 8);
568 struct tpstatpr {
569 size_t off;
570 const char *text;
573 #define o(f) offsetof(struct tp_stat, f)
575 static struct tpstatpr tpstatpr_r[] = {
576 { o(ts_param_ignored), "\t%*s%ld variable parameter%s ignored\n"},
577 { o(ts_inv_pcode), "\t%*s%ld invalid parameter code%s\n"},
578 { o(ts_inv_pval), "\t%*s%ld invalid parameter value%s\n"},
579 { o(ts_inv_dutype), "\t%*s%ld invalid dutype%s\n"},
580 { o(ts_negotfailed), "\t%*s%ld negotiation failure%s\n"},
581 { o(ts_inv_dref), "\t%*s%ld invalid destination reference%s\n"},
582 { o(ts_inv_sufx), "\t%*s%ld invalid suffix parameter%s\n"},
583 { o(ts_inv_length), "\t%*s%ld invalid length%s\n"},
584 { o(ts_bad_csum), "\t%*s%ld invalid checksum%s\n"},
585 { o(ts_dt_ooo), "\t%*s%ld DT%s out of order\n"},
586 { o(ts_dt_niw), "\t%*s%ld DT%s not in window\n"},
587 { o(ts_dt_dup), "\t%*s%ld duplicate DT%s\n"},
588 { o(ts_xpd_niw), "\t%*s%ld XPD%s not in window\n"},
589 { o(ts_xpd_dup), "\t%*s%ld XPD%s w/o credit to stash\n"},
590 { o(ts_lcdt_reduced), "\t%*s%ld time%s local credit reneged\n"},
591 { o(ts_concat_rcvd), "\t%*s%ld concatenated TPDU%s\n"},
592 { 0, NULL }
595 static struct tpstatpr tpstatpr_s[] = {
596 { o(ts_xpdmark_del), "\t%*s%ld XPD mark%s discarded\n"},
597 { o(ts_xpd_intheway), "\t%*sXPD stopped data flow %ld time%s\n"},
598 { o(ts_zfcdt), "\t%*s%ld time%s foreign window closed\n"},
599 { 0, NULL }
602 static struct tpstatpr tpstatpr_m[] = {
603 { o(ts_mb_small), "\t%*s%ld small mbuf%s\n"},
604 { o(ts_mb_cluster), "\t%*s%ld cluster%s\n"},
605 { o(ts_quench), "\t%*s%ld source quench%s\n"},
606 { o(ts_rcvdecbit), "\t%*s%ld dec bit%s\n"},
607 { o(ts_eot_input), "\t%*s%ld EOT%s rcvd\n"},
608 { o(ts_EOT_sent), "\t%*s%ld EOT%s sent\n"},
609 { o(ts_eot_user), "\t%*s%ld EOT indication%s\n"},
610 { 0, NULL }
613 static struct tpstatpr tpstatpr_c[] = {
614 { o(ts_xtd_fmt), "\t%*s%ld connection%s used extended format\n"},
615 { o(ts_use_txpd), "\t%*s%ld connection%s allowed transport expedited data\n"},
616 { o(ts_csum_off), "\t%*s%ld connection%s turned off checksumming\n"},
617 { o(ts_conn_gaveup), "\t%*s%ld connection%s dropped due to retrans limit\n"},
618 { o(ts_tp4_conn), "\t%*s%ld tp 4 connection%s\n"},
619 { o(ts_tp0_conn), "\t%*s%ld tp 0 connection%s\n"},
620 { 0, NULL }
623 static struct tpstatpr tpstatpr_p[] = {
624 { o(ts_zdebug), "\t%*s%6ld CC%s sent to zero dref\n"},
625 /* SAME LINE AS ABOVE */
626 { o(ts_ydebug), "\t%*s%6ld random DT%s dropped\n"},
627 { o(ts_vdebug), "\t%*s%6ld illegally large XPD TPDU%s\n"},
628 { o(ts_ldebug), "\t%*s%6ld faked reneging%s of cdt\n"},
629 { 0, NULL }
632 static struct tpstatpr tpstatpr_A[] = {
633 { o(ts_ackreason[_ACK_DONT_]), "\t%*s%6ld not acked immediately%s\n"},
634 { o(ts_ackreason[_ACK_STRAT_EACH_]), "\t%*s%6ld strategy==each%s\n"},
635 { o(ts_ackreason[_ACK_STRAT_FULLWIN_]), "\t%*s%6ld strategy==fullwindow%s\n"},
636 { o(ts_ackreason[_ACK_DUP_]), "\t%*s%6ld duplicate DT%s\n"},
637 { o(ts_ackreason[_ACK_EOT_]), "\t%*s%6ld EOTSDU%s\n"},
638 { o(ts_ackreason[_ACK_REORDER_]), "\t%*s%6ld reordered DT%s\n"},
639 { o(ts_ackreason[_ACK_USRRCV_]), "\t%*s%6ld user rcvd%s\n"},
640 { o(ts_ackreason[_ACK_FCC_]), "\t%*s%6ld fcc reqd%s\n"},
641 { 0, NULL }
643 #undef o
645 static void
646 tprintstat(s, indent)
647 struct tp_stat *s;
648 int indent;
650 int j, tpfirst, tpfirst2;
652 static const char *rttname[]= {
653 "~LOCAL, PDN",
654 "~LOCAL,~PDN",
655 " LOCAL,~PDN",
656 " LOCAL, PDN"
660 * Loop through a struct tpstatpr; if any value is non-zero,
661 * or sflag<=1, print the header if first, and then print the value.
663 #define pgroup(group, header) \
664 for (j = 0, tpfirst=1; group[j].text; j++) \
665 if (*(u_long*)((u_long)s + group[j].off) || \
666 sflag <=1) { \
667 if (tpfirst) { \
668 fprintf(stdout, \
669 header,indent," "); \
670 tpfirst=0; \
672 fprintf(stdout, group[j].text, indent, " ", \
673 *(u_long*)((u_long)s + group[j].off), \
674 plural(*(u_long*)((u_long)s + group[j].off))); \
678 pgroup(tpstatpr_r, "%*sReceived:\n");
679 pgroup(tpstatpr_s, "%*sSending:\n");
681 pgroup(tpstatpr_m, "%*sMiscellaneous:\n");
682 /* print the mbuf chain statistics under the Misc. header */
683 tpfirst2=1;
684 for( j=0, tpfirst2=1; j<=8; j++) {
685 if (s->ts_mb_len_distr[j] || s->ts_mb_len_distr[j<<1] ||
686 sflag <=1) {
687 if (tpfirst) {
688 fprintf(stdout, "%*sMiscellaneous:\n",
689 indent, " ");
690 tpfirst=0;
692 if (tpfirst2) {
693 fprintf(stdout,
694 "\t%*sM:L ( M mbuf chains of length L)\n",
695 indent, " ");
696 tpfirst2=0;
698 if (j==0)
699 fprintf(stdout, "\t%*s%ld: over 16\n",
700 indent, " ", s->ts_mb_len_distr[0]);
701 else
702 fprintf(stdout,
703 "\t%*s%ld: %d\t\t%ld: %d\n", indent, " ",
704 s->ts_mb_len_distr[j],j,
705 s->ts_mb_len_distr[j<<1],j<<1);
709 pgroup(tpstatpr_c, "%*sConnections:\n");
711 tpfirst=1;
712 for (j = 0; j <= 3; j++) {
713 if (s->ts_rtt[j] || s->ts_rtt[j] || s->ts_rtv[j] ||
714 s->ts_rtv[j] || sflag<=1) {
715 if (tpfirst) {
716 fprintf(stdout,
717 "\n%*sRound trip times, "
718 "listed in ticks:\n"
719 "\t%*s%11.11s %12.12s | "
720 "%12.12s | %s\n", indent, " ",
721 indent, " ",
722 "Category",
723 "Smoothed avg", "Deviation",
724 "Deviation/Avg");
725 tpfirst=0;
727 fprintf(stdout,
728 "\t%*s%11.11s: %-11d | %-11d | %-11d | %-11d\n",
729 indent, " ",
730 rttname[j], s->ts_rtt[j], s->ts_rtt[j],
731 s->ts_rtv[j], s->ts_rtv[j]);
736 if (s->ts_tpdu_rcvd || s->ts_pkt_rcvd || s->ts_recv_drop ||
737 s->ts_DT_rcvd || s->ts_AK_rcvd || s->ts_DR_rcvd || s->ts_CR_rcvd ||
738 s->ts_XPD_rcvd || s->ts_XAK_rcvd || s->ts_DC_rcvd ||
739 s->ts_CC_rcvd || s->ts_ER_rcvd || sflag<=1 ) {
740 fprintf(stdout, "\n%*sTpdus RECVD "
741 "[%ld valid, %3.6f %% of total (%ld); %ld dropped]\n",
742 indent," ", s->ts_tpdu_rcvd,
743 ((s->ts_pkt_rcvd > 0) ?
744 ((100 * (float)s->ts_tpdu_rcvd)/(float)s->ts_pkt_rcvd)
745 : 0),
746 s->ts_pkt_rcvd, s->ts_recv_drop );
747 fprintf(stdout,
748 "\t%*sDT %6ld AK %6ld DR %4ld CR %4ld \n",
749 indent, " ", s->ts_DT_rcvd, s->ts_AK_rcvd, s->ts_DR_rcvd,
750 s->ts_CR_rcvd);
751 fprintf(stdout, "\t%*sXPD %6ld XAK %6ld DC %4ld "
752 "CC %4ld ER %4ld\n", indent, " ", s->ts_XPD_rcvd,
753 s->ts_XAK_rcvd, s->ts_DC_rcvd, s->ts_CC_rcvd,
754 s->ts_ER_rcvd);
757 if (s->ts_tpdu_sent || s->ts_send_drop || s->ts_DT_sent ||
758 s->ts_AK_sent || s->ts_DR_sent || s->ts_CR_sent ||
759 s->ts_XPD_sent || s->ts_XAK_sent || s->ts_DC_sent ||
760 s->ts_CC_sent || s->ts_ER_sent || sflag<=1 ) {
761 fprintf(stdout,
762 "\n%*sTpdus SENT [%ld total, %ld dropped]\n", indent, " ",
763 s->ts_tpdu_sent, s->ts_send_drop);
764 fprintf(stdout,
765 "\t%*sDT %6ld AK %6ld DR %4ld CR %4ld \n",
766 indent, " ", s->ts_DT_sent, s->ts_AK_sent, s->ts_DR_sent,
767 s->ts_CR_sent);
768 fprintf(stdout, "\t%*sXPD %6ld XAK %6ld DC %4ld "
769 "CC %4ld ER %4ld\n", indent, " ", s->ts_XPD_sent,
770 s->ts_XAK_sent, s->ts_DC_sent, s->ts_CC_sent,
771 s->ts_ER_sent);
774 if (s->ts_retrans_cr || s->ts_retrans_cc || s->ts_retrans_dr ||
775 s->ts_retrans_dt || s->ts_retrans_xpd || sflag<=1) {
776 fprintf(stdout,
777 "\n%*sRetransmissions:\n", indent, " ");
778 #define PERCENT(X,Y) (((Y)>0)?((100 *(float)(X)) / (float) (Y)):0)
779 fprintf(stdout,
780 "\t%*sCR %6ld CC %6ld DR %6ld \n", indent, " ",
781 s->ts_retrans_cr, s->ts_retrans_cc, s->ts_retrans_dr);
782 fprintf(stdout,
783 "\t%*sDT %6ld (%5.2f%%)\n", indent, " ",
784 s->ts_retrans_dt,
785 PERCENT(s->ts_retrans_dt, s->ts_DT_sent));
786 fprintf(stdout,
787 "\t%*sXPD %6ld (%5.2f%%)\n", indent, " ",
788 s->ts_retrans_xpd,
789 PERCENT(s->ts_retrans_xpd, s->ts_XPD_sent));
790 #undef PERCENT
793 if (s->ts_Eticks || s->ts_Eset || s->ts_Eexpired || s->ts_Ecan_act ||
794 sflag<=1) {
795 fprintf(stdout,
796 "\n%*sE Timers: [%6ld ticks]\n", indent, " ",
797 s->ts_Eticks);
798 fprintf(stdout,
799 "%*s%6ld timer%s set \t%6ld timer%s expired "
800 "\t%6ld timer%s cancelled\n", indent, " ",
801 s->ts_Eset, plural(s->ts_Eset),
802 s->ts_Eexpired, plural(s->ts_Eexpired),
803 s->ts_Ecan_act, plural(s->ts_Ecan_act));
806 if (s->ts_Cset || s->ts_Cexpired || s->ts_Ccan_act ||
807 s->ts_Ccan_inact || sflag<=1) {
808 fprintf(stdout,
809 "\n%*sC Timers: [%6ld ticks]\n", indent, " ",
810 s->ts_Cticks);
811 fprintf(stdout,
812 "%*s%6ld timer%s set \t%6ld timer%s expired "
813 "\t%6ld timer%s cancelled\n",
814 indent, " ",
815 s->ts_Cset, plural(s->ts_Cset),
816 s->ts_Cexpired, plural(s->ts_Cexpired),
817 s->ts_Ccan_act, plural(s->ts_Ccan_act));
818 fprintf(stdout,
819 "%*s%6ld inactive timer%s cancelled\n", indent, " ",
820 s->ts_Ccan_inact, plural(s->ts_Ccan_inact));
823 pgroup(tpstatpr_p, "\n%*sPathological debugging activity:\n");
825 pgroup(tpstatpr_A, "\n%*sACK reasons:\n");
826 #undef pgroup
828 #ifndef SSEL
829 #define SSEL(s) ((s)->siso_tlen + TSEL(s))
830 #define PSEL(s) ((s)->siso_slen + SSEL(s))
831 #endif
833 static void
834 isonetprint(siso, islocal)
835 struct sockaddr_iso *siso;
836 int islocal;
839 hexprint(siso->siso_nlen, siso->siso_addr.isoa_genaddr, "{}");
840 if (siso->siso_tlen || siso->siso_slen || siso->siso_plen)
841 hexprint(siso->siso_tlen, TSEL(siso), "()");
842 if (siso->siso_slen || siso->siso_plen)
843 hexprint(siso->siso_slen, SSEL(siso), "[]");
844 if (siso->siso_plen)
845 hexprint(siso->siso_plen, PSEL(siso), "<>");
846 putchar(' ');
849 static char hexlist[] = "0123456789abcdef", obuf[128];
851 static void
852 hexprint(n, buf, delim)
853 int n;
854 const char *buf;
855 const char *delim;
857 const u_char *in = (const u_char *)buf, *top = in + n;
858 char *out = obuf;
859 int i;
861 if (n == 0)
862 return;
863 while (in < top) {
864 i = *in++;
865 *out++ = '.';
866 if (i > 0xf) {
867 out[1] = hexlist[i & 0xf];
868 i >>= 4;
869 out[0] = hexlist[i];
870 out += 2;
871 } else
872 *out++ = hexlist[i];
874 *obuf = *delim; *out++ = delim[1]; *out = 0;
875 printf("%s", obuf);