xref: /freebsd/contrib/tcpdump/print-aodv.c (revision 0a7e5f1f02aad2ff5fff1c60f44c6975fd07e1d9)
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 
333340d773SGleb Smirnoff /* \summary: Ad hoc On-Demand Distance Vector (AODV) Routing printer */
343340d773SGleb Smirnoff 
35*ee67461eSJoseph Mingrone #include <config.h>
365b0fe478SBruce M Simpson 
37*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
385b0fe478SBruce M Simpson 
393340d773SGleb Smirnoff #include "netdissect.h"
405b0fe478SBruce M Simpson #include "addrtoname.h"
413340d773SGleb Smirnoff #include "extract.h"
425b0fe478SBruce M Simpson 
430bff6a5aSEd Maste /*
440bff6a5aSEd Maste  * RFC 3561
450bff6a5aSEd Maste  */
463c602fabSXin LI struct aodv_rreq {
47*ee67461eSJoseph Mingrone 	nd_uint8_t	rreq_type;	/* AODV message type (1) */
48*ee67461eSJoseph Mingrone 	nd_uint8_t	rreq_flags;	/* various flags */
49*ee67461eSJoseph Mingrone 	nd_uint8_t	rreq_zero0;	/* reserved, set to zero */
50*ee67461eSJoseph Mingrone 	nd_uint8_t	rreq_hops;	/* number of hops from originator */
51*ee67461eSJoseph Mingrone 	nd_uint32_t	rreq_id;	/* request ID */
52*ee67461eSJoseph Mingrone 	nd_ipv4		rreq_da;	/* destination IPv4 address */
53*ee67461eSJoseph Mingrone 	nd_uint32_t	rreq_ds;	/* destination sequence number */
54*ee67461eSJoseph Mingrone 	nd_ipv4		rreq_oa;	/* originator IPv4 address */
55*ee67461eSJoseph Mingrone 	nd_uint32_t	rreq_os;	/* originator sequence number */
563c602fabSXin LI };
573c602fabSXin LI struct aodv_rreq6 {
58*ee67461eSJoseph Mingrone 	nd_uint8_t	rreq_type;	/* AODV message type (1) */
59*ee67461eSJoseph Mingrone 	nd_uint8_t	rreq_flags;	/* various flags */
60*ee67461eSJoseph Mingrone 	nd_uint8_t	rreq_zero0;	/* reserved, set to zero */
61*ee67461eSJoseph Mingrone 	nd_uint8_t	rreq_hops;	/* number of hops from originator */
62*ee67461eSJoseph Mingrone 	nd_uint32_t	rreq_id;	/* request ID */
63*ee67461eSJoseph Mingrone 	nd_ipv6		rreq_da;	/* destination IPv6 address */
64*ee67461eSJoseph Mingrone 	nd_uint32_t	rreq_ds;	/* destination sequence number */
65*ee67461eSJoseph Mingrone 	nd_ipv6		rreq_oa;	/* originator IPv6 address */
66*ee67461eSJoseph Mingrone 	nd_uint32_t	rreq_os;	/* originator sequence number */
673c602fabSXin LI };
683c602fabSXin LI struct aodv_rreq6_draft_01 {
69*ee67461eSJoseph Mingrone 	nd_uint8_t	rreq_type;	/* AODV message type (16) */
70*ee67461eSJoseph Mingrone 	nd_uint8_t	rreq_flags;	/* various flags */
71*ee67461eSJoseph Mingrone 	nd_uint8_t	rreq_zero0;	/* reserved, set to zero */
72*ee67461eSJoseph Mingrone 	nd_uint8_t	rreq_hops;	/* number of hops from originator */
73*ee67461eSJoseph Mingrone 	nd_uint32_t	rreq_id;	/* request ID */
74*ee67461eSJoseph Mingrone 	nd_uint32_t	rreq_ds;	/* destination sequence number */
75*ee67461eSJoseph Mingrone 	nd_uint32_t	rreq_os;	/* originator sequence number */
76*ee67461eSJoseph Mingrone 	nd_ipv6		rreq_da;	/* destination IPv6 address */
77*ee67461eSJoseph Mingrone 	nd_ipv6		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 {
88*ee67461eSJoseph Mingrone 	nd_uint8_t	rrep_type;	/* AODV message type (2) */
89*ee67461eSJoseph Mingrone 	nd_uint8_t	rrep_flags;	/* various flags */
90*ee67461eSJoseph Mingrone 	nd_uint8_t	rrep_ps;	/* prefix size */
91*ee67461eSJoseph Mingrone 	nd_uint8_t	rrep_hops;	/* number of hops from o to d */
92*ee67461eSJoseph Mingrone 	nd_ipv4		rrep_da;	/* destination IPv4 address */
93*ee67461eSJoseph Mingrone 	nd_uint32_t	rrep_ds;	/* destination sequence number */
94*ee67461eSJoseph Mingrone 	nd_ipv4		rrep_oa;	/* originator IPv4 address */
95*ee67461eSJoseph Mingrone 	nd_uint32_t	rrep_life;	/* lifetime of this route */
963c602fabSXin LI };
973c602fabSXin LI struct aodv_rrep6 {
98*ee67461eSJoseph Mingrone 	nd_uint8_t	rrep_type;	/* AODV message type (2) */
99*ee67461eSJoseph Mingrone 	nd_uint8_t	rrep_flags;	/* various flags */
100*ee67461eSJoseph Mingrone 	nd_uint8_t	rrep_ps;	/* prefix size */
101*ee67461eSJoseph Mingrone 	nd_uint8_t	rrep_hops;	/* number of hops from o to d */
102*ee67461eSJoseph Mingrone 	nd_ipv6		rrep_da;	/* destination IPv6 address */
103*ee67461eSJoseph Mingrone 	nd_uint32_t	rrep_ds;	/* destination sequence number */
104*ee67461eSJoseph Mingrone 	nd_ipv6		rrep_oa;	/* originator IPv6 address */
105*ee67461eSJoseph Mingrone 	nd_uint32_t	rrep_life;	/* lifetime of this route */
1063c602fabSXin LI };
1073c602fabSXin LI struct aodv_rrep6_draft_01 {
108*ee67461eSJoseph Mingrone 	nd_uint8_t	rrep_type;	/* AODV message type (17) */
109*ee67461eSJoseph Mingrone 	nd_uint8_t	rrep_flags;	/* various flags */
110*ee67461eSJoseph Mingrone 	nd_uint8_t	rrep_ps;	/* prefix size */
111*ee67461eSJoseph Mingrone 	nd_uint8_t	rrep_hops;	/* number of hops from o to d */
112*ee67461eSJoseph Mingrone 	nd_uint32_t	rrep_ds;	/* destination sequence number */
113*ee67461eSJoseph Mingrone 	nd_ipv6		rrep_da;	/* destination IPv6 address */
114*ee67461eSJoseph Mingrone 	nd_ipv6		rrep_oa;	/* originator IPv6 address */
115*ee67461eSJoseph Mingrone 	nd_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 {
124*ee67461eSJoseph Mingrone 	nd_ipv4		u_da;	/* IPv4 address */
125*ee67461eSJoseph Mingrone 	nd_uint32_t	u_ds;	/* sequence number */
1263c602fabSXin LI };
1273c602fabSXin LI struct rerr_unreach6 {
128*ee67461eSJoseph Mingrone 	nd_ipv6		u_da;	/* IPv6 address */
129*ee67461eSJoseph Mingrone 	nd_uint32_t	u_ds;	/* sequence number */
1303c602fabSXin LI };
1313c602fabSXin LI struct rerr_unreach6_draft_01 {
132*ee67461eSJoseph Mingrone 	nd_ipv6		u_da;	/* IPv6 address */
133*ee67461eSJoseph Mingrone 	nd_uint32_t	u_ds;	/* sequence number */
1343c602fabSXin LI };
1353c602fabSXin LI 
1363c602fabSXin LI struct aodv_rerr {
137*ee67461eSJoseph Mingrone 	nd_uint8_t	rerr_type;	/* AODV message type (3 or 18) */
138*ee67461eSJoseph Mingrone 	nd_uint8_t	rerr_flags;	/* various flags */
139*ee67461eSJoseph Mingrone 	nd_uint8_t	rerr_zero0;	/* reserved, set to zero */
140*ee67461eSJoseph Mingrone 	nd_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 {
147*ee67461eSJoseph Mingrone 	nd_uint8_t	ra_type;
148*ee67461eSJoseph Mingrone 	nd_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 {
162*ee67461eSJoseph Mingrone 	nd_uint8_t	type;		/* extension type */
163*ee67461eSJoseph Mingrone 	nd_uint8_t	length;		/* extension length */
1643c602fabSXin LI };
1653c602fabSXin LI 
1663c602fabSXin LI struct aodv_hello {
1673c602fabSXin LI 	struct	aodv_ext	eh;		/* extension header */
168*ee67461eSJoseph Mingrone 	nd_uint32_t		interval;	/* 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
aodv_extension(netdissect_options * ndo,const struct aodv_ext * ep,u_int length)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 
181*ee67461eSJoseph Mingrone 	ND_TCHECK_SIZE(ep);
182*ee67461eSJoseph Mingrone 	switch (GET_U_1(ep->type)) {
1835b0fe478SBruce M Simpson 	case AODV_EXT_HELLO:
1848bdc5a62SPatrick Kelsey 		ah = (const struct aodv_hello *)(const void *)ep;
185*ee67461eSJoseph Mingrone 		ND_TCHECK_SIZE(ah);
1868bdc5a62SPatrick Kelsey 		if (length < sizeof(struct aodv_hello))
1878bdc5a62SPatrick Kelsey 			goto trunc;
188*ee67461eSJoseph Mingrone 		if (GET_U_1(ep->length) < 4) {
189*ee67461eSJoseph Mingrone 			ND_PRINT("\n\text HELLO - bad length %u",
190*ee67461eSJoseph Mingrone 				 GET_U_1(ep->length));
1910bff6a5aSEd Maste 			break;
1920bff6a5aSEd Maste 		}
193*ee67461eSJoseph Mingrone 		ND_PRINT("\n\text HELLO %u ms",
194*ee67461eSJoseph Mingrone 		    GET_BE_U_4(ah->interval));
1955b0fe478SBruce M Simpson 		break;
1965b0fe478SBruce M Simpson 
1975b0fe478SBruce M Simpson 	default:
198*ee67461eSJoseph Mingrone 		ND_PRINT("\n\text %u %u", GET_U_1(ep->type),
199*ee67461eSJoseph Mingrone 			 GET_U_1(ep->length));
2005b0fe478SBruce M Simpson 		break;
2015b0fe478SBruce M Simpson 	}
2028bdc5a62SPatrick Kelsey 	return;
2038bdc5a62SPatrick Kelsey 
2048bdc5a62SPatrick Kelsey trunc:
205*ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
2065b0fe478SBruce M Simpson }
2075b0fe478SBruce M Simpson 
2085b0fe478SBruce M Simpson static void
aodv_rreq(netdissect_options * ndo,const u_char * dat,u_int length)2098bdc5a62SPatrick Kelsey aodv_rreq(netdissect_options *ndo, const u_char *dat, u_int length)
2105b0fe478SBruce M Simpson {
2115b0fe478SBruce M Simpson 	u_int i;
2128bdc5a62SPatrick Kelsey 	const struct aodv_rreq *ap = (const struct aodv_rreq *)dat;
2135b0fe478SBruce M Simpson 
214*ee67461eSJoseph Mingrone 	ND_TCHECK_SIZE(ap);
2158bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
2168bdc5a62SPatrick Kelsey 		goto trunc;
217*ee67461eSJoseph Mingrone 	ND_PRINT(" rreq %u %s%s%s%s%shops %u id 0x%08x\n"
218*ee67461eSJoseph Mingrone 	    "\tdst %s seq %u src %s seq %u", length,
219*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "",
220*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "",
221*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "",
222*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "",
223*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ",
224*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_hops),
225*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rreq_id),
226*ee67461eSJoseph Mingrone 	    GET_IPADDR_STRING(ap->rreq_da),
227*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rreq_ds),
228*ee67461eSJoseph Mingrone 	    GET_IPADDR_STRING(ap->rreq_oa),
229*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rreq_os));
2308bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
2315b0fe478SBruce M Simpson 	if (i >= sizeof(struct aodv_ext))
2328bdc5a62SPatrick Kelsey 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
2338bdc5a62SPatrick Kelsey 	return;
2348bdc5a62SPatrick Kelsey 
2358bdc5a62SPatrick Kelsey trunc:
236*ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
2375b0fe478SBruce M Simpson }
2385b0fe478SBruce M Simpson 
2395b0fe478SBruce M Simpson static void
aodv_rrep(netdissect_options * ndo,const u_char * dat,u_int length)2408bdc5a62SPatrick Kelsey aodv_rrep(netdissect_options *ndo, const u_char *dat, u_int length)
2415b0fe478SBruce M Simpson {
2425b0fe478SBruce M Simpson 	u_int i;
2438bdc5a62SPatrick Kelsey 	const struct aodv_rrep *ap = (const struct aodv_rrep *)dat;
2445b0fe478SBruce M Simpson 
245*ee67461eSJoseph Mingrone 	ND_TCHECK_SIZE(ap);
2468bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
2478bdc5a62SPatrick Kelsey 		goto trunc;
248*ee67461eSJoseph Mingrone 	ND_PRINT(" rrep %u %s%sprefix %u hops %u\n"
249*ee67461eSJoseph Mingrone 	    "\tdst %s dseq %u src %s %u ms", length,
250*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "",
251*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ",
252*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK,
253*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rrep_hops),
254*ee67461eSJoseph Mingrone 	    GET_IPADDR_STRING(ap->rrep_da),
255*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rrep_ds),
256*ee67461eSJoseph Mingrone 	    GET_IPADDR_STRING(ap->rrep_oa),
257*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rrep_life));
2588bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
2595b0fe478SBruce M Simpson 	if (i >= sizeof(struct aodv_ext))
2608bdc5a62SPatrick Kelsey 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
2618bdc5a62SPatrick Kelsey 	return;
2628bdc5a62SPatrick Kelsey 
2638bdc5a62SPatrick Kelsey trunc:
264*ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
2655b0fe478SBruce M Simpson }
2665b0fe478SBruce M Simpson 
2675b0fe478SBruce M Simpson static void
aodv_rerr(netdissect_options * ndo,const u_char * dat,u_int length)2688bdc5a62SPatrick Kelsey aodv_rerr(netdissect_options *ndo, const u_char *dat, u_int length)
2695b0fe478SBruce M Simpson {
2708bdc5a62SPatrick Kelsey 	u_int i, dc;
2718bdc5a62SPatrick Kelsey 	const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
2728bdc5a62SPatrick Kelsey 	const struct rerr_unreach *dp;
2735b0fe478SBruce M Simpson 
274*ee67461eSJoseph Mingrone 	ND_TCHECK_SIZE(ap);
2758bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
2768bdc5a62SPatrick Kelsey 		goto trunc;
277*ee67461eSJoseph Mingrone 	ND_PRINT(" rerr %s [items %u] [%u]:",
278*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "",
279*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rerr_dc), length);
2803340d773SGleb Smirnoff 	dp = (const struct rerr_unreach *)(dat + sizeof(*ap));
2818bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
282*ee67461eSJoseph Mingrone 	for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) {
283*ee67461eSJoseph Mingrone 		ND_TCHECK_SIZE(dp);
2848bdc5a62SPatrick Kelsey 		if (i < sizeof(*dp))
2858bdc5a62SPatrick Kelsey 			goto trunc;
286*ee67461eSJoseph Mingrone 		ND_PRINT(" {%s}(%u)", GET_IPADDR_STRING(dp->u_da),
287*ee67461eSJoseph Mingrone 		    GET_BE_U_4(dp->u_ds));
2888bdc5a62SPatrick Kelsey 		dp++;
2898bdc5a62SPatrick Kelsey 		i -= sizeof(*dp);
2905b0fe478SBruce M Simpson 	}
2918bdc5a62SPatrick Kelsey 	return;
2928bdc5a62SPatrick Kelsey 
2938bdc5a62SPatrick Kelsey trunc:
294*ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
2955b0fe478SBruce M Simpson }
2965b0fe478SBruce M Simpson 
2975b0fe478SBruce M Simpson static void
aodv_v6_rreq(netdissect_options * ndo,const u_char * dat,u_int length)2988bdc5a62SPatrick Kelsey aodv_v6_rreq(netdissect_options *ndo, const u_char *dat, u_int length)
2995b0fe478SBruce M Simpson {
3005b0fe478SBruce M Simpson 	u_int i;
3018bdc5a62SPatrick Kelsey 	const struct aodv_rreq6 *ap = (const struct aodv_rreq6 *)dat;
3025b0fe478SBruce M Simpson 
303*ee67461eSJoseph Mingrone 	ND_TCHECK_SIZE(ap);
3048bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
3058bdc5a62SPatrick Kelsey 		goto trunc;
306*ee67461eSJoseph Mingrone 	ND_PRINT(" v6 rreq %u %s%s%s%s%shops %u id 0x%08x\n"
307*ee67461eSJoseph Mingrone 	    "\tdst %s seq %u src %s seq %u", length,
308*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "",
309*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "",
310*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "",
311*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "",
312*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ",
313*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_hops),
314*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rreq_id),
315*ee67461eSJoseph Mingrone 	    GET_IP6ADDR_STRING(ap->rreq_da),
316*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rreq_ds),
317*ee67461eSJoseph Mingrone 	    GET_IP6ADDR_STRING(ap->rreq_oa),
318*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rreq_os));
3198bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
3205b0fe478SBruce M Simpson 	if (i >= sizeof(struct aodv_ext))
3218bdc5a62SPatrick Kelsey 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
3228bdc5a62SPatrick Kelsey 	return;
3238bdc5a62SPatrick Kelsey 
3248bdc5a62SPatrick Kelsey trunc:
325*ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
3265b0fe478SBruce M Simpson }
3275b0fe478SBruce M Simpson 
3285b0fe478SBruce M Simpson static void
aodv_v6_rrep(netdissect_options * ndo,const u_char * dat,u_int length)3298bdc5a62SPatrick Kelsey aodv_v6_rrep(netdissect_options *ndo, const u_char *dat, u_int length)
3305b0fe478SBruce M Simpson {
3315b0fe478SBruce M Simpson 	u_int i;
3328bdc5a62SPatrick Kelsey 	const struct aodv_rrep6 *ap = (const struct aodv_rrep6 *)dat;
3335b0fe478SBruce M Simpson 
334*ee67461eSJoseph Mingrone 	ND_TCHECK_SIZE(ap);
3358bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
3368bdc5a62SPatrick Kelsey 		goto trunc;
337*ee67461eSJoseph Mingrone 	ND_PRINT(" rrep %u %s%sprefix %u hops %u\n"
338*ee67461eSJoseph Mingrone 	   "\tdst %s dseq %u src %s %u ms", length,
339*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "",
340*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ",
341*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK,
342*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rrep_hops),
343*ee67461eSJoseph Mingrone 	    GET_IP6ADDR_STRING(ap->rrep_da),
344*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rrep_ds),
345*ee67461eSJoseph Mingrone 	    GET_IP6ADDR_STRING(ap->rrep_oa),
346*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rrep_life));
3478bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
3485b0fe478SBruce M Simpson 	if (i >= sizeof(struct aodv_ext))
3498bdc5a62SPatrick Kelsey 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
3508bdc5a62SPatrick Kelsey 	return;
3518bdc5a62SPatrick Kelsey 
3528bdc5a62SPatrick Kelsey trunc:
353*ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
3545b0fe478SBruce M Simpson }
3555b0fe478SBruce M Simpson 
3565b0fe478SBruce M Simpson static void
aodv_v6_rerr(netdissect_options * ndo,const u_char * dat,u_int length)3578bdc5a62SPatrick Kelsey aodv_v6_rerr(netdissect_options *ndo, const u_char *dat, u_int length)
3585b0fe478SBruce M Simpson {
3598bdc5a62SPatrick Kelsey 	u_int i, dc;
3608bdc5a62SPatrick Kelsey 	const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
3618bdc5a62SPatrick Kelsey 	const struct rerr_unreach6 *dp6;
3625b0fe478SBruce M Simpson 
363*ee67461eSJoseph Mingrone 	ND_TCHECK_SIZE(ap);
3648bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
3658bdc5a62SPatrick Kelsey 		goto trunc;
366*ee67461eSJoseph Mingrone 	ND_PRINT(" rerr %s [items %u] [%u]:",
367*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "",
368*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rerr_dc), length);
3693340d773SGleb Smirnoff 	dp6 = (const struct rerr_unreach6 *)(const void *)(ap + 1);
3708bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
371*ee67461eSJoseph Mingrone 	for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) {
372*ee67461eSJoseph Mingrone 		ND_TCHECK_SIZE(dp6);
3738bdc5a62SPatrick Kelsey 		if (i < sizeof(*dp6))
3748bdc5a62SPatrick Kelsey 			goto trunc;
375*ee67461eSJoseph Mingrone 		ND_PRINT(" {%s}(%u)", GET_IP6ADDR_STRING(dp6->u_da),
376*ee67461eSJoseph Mingrone 			 GET_BE_U_4(dp6->u_ds));
3778bdc5a62SPatrick Kelsey 		dp6++;
3788bdc5a62SPatrick Kelsey 		i -= sizeof(*dp6);
3795b0fe478SBruce M Simpson 	}
3808bdc5a62SPatrick Kelsey 	return;
3818bdc5a62SPatrick Kelsey 
3828bdc5a62SPatrick Kelsey trunc:
383*ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
3845b0fe478SBruce M Simpson }
3855b0fe478SBruce M Simpson 
3865b0fe478SBruce M Simpson static void
aodv_v6_draft_01_rreq(netdissect_options * ndo,const u_char * dat,u_int length)3878bdc5a62SPatrick Kelsey aodv_v6_draft_01_rreq(netdissect_options *ndo, const u_char *dat, u_int length)
3885b0fe478SBruce M Simpson {
3895b0fe478SBruce M Simpson 	u_int i;
3908bdc5a62SPatrick Kelsey 	const struct aodv_rreq6_draft_01 *ap = (const struct aodv_rreq6_draft_01 *)dat;
3915b0fe478SBruce M Simpson 
392*ee67461eSJoseph Mingrone 	ND_TCHECK_SIZE(ap);
3938bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
3948bdc5a62SPatrick Kelsey 		goto trunc;
395*ee67461eSJoseph Mingrone 	ND_PRINT(" rreq %u %s%s%s%s%shops %u id 0x%08x\n"
396*ee67461eSJoseph Mingrone 	    "\tdst %s seq %u src %s seq %u", length,
397*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "",
398*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "",
399*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "",
400*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "",
401*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ",
402*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rreq_hops),
403*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rreq_id),
404*ee67461eSJoseph Mingrone 	    GET_IP6ADDR_STRING(ap->rreq_da),
405*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rreq_ds),
406*ee67461eSJoseph Mingrone 	    GET_IP6ADDR_STRING(ap->rreq_oa),
407*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rreq_os));
4088bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
4095b0fe478SBruce M Simpson 	if (i >= sizeof(struct aodv_ext))
4108bdc5a62SPatrick Kelsey 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
4118bdc5a62SPatrick Kelsey 	return;
4128bdc5a62SPatrick Kelsey 
4138bdc5a62SPatrick Kelsey trunc:
414*ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
4155b0fe478SBruce M Simpson }
4165b0fe478SBruce M Simpson 
4175b0fe478SBruce M Simpson static void
aodv_v6_draft_01_rrep(netdissect_options * ndo,const u_char * dat,u_int length)4188bdc5a62SPatrick Kelsey aodv_v6_draft_01_rrep(netdissect_options *ndo, const u_char *dat, u_int length)
4195b0fe478SBruce M Simpson {
4205b0fe478SBruce M Simpson 	u_int i;
4218bdc5a62SPatrick Kelsey 	const struct aodv_rrep6_draft_01 *ap = (const struct aodv_rrep6_draft_01 *)dat;
4225b0fe478SBruce M Simpson 
423*ee67461eSJoseph Mingrone 	ND_TCHECK_SIZE(ap);
4248bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
4258bdc5a62SPatrick Kelsey 		goto trunc;
426*ee67461eSJoseph Mingrone 	ND_PRINT(" rrep %u %s%sprefix %u hops %u\n"
427*ee67461eSJoseph Mingrone 	   "\tdst %s dseq %u src %s %u ms", length,
428*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "",
429*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ",
430*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK,
431*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rrep_hops),
432*ee67461eSJoseph Mingrone 	    GET_IP6ADDR_STRING(ap->rrep_da),
433*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rrep_ds),
434*ee67461eSJoseph Mingrone 	    GET_IP6ADDR_STRING(ap->rrep_oa),
435*ee67461eSJoseph Mingrone 	    GET_BE_U_4(ap->rrep_life));
4368bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
4375b0fe478SBruce M Simpson 	if (i >= sizeof(struct aodv_ext))
4388bdc5a62SPatrick Kelsey 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
4398bdc5a62SPatrick Kelsey 	return;
4408bdc5a62SPatrick Kelsey 
4418bdc5a62SPatrick Kelsey trunc:
442*ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
4435b0fe478SBruce M Simpson }
4445b0fe478SBruce M Simpson 
4455b0fe478SBruce M Simpson static void
aodv_v6_draft_01_rerr(netdissect_options * ndo,const u_char * dat,u_int length)4468bdc5a62SPatrick Kelsey aodv_v6_draft_01_rerr(netdissect_options *ndo, const u_char *dat, u_int length)
4475b0fe478SBruce M Simpson {
4488bdc5a62SPatrick Kelsey 	u_int i, dc;
4498bdc5a62SPatrick Kelsey 	const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
4508bdc5a62SPatrick Kelsey 	const struct rerr_unreach6_draft_01 *dp6;
4515b0fe478SBruce M Simpson 
452*ee67461eSJoseph Mingrone 	ND_TCHECK_SIZE(ap);
4538bdc5a62SPatrick Kelsey 	if (length < sizeof(*ap))
4548bdc5a62SPatrick Kelsey 		goto trunc;
455*ee67461eSJoseph Mingrone 	ND_PRINT(" rerr %s [items %u] [%u]:",
456*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "",
457*ee67461eSJoseph Mingrone 	    GET_U_1(ap->rerr_dc), length);
4583340d773SGleb Smirnoff 	dp6 = (const struct rerr_unreach6_draft_01 *)(const void *)(ap + 1);
4598bdc5a62SPatrick Kelsey 	i = length - sizeof(*ap);
460*ee67461eSJoseph Mingrone 	for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) {
461*ee67461eSJoseph Mingrone 		ND_TCHECK_SIZE(dp6);
4628bdc5a62SPatrick Kelsey 		if (i < sizeof(*dp6))
4638bdc5a62SPatrick Kelsey 			goto trunc;
464*ee67461eSJoseph Mingrone 		ND_PRINT(" {%s}(%u)", GET_IP6ADDR_STRING(dp6->u_da),
465*ee67461eSJoseph Mingrone 			 GET_BE_U_4(dp6->u_ds));
4668bdc5a62SPatrick Kelsey 		dp6++;
4678bdc5a62SPatrick Kelsey 		i -= sizeof(*dp6);
4685b0fe478SBruce M Simpson 	}
4698bdc5a62SPatrick Kelsey 	return;
4708bdc5a62SPatrick Kelsey 
4718bdc5a62SPatrick Kelsey trunc:
472*ee67461eSJoseph Mingrone 	nd_print_trunc(ndo);
4735b0fe478SBruce M Simpson }
4745b0fe478SBruce M Simpson 
4755b0fe478SBruce M Simpson void
aodv_print(netdissect_options * ndo,const u_char * dat,u_int length,int is_ip6)4763c602fabSXin LI aodv_print(netdissect_options *ndo,
4773c602fabSXin LI            const u_char *dat, u_int length, int is_ip6)
4785b0fe478SBruce M Simpson {
4798bdc5a62SPatrick Kelsey 	uint8_t msg_type;
4805b0fe478SBruce M Simpson 
481*ee67461eSJoseph Mingrone 	ndo->ndo_protocol = "aodv";
4828bdc5a62SPatrick Kelsey 	/*
4838bdc5a62SPatrick Kelsey 	 * The message type is the first byte; make sure we have it
4848bdc5a62SPatrick Kelsey 	 * and then fetch it.
4858bdc5a62SPatrick Kelsey 	 */
486*ee67461eSJoseph Mingrone 	msg_type = GET_U_1(dat);
487*ee67461eSJoseph Mingrone 	ND_PRINT(" aodv");
4885b0fe478SBruce M Simpson 
4898bdc5a62SPatrick Kelsey 	switch (msg_type) {
4905b0fe478SBruce M Simpson 
4915b0fe478SBruce M Simpson 	case AODV_RREQ:
4925b0fe478SBruce M Simpson 		if (is_ip6)
4938bdc5a62SPatrick Kelsey 			aodv_v6_rreq(ndo, dat, length);
4945b0fe478SBruce M Simpson 		else
4958bdc5a62SPatrick Kelsey 			aodv_rreq(ndo, dat, length);
4965b0fe478SBruce M Simpson 		break;
4975b0fe478SBruce M Simpson 
4985b0fe478SBruce M Simpson 	case AODV_RREP:
4995b0fe478SBruce M Simpson 		if (is_ip6)
5008bdc5a62SPatrick Kelsey 			aodv_v6_rrep(ndo, dat, length);
5015b0fe478SBruce M Simpson 		else
5028bdc5a62SPatrick Kelsey 			aodv_rrep(ndo, dat, length);
5035b0fe478SBruce M Simpson 		break;
5045b0fe478SBruce M Simpson 
5055b0fe478SBruce M Simpson 	case AODV_RERR:
5065b0fe478SBruce M Simpson 		if (is_ip6)
5078bdc5a62SPatrick Kelsey 			aodv_v6_rerr(ndo, dat, length);
5085b0fe478SBruce M Simpson 		else
5098bdc5a62SPatrick Kelsey 			aodv_rerr(ndo, dat, length);
5105b0fe478SBruce M Simpson 		break;
5115b0fe478SBruce M Simpson 
5125b0fe478SBruce M Simpson 	case AODV_RREP_ACK:
513*ee67461eSJoseph Mingrone 		ND_PRINT(" rrep-ack %u", length);
5145b0fe478SBruce M Simpson 		break;
5155b0fe478SBruce M Simpson 
5165b0fe478SBruce M Simpson 	case AODV_V6_DRAFT_01_RREQ:
5178bdc5a62SPatrick Kelsey 		aodv_v6_draft_01_rreq(ndo, dat, length);
5185b0fe478SBruce M Simpson 		break;
5195b0fe478SBruce M Simpson 
5205b0fe478SBruce M Simpson 	case AODV_V6_DRAFT_01_RREP:
5218bdc5a62SPatrick Kelsey 		aodv_v6_draft_01_rrep(ndo, dat, length);
5225b0fe478SBruce M Simpson 		break;
5235b0fe478SBruce M Simpson 
5245b0fe478SBruce M Simpson 	case AODV_V6_DRAFT_01_RERR:
5258bdc5a62SPatrick Kelsey 		aodv_v6_draft_01_rerr(ndo, dat, length);
5265b0fe478SBruce M Simpson 		break;
5275b0fe478SBruce M Simpson 
5285b0fe478SBruce M Simpson 	case AODV_V6_DRAFT_01_RREP_ACK:
529*ee67461eSJoseph Mingrone 		ND_PRINT(" rrep-ack %u", length);
5305b0fe478SBruce M Simpson 		break;
5315b0fe478SBruce M Simpson 
5325b0fe478SBruce M Simpson 	default:
533*ee67461eSJoseph Mingrone 		ND_PRINT(" type %u %u", msg_type, length);
5345b0fe478SBruce M Simpson 	}
5355b0fe478SBruce M Simpson }
536