Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-aodv.c
blob0f33665b45c1f222d4acf00b5e709335ef7e4af3
1 /* packet-aodv.c
2 * Routines for AODV dissection
3 * Copyright 2000, Erik Nordstrom <erik.nordstrom@it.uu.se>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/to_str.h>
16 #include <epan/expert.h>
17 #include <epan/tfs.h>
18 #include <epan/unit_strings.h>
21 * See
23 * RFC 3561 (which indicates that, for IPv6, the only change is that
24 * the address fields are enlarged)
26 * http://www.cs.ucsb.edu/~ebelding/txt/aodv6.txt
28 * http://www.tcs.hut.fi/~anttit/manet/drafts/draft-perkins-aodv6-01.txt
30 * (both of the above two are draft-perkins-manet-aodv6-01.txt, which
31 * is from November 2000)
33 void proto_register_aodv(void);
34 void proto_reg_handoff_aodv(void);
35 static dissector_handle_t aodv_handle;
37 #define INET6_ADDRLEN 16
38 #define UDP_PORT_AODV 654
40 /* Message Types */
41 #define RREQ 1
42 #define RREP 2
43 #define RERR 3
44 #define RREP_ACK 4
45 #define DRAFT_01_V6_RREQ 16
46 #define DRAFT_01_V6_RREP 17
47 #define DRAFT_01_V6_RERR 18
48 #define DRAFT_01_V6_RREP_ACK 19
50 /* Extension Types */
51 #define AODV_EXT 1
52 #define AODV_EXT_INT 2
53 #define AODV_EXT_NTP 3
55 /* Flag bits: */
56 #define RREQ_UNKNSEQ 0x0800
57 #define RREQ_DESTONLY 0x1000
58 #define RREQ_GRATRREP 0x2000
59 #define RREQ_REP 0x4000
60 #define RREQ_JOIN 0x8000
62 #define RREP_ACK_REQ 0x4000
63 #define RREP_REP 0x8000
65 #define RERR_NODEL 0x8000
67 static const value_string type_vals[] = {
68 { RREQ, "Route Request" },
69 { RREP, "Route Reply" },
70 { RERR, "Route Error" },
71 { RREP_ACK, "Route Reply Acknowledgment"},
72 { DRAFT_01_V6_RREQ, "draft-perkins-manet-aodv6-01 IPv6 Route Request"},
73 { DRAFT_01_V6_RREP, "draft-perkins-manet-aodv6-01 IPv6 Route Reply"},
74 { DRAFT_01_V6_RERR, "draft-perkins-manet-aodv6-01 IPv6 Route Error"},
75 { DRAFT_01_V6_RREP_ACK, "draft-perkins-manet-aodv6-01 IPv6 Route Reply Acknowledgment"},
76 { 0, NULL }
79 static const value_string exttype_vals[] = {
80 { AODV_EXT, "None"},
81 { AODV_EXT_INT, "Hello Interval"},
82 { AODV_EXT_NTP, "Timestamp"},
83 { 0, NULL}
86 typedef struct v6_ext {
87 uint8_t type;
88 uint8_t length;
89 } aodv_ext_t;
91 /* Initialize the protocol and registered fields */
92 static int proto_aodv;
93 static int hf_aodv_type;
94 static int hf_aodv_flags;
95 static int hf_aodv_prefix_sz;
96 static int hf_aodv_hopcount;
97 static int hf_aodv_rreq_id;
98 static int hf_aodv_dest_ip;
99 static int hf_aodv_dest_ipv6;
100 static int hf_aodv_dest_seqno;
101 static int hf_aodv_orig_ip;
102 static int hf_aodv_orig_ipv6;
103 static int hf_aodv_orig_seqno;
104 static int hf_aodv_lifetime;
105 static int hf_aodv_destcount;
106 static int hf_aodv_unreach_dest_ip;
107 static int hf_aodv_unreach_dest_ipv6;
108 /* static int hf_aodv_unreach_dest_seqno; */
109 static int hf_aodv_flags_rreq_join;
110 static int hf_aodv_flags_rreq_repair;
111 static int hf_aodv_flags_rreq_gratuitous;
112 static int hf_aodv_flags_rreq_destinationonly;
113 static int hf_aodv_flags_rreq_unknown;
114 static int hf_aodv_flags_rrep_repair;
115 static int hf_aodv_flags_rrep_ack;
116 static int hf_aodv_flags_rerr_nodelete;
117 static int hf_aodv_ext_type;
118 static int hf_aodv_ext_length;
119 static int hf_aodv_ext_interval;
120 static int hf_aodv_ext_timestamp;
122 /* Initialize the subtree pointers */
123 static int ett_aodv;
124 static int ett_aodv_flags;
125 static int ett_aodv_unreach_dest;
126 static int ett_aodv_extensions;
128 static expert_field ei_aodv_ext_length;
129 static expert_field ei_aodv_type;
131 /* Code to actually dissect the packets */
133 static void
134 dissect_aodv_ext(tvbuff_t * tvb, packet_info *pinfo, int offset, proto_tree * tree)
136 proto_tree *ext_tree;
137 proto_item *len_item;
138 uint8_t type, len;
140 again:
141 if ((int) tvb_reported_length(tvb) <= offset)
142 return; /* No more options left */
144 type = tvb_get_uint8(tvb, offset);
145 len = tvb_get_uint8(tvb, offset + 1);
147 ext_tree = proto_tree_add_subtree(tree, tvb, offset, 2 + len, ett_aodv_extensions, NULL, "Extensions");
149 proto_tree_add_item(ext_tree, hf_aodv_ext_type, tvb, offset, 1, ENC_BIG_ENDIAN);
151 len_item = proto_tree_add_uint(ext_tree, hf_aodv_ext_length, tvb, offset + 1, 1, len);
152 if (len == 0) {
153 expert_add_info(pinfo, len_item, &ei_aodv_ext_length);
154 return; /* we must not try to decode this */
157 offset += 2;
159 switch (type) {
160 case AODV_EXT_INT:
161 proto_tree_add_item(ext_tree, hf_aodv_ext_interval,
162 tvb, offset, 4, ENC_BIG_ENDIAN);
163 break;
164 case AODV_EXT_NTP:
165 proto_tree_add_item(ext_tree, hf_aodv_ext_timestamp,
166 tvb, offset, 8, ENC_BIG_ENDIAN);
167 break;
168 default:
169 break;
171 /* If multifield extensions appear, we need more
172 * sophisticated handler. For now, this is okay. */
174 offset += len;
175 goto again;
178 static void
179 dissect_aodv_rreq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *aodv_tree,
180 proto_item *ti, bool is_ipv6)
182 int offset = 1;
183 uint8_t hop_count;
184 uint32_t rreq_id;
185 const char *dest_addr_v4;
186 const char *dest_addr_v6;
187 uint32_t dest_seqno;
188 const char *orig_addr_v4;
189 const char *orig_addr_v6;
190 uint32_t orig_seqno;
191 int extlen;
192 static int * const aodv_flags[] = {
193 &hf_aodv_flags_rreq_join,
194 &hf_aodv_flags_rreq_repair,
195 &hf_aodv_flags_rreq_gratuitous,
196 &hf_aodv_flags_rreq_destinationonly,
197 &hf_aodv_flags_rreq_unknown,
198 NULL
201 proto_tree_add_bitmask_with_flags(aodv_tree, tvb, offset, hf_aodv_flags,
202 ett_aodv_flags, aodv_flags, ENC_BIG_ENDIAN, BMT_NO_FALSE | BMT_NO_TFS | BMT_NO_INT);
203 offset += 2; /* skip reserved byte */
205 hop_count = tvb_get_uint8(tvb, offset);
206 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
207 hop_count);
208 offset += 1;
210 rreq_id = tvb_get_ntohl(tvb, offset);
211 proto_tree_add_uint(aodv_tree, hf_aodv_rreq_id, tvb, offset, 4,
212 rreq_id);
213 offset += 4;
215 if (is_ipv6) {
216 dest_addr_v6 = tvb_ip6_to_str(pinfo->pool, tvb, offset);
217 if (aodv_tree) {
218 proto_tree_add_item(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
219 INET6_ADDRLEN, ENC_NA);
220 proto_item_append_text(ti, ", Dest IP: %s", dest_addr_v6);
222 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s", dest_addr_v6);
223 offset += INET6_ADDRLEN;
224 } else {
225 dest_addr_v4 = tvb_ip_to_str(pinfo->pool, tvb, offset);
226 if (aodv_tree) {
227 proto_tree_add_item(aodv_tree, hf_aodv_dest_ip, tvb, offset, 4,
228 ENC_BIG_ENDIAN);
229 proto_item_append_text(ti, ", Dest IP: %s", dest_addr_v4);
231 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s", dest_addr_v4);
232 offset += 4;
235 dest_seqno = tvb_get_ntohl(tvb, offset);
236 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
237 dest_seqno);
238 offset += 4;
240 if (is_ipv6) {
241 orig_addr_v6 = tvb_ip6_to_str(pinfo->pool, tvb, offset);
242 if (aodv_tree) {
243 proto_tree_add_item(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
244 INET6_ADDRLEN, ENC_NA);
245 proto_item_append_text(ti, ", Orig IP: %s", orig_addr_v6);
247 col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s", orig_addr_v6);
248 offset += INET6_ADDRLEN;
249 } else {
250 orig_addr_v4 = tvb_ip_to_str(pinfo->pool, tvb, offset);
251 if (aodv_tree) {
252 proto_tree_add_item(aodv_tree, hf_aodv_orig_ip, tvb, offset, 4,
253 ENC_BIG_ENDIAN);
254 proto_item_append_text(ti, ", Orig IP: %s", orig_addr_v4);
256 col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s", orig_addr_v4);
257 offset += 4;
260 orig_seqno = tvb_get_ntohl(tvb, offset);
261 proto_tree_add_uint(aodv_tree, hf_aodv_orig_seqno, tvb, offset, 4,
262 orig_seqno);
263 col_append_fstr(pinfo->cinfo, COL_INFO, " Id=%u Hcnt=%u DSN=%u OSN=%u",
264 rreq_id,
265 hop_count,
266 dest_seqno,
267 orig_seqno);
268 offset += 4;
270 extlen = tvb_reported_length_remaining(tvb, offset);
271 if (extlen > 0)
272 dissect_aodv_ext(tvb, pinfo, offset, aodv_tree);
275 static void
276 dissect_aodv_rrep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *aodv_tree,
277 proto_item *ti, bool is_ipv6)
279 int offset = 1;
280 uint16_t flags;
281 uint8_t prefix_sz;
282 uint8_t hop_count;
283 const char *dest_addr_v4;
284 const char *dest_addr_v6;
285 uint32_t dest_seqno;
286 const char *orig_addr_v4;
287 const char *orig_addr_v6;
288 uint32_t lifetime;
289 int extlen;
290 static int * const aodv_flags[] = {
291 &hf_aodv_flags_rrep_repair,
292 &hf_aodv_flags_rrep_ack,
293 NULL
296 flags = tvb_get_ntohs(tvb, offset);
297 proto_tree_add_bitmask_with_flags(aodv_tree, tvb, offset, hf_aodv_flags,
298 ett_aodv_flags, aodv_flags, ENC_BIG_ENDIAN, BMT_NO_FALSE | BMT_NO_TFS | BMT_NO_INT);
299 offset += 1;
301 prefix_sz = flags & 0x1F;
302 if (aodv_tree)
303 proto_tree_add_uint(aodv_tree, hf_aodv_prefix_sz, tvb, offset, 1,
304 prefix_sz);
305 offset += 1;
307 hop_count = tvb_get_uint8(tvb, offset);
308 if (aodv_tree)
309 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
310 hop_count);
311 offset += 1;
313 if (is_ipv6) {
314 dest_addr_v6 = tvb_ip6_to_str(pinfo->pool, tvb, offset);
315 if (aodv_tree) {
316 proto_tree_add_item(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
317 INET6_ADDRLEN, ENC_NA);
318 proto_item_append_text(ti, ", Dest IP: %s", dest_addr_v6);
321 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s", dest_addr_v6);
322 offset += INET6_ADDRLEN;
323 } else {
324 dest_addr_v4 = tvb_ip_to_str(pinfo->pool, tvb, offset);
325 if (aodv_tree) {
326 proto_tree_add_item(aodv_tree, hf_aodv_dest_ip, tvb, offset, 4,
327 ENC_BIG_ENDIAN);
328 proto_item_append_text(ti, ", Dest IP: %s", dest_addr_v4);
330 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s", dest_addr_v4);
331 offset += 4;
334 dest_seqno = tvb_get_ntohl(tvb, offset);
335 if (aodv_tree)
336 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
337 dest_seqno);
338 offset += 4;
340 if (is_ipv6) {
341 orig_addr_v6 = tvb_ip6_to_str(pinfo->pool, tvb, offset);
342 if (aodv_tree) {
343 proto_tree_add_item(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
344 INET6_ADDRLEN, ENC_NA);
345 proto_item_append_text(ti, ", Orig IP: %s", orig_addr_v6);
347 col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s", orig_addr_v6);
348 offset += INET6_ADDRLEN;
349 } else {
350 orig_addr_v4 = tvb_ip_to_str(pinfo->pool, tvb, offset);
351 if (aodv_tree) {
352 proto_tree_add_item(aodv_tree, hf_aodv_orig_ip, tvb, offset, 4,
353 ENC_BIG_ENDIAN);
354 proto_item_append_text(ti, ", Orig IP: %s", orig_addr_v4);
356 col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s", orig_addr_v4);
357 offset += 4;
360 lifetime = tvb_get_ntohl(tvb, offset);
361 if (aodv_tree) {
362 proto_tree_add_uint(aodv_tree, hf_aodv_lifetime, tvb, offset, 4,
363 lifetime);
364 proto_item_append_text(ti, ", Lifetime=%u", lifetime);
367 col_append_fstr(pinfo->cinfo, COL_INFO, " Hcnt=%u DSN=%u Lifetime=%u",
368 hop_count,
369 dest_seqno,
370 lifetime);
371 offset += 4;
373 extlen = tvb_reported_length_remaining(tvb, offset);
374 if (extlen > 0)
375 dissect_aodv_ext(tvb, pinfo, offset, aodv_tree);
378 static void
379 dissect_aodv_rerr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *aodv_tree,
380 bool is_ipv6)
382 int offset = 1;
383 proto_tree *aodv_unreach_dest_tree;
384 uint8_t dest_count;
385 int i;
386 static int * const aodv_flags[] = {
387 &hf_aodv_flags_rerr_nodelete,
388 NULL
391 proto_tree_add_bitmask_with_flags(aodv_tree, tvb, offset, hf_aodv_flags,
392 ett_aodv_flags, aodv_flags, ENC_BIG_ENDIAN, BMT_NO_FALSE | BMT_NO_TFS | BMT_NO_INT);
393 offset += 2; /* skip reserved byte */
395 dest_count = tvb_get_uint8(tvb, offset);
396 if (aodv_tree)
397 proto_tree_add_uint(aodv_tree, hf_aodv_destcount, tvb, offset, 1,
398 dest_count);
399 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dest Count=%u",
400 dest_count);
401 offset += 1;
403 if (is_ipv6) {
404 aodv_unreach_dest_tree = proto_tree_add_subtree(aodv_tree, tvb, offset,
405 (INET6_ADDRLEN + 4)*dest_count, ett_aodv_unreach_dest, NULL,
406 "Unreachable Destinations");
407 for (i = 0; i < dest_count; i++) {
408 proto_tree_add_item(aodv_unreach_dest_tree,
409 hf_aodv_unreach_dest_ipv6,
410 tvb, offset, INET6_ADDRLEN, ENC_NA);
411 offset += INET6_ADDRLEN;
412 proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_dest_seqno,
413 tvb, offset, 4, ENC_BIG_ENDIAN);
414 offset += 4;
416 } else {
417 aodv_unreach_dest_tree = proto_tree_add_subtree(aodv_tree, tvb, offset, (4 + 4)*dest_count,
418 ett_aodv_unreach_dest, NULL, "Unreachable Destinations");
419 for (i = 0; i < dest_count; i++) {
420 proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_unreach_dest_ip,
421 tvb, offset, 4, ENC_BIG_ENDIAN);
422 offset += 4;
423 proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_dest_seqno,
424 tvb, offset, 4, ENC_BIG_ENDIAN);
425 offset += 4;
430 static void
431 dissect_aodv_draft_01_v6_rreq(tvbuff_t *tvb, packet_info *pinfo,
432 proto_tree *aodv_tree, proto_item *ti)
434 int offset = 1;
435 uint8_t hop_count;
436 uint32_t rreq_id;
437 uint32_t dest_seqno;
438 uint32_t orig_seqno;
439 const char *dest_addr_v6;
440 const char *orig_addr_v6;
441 int extlen;
442 static int * const aodv_flags[] = {
443 &hf_aodv_flags_rreq_join,
444 &hf_aodv_flags_rreq_repair,
445 &hf_aodv_flags_rreq_gratuitous,
446 &hf_aodv_flags_rreq_destinationonly,
447 &hf_aodv_flags_rreq_unknown,
448 NULL
451 proto_tree_add_bitmask_with_flags(aodv_tree, tvb, offset, hf_aodv_flags,
452 ett_aodv_flags, aodv_flags, ENC_BIG_ENDIAN, BMT_NO_FALSE | BMT_NO_TFS | BMT_NO_INT);
453 offset += 2; /* skip reserved byte */
455 hop_count = tvb_get_uint8(tvb, offset);
456 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
457 hop_count);
458 offset += 1;
460 rreq_id = tvb_get_ntohl(tvb, offset);
461 proto_tree_add_uint(aodv_tree, hf_aodv_rreq_id, tvb, offset, 4,
462 rreq_id);
463 offset += 4;
465 dest_seqno = tvb_get_ntohl(tvb, offset);
466 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
467 dest_seqno);
468 offset += 4;
470 orig_seqno = tvb_get_ntohl(tvb, offset);
471 proto_tree_add_uint(aodv_tree, hf_aodv_orig_seqno, tvb, offset, 4,
472 orig_seqno);
473 offset += 4;
475 dest_addr_v6 = tvb_ip6_to_str(pinfo->pool, tvb, offset);
476 if (aodv_tree) {
477 proto_tree_add_item(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
478 INET6_ADDRLEN, ENC_NA);
479 proto_item_append_text(ti, ", Dest IP: %s", dest_addr_v6);
482 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s", dest_addr_v6);
483 offset += INET6_ADDRLEN;
485 orig_addr_v6 = tvb_ip6_to_str(pinfo->pool, tvb, offset);
486 if (aodv_tree) {
487 proto_tree_add_item(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
488 INET6_ADDRLEN, ENC_NA);
489 proto_item_append_text(ti, ", Orig IP: %s", orig_addr_v6);
492 col_append_fstr(pinfo->cinfo, COL_INFO,
493 ", O: %s Id=%u Hcnt=%u DSN=%u OSN=%u",
494 orig_addr_v6,
495 rreq_id,
496 hop_count,
497 dest_seqno,
498 orig_seqno);
499 offset += INET6_ADDRLEN;
501 extlen = tvb_reported_length_remaining(tvb, offset);
502 if (extlen > 0)
503 dissect_aodv_ext(tvb, pinfo, offset, aodv_tree);
506 static void
507 dissect_aodv_draft_01_v6_rrep(tvbuff_t *tvb, packet_info *pinfo,
508 proto_tree *aodv_tree, proto_item *ti)
510 int offset = 1;
511 uint16_t flags;
512 uint8_t prefix_sz;
513 uint8_t hop_count;
514 uint32_t dest_seqno;
515 const char *dest_addr_v6;
516 const char *orig_addr_v6;
517 uint32_t lifetime;
518 int extlen;
519 static int * const aodv_flags[] = {
520 &hf_aodv_flags_rrep_repair,
521 &hf_aodv_flags_rrep_ack,
522 NULL
525 flags = tvb_get_ntohs(tvb, offset);
526 proto_tree_add_bitmask_with_flags(aodv_tree, tvb, offset, hf_aodv_flags,
527 ett_aodv_flags, aodv_flags, ENC_BIG_ENDIAN, BMT_NO_FALSE | BMT_NO_TFS | BMT_NO_INT);
528 offset += 1;
530 prefix_sz = flags & 0x7F;
531 proto_tree_add_uint(aodv_tree, hf_aodv_prefix_sz, tvb, offset, 1,
532 prefix_sz);
533 offset += 1;
535 hop_count = tvb_get_uint8(tvb, offset);
536 proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
537 hop_count);
538 offset += 1;
540 dest_seqno = tvb_get_ntohl(tvb, offset);
541 proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
542 dest_seqno);
543 offset += 4;
545 dest_addr_v6 = tvb_ip6_to_str(pinfo->pool, tvb, offset);
546 if (aodv_tree) {
547 proto_tree_add_item(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
548 INET6_ADDRLEN, ENC_NA);
549 proto_item_append_text(ti, ", Dest IP: %s", dest_addr_v6);
552 col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s", dest_addr_v6);
553 offset += INET6_ADDRLEN;
555 orig_addr_v6 = tvb_ip6_to_str(pinfo->pool, tvb, offset);
556 if (aodv_tree) {
557 proto_tree_add_item(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
558 INET6_ADDRLEN, ENC_NA);
559 proto_item_append_text(ti, ", Orig IP: %s", orig_addr_v6);
562 col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s", orig_addr_v6);
563 offset += INET6_ADDRLEN;
565 lifetime = tvb_get_ntohl(tvb, offset);
566 if (aodv_tree) {
567 proto_tree_add_uint(aodv_tree, hf_aodv_lifetime, tvb, offset, 4,
568 lifetime);
569 proto_item_append_text(ti, ", Lifetime=%u", lifetime);
572 col_append_fstr(pinfo->cinfo, COL_INFO, " Hcnt=%u DSN=%u Lifetime=%u",
573 hop_count,
574 dest_seqno,
575 lifetime);
576 offset += 4;
578 extlen = tvb_reported_length_remaining(tvb, offset);
579 if (extlen > 0)
580 dissect_aodv_ext(tvb, pinfo, offset, aodv_tree);
583 static void
584 dissect_aodv_draft_01_v6_rerr(tvbuff_t *tvb, packet_info *pinfo,
585 proto_tree *aodv_tree)
587 int offset = 1;
588 proto_tree *aodv_unreach_dest_tree;
589 uint8_t dest_count;
590 int i;
591 static int * const aodv_flags[] = {
592 &hf_aodv_flags_rerr_nodelete,
593 NULL
596 proto_tree_add_bitmask_with_flags(aodv_tree, tvb, offset, hf_aodv_flags,
597 ett_aodv_flags, aodv_flags, ENC_BIG_ENDIAN, BMT_NO_FALSE | BMT_NO_TFS | BMT_NO_INT);
598 offset += 2; /* skip reserved byte */
600 dest_count = tvb_get_uint8(tvb, offset);
601 proto_tree_add_uint(aodv_tree, hf_aodv_destcount, tvb, offset, 1,
602 dest_count);
604 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dest Count=%u",
605 dest_count);
606 offset += 1;
608 aodv_unreach_dest_tree = proto_tree_add_subtree(aodv_tree, tvb, offset,
609 (4 + INET6_ADDRLEN)*dest_count,
610 ett_aodv_unreach_dest, NULL,
611 "Unreachable Destinations");
612 for (i = 0; i < dest_count; i++) {
613 proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_dest_seqno,
614 tvb, offset, 4, ENC_BIG_ENDIAN);
615 offset += 4;
616 proto_tree_add_item(aodv_unreach_dest_tree,
617 hf_aodv_unreach_dest_ipv6,
618 tvb, offset, INET6_ADDRLEN, ENC_NA);
619 offset += INET6_ADDRLEN;
623 static int
624 dissect_aodv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
626 proto_item *ti, *type_item;
627 proto_tree *aodv_tree;
628 bool is_ipv6;
629 uint8_t type;
631 /* Make entries in Protocol column and Info column on summary display */
632 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AODV");
634 col_clear(pinfo->cinfo, COL_INFO);
636 /* Is this running over IPv6? */
637 is_ipv6 = (pinfo->src.type == AT_IPv6);
639 /* Check the type of AODV packet. */
640 type = tvb_get_uint8(tvb, 0);
641 if (try_val_to_str(type, type_vals) == NULL) {
643 * We assume this is not an AODV packet.
645 return 0;
649 col_add_str(pinfo->cinfo, COL_INFO,
650 val_to_str(type, type_vals,
651 "Unknown AODV Packet Type (%u)"));
652 ti = proto_tree_add_protocol_format(tree, proto_aodv, tvb, 0, -1,
653 "Ad hoc On-demand Distance Vector Routing Protocol, %s",
654 val_to_str(type, type_vals, "Unknown AODV Packet Type (%u)"));
655 aodv_tree = proto_item_add_subtree(ti, ett_aodv);
657 type_item = proto_tree_add_uint(aodv_tree, hf_aodv_type, tvb, 0, 1, type);
659 switch (type) {
660 case RREQ:
661 dissect_aodv_rreq(tvb, pinfo, aodv_tree, ti, is_ipv6);
662 break;
663 case RREP:
664 dissect_aodv_rrep(tvb, pinfo, aodv_tree, ti, is_ipv6);
665 break;
666 case RERR:
667 dissect_aodv_rerr(tvb, pinfo, aodv_tree, is_ipv6);
668 break;
669 case RREP_ACK:
670 break;
671 case DRAFT_01_V6_RREQ:
672 dissect_aodv_draft_01_v6_rreq(tvb, pinfo, aodv_tree, ti);
673 break;
674 case DRAFT_01_V6_RREP:
675 dissect_aodv_draft_01_v6_rrep(tvb, pinfo, aodv_tree, ti);
676 break;
677 case DRAFT_01_V6_RERR:
678 dissect_aodv_draft_01_v6_rerr(tvb, pinfo, aodv_tree);
679 break;
680 case DRAFT_01_V6_RREP_ACK:
681 break;
682 default:
683 expert_add_info(pinfo, type_item, &ei_aodv_type);
686 return tvb_reported_length(tvb);
690 /* Register the protocol with Wireshark */
691 void
692 proto_register_aodv(void)
694 static hf_register_info hf[] = {
695 { &hf_aodv_type,
696 { "Type", "aodv.type",
697 FT_UINT8, BASE_DEC, VALS(type_vals), 0x0,
698 "AODV packet type", HFILL }
700 { &hf_aodv_flags,
701 { "Flags", "aodv.flags",
702 FT_UINT16, BASE_DEC, NULL, 0x0,
703 NULL, HFILL }
705 { &hf_aodv_flags_rreq_join,
706 { "RREQ Join", "aodv.flags.rreq_join",
707 FT_BOOLEAN, 16, TFS(&tfs_set_notset), RREQ_JOIN,
708 NULL, HFILL }
710 { &hf_aodv_flags_rreq_repair,
711 { "RREQ Repair", "aodv.flags.rreq_repair",
712 FT_BOOLEAN, 16, TFS(&tfs_set_notset), RREQ_REP,
713 NULL, HFILL }
715 { &hf_aodv_flags_rreq_gratuitous,
716 { "RREQ Gratuitous RREP", "aodv.flags.rreq_gratuitous",
717 FT_BOOLEAN, 16, TFS(&tfs_set_notset), RREQ_GRATRREP,
718 NULL, HFILL }
720 { &hf_aodv_flags_rreq_destinationonly,
721 { "RREQ Destination only", "aodv.flags.rreq_destinationonly",
722 FT_BOOLEAN, 16, TFS(&tfs_set_notset), RREQ_DESTONLY,
723 NULL, HFILL }
725 { &hf_aodv_flags_rreq_unknown,
726 { "RREQ Unknown Sequence Number", "aodv.flags.rreq_unknown",
727 FT_BOOLEAN, 16, TFS(&tfs_set_notset), RREQ_UNKNSEQ,
728 NULL, HFILL }
730 { &hf_aodv_flags_rrep_repair,
731 { "RREP Repair", "aodv.flags.rrep_repair",
732 FT_BOOLEAN, 16, TFS(&tfs_set_notset), RREP_REP,
733 NULL, HFILL }
735 { &hf_aodv_flags_rrep_ack,
736 { "RREP Acknowledgement", "aodv.flags.rrep_ack",
737 FT_BOOLEAN, 16, TFS(&tfs_set_notset), RREP_ACK_REQ,
738 NULL, HFILL }
740 { &hf_aodv_flags_rerr_nodelete,
741 { "RERR No Delete", "aodv.flags.rerr_nodelete",
742 FT_BOOLEAN, 16, TFS(&tfs_set_notset), RERR_NODEL,
743 NULL, HFILL }
745 { &hf_aodv_prefix_sz,
746 { "Prefix Size", "aodv.prefix_sz",
747 FT_UINT8, BASE_DEC, NULL, 0x0,
748 NULL, HFILL }
750 { &hf_aodv_hopcount,
751 { "Hop Count", "aodv.hopcount",
752 FT_UINT8, BASE_DEC, NULL, 0x0,
753 NULL, HFILL }
755 { &hf_aodv_rreq_id,
756 { "RREQ Id", "aodv.rreq_id",
757 FT_UINT32, BASE_DEC, NULL, 0x0,
758 NULL, HFILL }
760 { &hf_aodv_dest_ip,
761 { "Destination IP", "aodv.dest_ip",
762 FT_IPv4, BASE_NONE, NULL, 0x0,
763 "Destination IP Address", HFILL }
765 { &hf_aodv_dest_ipv6,
766 { "Destination IPv6", "aodv.dest_ipv6",
767 FT_IPv6, BASE_NONE, NULL, 0x0,
768 "Destination IPv6 Address", HFILL}
770 { &hf_aodv_dest_seqno,
771 { "Destination Sequence Number", "aodv.dest_seqno",
772 FT_UINT32, BASE_DEC, NULL, 0x0,
773 NULL, HFILL }
775 { &hf_aodv_orig_ip,
776 { "Originator IP", "aodv.orig_ip",
777 FT_IPv4, BASE_NONE, NULL, 0x0,
778 "Originator IP Address", HFILL }
780 { &hf_aodv_orig_ipv6,
781 { "Originator IPv6", "aodv.orig_ipv6",
782 FT_IPv6, BASE_NONE, NULL, 0x0,
783 "Originator IPv6 Address", HFILL}
785 { &hf_aodv_orig_seqno,
786 { "Originator Sequence Number", "aodv.orig_seqno",
787 FT_UINT32, BASE_DEC, NULL, 0x0,
788 NULL, HFILL }
790 { &hf_aodv_lifetime,
791 { "Lifetime", "aodv.lifetime",
792 FT_UINT32, BASE_DEC, NULL, 0x0,
793 NULL, HFILL }
795 { &hf_aodv_destcount,
796 { "Destination Count", "aodv.destcount",
797 FT_UINT8, BASE_DEC, NULL, 0x0,
798 "Unreachable Destinations Count", HFILL }
800 { &hf_aodv_unreach_dest_ip,
801 { "Unreachable Destination IP", "aodv.unreach_dest_ip",
802 FT_IPv4, BASE_NONE, NULL, 0x0,
803 "Unreachable Destination IP Address", HFILL }
805 { &hf_aodv_unreach_dest_ipv6,
806 { "Unreachable Destination IPv6", "aodv.unreach_dest_ipv6",
807 FT_IPv6, BASE_NONE, NULL, 0x0,
808 "Unreachable Destination IPv6 Address", HFILL}
810 #if 0
811 { &hf_aodv_unreach_dest_seqno,
812 { "Unreachable Destination Sequence Number", "aodv.unreach_dest_seqno",
813 FT_UINT32, BASE_DEC, NULL, 0x0,
814 NULL, HFILL }
816 #endif
817 { &hf_aodv_ext_type,
818 { "Extension Type", "aodv.ext_type",
819 FT_UINT8, BASE_DEC, VALS(exttype_vals), 0x0,
820 "Extension Format Type", HFILL}
822 { &hf_aodv_ext_length,
823 { "Extension Length", "aodv.ext_length",
824 FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0,
825 "Extension Data Length", HFILL}
827 { &hf_aodv_ext_interval,
828 { "Hello Interval", "aodv.hello_interval",
829 FT_UINT32, BASE_DEC, NULL, 0x0,
830 "Hello Interval Extension", HFILL}
832 { &hf_aodv_ext_timestamp,
833 { "Timestamp", "aodv.timestamp",
834 FT_UINT64, BASE_DEC, NULL, 0x0,
835 "Timestamp Extension", HFILL}
839 /* Setup protocol subtree array */
840 static int *ett[] = {
841 &ett_aodv,
842 &ett_aodv_flags,
843 &ett_aodv_unreach_dest,
844 &ett_aodv_extensions,
847 static ei_register_info ei[] = {
848 { &ei_aodv_ext_length, { "aodv.ext_length.invalid", PI_MALFORMED, PI_ERROR, "Invalid option length", EXPFILL }},
849 { &ei_aodv_type, { "aodv.ext_type.unknown", PI_PROTOCOL, PI_WARN, "Unknown AODV Packet Type", EXPFILL }},
852 expert_module_t* expert_aodv;
854 /* Register the protocol name and description */
855 proto_aodv = proto_register_protocol("Ad hoc On-demand Distance Vector Routing Protocol", "AODV", "aodv");
856 aodv_handle = register_dissector("aodv", dissect_aodv, proto_aodv);
858 /* Required function calls to register the header fields and subtrees used */
859 proto_register_field_array(proto_aodv, hf, array_length(hf));
860 proto_register_subtree_array(ett, array_length(ett));
861 expert_aodv = expert_register_protocol(proto_aodv);
862 expert_register_field_array(expert_aodv, ei, array_length(ei));
866 void
867 proto_reg_handoff_aodv(void)
869 dissector_add_uint_with_preference("udp.port", UDP_PORT_AODV, aodv_handle);
873 * Editor modelines - https://www.wireshark.org/tools/modelines.html
875 * Local variables:
876 * c-basic-offset: 4
877 * tab-width: 8
878 * indent-tabs-mode: nil
879 * End:
881 * vi: set shiftwidth=4 tabstop=8 expandtab:
882 * :indentSize=4:tabSize=8:noTabs=true: