2 * Routines for OLSR (IPv4 & IPv6 compatible) RFC parsing
3 * Compatible with RFC-compliant OLSR implementations such as
4 * NRLOLSRD (http://pf.itd.nrl.navy.mil/projects/olsr/).
5 * Parser created by Aaron Woo <woo@itd.nrl.navy.mil> of
6 * the Naval Research Laboratory
7 * Currently maintained by Jeff Weston <weston@itd.nrl.navy.mil>.
9 * Updated to Olsr.org and NRLOLSR packages by Henning Rogge <rogge@fgan.de>
10 * https://www.ietf.org/rfc/rfc3626
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * SPDX-License-Identifier: GPL-2.0-or-later
22 #include <epan/packet.h>
23 #include <epan/prefs.h>
24 #include <epan/expert.h>
25 #include <epan/to_str.h>
26 #include <wsutil/array.h>
28 void proto_register_olsr(void);
29 void proto_reg_handoff_olsr(void);
30 static dissector_handle_t olsr_handle
;
32 #define UDP_PORT_OLSR 698
38 #define OLSR_ORG_NAMESERVICE 130
39 #define OLSR_ORG_LQ_HELLO 201
40 #define OLSR_ORG_LQ_TC 202
41 #define NRLOLSR_TC_EXTRA 241
43 /* Initialize the protocol and registered fields */
44 static int proto_olsr
;
46 static int hf_olsr_packet_len
;
47 static int hf_olsr_packet_seq_num
;
49 static int hf_olsr_message
;
50 static int hf_olsr_message_type
;
51 static int hf_olsr_vtime
;
52 static int hf_olsr_message_size
;
53 static int hf_olsr_ttl
;
54 static int hf_olsr_hop_count
;
55 static int hf_olsr_message_seq_num
;
57 static int hf_olsr_htime
;
58 static int hf_olsr_willingness
;
60 static int hf_olsr_link_type
;
61 static int hf_olsr_link_message_size
;
62 static int hf_olsr_ansn
;
64 static int hf_olsr_neighbor
;
65 static int hf_olsr_origin_addr
;
66 static int hf_olsr_neighbor_addr
;
67 static int hf_olsr_interface_addr
;
68 static int hf_olsr_netmask
;
69 static int hf_olsr_network_addr
;
71 /* static int hf_olsr_neighbor6; */
72 static int hf_olsr_origin6_addr
;
73 static int hf_olsr_neighbor6_addr
;
74 static int hf_olsr_interface6_addr
;
75 static int hf_olsr_netmask6
;
76 static int hf_olsr_network6_addr
;
78 static int hf_olsrorg_lq
;
79 static int hf_olsrorg_nlq
;
80 static int hf_nrlolsr_f1
;
81 static int hf_nrlolsr_f2
;
83 static int hf_olsrorg_ns_version
;
84 static int hf_olsrorg_ns_count
;
86 static int hf_olsrorg_ns
;
87 static int hf_olsrorg_ns_type
;
88 static int hf_olsrorg_ns_length
;
89 static int hf_olsrorg_ns_ip
;
90 static int hf_olsrorg_ns_ip6
;
91 static int hf_olsrorg_ns_content
;
93 static int hf_olsr_data
;
95 /* Initialize the subtree pointers*/
97 static int ett_olsr_message
[UINT8_MAX
+ 1];
98 static int ett_olsr_message_linktype
;
99 static int ett_olsr_message_neigh
;
100 static int ett_olsr_message_neigh6
;
101 static int ett_olsr_message_ns
;
103 static expert_field ei_olsr_not_enough_bytes
;
104 static expert_field ei_olsrorg_ns_version
;
105 static expert_field ei_olsr_data_misaligned
;
107 static const value_string message_type_vals
[] = {
112 { OLSR_ORG_LQ_HELLO
, "HELLO (LQ, olsr.org)" },
113 { OLSR_ORG_LQ_TC
, "TC (LQ, olsr.org)" },
114 { OLSR_ORG_NAMESERVICE
, "Nameservice (olsr.org)" },
115 { NRLOLSR_TC_EXTRA
, "TC (LQ, nrlolsr)" },
119 static const value_string link_type_vals
[] = {
120 { 0, "Unspecified Link" },
121 { 1, "Asymmetric Link" },
123 { 5, "Pending Link" },
124 { 6, "Symmetric Link" },
129 static const value_string willingness_type_vals
[] = {
135 static const value_string nameservice_type_vals
[] = {
143 static bool global_olsr_olsrorg
= true;
144 static bool global_olsr_nrlolsr
= true;
146 static double getOlsrTime(uint8_t timeval
) {
147 int high_bits
, low_bits
;
149 high_bits
= ((timeval
& 0xF0) >> 4);
150 low_bits
= (timeval
& 0x0F);
151 return ((UINT64_C(1) << low_bits
) / 16.0) * (1 + (high_bits
/ 16.0));
154 /*------------------------- TC Dissecting Code-------------------------*/
155 static int dissect_olsr_tc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*olsr_tree
, int offset
, int message_end
) {
156 if (message_end
- offset
< 4) {
157 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, message_end
- offset
,
158 "Not enough bytes for TC");
162 proto_tree_add_item(olsr_tree
, hf_olsr_ansn
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
165 while (offset
< message_end
) {
166 if (message_end
- offset
< pinfo
->src
.len
) {
167 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, message_end
- offset
,
168 "Not enough bytes for last neighbor");
171 if (pinfo
->src
.type
== AT_IPv4
) {
172 proto_tree_add_item(olsr_tree
, hf_olsr_neighbor_addr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
174 } else if (pinfo
->src
.type
== AT_IPv6
) {
175 proto_tree_add_item(olsr_tree
, hf_olsr_neighbor6_addr
, tvb
, offset
, 16, ENC_NA
);
178 break; /* unknown address type should be handled in dissect_olsr, just be sure */
184 static int dissect_olsrorg_lq_tc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*olsr_tree
, int offset
, int message_end
) {
186 if (message_end
- offset
< 4) {
187 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, message_end
- offset
,
188 "Not enough bytes for Olsr.org LQ-TC");
191 proto_tree_add_item(olsr_tree
, hf_olsr_ansn
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
194 while (offset
< message_end
) {
195 proto_item
*address_group
;
196 proto_tree
*address_tree
;
199 if (pinfo
->src
.type
== AT_IPv4
) {
200 if (message_end
- offset
< 8) {
201 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, message_end
- offset
,
202 "Not enough bytes for last entry (need 8 bytes)");
205 lq
= tvb_get_uint8(tvb
, offset
+ 4);
206 nlq
= tvb_get_uint8(tvb
, offset
+ 5);
208 address_group
= proto_tree_add_bytes_format_value(olsr_tree
, hf_olsr_neighbor
, tvb
, offset
, 8,
209 NULL
, "%s (%d/%d)", tvb_ip_to_str(pinfo
->pool
, tvb
, offset
), lq
, nlq
);
211 address_tree
= proto_item_add_subtree(address_group
, ett_olsr_message_neigh
);
213 proto_tree_add_item(address_tree
, hf_olsr_neighbor_addr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
215 } else if (pinfo
->src
.type
== AT_IPv6
) {
216 if (message_end
- offset
< 20) {
217 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, message_end
- offset
,
218 "Not enough bytes for last entry (need 20 bytes)");
221 lq
= tvb_get_uint8(tvb
, offset
+ 16);
222 nlq
= tvb_get_uint8(tvb
, offset
+ 17);
224 address_group
= proto_tree_add_bytes_format_value(olsr_tree
, hf_olsr_neighbor
, tvb
, offset
, 20,
225 NULL
, "%s (%d/%d)", tvb_ip6_to_str(pinfo
->pool
, tvb
, offset
), lq
, nlq
);
227 address_tree
= proto_item_add_subtree(address_group
, ett_olsr_message_neigh
);
229 proto_tree_add_item(address_tree
, hf_olsr_neighbor6_addr
, tvb
, offset
, 16, ENC_NA
);
232 break; /* unknown address type should be handled in dissect_olsr, just be sure */
235 proto_tree_add_item(address_tree
, hf_olsrorg_lq
, tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
236 proto_tree_add_item(address_tree
, hf_olsrorg_nlq
, tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
242 static int dissect_nrlolsr_tc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*olsr_tree
, int offset
, int message_end
) {
243 int field1Ptr
, field2Ptr
, saneEnd
;
244 if (message_end
- offset
< 4) {
245 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, message_end
- offset
,
246 "Not enough bytes for NRLOLSR LQ-TC");
250 proto_tree_add_item(olsr_tree
, hf_olsr_ansn
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
253 field1Ptr
= offset
+ (message_end
- offset
) / (pinfo
->src
.len
+ 2) * (pinfo
->src
.len
);
254 field2Ptr
= offset
+ (message_end
- offset
) / (pinfo
->src
.len
+ 2) * (pinfo
->src
.len
+ 1);
256 saneEnd
= message_end
- ((message_end
- offset
) % (pinfo
->src
.len
+ 2));
257 while (field2Ptr
< saneEnd
) {
258 if (pinfo
->src
.type
== AT_IPv4
) {
259 proto_tree_add_item(olsr_tree
, hf_olsr_neighbor_addr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
261 } else if (pinfo
->src
.type
== AT_IPv6
) {
262 proto_tree_add_item(olsr_tree
, hf_olsr_neighbor6_addr
, tvb
, offset
, 16, ENC_NA
);
265 break; /* unknown address type should be handled in dissect_olsr, just be sure */
268 proto_tree_add_item(olsr_tree
, hf_nrlolsr_f1
, tvb
, field1Ptr
++, 1, ENC_BIG_ENDIAN
);
269 proto_tree_add_item(olsr_tree
, hf_nrlolsr_f2
, tvb
, field2Ptr
++, 1, ENC_BIG_ENDIAN
);
274 /*------------------------- Hello Dissecting Code-------------------------*/
275 static int dissect_olsr_hello(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*olsr_tree
, int offset
, int message_end
,
276 int(*handleNeighbors
)(tvbuff_t
*, packet_info
*, proto_tree
*, int, int)) {
279 proto_tree
*link_type_tree
;
281 uint16_t message_size
;
283 if (message_end
- offset
< 4) {
284 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, message_end
- offset
,
285 "Not enough bytes for Hello");
291 /*---------------------Dissect Hello Emission Inverval-------------------*/
292 hTime
= getOlsrTime(tvb_get_uint8(tvb
, offset
));
293 proto_tree_add_double_format_value(olsr_tree
, hf_olsr_htime
, tvb
, offset
, 1, hTime
,
294 "%.3f (in seconds)", hTime
);
297 /*-------------------------Dissect Willingness---------------------------*/
298 proto_tree_add_item(olsr_tree
, hf_olsr_willingness
, tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
300 while (offset
< message_end
) {
301 if (message_end
- offset
< 4) {
302 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, message_end
- offset
,
303 "Not enough bytes for last Hello entry");
307 /*------------------------------Dissect Link Type---------------------------------- */
308 ti
= proto_tree_add_item(olsr_tree
, hf_olsr_link_type
, tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
309 link_type_tree
= proto_item_add_subtree(ti
, ett_olsr_message_linktype
);
314 /*----------------------Dissect Link Message Size--------------------------*/
315 message_size
= tvb_get_ntohs(tvb
, offset
);
316 ti
= proto_tree_add_item(link_type_tree
, hf_olsr_link_message_size
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
319 if (message_size
< 4) {
320 expert_add_info_format(pinfo
, ti
, &ei_olsr_not_enough_bytes
, "(too short, must be >= 4)");
323 offset
= handleNeighbors(tvb
, pinfo
, link_type_tree
, offset
, offset
+ message_size
- 4);
328 static int handle_olsr_hello_rfc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*olsr_tree
, int offset
,
329 int link_message_end
) {
330 /*-------------------Dissect Neighbor Addresses--------------------*/
331 while (offset
< link_message_end
) {
332 if (link_message_end
- offset
< pinfo
->src
.len
) {
333 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, link_message_end
- offset
,
334 "Not enough bytes for last Hello entry");
335 return link_message_end
;
337 if (pinfo
->src
.type
== AT_IPv4
) {
338 proto_tree_add_item(olsr_tree
, hf_olsr_neighbor_addr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
340 } else if (pinfo
->src
.type
== AT_IPv6
) {
341 proto_tree_add_item(olsr_tree
, hf_olsr_neighbor6_addr
, tvb
, offset
, 16, ENC_NA
);
344 break; /* unknown address type should be handled in dissect_olsr, just be sure */
347 return link_message_end
;
350 static int handle_olsr_hello_olsrorg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*olsr_tree
, int offset
,
351 int link_message_end
) {
352 /*-------------------Dissect Neighbor Addresses--------------------*/
354 while (offset
< link_message_end
) {
355 proto_item
*address_group
;
356 proto_tree
*address_tree
;
359 if (link_message_end
- offset
< pinfo
->src
.len
+ 4) {
360 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, link_message_end
- offset
,
361 "Not enough bytes for last Olsr.org LQ-Hello entry");
362 return link_message_end
;
365 if (pinfo
->src
.type
== AT_IPv4
) {
366 lq
= tvb_get_uint8(tvb
, offset
+ 4);
367 nlq
= tvb_get_uint8(tvb
, offset
+ 5);
369 address_group
= proto_tree_add_bytes_format_value(olsr_tree
, hf_olsr_neighbor
, tvb
, offset
, 8,
370 NULL
, "%s (%d/%d)", tvb_ip_to_str(pinfo
->pool
, tvb
, offset
), lq
, nlq
);
372 address_tree
= proto_item_add_subtree(address_group
, ett_olsr_message_neigh
);
374 proto_tree_add_item(address_tree
, hf_olsr_neighbor_addr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
376 } else if (pinfo
->src
.type
== AT_IPv6
) {
377 lq
= tvb_get_uint8(tvb
, offset
+ 16);
378 nlq
= tvb_get_uint8(tvb
, offset
+ 17);
380 address_group
= proto_tree_add_bytes_format_value(olsr_tree
, hf_olsr_neighbor
, tvb
, offset
, 20,
381 NULL
, "%s (%d/%d)", tvb_ip6_to_str(pinfo
->pool
, tvb
, offset
), lq
, nlq
);
383 address_tree
= proto_item_add_subtree(address_group
, ett_olsr_message_neigh
);
385 proto_tree_add_item(address_tree
, hf_olsr_neighbor6_addr
, tvb
, offset
, 16, ENC_NA
);
388 break; /* unknown address type should be handled in dissect_olsr, just be sure */
391 proto_tree_add_item(address_tree
, hf_olsrorg_lq
, tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
392 proto_tree_add_item(address_tree
, hf_olsrorg_nlq
, tvb
, offset
++, 1, ENC_BIG_ENDIAN
);
395 return link_message_end
;
398 /*------------------------- MID Dissecting Code-------------------------*/
399 static int dissect_olsr_mid(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*olsr_tree
, int offset
, int message_end
) {
400 while (offset
< message_end
) {
401 if (message_end
- offset
< pinfo
->src
.len
) {
402 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, message_end
- offset
,
403 "Not enough bytes for last MID entry");
406 if (pinfo
->src
.type
== AT_IPv4
) {
407 proto_tree_add_item(olsr_tree
, hf_olsr_interface_addr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
409 } else if (pinfo
->src
.type
== AT_IPv6
) {
410 proto_tree_add_item(olsr_tree
, hf_olsr_interface6_addr
, tvb
, offset
, 16, ENC_NA
);
413 break; /* unknown address type should be handled in dissect_olsr, just be sure */
415 } /* end while for MID */
419 /*------------------------- HNA Dissecting Code-------------------------*/
420 static int dissect_olsr_hna(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*olsr_tree
, int offset
, int message_end
) {
421 while (offset
< message_end
) {
422 if (message_end
- offset
< pinfo
->src
.len
* 2) {
423 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, message_end
- offset
,
424 "Not enough bytes for last HNA entry");
428 if (pinfo
->src
.type
== AT_IPv4
) {
429 proto_tree_add_item(olsr_tree
, hf_olsr_network_addr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
431 proto_tree_add_item(olsr_tree
, hf_olsr_netmask
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
433 } else if (pinfo
->src
.type
== AT_IPv6
) {
434 proto_tree_add_item(olsr_tree
, hf_olsr_network6_addr
, tvb
, offset
, 4, ENC_NA
);
436 proto_tree_add_item(olsr_tree
, hf_olsr_netmask6
, tvb
, offset
, 4, ENC_NA
);
439 break; /* unknown address type should be handled in dissect_olsr, just be sure */
441 } /* end while for HNA */
445 /*------------------------- MID Dissecting Code-------------------------*/
446 static int dissect_olsrorg_nameservice(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*olsr_tree
, int offset
,
448 uint16_t version
, count
;
450 proto_item
*olsr_ns_item
, *ti
;
451 proto_tree
*olsr_ns_tree
;
453 if (message_end
- offset
< 4) {
454 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, message_end
- offset
,
455 "Not enough bytes for Olsr.org Nameservice message");
459 version
= tvb_get_ntohs(tvb
, offset
);
460 ti
= proto_tree_add_item(olsr_tree
, hf_olsrorg_ns_version
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
462 count
= tvb_get_ntohs(tvb
, offset
+ 2);
463 proto_tree_add_item(olsr_tree
, hf_olsrorg_ns_count
, tvb
, offset
+ 2, 2, ENC_BIG_ENDIAN
);
469 expert_add_info(pinfo
, ti
, &ei_olsrorg_ns_version
);
470 proto_tree_add_item(olsr_tree
, hf_olsr_data
, tvb
, offset
, message_end
- offset
, ENC_NA
);
474 while (offset
< message_end
&& count
-- > 0) {
475 uint16_t type
, length
;
478 if (message_end
- offset
< 20) {
479 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, message_end
- offset
,
480 "Not enough bytes for last nameservice entry");
484 type
= tvb_get_ntohs(tvb
, offset
);
485 length
= tvb_get_ntohs(tvb
, offset
+ 2);
487 total_length
= 4 + 16 + ((length
- 1) | 3) + 1;
489 olsr_ns_item
= proto_tree_add_bytes_format_value(olsr_tree
, hf_olsrorg_ns
, tvb
, offset
, total_length
,
490 NULL
, "%s (%d)", val_to_str_const(type
, nameservice_type_vals
, "UNKNOWN"), type
);
492 olsr_ns_tree
= proto_item_add_subtree(olsr_ns_item
, ett_olsr_message_ns
);
494 proto_tree_add_item(olsr_ns_tree
, hf_olsrorg_ns_type
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
495 proto_tree_add_uint(olsr_ns_tree
, hf_olsrorg_ns_length
, tvb
, offset
+ 2, 2, length
);
497 if (pinfo
->src
.type
== AT_IPv4
) {
498 proto_tree_add_item(olsr_ns_tree
, hf_olsrorg_ns_ip
, tvb
, offset
+ 4, 4, ENC_BIG_ENDIAN
);
499 } else if (pinfo
->src
.type
== AT_IPv6
) {
500 proto_tree_add_item(olsr_ns_tree
, hf_olsrorg_ns_ip6
, tvb
, offset
+ 4, 16, ENC_NA
);
502 break; /* unknown address type should be handled in dissect_olsr, just be sure */
505 if (message_end
- offset
< total_length
) {
506 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, message_end
- offset
,
507 "Not enough bytes for content of last nameservice entry");
510 proto_tree_add_item(olsr_ns_tree
, hf_olsrorg_ns_content
, tvb
, offset
+ 20, length
, ENC_ASCII
);
511 offset
+= 4 + 16 + ((length
- 1) | 3) + 1;
516 /*------------------------- Packet Dissecting Code-------------------------*/
517 static int dissect_olsr(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
) {
519 proto_tree
*olsr_tree
;
521 int offset
, message_len
, message_end
;
522 unsigned message_type
;
527 /* Does this packet have a valid message type at the beginning? */
528 if (tvb_captured_length(tvb
) < 4) {
529 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "OLSR Packet, Length: %u Bytes (not enough data in packet)",
530 tvb_captured_length(tvb
));
531 return 0; /* not enough bytes for the packet length */
533 packet_len
= tvb_get_ntohs(tvb
, 0);
534 if (packet_len
> tvb_reported_length(tvb
)) {
535 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "OLSR Packet, Length: %u Bytes (not enough data in packet)", packet_len
);
538 /*-------------Setting the Protocol and Info Columns in the Wireshark Display----------*/
539 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "OLSR v1");
540 col_clear(pinfo
->cinfo
, COL_INFO
);
542 if ((pinfo
->src
.type
!= AT_IPv4
) && (pinfo
->src
.type
!= AT_IPv6
)) {
543 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "OLSR (unknown address type) Packet, Length: %u Bytes", packet_len
);
546 if (pinfo
->src
.type
== AT_IPv4
) {
547 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "OLSR (IPv4) Packet, Length: %u Bytes", packet_len
);
548 } else if (pinfo
->src
.type
== AT_IPv6
) {
549 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "OLSR (IPv6) Packet, Length: %u Bytes", packet_len
);
552 /*-----------------Fetching Info from IP Packet and Adding to Tree------------------------*/
553 ti
= proto_tree_add_item(tree
, proto_olsr
, tvb
, 0, -1, ENC_NA
);
554 olsr_tree
= proto_item_add_subtree(ti
, ett_olsr
);
556 proto_tree_add_item(olsr_tree
, hf_olsr_packet_len
, tvb
, 0, 2, ENC_BIG_ENDIAN
);
557 proto_tree_add_item(olsr_tree
, hf_olsr_packet_seq_num
, tvb
, 2, 2, ENC_BIG_ENDIAN
);
561 while (offset
< packet_len
) {
562 proto_item
*message_item
;
563 proto_tree
*message_tree
;
565 if (packet_len
- offset
< 4) {
566 proto_tree_add_expert_format(olsr_tree
, pinfo
, &ei_olsr_not_enough_bytes
, tvb
, offset
, packet_len
- offset
,
567 "Message too short !");
571 message_type
= tvb_get_uint8(tvb
, offset
);
572 vTime
= getOlsrTime(tvb_get_uint8(tvb
, offset
+ 1));
573 message_len
= tvb_get_ntohs(tvb
, offset
+ 2);
575 message_item
= proto_tree_add_bytes_format_value(olsr_tree
, hf_olsr_message
, tvb
, offset
, message_len
,
576 NULL
, "%s (%d)", val_to_str_const(message_type
, message_type_vals
, "UNKNOWN"),
578 message_tree
= proto_item_add_subtree(message_item
, ett_olsr_message
[message_type
]);
580 proto_tree_add_uint(message_tree
, hf_olsr_message_type
, tvb
, offset
, 1, message_type
);
583 /*-------------Dissect Validity Time-------------------------*/
584 proto_tree_add_double_format_value(message_tree
, hf_olsr_vtime
, tvb
, offset
, 1, vTime
,
585 "%.3f (in seconds)", vTime
);
588 /*-------------Dissect Message Size---------------------------*/
589 ti
= proto_tree_add_item(message_tree
, hf_olsr_message_size
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
592 if (message_len
< 8 + pinfo
->src
.len
) {
593 expert_add_info_format(pinfo
, ti
, &ei_olsr_not_enough_bytes
, "(too short, must be >= %d)", 8 + pinfo
->src
.len
);
597 message_end
= offset
+ message_len
- 4;
598 if (message_end
> packet_len
) {
599 expert_add_info_format(pinfo
, ti
, &ei_olsr_not_enough_bytes
, "(not enough data for message)");
603 /*-----------------Dissecting: Origin Addr, TTL, Hop Count, and Message Seq Number*/
604 if (pinfo
->src
.type
== AT_IPv4
) {
605 proto_tree_add_item(message_tree
, hf_olsr_origin_addr
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
607 } else if (pinfo
->src
.type
== AT_IPv6
) {
608 proto_tree_add_item(message_tree
, hf_olsr_origin6_addr
, tvb
, offset
, 16, ENC_NA
);
611 break; /* unknown address type should be handled before this loop, just be sure */
614 proto_tree_add_item(message_tree
, hf_olsr_ttl
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
615 proto_tree_add_item(message_tree
, hf_olsr_hop_count
, tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
616 proto_tree_add_item(message_tree
, hf_olsr_message_seq_num
, tvb
, offset
+ 2, 2, ENC_BIG_ENDIAN
);
619 if (offset
< message_end
) {
620 /* --------------Dissecting TC message--------------------- */
621 if (message_type
== TC
) {
622 dissect_olsr_tc(tvb
, pinfo
, message_tree
, offset
, message_end
);
624 /* -------------Dissect HELLO message----------------------- */
625 else if (message_type
== HELLO
) {
626 dissect_olsr_hello(tvb
, pinfo
, message_tree
, offset
, message_end
, &handle_olsr_hello_rfc
);
628 /*---------------------------------Dissect MID Message----------------------------------*/
629 else if (message_type
== MID
) {
630 dissect_olsr_mid(tvb
, pinfo
, message_tree
, offset
, message_end
);
632 /*-----------------------------Dissect HNA Message--------------------------------*/
633 else if (message_type
== HNA
) {
634 dissect_olsr_hna(tvb
, pinfo
, message_tree
, offset
, message_end
);
636 /*-----------------------------Dissect Olsr.org Hello Message--------------------------------*/
637 else if (global_olsr_olsrorg
&& message_type
== OLSR_ORG_LQ_HELLO
) {
638 dissect_olsr_hello(tvb
, pinfo
, message_tree
, offset
, message_end
, &handle_olsr_hello_olsrorg
);
640 /*-----------------------------Dissect Olsr.org TC Message--------------------------------*/
641 else if (global_olsr_olsrorg
&& message_type
== OLSR_ORG_LQ_TC
) {
642 dissect_olsrorg_lq_tc(tvb
, pinfo
, message_tree
, offset
, message_end
);
645 /*-----------------------------Dissect Olsr.org NS Message--------------------------------*/
646 else if (global_olsr_olsrorg
&& message_type
== OLSR_ORG_NAMESERVICE
) {
647 dissect_olsrorg_nameservice(tvb
, pinfo
, message_tree
, offset
, message_end
);
649 /*-----------------------Dissect NRL OLSR TC Message-------------------------------------*/
650 else if (global_olsr_nrlolsr
&& message_type
== NRLOLSR_TC_EXTRA
) {
651 dissect_nrlolsr_tc(tvb
, pinfo
, message_tree
, offset
, message_end
);
654 /*-----------------------------Undefined message types-----------------------------*/
656 ti
= proto_tree_add_bytes_format(message_tree
, hf_olsr_data
, tvb
, offset
, message_len
- 12,
657 NULL
, "Data (%u bytes)", message_len
- 12);
658 if ((message_len
- 12) % 4) {
659 expert_add_info(pinfo
, ti
, &ei_olsr_data_misaligned
);
662 /*offset += message_len - 12;*/
663 } /* end if for undefined message types */
665 offset
= message_end
;
666 } /* end while for message alive */
668 return tvb_captured_length(tvb
);
669 } /* end Dissecting */
671 /*-----------Register the Dissector for OLSR--------------*/
672 void proto_register_olsr(void) {
673 static hf_register_info hf
[] = {
674 { &hf_olsr_packet_len
,
675 { "Packet Length", "olsr.packet_len",
676 FT_UINT16
, BASE_DEC
, NULL
, 0,
677 "Packet Length in Bytes", HFILL
681 { &hf_olsr_packet_seq_num
,
682 { "Packet Sequence Number", "olsr.packet_seq_num",
683 FT_UINT16
, BASE_DEC
, NULL
, 0,
689 { "Message", "olsr.message",
690 FT_BYTES
, BASE_NONE
, NULL
, 0,
695 { &hf_olsr_message_type
,
696 { "Message Type", "olsr.message_type",
697 FT_UINT8
, BASE_DEC
, VALS(message_type_vals
), 0,
702 { &hf_olsr_message_size
,
703 { "Message", "olsr.message_size",
704 FT_UINT16
, BASE_DEC
, NULL
, 0,
705 "Message Size in Bytes", HFILL
709 { &hf_olsr_message_seq_num
,
710 { "Message Sequence Number", "olsr.message_seq_num",
711 FT_UINT16
, BASE_DEC
, NULL
, 0,
717 { "Validity Time", "olsr.vtime",
718 FT_DOUBLE
, BASE_NONE
, NULL
, 0,
719 "Validity Time in seconds", HFILL
724 { "Advertised Neighbor Sequence Number (ANSN)", "olsr.ansn",
725 FT_UINT16
, BASE_DEC
, NULL
, 0,
731 { "Hello Emission Interval", "olsr.htime",
732 FT_DOUBLE
, BASE_NONE
, NULL
, 0,
733 "Hello emission interval in seconds", HFILL
737 { &hf_olsr_willingness
,
738 { "Willingness to forward messages", "olsr.willingness",
739 FT_UINT8
, BASE_DEC
, VALS(willingness_type_vals
), 0,
746 FT_UINT8
, BASE_DEC
, NULL
, 0,
747 "Time to Live in hops", HFILL
751 { &hf_olsr_link_type
,
752 { "Link Type", "olsr.link_type",
753 FT_UINT8
, BASE_DEC
, VALS(link_type_vals
), 0,
758 { &hf_olsr_link_message_size
,
759 { "Link Message Size", "olsr.link_message_size",
760 FT_UINT16
, BASE_DEC
, NULL
, 0,
761 "Link Message Size in bytes", HFILL
765 { &hf_olsr_hop_count
,
766 { "Hop Count", "olsr.hop_count",
767 FT_UINT8
, BASE_DEC
, NULL
, 0,
773 { "Neighbor Address", "olsr.neighbor",
774 FT_BYTES
, BASE_NONE
, NULL
, 0,
779 { &hf_olsr_origin_addr
,
780 { "Originator Address", "olsr.origin_addr",
781 FT_IPv4
, BASE_NONE
, NULL
, 0,
786 { &hf_olsr_neighbor_addr
,
787 { "Neighbor Address", "olsr.neighbor_addr",
788 FT_IPv4
, BASE_NONE
, NULL
, 0,
793 { &hf_olsr_network_addr
,
794 { "Network Address", "olsr.network_addr",
795 FT_IPv4
, BASE_NONE
, NULL
, 0,
800 { &hf_olsr_interface_addr
,
801 { "Interface Address", "olsr.interface_addr",
802 FT_IPv4
, BASE_NONE
, NULL
, 0,
808 { "Netmask", "olsr.netmask",
809 FT_IPv4
, BASE_NETMASK
, NULL
, 0,
815 { &hf_olsr_neighbor6
,
816 { "Neighbor Address", "olsr.neighbor6",
817 FT_BYTES
, BASE_NONE
, NULL
, 0,
823 { &hf_olsr_origin6_addr
,
824 { "Originator Address", "olsr.origin6_addr",
825 FT_IPv6
, BASE_NONE
, NULL
, 0,
830 { &hf_olsr_neighbor6_addr
,
831 { "Neighbor Address", "olsr.neighbor6_addr",
832 FT_IPv6
, BASE_NONE
, NULL
, 0,
837 { &hf_olsr_network6_addr
,
838 { "Network Address", "olsr.network6_addr",
839 FT_IPv6
, BASE_NONE
, NULL
, 0,
844 { &hf_olsr_interface6_addr
,
845 { "Interface Address", "olsr.interface6_addr",
846 FT_IPv6
, BASE_NONE
, NULL
, 0,
852 { "Netmask", "olsr.netmask6",
853 FT_IPv6
, BASE_NONE
, NULL
, 0,
859 { "Data", "olsr.data",
860 FT_BYTES
, BASE_NONE
, NULL
, 0,
867 FT_UINT8
, BASE_DEC
, NULL
, 0,
868 "Link quality", HFILL
873 FT_UINT8
, BASE_DEC
, NULL
, 0,
874 "Neighbor link quality", HFILL
879 { "Nameservice", "olsr.ns",
880 FT_BYTES
, BASE_NONE
, NULL
, 0,
884 { &hf_olsrorg_ns_version
,
885 { "Version", "olsr.ns.version",
886 FT_UINT16
, BASE_DEC
, NULL
, 0,
890 { &hf_olsrorg_ns_count
,
891 { "Count", "olsr.ns.count",
892 FT_UINT16
, BASE_DEC
, NULL
, 0,
893 "Number of nameservice messages", HFILL
896 { &hf_olsrorg_ns_type
,
897 { "Message Type", "olsr.ns.type",
898 FT_UINT16
, BASE_DEC
, VALS(nameservice_type_vals
), 0,
902 { &hf_olsrorg_ns_length
,
903 { "Length", "olsr.ns.length",
904 FT_UINT16
, BASE_DEC
, NULL
, 0,
909 { "Address", "olsr.ns.ip",
910 FT_IPv4
, BASE_NONE
, NULL
, 0,
914 { &hf_olsrorg_ns_ip6
,
915 { "Address", "olsr.ns.ip6",
916 FT_IPv6
, BASE_NONE
, NULL
, 0,
920 { &hf_olsrorg_ns_content
,
921 { "Content", "olsr.ns.content",
922 FT_STRING
, BASE_NONE
, NULL
, 0,
928 { "NRL MINMAX", "olsr.nrl.minmax",
929 FT_UINT8
, BASE_DEC
, NULL
, 0,
934 { "NRL SPF", "olsr.nrl.spf",
935 FT_UINT8
, BASE_DEC
, NULL
, 0,
941 static int *ett_base
[] = {
943 &ett_olsr_message_linktype
,
944 &ett_olsr_message_neigh
,
945 &ett_olsr_message_neigh6
,
949 static ei_register_info ei
[] = {
950 { &ei_olsr_not_enough_bytes
, { "olsr.not_enough_bytes", PI_MALFORMED
, PI_ERROR
, "Not enough bytes for field", EXPFILL
}},
951 { &ei_olsrorg_ns_version
, { "olsr.ns.version.unknown", PI_PROTOCOL
, PI_WARN
, "Unknown nameservice protocol version", EXPFILL
}},
952 { &ei_olsr_data_misaligned
, { "olsr.data.misaligned", PI_PROTOCOL
, PI_WARN
, "Must be aligned on 32 bits", EXPFILL
}},
955 int *ett
[array_length(ett_base
) + (UINT8_MAX
+1)];
957 module_t
*olsr_module
;
958 expert_module_t
*expert_olsr
;
961 memcpy(ett
, ett_base
, sizeof(ett_base
));
962 j
= array_length(ett_base
);
963 for (i
=0; i
<UINT8_MAX
+1; i
++) {
964 ett
[j
++] = &ett_olsr_message
[i
];
967 proto_olsr
= proto_register_protocol("Optimized Link State Routing Protocol", "OLSR", "olsr");
968 olsr_handle
= register_dissector("olsr", dissect_olsr
, proto_olsr
);
970 proto_register_field_array(proto_olsr
, hf
, array_length(hf
));
971 proto_register_subtree_array(ett
, array_length(ett
));
972 expert_olsr
= expert_register_protocol(proto_olsr
);
973 expert_register_field_array(expert_olsr
, ei
, array_length(ei
));
975 olsr_module
= prefs_register_protocol(proto_olsr
, NULL
);
976 prefs_register_bool_preference(olsr_module
, "ff_olsrorg",
977 "Dissect olsr.org messages","Dissect custom olsr.org message types (compatible with rfc routing agents)",
978 &global_olsr_olsrorg
);
979 prefs_register_bool_preference(olsr_module
, "nrlolsr",
980 "Dissect NRL-Olsr TC messages", "Dissect custom nrlolsr tc message (incompatible with rfc routing agents)",
981 &global_olsr_nrlolsr
);
984 void proto_reg_handoff_olsr(void) {
985 dissector_add_uint_with_preference("udp.port", UDP_PORT_OLSR
, olsr_handle
);
994 * indent-tabs-mode: nil
997 * ex: set shiftwidth=2 tabstop=8 expandtab:
998 * :indentSize=2:tabSize=8:noTabs=true: