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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 #include <epan/packet.h>
40 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
46 * RFC 3561 (which indicates that, for IPv6, the only change is that
47 * the address fields are enlarged)
49 * http://www.cs.ucsb.edu/~ebelding/txt/aodv6.txt
51 * http://www.tcs.hut.fi/~anttit/manet/drafts/draft-perkins-aodv6-01.txt
53 * (both of the above two are draft-perkins-manet-aodv6-01.txt, which
54 * is from November 2000)
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(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, FALSE);
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 if (check_col(pinfo->cinfo, COL_INFO))
269 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
270 ip6_to_str(&dest_addr_v6));
271 offset += INET6_ADDRLEN;
273 dest_addr_v4 = tvb_get_ipv4(tvb, offset);
275 proto_tree_add_ipv4(aodv_tree, hf_aodv_dest_ip, tvb, offset, 4,
277 proto_item_append_text(ti, ", Dest IP: %s",
278 ip_to_str((guint8 *)&dest_addr_v4));
280 if (check_col(pinfo->cinfo, COL_INFO))
281 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
282 ip_to_str((guint8 *)&dest_addr_v4));
286 dest_seqno = tvb_get_ntohl(tvb, offset);
288 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
293 tvb_get_ipv6(tvb, offset, &orig_addr_v6);
295 proto_tree_add_ipv6(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
296 INET6_ADDRLEN, (guint8 *)&orig_addr_v6);
297 proto_item_append_text(ti, ", Orig IP: %s",
298 ip6_to_str(&orig_addr_v6));
300 if (check_col(pinfo->cinfo, COL_INFO))
301 col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s",
302 ip6_to_str(&orig_addr_v6));
303 offset += INET6_ADDRLEN;
305 orig_addr_v4 = tvb_get_ipv4(tvb, offset);
307 proto_tree_add_ipv4(aodv_tree, hf_aodv_orig_ip, tvb, offset, 4,
309 proto_item_append_text(ti, ", Orig IP: %s",
310 ip_to_str((guint8 *)&orig_addr_v4));
312 if (check_col(pinfo->cinfo, COL_INFO))
313 col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s",
314 ip_to_str((guint8 *)&orig_addr_v4));
318 orig_seqno = tvb_get_ntohl(tvb, offset);
320 proto_tree_add_uint(aodv_tree, hf_aodv_orig_seqno, tvb, offset, 4,
322 if (check_col(pinfo->cinfo, COL_INFO))
323 col_append_fstr(pinfo->cinfo, COL_INFO, " Id=%u Hcnt=%u DSN=%u OSN=%u",
331 extlen = tvb_reported_length_remaining(tvb, offset);
333 dissect_aodv_ext(tvb, offset, aodv_tree);
338 dissect_aodv_rrep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *aodv_tree,
339 proto_item *ti, gboolean is_ipv6)
343 proto_tree *aodv_flags_tree;
347 guint32 dest_addr_v4;
348 struct e_in6_addr dest_addr_v6;
350 guint32 orig_addr_v4;
351 struct e_in6_addr orig_addr_v6;
355 flags = tvb_get_guint8(tvb, offset);
357 tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
358 aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
359 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rrep_repair,
360 tvb, offset, 1, flags);
361 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rrep_ack, tvb,
363 if (flags & RREP_REP)
364 proto_item_append_text(tj, " R");
365 if (flags & RREP_ACK_REQ)
366 proto_item_append_text(tj, " A");
370 prefix_sz = tvb_get_guint8(tvb, offset) & 0x1F;
372 proto_tree_add_uint(aodv_tree, hf_aodv_prefix_sz, tvb, offset, 1,
376 hop_count = tvb_get_guint8(tvb, offset);
378 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
383 tvb_get_ipv6(tvb, offset, &dest_addr_v6);
385 proto_tree_add_ipv6(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
386 INET6_ADDRLEN, (guint8 *)&dest_addr_v6);
387 proto_item_append_text(ti, ", Dest IP: %s",
388 ip6_to_str(&dest_addr_v6));
390 if (check_col(pinfo->cinfo, COL_INFO))
391 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
392 ip6_to_str(&dest_addr_v6));
393 offset += INET6_ADDRLEN;
395 dest_addr_v4 = tvb_get_ipv4(tvb, offset);
397 proto_tree_add_ipv4(aodv_tree, hf_aodv_dest_ip, tvb, offset, 4,
399 proto_item_append_text(ti, ", Dest IP: %s",
400 ip_to_str((guint8 *)&dest_addr_v4));
402 if (check_col(pinfo->cinfo, COL_INFO))
403 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
404 ip_to_str((guint8 *)&dest_addr_v4));
408 dest_seqno = tvb_get_ntohl(tvb, offset);
410 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
415 tvb_get_ipv6(tvb, offset, &orig_addr_v6);
417 proto_tree_add_ipv6(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
418 INET6_ADDRLEN, (guint8 *)&orig_addr_v6);
419 proto_item_append_text(ti, ", Orig IP: %s",
420 ip6_to_str(&orig_addr_v6));
422 if (check_col(pinfo->cinfo, COL_INFO))
423 col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s",
424 ip6_to_str(&orig_addr_v6));
425 offset += INET6_ADDRLEN;
427 orig_addr_v4 = tvb_get_ipv4(tvb, offset);
429 proto_tree_add_ipv4(aodv_tree, hf_aodv_orig_ip, tvb, offset, 4,
431 proto_item_append_text(ti, ", Orig IP: %s",
432 ip_to_str((guint8 *)&orig_addr_v4));
434 if (check_col(pinfo->cinfo, COL_INFO))
435 col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s",
436 ip_to_str((guint8 *)&orig_addr_v4));
440 lifetime = tvb_get_ntohl(tvb, offset);
442 proto_tree_add_uint(aodv_tree, hf_aodv_lifetime, tvb, offset, 4,
444 proto_item_append_text(ti, ", Lifetime=%u", lifetime);
446 if (check_col(pinfo->cinfo, COL_INFO))
447 col_append_fstr(pinfo->cinfo, COL_INFO, " Hcnt=%u DSN=%u Lifetime=%u",
454 extlen = tvb_reported_length_remaining(tvb, offset);
456 dissect_aodv_ext(tvb, offset, aodv_tree);
461 dissect_aodv_rerr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *aodv_tree,
466 proto_tree *aodv_flags_tree;
467 proto_tree *aodv_unreach_dest_tree;
472 flags = tvb_get_guint8(tvb, offset);
474 tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
475 aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
476 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rerr_nodelete,
477 tvb, offset, 1, flags);
478 if (flags & RERR_NODEL)
479 proto_item_append_text(tj, " N");
481 offset += 2; /* skip reserved byte */
483 dest_count = tvb_get_guint8(tvb, offset);
485 proto_tree_add_uint(aodv_tree, hf_aodv_destcount, tvb, offset, 1,
487 if (check_col(pinfo->cinfo, COL_INFO))
488 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dest Count=%u",
493 tj = proto_tree_add_text(aodv_tree, tvb, offset,
494 (INET6_ADDRLEN + 4)*dest_count,
495 "Unreachable Destinations");
496 aodv_unreach_dest_tree = proto_item_add_subtree(tj, ett_aodv_unreach_dest);
497 for (i = 0; i < dest_count; i++) {
498 proto_tree_add_item(aodv_unreach_dest_tree,
499 hf_aodv_unreach_dest_ipv6,
500 tvb, offset, INET6_ADDRLEN, FALSE);
501 offset += INET6_ADDRLEN;
502 proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_dest_seqno,
503 tvb, offset, 4, FALSE);
507 tj = proto_tree_add_text(aodv_tree, tvb, offset, (4 + 4)*dest_count,
508 "Unreachable Destinations");
509 aodv_unreach_dest_tree = proto_item_add_subtree(tj, ett_aodv_unreach_dest);
510 for (i = 0; i < dest_count; i++) {
511 proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_unreach_dest_ip,
512 tvb, offset, 4, FALSE);
514 proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_dest_seqno,
515 tvb, offset, 4, FALSE);
522 dissect_aodv_draft_01_v6_rreq(tvbuff_t *tvb, packet_info *pinfo,
523 proto_tree *aodv_tree, proto_item *ti)
527 proto_tree *aodv_flags_tree;
533 struct e_in6_addr dest_addr_v6;
534 struct e_in6_addr orig_addr_v6;
537 flags = tvb_get_guint8(tvb, offset);
539 tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
540 aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
541 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_join,
542 tvb, offset, 1, flags);
543 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_repair,
544 tvb, offset, 1, flags);
545 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_gratuitous,
546 tvb, offset, 1, flags);
547 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_destinationonly,
548 tvb, offset, 1, flags);
549 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_unknown,
550 tvb, offset, 1, flags);
551 if (flags & RREQ_JOIN)
552 proto_item_append_text(tj, " J");
553 if (flags & RREQ_REP)
554 proto_item_append_text(tj, " R");
555 if (flags & RREQ_GRATRREP)
556 proto_item_append_text(tj, " G");
557 if (flags & RREQ_DESTONLY)
558 proto_item_append_text(tj, " D");
559 if (flags & RREQ_UNKNSEQ)
560 proto_item_append_text(tj, " U");
562 offset += 2; /* skip reserved byte */
564 hop_count = tvb_get_guint8(tvb, offset);
566 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
570 rreq_id = tvb_get_ntohl(tvb, offset);
572 proto_tree_add_uint(aodv_tree, hf_aodv_rreq_id, tvb, offset, 4,
576 dest_seqno = tvb_get_ntohl(tvb, offset);
578 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
582 orig_seqno = tvb_get_ntohl(tvb, offset);
584 proto_tree_add_uint(aodv_tree, hf_aodv_orig_seqno, tvb, offset, 4,
588 tvb_get_ipv6(tvb, offset, &dest_addr_v6);
590 proto_tree_add_ipv6(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
591 INET6_ADDRLEN, (guint8 *)&dest_addr_v6);
592 proto_item_append_text(ti, ", Dest IP: %s",
593 ip6_to_str(&dest_addr_v6));
595 if (check_col(pinfo->cinfo, COL_INFO))
596 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
597 ip6_to_str(&dest_addr_v6));
598 offset += INET6_ADDRLEN;
600 tvb_get_ipv6(tvb, offset, &orig_addr_v6);
602 proto_tree_add_ipv6(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
603 INET6_ADDRLEN, (guint8 *)&orig_addr_v6);
604 proto_item_append_text(ti, ", Orig IP: %s",
605 ip6_to_str(&orig_addr_v6));
607 if (check_col(pinfo->cinfo, COL_INFO))
608 col_append_fstr(pinfo->cinfo, COL_INFO,
609 ", O: %s Id=%u Hcnt=%u DSN=%u OSN=%u",
610 ip6_to_str(&orig_addr_v6),
615 offset += INET6_ADDRLEN;
618 extlen = tvb_reported_length_remaining(tvb, offset);
620 dissect_aodv_ext(tvb, offset, aodv_tree);
625 dissect_aodv_draft_01_v6_rrep(tvbuff_t *tvb, packet_info *pinfo,
626 proto_tree *aodv_tree, proto_item *ti)
630 proto_tree *aodv_flags_tree;
635 struct e_in6_addr dest_addr_v6;
636 struct e_in6_addr orig_addr_v6;
640 flags = tvb_get_guint8(tvb, offset);
642 tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
643 aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
644 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rrep_repair,
645 tvb, offset, 1, flags);
646 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rrep_ack, tvb,
648 if (flags & RREP_REP)
649 proto_item_append_text(tj, " R");
650 if (flags & RREP_ACK_REQ)
651 proto_item_append_text(tj, " A");
655 prefix_sz = tvb_get_guint8(tvb, offset) & 0x7F;
657 proto_tree_add_uint(aodv_tree, hf_aodv_prefix_sz, tvb, offset, 1,
661 hop_count = tvb_get_guint8(tvb, offset);
663 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
667 dest_seqno = tvb_get_ntohl(tvb, offset);
669 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
673 tvb_get_ipv6(tvb, offset, &dest_addr_v6);
675 proto_tree_add_ipv6(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
676 INET6_ADDRLEN, (guint8 *)&dest_addr_v6);
677 proto_item_append_text(ti, ", Dest IP: %s",
678 ip6_to_str(&dest_addr_v6));
680 if (check_col(pinfo->cinfo, COL_INFO))
681 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
682 ip6_to_str(&dest_addr_v6));
683 offset += INET6_ADDRLEN;
685 tvb_get_ipv6(tvb, offset, &orig_addr_v6);
687 proto_tree_add_ipv6(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
688 INET6_ADDRLEN, (guint8 *)&orig_addr_v6);
689 proto_item_append_text(ti, ", Orig IP: %s",
690 ip6_to_str(&orig_addr_v6));
692 if (check_col(pinfo->cinfo, COL_INFO))
693 col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s",
694 ip6_to_str(&orig_addr_v6));
695 offset += INET6_ADDRLEN;
697 lifetime = tvb_get_ntohl(tvb, offset);
699 proto_tree_add_uint(aodv_tree, hf_aodv_lifetime, tvb, offset, 4,
701 proto_item_append_text(ti, ", Lifetime=%u", lifetime);
703 if (check_col(pinfo->cinfo, COL_INFO))
704 col_append_fstr(pinfo->cinfo, COL_INFO, " Hcnt=%u DSN=%u Lifetime=%u",
711 extlen = tvb_reported_length_remaining(tvb, offset);
713 dissect_aodv_ext(tvb, offset, aodv_tree);
718 dissect_aodv_draft_01_v6_rerr(tvbuff_t *tvb, packet_info *pinfo,
719 proto_tree *aodv_tree)
723 proto_tree *aodv_flags_tree;
724 proto_tree *aodv_unreach_dest_tree;
729 flags = tvb_get_guint8(tvb, offset);
731 tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
732 aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
733 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rerr_nodelete,
734 tvb, offset, 1, flags);
735 if (flags & RERR_NODEL)
736 proto_item_append_text(tj, " N");
738 offset += 2; /* skip reserved byte */
740 dest_count = tvb_get_guint8(tvb, offset);
742 proto_tree_add_uint(aodv_tree, hf_aodv_destcount, tvb, offset, 1,
744 if (check_col(pinfo->cinfo, COL_INFO))
745 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dest Count=%u",
749 tj = proto_tree_add_text(aodv_tree, tvb, offset,
750 (4 + INET6_ADDRLEN)*dest_count,
751 "Unreachable Destinations");
752 aodv_unreach_dest_tree = proto_item_add_subtree(tj, ett_aodv_unreach_dest);
753 for (i = 0; i < dest_count; i++) {
754 proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_dest_seqno,
755 tvb, offset, 4, FALSE);
757 proto_tree_add_item(aodv_unreach_dest_tree,
758 hf_aodv_unreach_dest_ipv6,
759 tvb, offset, INET6_ADDRLEN, FALSE);
760 offset += INET6_ADDRLEN;
765 dissect_aodv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
767 proto_item *ti = NULL;
768 proto_tree *aodv_tree = NULL;
772 /* Make entries in Protocol column and Info column on summary display */
773 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AODV");
775 if (check_col(pinfo->cinfo, COL_INFO))
776 col_clear(pinfo->cinfo, COL_INFO);
778 /* Is this running over IPv6? */
779 is_ipv6 = (pinfo->src.type == AT_IPv6);
781 /* Check the type of AODV packet. */
782 type = tvb_get_guint8(tvb, 0);
783 if (match_strval(type, type_vals) == NULL) {
785 * We assume this is not an AODV packet.
790 if (check_col(pinfo->cinfo, COL_INFO))
791 col_add_str(pinfo->cinfo, COL_INFO,
792 val_to_str(type, type_vals,
793 "Unknown AODV Packet Type (%u)"));
795 ti = proto_tree_add_protocol_format(tree, proto_aodv, tvb, 0, -1,
796 "Ad hoc On-demand Distance Vector Routing Protocol, %s",
797 val_to_str(type, type_vals, "Unknown AODV Packet Type (%u)"));
798 aodv_tree = proto_item_add_subtree(ti, ett_aodv);
800 proto_tree_add_uint(aodv_tree, hf_aodv_type, tvb, 0, 1, type);
805 dissect_aodv_rreq(tvb, pinfo, aodv_tree, ti, is_ipv6);
808 dissect_aodv_rrep(tvb, pinfo, aodv_tree, ti, is_ipv6);
811 dissect_aodv_rerr(tvb, pinfo, aodv_tree, is_ipv6);
815 case DRAFT_01_V6_RREQ:
816 dissect_aodv_draft_01_v6_rreq(tvb, pinfo, aodv_tree, ti);
818 case DRAFT_01_V6_RREP:
819 dissect_aodv_draft_01_v6_rrep(tvb, pinfo, aodv_tree, ti);
821 case DRAFT_01_V6_RERR:
822 dissect_aodv_draft_01_v6_rerr(tvb, pinfo, aodv_tree);
824 case DRAFT_01_V6_RREP_ACK:
827 proto_tree_add_text(aodv_tree, tvb, 0, -1,
828 "Unknown AODV Packet Type (%u)", type);
831 return tvb_length(tvb);
835 /* Register the protocol with Wireshark */
837 proto_register_aodv(void)
839 static hf_register_info hf[] = {
841 { "Type", "aodv.type",
842 FT_UINT8, BASE_DEC, VALS(type_vals), 0x0,
843 "AODV packet type", HFILL }
846 { "Flags", "aodv.flags",
847 FT_UINT16, BASE_DEC, NULL, 0x0,
850 { &hf_aodv_flags_rreq_join,
851 { "RREQ Join", "aodv.flags.rreq_join",
852 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RREQ_JOIN,
855 { &hf_aodv_flags_rreq_repair,
856 { "RREQ Repair", "aodv.flags.rreq_repair",
857 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RREQ_REP,
860 { &hf_aodv_flags_rreq_gratuitous,
861 { "RREQ Gratuitous RREP", "aodv.flags.rreq_gratuitous",
862 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RREQ_GRATRREP,
865 { &hf_aodv_flags_rreq_destinationonly,
866 { "RREQ Destination only", "aodv.flags.rreq_destinationonly",
867 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RREQ_DESTONLY,
870 { &hf_aodv_flags_rreq_unknown,
871 { "RREQ Unknown Sequence Number", "aodv.flags.rreq_unknown",
872 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RREQ_UNKNSEQ,
875 { &hf_aodv_flags_rrep_repair,
876 { "RREP Repair", "aodv.flags.rrep_repair",
877 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RREP_REP,
880 { &hf_aodv_flags_rrep_ack,
881 { "RREP Acknowledgement", "aodv.flags.rrep_ack",
882 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RREP_ACK_REQ,
885 { &hf_aodv_flags_rerr_nodelete,
886 { "RERR No Delete", "aodv.flags.rerr_nodelete",
887 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RERR_NODEL,
890 { &hf_aodv_prefix_sz,
891 { "Prefix Size", "aodv.prefix_sz",
892 FT_UINT8, BASE_DEC, NULL, 0x0,
896 { "Hop Count", "aodv.hopcount",
897 FT_UINT8, BASE_DEC, NULL, 0x0,
901 { "RREQ Id", "aodv.rreq_id",
902 FT_UINT32, BASE_DEC, NULL, 0x0,
906 { "Destination IP", "aodv.dest_ip",
907 FT_IPv4, BASE_NONE, NULL, 0x0,
908 "Destination IP Address", HFILL }
910 { &hf_aodv_dest_ipv6,
911 { "Destination IPv6", "aodv.dest_ipv6",
912 FT_IPv6, BASE_NONE, NULL, 0x0,
913 "Destination IPv6 Address", HFILL}
915 { &hf_aodv_dest_seqno,
916 { "Destination Sequence Number", "aodv.dest_seqno",
917 FT_UINT32, BASE_DEC, NULL, 0x0,
921 { "Originator IP", "aodv.orig_ip",
922 FT_IPv4, BASE_NONE, NULL, 0x0,
923 "Originator IP Address", HFILL }
925 { &hf_aodv_orig_ipv6,
926 { "Originator IPv6", "aodv.orig_ipv6",
927 FT_IPv6, BASE_NONE, NULL, 0x0,
928 "Originator IPv6 Address", HFILL}
930 { &hf_aodv_orig_seqno,
931 { "Originator Sequence Number", "aodv.orig_seqno",
932 FT_UINT32, BASE_DEC, NULL, 0x0,
936 { "Lifetime", "aodv.lifetime",
937 FT_UINT32, BASE_DEC, NULL, 0x0,
940 { &hf_aodv_destcount,
941 { "Destination Count", "aodv.destcount",
942 FT_UINT8, BASE_DEC, NULL, 0x0,
943 "Unreachable Destinations Count", HFILL }
945 { &hf_aodv_unreach_dest_ip,
946 { "Unreachable Destination IP", "aodv.unreach_dest_ip",
947 FT_IPv4, BASE_NONE, NULL, 0x0,
948 "Unreachable Destination IP Address", HFILL }
950 { &hf_aodv_unreach_dest_ipv6,
951 { "Unreachable Destination IPv6", "aodv.unreach_dest_ipv6",
952 FT_IPv6, BASE_NONE, NULL, 0x0,
953 "Unreachable Destination IPv6 Address", HFILL}
955 { &hf_aodv_unreach_dest_seqno,
956 { "Unreachable Destination Sequence Number", "aodv.unreach_dest_seqno",
957 FT_UINT32, BASE_DEC, NULL, 0x0,
961 { "Extension Type", "aodv.ext_type",
962 FT_UINT8, BASE_DEC, NULL, 0x0,
963 "Extension Format Type", HFILL}
965 { &hf_aodv_ext_length,
966 { "Extension Length", "aodv.ext_length",
967 FT_UINT8, BASE_DEC, NULL, 0x0,
968 "Extension Data Length", HFILL}
970 { &hf_aodv_ext_interval,
971 { "Hello Interval", "aodv.hello_interval",
972 FT_UINT32, BASE_DEC, NULL, 0x0,
973 "Hello Interval Extension", HFILL}
975 { &hf_aodv_ext_timestamp,
976 { "Timestamp", "aodv.timestamp",
977 FT_UINT64, BASE_DEC, NULL, 0x0,
978 "Timestamp Extension", HFILL}
982 /* Setup protocol subtree array */
983 static gint *ett[] = {
986 &ett_aodv_unreach_dest,
987 &ett_aodv_extensions,
990 /* Register the protocol name and description */
991 proto_aodv = proto_register_protocol("Ad hoc On-demand Distance Vector Routing Protocol", "AODV", "aodv");
993 /* Required function calls to register the header fields and subtrees used */
994 proto_register_field_array(proto_aodv, hf, array_length(hf));
995 proto_register_subtree_array(ett, array_length(ett));
1000 proto_reg_handoff_aodv(void)
1002 dissector_handle_t aodv_handle;
1004 aodv_handle = new_create_dissector_handle(dissect_aodv,
1006 dissector_add("udp.port", UDP_PORT_AODV, aodv_handle);