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