2 * Routines for AODV dissection
3 * Copyright 2000, Erik Nordström <erik.nordstrom@it.uu.se>
5 * $Id: packet-aodv.c,v 1.10 2003/09/13 00:57:10 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
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/int-64bit.h>
38 #include <epan/packet.h>
39 #include <epan/ipv6-utils.h>
42 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
48 * http://www.ietf.org/internet-drafts/draft-ietf-manet-aodv-13.txt
50 * http://www.cs.ucsb.edu/~ebelding/txt/aodv6.txt
52 * http://www.tcs.hut.fi/~anttit/manet/drafts/draft-perkins-aodv6-01.txt
55 #define INET6_ADDRLEN 16
56 #define UDP_PORT_AODV 654
63 #define DRAFT_01_V6_RREQ 16
64 #define DRAFT_01_V6_RREP 17
65 #define DRAFT_01_V6_RERR 18
66 #define DRAFT_01_V6_RREP_ACK 19
70 #define AODV_EXT_INT 2
71 #define AODV_EXT_NTP 3
74 #define RREQ_GRAT 0x20
76 #define RREQ_JOIN 0x80
78 #define RREP_ACK_REQ 0x40
81 #define RERR_NODEL 0x80
83 static const value_string type_vals[] = {
84 { RREQ, "Route Request" },
85 { RREP, "Route Reply" },
86 { RERR, "Route Error" },
87 { RREP_ACK, "Route Reply Acknowledgment"},
88 { DRAFT_01_V6_RREQ, "draft-perkins-aodv6-01 Route Request"},
89 { DRAFT_01_V6_RREP, "draft-perkins-aodv6-01 Route Reply"},
90 { DRAFT_01_V6_RERR, "draft-perkins-aodv6-01 Route Error"},
91 { DRAFT_01_V6_RREP_ACK, "draft-perkins-aodv6-01 Route Reply Acknowledgment"},
95 static const value_string exttype_vals[] = {
97 { AODV_EXT_INT, "Hello Interval"},
98 { AODV_EXT_NTP, "Timestamp"},
102 typedef struct v6_ext {
107 /* Initialize the protocol and registered fields */
108 static int proto_aodv = -1;
109 static int hf_aodv_type = -1;
110 static int hf_aodv_flags = -1;
111 static int hf_aodv_prefix_sz = -1;
112 static int hf_aodv_hopcount = -1;
113 static int hf_aodv_rreq_id = -1;
114 static int hf_aodv_dest_ip = -1;
115 static int hf_aodv_dest_ipv6 = -1;
116 static int hf_aodv_dest_seqno = -1;
117 static int hf_aodv_orig_ip = -1;
118 static int hf_aodv_orig_ipv6 = -1;
119 static int hf_aodv_orig_seqno = -1;
120 static int hf_aodv_lifetime = -1;
121 static int hf_aodv_destcount = -1;
122 static int hf_aodv_unreach_dest_ip = -1;
123 static int hf_aodv_unreach_dest_ipv6 = -1;
124 static int hf_aodv_unreach_dest_seqno = -1;
125 static int hf_aodv_flags_rreq_join = -1;
126 static int hf_aodv_flags_rreq_repair = -1;
127 static int hf_aodv_flags_rreq_gratuitous = -1;
128 static int hf_aodv_flags_rrep_repair = -1;
129 static int hf_aodv_flags_rrep_ack = -1;
130 static int hf_aodv_flags_rerr_nodelete = -1;
131 static int hf_aodv_ext_type = -1;
132 static int hf_aodv_ext_length = -1;
133 static int hf_aodv_ext_interval = -1;
134 static int hf_aodv_ext_timestamp = -1;
136 /* Initialize the subtree pointers */
137 static gint ett_aodv = -1;
138 static gint ett_aodv_flags = -1;
139 static gint ett_aodv_unreach_dest = -1;
140 static gint ett_aodv_extensions = -1;
142 /* Code to actually dissect the packets */
145 dissect_aodv_ext(tvbuff_t * tvb, int offset, proto_tree * tree)
147 proto_tree *ext_tree;
149 aodv_ext_t aodvext, *ext;
156 if ((int) tvb_reported_length(tvb) <= offset)
157 return; /* No more options left */
160 tvb_memcpy(tvb, (guint8 *) ext, offset, sizeof(*ext));
163 ti = proto_tree_add_text(tree, tvb, offset, sizeof(aodv_ext_t) +
165 ext_tree = proto_item_add_subtree(ti, ett_aodv_extensions);
168 proto_tree_add_text(ext_tree, tvb,
169 offset + offsetof(aodv_ext_t, length), 1,
170 "Invalid option length: %u", ext->length);
171 return; /* we must not try to decode this */
174 proto_tree_add_text(ext_tree, tvb,
175 offset + offsetof(aodv_ext_t, type), 1,
176 "Type: %u (%s)", ext->type,
177 val_to_str(ext->type, exttype_vals, "Unknown"));
178 proto_tree_add_text(ext_tree, tvb,
179 offset + offsetof(aodv_ext_t, length), 1,
180 "Length: %u bytes", ext->length);
182 offset += sizeof(aodv_ext_t);
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. */
199 offset += ext->length;
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 if (flags & RREQ_JOIN)
232 proto_item_append_text(tj, " J");
233 if (flags & RREQ_REP)
234 proto_item_append_text(tj, " R");
235 if (flags & RREQ_GRAT)
236 proto_item_append_text(tj, " G");
238 offset += 2; /* skip reserved byte */
240 hop_count = tvb_get_guint8(tvb, offset);
242 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
246 rreq_id = tvb_get_ntohl(tvb, offset);
248 proto_tree_add_uint(aodv_tree, hf_aodv_rreq_id, tvb, offset, 4,
253 tvb_memcpy(tvb, (guint8 *)&dest_addr_v6, offset, INET6_ADDRLEN);
255 proto_tree_add_ipv6(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
256 INET6_ADDRLEN, (guint8 *)&dest_addr_v6);
257 proto_item_append_text(ti, ", Dest IP: %s",
258 ip6_to_str(&dest_addr_v6));
260 if (check_col(pinfo->cinfo, COL_INFO))
261 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
262 ip6_to_str(&dest_addr_v6));
263 offset += INET6_ADDRLEN;
265 tvb_memcpy(tvb, (guint8 *)&dest_addr_v4, offset, 4);
267 proto_tree_add_ipv4(aodv_tree, hf_aodv_dest_ip, tvb, offset, 4,
269 proto_item_append_text(ti, ", Dest IP: %s",
270 ip_to_str((guint8 *)&dest_addr_v4));
272 if (check_col(pinfo->cinfo, COL_INFO))
273 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
274 ip_to_str((guint8 *)&dest_addr_v4));
278 dest_seqno = tvb_get_ntohl(tvb, offset);
280 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
285 tvb_memcpy(tvb, (guint8 *)&orig_addr_v6, offset, INET6_ADDRLEN);
287 proto_tree_add_ipv6(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
288 INET6_ADDRLEN, (guint8 *)&orig_addr_v6);
289 proto_item_append_text(ti, ", Orig IP: %s",
290 ip6_to_str(&orig_addr_v6));
292 if (check_col(pinfo->cinfo, COL_INFO))
293 col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s",
294 ip6_to_str(&orig_addr_v6));
295 offset += INET6_ADDRLEN;
297 tvb_memcpy(tvb, (guint8 *)&orig_addr_v4, offset, 4);
299 proto_tree_add_ipv4(aodv_tree, hf_aodv_orig_ip, tvb, offset, 4,
301 proto_item_append_text(ti, ", Orig IP: %s",
302 ip_to_str((guint8 *)&orig_addr_v4));
304 if (check_col(pinfo->cinfo, COL_INFO))
305 col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s",
306 ip_to_str((guint8 *)&orig_addr_v4));
310 orig_seqno = tvb_get_ntohl(tvb, offset);
312 proto_tree_add_uint(aodv_tree, hf_aodv_orig_seqno, tvb, offset, 4,
314 if (check_col(pinfo->cinfo, COL_INFO))
315 col_append_fstr(pinfo->cinfo, COL_INFO, " Id=%u Hcnt=%u DSN=%u OSN=%u",
323 extlen = tvb_reported_length_remaining(tvb, offset);
325 dissect_aodv_ext(tvb, offset, aodv_tree);
330 dissect_aodv_rrep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *aodv_tree,
331 proto_item *ti, gboolean is_ipv6)
335 proto_tree *aodv_flags_tree;
339 guint32 dest_addr_v4;
340 struct e_in6_addr dest_addr_v6;
342 guint32 orig_addr_v4;
343 struct e_in6_addr orig_addr_v6;
347 flags = tvb_get_guint8(tvb, offset);
349 tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
350 aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
351 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rrep_repair,
352 tvb, offset, 1, flags);
353 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rrep_ack, tvb,
355 if (flags & RREP_REP)
356 proto_item_append_text(tj, " R");
357 if (flags & RREP_ACK_REQ)
358 proto_item_append_text(tj, " A");
362 prefix_sz = tvb_get_guint8(tvb, offset) & 0x1F;
364 proto_tree_add_uint(aodv_tree, hf_aodv_prefix_sz, tvb, offset, 1,
368 hop_count = tvb_get_guint8(tvb, offset);
370 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
375 tvb_memcpy(tvb, (guint8 *)&dest_addr_v6, offset, INET6_ADDRLEN);
377 proto_tree_add_ipv6(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
378 INET6_ADDRLEN, (guint8 *)&dest_addr_v6);
379 proto_item_append_text(ti, ", Dest IP: %s",
380 ip6_to_str(&dest_addr_v6));
382 if (check_col(pinfo->cinfo, COL_INFO))
383 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
384 ip6_to_str(&dest_addr_v6));
385 offset += INET6_ADDRLEN;
387 tvb_memcpy(tvb, (guint8 *)&dest_addr_v4, offset, 4);
389 proto_tree_add_ipv4(aodv_tree, hf_aodv_dest_ip, tvb, offset, 4,
391 proto_item_append_text(ti, ", Dest IP: %s",
392 ip_to_str((guint8 *)&dest_addr_v4));
394 if (check_col(pinfo->cinfo, COL_INFO))
395 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
396 ip_to_str((guint8 *)&dest_addr_v4));
400 dest_seqno = tvb_get_ntohl(tvb, offset);
402 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
407 tvb_memcpy(tvb, (guint8 *)&orig_addr_v6, offset, INET6_ADDRLEN);
409 proto_tree_add_ipv6(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
410 INET6_ADDRLEN, (guint8 *)&orig_addr_v6);
411 proto_item_append_text(ti, ", Dest IP: %s",
412 ip6_to_str(&orig_addr_v6));
414 if (check_col(pinfo->cinfo, COL_INFO))
415 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
416 ip6_to_str(&orig_addr_v6));
417 offset += INET6_ADDRLEN;
419 tvb_memcpy(tvb, (guint8 *)&orig_addr_v4, offset, 4);
421 proto_tree_add_ipv4(aodv_tree, hf_aodv_orig_ip, tvb, offset, 4,
423 proto_item_append_text(ti, ", Orig IP: %s",
424 ip_to_str((guint8 *)&orig_addr_v4));
426 if (check_col(pinfo->cinfo, COL_INFO))
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);
438 if (check_col(pinfo->cinfo, COL_INFO))
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 if (check_col(pinfo->cinfo, COL_INFO))
480 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dest Count=%u",
485 tj = proto_tree_add_text(aodv_tree, tvb, offset,
486 (INET6_ADDRLEN + 4)*dest_count,
487 "Unreachable Destinations");
488 aodv_unreach_dest_tree = proto_item_add_subtree(tj, ett_aodv_unreach_dest);
489 for (i = 0; i < dest_count; i++) {
490 proto_tree_add_item(aodv_unreach_dest_tree,
491 hf_aodv_unreach_dest_ipv6,
492 tvb, offset, INET6_ADDRLEN, FALSE);
493 proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_dest_seqno,
494 tvb, offset, 4, FALSE);
495 offset += INET6_ADDRLEN + 4;
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, FALSE);
504 proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_dest_seqno,
505 tvb, offset, 4, FALSE);
512 dissect_aodv_draft_01_v6_rreq(tvbuff_t *tvb, packet_info *pinfo,
513 proto_tree *aodv_tree, proto_item *ti)
517 proto_tree *aodv_flags_tree;
523 struct e_in6_addr dest_addr_v6;
524 struct e_in6_addr orig_addr_v6;
527 flags = tvb_get_guint8(tvb, offset);
529 tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
530 aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
531 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_join,
532 tvb, offset, 1, flags);
533 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_repair,
534 tvb, offset, 1, flags);
535 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_gratuitous,
536 tvb, offset, 1, flags);
537 if (flags & RREQ_JOIN)
538 proto_item_append_text(tj, " J");
539 if (flags & RREQ_REP)
540 proto_item_append_text(tj, " R");
541 if (flags & RREQ_GRAT)
542 proto_item_append_text(tj, " G");
544 offset += 2; /* skip reserved byte */
546 hop_count = tvb_get_guint8(tvb, offset);
548 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
552 rreq_id = tvb_get_ntohl(tvb, offset);
554 proto_tree_add_uint(aodv_tree, hf_aodv_rreq_id, tvb, offset, 4,
558 dest_seqno = tvb_get_ntohl(tvb, offset);
560 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
564 orig_seqno = tvb_get_ntohl(tvb, offset);
566 proto_tree_add_uint(aodv_tree, hf_aodv_orig_seqno, tvb, offset, 4,
570 tvb_memcpy(tvb, (guint8 *)&dest_addr_v6, offset, INET6_ADDRLEN);
572 proto_tree_add_ipv6(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
573 INET6_ADDRLEN, (guint8 *)&dest_addr_v6);
574 proto_item_append_text(ti, ", Dest IP: %s",
575 ip6_to_str(&dest_addr_v6));
577 if (check_col(pinfo->cinfo, COL_INFO))
578 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
579 ip6_to_str(&dest_addr_v6));
580 offset += INET6_ADDRLEN;
582 tvb_memcpy(tvb, (guint8 *)&orig_addr_v6, offset, INET6_ADDRLEN);
584 proto_tree_add_ipv6(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
585 INET6_ADDRLEN, (guint8 *)&orig_addr_v6);
586 proto_item_append_text(ti, ", Orig IP: %s",
587 ip6_to_str(&orig_addr_v6));
589 if (check_col(pinfo->cinfo, COL_INFO))
590 col_append_fstr(pinfo->cinfo, COL_INFO,
591 ", O: %s Id=%u Hcnt=%u DSN=%u OSN=%u",
592 ip6_to_str(&orig_addr_v6),
597 offset += INET6_ADDRLEN;
600 extlen = tvb_reported_length_remaining(tvb, offset);
602 dissect_aodv_ext(tvb, offset, aodv_tree);
607 dissect_aodv_draft_01_v6_rrep(tvbuff_t *tvb, packet_info *pinfo,
608 proto_tree *aodv_tree, proto_item *ti)
612 proto_tree *aodv_flags_tree;
617 struct e_in6_addr dest_addr_v6;
618 struct e_in6_addr orig_addr_v6;
622 flags = tvb_get_guint8(tvb, offset);
624 tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
625 aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
626 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rrep_repair,
627 tvb, offset, 1, flags);
628 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rrep_ack, tvb,
630 if (flags & RREP_REP)
631 proto_item_append_text(tj, " R");
632 if (flags & RREP_ACK_REQ)
633 proto_item_append_text(tj, " A");
637 prefix_sz = tvb_get_guint8(tvb, offset) & 0x1F;
639 proto_tree_add_uint(aodv_tree, hf_aodv_prefix_sz, tvb, offset, 1,
643 hop_count = tvb_get_guint8(tvb, offset);
645 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
649 dest_seqno = tvb_get_ntohl(tvb, offset);
651 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
655 tvb_memcpy(tvb, (guint8 *)&dest_addr_v6, offset, INET6_ADDRLEN);
657 proto_tree_add_ipv6(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
658 INET6_ADDRLEN, (guint8 *)&dest_addr_v6);
659 proto_item_append_text(ti, ", Dest IP: %s",
660 ip6_to_str(&dest_addr_v6));
662 if (check_col(pinfo->cinfo, COL_INFO))
663 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
664 ip6_to_str(&dest_addr_v6));
665 offset += INET6_ADDRLEN;
667 tvb_memcpy(tvb, (guint8 *)&orig_addr_v6, offset, INET6_ADDRLEN);
669 proto_tree_add_ipv6(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
670 INET6_ADDRLEN, (guint8 *)&orig_addr_v6);
671 proto_item_append_text(ti, ", Dest IP: %s",
672 ip6_to_str(&orig_addr_v6));
674 if (check_col(pinfo->cinfo, COL_INFO))
675 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
676 ip6_to_str(&orig_addr_v6));
677 offset += INET6_ADDRLEN;
679 lifetime = tvb_get_ntohl(tvb, offset);
681 proto_tree_add_uint(aodv_tree, hf_aodv_lifetime, tvb, offset, 4,
683 proto_item_append_text(ti, ", Lifetime=%u", lifetime);
685 if (check_col(pinfo->cinfo, COL_INFO))
686 col_append_fstr(pinfo->cinfo, COL_INFO, " Hcnt=%u DSN=%u Lifetime=%u",
693 extlen = tvb_reported_length_remaining(tvb, offset);
695 dissect_aodv_ext(tvb, offset, aodv_tree);
700 dissect_aodv_draft_01_v6_rerr(tvbuff_t *tvb, packet_info *pinfo,
701 proto_tree *aodv_tree)
705 proto_tree *aodv_flags_tree;
706 proto_tree *aodv_unreach_dest_tree;
711 flags = tvb_get_guint8(tvb, offset);
713 tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
714 aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
715 proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rerr_nodelete,
716 tvb, offset, 1, flags);
717 if (flags & RERR_NODEL)
718 proto_item_append_text(tj, " N");
720 offset += 2; /* skip reserved byte */
722 dest_count = tvb_get_guint8(tvb, offset);
724 proto_tree_add_uint(aodv_tree, hf_aodv_destcount, tvb, offset, 1,
726 if (check_col(pinfo->cinfo, COL_INFO))
727 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dest Count=%u",
731 tj = proto_tree_add_text(aodv_tree, tvb, offset,
732 (4 + INET6_ADDRLEN)*dest_count,
733 "Unreachable Destinations");
734 aodv_unreach_dest_tree = proto_item_add_subtree(tj, ett_aodv_unreach_dest);
735 for (i = 0; i < dest_count; i++) {
736 proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_dest_seqno,
737 tvb, offset, 4, FALSE);
738 proto_tree_add_item(aodv_unreach_dest_tree,
739 hf_aodv_unreach_dest_ipv6,
740 tvb, offset, INET6_ADDRLEN, FALSE);
741 offset += 4 + INET6_ADDRLEN;
746 dissect_aodv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
748 proto_item *ti = NULL;
749 proto_tree *aodv_tree = NULL;
753 /* Make entries in Protocol column and Info column on summary display */
754 if (check_col(pinfo->cinfo, COL_PROTOCOL))
755 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AODV");
757 if (check_col(pinfo->cinfo, COL_INFO))
758 col_clear(pinfo->cinfo, COL_INFO);
760 /* Is this running over IPv6? */
761 is_ipv6 = (pinfo->src.type == AT_IPv6);
763 /* Check the type of AODV packet. */
764 type = tvb_get_guint8(tvb, 0);
765 if (match_strval(type, type_vals) == NULL) {
767 * We assume this is not an AODV packet.
772 if (check_col(pinfo->cinfo, COL_INFO))
773 col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
774 val_to_str(type, type_vals,
775 "Unknown AODV Packet Type (%u)"));
777 ti = proto_tree_add_protocol_format(tree, proto_aodv, tvb, 0, -1,
778 "Ad hoc On-demand Distance Vector Routing Protocol, %s",
779 val_to_str(type, type_vals, "Unknown AODV Packet Type (%u)"));
780 aodv_tree = proto_item_add_subtree(ti, ett_aodv);
782 proto_tree_add_uint(aodv_tree, hf_aodv_type, tvb, 0, 1, type);
787 dissect_aodv_rreq(tvb, pinfo, tree, ti, is_ipv6);
790 dissect_aodv_rrep(tvb, pinfo, tree, ti, is_ipv6);
793 dissect_aodv_rerr(tvb, pinfo, tree, is_ipv6);
797 case DRAFT_01_V6_RREQ:
798 dissect_aodv_draft_01_v6_rreq(tvb, pinfo, tree, ti);
800 case DRAFT_01_V6_RREP:
801 dissect_aodv_draft_01_v6_rrep(tvb, pinfo, tree, ti);
803 case DRAFT_01_V6_RERR:
804 dissect_aodv_draft_01_v6_rerr(tvb, pinfo, tree);
806 case DRAFT_01_V6_RREP_ACK:
809 proto_tree_add_text(aodv_tree, tvb, 0, -1,
810 "Unknown AODV Packet Type (%u)", type);
813 return tvb_length(tvb);
817 /* Register the protocol with Ethereal */
819 proto_register_aodv(void)
821 static hf_register_info hf[] = {
823 { "Type", "aodv.type",
824 FT_UINT8, BASE_DEC, VALS(type_vals), 0x0,
825 "AODV packet type", HFILL }
828 { "Flags", "aodv.flags",
829 FT_UINT16, BASE_DEC, NULL, 0x0,
832 { &hf_aodv_flags_rreq_join,
833 { "RREQ Join", "aodv.flags.rreq_join",
834 FT_BOOLEAN, 8, TFS(&flags_set_truth), RREQ_JOIN,
837 { &hf_aodv_flags_rreq_repair,
838 { "RREQ Repair", "aodv.flags.rreq_repair",
839 FT_BOOLEAN, 8, TFS(&flags_set_truth), RREQ_REP,
842 { &hf_aodv_flags_rreq_gratuitous,
843 { "RREQ Gratuitous", "aodv.flags.rreq_gratuitous",
844 FT_BOOLEAN, 8, TFS(&flags_set_truth), RREQ_GRAT,
847 { &hf_aodv_flags_rrep_repair,
848 { "RREP Repair", "aodv.flags.rrep_repair",
849 FT_BOOLEAN, 8, TFS(&flags_set_truth), RREP_REP,
852 { &hf_aodv_flags_rrep_ack,
853 { "RREP Acknowledgement", "aodv.flags.rrep_ack",
854 FT_BOOLEAN, 8, TFS(&flags_set_truth), RREP_ACK_REQ,
857 { &hf_aodv_flags_rerr_nodelete,
858 { "RERR No Delete", "aodv.flags.rerr_nodelete",
859 FT_BOOLEAN, 8, TFS(&flags_set_truth), RERR_NODEL,
862 { &hf_aodv_prefix_sz,
863 { "Prefix Size", "aodv.prefix_sz",
864 FT_UINT8, BASE_DEC, NULL, 0x0,
865 "Prefix Size", HFILL }
868 { "Hop Count", "aodv.hopcount",
869 FT_UINT8, BASE_DEC, NULL, 0x0,
873 { "RREQ Id", "aodv.rreq_id",
874 FT_UINT32, BASE_DEC, NULL, 0x0,
878 { "Destination IP", "aodv.dest_ip",
879 FT_IPv4, BASE_NONE, NULL, 0x0,
880 "Destination IP Address", HFILL }
882 { &hf_aodv_dest_ipv6,
883 { "Destination IPv6", "aodv.dest_ipv6",
884 FT_IPv6, BASE_NONE, NULL, 0x0,
885 "Destination IPv6 Address", HFILL}
887 { &hf_aodv_dest_seqno,
888 { "Destination Sequence Number", "aodv.dest_seqno",
889 FT_UINT32, BASE_DEC, NULL, 0x0,
890 "Destination Sequence Number", HFILL }
893 { "Originator IP", "aodv.orig_ip",
894 FT_IPv4, BASE_NONE, NULL, 0x0,
895 "Originator IP Address", HFILL }
897 { &hf_aodv_orig_ipv6,
898 { "Originator IPv6", "aodv.orig_ipv6",
899 FT_IPv6, BASE_NONE, NULL, 0x0,
900 "Originator IPv6 Address", HFILL}
902 { &hf_aodv_orig_seqno,
903 { "Originator Sequence Number", "aodv.orig_seqno",
904 FT_UINT32, BASE_DEC, NULL, 0x0,
905 "Originator Sequence Number", HFILL }
908 { "Lifetime", "aodv.lifetime",
909 FT_UINT32, BASE_DEC, NULL, 0x0,
912 { &hf_aodv_destcount,
913 { "Destination Count", "aodv.destcount",
914 FT_UINT8, BASE_DEC, NULL, 0x0,
915 "Unreachable Destinations Count", HFILL }
917 { &hf_aodv_unreach_dest_ip,
918 { "Unreachable Destination IP", "aodv.unreach_dest_ip",
919 FT_IPv4, BASE_NONE, NULL, 0x0,
920 "Unreachable Destination IP Address", HFILL }
922 { &hf_aodv_unreach_dest_ipv6,
923 { "Unreachable Destination IPv6", "aodv.unreach_dest_ipv6",
924 FT_IPv6, BASE_NONE, NULL, 0x0,
925 "Unreachable Destination IPv6 Address", HFILL}
927 { &hf_aodv_unreach_dest_seqno,
928 { "Unreachable Destination Sequence Number", "aodv.unreach_dest_seqno",
929 FT_UINT32, BASE_DEC, NULL, 0x0,
930 "Unreachable Destination Sequence Number", HFILL }
933 { "Extension Type", "aodv.ext_type",
934 FT_UINT8, BASE_DEC, NULL, 0x0,
935 "Extension Format Type", HFILL}
937 { &hf_aodv_ext_length,
938 { "Extension Length", "aodv.ext_length",
939 FT_UINT8, BASE_DEC, NULL, 0x0,
940 "Extension Data Length", HFILL}
942 { &hf_aodv_ext_interval,
943 { "Hello Interval", "aodv.hello_interval",
944 FT_UINT32, BASE_DEC, NULL, 0x0,
945 "Hello Interval Extension", HFILL}
947 { &hf_aodv_ext_timestamp,
948 { "Timestamp", "aodv.timestamp",
949 FT_UINT64, BASE_DEC, NULL, 0x0,
950 "Timestamp Extension", HFILL}
954 /* Setup protocol subtree array */
955 static gint *ett[] = {
958 &ett_aodv_unreach_dest,
959 &ett_aodv_extensions,
962 /* Register the protocol name and description */
963 proto_aodv = proto_register_protocol("Ad hoc On-demand Distance Vector Routing Protocol", "AODV", "aodv");
965 /* Required function calls to register the header fields and subtrees used */
966 proto_register_field_array(proto_aodv, hf, array_length(hf));
967 proto_register_subtree_array(ett, array_length(ett));
972 proto_reg_handoff_aodv(void)
974 dissector_handle_t aodv_handle;
976 aodv_handle = new_create_dissector_handle(dissect_aodv,
978 dissector_add("udp.port", UDP_PORT_AODV, aodv_handle);