aboutsummaryrefslogtreecommitdiff
path: root/contrib/tcpdump/print-decnet.c
diff options
context:
space:
mode:
authorSam Leffler <sam@FreeBSD.org>2005-07-11 03:54:22 +0000
committerSam Leffler <sam@FreeBSD.org>2005-07-11 03:54:22 +0000
commitf4d0c64a1ddc84cf60d453e0f1ea0a70bea248e3 (patch)
tree87e350d89f0c352cd41839a49086d78bf700350e /contrib/tcpdump/print-decnet.c
parentcc157742d16ed3507376178a603a01aaab58e0e6 (diff)
downloadsrc-f4d0c64a1ddc84cf60d453e0f1ea0a70bea248e3.tar.gz
src-f4d0c64a1ddc84cf60d453e0f1ea0a70bea248e3.zip
Notes
Diffstat (limited to 'contrib/tcpdump/print-decnet.c')
-rw-r--r--contrib/tcpdump/print-decnet.c223
1 files changed, 174 insertions, 49 deletions
diff --git a/contrib/tcpdump/print-decnet.c b/contrib/tcpdump/print-decnet.c
index 43fe71d53dfa..ae7ba5c4ea55 100644
--- a/contrib/tcpdump/print-decnet.c
+++ b/contrib/tcpdump/print-decnet.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-decnet.c,v 1.38 2003/11/16 09:36:17 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-decnet.c,v 1.38.2.1 2005/05/06 02:16:53 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -47,13 +47,13 @@ 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);
@@ -67,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)) {
@@ -79,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) {
@@ -92,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;
}
@@ -150,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;
@@ -162,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);
@@ -178,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);
@@ -222,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);
@@ -246,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
@@ -271,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;
@@ -280,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);
@@ -294,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;
@@ -305,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);
@@ -319,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
@@ -339,18 +402,22 @@ print_i_info(int info)
(void)printf("blo ");
}
-static void
+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
-print_nsp(const u_char *nspp, u_int nsplen _U_)
+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);
@@ -371,27 +438,39 @@ print_nsp(const u_char *nspp, u_int nsplen _U_)
#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;
@@ -405,27 +484,39 @@ print_nsp(const u_char *nspp, u_int nsplen _U_)
#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;
@@ -438,22 +529,28 @@ print_nsp(const u_char *nspp, u_int nsplen _U_)
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) {
@@ -495,6 +592,9 @@ print_nsp(const u_char *nspp, u_int nsplen _U_)
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)
@@ -517,12 +617,16 @@ print_nsp(const u_char *nspp, u_int nsplen _U_)
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)
@@ -557,6 +661,9 @@ print_nsp(const u_char *nspp, u_int nsplen _U_)
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);
@@ -590,8 +697,11 @@ print_nsp(const u_char *nspp, u_int nsplen _U_)
}
(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;
@@ -605,6 +715,9 @@ print_nsp(const u_char *nspp, u_int nsplen _U_)
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);
@@ -641,8 +754,10 @@ print_nsp(const u_char *nspp, u_int nsplen _U_)
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
}
@@ -658,6 +773,9 @@ print_nsp(const u_char *nspp, u_int nsplen _U_)
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);
@@ -665,8 +783,10 @@ print_nsp(const u_char *nspp, u_int nsplen _U_)
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
}
@@ -678,6 +798,7 @@ print_nsp(const u_char *nspp, u_int nsplen _U_)
struct dcmsg *dcmp = (struct dcmsg *)nspp;
int reason;
+ TCHECK(*dcmp);
reason = EXTRACT_LE_16BITS(dcmp->dc_reason);
print_reason(reason);
@@ -692,6 +813,10 @@ print_nsp(const u_char *nspp, u_int nsplen _U_)
(void)printf("reserved-type? %x %d > %d", flags, src, dst);
break;
}
+ return (1);
+
+trunc:
+ return (0);
}
static struct tok reason2str[] = {