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