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