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