xref: /freebsd/contrib/tcpdump/print-aodv.c (revision 3340d77368116708ab5b5b95acf6c9c710528300)
15b0fe478SBruce M Simpson /*
25b0fe478SBruce M Simpson  * Copyright (c) 2003 Bruce M. Simpson <bms@spc.org>
35b0fe478SBruce M Simpson  * All rights reserved.
45b0fe478SBruce M Simpson  *
55b0fe478SBruce M Simpson  * Redistribution and use in source and binary forms, with or without
65b0fe478SBruce M Simpson  * modification, are permitted provided that the following conditions
75b0fe478SBruce M Simpson  * are met:
85b0fe478SBruce M Simpson  * 1. Redistributions of source code must retain the above copyright
95b0fe478SBruce M Simpson  *    notice, this list of conditions and the following disclaimer.
105b0fe478SBruce M Simpson  * 2. Redistributions in binary form must reproduce the above copyright
115b0fe478SBruce M Simpson  *    notice, this list of conditions and the following disclaimer in the
125b0fe478SBruce M Simpson  *    documentation and/or other materials provided with the distribution.
135b0fe478SBruce M Simpson  * 3. All advertising materials mentioning features or use of this software
145b0fe478SBruce M Simpson  *    must display the following acknowledgement:
155b0fe478SBruce M Simpson  *        This product includes software developed by Bruce M. Simpson.
165b0fe478SBruce M Simpson  * 4. Neither the name of Bruce M. Simpson nor the names of co-
175b0fe478SBruce M Simpson  *    contributors may be used to endorse or promote products derived
185b0fe478SBruce M Simpson  *    from this software without specific prior written permission.
195b0fe478SBruce M Simpson  *
205b0fe478SBruce M Simpson  * THIS SOFTWARE IS PROVIDED BY Bruce M. Simpson AND CONTRIBUTORS
215b0fe478SBruce M Simpson  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
225b0fe478SBruce M Simpson  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
235b0fe478SBruce M Simpson  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL Bruce M. Simpson OR CONTRIBUTORS
245b0fe478SBruce M Simpson  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
255b0fe478SBruce M Simpson  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
265b0fe478SBruce M Simpson  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
275b0fe478SBruce M Simpson  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
285b0fe478SBruce M Simpson  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
295b0fe478SBruce M Simpson  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
305b0fe478SBruce M Simpson  * POSSIBILITY OF SUCH DAMAGE.
315b0fe478SBruce M Simpson  */
325b0fe478SBruce M Simpson 
33*3340d773SGleb Smirnoff /* \summary: Ad hoc On-Demand Distance Vector (AODV) Routing printer */
34*3340d773SGleb Smirnoff 
355b0fe478SBruce M Simpson #ifdef HAVE_CONFIG_H
365b0fe478SBruce M Simpson #include "config.h"
375b0fe478SBruce M Simpson #endif
385b0fe478SBruce M Simpson 
39*3340d773SGleb Smirnoff #include <netdissect-stdinc.h>
405b0fe478SBruce M Simpson 
41*3340d773SGleb Smirnoff #include "netdissect.h"
425b0fe478SBruce M Simpson #include "addrtoname.h"
43*3340d773SGleb Smirnoff #include "extract.h"
445b0fe478SBruce M Simpson 
453c602fabSXin LI 
463c602fabSXin LI struct aodv_rreq {
473c602fabSXin LI 	uint8_t		rreq_type;	/* AODV message type (1) */
483c602fabSXin LI 	uint8_t		rreq_flags;	/* various flags */
493c602fabSXin LI 	uint8_t		rreq_zero0;	/* reserved, set to zero */
503c602fabSXin LI 	uint8_t		rreq_hops;	/* number of hops from originator */
513c602fabSXin LI 	uint32_t	rreq_id;	/* request ID */
523c602fabSXin LI 	uint32_t	rreq_da;	/* destination IPv4 address */
533c602fabSXin LI 	uint32_t	rreq_ds;	/* destination sequence number */
543c602fabSXin LI 	uint32_t	rreq_oa;	/* originator IPv4 address */
553c602fabSXin LI 	uint32_t	rreq_os;	/* originator sequence number */
563c602fabSXin LI };
573c602fabSXin LI struct aodv_rreq6 {
583c602fabSXin LI 	uint8_t		rreq_type;	/* AODV message type (1) */
593c602fabSXin LI 	uint8_t		rreq_flags;	/* various flags */
603c602fabSXin LI 	uint8_t		rreq_zero0;	/* reserved, set to zero */
613c602fabSXin LI 	uint8_t		rreq_hops;	/* number of hops from originator */
623c602fabSXin LI 	uint32_t	rreq_id;	/* request ID */
633c602fabSXin LI 	struct in6_addr	rreq_da;	/* destination IPv6 address */
643c602fabSXin LI 	uint32_t	rreq_ds;	/* destination sequence number */
653c602fabSXin LI 	struct in6_addr	rreq_oa;	/* originator IPv6 address */
663c602fabSXin LI 	uint32_t	rreq_os;	/* originator sequence number */
673c602fabSXin LI };
683c602fabSXin LI struct aodv_rreq6_draft_01 {
693c602fabSXin LI 	uint8_t		rreq_type;	/* AODV message type (16) */
703c602fabSXin LI 	uint8_t		rreq_flags;	/* various flags */
713c602fabSXin LI 	uint8_t		rreq_zero0;	/* reserved, set to zero */
723c602fabSXin LI 	uint8_t		rreq_hops;	/* number of hops from originator */
733c602fabSXin LI 	uint32_t	rreq_id;	/* request ID */
743c602fabSXin LI 	uint32_t	rreq_ds;	/* destination sequence number */
753c602fabSXin LI 	uint32_t	rreq_os;	/* originator sequence number */
763c602fabSXin LI 	struct in6_addr	rreq_da;	/* destination IPv6 address */
773c602fabSXin LI 	struct in6_addr	rreq_oa;	/* originator IPv6 address */
783c602fabSXin LI };
793c602fabSXin LI 
803c602fabSXin LI #define	RREQ_JOIN	0x80		/* join (reserved for multicast */
813c602fabSXin LI #define	RREQ_REPAIR	0x40		/* repair (reserved for multicast */
823c602fabSXin LI #define	RREQ_GRAT	0x20		/* gratuitous RREP */
833c602fabSXin LI #define	RREQ_DEST	0x10		/* destination only */
843c602fabSXin LI #define	RREQ_UNKNOWN	0x08		/* unknown destination sequence num */
853c602fabSXin LI #define	RREQ_FLAGS_MASK	0xF8		/* mask for rreq_flags */
863c602fabSXin LI 
873c602fabSXin LI struct aodv_rrep {
883c602fabSXin LI 	uint8_t		rrep_type;	/* AODV message type (2) */
893c602fabSXin LI 	uint8_t		rrep_flags;	/* various flags */
903c602fabSXin LI 	uint8_t		rrep_ps;	/* prefix size */
913c602fabSXin LI 	uint8_t		rrep_hops;	/* number of hops from o to d */
923c602fabSXin LI 	uint32_t	rrep_da;	/* destination IPv4 address */
933c602fabSXin LI 	uint32_t	rrep_ds;	/* destination sequence number */
943c602fabSXin LI 	uint32_t	rrep_oa;	/* originator IPv4 address */
953c602fabSXin LI 	uint32_t	rrep_life;	/* lifetime of this route */
963c602fabSXin LI };
973c602fabSXin LI struct aodv_rrep6 {
983c602fabSXin LI 	uint8_t		rrep_type;	/* AODV message type (2) */
993c602fabSXin LI 	uint8_t		rrep_flags;	/* various flags */
1003c602fabSXin LI 	uint8_t		rrep_ps;	/* prefix size */
1013c602fabSXin LI 	uint8_t		rrep_hops;	/* number of hops from o to d */
1023c602fabSXin LI 	struct in6_addr	rrep_da;	/* destination IPv6 address */
1033c602fabSXin LI 	uint32_t	rrep_ds;	/* destination sequence number */
1043c602fabSXin LI 	struct in6_addr	rrep_oa;	/* originator IPv6 address */
1053c602fabSXin LI 	uint32_t	rrep_life;	/* lifetime of this route */
1063c602fabSXin LI };
1073c602fabSXin LI struct aodv_rrep6_draft_01 {
1083c602fabSXin LI 	uint8_t		rrep_type;	/* AODV message type (17) */
1093c602fabSXin LI 	uint8_t		rrep_flags;	/* various flags */
1103c602fabSXin LI 	uint8_t		rrep_ps;	/* prefix size */
1113c602fabSXin LI 	uint8_t		rrep_hops;	/* number of hops from o to d */
1123c602fabSXin LI 	uint32_t	rrep_ds;	/* destination sequence number */
1133c602fabSXin LI 	struct in6_addr	rrep_da;	/* destination IPv6 address */
1143c602fabSXin LI 	struct in6_addr	rrep_oa;	/* originator IPv6 address */
1153c602fabSXin LI 	uint32_t	rrep_life;	/* lifetime of this route */
1163c602fabSXin LI };
1173c602fabSXin LI 
1183c602fabSXin LI #define	RREP_REPAIR		0x80	/* repair (reserved for multicast */
1193c602fabSXin LI #define	RREP_ACK		0x40	/* acknowledgement required */
1203c602fabSXin LI #define	RREP_FLAGS_MASK		0xC0	/* mask for rrep_flags */
1213c602fabSXin LI #define	RREP_PREFIX_MASK	0x1F	/* mask for prefix size */
1223c602fabSXin LI 
1233c602fabSXin LI struct rerr_unreach {
1243c602fabSXin LI 	uint32_t	u_da;	/* IPv4 address */
1253c602fabSXin LI 	uint32_t	u_ds;	/* sequence number */
1263c602fabSXin LI };
1273c602fabSXin LI struct rerr_unreach6 {
1283c602fabSXin LI 	struct in6_addr	u_da;	/* IPv6 address */
1293c602fabSXin LI 	uint32_t	u_ds;	/* sequence number */
1303c602fabSXin LI };
1313c602fabSXin LI struct rerr_unreach6_draft_01 {
1323c602fabSXin LI 	struct in6_addr	u_da;	/* IPv6 address */
1333c602fabSXin LI 	uint32_t	u_ds;	/* sequence number */
1343c602fabSXin LI };
1353c602fabSXin LI 
1363c602fabSXin LI struct aodv_rerr {
1373c602fabSXin LI 	uint8_t		rerr_type;	/* AODV message type (3 or 18) */
1383c602fabSXin LI 	uint8_t		rerr_flags;	/* various flags */
1393c602fabSXin LI 	uint8_t		rerr_zero0;	/* reserved, set to zero */
1403c602fabSXin LI 	uint8_t		rerr_dc;	/* destination count */
1413c602fabSXin LI };
1423c602fabSXin LI 
1433c602fabSXin LI #define RERR_NODELETE		0x80	/* don't delete the link */
1443c602fabSXin LI #define RERR_FLAGS_MASK		0x80	/* mask for rerr_flags */
1453c602fabSXin LI 
1463c602fabSXin LI struct aodv_rrep_ack {
1473c602fabSXin LI 	uint8_t		ra_type;
1483c602fabSXin LI 	uint8_t		ra_zero0;
1493c602fabSXin LI };
1503c602fabSXin LI 
1513c602fabSXin LI #define	AODV_RREQ		1	/* route request */
1523c602fabSXin LI #define	AODV_RREP		2	/* route response */
1533c602fabSXin LI #define	AODV_RERR		3	/* error report */
1543c602fabSXin LI #define	AODV_RREP_ACK		4	/* route response acknowledgement */
1553c602fabSXin LI 
1563c602fabSXin LI #define AODV_V6_DRAFT_01_RREQ		16	/* IPv6 route request */
1573c602fabSXin LI #define AODV_V6_DRAFT_01_RREP		17	/* IPv6 route response */
1583c602fabSXin LI #define AODV_V6_DRAFT_01_RERR		18	/* IPv6 error report */
1593c602fabSXin LI #define AODV_V6_DRAFT_01_RREP_ACK	19	/* IPV6 route response acknowledgment */
1603c602fabSXin LI 
1613c602fabSXin LI struct aodv_ext {
1623c602fabSXin LI 	uint8_t		type;		/* extension type */
1633c602fabSXin LI 	uint8_t		length;		/* extension length */
1643c602fabSXin LI };
1653c602fabSXin LI 
1663c602fabSXin LI struct aodv_hello {
1673c602fabSXin LI 	struct	aodv_ext	eh;		/* extension header */
1683c602fabSXin LI 	uint8_t			interval[4];	/* expect my next hello in
1693c602fabSXin LI 						 * (n) ms
1703c602fabSXin LI 						 * NOTE: this is not aligned */
1713c602fabSXin LI };
1723c602fabSXin LI 
1733c602fabSXin LI #define	AODV_EXT_HELLO	1
1745b0fe478SBruce M Simpson 
1755b0fe478SBruce M Simpson static void
1763c602fabSXin LI aodv_extension(netdissect_options *ndo,
1773c602fabSXin LI                const struct aodv_ext *ep, u_int length)
1785b0fe478SBruce M Simpson {
1795b0fe478SBruce M Simpson 	const struct aodv_hello *ah;
1805b0fe478SBruce M Simpson 
1815b0fe478SBruce M Simpson 	switch (ep->type) {
1825b0fe478SBruce M Simpson 	case AODV_EXT_HELLO:
1838bdc5a62SPatrick Kelsey 		ah = (const struct aodv_hello *)(const void *)ep;
1848bdc5a62SPatrick Kelsey 		ND_TCHECK(*ah);
1858bdc5a62SPatrick Kelsey 		if (length < sizeof(struct aodv_hello))
1868bdc5a62SPatrick Kelsey 			goto trunc;
1873c602fabSXin LI 		ND_PRINT((ndo, "\n\text HELLO %ld ms",
1883c602fabSXin LI 		    (unsigned long)EXTRACT_32BITS(&ah->interval)));
1895b0fe478SBruce M Simpson 		break;
1905b0fe478SBruce M Simpson 
1915b0fe478SBruce M Simpson 	default:
1923c602fabSXin LI 		ND_PRINT((ndo, "\n\text %u %u", ep->type, ep->length));
1935b0fe478SBruce M Simpson 		break;
1945b0fe478SBruce M Simpson 	}
1958bdc5a62SPatrick Kelsey 	return;
1968bdc5a62SPatrick Kelsey 
1978bdc5a62SPatrick Kelsey trunc:
1988bdc5a62SPatrick Kelsey 	ND_PRINT((ndo, " [|hello]"));
1995b0fe478SBruce M Simpson }
2005b0fe478SBruce M Simpson 
2015b0fe478SBruce M Simpson static void
2028bdc5a62SPatrick Kelsey aodv_rreq(netdissect_options *ndo, const u_char *dat, u_int length)
2035b0fe478SBruce M Simpson {
2045b0fe478SBruce M Simpson 	u_int i;
2058bdc5a62SPatrick Kelsey 	const struct aodv_rreq *ap = (const struct aodv_rreq *)dat;
2065b0fe478SBruce M Simpson 
2078bdc5a62SPatrick Kelsey 	ND_TCHECK(*ap);
2088bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
2098bdc5a62SPatrick Kelsey 		goto trunc;
2103c602fabSXin LI 	ND_PRINT((ndo, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
2115b0fe478SBruce M Simpson 	    "\tdst %s seq %lu src %s seq %lu", length,
2128bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_JOIN ? "[J]" : "",
2138bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
2148bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_GRAT ? "[G]" : "",
2158bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_DEST ? "[D]" : "",
2168bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
2178bdc5a62SPatrick Kelsey 	    ap->rreq_hops,
2188bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
2198bdc5a62SPatrick Kelsey 	    ipaddr_string(ndo, &ap->rreq_da),
2208bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
2218bdc5a62SPatrick Kelsey 	    ipaddr_string(ndo, &ap->rreq_oa),
2228bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_os)));
2238bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
2245b0fe478SBruce M Simpson 	if (i >= sizeof(struct aodv_ext))
2258bdc5a62SPatrick Kelsey 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
2268bdc5a62SPatrick Kelsey 	return;
2278bdc5a62SPatrick Kelsey 
2288bdc5a62SPatrick Kelsey trunc:
2298bdc5a62SPatrick Kelsey 	ND_PRINT((ndo, " [|rreq"));
2305b0fe478SBruce M Simpson }
2315b0fe478SBruce M Simpson 
2325b0fe478SBruce M Simpson static void
2338bdc5a62SPatrick Kelsey aodv_rrep(netdissect_options *ndo, const u_char *dat, u_int length)
2345b0fe478SBruce M Simpson {
2355b0fe478SBruce M Simpson 	u_int i;
2368bdc5a62SPatrick Kelsey 	const struct aodv_rrep *ap = (const struct aodv_rrep *)dat;
2375b0fe478SBruce M Simpson 
2388bdc5a62SPatrick Kelsey 	ND_TCHECK(*ap);
2398bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
2408bdc5a62SPatrick Kelsey 		goto trunc;
2413c602fabSXin LI 	ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n"
2425b0fe478SBruce M Simpson 	    "\tdst %s dseq %lu src %s %lu ms", length,
2438bdc5a62SPatrick Kelsey 	    ap->rrep_type & RREP_REPAIR ? "[R]" : "",
2448bdc5a62SPatrick Kelsey 	    ap->rrep_type & RREP_ACK ? "[A] " : " ",
2458bdc5a62SPatrick Kelsey 	    ap->rrep_ps & RREP_PREFIX_MASK,
2468bdc5a62SPatrick Kelsey 	    ap->rrep_hops,
2478bdc5a62SPatrick Kelsey 	    ipaddr_string(ndo, &ap->rrep_da),
2488bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
2498bdc5a62SPatrick Kelsey 	    ipaddr_string(ndo, &ap->rrep_oa),
2508bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rrep_life)));
2518bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
2525b0fe478SBruce M Simpson 	if (i >= sizeof(struct aodv_ext))
2538bdc5a62SPatrick Kelsey 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
2548bdc5a62SPatrick Kelsey 	return;
2558bdc5a62SPatrick Kelsey 
2568bdc5a62SPatrick Kelsey trunc:
2578bdc5a62SPatrick Kelsey 	ND_PRINT((ndo, " [|rreq"));
2585b0fe478SBruce M Simpson }
2595b0fe478SBruce M Simpson 
2605b0fe478SBruce M Simpson static void
2618bdc5a62SPatrick Kelsey aodv_rerr(netdissect_options *ndo, const u_char *dat, u_int length)
2625b0fe478SBruce M Simpson {
2638bdc5a62SPatrick Kelsey 	u_int i, dc;
2648bdc5a62SPatrick Kelsey 	const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
2658bdc5a62SPatrick Kelsey 	const struct rerr_unreach *dp;
2665b0fe478SBruce M Simpson 
2678bdc5a62SPatrick Kelsey 	ND_TCHECK(*ap);
2688bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
2698bdc5a62SPatrick Kelsey 		goto trunc;
2703c602fabSXin LI 	ND_PRINT((ndo, " rerr %s [items %u] [%u]:",
2718bdc5a62SPatrick Kelsey 	    ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
2728bdc5a62SPatrick Kelsey 	    ap->rerr_dc, length));
273*3340d773SGleb Smirnoff 	dp = (const struct rerr_unreach *)(dat + sizeof(*ap));
2748bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
2758bdc5a62SPatrick Kelsey 	for (dc = ap->rerr_dc; dc != 0; dc--) {
2768bdc5a62SPatrick Kelsey 		ND_TCHECK(*dp);
2778bdc5a62SPatrick Kelsey 		if (i < sizeof(*dp))
2788bdc5a62SPatrick Kelsey 			goto trunc;
2793c602fabSXin LI 		ND_PRINT((ndo, " {%s}(%ld)", ipaddr_string(ndo, &dp->u_da),
2803c602fabSXin LI 		    (unsigned long)EXTRACT_32BITS(&dp->u_ds)));
2818bdc5a62SPatrick Kelsey 		dp++;
2828bdc5a62SPatrick Kelsey 		i -= sizeof(*dp);
2835b0fe478SBruce M Simpson 	}
2848bdc5a62SPatrick Kelsey 	return;
2858bdc5a62SPatrick Kelsey 
2868bdc5a62SPatrick Kelsey trunc:
2873c602fabSXin LI 	ND_PRINT((ndo, "[|rerr]"));
2885b0fe478SBruce M Simpson }
2895b0fe478SBruce M Simpson 
2905b0fe478SBruce M Simpson static void
2918bdc5a62SPatrick Kelsey aodv_v6_rreq(netdissect_options *ndo, const u_char *dat, u_int length)
2925b0fe478SBruce M Simpson {
2935b0fe478SBruce M Simpson 	u_int i;
2948bdc5a62SPatrick Kelsey 	const struct aodv_rreq6 *ap = (const struct aodv_rreq6 *)dat;
2955b0fe478SBruce M Simpson 
2968bdc5a62SPatrick Kelsey 	ND_TCHECK(*ap);
2978bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
2988bdc5a62SPatrick Kelsey 		goto trunc;
2993c602fabSXin LI 	ND_PRINT((ndo, " v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
3005b0fe478SBruce M Simpson 	    "\tdst %s seq %lu src %s seq %lu", length,
3018bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_JOIN ? "[J]" : "",
3028bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
3038bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_GRAT ? "[G]" : "",
3048bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_DEST ? "[D]" : "",
3058bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
3068bdc5a62SPatrick Kelsey 	    ap->rreq_hops,
3078bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
3088bdc5a62SPatrick Kelsey 	    ip6addr_string(ndo, &ap->rreq_da),
3098bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
3108bdc5a62SPatrick Kelsey 	    ip6addr_string(ndo, &ap->rreq_oa),
3118bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_os)));
3128bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
3135b0fe478SBruce M Simpson 	if (i >= sizeof(struct aodv_ext))
3148bdc5a62SPatrick Kelsey 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
3158bdc5a62SPatrick Kelsey 	return;
3168bdc5a62SPatrick Kelsey 
3178bdc5a62SPatrick Kelsey trunc:
3188bdc5a62SPatrick Kelsey 	ND_PRINT((ndo, " [|rreq"));
3195b0fe478SBruce M Simpson }
3205b0fe478SBruce M Simpson 
3215b0fe478SBruce M Simpson static void
3228bdc5a62SPatrick Kelsey aodv_v6_rrep(netdissect_options *ndo, const u_char *dat, u_int length)
3235b0fe478SBruce M Simpson {
3245b0fe478SBruce M Simpson 	u_int i;
3258bdc5a62SPatrick Kelsey 	const struct aodv_rrep6 *ap = (const struct aodv_rrep6 *)dat;
3265b0fe478SBruce M Simpson 
3278bdc5a62SPatrick Kelsey 	ND_TCHECK(*ap);
3288bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
3298bdc5a62SPatrick Kelsey 		goto trunc;
3303c602fabSXin LI 	ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n"
3315b0fe478SBruce M Simpson 	   "\tdst %s dseq %lu src %s %lu ms", length,
3328bdc5a62SPatrick Kelsey 	    ap->rrep_type & RREP_REPAIR ? "[R]" : "",
3338bdc5a62SPatrick Kelsey 	    ap->rrep_type & RREP_ACK ? "[A] " : " ",
3348bdc5a62SPatrick Kelsey 	    ap->rrep_ps & RREP_PREFIX_MASK,
3358bdc5a62SPatrick Kelsey 	    ap->rrep_hops,
3368bdc5a62SPatrick Kelsey 	    ip6addr_string(ndo, &ap->rrep_da),
3378bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
3388bdc5a62SPatrick Kelsey 	    ip6addr_string(ndo, &ap->rrep_oa),
3398bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rrep_life)));
3408bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
3415b0fe478SBruce M Simpson 	if (i >= sizeof(struct aodv_ext))
3428bdc5a62SPatrick Kelsey 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
3438bdc5a62SPatrick Kelsey 	return;
3448bdc5a62SPatrick Kelsey 
3458bdc5a62SPatrick Kelsey trunc:
3468bdc5a62SPatrick Kelsey 	ND_PRINT((ndo, " [|rreq"));
3475b0fe478SBruce M Simpson }
3485b0fe478SBruce M Simpson 
3495b0fe478SBruce M Simpson static void
3508bdc5a62SPatrick Kelsey aodv_v6_rerr(netdissect_options *ndo, const u_char *dat, u_int length)
3515b0fe478SBruce M Simpson {
3528bdc5a62SPatrick Kelsey 	u_int i, dc;
3538bdc5a62SPatrick Kelsey 	const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
3548bdc5a62SPatrick Kelsey 	const struct rerr_unreach6 *dp6;
3555b0fe478SBruce M Simpson 
3568bdc5a62SPatrick Kelsey 	ND_TCHECK(*ap);
3578bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
3588bdc5a62SPatrick Kelsey 		goto trunc;
3593c602fabSXin LI 	ND_PRINT((ndo, " rerr %s [items %u] [%u]:",
3608bdc5a62SPatrick Kelsey 	    ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
3618bdc5a62SPatrick Kelsey 	    ap->rerr_dc, length));
362*3340d773SGleb Smirnoff 	dp6 = (const struct rerr_unreach6 *)(const void *)(ap + 1);
3638bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
3648bdc5a62SPatrick Kelsey 	for (dc = ap->rerr_dc; dc != 0; dc--) {
3658bdc5a62SPatrick Kelsey 		ND_TCHECK(*dp6);
3668bdc5a62SPatrick Kelsey 		if (i < sizeof(*dp6))
3678bdc5a62SPatrick Kelsey 			goto trunc;
3683c602fabSXin LI 		ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(ndo, &dp6->u_da),
3693c602fabSXin LI 		    (unsigned long)EXTRACT_32BITS(&dp6->u_ds)));
3708bdc5a62SPatrick Kelsey 		dp6++;
3718bdc5a62SPatrick Kelsey 		i -= sizeof(*dp6);
3725b0fe478SBruce M Simpson 	}
3738bdc5a62SPatrick Kelsey 	return;
3748bdc5a62SPatrick Kelsey 
3758bdc5a62SPatrick Kelsey trunc:
3763c602fabSXin LI 	ND_PRINT((ndo, "[|rerr]"));
3775b0fe478SBruce M Simpson }
3785b0fe478SBruce M Simpson 
3795b0fe478SBruce M Simpson static void
3808bdc5a62SPatrick Kelsey aodv_v6_draft_01_rreq(netdissect_options *ndo, const u_char *dat, u_int length)
3815b0fe478SBruce M Simpson {
3825b0fe478SBruce M Simpson 	u_int i;
3838bdc5a62SPatrick Kelsey 	const struct aodv_rreq6_draft_01 *ap = (const struct aodv_rreq6_draft_01 *)dat;
3845b0fe478SBruce M Simpson 
3858bdc5a62SPatrick Kelsey 	ND_TCHECK(*ap);
3868bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
3878bdc5a62SPatrick Kelsey 		goto trunc;
3883c602fabSXin LI 	ND_PRINT((ndo, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
3895b0fe478SBruce M Simpson 	    "\tdst %s seq %lu src %s seq %lu", length,
3908bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_JOIN ? "[J]" : "",
3918bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
3928bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_GRAT ? "[G]" : "",
3938bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_DEST ? "[D]" : "",
3948bdc5a62SPatrick Kelsey 	    ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
3958bdc5a62SPatrick Kelsey 	    ap->rreq_hops,
3968bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
3978bdc5a62SPatrick Kelsey 	    ip6addr_string(ndo, &ap->rreq_da),
3988bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
3998bdc5a62SPatrick Kelsey 	    ip6addr_string(ndo, &ap->rreq_oa),
4008bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_os)));
4018bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
4025b0fe478SBruce M Simpson 	if (i >= sizeof(struct aodv_ext))
4038bdc5a62SPatrick Kelsey 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
4048bdc5a62SPatrick Kelsey 	return;
4058bdc5a62SPatrick Kelsey 
4068bdc5a62SPatrick Kelsey trunc:
4078bdc5a62SPatrick Kelsey 	ND_PRINT((ndo, " [|rreq"));
4085b0fe478SBruce M Simpson }
4095b0fe478SBruce M Simpson 
4105b0fe478SBruce M Simpson static void
4118bdc5a62SPatrick Kelsey aodv_v6_draft_01_rrep(netdissect_options *ndo, const u_char *dat, u_int length)
4125b0fe478SBruce M Simpson {
4135b0fe478SBruce M Simpson 	u_int i;
4148bdc5a62SPatrick Kelsey 	const struct aodv_rrep6_draft_01 *ap = (const struct aodv_rrep6_draft_01 *)dat;
4155b0fe478SBruce M Simpson 
4168bdc5a62SPatrick Kelsey 	ND_TCHECK(*ap);
4178bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
4188bdc5a62SPatrick Kelsey 		goto trunc;
4193c602fabSXin LI 	ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n"
4205b0fe478SBruce M Simpson 	   "\tdst %s dseq %lu src %s %lu ms", length,
4218bdc5a62SPatrick Kelsey 	    ap->rrep_type & RREP_REPAIR ? "[R]" : "",
4228bdc5a62SPatrick Kelsey 	    ap->rrep_type & RREP_ACK ? "[A] " : " ",
4238bdc5a62SPatrick Kelsey 	    ap->rrep_ps & RREP_PREFIX_MASK,
4248bdc5a62SPatrick Kelsey 	    ap->rrep_hops,
4258bdc5a62SPatrick Kelsey 	    ip6addr_string(ndo, &ap->rrep_da),
4268bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
4278bdc5a62SPatrick Kelsey 	    ip6addr_string(ndo, &ap->rrep_oa),
4288bdc5a62SPatrick Kelsey 	    (unsigned long)EXTRACT_32BITS(&ap->rrep_life)));
4298bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
4305b0fe478SBruce M Simpson 	if (i >= sizeof(struct aodv_ext))
4318bdc5a62SPatrick Kelsey 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
4328bdc5a62SPatrick Kelsey 	return;
4338bdc5a62SPatrick Kelsey 
4348bdc5a62SPatrick Kelsey trunc:
4358bdc5a62SPatrick Kelsey 	ND_PRINT((ndo, " [|rreq"));
4365b0fe478SBruce M Simpson }
4375b0fe478SBruce M Simpson 
4385b0fe478SBruce M Simpson static void
4398bdc5a62SPatrick Kelsey aodv_v6_draft_01_rerr(netdissect_options *ndo, const u_char *dat, u_int length)
4405b0fe478SBruce M Simpson {
4418bdc5a62SPatrick Kelsey 	u_int i, dc;
4428bdc5a62SPatrick Kelsey 	const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
4438bdc5a62SPatrick Kelsey 	const struct rerr_unreach6_draft_01 *dp6;
4445b0fe478SBruce M Simpson 
4458bdc5a62SPatrick Kelsey 	ND_TCHECK(*ap);
4468bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
4478bdc5a62SPatrick Kelsey 		goto trunc;
4483c602fabSXin LI 	ND_PRINT((ndo, " rerr %s [items %u] [%u]:",
4498bdc5a62SPatrick Kelsey 	    ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
4508bdc5a62SPatrick Kelsey 	    ap->rerr_dc, length));
451*3340d773SGleb Smirnoff 	dp6 = (const struct rerr_unreach6_draft_01 *)(const void *)(ap + 1);
4528bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
4538bdc5a62SPatrick Kelsey 	for (dc = ap->rerr_dc; dc != 0; dc--) {
4548bdc5a62SPatrick Kelsey 		ND_TCHECK(*dp6);
4558bdc5a62SPatrick Kelsey 		if (i < sizeof(*dp6))
4568bdc5a62SPatrick Kelsey 			goto trunc;
4573c602fabSXin LI 		ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(ndo, &dp6->u_da),
4583c602fabSXin LI 		    (unsigned long)EXTRACT_32BITS(&dp6->u_ds)));
4598bdc5a62SPatrick Kelsey 		dp6++;
4608bdc5a62SPatrick Kelsey 		i -= sizeof(*dp6);
4615b0fe478SBruce M Simpson 	}
4628bdc5a62SPatrick Kelsey 	return;
4638bdc5a62SPatrick Kelsey 
4648bdc5a62SPatrick Kelsey trunc:
4653c602fabSXin LI 	ND_PRINT((ndo, "[|rerr]"));
4665b0fe478SBruce M Simpson }
4675b0fe478SBruce M Simpson 
4685b0fe478SBruce M Simpson void
4693c602fabSXin LI aodv_print(netdissect_options *ndo,
4703c602fabSXin LI            const u_char *dat, u_int length, int is_ip6)
4715b0fe478SBruce M Simpson {
4728bdc5a62SPatrick Kelsey 	uint8_t msg_type;
4735b0fe478SBruce M Simpson 
4748bdc5a62SPatrick Kelsey 	/*
4758bdc5a62SPatrick Kelsey 	 * The message type is the first byte; make sure we have it
4768bdc5a62SPatrick Kelsey 	 * and then fetch it.
4778bdc5a62SPatrick Kelsey 	 */
4788bdc5a62SPatrick Kelsey 	ND_TCHECK(*dat);
4798bdc5a62SPatrick Kelsey 	msg_type = *dat;
4803c602fabSXin LI 	ND_PRINT((ndo, " aodv"));
4815b0fe478SBruce M Simpson 
4828bdc5a62SPatrick Kelsey 	switch (msg_type) {
4835b0fe478SBruce M Simpson 
4845b0fe478SBruce M Simpson 	case AODV_RREQ:
4855b0fe478SBruce M Simpson 		if (is_ip6)
4868bdc5a62SPatrick Kelsey 			aodv_v6_rreq(ndo, dat, length);
4875b0fe478SBruce M Simpson 		else
4888bdc5a62SPatrick Kelsey 			aodv_rreq(ndo, dat, length);
4895b0fe478SBruce M Simpson 		break;
4905b0fe478SBruce M Simpson 
4915b0fe478SBruce M Simpson 	case AODV_RREP:
4925b0fe478SBruce M Simpson 		if (is_ip6)
4938bdc5a62SPatrick Kelsey 			aodv_v6_rrep(ndo, dat, length);
4945b0fe478SBruce M Simpson 		else
4958bdc5a62SPatrick Kelsey 			aodv_rrep(ndo, dat, length);
4965b0fe478SBruce M Simpson 		break;
4975b0fe478SBruce M Simpson 
4985b0fe478SBruce M Simpson 	case AODV_RERR:
4995b0fe478SBruce M Simpson 		if (is_ip6)
5008bdc5a62SPatrick Kelsey 			aodv_v6_rerr(ndo, dat, length);
5015b0fe478SBruce M Simpson 		else
5028bdc5a62SPatrick Kelsey 			aodv_rerr(ndo, dat, length);
5035b0fe478SBruce M Simpson 		break;
5045b0fe478SBruce M Simpson 
5055b0fe478SBruce M Simpson 	case AODV_RREP_ACK:
5063c602fabSXin LI 		ND_PRINT((ndo, " rrep-ack %u", length));
5075b0fe478SBruce M Simpson 		break;
5085b0fe478SBruce M Simpson 
5095b0fe478SBruce M Simpson 	case AODV_V6_DRAFT_01_RREQ:
5108bdc5a62SPatrick Kelsey 		aodv_v6_draft_01_rreq(ndo, dat, length);
5115b0fe478SBruce M Simpson 		break;
5125b0fe478SBruce M Simpson 
5135b0fe478SBruce M Simpson 	case AODV_V6_DRAFT_01_RREP:
5148bdc5a62SPatrick Kelsey 		aodv_v6_draft_01_rrep(ndo, dat, length);
5155b0fe478SBruce M Simpson 		break;
5165b0fe478SBruce M Simpson 
5175b0fe478SBruce M Simpson 	case AODV_V6_DRAFT_01_RERR:
5188bdc5a62SPatrick Kelsey 		aodv_v6_draft_01_rerr(ndo, dat, length);
5195b0fe478SBruce M Simpson 		break;
5205b0fe478SBruce M Simpson 
5215b0fe478SBruce M Simpson 	case AODV_V6_DRAFT_01_RREP_ACK:
5223c602fabSXin LI 		ND_PRINT((ndo, " rrep-ack %u", length));
5235b0fe478SBruce M Simpson 		break;
5245b0fe478SBruce M Simpson 
5255b0fe478SBruce M Simpson 	default:
5268bdc5a62SPatrick Kelsey 		ND_PRINT((ndo, " type %u %u", msg_type, length));
5275b0fe478SBruce M Simpson 	}
5288bdc5a62SPatrick Kelsey 	return;
5298bdc5a62SPatrick Kelsey 
5308bdc5a62SPatrick Kelsey trunc:
5318bdc5a62SPatrick Kelsey 	ND_PRINT((ndo, " [|aodv]"));
5325b0fe478SBruce M Simpson }
533