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.
34 static const char rcsid
[] _U_
=
35 "@(#) $Header: /tcpdump/master/tcpdump/print-aodv.c,v 1.11 2004-03-24 00:30:19 guy Exp $ (LBL)";
42 #include <tcpdump-stdinc.h>
49 #include "interface.h"
50 #include "addrtoname.h"
51 #include "extract.h" /* must come after interface.h */
55 u_int8_t rreq_type
; /* AODV message type (1) */
56 u_int8_t rreq_flags
; /* various flags */
57 u_int8_t rreq_zero0
; /* reserved, set to zero */
58 u_int8_t rreq_hops
; /* number of hops from originator */
59 u_int32_t rreq_id
; /* request ID */
60 u_int32_t rreq_da
; /* destination IPv4 address */
61 u_int32_t rreq_ds
; /* destination sequence number */
62 u_int32_t rreq_oa
; /* originator IPv4 address */
63 u_int32_t rreq_os
; /* originator sequence number */
67 u_int8_t rreq_type
; /* AODV message type (1) */
68 u_int8_t rreq_flags
; /* various flags */
69 u_int8_t rreq_zero0
; /* reserved, set to zero */
70 u_int8_t rreq_hops
; /* number of hops from originator */
71 u_int32_t rreq_id
; /* request ID */
72 struct in6_addr rreq_da
; /* destination IPv6 address */
73 u_int32_t rreq_ds
; /* destination sequence number */
74 struct in6_addr rreq_oa
; /* originator IPv6 address */
75 u_int32_t rreq_os
; /* originator sequence number */
77 struct aodv_rreq6_draft_01
{
78 u_int8_t rreq_type
; /* AODV message type (16) */
79 u_int8_t rreq_flags
; /* various flags */
80 u_int8_t rreq_zero0
; /* reserved, set to zero */
81 u_int8_t rreq_hops
; /* number of hops from originator */
82 u_int32_t rreq_id
; /* request ID */
83 u_int32_t rreq_ds
; /* destination sequence number */
84 u_int32_t rreq_os
; /* originator sequence number */
85 struct in6_addr rreq_da
; /* destination IPv6 address */
86 struct in6_addr rreq_oa
; /* originator IPv6 address */
90 #define RREQ_JOIN 0x80 /* join (reserved for multicast */
91 #define RREQ_REPAIR 0x40 /* repair (reserved for multicast */
92 #define RREQ_GRAT 0x20 /* gratuitous RREP */
93 #define RREQ_DEST 0x10 /* destination only */
94 #define RREQ_UNKNOWN 0x08 /* unknown destination sequence num */
95 #define RREQ_FLAGS_MASK 0xF8 /* mask for rreq_flags */
98 u_int8_t rrep_type
; /* AODV message type (2) */
99 u_int8_t rrep_flags
; /* various flags */
100 u_int8_t rrep_ps
; /* prefix size */
101 u_int8_t rrep_hops
; /* number of hops from o to d */
102 u_int32_t rrep_da
; /* destination IPv4 address */
103 u_int32_t rrep_ds
; /* destination sequence number */
104 u_int32_t rrep_oa
; /* originator IPv4 address */
105 u_int32_t rrep_life
; /* lifetime of this route */
109 u_int8_t rrep_type
; /* AODV message type (2) */
110 u_int8_t rrep_flags
; /* various flags */
111 u_int8_t rrep_ps
; /* prefix size */
112 u_int8_t rrep_hops
; /* number of hops from o to d */
113 struct in6_addr rrep_da
; /* destination IPv6 address */
114 u_int32_t rrep_ds
; /* destination sequence number */
115 struct in6_addr rrep_oa
; /* originator IPv6 address */
116 u_int32_t rrep_life
; /* lifetime of this route */
118 struct aodv_rrep6_draft_01
{
119 u_int8_t rrep_type
; /* AODV message type (17) */
120 u_int8_t rrep_flags
; /* various flags */
121 u_int8_t rrep_ps
; /* prefix size */
122 u_int8_t rrep_hops
; /* number of hops from o to d */
123 u_int32_t rrep_ds
; /* destination sequence number */
124 struct in6_addr rrep_da
; /* destination IPv6 address */
125 struct in6_addr rrep_oa
; /* originator IPv6 address */
126 u_int32_t rrep_life
; /* lifetime of this route */
130 #define RREP_REPAIR 0x80 /* repair (reserved for multicast */
131 #define RREP_ACK 0x40 /* acknowledgement required */
132 #define RREP_FLAGS_MASK 0xC0 /* mask for rrep_flags */
133 #define RREP_PREFIX_MASK 0x1F /* mask for prefix size */
135 struct rerr_unreach
{
136 u_int32_t u_da
; /* IPv4 address */
137 u_int32_t u_ds
; /* sequence number */
140 struct rerr_unreach6
{
141 struct in6_addr u_da
; /* IPv6 address */
142 u_int32_t u_ds
; /* sequence number */
144 struct rerr_unreach6_draft_01
{
145 struct in6_addr u_da
; /* IPv6 address */
146 u_int32_t u_ds
; /* sequence number */
151 u_int8_t rerr_type
; /* AODV message type (3 or 18) */
152 u_int8_t rerr_flags
; /* various flags */
153 u_int8_t rerr_zero0
; /* reserved, set to zero */
154 u_int8_t rerr_dc
; /* destination count */
156 struct rerr_unreach dest
[1];
158 struct rerr_unreach6 dest6
[1];
159 struct rerr_unreach6_draft_01 dest6_draft_01
[1];
164 #define RERR_NODELETE 0x80 /* don't delete the link */
165 #define RERR_FLAGS_MASK 0x80 /* mask for rerr_flags */
167 struct aodv_rrep_ack
{
173 struct aodv_rreq rreq
;
174 struct aodv_rrep rrep
;
175 struct aodv_rerr rerr
;
176 struct aodv_rrep_ack rrep_ack
;
178 struct aodv_rreq6 rreq6
;
179 struct aodv_rreq6_draft_01 rreq6_draft_01
;
180 struct aodv_rrep6 rrep6
;
181 struct aodv_rrep6_draft_01 rrep6_draft_01
;
185 #define AODV_RREQ 1 /* route request */
186 #define AODV_RREP 2 /* route response */
187 #define AODV_RERR 3 /* error report */
188 #define AODV_RREP_ACK 4 /* route response acknowledgement */
190 #define AODV_V6_DRAFT_01_RREQ 16 /* IPv6 route request */
191 #define AODV_V6_DRAFT_01_RREP 17 /* IPv6 route response */
192 #define AODV_V6_DRAFT_01_RERR 18 /* IPv6 error report */
193 #define AODV_V6_DRAFT_01_RREP_ACK 19 /* IPV6 route response acknowledgment */
196 u_int8_t type
; /* extension type */
197 u_int8_t length
; /* extension length */
201 struct aodv_ext eh
; /* extension header */
202 u_int32_t interval
; /* expect my next hello in
206 #define AODV_EXT_HELLO 1
209 aodv_extension(const struct aodv_ext
*ep
, u_int length
)
212 const struct aodv_hello
*ah
;
216 if (snapend
< (u_char
*) ep
) {
220 i
= min(length
, (u_int
)(snapend
- (u_char
*)ep
));
221 if (i
< sizeof(struct aodv_hello
)) {
225 i
-= sizeof(struct aodv_hello
);
227 printf("\n\text HELLO %ld ms",
228 (unsigned long)EXTRACT_32BITS(&ah
->interval
));
232 printf("\n\text %u %u", ep
->type
, ep
->length
);
238 aodv_rreq(const union aodv
*ap
, const u_char
*dat
, u_int length
)
246 i
= min(length
, (u_int
)(snapend
- dat
));
247 if (i
< sizeof(ap
->rreq
)) {
251 i
-= sizeof(ap
->rreq
);
252 printf(" rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
253 "\tdst %s seq %lu src %s seq %lu", length
,
254 ap
->rreq
.rreq_type
& RREQ_JOIN
? "[J]" : "",
255 ap
->rreq
.rreq_type
& RREQ_REPAIR
? "[R]" : "",
256 ap
->rreq
.rreq_type
& RREQ_GRAT
? "[G]" : "",
257 ap
->rreq
.rreq_type
& RREQ_DEST
? "[D]" : "",
258 ap
->rreq
.rreq_type
& RREQ_UNKNOWN
? "[U] " : " ",
260 (unsigned long)EXTRACT_32BITS(&ap
->rreq
.rreq_id
),
261 ipaddr_string(&ap
->rreq
.rreq_da
),
262 (unsigned long)EXTRACT_32BITS(&ap
->rreq
.rreq_ds
),
263 ipaddr_string(&ap
->rreq
.rreq_oa
),
264 (unsigned long)EXTRACT_32BITS(&ap
->rreq
.rreq_os
));
265 if (i
>= sizeof(struct aodv_ext
))
266 aodv_extension((void *)(&ap
->rreq
+ 1), i
);
270 aodv_rrep(const union aodv
*ap
, const u_char
*dat
, u_int length
)
278 i
= min(length
, (u_int
)(snapend
- dat
));
279 if (i
< sizeof(ap
->rrep
)) {
283 i
-= sizeof(ap
->rrep
);
284 printf(" rrep %u %s%sprefix %u hops %u\n"
285 "\tdst %s dseq %lu src %s %lu ms", length
,
286 ap
->rrep
.rrep_type
& RREP_REPAIR
? "[R]" : "",
287 ap
->rrep
.rrep_type
& RREP_ACK
? "[A] " : " ",
288 ap
->rrep
.rrep_ps
& RREP_PREFIX_MASK
,
290 ipaddr_string(&ap
->rrep
.rrep_da
),
291 (unsigned long)EXTRACT_32BITS(&ap
->rrep
.rrep_ds
),
292 ipaddr_string(&ap
->rrep
.rrep_oa
),
293 (unsigned long)EXTRACT_32BITS(&ap
->rrep
.rrep_life
));
294 if (i
>= sizeof(struct aodv_ext
))
295 aodv_extension((void *)(&ap
->rrep
+ 1), i
);
299 aodv_rerr(const union aodv
*ap
, const u_char
*dat
, u_int length
)
302 const struct rerr_unreach
*dp
= NULL
;
309 i
= min(length
, (u_int
)(snapend
- dat
));
310 if (i
< offsetof(struct aodv_rerr
, r
)) {
314 i
-= offsetof(struct aodv_rerr
, r
);
315 dp
= &ap
->rerr
.r
.dest
[0];
316 n
= ap
->rerr
.rerr_dc
* sizeof(ap
->rerr
.r
.dest
[0]);
317 printf(" rerr %s [items %u] [%u]:",
318 ap
->rerr
.rerr_flags
& RERR_NODELETE
? "[D]" : "",
319 ap
->rerr
.rerr_dc
, length
);
320 trunc
= n
- (i
/sizeof(ap
->rerr
.r
.dest
[0]));
321 for (; i
>= sizeof(ap
->rerr
.r
.dest
[0]);
322 ++dp
, i
-= sizeof(ap
->rerr
.r
.dest
[0])) {
323 printf(" {%s}(%ld)", ipaddr_string(&dp
->u_da
),
324 (unsigned long)EXTRACT_32BITS(&dp
->u_ds
));
332 aodv_v6_rreq(const union aodv
*ap
, const u_char
*dat
, u_int length
)
334 aodv_v6_rreq(const union aodv
*ap _U_
, const u_char
*dat _U_
, u_int length
)
344 i
= min(length
, (u_int
)(snapend
- dat
));
345 if (i
< sizeof(ap
->rreq6
)) {
349 i
-= sizeof(ap
->rreq6
);
350 printf(" v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
351 "\tdst %s seq %lu src %s seq %lu", length
,
352 ap
->rreq6
.rreq_type
& RREQ_JOIN
? "[J]" : "",
353 ap
->rreq6
.rreq_type
& RREQ_REPAIR
? "[R]" : "",
354 ap
->rreq6
.rreq_type
& RREQ_GRAT
? "[G]" : "",
355 ap
->rreq6
.rreq_type
& RREQ_DEST
? "[D]" : "",
356 ap
->rreq6
.rreq_type
& RREQ_UNKNOWN
? "[U] " : " ",
358 (unsigned long)EXTRACT_32BITS(&ap
->rreq6
.rreq_id
),
359 ip6addr_string(&ap
->rreq6
.rreq_da
),
360 (unsigned long)EXTRACT_32BITS(&ap
->rreq6
.rreq_ds
),
361 ip6addr_string(&ap
->rreq6
.rreq_oa
),
362 (unsigned long)EXTRACT_32BITS(&ap
->rreq6
.rreq_os
));
363 if (i
>= sizeof(struct aodv_ext
))
364 aodv_extension((void *)(&ap
->rreq6
+ 1), i
);
366 printf(" v6 rreq %u", length
);
372 aodv_v6_rrep(const union aodv
*ap
, const u_char
*dat
, u_int length
)
374 aodv_v6_rrep(const union aodv
*ap _U_
, const u_char
*dat _U_
, u_int length
)
384 i
= min(length
, (u_int
)(snapend
- dat
));
385 if (i
< sizeof(ap
->rrep6
)) {
389 i
-= sizeof(ap
->rrep6
);
390 printf(" rrep %u %s%sprefix %u hops %u\n"
391 "\tdst %s dseq %lu src %s %lu ms", length
,
392 ap
->rrep6
.rrep_type
& RREP_REPAIR
? "[R]" : "",
393 ap
->rrep6
.rrep_type
& RREP_ACK
? "[A] " : " ",
394 ap
->rrep6
.rrep_ps
& RREP_PREFIX_MASK
,
396 ip6addr_string(&ap
->rrep6
.rrep_da
),
397 (unsigned long)EXTRACT_32BITS(&ap
->rrep6
.rrep_ds
),
398 ip6addr_string(&ap
->rrep6
.rrep_oa
),
399 (unsigned long)EXTRACT_32BITS(&ap
->rrep6
.rrep_life
));
400 if (i
>= sizeof(struct aodv_ext
))
401 aodv_extension((void *)(&ap
->rrep6
+ 1), i
);
403 printf(" rrep %u", length
);
409 aodv_v6_rerr(const union aodv
*ap
, u_int length
)
411 aodv_v6_rerr(const union aodv
*ap _U_
, u_int length
)
415 const struct rerr_unreach6
*dp6
= NULL
;
418 i
= length
- offsetof(struct aodv_rerr
, r
);
419 j
= sizeof(ap
->rerr
.r
.dest6
[0]);
420 dp6
= &ap
->rerr
.r
.dest6
[0];
421 n
= ap
->rerr
.rerr_dc
* j
;
422 printf(" rerr %s [items %u] [%u]:",
423 ap
->rerr
.rerr_flags
& RERR_NODELETE
? "[D]" : "",
424 ap
->rerr
.rerr_dc
, length
);
426 for (; i
-= j
>= 0; ++dp6
) {
427 printf(" {%s}(%ld)", ip6addr_string(&dp6
->u_da
),
428 (unsigned long)EXTRACT_32BITS(&dp6
->u_ds
));
433 printf(" rerr %u", length
);
439 aodv_v6_draft_01_rreq(const union aodv
*ap
, const u_char
*dat
, u_int length
)
441 aodv_v6_draft_01_rreq(const union aodv
*ap _U_
, const u_char
*dat _U_
,
452 i
= min(length
, (u_int
)(snapend
- dat
));
453 if (i
< sizeof(ap
->rreq6_draft_01
)) {
457 i
-= sizeof(ap
->rreq6_draft_01
);
458 printf(" rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
459 "\tdst %s seq %lu src %s seq %lu", length
,
460 ap
->rreq6_draft_01
.rreq_type
& RREQ_JOIN
? "[J]" : "",
461 ap
->rreq6_draft_01
.rreq_type
& RREQ_REPAIR
? "[R]" : "",
462 ap
->rreq6_draft_01
.rreq_type
& RREQ_GRAT
? "[G]" : "",
463 ap
->rreq6_draft_01
.rreq_type
& RREQ_DEST
? "[D]" : "",
464 ap
->rreq6_draft_01
.rreq_type
& RREQ_UNKNOWN
? "[U] " : " ",
465 ap
->rreq6_draft_01
.rreq_hops
,
466 (unsigned long)EXTRACT_32BITS(&ap
->rreq6_draft_01
.rreq_id
),
467 ip6addr_string(&ap
->rreq6_draft_01
.rreq_da
),
468 (unsigned long)EXTRACT_32BITS(&ap
->rreq6_draft_01
.rreq_ds
),
469 ip6addr_string(&ap
->rreq6_draft_01
.rreq_oa
),
470 (unsigned long)EXTRACT_32BITS(&ap
->rreq6_draft_01
.rreq_os
));
471 if (i
>= sizeof(struct aodv_ext
))
472 aodv_extension((void *)(&ap
->rreq6_draft_01
+ 1), i
);
474 printf(" rreq %u", length
);
480 aodv_v6_draft_01_rrep(const union aodv
*ap
, const u_char
*dat
, u_int length
)
482 aodv_v6_draft_01_rrep(const union aodv
*ap _U_
, const u_char
*dat _U_
,
493 i
= min(length
, (u_int
)(snapend
- dat
));
494 if (i
< sizeof(ap
->rrep6_draft_01
)) {
498 i
-= sizeof(ap
->rrep6_draft_01
);
499 printf(" rrep %u %s%sprefix %u hops %u\n"
500 "\tdst %s dseq %lu src %s %lu ms", length
,
501 ap
->rrep6_draft_01
.rrep_type
& RREP_REPAIR
? "[R]" : "",
502 ap
->rrep6_draft_01
.rrep_type
& RREP_ACK
? "[A] " : " ",
503 ap
->rrep6_draft_01
.rrep_ps
& RREP_PREFIX_MASK
,
504 ap
->rrep6_draft_01
.rrep_hops
,
505 ip6addr_string(&ap
->rrep6_draft_01
.rrep_da
),
506 (unsigned long)EXTRACT_32BITS(&ap
->rrep6_draft_01
.rrep_ds
),
507 ip6addr_string(&ap
->rrep6_draft_01
.rrep_oa
),
508 (unsigned long)EXTRACT_32BITS(&ap
->rrep6_draft_01
.rrep_life
));
509 if (i
>= sizeof(struct aodv_ext
))
510 aodv_extension((void *)(&ap
->rrep6_draft_01
+ 1), i
);
512 printf(" rrep %u", length
);
518 aodv_v6_draft_01_rerr(const union aodv
*ap
, u_int length
)
520 aodv_v6_draft_01_rerr(const union aodv
*ap _U_
, u_int length
)
524 const struct rerr_unreach6_draft_01
*dp6
= NULL
;
527 i
= length
- offsetof(struct aodv_rerr
, r
);
528 j
= sizeof(ap
->rerr
.r
.dest6_draft_01
[0]);
529 dp6
= &ap
->rerr
.r
.dest6_draft_01
[0];
530 n
= ap
->rerr
.rerr_dc
* j
;
531 printf(" rerr %s [items %u] [%u]:",
532 ap
->rerr
.rerr_flags
& RERR_NODELETE
? "[D]" : "",
533 ap
->rerr
.rerr_dc
, length
);
535 for (; i
-= j
>= 0; ++dp6
) {
536 printf(" {%s}(%ld)", ip6addr_string(&dp6
->u_da
),
537 (unsigned long)EXTRACT_32BITS(&dp6
->u_ds
));
542 printf(" rerr %u", length
);
547 aodv_print(const u_char
*dat
, u_int length
, int is_ip6
)
549 const union aodv
*ap
;
551 ap
= (union aodv
*)dat
;
556 if (min(length
, (u_int
)(snapend
- dat
)) < sizeof(ap
->rrep_ack
)) {
562 switch (ap
->rerr
.rerr_type
) {
566 aodv_v6_rreq(ap
, dat
, length
);
568 aodv_rreq(ap
, dat
, length
);
573 aodv_v6_rrep(ap
, dat
, length
);
575 aodv_rrep(ap
, dat
, length
);
580 aodv_v6_rerr(ap
, length
);
582 aodv_rerr(ap
, dat
, length
);
586 printf(" rrep-ack %u", length
);
589 case AODV_V6_DRAFT_01_RREQ
:
590 aodv_v6_draft_01_rreq(ap
, dat
, length
);
593 case AODV_V6_DRAFT_01_RREP
:
594 aodv_v6_draft_01_rrep(ap
, dat
, length
);
597 case AODV_V6_DRAFT_01_RERR
:
598 aodv_v6_draft_01_rerr(ap
, length
);
601 case AODV_V6_DRAFT_01_RREP_ACK
:
602 printf(" rrep-ack %u", length
);
606 printf(" %u %u", ap
->rreq
.rreq_type
, length
);