HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-aodv.c
bloba685c64698429561640ac444ff569ed98c2bbc95
1 /* packet-aodv.c
2 * Routines for AODV dissection
3 * Copyright 2000, Erik Nordstrom <erik.nordstrom@it.uu.se>
5 * $Id$
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.
26 #include "config.h"
28 #ifdef HAVE_STDDEF_H
29 #include <stddef.h>
30 #endif
32 #include <glib.h>
34 #include <epan/packet.h>
35 #include <epan/to_str.h>
37 #ifndef offsetof
38 #define offsetof(type, member) ((size_t)(&((type *)0)->member))
39 #endif
42 * See
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
60 /* Message Types */
61 #define RREQ 1
62 #define RREP 2
63 #define RERR 3
64 #define RREP_ACK 4
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
70 /* Extension Types */
71 #define AODV_EXT 1
72 #define AODV_EXT_INT 2
73 #define AODV_EXT_NTP 3
75 /* Flag bits: */
76 #define RREQ_UNKNSEQ 0x08
77 #define RREQ_DESTONLY 0x10
78 #define RREQ_GRATRREP 0x20
79 #define RREQ_REP 0x40
80 #define RREQ_JOIN 0x80
82 #define RREP_ACK_REQ 0x40
83 #define RREP_REP 0x80
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"},
96 { 0, NULL }
99 static const value_string exttype_vals[] = {
100 { AODV_EXT, "None"},
101 { AODV_EXT_INT, "Hello Interval"},
102 { AODV_EXT_NTP, "Timestamp"},
103 { 0, NULL}
106 typedef struct v6_ext {
107 guint8 type;
108 guint8 length;
109 } aodv_ext_t;
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 */
150 static void
151 dissect_aodv_ext(tvbuff_t * tvb, int offset, proto_tree * tree)
153 proto_tree *ext_tree;
154 proto_item *ti;
155 guint8 type, len;
157 if (!tree)
158 return;
160 again:
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"));
174 if (len == 0) {
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);
182 offset += 2;
184 switch (type) {
185 case AODV_EXT_INT:
186 proto_tree_add_uint(ext_tree, hf_aodv_ext_interval,
187 tvb, offset, 4, tvb_get_ntohl(tvb, offset));
188 break;
189 case AODV_EXT_NTP:
190 proto_tree_add_item(ext_tree, hf_aodv_ext_timestamp,
191 tvb, offset, 8, ENC_BIG_ENDIAN);
192 break;
193 default:
194 break;
196 /* If multifield extensions appear, we need more
197 * sophisticated handler. For now, this is okay. */
199 offset += len;
200 goto again;
203 static void
204 dissect_aodv_rreq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *aodv_tree,
205 proto_item *ti, gboolean is_ipv6)
207 int offset = 1;
208 proto_item *tj;
209 proto_tree *aodv_flags_tree;
210 guint8 flags;
211 guint8 hop_count;
212 guint32 rreq_id;
213 guint32 dest_addr_v4;
214 struct e_in6_addr dest_addr_v6;
215 guint32 dest_seqno;
216 guint32 orig_addr_v4;
217 struct e_in6_addr orig_addr_v6;
218 guint32 orig_seqno;
219 int extlen;
221 flags = tvb_get_guint8(tvb, offset);
222 if (aodv_tree) {
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);
249 if (aodv_tree)
250 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
251 hop_count);
252 offset += 1;
254 rreq_id = tvb_get_ntohl(tvb, offset);
255 if (aodv_tree)
256 proto_tree_add_uint(aodv_tree, hf_aodv_rreq_id, tvb, offset, 4,
257 rreq_id);
258 offset += 4;
260 if (is_ipv6) {
261 tvb_get_ipv6(tvb, offset, &dest_addr_v6);
262 if (aodv_tree) {
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;
271 } else {
272 dest_addr_v4 = tvb_get_ipv4(tvb, offset);
273 if (aodv_tree) {
274 proto_tree_add_ipv4(aodv_tree, hf_aodv_dest_ip, tvb, offset, 4,
275 dest_addr_v4);
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));
281 offset += 4;
284 dest_seqno = tvb_get_ntohl(tvb, offset);
285 if (aodv_tree)
286 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
287 dest_seqno);
288 offset += 4;
290 if (is_ipv6) {
291 tvb_get_ipv6(tvb, offset, &orig_addr_v6);
292 if (aodv_tree) {
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;
301 } else {
302 orig_addr_v4 = tvb_get_ipv4(tvb, offset);
303 if (aodv_tree) {
304 proto_tree_add_ipv4(aodv_tree, hf_aodv_orig_ip, tvb, offset, 4,
305 orig_addr_v4);
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));
311 offset += 4;
314 orig_seqno = tvb_get_ntohl(tvb, offset);
315 if (aodv_tree)
316 proto_tree_add_uint(aodv_tree, hf_aodv_orig_seqno, tvb, offset, 4,
317 orig_seqno);
318 col_append_fstr(pinfo->cinfo, COL_INFO, " Id=%u Hcnt=%u DSN=%u OSN=%u",
319 rreq_id,
320 hop_count,
321 dest_seqno,
322 orig_seqno);
323 offset += 4;
325 if (aodv_tree) {
326 extlen = tvb_reported_length_remaining(tvb, offset);
327 if (extlen > 0)
328 dissect_aodv_ext(tvb, offset, aodv_tree);
332 static void
333 dissect_aodv_rrep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *aodv_tree,
334 proto_item *ti, gboolean is_ipv6)
336 int offset = 1;
337 proto_item *tj;
338 proto_tree *aodv_flags_tree;
339 guint8 flags;
340 guint8 prefix_sz;
341 guint8 hop_count;
342 guint32 dest_addr_v4;
343 struct e_in6_addr dest_addr_v6;
344 guint32 dest_seqno;
345 guint32 orig_addr_v4;
346 struct e_in6_addr orig_addr_v6;
347 guint32 lifetime;
348 int extlen;
350 flags = tvb_get_guint8(tvb, offset);
351 if (aodv_tree) {
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,
357 offset, 1, flags);
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");
363 offset += 1;
365 prefix_sz = tvb_get_guint8(tvb, offset) & 0x1F;
366 if (aodv_tree)
367 proto_tree_add_uint(aodv_tree, hf_aodv_prefix_sz, tvb, offset, 1,
368 prefix_sz);
369 offset += 1;
371 hop_count = tvb_get_guint8(tvb, offset);
372 if (aodv_tree)
373 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
374 hop_count);
375 offset += 1;
377 if (is_ipv6) {
378 tvb_get_ipv6(tvb, offset, &dest_addr_v6);
379 if (aodv_tree) {
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;
389 } else {
390 dest_addr_v4 = tvb_get_ipv4(tvb, offset);
391 if (aodv_tree) {
392 proto_tree_add_ipv4(aodv_tree, hf_aodv_dest_ip, tvb, offset, 4,
393 dest_addr_v4);
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));
399 offset += 4;
402 dest_seqno = tvb_get_ntohl(tvb, offset);
403 if (aodv_tree)
404 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
405 dest_seqno);
406 offset += 4;
408 if (is_ipv6) {
409 tvb_get_ipv6(tvb, offset, &orig_addr_v6);
410 if (aodv_tree) {
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;
419 } else {
420 orig_addr_v4 = tvb_get_ipv4(tvb, offset);
421 if (aodv_tree) {
422 proto_tree_add_ipv4(aodv_tree, hf_aodv_orig_ip, tvb, offset, 4,
423 orig_addr_v4);
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));
429 offset += 4;
432 lifetime = tvb_get_ntohl(tvb, offset);
433 if (aodv_tree) {
434 proto_tree_add_uint(aodv_tree, hf_aodv_lifetime, tvb, offset, 4,
435 lifetime);
436 proto_item_append_text(ti, ", Lifetime=%u", lifetime);
439 col_append_fstr(pinfo->cinfo, COL_INFO, " Hcnt=%u DSN=%u Lifetime=%u",
440 hop_count,
441 dest_seqno,
442 lifetime);
443 offset += 4;
445 if (aodv_tree) {
446 extlen = tvb_reported_length_remaining(tvb, offset);
447 if (extlen > 0)
448 dissect_aodv_ext(tvb, offset, aodv_tree);
452 static void
453 dissect_aodv_rerr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *aodv_tree,
454 gboolean is_ipv6)
456 int offset = 1;
457 proto_item *tj;
458 proto_tree *aodv_flags_tree;
459 proto_tree *aodv_unreach_dest_tree;
460 guint8 flags;
461 guint8 dest_count;
462 int i;
464 flags = tvb_get_guint8(tvb, offset);
465 if (aodv_tree) {
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);
476 if (aodv_tree)
477 proto_tree_add_uint(aodv_tree, hf_aodv_destcount, tvb, offset, 1,
478 dest_count);
479 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dest Count=%u",
480 dest_count);
481 offset += 1;
483 if (is_ipv6) {
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);
495 offset += 4;
497 } else {
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);
504 offset += 4;
505 proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_dest_seqno,
506 tvb, offset, 4, ENC_BIG_ENDIAN);
507 offset += 4;
512 static void
513 dissect_aodv_draft_01_v6_rreq(tvbuff_t *tvb, packet_info *pinfo,
514 proto_tree *aodv_tree, proto_item *ti)
516 int offset = 1;
517 proto_item *tj;
518 proto_tree *aodv_flags_tree;
519 guint8 flags;
520 guint8 hop_count;
521 guint32 rreq_id;
522 guint32 dest_seqno;
523 guint32 orig_seqno;
524 struct e_in6_addr dest_addr_v6;
525 struct e_in6_addr orig_addr_v6;
526 int extlen;
528 flags = tvb_get_guint8(tvb, offset);
529 if (aodv_tree) {
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);
556 if (aodv_tree)
557 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
558 hop_count);
559 offset += 1;
561 rreq_id = tvb_get_ntohl(tvb, offset);
562 if (aodv_tree)
563 proto_tree_add_uint(aodv_tree, hf_aodv_rreq_id, tvb, offset, 4,
564 rreq_id);
565 offset += 4;
567 dest_seqno = tvb_get_ntohl(tvb, offset);
568 if (aodv_tree)
569 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
570 dest_seqno);
571 offset += 4;
573 orig_seqno = tvb_get_ntohl(tvb, offset);
574 if (aodv_tree)
575 proto_tree_add_uint(aodv_tree, hf_aodv_orig_seqno, tvb, offset, 4,
576 orig_seqno);
577 offset += 4;
579 tvb_get_ipv6(tvb, offset, &dest_addr_v6);
580 if (aodv_tree) {
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);
592 if (aodv_tree) {
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),
602 rreq_id,
603 hop_count,
604 dest_seqno,
605 orig_seqno);
606 offset += INET6_ADDRLEN;
608 if (aodv_tree) {
609 extlen = tvb_reported_length_remaining(tvb, offset);
610 if (extlen > 0)
611 dissect_aodv_ext(tvb, offset, aodv_tree);
615 static void
616 dissect_aodv_draft_01_v6_rrep(tvbuff_t *tvb, packet_info *pinfo,
617 proto_tree *aodv_tree, proto_item *ti)
619 int offset = 1;
620 proto_item *tj;
621 proto_tree *aodv_flags_tree;
622 guint8 flags;
623 guint8 prefix_sz;
624 guint8 hop_count;
625 guint32 dest_seqno;
626 struct e_in6_addr dest_addr_v6;
627 struct e_in6_addr orig_addr_v6;
628 guint32 lifetime;
629 int extlen;
631 flags = tvb_get_guint8(tvb, offset);
632 if (aodv_tree) {
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,
638 offset, 1, flags);
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");
644 offset += 1;
646 prefix_sz = tvb_get_guint8(tvb, offset) & 0x7F;
647 if (aodv_tree)
648 proto_tree_add_uint(aodv_tree, hf_aodv_prefix_sz, tvb, offset, 1,
649 prefix_sz);
650 offset += 1;
652 hop_count = tvb_get_guint8(tvb, offset);
653 if (aodv_tree)
654 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
655 hop_count);
656 offset += 1;
658 dest_seqno = tvb_get_ntohl(tvb, offset);
659 if (aodv_tree)
660 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
661 dest_seqno);
662 offset += 4;
664 tvb_get_ipv6(tvb, offset, &dest_addr_v6);
665 if (aodv_tree) {
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);
677 if (aodv_tree) {
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);
689 if (aodv_tree) {
690 proto_tree_add_uint(aodv_tree, hf_aodv_lifetime, tvb, offset, 4,
691 lifetime);
692 proto_item_append_text(ti, ", Lifetime=%u", lifetime);
695 col_append_fstr(pinfo->cinfo, COL_INFO, " Hcnt=%u DSN=%u Lifetime=%u",
696 hop_count,
697 dest_seqno,
698 lifetime);
699 offset += 4;
701 if (aodv_tree) {
702 extlen = tvb_reported_length_remaining(tvb, offset);
703 if (extlen > 0)
704 dissect_aodv_ext(tvb, offset, aodv_tree);
708 static void
709 dissect_aodv_draft_01_v6_rerr(tvbuff_t *tvb, packet_info *pinfo,
710 proto_tree *aodv_tree)
712 int offset = 1;
713 proto_item *tj;
714 proto_tree *aodv_flags_tree;
715 proto_tree *aodv_unreach_dest_tree;
716 guint8 flags;
717 guint8 dest_count;
718 int i;
720 flags = tvb_get_guint8(tvb, offset);
721 if (aodv_tree) {
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);
732 if (aodv_tree)
733 proto_tree_add_uint(aodv_tree, hf_aodv_destcount, tvb, offset, 1,
734 dest_count);
736 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dest Count=%u",
737 dest_count);
738 offset += 1;
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);
747 offset += 4;
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;
755 static int
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;
760 gboolean is_ipv6;
761 guint8 type;
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.
777 return 0;
781 col_add_str(pinfo->cinfo, COL_INFO,
782 val_to_str(type, type_vals,
783 "Unknown AODV Packet Type (%u)"));
784 if (tree) {
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);
793 switch (type) {
794 case RREQ:
795 dissect_aodv_rreq(tvb, pinfo, aodv_tree, ti, is_ipv6);
796 break;
797 case RREP:
798 dissect_aodv_rrep(tvb, pinfo, aodv_tree, ti, is_ipv6);
799 break;
800 case RERR:
801 dissect_aodv_rerr(tvb, pinfo, aodv_tree, is_ipv6);
802 break;
803 case RREP_ACK:
804 break;
805 case DRAFT_01_V6_RREQ:
806 dissect_aodv_draft_01_v6_rreq(tvb, pinfo, aodv_tree, ti);
807 break;
808 case DRAFT_01_V6_RREP:
809 dissect_aodv_draft_01_v6_rrep(tvb, pinfo, aodv_tree, ti);
810 break;
811 case DRAFT_01_V6_RERR:
812 dissect_aodv_draft_01_v6_rerr(tvb, pinfo, aodv_tree);
813 break;
814 case DRAFT_01_V6_RREP_ACK:
815 break;
816 default:
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 */
826 void
827 proto_register_aodv(void)
829 static hf_register_info hf[] = {
830 { &hf_aodv_type,
831 { "Type", "aodv.type",
832 FT_UINT8, BASE_DEC, VALS(type_vals), 0x0,
833 "AODV packet type", HFILL }
835 #if 0
836 { &hf_aodv_flags,
837 { "Flags", "aodv.flags",
838 FT_UINT16, BASE_DEC, NULL, 0x0,
839 NULL, HFILL }
841 #endif
842 { &hf_aodv_flags_rreq_join,
843 { "RREQ Join", "aodv.flags.rreq_join",
844 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RREQ_JOIN,
845 NULL, HFILL }
847 { &hf_aodv_flags_rreq_repair,
848 { "RREQ Repair", "aodv.flags.rreq_repair",
849 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RREQ_REP,
850 NULL, HFILL }
852 { &hf_aodv_flags_rreq_gratuitous,
853 { "RREQ Gratuitous RREP", "aodv.flags.rreq_gratuitous",
854 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RREQ_GRATRREP,
855 NULL, HFILL }
857 { &hf_aodv_flags_rreq_destinationonly,
858 { "RREQ Destination only", "aodv.flags.rreq_destinationonly",
859 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RREQ_DESTONLY,
860 NULL, HFILL }
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,
865 NULL, HFILL }
867 { &hf_aodv_flags_rrep_repair,
868 { "RREP Repair", "aodv.flags.rrep_repair",
869 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RREP_REP,
870 NULL, HFILL }
872 { &hf_aodv_flags_rrep_ack,
873 { "RREP Acknowledgement", "aodv.flags.rrep_ack",
874 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RREP_ACK_REQ,
875 NULL, HFILL }
877 { &hf_aodv_flags_rerr_nodelete,
878 { "RERR No Delete", "aodv.flags.rerr_nodelete",
879 FT_BOOLEAN, 8, TFS(&tfs_set_notset), RERR_NODEL,
880 NULL, HFILL }
882 { &hf_aodv_prefix_sz,
883 { "Prefix Size", "aodv.prefix_sz",
884 FT_UINT8, BASE_DEC, NULL, 0x0,
885 NULL, HFILL }
887 { &hf_aodv_hopcount,
888 { "Hop Count", "aodv.hopcount",
889 FT_UINT8, BASE_DEC, NULL, 0x0,
890 NULL, HFILL }
892 { &hf_aodv_rreq_id,
893 { "RREQ Id", "aodv.rreq_id",
894 FT_UINT32, BASE_DEC, NULL, 0x0,
895 NULL, HFILL }
897 { &hf_aodv_dest_ip,
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,
910 NULL, HFILL }
912 { &hf_aodv_orig_ip,
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,
925 NULL, HFILL }
927 { &hf_aodv_lifetime,
928 { "Lifetime", "aodv.lifetime",
929 FT_UINT32, BASE_DEC, NULL, 0x0,
930 NULL, HFILL }
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}
947 #if 0
948 { &hf_aodv_unreach_dest_seqno,
949 { "Unreachable Destination Sequence Number", "aodv.unreach_dest_seqno",
950 FT_UINT32, BASE_DEC, NULL, 0x0,
951 NULL, HFILL }
953 { &hf_aodv_ext_type,
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}
963 #endif
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[] = {
978 &ett_aodv,
979 &ett_aodv_flags,
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));
993 void
994 proto_reg_handoff_aodv(void)
996 dissector_handle_t aodv_handle;
998 aodv_handle = new_create_dissector_handle(dissect_aodv,
999 proto_aodv);
1000 dissector_add_uint("udp.port", UDP_PORT_AODV, aodv_handle);