diff options
author | guy <guy> | 2004-03-24 00:30:19 +0000 |
---|---|---|
committer | guy <guy> | 2004-03-24 00:30:19 +0000 |
commit | b340e34b6ac70fe143bf375c91446273ed3e6552 (patch) | |
tree | 7318e590fa335b1b95439f2400306219aeda69ae /print-aodv.c | |
parent | 33ede7fbeaf45b5a26884f8ce4c4cb660b85adc1 (diff) | |
download | tcpdump-b340e34b6ac70fe143bf375c91446273ed3e6552.tar.gz |
Add bounds checking.
Diffstat (limited to 'print-aodv.c')
-rw-r--r-- | print-aodv.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/print-aodv.c b/print-aodv.c index b1539a9a..c5f66223 100644 --- a/print-aodv.c +++ b/print-aodv.c @@ -32,7 +32,7 @@ #ifndef lint static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/tcpdump/print-aodv.c,v 1.10 2003-11-16 09:36:12 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/print-aodv.c,v 1.11 2004-03-24 00:30:19 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -143,20 +143,30 @@ aodv_rrep(const union aodv *ap, const u_char *dat, u_int length) } static void -aodv_rerr(const union aodv *ap, u_int length) +aodv_rerr(const union aodv *ap, const u_char *dat, u_int length) { + u_int i; const struct rerr_unreach *dp = NULL; - int i, j, n, trunc; + int n, trunc; - i = length - offsetof(struct aodv_rerr, r); - j = sizeof(ap->rerr.r.dest[0]); + if (snapend < dat) { + printf(" [|aodv]"); + return; + } + i = min(length, (u_int)(snapend - dat)); + if (i < offsetof(struct aodv_rerr, r)) { + printf(" [|rerr]"); + return; + } + i -= offsetof(struct aodv_rerr, r); dp = &ap->rerr.r.dest[0]; - n = ap->rerr.rerr_dc * j; + n = ap->rerr.rerr_dc * sizeof(ap->rerr.r.dest[0]); printf(" rerr %s [items %u] [%u]:", ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "", ap->rerr.rerr_dc, length); - trunc = n - (i/j); - for (; i -= j >= 0; ++dp) { + trunc = n - (i/sizeof(ap->rerr.r.dest[0])); + for (; i >= sizeof(ap->rerr.r.dest[0]); + ++dp, i -= sizeof(ap->rerr.r.dest[0])) { printf(" {%s}(%ld)", ipaddr_string(&dp->u_da), (unsigned long)EXTRACT_32BITS(&dp->u_ds)); } @@ -416,7 +426,7 @@ aodv_print(const u_char *dat, u_int length, int is_ip6) if (is_ip6) aodv_v6_rerr(ap, length); else - aodv_rerr(ap, length); + aodv_rerr(ap, dat, length); break; case AODV_RREP_ACK: |