Since intr has been setup in the last step of vr_attach(), mii_phy_probe()
[dragonfly.git] / contrib / tcpdump-3.8.3 / print-decnet.c
1 /*
2  * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
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: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  */
21
22 #ifndef lint
23 static const char rcsid[] _U_ =
24     "@(#) $Header: /tcpdump/master/tcpdump/print-decnet.c,v 1.36.2.2 2003/11/16 08:51:16 guy Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <tcpdump-stdinc.h>
32
33 struct mbuf;
34 struct rtentry;
35
36 #ifdef HAVE_NETDNET_DNETDB_H
37 #include <netdnet/dnetdb.h>
38 #endif
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include "decnet.h"
45 #include "extract.h"
46 #include "interface.h"
47 #include "addrtoname.h"
48
49 /* Forwards */
50 static void print_decnet_ctlmsg(const union routehdr *, u_int);
51 static void print_t_info(int);
52 static void print_l1_routes(const char *, u_int);
53 static void print_l2_routes(const char *, u_int);
54 static void print_i_info(int);
55 static void print_elist(const char *, u_int);
56 static void print_nsp(const u_char *, u_int);
57 static void print_reason(int);
58 #ifdef  PRINT_NSPDATA
59 static void pdata(u_char *, int);
60 #endif
61
62 #ifndef HAVE_NETDNET_DNETDB_H_DNET_HTOA
63 extern char *dnet_htoa(struct dn_naddr *);
64 #endif
65
66 void
67 decnet_print(register const u_char *ap, register u_int length,
68              register u_int caplen)
69 {
70         static union routehdr rhcopy;
71         register union routehdr *rhp = &rhcopy;
72         register int mflags;
73         int dst, src, hops;
74         u_int rhlen, nsplen, pktlen;
75         const u_char *nspp;
76
77         if (length < sizeof(struct shorthdr)) {
78                 (void)printf("[|decnet]");
79                 return;
80         }
81
82         pktlen = EXTRACT_LE_16BITS(ap);
83
84         rhlen = min(length, caplen);
85         rhlen = min(rhlen, sizeof(*rhp));
86         memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen);
87
88         mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
89
90         if (mflags & RMF_PAD) {
91             /* pad bytes of some sort in front of message */
92             u_int padlen = mflags & RMF_PADMASK;
93             if (vflag)
94                 (void) printf("[pad:%d] ", padlen);
95             ap += padlen;
96             length -= padlen;
97             caplen -= padlen;
98             rhlen = min(length, caplen);
99             rhlen = min(rhlen, sizeof(*rhp));
100             memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen);
101             mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
102         }
103
104         if (mflags & RMF_FVER) {
105                 (void) printf("future-version-decnet");
106                 default_print(ap, length);
107                 return;
108         }
109
110         /* is it a control message? */
111         if (mflags & RMF_CTLMSG) {
112                 print_decnet_ctlmsg(rhp, min(length, caplen));
113                 return;
114         }
115
116         switch (mflags & RMF_MASK) {
117         case RMF_LONG:
118             dst =
119                 EXTRACT_LE_16BITS(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr);
120             src =
121                 EXTRACT_LE_16BITS(rhp->rh_long.lg_src.dne_remote.dne_nodeaddr);
122             hops = EXTRACT_LE_8BITS(rhp->rh_long.lg_visits);
123             nspp = &(ap[sizeof(short) + sizeof(struct longhdr)]);
124             nsplen = min((length - sizeof(struct longhdr)),
125                          (caplen - sizeof(struct longhdr)));
126             break;
127         case RMF_SHORT:
128             dst = EXTRACT_LE_16BITS(rhp->rh_short.sh_dst);
129             src = EXTRACT_LE_16BITS(rhp->rh_short.sh_src);
130             hops = (EXTRACT_LE_8BITS(rhp->rh_short.sh_visits) & VIS_MASK)+1;
131             nspp = &(ap[sizeof(short) + sizeof(struct shorthdr)]);
132             nsplen = min((length - sizeof(struct shorthdr)),
133                          (caplen - sizeof(struct shorthdr)));
134             break;
135         default:
136             (void) printf("unknown message flags under mask");
137             default_print((u_char *)ap, length);
138             return;
139         }
140
141         (void)printf("%s > %s %d ",
142                         dnaddr_string(src), dnaddr_string(dst), pktlen);
143         if (vflag) {
144             if (mflags & RMF_RQR)
145                 (void)printf("RQR ");
146             if (mflags & RMF_RTS)
147                 (void)printf("RTS ");
148             if (mflags & RMF_IE)
149                 (void)printf("IE ");
150             (void)printf("%d hops ", hops);
151         }
152
153         print_nsp(nspp, nsplen);
154 }
155
156 static void
157 print_decnet_ctlmsg(register const union routehdr *rhp, u_int length)
158 {
159         int mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
160         register union controlmsg *cmp = (union controlmsg *)rhp;
161         int src, dst, info, blksize, eco, ueco, hello, other, vers;
162         etheraddr srcea, rtea;
163         int priority;
164         char *rhpx = (char *)rhp;
165
166         switch (mflags & RMF_CTLMASK) {
167         case RMF_INIT:
168             (void)printf("init ");
169             src = EXTRACT_LE_16BITS(cmp->cm_init.in_src);
170             info = EXTRACT_LE_8BITS(cmp->cm_init.in_info);
171             blksize = EXTRACT_LE_16BITS(cmp->cm_init.in_blksize);
172             vers = EXTRACT_LE_8BITS(cmp->cm_init.in_vers);
173             eco = EXTRACT_LE_8BITS(cmp->cm_init.in_eco);
174             ueco = EXTRACT_LE_8BITS(cmp->cm_init.in_ueco);
175             hello = EXTRACT_LE_16BITS(cmp->cm_init.in_hello);
176             print_t_info(info);
177             (void)printf(
178                 "src %sblksize %d vers %d eco %d ueco %d hello %d",
179                         dnaddr_string(src), blksize, vers, eco, ueco,
180                         hello);
181             break;
182         case RMF_VER:
183             (void)printf("verification ");
184             src = EXTRACT_LE_16BITS(cmp->cm_ver.ve_src);
185             other = EXTRACT_LE_8BITS(cmp->cm_ver.ve_fcnval);
186             (void)printf("src %s fcnval %o", dnaddr_string(src), other);
187             break;
188         case RMF_TEST:
189             (void)printf("test ");
190             src = EXTRACT_LE_16BITS(cmp->cm_test.te_src);
191             other = EXTRACT_LE_8BITS(cmp->cm_test.te_data);
192             (void)printf("src %s data %o", dnaddr_string(src), other);
193             break;
194         case RMF_L1ROUT:
195             (void)printf("lev-1-routing ");
196             src = EXTRACT_LE_16BITS(cmp->cm_l1rou.r1_src);
197             (void)printf("src %s ", dnaddr_string(src));
198             print_l1_routes(&(rhpx[sizeof(struct l1rout)]),
199                                 length - sizeof(struct l1rout));
200             break;
201         case RMF_L2ROUT:
202             (void)printf("lev-2-routing ");
203             src = EXTRACT_LE_16BITS(cmp->cm_l2rout.r2_src);
204             (void)printf("src %s ", dnaddr_string(src));
205             print_l2_routes(&(rhpx[sizeof(struct l2rout)]),
206                                 length - sizeof(struct l2rout));
207             break;
208         case RMF_RHELLO:
209             (void)printf("router-hello ");
210             vers = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_vers);
211             eco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_eco);
212             ueco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_ueco);
213             memcpy((char *)&srcea, (char *)&(cmp->cm_rhello.rh_src),
214                 sizeof(srcea));
215             src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr);
216             info = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_info);
217             blksize = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_blksize);
218             priority = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_priority);
219             hello = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_hello);
220             print_i_info(info);
221             (void)printf(
222             "vers %d eco %d ueco %d src %s blksize %d pri %d hello %d",
223                         vers, eco, ueco, dnaddr_string(src),
224                         blksize, priority, hello);
225             print_elist(&(rhpx[sizeof(struct rhellomsg)]),
226                                 length - sizeof(struct rhellomsg));
227             break;
228         case RMF_EHELLO:
229             (void)printf("endnode-hello ");
230             vers = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_vers);
231             eco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_eco);
232             ueco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_ueco);
233             memcpy((char *)&srcea, (char *)&(cmp->cm_ehello.eh_src),
234                 sizeof(srcea));
235             src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr);
236             info = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_info);
237             blksize = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_blksize);
238             /*seed*/
239             memcpy((char *)&rtea, (char *)&(cmp->cm_ehello.eh_router),
240                 sizeof(rtea));
241             dst = EXTRACT_LE_16BITS(rtea.dne_remote.dne_nodeaddr);
242             hello = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_hello);
243             other = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_data);
244             print_i_info(info);
245             (void)printf(
246         "vers %d eco %d ueco %d src %s blksize %d rtr %s hello %d data %o",
247                         vers, eco, ueco, dnaddr_string(src),
248                         blksize, dnaddr_string(dst), hello, other);
249             break;
250
251         default:
252             (void)printf("unknown control message");
253             default_print((u_char *)rhp, length);
254             break;
255         }
256 }
257
258 static void
259 print_t_info(int info)
260 {
261         int ntype = info & 3;
262         switch (ntype) {
263         case 0: (void)printf("reserved-ntype? "); break;
264         case TI_L2ROUT: (void)printf("l2rout "); break;
265         case TI_L1ROUT: (void)printf("l1rout "); break;
266         case TI_ENDNODE: (void)printf("endnode "); break;
267         }
268         if (info & TI_VERIF)
269             (void)printf("verif ");
270         if (info & TI_BLOCK)
271             (void)printf("blo ");
272 }
273
274 static void
275 print_l1_routes(const char *rp, u_int len)
276 {
277         int count;
278         int id;
279         int info;
280
281         /* The last short is a checksum */
282         while (len > (3 * sizeof(short))) {
283             count = EXTRACT_LE_16BITS(rp);
284             if (count > 1024)
285                 return; /* seems to be bogus from here on */
286             rp += sizeof(short);
287             len -= sizeof(short);
288             id = EXTRACT_LE_16BITS(rp);
289             rp += sizeof(short);
290             len -= sizeof(short);
291             info = EXTRACT_LE_16BITS(rp);
292             rp += sizeof(short);
293             len -= sizeof(short);
294             (void)printf("{ids %d-%d cost %d hops %d} ", id, id + count,
295                             RI_COST(info), RI_HOPS(info));
296         }
297 }
298
299 static void
300 print_l2_routes(const char *rp, u_int len)
301 {
302         int count;
303         int area;
304         int info;
305
306         /* The last short is a checksum */
307         while (len > (3 * sizeof(short))) {
308             count = EXTRACT_LE_16BITS(rp);
309             if (count > 1024)
310                 return; /* seems to be bogus from here on */
311             rp += sizeof(short);
312             len -= sizeof(short);
313             area = EXTRACT_LE_16BITS(rp);
314             rp += sizeof(short);
315             len -= sizeof(short);
316             info = EXTRACT_LE_16BITS(rp);
317             rp += sizeof(short);
318             len -= sizeof(short);
319             (void)printf("{areas %d-%d cost %d hops %d} ", area, area + count,
320                             RI_COST(info), RI_HOPS(info));
321         }
322 }
323
324 static void
325 print_i_info(int info)
326 {
327         int ntype = info & II_TYPEMASK;
328         switch (ntype) {
329         case 0: (void)printf("reserved-ntype? "); break;
330         case II_L2ROUT: (void)printf("l2rout "); break;
331         case II_L1ROUT: (void)printf("l1rout "); break;
332         case II_ENDNODE: (void)printf("endnode "); break;
333         }
334         if (info & II_VERIF)
335             (void)printf("verif ");
336         if (info & II_NOMCAST)
337             (void)printf("nomcast ");
338         if (info & II_BLOCK)
339             (void)printf("blo ");
340 }
341
342 static void
343 print_elist(const char *elp _U_, u_int len _U_)
344 {
345         /* Not enough examples available for me to debug this */
346 }
347
348 static void
349 print_nsp(const u_char *nspp, u_int nsplen _U_)
350 {
351         const struct nsphdr *nsphp = (struct nsphdr *)nspp;
352         int dst, src, flags;
353
354         flags = EXTRACT_LE_8BITS(nsphp->nh_flags);
355         dst = EXTRACT_LE_16BITS(nsphp->nh_dst);
356         src = EXTRACT_LE_16BITS(nsphp->nh_src);
357
358         switch (flags & NSP_TYPEMASK) {
359         case MFT_DATA:
360             switch (flags & NSP_SUBMASK) {
361             case MFS_BOM:
362             case MFS_MOM:
363             case MFS_EOM:
364             case MFS_BOM+MFS_EOM:
365                 printf("data %d>%d ", src, dst);
366                 {
367                     struct seghdr *shp = (struct seghdr *)nspp;
368                     int ack;
369 #ifdef  PRINT_NSPDATA
370                     u_char *dp;
371 #endif
372                     u_int data_off = sizeof(struct minseghdr);
373
374                     ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
375                     if (ack & SGQ_ACK) {        /* acknum field */
376                         if ((ack & SGQ_NAK) == SGQ_NAK)
377                             (void)printf("nak %d ", ack & SGQ_MASK);
378                         else
379                             (void)printf("ack %d ", ack & SGQ_MASK);
380                         ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
381                         data_off += sizeof(short);
382                         if (ack & SGQ_OACK) {   /* ackoth field */
383                             if ((ack & SGQ_ONAK) == SGQ_ONAK)
384                                 (void)printf("onak %d ", ack & SGQ_MASK);
385                             else
386                                 (void)printf("oack %d ", ack & SGQ_MASK);
387                             ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
388                             data_off += sizeof(short);
389                         }
390                     }
391                     (void)printf("seg %d ", ack & SGQ_MASK);
392 #ifdef  PRINT_NSPDATA
393                     dp = &(nspp[data_off]);
394                     pdata(dp, 10);
395 #endif
396                 }
397                 break;
398             case MFS_ILS+MFS_INT:
399                 printf("intr ");
400                 {
401                     struct seghdr *shp = (struct seghdr *)nspp;
402                     int ack;
403 #ifdef  PRINT_NSPDATA
404                     u_char *dp;
405 #endif
406                     u_int data_off = sizeof(struct minseghdr);
407
408                     ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
409                     if (ack & SGQ_ACK) {        /* acknum field */
410                         if ((ack & SGQ_NAK) == SGQ_NAK)
411                             (void)printf("nak %d ", ack & SGQ_MASK);
412                         else
413                             (void)printf("ack %d ", ack & SGQ_MASK);
414                         ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
415                         data_off += sizeof(short);
416                         if (ack & SGQ_OACK) {   /* ackdat field */
417                             if ((ack & SGQ_ONAK) == SGQ_ONAK)
418                                 (void)printf("nakdat %d ", ack & SGQ_MASK);
419                             else
420                                 (void)printf("ackdat %d ", ack & SGQ_MASK);
421                             ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
422                             data_off += sizeof(short);
423                         }
424                     }
425                     (void)printf("seg %d ", ack & SGQ_MASK);
426 #ifdef  PRINT_NSPDATA
427                     dp = &(nspp[data_off]);
428                     pdata(dp, 10);
429 #endif
430                 }
431                 break;
432             case MFS_ILS:
433                 (void)printf("link-service %d>%d ", src, dst);
434                 {
435                     struct seghdr *shp = (struct seghdr *)nspp;
436                     struct lsmsg *lsmp =
437                         (struct lsmsg *)&(nspp[sizeof(struct seghdr)]);
438                     int ack;
439                     int lsflags, fcval;
440
441                     ack = EXTRACT_LE_16BITS(shp->sh_seq[0]);
442                     if (ack & SGQ_ACK) {        /* acknum field */
443                         if ((ack & SGQ_NAK) == SGQ_NAK)
444                             (void)printf("nak %d ", ack & SGQ_MASK);
445                         else
446                             (void)printf("ack %d ", ack & SGQ_MASK);
447                         ack = EXTRACT_LE_16BITS(shp->sh_seq[1]);
448                         if (ack & SGQ_OACK) {   /* ackdat field */
449                             if ((ack & SGQ_ONAK) == SGQ_ONAK)
450                                 (void)printf("nakdat %d ", ack & SGQ_MASK);
451                             else
452                                 (void)printf("ackdat %d ", ack & SGQ_MASK);
453                             ack = EXTRACT_LE_16BITS(shp->sh_seq[2]);
454                         }
455                     }
456                     (void)printf("seg %d ", ack & SGQ_MASK);
457                     lsflags = EXTRACT_LE_8BITS(lsmp->ls_lsflags);
458                     fcval = EXTRACT_LE_8BITS(lsmp->ls_fcval);
459                     switch (lsflags & LSI_MASK) {
460                     case LSI_DATA:
461                         (void)printf("dat seg count %d ", fcval);
462                         switch (lsflags & LSM_MASK) {
463                         case LSM_NOCHANGE:
464                             break;
465                         case LSM_DONOTSEND:
466                             (void)printf("donotsend-data ");
467                             break;
468                         case LSM_SEND:
469                             (void)printf("send-data ");
470                             break;
471                         default:
472                             (void)printf("reserved-fcmod? %x", lsflags);
473                             break;
474                         }
475                         break;
476                     case LSI_INTR:
477                         (void)printf("intr req count %d ", fcval);
478                         break;
479                     default:
480                         (void)printf("reserved-fcval-int? %x", lsflags);
481                         break;
482                     }
483                 }
484                 break;
485             default:
486                 (void)printf("reserved-subtype? %x %d > %d", flags, src, dst);
487                 break;
488             }
489             break;
490         case MFT_ACK:
491             switch (flags & NSP_SUBMASK) {
492             case MFS_DACK:
493                 (void)printf("data-ack %d>%d ", src, dst);
494                 {
495                     struct ackmsg *amp = (struct ackmsg *)nspp;
496                     int ack;
497
498                     ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]);
499                     if (ack & SGQ_ACK) {        /* acknum field */
500                         if ((ack & SGQ_NAK) == SGQ_NAK)
501                             (void)printf("nak %d ", ack & SGQ_MASK);
502                         else
503                             (void)printf("ack %d ", ack & SGQ_MASK);
504                         ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]);
505                         if (ack & SGQ_OACK) {   /* ackoth field */
506                             if ((ack & SGQ_ONAK) == SGQ_ONAK)
507                                 (void)printf("onak %d ", ack & SGQ_MASK);
508                             else
509                                 (void)printf("oack %d ", ack & SGQ_MASK);
510                         }
511                     }
512                 }
513                 break;
514             case MFS_IACK:
515                 (void)printf("ils-ack %d>%d ", src, dst);
516                 {
517                     struct ackmsg *amp = (struct ackmsg *)nspp;
518                     int ack;
519
520                     ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]);
521                     if (ack & SGQ_ACK) {        /* acknum field */
522                         if ((ack & SGQ_NAK) == SGQ_NAK)
523                             (void)printf("nak %d ", ack & SGQ_MASK);
524                         else
525                             (void)printf("ack %d ", ack & SGQ_MASK);
526                         ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]);
527                         if (ack & SGQ_OACK) {   /* ackdat field */
528                             if ((ack & SGQ_ONAK) == SGQ_ONAK)
529                                 (void)printf("nakdat %d ", ack & SGQ_MASK);
530                             else
531                                 (void)printf("ackdat %d ", ack & SGQ_MASK);
532                         }
533                     }
534                 }
535                 break;
536             case MFS_CACK:
537                 (void)printf("conn-ack %d", dst);
538                 break;
539             default:
540                 (void)printf("reserved-acktype? %x %d > %d", flags, src, dst);
541                 break;
542             }
543             break;
544         case MFT_CTL:
545             switch (flags & NSP_SUBMASK) {
546             case MFS_CI:
547             case MFS_RCI:
548                 if ((flags & NSP_SUBMASK) == MFS_CI)
549                     (void)printf("conn-initiate ");
550                 else
551                     (void)printf("retrans-conn-initiate ");
552                 (void)printf("%d>%d ", src, dst);
553                 {
554                     struct cimsg *cimp = (struct cimsg *)nspp;
555                     int services, info, segsize;
556 #ifdef  PRINT_NSPDATA
557                     u_char *dp;
558 #endif
559
560                     services = EXTRACT_LE_8BITS(cimp->ci_services);
561                     info = EXTRACT_LE_8BITS(cimp->ci_info);
562                     segsize = EXTRACT_LE_16BITS(cimp->ci_segsize);
563
564                     switch (services & COS_MASK) {
565                     case COS_NONE:
566                         break;
567                     case COS_SEGMENT:
568                         (void)printf("seg ");
569                         break;
570                     case COS_MESSAGE:
571                         (void)printf("msg ");
572                         break;
573                     case COS_CRYPTSER:
574                         (void)printf("crypt ");
575                         break;
576                     }
577                     switch (info & COI_MASK) {
578                     case COI_32:
579                         (void)printf("ver 3.2 ");
580                         break;
581                     case COI_31:
582                         (void)printf("ver 3.1 ");
583                         break;
584                     case COI_40:
585                         (void)printf("ver 4.0 ");
586                         break;
587                     case COI_41:
588                         (void)printf("ver 4.1 ");
589                         break;
590                     }
591                     (void)printf("segsize %d ", segsize);
592 #ifdef  PRINT_NSPDATA
593                     dp = &(nspp[sizeof(struct cimsg)]);
594                     pdata(dp, nsplen - sizeof(struct cimsg));
595 #endif
596                 }
597                 break;
598             case MFS_CC:
599                 (void)printf("conn-confirm %d>%d ", src, dst);
600                 {
601                     struct ccmsg *ccmp = (struct ccmsg *)nspp;
602                     int services, info;
603                     u_int segsize, optlen;
604 #ifdef  PRINT_NSPDATA
605                     u_char *dp;
606 #endif
607
608                     services = EXTRACT_LE_8BITS(ccmp->cc_services);
609                     info = EXTRACT_LE_8BITS(ccmp->cc_info);
610                     segsize = EXTRACT_LE_16BITS(ccmp->cc_segsize);
611                     optlen = EXTRACT_LE_8BITS(ccmp->cc_optlen);
612
613                     switch (services & COS_MASK) {
614                     case COS_NONE:
615                         break;
616                     case COS_SEGMENT:
617                         (void)printf("seg ");
618                         break;
619                     case COS_MESSAGE:
620                         (void)printf("msg ");
621                         break;
622                     case COS_CRYPTSER:
623                         (void)printf("crypt ");
624                         break;
625                     }
626                     switch (info & COI_MASK) {
627                     case COI_32:
628                         (void)printf("ver 3.2 ");
629                         break;
630                     case COI_31:
631                         (void)printf("ver 3.1 ");
632                         break;
633                     case COI_40:
634                         (void)printf("ver 4.0 ");
635                         break;
636                     case COI_41:
637                         (void)printf("ver 4.1 ");
638                         break;
639                     }
640                     (void)printf("segsize %d ", segsize);
641                     if (optlen) {
642                         (void)printf("optlen %d ", optlen);
643 #ifdef  PRINT_NSPDATA
644                         optlen = min(optlen, nsplen - sizeof(struct ccmsg));
645                         dp = &(nspp[sizeof(struct ccmsg)]);
646                         pdata(dp, optlen);
647 #endif
648                     }
649                 }
650                 break;
651             case MFS_DI:
652                 (void)printf("disconn-initiate %d>%d ", src, dst);
653                 {
654                     struct dimsg *dimp = (struct dimsg *)nspp;
655                     int reason;
656                     u_int optlen;
657 #ifdef  PRINT_NSPDATA
658                     u_char *dp;
659 #endif
660
661                     reason = EXTRACT_LE_16BITS(dimp->di_reason);
662                     optlen = EXTRACT_LE_8BITS(dimp->di_optlen);
663
664                     print_reason(reason);
665                     if (optlen) {
666                         (void)printf("optlen %d ", optlen);
667 #ifdef  PRINT_NSPDATA
668                         optlen = min(optlen, nsplen - sizeof(struct dimsg));
669                         dp = &(nspp[sizeof(struct dimsg)]);
670                         pdata(dp, optlen);
671 #endif
672                     }
673                 }
674                 break;
675             case MFS_DC:
676                 (void)printf("disconn-confirm %d>%d ", src, dst);
677                 {
678                     struct dcmsg *dcmp = (struct dcmsg *)nspp;
679                     int reason;
680
681                     reason = EXTRACT_LE_16BITS(dcmp->dc_reason);
682
683                     print_reason(reason);
684                 }
685                 break;
686             default:
687                 (void)printf("reserved-ctltype? %x %d > %d", flags, src, dst);
688                 break;
689             }
690             break;
691         default:
692             (void)printf("reserved-type? %x %d > %d", flags, src, dst);
693             break;
694         }
695 }
696
697 static struct tok reason2str[] = {
698         { UC_OBJREJECT,         "object rejected connect" },
699         { UC_RESOURCES,         "insufficient resources" },
700         { UC_NOSUCHNODE,        "unrecognized node name" },
701         { DI_SHUT,              "node is shutting down" },
702         { UC_NOSUCHOBJ,         "unrecognized object" },
703         { UC_INVOBJFORMAT,      "invalid object name format" },
704         { UC_OBJTOOBUSY,        "object too busy" },
705         { DI_PROTOCOL,          "protocol error discovered" },
706         { DI_TPA,               "third party abort" },
707         { UC_USERABORT,         "user abort" },
708         { UC_INVNODEFORMAT,     "invalid node name format" },
709         { UC_LOCALSHUT,         "local node shutting down" },
710         { DI_LOCALRESRC,        "insufficient local resources" },
711         { DI_REMUSERRESRC,      "insufficient remote user resources" },
712         { UC_ACCESSREJECT,      "invalid access control information" },
713         { DI_BADACCNT,          "bad ACCOUNT information" },
714         { UC_NORESPONSE,        "no response from object" },
715         { UC_UNREACHABLE,       "node unreachable" },
716         { DC_NOLINK,            "no link terminate" },
717         { DC_COMPLETE,          "disconnect complete" },
718         { DI_BADIMAGE,          "bad image data in connect" },
719         { DI_SERVMISMATCH,      "cryptographic service mismatch" },
720         { 0,                    NULL }
721 };
722
723 static void
724 print_reason(register int reason)
725 {
726         printf("%s ", tok2str(reason2str, "reason-%d", reason));
727 }
728
729 const char *
730 dnnum_string(u_short dnaddr)
731 {
732         char *str;
733         size_t siz;
734         int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT;
735         int node = dnaddr & NODEMASK;
736
737         str = (char *)malloc(siz = sizeof("00.0000"));
738         if (str == NULL)
739                 error("dnnum_string: malloc");
740         snprintf(str, siz, "%d.%d", area, node);
741         return(str);
742 }
743
744 const char *
745 dnname_string(u_short dnaddr)
746 {
747 #ifdef HAVE_DNET_HTOA
748         struct dn_naddr dna;
749
750         dna.a_len = sizeof(short);
751         memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short));
752         return (strdup(dnet_htoa(&dna)));
753 #else
754         return(dnnum_string(dnaddr));   /* punt */
755 #endif
756 }
757
758 #ifdef  PRINT_NSPDATA
759 static void
760 pdata(u_char *dp, u_int maxlen)
761 {
762         char c;
763         u_int x = maxlen;
764
765         while (x-- > 0) {
766             c = *dp++;
767             safeputchar(c);
768         }
769 }
770 #endif