From ab4e52b94aac6cb729a5a695aa612d5ebda2ec3a Mon Sep 17 00:00:00 2001
From: Guy Harris <guy@alum.mit.edu>
Date: Tue, 11 Nov 2014 17:24:12 -0800
Subject: [PATCH 3/3] Add initial bounds check, get rid of union aodv.

Fetch the type field without using a structure, and check to make sure
it's not past the end of the packet.

Pass to each dissection routine a pointer to the appropriate message
type structure, rather than a pointer to a union of all the message type
structures.
---
 print-aodv.c | 274 ++++++++++++++++++++++++++++-------------------------------
 1 file changed, 130 insertions(+), 144 deletions(-)

Index: tcpdump-3.9.8/print-aodv.c
===================================================================
--- tcpdump-3.9.8.orig/print-aodv.c	2004-03-24 01:30:19.000000000 +0100
+++ tcpdump-3.9.8/print-aodv.c	2014-12-11 18:56:56.209247674 +0100
@@ -82,7 +82,7 @@ aodv_extension(const struct aodv_ext *ep
 }
 
 static void
-aodv_rreq(const union aodv *ap, const u_char *dat, u_int length)
+aodv_rreq(const struct aodv_rreq *ap, const u_char *dat, u_int length)
 {
 	u_int i;
 
@@ -91,30 +91,30 @@ aodv_rreq(const union aodv *ap, const u_
 		return;
 	}
 	i = min(length, (u_int)(snapend - dat));
-	if (i < sizeof(ap->rreq)) {
+	if (i < sizeof(*ap)) {
 		printf(" [|rreq]");
 		return;
 	}
-	i -= sizeof(ap->rreq);
+	i -= sizeof(*ap);
 	printf(" rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
 	    "\tdst %s seq %lu src %s seq %lu", length,
-	    ap->rreq.rreq_type & RREQ_JOIN ? "[J]" : "",
-	    ap->rreq.rreq_type & RREQ_REPAIR ? "[R]" : "",
-	    ap->rreq.rreq_type & RREQ_GRAT ? "[G]" : "",
-	    ap->rreq.rreq_type & RREQ_DEST ? "[D]" : "",
-	    ap->rreq.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
-	    ap->rreq.rreq_hops,
-	    (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_id),
-	    ipaddr_string(&ap->rreq.rreq_da),
-	    (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_ds),
-	    ipaddr_string(&ap->rreq.rreq_oa),
-	    (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_os));
+	    ap->rreq_type & RREQ_JOIN ? "[J]" : "",
+	    ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
+	    ap->rreq_type & RREQ_GRAT ? "[G]" : "",
+	    ap->rreq_type & RREQ_DEST ? "[D]" : "",
+	    ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
+	    ap->rreq_hops,
+	    (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
+	    ipaddr_string(&ap->rreq_da),
+	    (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
+	    ipaddr_string(&ap->rreq_oa),
+	    (unsigned long)EXTRACT_32BITS(&ap->rreq_os));
 	if (i >= sizeof(struct aodv_ext))
-		aodv_extension((void *)(&ap->rreq + 1), i);
+		aodv_extension((void *)(ap + 1), i);
 }
 
 static void
-aodv_rrep(const union aodv *ap, const u_char *dat, u_int length)
+aodv_rrep(const struct aodv_rrep *ap, const u_char *dat, u_int length)
 {
 	u_int i;
 
@@ -123,27 +123,27 @@ aodv_rrep(const union aodv *ap, const u_
 		return;
 	}
 	i = min(length, (u_int)(snapend - dat));
-	if (i < sizeof(ap->rrep)) {
+	if (i < sizeof(*ap)) {
 		printf(" [|rrep]");
 		return;
 	}
-	i -= sizeof(ap->rrep);
+	i -= sizeof(*ap);
 	printf(" rrep %u %s%sprefix %u hops %u\n"
 	    "\tdst %s dseq %lu src %s %lu ms", length,
-	    ap->rrep.rrep_type & RREP_REPAIR ? "[R]" : "",
-	    ap->rrep.rrep_type & RREP_ACK ? "[A] " : " ",
-	    ap->rrep.rrep_ps & RREP_PREFIX_MASK,
-	    ap->rrep.rrep_hops,
-	    ipaddr_string(&ap->rrep.rrep_da),
-	    (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_ds),
-	    ipaddr_string(&ap->rrep.rrep_oa),
-	    (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_life));
+	    ap->rrep_type & RREP_REPAIR ? "[R]" : "",
+	    ap->rrep_type & RREP_ACK ? "[A] " : " ",
+	    ap->rrep_ps & RREP_PREFIX_MASK,
+	    ap->rrep_hops,
+	    ipaddr_string(&ap->rrep_da),
+	    (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
+	    ipaddr_string(&ap->rrep_oa),
+	    (unsigned long)EXTRACT_32BITS(&ap->rrep_life));
 	if (i >= sizeof(struct aodv_ext))
-		aodv_extension((void *)(&ap->rrep + 1), i);
+		aodv_extension((void *)(ap + 1), i);
 }
 
 static void
-aodv_rerr(const union aodv *ap, const u_char *dat, u_int length)
+aodv_rerr(const struct aodv_rerr *ap, const u_char *dat, u_int length)
 {
 	u_int i;
 	const struct rerr_unreach *dp = NULL;
@@ -159,14 +159,14 @@ aodv_rerr(const union aodv *ap, const u_
 		return;
 	}
 	i -= offsetof(struct aodv_rerr, r);
-	dp = &ap->rerr.r.dest[0];
-	n = ap->rerr.rerr_dc * sizeof(ap->rerr.r.dest[0]);
+	dp = &ap->r.dest[0];
+	n = ap->rerr_dc * sizeof(ap->r.dest[0]);
 	printf(" rerr %s [items %u] [%u]:",
-	    ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
-	    ap->rerr.rerr_dc, length);
-	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])) {
+	    ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
+	    ap->rerr_dc, length);
+	trunc = n - (i/sizeof(ap->r.dest[0]));
+	for (; i >= sizeof(ap->r.dest[0]);
+	    ++dp, i -= sizeof(ap->r.dest[0])) {
 		printf(" {%s}(%ld)", ipaddr_string(&dp->u_da),
 		    (unsigned long)EXTRACT_32BITS(&dp->u_ds));
 	}
@@ -176,9 +176,9 @@ aodv_rerr(const union aodv *ap, const u_
 
 static void
 #ifdef INET6
-aodv_v6_rreq(const union aodv *ap, const u_char *dat, u_int length)
+aodv_v6_rreq(const struct aodv_rreq6 *ap, const u_char *dat, u_int length)
 #else
-aodv_v6_rreq(const union aodv *ap _U_, const u_char *dat _U_, u_int length)
+aodv_v6_rreq(const struct aodv_rreq6 *ap _U_, const u_char *dat _U_, u_int length)
 #endif
 {
 #ifdef INET6
@@ -189,26 +189,26 @@ aodv_v6_rreq(const union aodv *ap _U_, c
 		return;
 	}
 	i = min(length, (u_int)(snapend - dat));
-	if (i < sizeof(ap->rreq6)) {
+	if (i < sizeof(*ap)) {
 		printf(" [|rreq6]");
 		return;
 	}
-	i -= sizeof(ap->rreq6);
+	i -= sizeof(*ap);
 	printf(" v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
 	    "\tdst %s seq %lu src %s seq %lu", length,
-	    ap->rreq6.rreq_type & RREQ_JOIN ? "[J]" : "",
-	    ap->rreq6.rreq_type & RREQ_REPAIR ? "[R]" : "",
-	    ap->rreq6.rreq_type & RREQ_GRAT ? "[G]" : "",
-	    ap->rreq6.rreq_type & RREQ_DEST ? "[D]" : "",
-	    ap->rreq6.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
-	    ap->rreq6.rreq_hops,
-	    (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_id),
-	    ip6addr_string(&ap->rreq6.rreq_da),
-	    (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_ds),
-	    ip6addr_string(&ap->rreq6.rreq_oa),
-	    (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_os));
+	    ap->rreq_type & RREQ_JOIN ? "[J]" : "",
+	    ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
+	    ap->rreq_type & RREQ_GRAT ? "[G]" : "",
+	    ap->rreq_type & RREQ_DEST ? "[D]" : "",
+	    ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
+	    ap->rreq_hops,
+	    (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
+	    ip6addr_string(&ap->rreq_da),
+	    (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
+	    ip6addr_string(&ap->rreq_oa),
+	    (unsigned long)EXTRACT_32BITS(&ap->rreq_os));
 	if (i >= sizeof(struct aodv_ext))
-		aodv_extension((void *)(&ap->rreq6 + 1), i);
+		aodv_extension((void *)(ap + 1), i);
 #else
 	printf(" v6 rreq %u", length);
 #endif
@@ -216,9 +216,9 @@ aodv_v6_rreq(const union aodv *ap _U_, c
 
 static void
 #ifdef INET6
-aodv_v6_rrep(const union aodv *ap, const u_char *dat, u_int length)
+aodv_v6_rrep(const struct aodv_rrep6 *ap, const u_char *dat, u_int length)
 #else
-aodv_v6_rrep(const union aodv *ap _U_, const u_char *dat _U_, u_int length)
+aodv_v6_rrep(const struct aodv_rrep6 *ap _U_, const u_char *dat _U_, u_int length)
 #endif
 {
 #ifdef INET6
@@ -229,23 +229,23 @@ aodv_v6_rrep(const union aodv *ap _U_, c
 		return;
 	}
 	i = min(length, (u_int)(snapend - dat));
-	if (i < sizeof(ap->rrep6)) {
+	if (i < sizeof(*ap)) {
 		printf(" [|rrep6]");
 		return;
 	}
-	i -= sizeof(ap->rrep6);
+	i -= sizeof(*ap);
 	printf(" rrep %u %s%sprefix %u hops %u\n"
 	   "\tdst %s dseq %lu src %s %lu ms", length,
-	    ap->rrep6.rrep_type & RREP_REPAIR ? "[R]" : "",
-	    ap->rrep6.rrep_type & RREP_ACK ? "[A] " : " ",
-	    ap->rrep6.rrep_ps & RREP_PREFIX_MASK,
-	    ap->rrep6.rrep_hops,
-	    ip6addr_string(&ap->rrep6.rrep_da),
-	    (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_ds),
-	    ip6addr_string(&ap->rrep6.rrep_oa),
-	    (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_life));
+	    ap->rrep_type & RREP_REPAIR ? "[R]" : "",
+	    ap->rrep_type & RREP_ACK ? "[A] " : " ",
+	    ap->rrep_ps & RREP_PREFIX_MASK,
+	    ap->rrep_hops,
+	    ip6addr_string(&ap->rrep_da),
+	    (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
+	    ip6addr_string(&ap->rrep_oa),
+	    (unsigned long)EXTRACT_32BITS(&ap->rrep_life));
 	if (i >= sizeof(struct aodv_ext))
-		aodv_extension((void *)(&ap->rrep6 + 1), i);
+		aodv_extension((void *)(ap + 1), i);
 #else
 	printf(" rrep %u", length);
 #endif
@@ -253,9 +253,9 @@ aodv_v6_rrep(const union aodv *ap _U_, c
 
 static void
 #ifdef INET6
-aodv_v6_rerr(const union aodv *ap, u_int length)
+aodv_v6_rerr(const struct aodv_rerr *ap, u_int length)
 #else
-aodv_v6_rerr(const union aodv *ap _U_, u_int length)
+aodv_v6_rerr(const struct aodv_rerr *ap _U_, u_int length)
 #endif
 {
 #ifdef INET6
@@ -263,12 +263,12 @@ aodv_v6_rerr(const union aodv *ap _U_, u
 	int i, j, n, trunc;
 
 	i = length - offsetof(struct aodv_rerr, r);
-	j = sizeof(ap->rerr.r.dest6[0]);
-	dp6 = &ap->rerr.r.dest6[0];
-	n = ap->rerr.rerr_dc * j;
+	j = sizeof(ap->r.dest6[0]);
+	dp6 = &ap->r.dest6[0];
+	n = ap->rerr_dc * j;
 	printf(" rerr %s [items %u] [%u]:",
-	    ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
-	    ap->rerr.rerr_dc, length);
+	    ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
+	    ap->rerr_dc, length);
 	trunc = n - (i/j);
 	for (; i -= j >= 0; ++dp6) {
 		printf(" {%s}(%ld)", ip6addr_string(&dp6->u_da),
@@ -283,10 +283,9 @@ aodv_v6_rerr(const union aodv *ap _U_, u
 
 static void
 #ifdef INET6
-aodv_v6_draft_01_rreq(const union aodv *ap, const u_char *dat, u_int length)
+aodv_v6_draft_01_rreq(const struct aodv_rreq6_draft_01 *ap, const u_char *dat, u_int length)
 #else
-aodv_v6_draft_01_rreq(const union aodv *ap _U_, const u_char *dat _U_,
-    u_int length)
+aodv_v6_draft_01_rreq(const struct aodv_rreq6_draft_01 *ap _U_, const u_char *dat _U_, u_int length)
 #endif
 {
 #ifdef INET6
@@ -297,26 +296,26 @@ aodv_v6_draft_01_rreq(const union aodv *
 		return;
 	}
 	i = min(length, (u_int)(snapend - dat));
-	if (i < sizeof(ap->rreq6_draft_01)) {
+	if (i < sizeof(*ap)) {
 		printf(" [|rreq6]");
 		return;
 	}
-	i -= sizeof(ap->rreq6_draft_01);
+	i -= sizeof(*ap);
 	printf(" rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
 	    "\tdst %s seq %lu src %s seq %lu", length,
-	    ap->rreq6_draft_01.rreq_type & RREQ_JOIN ? "[J]" : "",
-	    ap->rreq6_draft_01.rreq_type & RREQ_REPAIR ? "[R]" : "",
-	    ap->rreq6_draft_01.rreq_type & RREQ_GRAT ? "[G]" : "",
-	    ap->rreq6_draft_01.rreq_type & RREQ_DEST ? "[D]" : "",
-	    ap->rreq6_draft_01.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
-	    ap->rreq6_draft_01.rreq_hops,
-	    (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_id),
-	    ip6addr_string(&ap->rreq6_draft_01.rreq_da),
-	    (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_ds),
-	    ip6addr_string(&ap->rreq6_draft_01.rreq_oa),
-	    (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_os));
+	    ap->rreq_type & RREQ_JOIN ? "[J]" : "",
+	    ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
+	    ap->rreq_type & RREQ_GRAT ? "[G]" : "",
+	    ap->rreq_type & RREQ_DEST ? "[D]" : "",
+	    ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
+	    ap->rreq_hops,
+	    (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
+	    ip6addr_string(&ap->rreq_da),
+	    (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
+	    ip6addr_string(&ap->rreq_oa),
+	    (unsigned long)EXTRACT_32BITS(&ap->rreq_os));
 	if (i >= sizeof(struct aodv_ext))
-		aodv_extension((void *)(&ap->rreq6_draft_01 + 1), i);
+		aodv_extension((void *)(ap + 1), i);
 #else
 	printf(" rreq %u", length);
 #endif
@@ -324,9 +323,9 @@ aodv_v6_draft_01_rreq(const union aodv *
 
 static void
 #ifdef INET6
-aodv_v6_draft_01_rrep(const union aodv *ap, const u_char *dat, u_int length)
+aodv_v6_draft_01_rrep(const struct aodv_rrep6_draft_01 *ap, const u_char *dat, u_int length)
 #else
-aodv_v6_draft_01_rrep(const union aodv *ap _U_, const u_char *dat _U_,
+aodv_v6_draft_01_rrep(const struct aodv_rrep6_draft_01 *ap _U_, const u_char *dat _U_,
     u_int length)
 #endif
 {
@@ -338,23 +337,23 @@ aodv_v6_draft_01_rrep(const union aodv *
 		return;
 	}
 	i = min(length, (u_int)(snapend - dat));
-	if (i < sizeof(ap->rrep6_draft_01)) {
+	if (i < sizeof(*ap)) {
 		printf(" [|rrep6]");
 		return;
 	}
-	i -= sizeof(ap->rrep6_draft_01);
+	i -= sizeof(*ap);
 	printf(" rrep %u %s%sprefix %u hops %u\n"
 	   "\tdst %s dseq %lu src %s %lu ms", length,
-	    ap->rrep6_draft_01.rrep_type & RREP_REPAIR ? "[R]" : "",
-	    ap->rrep6_draft_01.rrep_type & RREP_ACK ? "[A] " : " ",
-	    ap->rrep6_draft_01.rrep_ps & RREP_PREFIX_MASK,
-	    ap->rrep6_draft_01.rrep_hops,
-	    ip6addr_string(&ap->rrep6_draft_01.rrep_da),
-	    (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_ds),
-	    ip6addr_string(&ap->rrep6_draft_01.rrep_oa),
-	    (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_life));
+	    ap->rrep_type & RREP_REPAIR ? "[R]" : "",
+	    ap->rrep_type & RREP_ACK ? "[A] " : " ",
+	    ap->rrep_ps & RREP_PREFIX_MASK,
+	    ap->rrep_hops,
+	    ip6addr_string(&ap->rrep_da),
+	    (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
+	    ip6addr_string(&ap->rrep_oa),
+	    (unsigned long)EXTRACT_32BITS(&ap->rrep_life));
 	if (i >= sizeof(struct aodv_ext))
-		aodv_extension((void *)(&ap->rrep6_draft_01 + 1), i);
+		aodv_extension((void *)(ap + 1), i);
 #else
 	printf(" rrep %u", length);
 #endif
@@ -362,9 +361,9 @@ aodv_v6_draft_01_rrep(const union aodv *
 
 static void
 #ifdef INET6
-aodv_v6_draft_01_rerr(const union aodv *ap, u_int length)
+aodv_v6_draft_01_rerr(const struct aodv_rerr *ap, u_int length)
 #else
-aodv_v6_draft_01_rerr(const union aodv *ap _U_, u_int length)
+aodv_v6_draft_01_rerr(const struct aodv_rerr *ap _U_, u_int length)
 #endif
 {
 #ifdef INET6
@@ -372,12 +371,12 @@ aodv_v6_draft_01_rerr(const union aodv *
 	int i, j, n, trunc;
 
 	i = length - offsetof(struct aodv_rerr, r);
-	j = sizeof(ap->rerr.r.dest6_draft_01[0]);
-	dp6 = &ap->rerr.r.dest6_draft_01[0];
-	n = ap->rerr.rerr_dc * j;
+	j = sizeof(ap->r.dest6_draft_01[0]);
+	dp6 = &ap->r.dest6_draft_01[0];
+	n = ap->rerr_dc * j;
 	printf(" rerr %s [items %u] [%u]:",
-	    ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
-	    ap->rerr.rerr_dc, length);
+	    ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
+	    ap->rerr_dc, length);
 	trunc = n - (i/j);
 	for (; i -= j >= 0; ++dp6) {
 		printf(" {%s}(%ld)", ip6addr_string(&dp6->u_da),
@@ -391,42 +390,40 @@ aodv_v6_draft_01_rerr(const union aodv *
 }
 
 void
-aodv_print(const u_char *dat, u_int length, int is_ip6)
+aodv_print(netdissect_options *ndo,
+           const u_char *dat, u_int length, int is_ip6)
 {
-	const union aodv *ap;
+	uint8_t msg_type;
 
-	ap = (union aodv *)dat;
-	if (snapend < dat) {
-		printf(" [|aodv]");
-		return;
-	}
-	if (min(length, (u_int)(snapend - dat)) < sizeof(ap->rrep_ack)) {
-		printf(" [|aodv]");
-		return;
-	}
+	/*
+	 * The message type is the first byte; make sure we have it
+	 * and then fetch it.
+	 */
+	ND_TCHECK(*dat);
+	msg_type = *dat;
 	printf(" aodv");
 
-	switch (ap->rerr.rerr_type) {
+	switch (msg_type) {
 
 	case AODV_RREQ:
 		if (is_ip6)
-			aodv_v6_rreq(ap, dat, length);
+			aodv_v6_rreq((const struct aodv_rreq6 *)dat, dat, length);
 		else
-			aodv_rreq(ap, dat, length);
+			aodv_rreq((const struct aodv_rreq *)dat, dat, length);
 		break;
 
 	case AODV_RREP:
 		if (is_ip6)
-			aodv_v6_rrep(ap, dat, length);
+			aodv_v6_rrep((const struct aodv_rrep6 *)dat, dat, length);
 		else
-			aodv_rrep(ap, dat, length);
+			aodv_rrep((const struct aodv_rrep *)dat, dat, length);
 		break;
 
 	case AODV_RERR:
 		if (is_ip6)
-			aodv_v6_rerr(ap, length);
+			aodv_v6_rerr((const struct aodv_rerr *)dat, length);
 		else
-			aodv_rerr(ap, dat, length);
+			aodv_rerr((const struct aodv_rerr *)dat, dat, length);
 		break;
 
 	case AODV_RREP_ACK:
@@ -434,15 +431,15 @@ aodv_print(const u_char *dat, u_int leng
 		break;
 
 	case AODV_V6_DRAFT_01_RREQ:
-		aodv_v6_draft_01_rreq(ap, dat, length);
+		aodv_v6_draft_01_rreq((const struct aodv_rreq6_draft_01 *)dat, dat, length);
 		break;
 
 	case AODV_V6_DRAFT_01_RREP:
-		aodv_v6_draft_01_rrep(ap, dat, length);
+		aodv_v6_draft_01_rrep((const struct aodv_rrep6_draft_01 *)dat, dat, length);
 		break;
 
 	case AODV_V6_DRAFT_01_RERR:
-		aodv_v6_draft_01_rerr(ap, length);
+		aodv_v6_draft_01_rerr((const struct aodv_rerr *)dat, length);
 		break;
 
 	case AODV_V6_DRAFT_01_RREP_ACK:
@@ -450,6 +447,9 @@ aodv_print(const u_char *dat, u_int leng
 		break;
 
 	default:
-		printf(" %u %u", ap->rreq.rreq_type, length);
+		printf(" type %u %u", msg_type, length);
 	}
+	return;
+trunc:
+	printf(" [|aodv]");
 }
Index: tcpdump-3.9.8/print-ip6.c
===================================================================
--- tcpdump-3.9.8.orig/print-ip6.c	2007-09-26 03:59:54.000000000 +0200
+++ tcpdump-3.9.8/print-ip6.c	2014-12-11 18:56:56.209247674 +0100
@@ -167,7 +167,7 @@ ip6_print(register const u_char *bp, reg
 			tcp_print(cp, len, (const u_char *)ip6, fragmented);
 			return;
 		case IPPROTO_UDP:
-			udp_print(cp, len, (const u_char *)ip6, fragmented);
+			udp_print(ndo, cp, len, (const u_char *)ip6, fragmented);
 			return;
 		case IPPROTO_ICMPV6:
 			icmp6_print(cp, len, (const u_char *)ip6, fragmented);
Index: tcpdump-3.9.8/print-udp.c
===================================================================
--- tcpdump-3.9.8.orig/print-udp.c	2014-12-11 18:56:56.201247573 +0100
+++ tcpdump-3.9.8/print-udp.c	2014-12-11 18:56:56.209247674 +0100
@@ -522,7 +522,7 @@ udp_print(netdissect_options *ndo, regis
 
 		case PT_AODV:
 			udpipaddr_print(ip, sport, dport);
-			aodv_print((const u_char *)(up + 1), length,
+			aodv_print(ndo, (const u_char *)(up + 1), length,
 #ifdef INET6
 			    ip6 != NULL);
 #else
@@ -609,7 +609,7 @@ udp_print(netdissect_options *ndo, regis
 		else if (ISPORT(RIP_PORT))
 			rip_print((const u_char *)(up + 1), length);
 		else if (ISPORT(AODV_PORT))
-			aodv_print((const u_char *)(up + 1), length,
+			aodv_print(ndo, (const u_char *)(up + 1), length,
 #ifdef INET6
 			    ip6 != NULL);
 #else
Index: tcpdump-3.9.8/print-ip.c
===================================================================
--- tcpdump-3.9.8.orig/print-ip.c	2007-09-26 03:59:54.000000000 +0200
+++ tcpdump-3.9.8/print-ip.c	2014-12-11 18:56:56.209247674 +0100
@@ -431,7 +431,7 @@ again:
 		
 	case IPPROTO_UDP:
 		/* pass on the MF bit plus the offset to detect fragments */
-		udp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
+		udp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip,
 			  ipds->off & (IP_MF|IP_OFFMASK));
 		break;
 		
Index: tcpdump-3.9.8/interface.h
===================================================================
--- tcpdump-3.9.8.orig/interface.h	2014-12-11 18:56:56.201247573 +0100
+++ tcpdump-3.9.8/interface.h	2014-12-11 19:00:34.699992054 +0100
@@ -182,7 +182,7 @@ extern int llc_print(const u_char *, u_i
 	const u_char *, u_short *);
 extern int snap_print(const u_char *, u_int, u_int, u_short *, u_int);
 extern void aarp_print(const u_char *, u_int);
-extern void aodv_print(const u_char *, u_int, int);
+extern void aodv_print(netdissect_options *, const u_char *, u_int, int);
 extern void atalk_print(const u_char *, u_int);
 extern void atm_print(u_int, u_int, u_int, const u_char *, u_int, u_int);
 extern u_int atm_if_print(const struct pcap_pkthdr *, const u_char *);
@@ -282,7 +282,7 @@ extern u_int symantec_if_print(const str
 extern void tcp_print(const u_char *, u_int, const u_char *, int);
 extern void tftp_print(const u_char *, u_int);
 extern void timed_print(const u_char *);
-extern void udp_print(const u_char *, u_int, const u_char *, int);
+extern void udp_print(netdissect_options *, const u_char *, u_int, const u_char *, int);
 extern void wb_print(const void *, u_int);
 extern int ah_print(register const u_char *);
 extern int ipcomp_print(register const u_char *, int *);
