2 * Copyright (c) 2003 Bruce M. Simpson <bms@spc.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Bruce M. Simpson.
16 * 4. Neither the name of Bruce M. Simpson nor the names of co-
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY Bruce M. Simpson AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Bruce M. Simpson OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
35 __RCSID("$NetBSD: print-aodv.c,v 1.5 2015/03/31 21:59:35 christos Exp $");
38 #define NETDISSECT_REWORKED
43 #include <tcpdump-stdinc.h>
45 #include "interface.h"
46 #include "addrtoname.h"
47 #include "extract.h" /* must come after interface.h */
51 uint8_t rreq_type
; /* AODV message type (1) */
52 uint8_t rreq_flags
; /* various flags */
53 uint8_t rreq_zero0
; /* reserved, set to zero */
54 uint8_t rreq_hops
; /* number of hops from originator */
55 uint32_t rreq_id
; /* request ID */
56 uint32_t rreq_da
; /* destination IPv4 address */
57 uint32_t rreq_ds
; /* destination sequence number */
58 uint32_t rreq_oa
; /* originator IPv4 address */
59 uint32_t rreq_os
; /* originator sequence number */
63 uint8_t rreq_type
; /* AODV message type (1) */
64 uint8_t rreq_flags
; /* various flags */
65 uint8_t rreq_zero0
; /* reserved, set to zero */
66 uint8_t rreq_hops
; /* number of hops from originator */
67 uint32_t rreq_id
; /* request ID */
68 struct in6_addr rreq_da
; /* destination IPv6 address */
69 uint32_t rreq_ds
; /* destination sequence number */
70 struct in6_addr rreq_oa
; /* originator IPv6 address */
71 uint32_t rreq_os
; /* originator sequence number */
73 struct aodv_rreq6_draft_01
{
74 uint8_t rreq_type
; /* AODV message type (16) */
75 uint8_t rreq_flags
; /* various flags */
76 uint8_t rreq_zero0
; /* reserved, set to zero */
77 uint8_t rreq_hops
; /* number of hops from originator */
78 uint32_t rreq_id
; /* request ID */
79 uint32_t rreq_ds
; /* destination sequence number */
80 uint32_t rreq_os
; /* originator sequence number */
81 struct in6_addr rreq_da
; /* destination IPv6 address */
82 struct in6_addr rreq_oa
; /* originator IPv6 address */
86 #define RREQ_JOIN 0x80 /* join (reserved for multicast */
87 #define RREQ_REPAIR 0x40 /* repair (reserved for multicast */
88 #define RREQ_GRAT 0x20 /* gratuitous RREP */
89 #define RREQ_DEST 0x10 /* destination only */
90 #define RREQ_UNKNOWN 0x08 /* unknown destination sequence num */
91 #define RREQ_FLAGS_MASK 0xF8 /* mask for rreq_flags */
94 uint8_t rrep_type
; /* AODV message type (2) */
95 uint8_t rrep_flags
; /* various flags */
96 uint8_t rrep_ps
; /* prefix size */
97 uint8_t rrep_hops
; /* number of hops from o to d */
98 uint32_t rrep_da
; /* destination IPv4 address */
99 uint32_t rrep_ds
; /* destination sequence number */
100 uint32_t rrep_oa
; /* originator IPv4 address */
101 uint32_t rrep_life
; /* lifetime of this route */
105 uint8_t rrep_type
; /* AODV message type (2) */
106 uint8_t rrep_flags
; /* various flags */
107 uint8_t rrep_ps
; /* prefix size */
108 uint8_t rrep_hops
; /* number of hops from o to d */
109 struct in6_addr rrep_da
; /* destination IPv6 address */
110 uint32_t rrep_ds
; /* destination sequence number */
111 struct in6_addr rrep_oa
; /* originator IPv6 address */
112 uint32_t rrep_life
; /* lifetime of this route */
114 struct aodv_rrep6_draft_01
{
115 uint8_t rrep_type
; /* AODV message type (17) */
116 uint8_t rrep_flags
; /* various flags */
117 uint8_t rrep_ps
; /* prefix size */
118 uint8_t rrep_hops
; /* number of hops from o to d */
119 uint32_t rrep_ds
; /* destination sequence number */
120 struct in6_addr rrep_da
; /* destination IPv6 address */
121 struct in6_addr rrep_oa
; /* originator IPv6 address */
122 uint32_t rrep_life
; /* lifetime of this route */
126 #define RREP_REPAIR 0x80 /* repair (reserved for multicast */
127 #define RREP_ACK 0x40 /* acknowledgement required */
128 #define RREP_FLAGS_MASK 0xC0 /* mask for rrep_flags */
129 #define RREP_PREFIX_MASK 0x1F /* mask for prefix size */
131 struct rerr_unreach
{
132 uint32_t u_da
; /* IPv4 address */
133 uint32_t u_ds
; /* sequence number */
136 struct rerr_unreach6
{
137 struct in6_addr u_da
; /* IPv6 address */
138 uint32_t u_ds
; /* sequence number */
140 struct rerr_unreach6_draft_01
{
141 struct in6_addr u_da
; /* IPv6 address */
142 uint32_t u_ds
; /* sequence number */
147 uint8_t rerr_type
; /* AODV message type (3 or 18) */
148 uint8_t rerr_flags
; /* various flags */
149 uint8_t rerr_zero0
; /* reserved, set to zero */
150 uint8_t rerr_dc
; /* destination count */
153 #define RERR_NODELETE 0x80 /* don't delete the link */
154 #define RERR_FLAGS_MASK 0x80 /* mask for rerr_flags */
156 struct aodv_rrep_ack
{
161 #define AODV_RREQ 1 /* route request */
162 #define AODV_RREP 2 /* route response */
163 #define AODV_RERR 3 /* error report */
164 #define AODV_RREP_ACK 4 /* route response acknowledgement */
166 #define AODV_V6_DRAFT_01_RREQ 16 /* IPv6 route request */
167 #define AODV_V6_DRAFT_01_RREP 17 /* IPv6 route response */
168 #define AODV_V6_DRAFT_01_RERR 18 /* IPv6 error report */
169 #define AODV_V6_DRAFT_01_RREP_ACK 19 /* IPV6 route response acknowledgment */
172 uint8_t type
; /* extension type */
173 uint8_t length
; /* extension length */
177 struct aodv_ext eh
; /* extension header */
178 uint8_t interval
[4]; /* expect my next hello in
180 * NOTE: this is not aligned */
183 #define AODV_EXT_HELLO 1
186 aodv_extension(netdissect_options
*ndo
,
187 const struct aodv_ext
*ep
, u_int length
)
189 const struct aodv_hello
*ah
;
193 ah
= (const struct aodv_hello
*)(const void *)ep
;
195 if (length
< sizeof(struct aodv_hello
))
197 ND_PRINT((ndo
, "\n\text HELLO %ld ms",
198 (unsigned long)EXTRACT_32BITS(&ah
->interval
)));
202 ND_PRINT((ndo
, "\n\text %u %u", ep
->type
, ep
->length
));
208 ND_PRINT((ndo
, " [|hello]"));
212 aodv_rreq(netdissect_options
*ndo
, const u_char
*dat
, u_int length
)
215 const struct aodv_rreq
*ap
= (const struct aodv_rreq
*)dat
;
218 if (length
< sizeof(*ap
))
220 ND_PRINT((ndo
, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
221 "\tdst %s seq %lu src %s seq %lu", length
,
222 ap
->rreq_type
& RREQ_JOIN
? "[J]" : "",
223 ap
->rreq_type
& RREQ_REPAIR
? "[R]" : "",
224 ap
->rreq_type
& RREQ_GRAT
? "[G]" : "",
225 ap
->rreq_type
& RREQ_DEST
? "[D]" : "",
226 ap
->rreq_type
& RREQ_UNKNOWN
? "[U] " : " ",
228 (unsigned long)EXTRACT_32BITS(&ap
->rreq_id
),
229 ipaddr_string(ndo
, &ap
->rreq_da
),
230 (unsigned long)EXTRACT_32BITS(&ap
->rreq_ds
),
231 ipaddr_string(ndo
, &ap
->rreq_oa
),
232 (unsigned long)EXTRACT_32BITS(&ap
->rreq_os
)));
233 i
= length
- sizeof(*ap
);
234 if (i
>= sizeof(struct aodv_ext
))
235 aodv_extension(ndo
, (const struct aodv_ext
*)(dat
+ sizeof(*ap
)), i
);
239 ND_PRINT((ndo
, " [|rreq"));
243 aodv_rrep(netdissect_options
*ndo
, const u_char
*dat
, u_int length
)
246 const struct aodv_rrep
*ap
= (const struct aodv_rrep
*)dat
;
249 if (length
< sizeof(*ap
))
251 ND_PRINT((ndo
, " rrep %u %s%sprefix %u hops %u\n"
252 "\tdst %s dseq %lu src %s %lu ms", length
,
253 ap
->rrep_type
& RREP_REPAIR
? "[R]" : "",
254 ap
->rrep_type
& RREP_ACK
? "[A] " : " ",
255 ap
->rrep_ps
& RREP_PREFIX_MASK
,
257 ipaddr_string(ndo
, &ap
->rrep_da
),
258 (unsigned long)EXTRACT_32BITS(&ap
->rrep_ds
),
259 ipaddr_string(ndo
, &ap
->rrep_oa
),
260 (unsigned long)EXTRACT_32BITS(&ap
->rrep_life
)));
261 i
= length
- sizeof(*ap
);
262 if (i
>= sizeof(struct aodv_ext
))
263 aodv_extension(ndo
, (const struct aodv_ext
*)(dat
+ sizeof(*ap
)), i
);
267 ND_PRINT((ndo
, " [|rreq"));
271 aodv_rerr(netdissect_options
*ndo
, const u_char
*dat
, u_int length
)
274 const struct aodv_rerr
*ap
= (const struct aodv_rerr
*)dat
;
275 const struct rerr_unreach
*dp
;
278 if (length
< sizeof(*ap
))
280 ND_PRINT((ndo
, " rerr %s [items %u] [%u]:",
281 ap
->rerr_flags
& RERR_NODELETE
? "[D]" : "",
282 ap
->rerr_dc
, length
));
283 dp
= (struct rerr_unreach
*)(dat
+ sizeof(*ap
));
284 i
= length
- sizeof(*ap
);
285 for (dc
= ap
->rerr_dc
; dc
!= 0; dc
--) {
289 ND_PRINT((ndo
, " {%s}(%ld)", ipaddr_string(ndo
, &dp
->u_da
),
290 (unsigned long)EXTRACT_32BITS(&dp
->u_ds
)));
297 ND_PRINT((ndo
, "[|rerr]"));
302 aodv_v6_rreq(netdissect_options
*ndo
, const u_char
*dat
, u_int length
)
304 aodv_v6_rreq(netdissect_options
*ndo
, const u_char
*dat _U_
, u_int length
)
309 const struct aodv_rreq6
*ap
= (const struct aodv_rreq6
*)dat
;
312 if (length
< sizeof(*ap
))
314 ND_PRINT((ndo
, " v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
315 "\tdst %s seq %lu src %s seq %lu", length
,
316 ap
->rreq_type
& RREQ_JOIN
? "[J]" : "",
317 ap
->rreq_type
& RREQ_REPAIR
? "[R]" : "",
318 ap
->rreq_type
& RREQ_GRAT
? "[G]" : "",
319 ap
->rreq_type
& RREQ_DEST
? "[D]" : "",
320 ap
->rreq_type
& RREQ_UNKNOWN
? "[U] " : " ",
322 (unsigned long)EXTRACT_32BITS(&ap
->rreq_id
),
323 ip6addr_string(ndo
, &ap
->rreq_da
),
324 (unsigned long)EXTRACT_32BITS(&ap
->rreq_ds
),
325 ip6addr_string(ndo
, &ap
->rreq_oa
),
326 (unsigned long)EXTRACT_32BITS(&ap
->rreq_os
)));
327 i
= length
- sizeof(*ap
);
328 if (i
>= sizeof(struct aodv_ext
))
329 aodv_extension(ndo
, (const struct aodv_ext
*)(dat
+ sizeof(*ap
)), i
);
333 ND_PRINT((ndo
, " [|rreq"));
335 ND_PRINT((ndo
, " v6 rreq %u", length
));
341 aodv_v6_rrep(netdissect_options
*ndo
, const u_char
*dat
, u_int length
)
343 aodv_v6_rrep(netdissect_options
*ndo
, const u_char
*dat _U_
, u_int length
)
348 const struct aodv_rrep6
*ap
= (const struct aodv_rrep6
*)dat
;
351 if (length
< sizeof(*ap
))
353 ND_PRINT((ndo
, " rrep %u %s%sprefix %u hops %u\n"
354 "\tdst %s dseq %lu src %s %lu ms", length
,
355 ap
->rrep_type
& RREP_REPAIR
? "[R]" : "",
356 ap
->rrep_type
& RREP_ACK
? "[A] " : " ",
357 ap
->rrep_ps
& RREP_PREFIX_MASK
,
359 ip6addr_string(ndo
, &ap
->rrep_da
),
360 (unsigned long)EXTRACT_32BITS(&ap
->rrep_ds
),
361 ip6addr_string(ndo
, &ap
->rrep_oa
),
362 (unsigned long)EXTRACT_32BITS(&ap
->rrep_life
)));
363 i
= length
- sizeof(*ap
);
364 if (i
>= sizeof(struct aodv_ext
))
365 aodv_extension(ndo
, (const struct aodv_ext
*)(dat
+ sizeof(*ap
)), i
);
369 ND_PRINT((ndo
, " [|rreq"));
371 ND_PRINT((ndo
, " rrep %u", length
));
377 aodv_v6_rerr(netdissect_options
*ndo
, const u_char
*dat
, u_int length
)
379 aodv_v6_rerr(netdissect_options
*ndo
, const u_char
*dat _U_
, u_int length
)
384 const struct aodv_rerr
*ap
= (const struct aodv_rerr
*)dat
;
385 const struct rerr_unreach6
*dp6
;
388 if (length
< sizeof(*ap
))
390 ND_PRINT((ndo
, " rerr %s [items %u] [%u]:",
391 ap
->rerr_flags
& RERR_NODELETE
? "[D]" : "",
392 ap
->rerr_dc
, length
));
393 dp6
= (struct rerr_unreach6
*)(void *)(ap
+ 1);
394 i
= length
- sizeof(*ap
);
395 for (dc
= ap
->rerr_dc
; dc
!= 0; dc
--) {
397 if (i
< sizeof(*dp6
))
399 ND_PRINT((ndo
, " {%s}(%ld)", ip6addr_string(ndo
, &dp6
->u_da
),
400 (unsigned long)EXTRACT_32BITS(&dp6
->u_ds
)));
407 ND_PRINT((ndo
, "[|rerr]"));
409 ND_PRINT((ndo
, " rerr %u", length
));
415 aodv_v6_draft_01_rreq(netdissect_options
*ndo
, const u_char
*dat
, u_int length
)
417 aodv_v6_draft_01_rreq(netdissect_options
*ndo
, const u_char
*dat _U_
, u_int length
)
422 const struct aodv_rreq6_draft_01
*ap
= (const struct aodv_rreq6_draft_01
*)dat
;
425 if (length
< sizeof(*ap
))
427 ND_PRINT((ndo
, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
428 "\tdst %s seq %lu src %s seq %lu", length
,
429 ap
->rreq_type
& RREQ_JOIN
? "[J]" : "",
430 ap
->rreq_type
& RREQ_REPAIR
? "[R]" : "",
431 ap
->rreq_type
& RREQ_GRAT
? "[G]" : "",
432 ap
->rreq_type
& RREQ_DEST
? "[D]" : "",
433 ap
->rreq_type
& RREQ_UNKNOWN
? "[U] " : " ",
435 (unsigned long)EXTRACT_32BITS(&ap
->rreq_id
),
436 ip6addr_string(ndo
, &ap
->rreq_da
),
437 (unsigned long)EXTRACT_32BITS(&ap
->rreq_ds
),
438 ip6addr_string(ndo
, &ap
->rreq_oa
),
439 (unsigned long)EXTRACT_32BITS(&ap
->rreq_os
)));
440 i
= length
- sizeof(*ap
);
441 if (i
>= sizeof(struct aodv_ext
))
442 aodv_extension(ndo
, (const struct aodv_ext
*)(dat
+ sizeof(*ap
)), i
);
446 ND_PRINT((ndo
, " [|rreq"));
448 ND_PRINT((ndo
, " rreq %u", length
));
454 aodv_v6_draft_01_rrep(netdissect_options
*ndo
, const u_char
*dat
, u_int length
)
456 aodv_v6_draft_01_rrep(netdissect_options
*ndo
, const u_char
*dat _U_
, u_int length
)
461 const struct aodv_rrep6_draft_01
*ap
= (const struct aodv_rrep6_draft_01
*)dat
;
464 if (length
< sizeof(*ap
))
466 ND_PRINT((ndo
, " rrep %u %s%sprefix %u hops %u\n"
467 "\tdst %s dseq %lu src %s %lu ms", length
,
468 ap
->rrep_type
& RREP_REPAIR
? "[R]" : "",
469 ap
->rrep_type
& RREP_ACK
? "[A] " : " ",
470 ap
->rrep_ps
& RREP_PREFIX_MASK
,
472 ip6addr_string(ndo
, &ap
->rrep_da
),
473 (unsigned long)EXTRACT_32BITS(&ap
->rrep_ds
),
474 ip6addr_string(ndo
, &ap
->rrep_oa
),
475 (unsigned long)EXTRACT_32BITS(&ap
->rrep_life
)));
476 i
= length
- sizeof(*ap
);
477 if (i
>= sizeof(struct aodv_ext
))
478 aodv_extension(ndo
, (const struct aodv_ext
*)(dat
+ sizeof(*ap
)), i
);
482 ND_PRINT((ndo
, " [|rreq"));
484 ND_PRINT((ndo
, " rrep %u", length
));
490 aodv_v6_draft_01_rerr(netdissect_options
*ndo
, const u_char
*dat
, u_int length
)
492 aodv_v6_draft_01_rerr(netdissect_options
*ndo
, const u_char
*dat _U_
, u_int length
)
497 const struct aodv_rerr
*ap
= (const struct aodv_rerr
*)dat
;
498 const struct rerr_unreach6_draft_01
*dp6
;
501 if (length
< sizeof(*ap
))
503 ND_PRINT((ndo
, " rerr %s [items %u] [%u]:",
504 ap
->rerr_flags
& RERR_NODELETE
? "[D]" : "",
505 ap
->rerr_dc
, length
));
506 dp6
= (struct rerr_unreach6_draft_01
*)(void *)(ap
+ 1);
507 i
= length
- sizeof(*ap
);
508 for (dc
= ap
->rerr_dc
; dc
!= 0; dc
--) {
510 if (i
< sizeof(*dp6
))
512 ND_PRINT((ndo
, " {%s}(%ld)", ip6addr_string(ndo
, &dp6
->u_da
),
513 (unsigned long)EXTRACT_32BITS(&dp6
->u_ds
)));
520 ND_PRINT((ndo
, "[|rerr]"));
522 ND_PRINT((ndo
, " rerr %u", length
));
527 aodv_print(netdissect_options
*ndo
,
528 const u_char
*dat
, u_int length
, int is_ip6
)
533 * The message type is the first byte; make sure we have it
538 ND_PRINT((ndo
, " aodv"));
544 aodv_v6_rreq(ndo
, dat
, length
);
546 aodv_rreq(ndo
, dat
, length
);
551 aodv_v6_rrep(ndo
, dat
, length
);
553 aodv_rrep(ndo
, dat
, length
);
558 aodv_v6_rerr(ndo
, dat
, length
);
560 aodv_rerr(ndo
, dat
, length
);
564 ND_PRINT((ndo
, " rrep-ack %u", length
));
567 case AODV_V6_DRAFT_01_RREQ
:
568 aodv_v6_draft_01_rreq(ndo
, dat
, length
);
571 case AODV_V6_DRAFT_01_RREP
:
572 aodv_v6_draft_01_rrep(ndo
, dat
, length
);
575 case AODV_V6_DRAFT_01_RERR
:
576 aodv_v6_draft_01_rerr(ndo
, dat
, length
);
579 case AODV_V6_DRAFT_01_RREP_ACK
:
580 ND_PRINT((ndo
, " rrep-ack %u", length
));
584 ND_PRINT((ndo
, " type %u %u", msg_type
, length
));
589 ND_PRINT((ndo
, " [|aodv]"));