X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/dc9744f7c6f1aa8f676f84829ee9a69a52952f94..HEAD:/print-decnet.c diff --git a/print-decnet.c b/print-decnet.c index e595067b..989776b4 100644 --- a/print-decnet.c +++ b/print-decnet.c @@ -20,36 +20,23 @@ */ /* \summary: DECnet printer */ +/* + * specification: Section 10.0 MESSAGES + * DECnet Digital Network Architecture + * Phase IV + * Routing Layer Functional Specification + * Order No. AA-X435A-TK + * Version 2.0.0 December 1983 + */ -#ifdef HAVE_CONFIG_H #include -#endif #include "netdissect-stdinc.h" #include #include -#include - -#ifdef HAVE_DNET_HTOA - #ifdef HAVE_NETDNET_DN_H - #include - #endif - #ifndef HAVE_STRUCT_DN_NADDR -#define DN_MAXADDL 20 /* max size of DECnet address */ -struct dn_naddr { - unsigned short a_len; /* length of address */ - unsigned char a_addr[DN_MAXADDL]; /* address as bytes */ -}; - #endif /* HAVE_STRUCT_DN_NADDR */ - #ifdef HAVE_NETDNET_DNETDB_H - #include - #endif - #ifndef NETDNET_DNETDB_H_DECLARES_DNET_HTOA - extern char *dnet_htoa(struct dn_naddr *); - #endif -#endif +#define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" #include "addrtoname.h" @@ -71,7 +58,7 @@ typedef nd_uint32_t longword; /* 4 bytes field */ * Definitions for DECNET Phase IV protocol headers */ typedef union { - nd_byte dne_addr[6]; /* full ethernet address */ + nd_mac48 dne_addr; /* full Ethernet address */ struct { nd_byte dne_hiord[4]; /* DECnet HIORD prefix */ nd_byte dne_nodeaddr[2]; /* DECnet node address */ @@ -176,18 +163,6 @@ union routehdr /* * Define control message formats. */ -struct initmsgIII /* phase III initialization message */ - { - byte inIII_flags; /* route flags */ - word inIII_src; /* source node address */ - byte inIII_info; /* routing layer information */ - word inIII_blksize; /* maximum data link block size */ - byte inIII_vers; /* version number */ - byte inIII_eco; /* ECO number */ - byte inIII_ueco; /* user ECO number */ - byte inIII_rsvd; /* reserved image field */ - }; - struct initmsg /* initialization message */ { byte in_flags; /* route flags */ @@ -488,10 +463,10 @@ struct dcmsg /* disconnect confirm message */ /* Forwards */ static int print_decnet_ctlmsg(netdissect_options *, const union routehdr *, u_int, u_int); static void print_t_info(netdissect_options *, u_int); -static int print_l1_routes(netdissect_options *, const u_char *, u_int); -static int print_l2_routes(netdissect_options *, const u_char *, u_int); +static void print_l1_routes(netdissect_options *, const u_char *, u_int); +static void print_l2_routes(netdissect_options *, const u_char *, u_int); static void print_i_info(netdissect_options *, u_int); -static int print_elist(const u_char *, u_int); +static void print_elist(const u_char *, u_int); static int print_nsp(netdissect_options *, const u_char *, u_int); static void print_reason(netdissect_options *, u_int); @@ -509,24 +484,27 @@ decnet_print(netdissect_options *ndo, ndo->ndo_protocol = "decnet"; if (length < sizeof(struct shorthdr)) { - nd_print_trunc(ndo); - return; + ND_PRINT(" (length %u < %zu)", length, sizeof(struct shorthdr)); + goto invalid; } - ND_TCHECK_LEN(ap, sizeof(short)); + /* + * This length does not seem to be in any specification, but it is present + * in the test case packet capture, which is consistent with the Wireshark + * protocol decoder. + */ pktlen = GET_LE_U_2(ap); if (pktlen < sizeof(struct shorthdr)) { - nd_print_trunc(ndo); - return; + ND_PRINT(" (pktlen %u < %zu)", pktlen, sizeof(struct shorthdr)); + goto invalid; } if (pktlen > length) { - nd_print_trunc(ndo); - return; + ND_PRINT(" (pktlen %u > %u)", pktlen, length); + goto invalid; } length = pktlen; rhp = (const union routehdr *)(ap + sizeof(short)); - ND_TCHECK_1(rhp->rh_short.sh_flags); mflags = GET_U_1(rhp->rh_short.sh_flags); if (mflags & RMF_PAD) { @@ -535,36 +513,35 @@ decnet_print(netdissect_options *ndo, if (ndo->ndo_vflag) ND_PRINT("[pad:%u] ", padlen); if (length < padlen + 2) { - nd_print_trunc(ndo); - return; + ND_PRINT(" (length %u < %u)", length, padlen + 2); + goto invalid; } ND_TCHECK_LEN(ap + sizeof(short), padlen); ap += padlen; length -= padlen; caplen -= padlen; rhp = (const union routehdr *)(ap + sizeof(short)); - ND_TCHECK_1(rhp->rh_short.sh_flags); mflags = GET_U_1(rhp->rh_short.sh_flags); } if (mflags & RMF_FVER) { ND_PRINT("future-version-decnet"); - ND_DEFAULTPRINT(ap, min(length, caplen)); + ND_DEFAULTPRINT(ap, ND_MIN(length, caplen)); return; } /* is it a control message? */ if (mflags & RMF_CTLMSG) { if (!print_decnet_ctlmsg(ndo, rhp, length, caplen)) - goto trunc; + goto invalid; return; } switch (mflags & RMF_MASK) { case RMF_LONG: if (length < sizeof(struct longhdr)) { - nd_print_trunc(ndo); - return; + ND_PRINT(" (length %u < %zu)", length, sizeof(struct longhdr)); + goto invalid; } ND_TCHECK_SIZE(&rhp->rh_long); dst = @@ -576,7 +553,6 @@ decnet_print(netdissect_options *ndo, nsplen = length - sizeof(struct longhdr); break; case RMF_SHORT: - ND_TCHECK_SIZE(&rhp->rh_short); dst = GET_LE_U_2(rhp->rh_short.sh_dst); src = GET_LE_U_2(rhp->rh_short.sh_src); hops = (GET_U_1(rhp->rh_short.sh_visits) & VIS_MASK)+1; @@ -585,7 +561,7 @@ decnet_print(netdissect_options *ndo, break; default: ND_PRINT("unknown message flags under mask"); - ND_DEFAULTPRINT((const u_char *)ap, min(length, caplen)); + ND_DEFAULTPRINT((const u_char *)ap, ND_MIN(length, caplen)); return; } @@ -602,12 +578,11 @@ decnet_print(netdissect_options *ndo, } if (!print_nsp(ndo, nspp, nsplen)) - goto trunc; + goto invalid; return; -trunc: - nd_print_trunc(ndo); - return; +invalid: + nd_print_invalid(ndo); } static int @@ -622,13 +597,12 @@ print_decnet_ctlmsg(netdissect_options *ndo, u_int info, blksize, eco, ueco, hello, other, vers; u_int priority; const u_char *rhpx = (const u_char *)rhp; - int ret; switch (mflags & RMF_CTLMASK) { case RMF_INIT: ND_PRINT("init "); if (length < sizeof(struct initmsg)) - goto trunc; + goto invalid; ND_TCHECK_SIZE(&cmp->cm_init); src = GET_LE_U_2(cmp->cm_init.in_src); info = GET_U_1(cmp->cm_init.in_info); @@ -641,52 +615,47 @@ print_decnet_ctlmsg(netdissect_options *ndo, ND_PRINT("src %sblksize %u vers %u eco %u ueco %u hello %u", dnaddr_string(ndo, src), blksize, vers, eco, ueco, hello); - ret = 1; break; case RMF_VER: ND_PRINT("verification "); if (length < sizeof(struct verifmsg)) - goto trunc; - ND_TCHECK_SIZE(&cmp->cm_ver); + goto invalid; src = GET_LE_U_2(cmp->cm_ver.ve_src); other = GET_U_1(cmp->cm_ver.ve_fcnval); ND_PRINT("src %s fcnval %o", dnaddr_string(ndo, src), other); - ret = 1; break; case RMF_TEST: ND_PRINT("test "); if (length < sizeof(struct testmsg)) - goto trunc; - ND_TCHECK_SIZE(&cmp->cm_test); + goto invalid; src = GET_LE_U_2(cmp->cm_test.te_src); other = GET_U_1(cmp->cm_test.te_data); ND_PRINT("src %s data %o", dnaddr_string(ndo, src), other); - ret = 1; break; case RMF_L1ROUT: ND_PRINT("lev-1-routing "); if (length < sizeof(struct l1rout)) - goto trunc; + goto invalid; ND_TCHECK_SIZE(&cmp->cm_l1rou); src = GET_LE_U_2(cmp->cm_l1rou.r1_src); ND_PRINT("src %s ", dnaddr_string(ndo, src)); - ret = print_l1_routes(ndo, &(rhpx[sizeof(struct l1rout)]), + print_l1_routes(ndo, &(rhpx[sizeof(struct l1rout)]), length - sizeof(struct l1rout)); break; case RMF_L2ROUT: ND_PRINT("lev-2-routing "); if (length < sizeof(struct l2rout)) - goto trunc; + goto invalid; ND_TCHECK_SIZE(&cmp->cm_l2rout); src = GET_LE_U_2(cmp->cm_l2rout.r2_src); ND_PRINT("src %s ", dnaddr_string(ndo, src)); - ret = print_l2_routes(ndo, &(rhpx[sizeof(struct l2rout)]), + print_l2_routes(ndo, &(rhpx[sizeof(struct l2rout)]), length - sizeof(struct l2rout)); break; case RMF_RHELLO: ND_PRINT("router-hello "); if (length < sizeof(struct rhellomsg)) - goto trunc; + goto invalid; ND_TCHECK_SIZE(&cmp->cm_rhello); vers = GET_U_1(cmp->cm_rhello.rh_vers); eco = GET_U_1(cmp->cm_rhello.rh_eco); @@ -701,14 +670,13 @@ print_decnet_ctlmsg(netdissect_options *ndo, ND_PRINT("vers %u eco %u ueco %u src %s blksize %u pri %u hello %u", vers, eco, ueco, dnaddr_string(ndo, src), blksize, priority, hello); - ret = print_elist(&(rhpx[sizeof(struct rhellomsg)]), + print_elist(&(rhpx[sizeof(struct rhellomsg)]), length - sizeof(struct rhellomsg)); break; case RMF_EHELLO: ND_PRINT("endnode-hello "); if (length < sizeof(struct ehellomsg)) - goto trunc; - ND_TCHECK_SIZE(&cmp->cm_ehello); + goto invalid; vers = GET_U_1(cmp->cm_ehello.eh_vers); eco = GET_U_1(cmp->cm_ehello.eh_eco); ueco = GET_U_1(cmp->cm_ehello.eh_ueco); @@ -725,18 +693,16 @@ print_decnet_ctlmsg(netdissect_options *ndo, ND_PRINT("vers %u eco %u ueco %u src %s blksize %u rtr %s hello %u data %o", vers, eco, ueco, dnaddr_string(ndo, src), blksize, dnaddr_string(ndo, dst), hello, other); - ret = 1; break; default: ND_PRINT("unknown control message"); - ND_DEFAULTPRINT((const u_char *)rhp, min(length, caplen)); - ret = 1; + ND_DEFAULTPRINT((const u_char *)rhp, ND_MIN(length, caplen)); break; } - return (ret); + return (1); -trunc: +invalid: return (0); } @@ -757,7 +723,7 @@ print_t_info(netdissect_options *ndo, ND_PRINT("blo "); } -static int +static void print_l1_routes(netdissect_options *ndo, const u_char *rp, u_int len) { @@ -770,7 +736,7 @@ print_l1_routes(netdissect_options *ndo, ND_TCHECK_LEN(rp, 3 * sizeof(short)); count = GET_LE_U_2(rp); if (count > 1024) - return (1); /* seems to be bogus from here on */ + return; /* seems to be bogus from here on */ rp += sizeof(short); len -= sizeof(short); id = GET_LE_U_2(rp); @@ -782,13 +748,9 @@ print_l1_routes(netdissect_options *ndo, ND_PRINT("{ids %u-%u cost %u hops %u} ", id, id + count, RI_COST(info), RI_HOPS(info)); } - return (1); - -trunc: - return (0); } -static int +static void print_l2_routes(netdissect_options *ndo, const u_char *rp, u_int len) { @@ -801,7 +763,7 @@ print_l2_routes(netdissect_options *ndo, ND_TCHECK_LEN(rp, 3 * sizeof(short)); count = GET_LE_U_2(rp); if (count > 1024) - return (1); /* seems to be bogus from here on */ + return; /* seems to be bogus from here on */ rp += sizeof(short); len -= sizeof(short); area = GET_LE_U_2(rp); @@ -813,10 +775,6 @@ print_l2_routes(netdissect_options *ndo, ND_PRINT("{areas %u-%u cost %u hops %u} ", area, area + count, RI_COST(info), RI_HOPS(info)); } - return (1); - -trunc: - return (0); } static void @@ -838,11 +796,10 @@ print_i_info(netdissect_options *ndo, ND_PRINT("blo "); } -static int +static void print_elist(const u_char *elp _U_, u_int len _U_) { /* Not enough examples available for me to debug this */ - return (1); } static int @@ -852,9 +809,10 @@ print_nsp(netdissect_options *ndo, const struct nsphdr *nsphp = (const struct nsphdr *)nspp; u_int dst, src, flags; - if (nsplen < sizeof(struct nsphdr)) - goto trunc; - ND_TCHECK_SIZE(nsphp); + if (nsplen < sizeof(struct nsphdr)) { + ND_PRINT(" (nsplen %u < %zu)", nsplen, sizeof(struct nsphdr)); + goto invalid; + } flags = GET_U_1(nsphp->nh_flags); dst = GET_LE_U_2(nsphp->nh_dst); src = GET_LE_U_2(nsphp->nh_src); @@ -873,8 +831,7 @@ print_nsp(netdissect_options *ndo, u_int data_off = sizeof(struct minseghdr); if (nsplen < data_off) - goto trunc; - ND_TCHECK_2(shp->sh_seq[0]); + goto invalid; ack = GET_LE_U_2(shp->sh_seq[0]); if (ack & SGQ_ACK) { /* acknum field */ if ((ack & SGQ_NAK) == SGQ_NAK) @@ -883,8 +840,7 @@ print_nsp(netdissect_options *ndo, ND_PRINT("ack %u ", ack & SGQ_MASK); data_off += sizeof(short); if (nsplen < data_off) - goto trunc; - ND_TCHECK_2(shp->sh_seq[1]); + goto invalid; ack = GET_LE_U_2(shp->sh_seq[1]); if (ack & SGQ_OACK) { /* ackoth field */ if ((ack & SGQ_ONAK) == SGQ_ONAK) @@ -893,8 +849,7 @@ print_nsp(netdissect_options *ndo, ND_PRINT("oack %u ", ack & SGQ_MASK); data_off += sizeof(short); if (nsplen < data_off) - goto trunc; - ND_TCHECK_2(shp->sh_seq[2]); + goto invalid; ack = GET_LE_U_2(shp->sh_seq[2]); } } @@ -909,8 +864,7 @@ print_nsp(netdissect_options *ndo, u_int data_off = sizeof(struct minseghdr); if (nsplen < data_off) - goto trunc; - ND_TCHECK_2(shp->sh_seq[0]); + goto invalid; ack = GET_LE_U_2(shp->sh_seq[0]); if (ack & SGQ_ACK) { /* acknum field */ if ((ack & SGQ_NAK) == SGQ_NAK) @@ -919,8 +873,7 @@ print_nsp(netdissect_options *ndo, ND_PRINT("ack %u ", ack & SGQ_MASK); data_off += sizeof(short); if (nsplen < data_off) - goto trunc; - ND_TCHECK_2(shp->sh_seq[1]); + goto invalid; ack = GET_LE_U_2(shp->sh_seq[1]); if (ack & SGQ_OACK) { /* ackdat field */ if ((ack & SGQ_ONAK) == SGQ_ONAK) @@ -929,8 +882,7 @@ print_nsp(netdissect_options *ndo, ND_PRINT("ackdat %u ", ack & SGQ_MASK); data_off += sizeof(short); if (nsplen < data_off) - goto trunc; - ND_TCHECK_2(shp->sh_seq[2]); + goto invalid; ack = GET_LE_U_2(shp->sh_seq[2]); } } @@ -947,27 +899,23 @@ print_nsp(netdissect_options *ndo, u_int lsflags, fcval; if (nsplen < sizeof(struct seghdr) + sizeof(struct lsmsg)) - goto trunc; - ND_TCHECK_2(shp->sh_seq[0]); + goto invalid; ack = GET_LE_U_2(shp->sh_seq[0]); if (ack & SGQ_ACK) { /* acknum field */ if ((ack & SGQ_NAK) == SGQ_NAK) ND_PRINT("nak %u ", ack & SGQ_MASK); else ND_PRINT("ack %u ", ack & SGQ_MASK); - ND_TCHECK_2(shp->sh_seq[1]); ack = GET_LE_U_2(shp->sh_seq[1]); if (ack & SGQ_OACK) { /* ackdat field */ if ((ack & SGQ_ONAK) == SGQ_ONAK) ND_PRINT("nakdat %u ", ack & SGQ_MASK); else ND_PRINT("ackdat %u ", ack & SGQ_MASK); - ND_TCHECK_2(shp->sh_seq[2]); ack = GET_LE_U_2(shp->sh_seq[2]); } } ND_PRINT("seg %u ", ack & SGQ_MASK); - ND_TCHECK_SIZE(lsmp); lsflags = GET_U_1(lsmp->ls_lsflags); fcval = GET_U_1(lsmp->ls_fcval); switch (lsflags & LSI_MASK) { @@ -1010,7 +958,7 @@ print_nsp(netdissect_options *ndo, u_int ack; if (nsplen < sizeof(struct ackmsg)) - goto trunc; + goto invalid; ND_TCHECK_SIZE(amp); ack = GET_LE_U_2(amp->ak_acknum[0]); if (ack & SGQ_ACK) { /* acknum field */ @@ -1035,7 +983,7 @@ print_nsp(netdissect_options *ndo, u_int ack; if (nsplen < sizeof(struct ackmsg)) - goto trunc; + goto invalid; ND_TCHECK_SIZE(amp); ack = GET_LE_U_2(amp->ak_acknum[0]); if (ack & SGQ_ACK) { /* acknum field */ @@ -1043,7 +991,6 @@ print_nsp(netdissect_options *ndo, ND_PRINT("nak %u ", ack & SGQ_MASK); else ND_PRINT("ack %u ", ack & SGQ_MASK); - ND_TCHECK_2(amp->ak_acknum[1]); ack = GET_LE_U_2(amp->ak_acknum[1]); if (ack & SGQ_OACK) { /* ackdat field */ if ((ack & SGQ_ONAK) == SGQ_ONAK) @@ -1076,8 +1023,7 @@ print_nsp(netdissect_options *ndo, u_int services, info, segsize; if (nsplen < sizeof(struct cimsg)) - goto trunc; - ND_TCHECK_SIZE(cimp); + goto invalid; services = GET_U_1(cimp->ci_services); info = GET_U_1(cimp->ci_info); segsize = GET_LE_U_2(cimp->ci_segsize); @@ -1117,8 +1063,7 @@ print_nsp(netdissect_options *ndo, u_int segsize, optlen; if (nsplen < sizeof(struct ccmsg)) - goto trunc; - ND_TCHECK_SIZE(ccmp); + goto invalid; services = GET_U_1(ccmp->cc_services); info = GET_U_1(ccmp->cc_info); segsize = GET_LE_U_2(ccmp->cc_segsize); @@ -1162,8 +1107,7 @@ print_nsp(netdissect_options *ndo, u_int optlen; if (nsplen < sizeof(struct dimsg)) - goto trunc; - ND_TCHECK_SIZE(dimp); + goto invalid; reason = GET_LE_U_2(dimp->di_reason); optlen = GET_U_1(dimp->di_optlen); @@ -1179,7 +1123,6 @@ print_nsp(netdissect_options *ndo, const struct dcmsg *dcmp = (const struct dcmsg *)nspp; u_int reason; - ND_TCHECK_SIZE(dcmp); reason = GET_LE_U_2(dcmp->dc_reason); print_reason(ndo, reason); @@ -1196,7 +1139,7 @@ print_nsp(netdissect_options *ndo, } return (1); -trunc: +invalid: return (0); } @@ -1244,26 +1187,7 @@ dnnum_string(netdissect_options *ndo, u_short dnaddr) /* malloc() return used by the 'dnaddrtable' hash table: do not free() */ str = (char *)malloc(siz = sizeof("00.0000")); if (str == NULL) - (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "dnnum_string: malloc"); - nd_snprintf(str, siz, "%u.%u", area, node); + (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "%s: malloc", __func__); + snprintf(str, siz, "%u.%u", area, node); return(str); } - -const char * -dnname_string(netdissect_options *ndo, u_short dnaddr) -{ -#ifdef HAVE_DNET_HTOA - struct dn_naddr dna; - char *dnname; - - dna.a_len = sizeof(short); - memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short)); - dnname = dnet_htoa(&dna); - if(dnname != NULL) - return (strdup(dnname)); - else - return(dnnum_string(ndo, dnaddr)); -#else - return(dnnum_string(ndo, dnaddr)); /* punt */ -#endif -}