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