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