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