xref: /freebsd/contrib/tcpdump/print-decnet.c (revision a35d88931c87cfe6bd38f01d7bad22140b3b38f3)
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
771