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