2 * Routines for AODV dissection
3 * Copyright 2000, Erik Nordstrom <erik.nordstrom@it.uu.se>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 #include <epan/packet.h>
35 #include <epan/to_str.h>
38 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
44 * RFC 3561 (which indicates that, for IPv6, the only change is that
45 * the address fields are enlarged)
47 * http://www.cs.ucsb.edu/~ebelding/txt/aodv6.txt
49 * http://www.tcs.hut.fi/~anttit/manet/drafts/draft-perkins-aodv6-01.txt
51 * (both of the above two are draft-perkins-manet-aodv6-01.txt, which
52 * is from November 2000)
54 void proto_register_aodv(void);
55 void proto_reg_handoff_aodv(void);
57 #define INET6_ADDRLEN 16
58 #define UDP_PORT_AODV 654
65 #define DRAFT_01_V6_RREQ 16
66 #define DRAFT_01_V6_RREP 17
67 #define DRAFT_01_V6_RERR 18
68 #define DRAFT_01_V6_RREP_ACK 19
72 #define AODV_EXT_INT 2
73 #define AODV_EXT_NTP 3
76 #define RREQ_UNKNSEQ 0x08
77 #define RREQ_DESTONLY 0x10
78 #define RREQ_GRATRREP 0x20
80 #define RREQ_JOIN 0x80
82 #define RREP_ACK_REQ 0x40
85 #define RERR_NODEL 0x80
87 static const value_string type_vals
[] = {
88 { RREQ
, "Route Request" },
89 { RREP
, "Route Reply" },
90 { RERR
, "Route Error" },
91 { RREP_ACK
, "Route Reply Acknowledgment"},
92 { DRAFT_01_V6_RREQ
, "draft-perkins-manet-aodv6-01 IPv6 Route Request"},
93 { DRAFT_01_V6_RREP
, "draft-perkins-manet-aodv6-01 IPv6 Route Reply"},
94 { DRAFT_01_V6_RERR
, "draft-perkins-manet-aodv6-01 IPv6 Route Error"},
95 { DRAFT_01_V6_RREP_ACK
, "draft-perkins-manet-aodv6-01 IPv6 Route Reply Acknowledgment"},
99 static const value_string exttype_vals
[] = {
101 { AODV_EXT_INT
, "Hello Interval"},
102 { AODV_EXT_NTP
, "Timestamp"},
106 typedef struct v6_ext
{
111 /* Initialize the protocol and registered fields */
112 static int proto_aodv
= -1;
113 static int hf_aodv_type
= -1;
114 /* static int hf_aodv_flags = -1; */
115 static int hf_aodv_prefix_sz
= -1;
116 static int hf_aodv_hopcount
= -1;
117 static int hf_aodv_rreq_id
= -1;
118 static int hf_aodv_dest_ip
= -1;
119 static int hf_aodv_dest_ipv6
= -1;
120 static int hf_aodv_dest_seqno
= -1;
121 static int hf_aodv_orig_ip
= -1;
122 static int hf_aodv_orig_ipv6
= -1;
123 static int hf_aodv_orig_seqno
= -1;
124 static int hf_aodv_lifetime
= -1;
125 static int hf_aodv_destcount
= -1;
126 static int hf_aodv_unreach_dest_ip
= -1;
127 static int hf_aodv_unreach_dest_ipv6
= -1;
128 /* static int hf_aodv_unreach_dest_seqno = -1; */
129 static int hf_aodv_flags_rreq_join
= -1;
130 static int hf_aodv_flags_rreq_repair
= -1;
131 static int hf_aodv_flags_rreq_gratuitous
= -1;
132 static int hf_aodv_flags_rreq_destinationonly
= -1;
133 static int hf_aodv_flags_rreq_unknown
= -1;
134 static int hf_aodv_flags_rrep_repair
= -1;
135 static int hf_aodv_flags_rrep_ack
= -1;
136 static int hf_aodv_flags_rerr_nodelete
= -1;
137 /* static int hf_aodv_ext_type = -1; */
138 /* static int hf_aodv_ext_length = -1; */
139 static int hf_aodv_ext_interval
= -1;
140 static int hf_aodv_ext_timestamp
= -1;
142 /* Initialize the subtree pointers */
143 static gint ett_aodv
= -1;
144 static gint ett_aodv_flags
= -1;
145 static gint ett_aodv_unreach_dest
= -1;
146 static gint ett_aodv_extensions
= -1;
148 /* Code to actually dissect the packets */
151 dissect_aodv_ext(tvbuff_t
* tvb
, int offset
, proto_tree
* tree
)
153 proto_tree
*ext_tree
;
161 if ((int) tvb_reported_length(tvb
) <= offset
)
162 return; /* No more options left */
164 type
= tvb_get_guint8(tvb
, offset
);
165 len
= tvb_get_guint8(tvb
, offset
+ 1);
167 ti
= proto_tree_add_text(tree
, tvb
, offset
, 2 + len
, "Extensions");
168 ext_tree
= proto_item_add_subtree(ti
, ett_aodv_extensions
);
170 proto_tree_add_text(ext_tree
, tvb
, offset
, 1,
171 "Type: %u (%s)", type
,
172 val_to_str_const(type
, exttype_vals
, "Unknown"));
175 proto_tree_add_text(ext_tree
, tvb
, offset
+ 1, 1,
176 "Invalid option length: %u", len
);
177 return; /* we must not try to decode this */
179 proto_tree_add_text(ext_tree
, tvb
, offset
+ 1, 1,
180 "Length: %u bytes", len
);
186 proto_tree_add_uint(ext_tree
, hf_aodv_ext_interval
,
187 tvb
, offset
, 4, tvb_get_ntohl(tvb
, offset
));
190 proto_tree_add_item(ext_tree
, hf_aodv_ext_timestamp
,
191 tvb
, offset
, 8, ENC_BIG_ENDIAN
);
196 /* If multifield extensions appear, we need more
197 * sophisticated handler. For now, this is okay. */
204 dissect_aodv_rreq(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*aodv_tree
,
205 proto_item
*ti
, gboolean is_ipv6
)
209 proto_tree
*aodv_flags_tree
;
213 guint32 dest_addr_v4
;
214 struct e_in6_addr dest_addr_v6
;
216 guint32 orig_addr_v4
;
217 struct e_in6_addr orig_addr_v6
;
221 flags
= tvb_get_guint8(tvb
, offset
);
223 tj
= proto_tree_add_text(aodv_tree
, tvb
, offset
, 1, "Flags:");
224 aodv_flags_tree
= proto_item_add_subtree(tj
, ett_aodv_flags
);
225 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rreq_join
,
226 tvb
, offset
, 1, flags
);
227 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rreq_repair
,
228 tvb
, offset
, 1, flags
);
229 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rreq_gratuitous
,
230 tvb
, offset
, 1, flags
);
231 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rreq_destinationonly
,
232 tvb
, offset
, 1, flags
);
233 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rreq_unknown
,
234 tvb
, offset
, 1, flags
);
235 if (flags
& RREQ_JOIN
)
236 proto_item_append_text(tj
, " J");
237 if (flags
& RREQ_REP
)
238 proto_item_append_text(tj
, " R");
239 if (flags
& RREQ_GRATRREP
)
240 proto_item_append_text(tj
, " G");
241 if (flags
& RREQ_DESTONLY
)
242 proto_item_append_text(tj
, " D");
243 if (flags
& RREQ_UNKNSEQ
)
244 proto_item_append_text(tj
, " U");
246 offset
+= 2; /* skip reserved byte */
248 hop_count
= tvb_get_guint8(tvb
, offset
);
250 proto_tree_add_uint(aodv_tree
, hf_aodv_hopcount
, tvb
, offset
, 1,
254 rreq_id
= tvb_get_ntohl(tvb
, offset
);
256 proto_tree_add_uint(aodv_tree
, hf_aodv_rreq_id
, tvb
, offset
, 4,
261 tvb_get_ipv6(tvb
, offset
, &dest_addr_v6
);
263 proto_tree_add_ipv6(aodv_tree
, hf_aodv_dest_ipv6
, tvb
, offset
,
264 INET6_ADDRLEN
, (guint8
*)&dest_addr_v6
);
265 proto_item_append_text(ti
, ", Dest IP: %s",
266 ip6_to_str(&dest_addr_v6
));
268 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", D: %s",
269 ip6_to_str(&dest_addr_v6
));
270 offset
+= INET6_ADDRLEN
;
272 dest_addr_v4
= tvb_get_ipv4(tvb
, offset
);
274 proto_tree_add_ipv4(aodv_tree
, hf_aodv_dest_ip
, tvb
, offset
, 4,
276 proto_item_append_text(ti
, ", Dest IP: %s",
277 ip_to_str((guint8
*)&dest_addr_v4
));
279 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", D: %s",
280 ip_to_str((guint8
*)&dest_addr_v4
));
284 dest_seqno
= tvb_get_ntohl(tvb
, offset
);
286 proto_tree_add_uint(aodv_tree
, hf_aodv_dest_seqno
, tvb
, offset
, 4,
291 tvb_get_ipv6(tvb
, offset
, &orig_addr_v6
);
293 proto_tree_add_ipv6(aodv_tree
, hf_aodv_orig_ipv6
, tvb
, offset
,
294 INET6_ADDRLEN
, (guint8
*)&orig_addr_v6
);
295 proto_item_append_text(ti
, ", Orig IP: %s",
296 ip6_to_str(&orig_addr_v6
));
298 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", O: %s",
299 ip6_to_str(&orig_addr_v6
));
300 offset
+= INET6_ADDRLEN
;
302 orig_addr_v4
= tvb_get_ipv4(tvb
, offset
);
304 proto_tree_add_ipv4(aodv_tree
, hf_aodv_orig_ip
, tvb
, offset
, 4,
306 proto_item_append_text(ti
, ", Orig IP: %s",
307 ip_to_str((guint8
*)&orig_addr_v4
));
309 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", O: %s",
310 ip_to_str((guint8
*)&orig_addr_v4
));
314 orig_seqno
= tvb_get_ntohl(tvb
, offset
);
316 proto_tree_add_uint(aodv_tree
, hf_aodv_orig_seqno
, tvb
, offset
, 4,
318 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Id=%u Hcnt=%u DSN=%u OSN=%u",
326 extlen
= tvb_reported_length_remaining(tvb
, offset
);
328 dissect_aodv_ext(tvb
, offset
, aodv_tree
);
333 dissect_aodv_rrep(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*aodv_tree
,
334 proto_item
*ti
, gboolean is_ipv6
)
338 proto_tree
*aodv_flags_tree
;
342 guint32 dest_addr_v4
;
343 struct e_in6_addr dest_addr_v6
;
345 guint32 orig_addr_v4
;
346 struct e_in6_addr orig_addr_v6
;
350 flags
= tvb_get_guint8(tvb
, offset
);
352 tj
= proto_tree_add_text(aodv_tree
, tvb
, offset
, 1, "Flags:");
353 aodv_flags_tree
= proto_item_add_subtree(tj
, ett_aodv_flags
);
354 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rrep_repair
,
355 tvb
, offset
, 1, flags
);
356 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rrep_ack
, tvb
,
358 if (flags
& RREP_REP
)
359 proto_item_append_text(tj
, " R");
360 if (flags
& RREP_ACK_REQ
)
361 proto_item_append_text(tj
, " A");
365 prefix_sz
= tvb_get_guint8(tvb
, offset
) & 0x1F;
367 proto_tree_add_uint(aodv_tree
, hf_aodv_prefix_sz
, tvb
, offset
, 1,
371 hop_count
= tvb_get_guint8(tvb
, offset
);
373 proto_tree_add_uint(aodv_tree
, hf_aodv_hopcount
, tvb
, offset
, 1,
378 tvb_get_ipv6(tvb
, offset
, &dest_addr_v6
);
380 proto_tree_add_ipv6(aodv_tree
, hf_aodv_dest_ipv6
, tvb
, offset
,
381 INET6_ADDRLEN
, (guint8
*)&dest_addr_v6
);
382 proto_item_append_text(ti
, ", Dest IP: %s",
383 ip6_to_str(&dest_addr_v6
));
386 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", D: %s",
387 ip6_to_str(&dest_addr_v6
));
388 offset
+= INET6_ADDRLEN
;
390 dest_addr_v4
= tvb_get_ipv4(tvb
, offset
);
392 proto_tree_add_ipv4(aodv_tree
, hf_aodv_dest_ip
, tvb
, offset
, 4,
394 proto_item_append_text(ti
, ", Dest IP: %s",
395 ip_to_str((guint8
*)&dest_addr_v4
));
397 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", D: %s",
398 ip_to_str((guint8
*)&dest_addr_v4
));
402 dest_seqno
= tvb_get_ntohl(tvb
, offset
);
404 proto_tree_add_uint(aodv_tree
, hf_aodv_dest_seqno
, tvb
, offset
, 4,
409 tvb_get_ipv6(tvb
, offset
, &orig_addr_v6
);
411 proto_tree_add_ipv6(aodv_tree
, hf_aodv_orig_ipv6
, tvb
, offset
,
412 INET6_ADDRLEN
, (guint8
*)&orig_addr_v6
);
413 proto_item_append_text(ti
, ", Orig IP: %s",
414 ip6_to_str(&orig_addr_v6
));
416 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", O: %s",
417 ip6_to_str(&orig_addr_v6
));
418 offset
+= INET6_ADDRLEN
;
420 orig_addr_v4
= tvb_get_ipv4(tvb
, offset
);
422 proto_tree_add_ipv4(aodv_tree
, hf_aodv_orig_ip
, tvb
, offset
, 4,
424 proto_item_append_text(ti
, ", Orig IP: %s",
425 ip_to_str((guint8
*)&orig_addr_v4
));
427 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", O: %s",
428 ip_to_str((guint8
*)&orig_addr_v4
));
432 lifetime
= tvb_get_ntohl(tvb
, offset
);
434 proto_tree_add_uint(aodv_tree
, hf_aodv_lifetime
, tvb
, offset
, 4,
436 proto_item_append_text(ti
, ", Lifetime=%u", lifetime
);
439 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Hcnt=%u DSN=%u Lifetime=%u",
446 extlen
= tvb_reported_length_remaining(tvb
, offset
);
448 dissect_aodv_ext(tvb
, offset
, aodv_tree
);
453 dissect_aodv_rerr(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*aodv_tree
,
458 proto_tree
*aodv_flags_tree
;
459 proto_tree
*aodv_unreach_dest_tree
;
464 flags
= tvb_get_guint8(tvb
, offset
);
466 tj
= proto_tree_add_text(aodv_tree
, tvb
, offset
, 1, "Flags:");
467 aodv_flags_tree
= proto_item_add_subtree(tj
, ett_aodv_flags
);
468 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rerr_nodelete
,
469 tvb
, offset
, 1, flags
);
470 if (flags
& RERR_NODEL
)
471 proto_item_append_text(tj
, " N");
473 offset
+= 2; /* skip reserved byte */
475 dest_count
= tvb_get_guint8(tvb
, offset
);
477 proto_tree_add_uint(aodv_tree
, hf_aodv_destcount
, tvb
, offset
, 1,
479 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Dest Count=%u",
484 tj
= proto_tree_add_text(aodv_tree
, tvb
, offset
,
485 (INET6_ADDRLEN
+ 4)*dest_count
,
486 "Unreachable Destinations");
487 aodv_unreach_dest_tree
= proto_item_add_subtree(tj
, ett_aodv_unreach_dest
);
488 for (i
= 0; i
< dest_count
; i
++) {
489 proto_tree_add_item(aodv_unreach_dest_tree
,
490 hf_aodv_unreach_dest_ipv6
,
491 tvb
, offset
, INET6_ADDRLEN
, ENC_NA
);
492 offset
+= INET6_ADDRLEN
;
493 proto_tree_add_item(aodv_unreach_dest_tree
, hf_aodv_dest_seqno
,
494 tvb
, offset
, 4, ENC_BIG_ENDIAN
);
498 tj
= proto_tree_add_text(aodv_tree
, tvb
, offset
, (4 + 4)*dest_count
,
499 "Unreachable Destinations");
500 aodv_unreach_dest_tree
= proto_item_add_subtree(tj
, ett_aodv_unreach_dest
);
501 for (i
= 0; i
< dest_count
; i
++) {
502 proto_tree_add_item(aodv_unreach_dest_tree
, hf_aodv_unreach_dest_ip
,
503 tvb
, offset
, 4, ENC_BIG_ENDIAN
);
505 proto_tree_add_item(aodv_unreach_dest_tree
, hf_aodv_dest_seqno
,
506 tvb
, offset
, 4, ENC_BIG_ENDIAN
);
513 dissect_aodv_draft_01_v6_rreq(tvbuff_t
*tvb
, packet_info
*pinfo
,
514 proto_tree
*aodv_tree
, proto_item
*ti
)
518 proto_tree
*aodv_flags_tree
;
524 struct e_in6_addr dest_addr_v6
;
525 struct e_in6_addr orig_addr_v6
;
528 flags
= tvb_get_guint8(tvb
, offset
);
530 tj
= proto_tree_add_text(aodv_tree
, tvb
, offset
, 1, "Flags:");
531 aodv_flags_tree
= proto_item_add_subtree(tj
, ett_aodv_flags
);
532 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rreq_join
,
533 tvb
, offset
, 1, flags
);
534 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rreq_repair
,
535 tvb
, offset
, 1, flags
);
536 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rreq_gratuitous
,
537 tvb
, offset
, 1, flags
);
538 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rreq_destinationonly
,
539 tvb
, offset
, 1, flags
);
540 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rreq_unknown
,
541 tvb
, offset
, 1, flags
);
542 if (flags
& RREQ_JOIN
)
543 proto_item_append_text(tj
, " J");
544 if (flags
& RREQ_REP
)
545 proto_item_append_text(tj
, " R");
546 if (flags
& RREQ_GRATRREP
)
547 proto_item_append_text(tj
, " G");
548 if (flags
& RREQ_DESTONLY
)
549 proto_item_append_text(tj
, " D");
550 if (flags
& RREQ_UNKNSEQ
)
551 proto_item_append_text(tj
, " U");
553 offset
+= 2; /* skip reserved byte */
555 hop_count
= tvb_get_guint8(tvb
, offset
);
557 proto_tree_add_uint(aodv_tree
, hf_aodv_hopcount
, tvb
, offset
, 1,
561 rreq_id
= tvb_get_ntohl(tvb
, offset
);
563 proto_tree_add_uint(aodv_tree
, hf_aodv_rreq_id
, tvb
, offset
, 4,
567 dest_seqno
= tvb_get_ntohl(tvb
, offset
);
569 proto_tree_add_uint(aodv_tree
, hf_aodv_dest_seqno
, tvb
, offset
, 4,
573 orig_seqno
= tvb_get_ntohl(tvb
, offset
);
575 proto_tree_add_uint(aodv_tree
, hf_aodv_orig_seqno
, tvb
, offset
, 4,
579 tvb_get_ipv6(tvb
, offset
, &dest_addr_v6
);
581 proto_tree_add_ipv6(aodv_tree
, hf_aodv_dest_ipv6
, tvb
, offset
,
582 INET6_ADDRLEN
, (guint8
*)&dest_addr_v6
);
583 proto_item_append_text(ti
, ", Dest IP: %s",
584 ip6_to_str(&dest_addr_v6
));
587 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", D: %s",
588 ip6_to_str(&dest_addr_v6
));
589 offset
+= INET6_ADDRLEN
;
591 tvb_get_ipv6(tvb
, offset
, &orig_addr_v6
);
593 proto_tree_add_ipv6(aodv_tree
, hf_aodv_orig_ipv6
, tvb
, offset
,
594 INET6_ADDRLEN
, (guint8
*)&orig_addr_v6
);
595 proto_item_append_text(ti
, ", Orig IP: %s",
596 ip6_to_str(&orig_addr_v6
));
599 col_append_fstr(pinfo
->cinfo
, COL_INFO
,
600 ", O: %s Id=%u Hcnt=%u DSN=%u OSN=%u",
601 ip6_to_str(&orig_addr_v6
),
606 offset
+= INET6_ADDRLEN
;
609 extlen
= tvb_reported_length_remaining(tvb
, offset
);
611 dissect_aodv_ext(tvb
, offset
, aodv_tree
);
616 dissect_aodv_draft_01_v6_rrep(tvbuff_t
*tvb
, packet_info
*pinfo
,
617 proto_tree
*aodv_tree
, proto_item
*ti
)
621 proto_tree
*aodv_flags_tree
;
626 struct e_in6_addr dest_addr_v6
;
627 struct e_in6_addr orig_addr_v6
;
631 flags
= tvb_get_guint8(tvb
, offset
);
633 tj
= proto_tree_add_text(aodv_tree
, tvb
, offset
, 1, "Flags:");
634 aodv_flags_tree
= proto_item_add_subtree(tj
, ett_aodv_flags
);
635 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rrep_repair
,
636 tvb
, offset
, 1, flags
);
637 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rrep_ack
, tvb
,
639 if (flags
& RREP_REP
)
640 proto_item_append_text(tj
, " R");
641 if (flags
& RREP_ACK_REQ
)
642 proto_item_append_text(tj
, " A");
646 prefix_sz
= tvb_get_guint8(tvb
, offset
) & 0x7F;
648 proto_tree_add_uint(aodv_tree
, hf_aodv_prefix_sz
, tvb
, offset
, 1,
652 hop_count
= tvb_get_guint8(tvb
, offset
);
654 proto_tree_add_uint(aodv_tree
, hf_aodv_hopcount
, tvb
, offset
, 1,
658 dest_seqno
= tvb_get_ntohl(tvb
, offset
);
660 proto_tree_add_uint(aodv_tree
, hf_aodv_dest_seqno
, tvb
, offset
, 4,
664 tvb_get_ipv6(tvb
, offset
, &dest_addr_v6
);
666 proto_tree_add_ipv6(aodv_tree
, hf_aodv_dest_ipv6
, tvb
, offset
,
667 INET6_ADDRLEN
, (guint8
*)&dest_addr_v6
);
668 proto_item_append_text(ti
, ", Dest IP: %s",
669 ip6_to_str(&dest_addr_v6
));
672 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", D: %s",
673 ip6_to_str(&dest_addr_v6
));
674 offset
+= INET6_ADDRLEN
;
676 tvb_get_ipv6(tvb
, offset
, &orig_addr_v6
);
678 proto_tree_add_ipv6(aodv_tree
, hf_aodv_orig_ipv6
, tvb
, offset
,
679 INET6_ADDRLEN
, (guint8
*)&orig_addr_v6
);
680 proto_item_append_text(ti
, ", Orig IP: %s",
681 ip6_to_str(&orig_addr_v6
));
684 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", O: %s",
685 ip6_to_str(&orig_addr_v6
));
686 offset
+= INET6_ADDRLEN
;
688 lifetime
= tvb_get_ntohl(tvb
, offset
);
690 proto_tree_add_uint(aodv_tree
, hf_aodv_lifetime
, tvb
, offset
, 4,
692 proto_item_append_text(ti
, ", Lifetime=%u", lifetime
);
695 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Hcnt=%u DSN=%u Lifetime=%u",
702 extlen
= tvb_reported_length_remaining(tvb
, offset
);
704 dissect_aodv_ext(tvb
, offset
, aodv_tree
);
709 dissect_aodv_draft_01_v6_rerr(tvbuff_t
*tvb
, packet_info
*pinfo
,
710 proto_tree
*aodv_tree
)
714 proto_tree
*aodv_flags_tree
;
715 proto_tree
*aodv_unreach_dest_tree
;
720 flags
= tvb_get_guint8(tvb
, offset
);
722 tj
= proto_tree_add_text(aodv_tree
, tvb
, offset
, 1, "Flags:");
723 aodv_flags_tree
= proto_item_add_subtree(tj
, ett_aodv_flags
);
724 proto_tree_add_boolean(aodv_flags_tree
, hf_aodv_flags_rerr_nodelete
,
725 tvb
, offset
, 1, flags
);
726 if (flags
& RERR_NODEL
)
727 proto_item_append_text(tj
, " N");
729 offset
+= 2; /* skip reserved byte */
731 dest_count
= tvb_get_guint8(tvb
, offset
);
733 proto_tree_add_uint(aodv_tree
, hf_aodv_destcount
, tvb
, offset
, 1,
736 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Dest Count=%u",
740 tj
= proto_tree_add_text(aodv_tree
, tvb
, offset
,
741 (4 + INET6_ADDRLEN
)*dest_count
,
742 "Unreachable Destinations");
743 aodv_unreach_dest_tree
= proto_item_add_subtree(tj
, ett_aodv_unreach_dest
);
744 for (i
= 0; i
< dest_count
; i
++) {
745 proto_tree_add_item(aodv_unreach_dest_tree
, hf_aodv_dest_seqno
,
746 tvb
, offset
, 4, ENC_BIG_ENDIAN
);
748 proto_tree_add_item(aodv_unreach_dest_tree
,
749 hf_aodv_unreach_dest_ipv6
,
750 tvb
, offset
, INET6_ADDRLEN
, ENC_NA
);
751 offset
+= INET6_ADDRLEN
;
756 dissect_aodv(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
758 proto_item
*ti
= NULL
;
759 proto_tree
*aodv_tree
= NULL
;
763 /* Make entries in Protocol column and Info column on summary display */
764 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "AODV");
766 col_clear(pinfo
->cinfo
, COL_INFO
);
768 /* Is this running over IPv6? */
769 is_ipv6
= (pinfo
->src
.type
== AT_IPv6
);
771 /* Check the type of AODV packet. */
772 type
= tvb_get_guint8(tvb
, 0);
773 if (try_val_to_str(type
, type_vals
) == NULL
) {
775 * We assume this is not an AODV packet.
781 col_add_str(pinfo
->cinfo
, COL_INFO
,
782 val_to_str(type
, type_vals
,
783 "Unknown AODV Packet Type (%u)"));
785 ti
= proto_tree_add_protocol_format(tree
, proto_aodv
, tvb
, 0, -1,
786 "Ad hoc On-demand Distance Vector Routing Protocol, %s",
787 val_to_str(type
, type_vals
, "Unknown AODV Packet Type (%u)"));
788 aodv_tree
= proto_item_add_subtree(ti
, ett_aodv
);
790 proto_tree_add_uint(aodv_tree
, hf_aodv_type
, tvb
, 0, 1, type
);
795 dissect_aodv_rreq(tvb
, pinfo
, aodv_tree
, ti
, is_ipv6
);
798 dissect_aodv_rrep(tvb
, pinfo
, aodv_tree
, ti
, is_ipv6
);
801 dissect_aodv_rerr(tvb
, pinfo
, aodv_tree
, is_ipv6
);
805 case DRAFT_01_V6_RREQ
:
806 dissect_aodv_draft_01_v6_rreq(tvb
, pinfo
, aodv_tree
, ti
);
808 case DRAFT_01_V6_RREP
:
809 dissect_aodv_draft_01_v6_rrep(tvb
, pinfo
, aodv_tree
, ti
);
811 case DRAFT_01_V6_RERR
:
812 dissect_aodv_draft_01_v6_rerr(tvb
, pinfo
, aodv_tree
);
814 case DRAFT_01_V6_RREP_ACK
:
817 proto_tree_add_text(aodv_tree
, tvb
, 0, -1,
818 "Unknown AODV Packet Type (%u)", type
);
821 return tvb_length(tvb
);
825 /* Register the protocol with Wireshark */
827 proto_register_aodv(void)
829 static hf_register_info hf
[] = {
831 { "Type", "aodv.type",
832 FT_UINT8
, BASE_DEC
, VALS(type_vals
), 0x0,
833 "AODV packet type", HFILL
}
837 { "Flags", "aodv.flags",
838 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
842 { &hf_aodv_flags_rreq_join
,
843 { "RREQ Join", "aodv.flags.rreq_join",
844 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), RREQ_JOIN
,
847 { &hf_aodv_flags_rreq_repair
,
848 { "RREQ Repair", "aodv.flags.rreq_repair",
849 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), RREQ_REP
,
852 { &hf_aodv_flags_rreq_gratuitous
,
853 { "RREQ Gratuitous RREP", "aodv.flags.rreq_gratuitous",
854 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), RREQ_GRATRREP
,
857 { &hf_aodv_flags_rreq_destinationonly
,
858 { "RREQ Destination only", "aodv.flags.rreq_destinationonly",
859 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), RREQ_DESTONLY
,
862 { &hf_aodv_flags_rreq_unknown
,
863 { "RREQ Unknown Sequence Number", "aodv.flags.rreq_unknown",
864 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), RREQ_UNKNSEQ
,
867 { &hf_aodv_flags_rrep_repair
,
868 { "RREP Repair", "aodv.flags.rrep_repair",
869 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), RREP_REP
,
872 { &hf_aodv_flags_rrep_ack
,
873 { "RREP Acknowledgement", "aodv.flags.rrep_ack",
874 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), RREP_ACK_REQ
,
877 { &hf_aodv_flags_rerr_nodelete
,
878 { "RERR No Delete", "aodv.flags.rerr_nodelete",
879 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), RERR_NODEL
,
882 { &hf_aodv_prefix_sz
,
883 { "Prefix Size", "aodv.prefix_sz",
884 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
888 { "Hop Count", "aodv.hopcount",
889 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
893 { "RREQ Id", "aodv.rreq_id",
894 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
898 { "Destination IP", "aodv.dest_ip",
899 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
900 "Destination IP Address", HFILL
}
902 { &hf_aodv_dest_ipv6
,
903 { "Destination IPv6", "aodv.dest_ipv6",
904 FT_IPv6
, BASE_NONE
, NULL
, 0x0,
905 "Destination IPv6 Address", HFILL
}
907 { &hf_aodv_dest_seqno
,
908 { "Destination Sequence Number", "aodv.dest_seqno",
909 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
913 { "Originator IP", "aodv.orig_ip",
914 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
915 "Originator IP Address", HFILL
}
917 { &hf_aodv_orig_ipv6
,
918 { "Originator IPv6", "aodv.orig_ipv6",
919 FT_IPv6
, BASE_NONE
, NULL
, 0x0,
920 "Originator IPv6 Address", HFILL
}
922 { &hf_aodv_orig_seqno
,
923 { "Originator Sequence Number", "aodv.orig_seqno",
924 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
928 { "Lifetime", "aodv.lifetime",
929 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
932 { &hf_aodv_destcount
,
933 { "Destination Count", "aodv.destcount",
934 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
935 "Unreachable Destinations Count", HFILL
}
937 { &hf_aodv_unreach_dest_ip
,
938 { "Unreachable Destination IP", "aodv.unreach_dest_ip",
939 FT_IPv4
, BASE_NONE
, NULL
, 0x0,
940 "Unreachable Destination IP Address", HFILL
}
942 { &hf_aodv_unreach_dest_ipv6
,
943 { "Unreachable Destination IPv6", "aodv.unreach_dest_ipv6",
944 FT_IPv6
, BASE_NONE
, NULL
, 0x0,
945 "Unreachable Destination IPv6 Address", HFILL
}
948 { &hf_aodv_unreach_dest_seqno
,
949 { "Unreachable Destination Sequence Number", "aodv.unreach_dest_seqno",
950 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
954 { "Extension Type", "aodv.ext_type",
955 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
956 "Extension Format Type", HFILL
}
958 { &hf_aodv_ext_length
,
959 { "Extension Length", "aodv.ext_length",
960 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
961 "Extension Data Length", HFILL
}
964 { &hf_aodv_ext_interval
,
965 { "Hello Interval", "aodv.hello_interval",
966 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
967 "Hello Interval Extension", HFILL
}
969 { &hf_aodv_ext_timestamp
,
970 { "Timestamp", "aodv.timestamp",
971 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
972 "Timestamp Extension", HFILL
}
976 /* Setup protocol subtree array */
977 static gint
*ett
[] = {
980 &ett_aodv_unreach_dest
,
981 &ett_aodv_extensions
,
984 /* Register the protocol name and description */
985 proto_aodv
= proto_register_protocol("Ad hoc On-demand Distance Vector Routing Protocol", "AODV", "aodv");
987 /* Required function calls to register the header fields and subtrees used */
988 proto_register_field_array(proto_aodv
, hf
, array_length(hf
));
989 proto_register_subtree_array(ett
, array_length(ett
));
994 proto_reg_handoff_aodv(void)
996 dissector_handle_t aodv_handle
;
998 aodv_handle
= new_create_dissector_handle(dissect_aodv
,
1000 dissector_add_uint("udp.port", UDP_PORT_AODV
, aodv_handle
);