X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/dff10c7f70d539c431a1eba9ab5e076d8b0f5c8e..2b4965f56167dfda7c60fc9db2d145698d948fd5:/print-decnet.c diff --git a/print-decnet.c b/print-decnet.c index 4c290f9e..7fea582e 100644 --- a/print-decnet.c +++ b/print-decnet.c @@ -20,36 +20,26 @@ */ #ifndef lint -static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-decnet.c,v 1.28 2000-01-17 06:24:24 itojun Exp $ (LBL)"; +static const char rcsid[] _U_ = + "@(#) $Header: /tcpdump/master/tcpdump/print-decnet.c,v 1.39 2005-05-06 02:16:26 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include -#include -#include +#include -#if __STDC__ struct mbuf; struct rtentry; -#endif -#include -#ifdef HAVE_LIBDNET +#ifdef HAVE_NETDNET_DNETDB_H #include #endif -#include -#ifdef HAVE_MALLOC_H -#include -#endif #include #include #include -#include #include "decnet.h" #include "extract.h" @@ -57,19 +47,19 @@ struct rtentry; #include "addrtoname.h" /* Forwards */ -static void print_decnet_ctlmsg(const union routehdr *, u_int); +static int print_decnet_ctlmsg(const union routehdr *, u_int, u_int); static void print_t_info(int); -static void print_l1_routes(const char *, u_int); -static void print_l2_routes(const char *, u_int); +static int print_l1_routes(const char *, u_int); +static int print_l2_routes(const char *, u_int); static void print_i_info(int); -static void print_elist(const char *, u_int); -static void print_nsp(const u_char *, u_int); +static int print_elist(const char *, u_int); +static int print_nsp(const u_char *, u_int); static void print_reason(int); #ifdef PRINT_NSPDATA static void pdata(u_char *, int); #endif -#ifdef HAVE_LIBDNET +#ifndef HAVE_NETDNET_DNETDB_H_DNET_HTOA extern char *dnet_htoa(struct dn_naddr *); #endif @@ -77,11 +67,10 @@ void decnet_print(register const u_char *ap, register u_int length, register u_int caplen) { - static union routehdr rhcopy; - register union routehdr *rhp = &rhcopy; + register const union routehdr *rhp; register int mflags; int dst, src, hops; - u_int rhlen, nsplen, pktlen; + u_int nsplen, pktlen; const u_char *nspp; if (length < sizeof(struct shorthdr)) { @@ -89,12 +78,20 @@ decnet_print(register const u_char *ap, register u_int length, return; } + TCHECK2(*ap, sizeof(short)); pktlen = EXTRACT_LE_16BITS(ap); + if (pktlen < sizeof(struct shorthdr)) { + (void)printf("[|decnet]"); + return; + } + if (pktlen > length) { + (void)printf("[|decnet]"); + return; + } + length = pktlen; - rhlen = min(length, caplen); - rhlen = min(rhlen, sizeof(*rhp)); - memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen); - + rhp = (const union routehdr *)&(ap[sizeof(short)]); + TCHECK(rhp->rh_short.sh_flags); mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); if (mflags & RMF_PAD) { @@ -102,49 +99,57 @@ decnet_print(register const u_char *ap, register u_int length, u_int padlen = mflags & RMF_PADMASK; if (vflag) (void) printf("[pad:%d] ", padlen); + if (length < padlen + 2) { + (void)printf("[|decnet]"); + return; + } + TCHECK2(ap[sizeof(short)], padlen); ap += padlen; length -= padlen; caplen -= padlen; - rhlen = min(length, caplen); - rhlen = min(rhlen, sizeof(*rhp)); - memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen); + rhp = (const union routehdr *)&(ap[sizeof(short)]); mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); } if (mflags & RMF_FVER) { (void) printf("future-version-decnet"); - default_print(ap, length); + default_print(ap, min(length, caplen)); return; } /* is it a control message? */ if (mflags & RMF_CTLMSG) { - print_decnet_ctlmsg(rhp, min(length, caplen)); + if (!print_decnet_ctlmsg(rhp, length, caplen)) + goto trunc; return; } switch (mflags & RMF_MASK) { case RMF_LONG: + if (length < sizeof(struct longhdr)) { + (void)printf("[|decnet]"); + return; + } + TCHECK(rhp->rh_long); dst = EXTRACT_LE_16BITS(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr); src = EXTRACT_LE_16BITS(rhp->rh_long.lg_src.dne_remote.dne_nodeaddr); hops = EXTRACT_LE_8BITS(rhp->rh_long.lg_visits); nspp = &(ap[sizeof(short) + sizeof(struct longhdr)]); - nsplen = min((length - sizeof(struct longhdr)), - (caplen - sizeof(struct longhdr))); + nsplen = length - sizeof(struct longhdr); break; case RMF_SHORT: + TCHECK(rhp->rh_short); dst = EXTRACT_LE_16BITS(rhp->rh_short.sh_dst); src = EXTRACT_LE_16BITS(rhp->rh_short.sh_src); hops = (EXTRACT_LE_8BITS(rhp->rh_short.sh_visits) & VIS_MASK)+1; nspp = &(ap[sizeof(short) + sizeof(struct shorthdr)]); - nsplen = min((length - sizeof(struct shorthdr)), - (caplen - sizeof(struct shorthdr))); + nsplen = length - sizeof(struct shorthdr); break; default: (void) printf("unknown message flags under mask"); - default_print((u_char *)ap, length); + default_print((u_char *)ap, min(length, caplen)); return; } @@ -160,11 +165,18 @@ decnet_print(register const u_char *ap, register u_int length, (void)printf("%d hops ", hops); } - print_nsp(nspp, nsplen); + if (!print_nsp(nspp, nsplen)) + goto trunc; + return; + +trunc: + (void)printf("[|decnet]"); + return; } -static void -print_decnet_ctlmsg(register const union routehdr *rhp, u_int length) +static int +print_decnet_ctlmsg(register const union routehdr *rhp, u_int length, + u_int caplen) { int mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); register union controlmsg *cmp = (union controlmsg *)rhp; @@ -172,10 +184,14 @@ print_decnet_ctlmsg(register const union routehdr *rhp, u_int length) etheraddr srcea, rtea; int priority; char *rhpx = (char *)rhp; + int ret; switch (mflags & RMF_CTLMASK) { case RMF_INIT: (void)printf("init "); + if (length < sizeof(struct initmsg)) + goto trunc; + TCHECK(cmp->cm_init); src = EXTRACT_LE_16BITS(cmp->cm_init.in_src); info = EXTRACT_LE_8BITS(cmp->cm_init.in_info); blksize = EXTRACT_LE_16BITS(cmp->cm_init.in_blksize); @@ -188,35 +204,53 @@ print_decnet_ctlmsg(register const union routehdr *rhp, u_int length) "src %sblksize %d vers %d eco %d ueco %d hello %d", dnaddr_string(src), blksize, vers, eco, ueco, hello); + ret = 1; break; case RMF_VER: (void)printf("verification "); + if (length < sizeof(struct verifmsg)) + goto trunc; + TCHECK(cmp->cm_ver); src = EXTRACT_LE_16BITS(cmp->cm_ver.ve_src); other = EXTRACT_LE_8BITS(cmp->cm_ver.ve_fcnval); (void)printf("src %s fcnval %o", dnaddr_string(src), other); + ret = 1; break; case RMF_TEST: (void)printf("test "); + if (length < sizeof(struct testmsg)) + goto trunc; + TCHECK(cmp->cm_test); src = EXTRACT_LE_16BITS(cmp->cm_test.te_src); other = EXTRACT_LE_8BITS(cmp->cm_test.te_data); (void)printf("src %s data %o", dnaddr_string(src), other); + ret = 1; break; case RMF_L1ROUT: (void)printf("lev-1-routing "); + if (length < sizeof(struct l1rout)) + goto trunc; + TCHECK(cmp->cm_l1rou); src = EXTRACT_LE_16BITS(cmp->cm_l1rou.r1_src); (void)printf("src %s ", dnaddr_string(src)); - print_l1_routes(&(rhpx[sizeof(struct l1rout)]), + ret = print_l1_routes(&(rhpx[sizeof(struct l1rout)]), length - sizeof(struct l1rout)); break; case RMF_L2ROUT: (void)printf("lev-2-routing "); + if (length < sizeof(struct l2rout)) + goto trunc; + TCHECK(cmp->cm_l2rout); src = EXTRACT_LE_16BITS(cmp->cm_l2rout.r2_src); (void)printf("src %s ", dnaddr_string(src)); - print_l2_routes(&(rhpx[sizeof(struct l2rout)]), + ret = print_l2_routes(&(rhpx[sizeof(struct l2rout)]), length - sizeof(struct l2rout)); break; case RMF_RHELLO: (void)printf("router-hello "); + if (length < sizeof(struct rhellomsg)) + goto trunc; + TCHECK(cmp->cm_rhello); vers = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_vers); eco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_eco); ueco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_ueco); @@ -232,11 +266,14 @@ print_decnet_ctlmsg(register const union routehdr *rhp, u_int length) "vers %d eco %d ueco %d src %s blksize %d pri %d hello %d", vers, eco, ueco, dnaddr_string(src), blksize, priority, hello); - print_elist(&(rhpx[sizeof(struct rhellomsg)]), + ret = print_elist(&(rhpx[sizeof(struct rhellomsg)]), length - sizeof(struct rhellomsg)); break; case RMF_EHELLO: (void)printf("endnode-hello "); + if (length < sizeof(struct ehellomsg)) + goto trunc; + TCHECK(cmp->cm_ehello); vers = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_vers); eco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_eco); ueco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_ueco); @@ -256,13 +293,19 @@ print_decnet_ctlmsg(register const union routehdr *rhp, u_int length) "vers %d eco %d ueco %d src %s blksize %d rtr %s hello %d data %o", vers, eco, ueco, dnaddr_string(src), blksize, dnaddr_string(dst), hello, other); + ret = 1; break; default: (void)printf("unknown control message"); - default_print((u_char *)rhp, length); + default_print((u_char *)rhp, min(length, caplen)); + ret = 1; break; } + return (ret); + +trunc: + return (0); } static void @@ -281,7 +324,7 @@ print_t_info(int info) (void)printf("blo "); } -static void +static int print_l1_routes(const char *rp, u_int len) { int count; @@ -290,9 +333,10 @@ print_l1_routes(const char *rp, u_int len) /* The last short is a checksum */ while (len > (3 * sizeof(short))) { + TCHECK2(*rp, 3 * sizeof(short)); count = EXTRACT_LE_16BITS(rp); if (count > 1024) - return; /* seems to be bogus from here on */ + return (1); /* seems to be bogus from here on */ rp += sizeof(short); len -= sizeof(short); id = EXTRACT_LE_16BITS(rp); @@ -304,9 +348,13 @@ print_l1_routes(const char *rp, u_int len) (void)printf("{ids %d-%d cost %d hops %d} ", id, id + count, RI_COST(info), RI_HOPS(info)); } + return (1); + +trunc: + return (0); } -static void +static int print_l2_routes(const char *rp, u_int len) { int count; @@ -315,9 +363,10 @@ print_l2_routes(const char *rp, u_int len) /* The last short is a checksum */ while (len > (3 * sizeof(short))) { + TCHECK2(*rp, 3 * sizeof(short)); count = EXTRACT_LE_16BITS(rp); if (count > 1024) - return; /* seems to be bogus from here on */ + return (1); /* seems to be bogus from here on */ rp += sizeof(short); len -= sizeof(short); area = EXTRACT_LE_16BITS(rp); @@ -329,6 +378,10 @@ print_l2_routes(const char *rp, u_int len) (void)printf("{areas %d-%d cost %d hops %d} ", area, area + count, RI_COST(info), RI_HOPS(info)); } + return (1); + +trunc: + return (0); } static void @@ -349,18 +402,22 @@ print_i_info(int info) (void)printf("blo "); } -static void -print_elist(const char *elp, u_int len) +static int +print_elist(const char *elp _U_, u_int len _U_) { /* Not enough examples available for me to debug this */ + return (1); } -static void +static int print_nsp(const u_char *nspp, u_int nsplen) { const struct nsphdr *nsphp = (struct nsphdr *)nspp; int dst, src, flags; + if (nsplen < sizeof(struct nsphdr)) + goto trunc; + TCHECK(*nsphp); flags = EXTRACT_LE_8BITS(nsphp->nh_flags); dst = EXTRACT_LE_16BITS(nsphp->nh_dst); src = EXTRACT_LE_16BITS(nsphp->nh_src); @@ -381,27 +438,39 @@ print_nsp(const u_char *nspp, u_int nsplen) #endif u_int data_off = sizeof(struct minseghdr); + if (nsplen < data_off) + goto trunc; + TCHECK(shp->sh_seq[0]); ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); if (ack & SGQ_ACK) { /* acknum field */ if ((ack & SGQ_NAK) == SGQ_NAK) (void)printf("nak %d ", ack & SGQ_MASK); else (void)printf("ack %d ", ack & SGQ_MASK); - ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); data_off += sizeof(short); + if (nsplen < data_off) + goto trunc; + TCHECK(shp->sh_seq[1]); + ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); if (ack & SGQ_OACK) { /* ackoth field */ if ((ack & SGQ_ONAK) == SGQ_ONAK) (void)printf("onak %d ", ack & SGQ_MASK); else (void)printf("oack %d ", ack & SGQ_MASK); - ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); data_off += sizeof(short); + if (nsplen < data_off) + goto trunc; + TCHECK(shp->sh_seq[2]); + ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); } } (void)printf("seg %d ", ack & SGQ_MASK); #ifdef PRINT_NSPDATA - dp = &(nspp[data_off]); - pdata(dp, 10); + if (nsplen > data_off) { + dp = &(nspp[data_off]); + TCHECK2(*dp, nsplen - data_off); + pdata(dp, nsplen - data_off); + } #endif } break; @@ -415,27 +484,39 @@ print_nsp(const u_char *nspp, u_int nsplen) #endif u_int data_off = sizeof(struct minseghdr); + if (nsplen < data_off) + goto trunc; + TCHECK(shp->sh_seq[0]); ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); if (ack & SGQ_ACK) { /* acknum field */ if ((ack & SGQ_NAK) == SGQ_NAK) (void)printf("nak %d ", ack & SGQ_MASK); else (void)printf("ack %d ", ack & SGQ_MASK); - ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); data_off += sizeof(short); + if (nsplen < data_off) + goto trunc; + TCHECK(shp->sh_seq[1]); + ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); if (ack & SGQ_OACK) { /* ackdat field */ if ((ack & SGQ_ONAK) == SGQ_ONAK) (void)printf("nakdat %d ", ack & SGQ_MASK); else (void)printf("ackdat %d ", ack & SGQ_MASK); - ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); data_off += sizeof(short); + if (nsplen < data_off) + goto trunc; + TCHECK(shp->sh_seq[2]); + ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); } } (void)printf("seg %d ", ack & SGQ_MASK); #ifdef PRINT_NSPDATA - dp = &(nspp[data_off]); - pdata(dp, 10); + if (nsplen > data_off) { + dp = &(nspp[data_off]); + TCHECK2(*dp, nsplen - data_off); + pdata(dp, nsplen - data_off); + } #endif } break; @@ -448,22 +529,28 @@ print_nsp(const u_char *nspp, u_int nsplen) int ack; int lsflags, fcval; + if (nsplen < sizeof(struct seghdr) + sizeof(struct lsmsg)) + goto trunc; + TCHECK(shp->sh_seq[0]); ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); if (ack & SGQ_ACK) { /* acknum field */ if ((ack & SGQ_NAK) == SGQ_NAK) (void)printf("nak %d ", ack & SGQ_MASK); else (void)printf("ack %d ", ack & SGQ_MASK); + TCHECK(shp->sh_seq[1]); ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); if (ack & SGQ_OACK) { /* ackdat field */ if ((ack & SGQ_ONAK) == SGQ_ONAK) (void)printf("nakdat %d ", ack & SGQ_MASK); else (void)printf("ackdat %d ", ack & SGQ_MASK); + TCHECK(shp->sh_seq[2]); ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); } } (void)printf("seg %d ", ack & SGQ_MASK); + TCHECK(*lsmp); lsflags = EXTRACT_LE_8BITS(lsmp->ls_lsflags); fcval = EXTRACT_LE_8BITS(lsmp->ls_fcval); switch (lsflags & LSI_MASK) { @@ -505,6 +592,9 @@ print_nsp(const u_char *nspp, u_int nsplen) struct ackmsg *amp = (struct ackmsg *)nspp; int ack; + if (nsplen < sizeof(struct ackmsg)) + goto trunc; + TCHECK(*amp); ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]); if (ack & SGQ_ACK) { /* acknum field */ if ((ack & SGQ_NAK) == SGQ_NAK) @@ -527,12 +617,16 @@ print_nsp(const u_char *nspp, u_int nsplen) struct ackmsg *amp = (struct ackmsg *)nspp; int ack; + if (nsplen < sizeof(struct ackmsg)) + goto trunc; + TCHECK(*amp); ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]); if (ack & SGQ_ACK) { /* acknum field */ if ((ack & SGQ_NAK) == SGQ_NAK) (void)printf("nak %d ", ack & SGQ_MASK); else (void)printf("ack %d ", ack & SGQ_MASK); + TCHECK(amp->ak_acknum[1]); ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]); if (ack & SGQ_OACK) { /* ackdat field */ if ((ack & SGQ_ONAK) == SGQ_ONAK) @@ -567,6 +661,9 @@ print_nsp(const u_char *nspp, u_int nsplen) u_char *dp; #endif + if (nsplen < sizeof(struct cimsg)) + goto trunc; + TCHECK(*cimp); services = EXTRACT_LE_8BITS(cimp->ci_services); info = EXTRACT_LE_8BITS(cimp->ci_info); segsize = EXTRACT_LE_16BITS(cimp->ci_segsize); @@ -600,8 +697,11 @@ print_nsp(const u_char *nspp, u_int nsplen) } (void)printf("segsize %d ", segsize); #ifdef PRINT_NSPDATA - dp = &(nspp[sizeof(struct cimsg)]); - pdata(dp, nsplen - sizeof(struct cimsg)); + if (nsplen > sizeof(struct cimsg)) { + dp = &(nspp[sizeof(struct cimsg)]); + TCHECK2(*dp, nsplen - sizeof(struct cimsg)); + pdata(dp, nsplen - sizeof(struct cimsg)); + } #endif } break; @@ -615,6 +715,9 @@ print_nsp(const u_char *nspp, u_int nsplen) u_char *dp; #endif + if (nsplen < sizeof(struct ccmsg)) + goto trunc; + TCHECK(*ccmp); services = EXTRACT_LE_8BITS(ccmp->cc_services); info = EXTRACT_LE_8BITS(ccmp->cc_info); segsize = EXTRACT_LE_16BITS(ccmp->cc_segsize); @@ -651,8 +754,10 @@ print_nsp(const u_char *nspp, u_int nsplen) if (optlen) { (void)printf("optlen %d ", optlen); #ifdef PRINT_NSPDATA - optlen = min(optlen, nsplen - sizeof(struct ccmsg)); + if (optlen > nsplen - sizeof(struct ccmsg)) + goto trunc; dp = &(nspp[sizeof(struct ccmsg)]); + TCHECK2(*dp, optlen); pdata(dp, optlen); #endif } @@ -668,6 +773,9 @@ print_nsp(const u_char *nspp, u_int nsplen) u_char *dp; #endif + if (nsplen < sizeof(struct dimsg)) + goto trunc; + TCHECK(*dimp); reason = EXTRACT_LE_16BITS(dimp->di_reason); optlen = EXTRACT_LE_8BITS(dimp->di_optlen); @@ -675,8 +783,10 @@ print_nsp(const u_char *nspp, u_int nsplen) if (optlen) { (void)printf("optlen %d ", optlen); #ifdef PRINT_NSPDATA - optlen = min(optlen, nsplen - sizeof(struct dimsg)); + if (optlen > nsplen - sizeof(struct dimsg)) + goto trunc; dp = &(nspp[sizeof(struct dimsg)]); + TCHECK2(*dp, optlen); pdata(dp, optlen); #endif } @@ -688,6 +798,7 @@ print_nsp(const u_char *nspp, u_int nsplen) struct dcmsg *dcmp = (struct dcmsg *)nspp; int reason; + TCHECK(*dcmp); reason = EXTRACT_LE_16BITS(dcmp->dc_reason); print_reason(reason); @@ -702,6 +813,10 @@ print_nsp(const u_char *nspp, u_int nsplen) (void)printf("reserved-type? %x %d > %d", flags, src, dst); break; } + return (1); + +trunc: + return (0); } static struct tok reason2str[] = { @@ -736,7 +851,7 @@ print_reason(register int reason) printf("%s ", tok2str(reason2str, "reason-%d", reason)); } -char * +const char * dnnum_string(u_short dnaddr) { char *str; @@ -751,15 +866,15 @@ dnnum_string(u_short dnaddr) return(str); } -char * +const char * dnname_string(u_short dnaddr) { -#ifdef HAVE_LIBDNET +#ifdef HAVE_DNET_HTOA struct dn_naddr dna; dna.a_len = sizeof(short); memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short)); - return (savestr(dnet_htoa(&dna))); + return (strdup(dnet_htoa(&dna))); #else return(dnnum_string(dnaddr)); /* punt */ #endif @@ -774,10 +889,7 @@ pdata(u_char *dp, u_int maxlen) while (x-- > 0) { c = *dp++; - if (isprint(c)) - putchar(c); - else - printf("\\%o", c & 0xFF); + safeputchar(c); } } #endif