Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-olsr.c
blob1068888307466e94b90acd3a40abe7eec143af19
1 /* packet-olsr.c
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
19 #include "config.h"
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
33 #define HELLO 1
34 #define TC 2
35 #define MID 3
36 #define HNA 4
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*/
96 static int ett_olsr;
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[] = {
108 { HELLO, "HELLO" },
109 { TC, "TC" },
110 { MID, "MID" },
111 { HNA, "HNA" },
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)" },
116 { 0, NULL }
119 static const value_string link_type_vals[] = {
120 { 0, "Unspecified Link" },
121 { 1, "Asymmetric Link" },
122 { 3, "Lost Link" },
123 { 5, "Pending Link" },
124 { 6, "Symmetric Link" },
125 { 10, "MPR Link" },
126 { 0, NULL }
129 static const value_string willingness_type_vals[] = {
130 { 0, "never" },
131 { 7, "always" },
132 { 0, NULL }
135 static const value_string nameservice_type_vals[] = {
136 { 0, "HOST" },
137 { 1, "FORWARDER" },
138 { 2, "SERVICE" },
139 { 3, "LATLON" },
140 { 0, NULL }
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");
159 return message_end;
162 proto_tree_add_item(olsr_tree, hf_olsr_ansn, tvb, offset, 2, ENC_BIG_ENDIAN);
163 offset += 4;
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");
169 return message_end;
171 if (pinfo->src.type == AT_IPv4) {
172 proto_tree_add_item(olsr_tree, hf_olsr_neighbor_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
173 offset += 4;
174 } else if (pinfo->src.type == AT_IPv6) {
175 proto_tree_add_item(olsr_tree, hf_olsr_neighbor6_addr, tvb, offset, 16, ENC_NA);
176 offset += 16;
177 } else {
178 break; /* unknown address type should be handled in dissect_olsr, just be sure */
181 return message_end;
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");
189 return message_end;
191 proto_tree_add_item(olsr_tree, hf_olsr_ansn, tvb, offset, 2, ENC_BIG_ENDIAN);
192 offset += 4;
194 while (offset < message_end) {
195 proto_item *address_group;
196 proto_tree *address_tree;
197 uint8_t lq, nlq;
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)");
203 return message_end;
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);
214 offset += 4;
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)");
219 return message_end;
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);
230 offset += 16;
231 } else {
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);
237 offset += 2;
239 return message_end;
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");
247 return message_end;
250 proto_tree_add_item(olsr_tree, hf_olsr_ansn, tvb, offset, 2, ENC_BIG_ENDIAN);
251 offset += 4;
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);
260 offset += 4;
261 } else if (pinfo->src.type == AT_IPv6) {
262 proto_tree_add_item(olsr_tree, hf_olsr_neighbor6_addr, tvb, offset, 16, ENC_NA);
263 offset += 16;
264 } else {
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);
271 return message_end;
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)) {
277 double hTime;
278 proto_item *ti;
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");
286 return message_end;
289 offset += 2;
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);
295 offset += 1;
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");
304 return message_end;
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);
311 /* reserved byte */
312 offset += 1;
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);
317 offset += 2;
319 if (message_size < 4) {
320 expert_add_info_format(pinfo, ti, &ei_olsr_not_enough_bytes, "(too short, must be >= 4)");
321 return message_end;
323 offset = handleNeighbors(tvb, pinfo, link_type_tree, offset, offset + message_size - 4);
325 return message_end;
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);
339 offset += 4;
340 } else if (pinfo->src.type == AT_IPv6) {
341 proto_tree_add_item(olsr_tree, hf_olsr_neighbor6_addr, tvb, offset, 16, ENC_NA);
342 offset += 16;
343 } else {
344 break; /* unknown address type should be handled in dissect_olsr, just be sure */
346 } /* end while */
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;
357 uint8_t lq, nlq;
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);
375 offset += 4;
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);
386 offset += 16;
387 } else {
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);
393 offset += 2;
394 } /* end while */
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");
404 return message_end;
406 if (pinfo->src.type == AT_IPv4) {
407 proto_tree_add_item(olsr_tree, hf_olsr_interface_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
408 offset += 4;
409 } else if (pinfo->src.type == AT_IPv6) {
410 proto_tree_add_item(olsr_tree, hf_olsr_interface6_addr, tvb, offset, 16, ENC_NA);
411 offset += 16;
412 } else {
413 break; /* unknown address type should be handled in dissect_olsr, just be sure */
415 } /* end while for MID */
416 return message_end;
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");
425 return message_end;
428 if (pinfo->src.type == AT_IPv4) {
429 proto_tree_add_item(olsr_tree, hf_olsr_network_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
430 offset += 4;
431 proto_tree_add_item(olsr_tree, hf_olsr_netmask, tvb, offset, 4, ENC_BIG_ENDIAN);
432 offset += 4;
433 } else if (pinfo->src.type == AT_IPv6) {
434 proto_tree_add_item(olsr_tree, hf_olsr_network6_addr, tvb, offset, 4, ENC_NA);
435 offset += 16;
436 proto_tree_add_item(olsr_tree, hf_olsr_netmask6, tvb, offset, 4, ENC_NA);
437 offset += 16;
438 } else {
439 break; /* unknown address type should be handled in dissect_olsr, just be sure */
441 } /* end while for HNA */
442 return message_end;
445 /*------------------------- MID Dissecting Code-------------------------*/
446 static int dissect_olsrorg_nameservice(tvbuff_t *tvb, packet_info *pinfo, proto_tree *olsr_tree, int offset,
447 int message_end) {
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");
456 return message_end;
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);
465 offset += 4;
467 if (version != 1) {
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);
471 return message_end;
474 while (offset < message_end && count-- > 0) {
475 uint16_t type, length;
476 int total_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");
481 return message_end;
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);
501 } else {
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");
508 return message_end;
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;
513 return message_end;
516 /*------------------------- Packet Dissecting Code-------------------------*/
517 static int dissect_olsr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
518 proto_item *ti;
519 proto_tree *olsr_tree;
521 int offset, message_len, message_end;
522 unsigned message_type;
523 double vTime;
525 uint16_t packet_len;
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);
536 return 0;
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);
544 return 0;
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);
559 offset = 4;
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 !");
568 break;
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"),
577 message_type);
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);
581 offset += 1;
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);
586 offset += 1;
588 /*-------------Dissect Message Size---------------------------*/
589 ti = proto_tree_add_item(message_tree, hf_olsr_message_size, tvb, offset, 2, ENC_BIG_ENDIAN);
590 offset += 2;
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);
594 break;
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)");
600 break;
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);
606 offset += 4;
607 } else if (pinfo->src.type == AT_IPv6) {
608 proto_tree_add_item(message_tree, hf_olsr_origin6_addr, tvb, offset, 16, ENC_NA);
609 offset += 16;
610 } else {
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);
617 offset += 4;
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-----------------------------*/
655 else {
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);
660 break;
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,
684 NULL, HFILL
688 { &hf_olsr_message,
689 { "Message", "olsr.message",
690 FT_BYTES, BASE_NONE, NULL, 0,
691 NULL, HFILL
695 { &hf_olsr_message_type,
696 { "Message Type", "olsr.message_type",
697 FT_UINT8, BASE_DEC, VALS(message_type_vals), 0,
698 NULL, HFILL
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,
712 NULL, HFILL
716 { &hf_olsr_vtime,
717 { "Validity Time", "olsr.vtime",
718 FT_DOUBLE, BASE_NONE, NULL, 0,
719 "Validity Time in seconds", HFILL
723 { &hf_olsr_ansn,
724 { "Advertised Neighbor Sequence Number (ANSN)", "olsr.ansn",
725 FT_UINT16, BASE_DEC, NULL, 0,
726 NULL, HFILL
730 { &hf_olsr_htime,
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,
740 NULL, HFILL
744 { &hf_olsr_ttl,
745 { "TTL", "olsr.ttl",
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,
754 NULL, HFILL
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,
768 NULL, HFILL
772 { &hf_olsr_neighbor,
773 { "Neighbor Address", "olsr.neighbor",
774 FT_BYTES, BASE_NONE, NULL, 0,
775 NULL, HFILL
779 { &hf_olsr_origin_addr,
780 { "Originator Address", "olsr.origin_addr",
781 FT_IPv4, BASE_NONE, NULL, 0,
782 NULL, HFILL
786 { &hf_olsr_neighbor_addr,
787 { "Neighbor Address", "olsr.neighbor_addr",
788 FT_IPv4, BASE_NONE, NULL, 0,
789 NULL, HFILL
793 { &hf_olsr_network_addr,
794 { "Network Address", "olsr.network_addr",
795 FT_IPv4, BASE_NONE, NULL, 0,
796 NULL, HFILL
800 { &hf_olsr_interface_addr,
801 { "Interface Address", "olsr.interface_addr",
802 FT_IPv4, BASE_NONE, NULL, 0,
803 NULL, HFILL
807 { &hf_olsr_netmask,
808 { "Netmask", "olsr.netmask",
809 FT_IPv4, BASE_NETMASK, NULL, 0,
810 NULL, HFILL
814 #if 0
815 { &hf_olsr_neighbor6,
816 { "Neighbor Address", "olsr.neighbor6",
817 FT_BYTES, BASE_NONE, NULL, 0,
818 NULL, HFILL
821 #endif
823 { &hf_olsr_origin6_addr,
824 { "Originator Address", "olsr.origin6_addr",
825 FT_IPv6, BASE_NONE, NULL, 0,
826 NULL, HFILL
830 { &hf_olsr_neighbor6_addr,
831 { "Neighbor Address", "olsr.neighbor6_addr",
832 FT_IPv6, BASE_NONE, NULL, 0,
833 NULL, HFILL
837 { &hf_olsr_network6_addr,
838 { "Network Address", "olsr.network6_addr",
839 FT_IPv6, BASE_NONE, NULL, 0,
840 NULL, HFILL
844 { &hf_olsr_interface6_addr,
845 { "Interface Address", "olsr.interface6_addr",
846 FT_IPv6, BASE_NONE, NULL, 0,
847 NULL, HFILL
851 { &hf_olsr_netmask6,
852 { "Netmask", "olsr.netmask6",
853 FT_IPv6, BASE_NONE, NULL, 0,
854 NULL, HFILL
858 { &hf_olsr_data,
859 { "Data", "olsr.data",
860 FT_BYTES, BASE_NONE, NULL, 0,
861 NULL, HFILL
865 { &hf_olsrorg_lq,
866 { "LQ", "olsr.lq",
867 FT_UINT8, BASE_DEC, NULL, 0,
868 "Link quality", HFILL
871 { &hf_olsrorg_nlq,
872 { "NLQ", "olsr.nlq",
873 FT_UINT8, BASE_DEC, NULL, 0,
874 "Neighbor link quality", HFILL
878 { &hf_olsrorg_ns,
879 { "Nameservice", "olsr.ns",
880 FT_BYTES, BASE_NONE, NULL, 0,
881 NULL, HFILL
884 { &hf_olsrorg_ns_version,
885 { "Version", "olsr.ns.version",
886 FT_UINT16, BASE_DEC, NULL, 0,
887 NULL, HFILL
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,
899 NULL, HFILL
902 { &hf_olsrorg_ns_length,
903 { "Length", "olsr.ns.length",
904 FT_UINT16, BASE_DEC, NULL, 0,
905 NULL, HFILL
908 { &hf_olsrorg_ns_ip,
909 { "Address", "olsr.ns.ip",
910 FT_IPv4, BASE_NONE, NULL, 0,
911 NULL, HFILL
914 { &hf_olsrorg_ns_ip6,
915 { "Address", "olsr.ns.ip6",
916 FT_IPv6, BASE_NONE, NULL, 0,
917 NULL, HFILL
920 { &hf_olsrorg_ns_content,
921 { "Content", "olsr.ns.content",
922 FT_STRING, BASE_NONE, NULL, 0,
923 NULL, HFILL
927 { &hf_nrlolsr_f1,
928 { "NRL MINMAX", "olsr.nrl.minmax",
929 FT_UINT8, BASE_DEC, NULL, 0,
930 NULL, HFILL
933 { &hf_nrlolsr_f2,
934 { "NRL SPF", "olsr.nrl.spf",
935 FT_UINT8, BASE_DEC, NULL, 0,
936 NULL, HFILL
941 static int *ett_base[] = {
942 &ett_olsr,
943 &ett_olsr_message_linktype,
944 &ett_olsr_message_neigh,
945 &ett_olsr_message_neigh6,
946 &ett_olsr_message_ns
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;
959 int i,j;
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);
989 * Editor modelines
991 * Local Variables:
992 * c-basic-offset: 2
993 * tab-width: 8
994 * indent-tabs-mode: nil
995 * End:
997 * ex: set shiftwidth=2 tabstop=8 expandtab:
998 * :indentSize=2:tabSize=8:noTabs=true: