/src/wireshark/epan/dissectors/packet-babel.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-babel.c |
2 | | * Routines for Babel dissection (RFC 6126) |
3 | | * Copyright 2011 by Juliusz Chroboczek <jch@pps.jussieu.fr> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | #include "config.h" |
13 | | |
14 | | #include <epan/packet.h> |
15 | | #include <epan/to_str.h> |
16 | | void proto_register_babel(void); |
17 | | void proto_reg_handoff_babel(void); |
18 | | |
19 | | static dissector_handle_t babel_handle; |
20 | | |
21 | | static int proto_babel; |
22 | | |
23 | | static int ett_babel; |
24 | | static int hf_babel_magic; |
25 | | static int hf_babel_version; |
26 | | static int hf_babel_bodylen; |
27 | | |
28 | | static int hf_babel_message; |
29 | | static int ett_message; |
30 | | static int hf_babel_message_type; |
31 | | static int hf_babel_message_length; |
32 | | static int hf_babel_message_nonce; |
33 | | static int hf_babel_message_interval; |
34 | | static int hf_babel_message_seqno; |
35 | | static int hf_babel_message_ae; |
36 | | static int hf_babel_message_prefix; |
37 | | static int hf_babel_message_rxcost; |
38 | | static int hf_babel_message_routerid; |
39 | | static int hf_babel_message_flags; |
40 | | static int hf_babel_message_plen; |
41 | | static int hf_babel_message_omitted; |
42 | | static int hf_babel_message_metric; |
43 | | static int hf_babel_message_hopcount; |
44 | | static int hf_babel_message_index; |
45 | | static int hf_babel_subtlv; |
46 | | static int hf_babel_subtlv_type; |
47 | | static int hf_babel_subtlv_len; |
48 | | static int hf_babel_subtlv_diversity; |
49 | | |
50 | | static int ett_subtree; |
51 | | static int ett_packet_trailer; |
52 | | static int ett_unicast; |
53 | | static int ett_subtlv; |
54 | | static int ett_timestamp; |
55 | | static int ett_mandatory; |
56 | | |
57 | 14 | #define UDP_PORT_RANGE_BABEL "6696" |
58 | | |
59 | 2.64k | #define MESSAGE_PAD1 0 |
60 | 503 | #define MESSAGE_PADN 1 |
61 | 345 | #define MESSAGE_ACK_REQ 2 |
62 | 231 | #define MESSAGE_ACK 3 |
63 | 204 | #define MESSAGE_HELLO 4 |
64 | 185 | #define MESSAGE_IHU 5 |
65 | 146 | #define MESSAGE_ROUTER_ID 6 |
66 | 140 | #define MESSAGE_NH 7 |
67 | 129 | #define MESSAGE_UPDATE 8 |
68 | 125 | #define MESSAGE_REQUEST 9 |
69 | 122 | #define MESSAGE_MH_REQUEST 10 |
70 | | #define MESSAGE_TS_PC 11 |
71 | | #define MESSAGE_HMAC_OLD 12 |
72 | | #define MESSAGE_SRC_UPDATE 13 |
73 | | #define MESSAGE_SRC_REQUEST 14 |
74 | | #define MESSAGE_SRC_SEQNO 15 |
75 | | #define MESSAGE_HMAC 16 |
76 | 119 | #define MESSAGE_PC 17 |
77 | | #define MESSAGE_CHALLENGE_REQUEST 18 |
78 | | #define MESSAGE_CHALLENGE_REPLY 19 |
79 | | |
80 | | /** sub-TLVs */ |
81 | 915 | #define MESSAGE_SUB_PAD1 0 |
82 | 87 | #define MESSAGE_SUB_PADN 1 |
83 | 27 | #define MESSAGE_SUB_DIVERSITY 2 |
84 | 6 | #define MESSAGE_SUB_TIMESTAMP 3 |
85 | | |
86 | | /** mask for bits */ |
87 | | #define UNICAST_FLAG 0x80 |
88 | 194 | #define MANDATORY_FLAG 128 |
89 | | |
90 | | /** message string values listed in rfc7557 */ |
91 | | static const value_string messages[] = { |
92 | | { MESSAGE_PAD1, "pad1"}, |
93 | | { MESSAGE_PADN, "padn"}, |
94 | | { MESSAGE_ACK_REQ, "ack-req"}, |
95 | | { MESSAGE_ACK, "ack"}, |
96 | | { MESSAGE_HELLO, "hello"}, |
97 | | { MESSAGE_IHU, "ihu"}, |
98 | | { MESSAGE_ROUTER_ID, "router-id"}, |
99 | | { MESSAGE_NH, "nh"}, |
100 | | { MESSAGE_UPDATE, "update"}, |
101 | | { MESSAGE_REQUEST, "request"}, |
102 | | { MESSAGE_MH_REQUEST, "mh-request"}, |
103 | | { MESSAGE_TS_PC, "ts/pc (obsolete)"}, |
104 | | { MESSAGE_HMAC_OLD, "hmac" }, |
105 | | { MESSAGE_SRC_UPDATE, "source-specific-update"}, |
106 | | { MESSAGE_SRC_REQUEST, "source-specific-req"}, |
107 | | { MESSAGE_SRC_SEQNO, "source-specific-seqno"}, |
108 | | { MESSAGE_HMAC, "hmac"}, |
109 | | { MESSAGE_PC, "pc"}, |
110 | | { MESSAGE_CHALLENGE_REQUEST, "challenge-request"}, |
111 | | { MESSAGE_CHALLENGE_REPLY, "challenge-reply"}, |
112 | | { 0, NULL} |
113 | | }; |
114 | | |
115 | | static const value_string subtlvs[] = { |
116 | | { MESSAGE_SUB_PAD1, "sub-pad1"}, |
117 | | { MESSAGE_SUB_PADN, "sub-padn"}, |
118 | | { MESSAGE_SUB_DIVERSITY, "diversity"}, |
119 | | { MESSAGE_SUB_TIMESTAMP, "timestamp"}, |
120 | | { 0, NULL} |
121 | | }; |
122 | | |
123 | | static const value_string aes[] = { |
124 | | { 0, "Wildcard" }, |
125 | | { 1, "IPv4" }, |
126 | | { 2, "IPv6" }, |
127 | | { 3, "Link-Local IPv6"}, |
128 | | { 0, NULL } |
129 | | }; |
130 | | |
131 | | /* The prefix for v6-mapped IPv4 addresses. Format_address below |
132 | | returns IPv4 addresses in that format. */ |
133 | | |
134 | | static const unsigned char v4prefix[16] = |
135 | | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; |
136 | | |
137 | | /* The following two functions return ephemeral or constant strings, no |
138 | | need to call free. */ |
139 | | |
140 | | static const char * |
141 | | format_address(wmem_allocator_t *scope, const unsigned char *prefix) |
142 | 54 | { |
143 | 54 | address addr; |
144 | | |
145 | 54 | if (prefix == NULL) |
146 | 44 | return "corrupt"; |
147 | 10 | else if (memcmp(prefix, v4prefix, 12) == 0) |
148 | 3 | { |
149 | 3 | addr.type = AT_IPv4; |
150 | 3 | addr.len = 4; |
151 | 3 | addr.data = prefix + 12; |
152 | | |
153 | 3 | return address_to_str(scope, &addr); |
154 | 3 | } |
155 | 7 | else |
156 | 7 | { |
157 | 7 | addr.type = AT_IPv6; |
158 | 7 | addr.len = 16; |
159 | 7 | addr.data = prefix; |
160 | | |
161 | 7 | return address_to_str(scope, &addr); |
162 | 7 | } |
163 | 54 | } |
164 | | |
165 | | static const char * |
166 | | format_prefix(wmem_allocator_t *scope, const unsigned char *prefix, unsigned char plen) |
167 | 10 | { |
168 | 10 | return wmem_strdup_printf(scope, "%s/%u", format_address(scope, prefix), plen); |
169 | 10 | } |
170 | | |
171 | | static int |
172 | | network_prefix(int ae, int plen, unsigned int omitted, |
173 | | tvbuff_t *tvb, int offset, const unsigned char *dp, |
174 | | unsigned int len, unsigned char *p_r) |
175 | 54 | { |
176 | 54 | unsigned pb; |
177 | 54 | unsigned char prefix[16]; |
178 | 54 | int consumed = 0; |
179 | | |
180 | 54 | if (plen >= 0) |
181 | 10 | pb = (plen + 7) / 8; |
182 | 44 | else if (ae == 1) |
183 | 3 | pb = 4; |
184 | 41 | else |
185 | 41 | pb = 16; |
186 | | |
187 | 54 | if (pb > 16) |
188 | 3 | return -1; |
189 | | |
190 | 51 | memset(prefix, 0, 16); |
191 | | |
192 | 51 | switch(ae) { |
193 | 5 | case 0: break; |
194 | 3 | case 1: |
195 | 3 | if (omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted)) |
196 | 0 | return -1; |
197 | 3 | memcpy(prefix, v4prefix, 12); |
198 | 3 | if (omitted) { |
199 | 0 | if (dp == NULL) return -1; |
200 | 0 | memcpy(prefix, dp, 12 + omitted); |
201 | 0 | } |
202 | 3 | if (pb > omitted) { |
203 | 3 | tvb_memcpy(tvb, prefix + 12 + omitted, offset, pb - omitted); |
204 | 3 | consumed = pb - omitted; |
205 | 3 | } |
206 | 3 | break; |
207 | 2 | case 2: |
208 | 2 | if (omitted > 16 || (pb > omitted && len < pb - omitted)) |
209 | 0 | return -1; |
210 | 2 | if (omitted) { |
211 | 0 | if (dp == NULL) return -1; |
212 | 0 | memcpy(prefix, dp, omitted); |
213 | 0 | } |
214 | 2 | if (pb > omitted) { |
215 | 2 | tvb_memcpy(tvb, prefix + omitted, offset, pb - omitted); |
216 | 2 | consumed = pb - omitted; |
217 | 2 | } |
218 | 2 | break; |
219 | 10 | case 3: |
220 | 10 | if (pb > 8 && len < pb - 8) return -1; |
221 | 0 | prefix[0] = 0xfe; |
222 | 0 | prefix[1] = 0x80; |
223 | 0 | if (pb > 8) { |
224 | 0 | tvb_memcpy(tvb, prefix + 8, offset, pb - 8); |
225 | 0 | consumed = pb - 8; |
226 | 0 | } |
227 | 0 | break; |
228 | 31 | default: |
229 | 31 | return -1; |
230 | 51 | } |
231 | | |
232 | 10 | memcpy(p_r, prefix, 16); |
233 | 10 | return consumed; |
234 | 51 | } |
235 | | |
236 | | static int |
237 | | network_address(int ae, tvbuff_t *tvb, int offset, unsigned int len, |
238 | | unsigned char *a_r) |
239 | 44 | { |
240 | 44 | return network_prefix(ae, -1, 0, tvb, offset, NULL, len, a_r); |
241 | 44 | } |
242 | | |
243 | | static const char * |
244 | | format_timestamp(const uint32_t i) |
245 | 12 | { |
246 | 12 | static char buf[sizeof("0000.000000s")]; |
247 | 12 | snprintf(buf, sizeof(buf), "%u.%06us", i / 1000000, i % 1000000); |
248 | 12 | return buf; |
249 | 12 | } |
250 | | |
251 | | static int |
252 | | dissect_babel_subtlvs(tvbuff_t * tvb, uint8_t type, uint16_t beg, |
253 | | uint16_t end, proto_tree *message_tree) |
254 | 23 | { |
255 | 23 | proto_tree *channel_tree = NULL; |
256 | 23 | proto_item *sub_item; |
257 | 23 | uint8_t subtype, sublen; |
258 | 23 | int i = 0; |
259 | | |
260 | 327 | while(beg < end) { |
261 | 305 | proto_tree *subtlv_tree; |
262 | 305 | subtype = tvb_get_uint8(tvb, beg); |
263 | 305 | if (subtype != MESSAGE_SUB_PAD1) { |
264 | 194 | sublen = tvb_get_uint8(tvb, beg+1); |
265 | 194 | } else { |
266 | 111 | sublen = 0; |
267 | 111 | } |
268 | | |
269 | 305 | sub_item = |
270 | 305 | proto_tree_add_uint_format(message_tree, hf_babel_subtlv, |
271 | 305 | tvb, beg, sublen + ((subtype == MESSAGE_SUB_PAD1) ? 1 : 2), |
272 | 305 | subtype, "Sub TLV %s (%u)", |
273 | 305 | val_to_str_const(subtype, subtlvs, "unknown"), |
274 | 305 | subtype); |
275 | 305 | subtlv_tree = proto_item_add_subtree(sub_item, ett_subtlv); |
276 | | |
277 | 305 | proto_tree_add_item(subtlv_tree, hf_babel_subtlv_type, |
278 | 305 | tvb, beg, 1, ENC_BIG_ENDIAN); |
279 | 305 | if(subtype == MESSAGE_SUB_PAD1){ |
280 | 111 | beg += 1; |
281 | 111 | continue; |
282 | 111 | } |
283 | 194 | proto_tree_add_item(subtlv_tree, hf_babel_subtlv_len, |
284 | 194 | tvb, beg+1, 1, ENC_BIG_ENDIAN); |
285 | | |
286 | 194 | if ((MANDATORY_FLAG & subtype) != 0) { |
287 | 31 | proto_tree_add_subtree_format(subtlv_tree, tvb, beg+2, sublen, |
288 | 31 | ett_mandatory, NULL, "Mandatory"); |
289 | 31 | } |
290 | | |
291 | 194 | switch(subtype) { |
292 | 87 | case MESSAGE_SUB_PADN: |
293 | 87 | break; |
294 | 27 | case MESSAGE_SUB_DIVERSITY: { |
295 | 27 | i = 0; |
296 | 27 | channel_tree = proto_tree_add_subtree_format(subtlv_tree, tvb, |
297 | 27 | beg+2, 0, ett_subtlv, |
298 | 27 | NULL, "Channel"); |
299 | 333 | while(i < sublen) { |
300 | 306 | proto_tree_add_item(channel_tree, hf_babel_subtlv_diversity, |
301 | 306 | tvb, beg+2+i, 1, ENC_BIG_ENDIAN); |
302 | 306 | i++; |
303 | 306 | } |
304 | 27 | } |
305 | 27 | break; |
306 | 6 | case MESSAGE_SUB_TIMESTAMP: { |
307 | 6 | if (type == MESSAGE_HELLO) { |
308 | 0 | uint32_t t1 = tvb_get_uint32(tvb, beg+2, ENC_BIG_ENDIAN); |
309 | 0 | proto_tree_add_subtree_format(subtlv_tree, tvb, beg+2, |
310 | 0 | sublen, ett_timestamp, NULL, |
311 | 0 | "Timestamp : %s", |
312 | 0 | format_timestamp(t1)); |
313 | 6 | } else if (type == MESSAGE_IHU) { |
314 | 6 | uint32_t t1 = tvb_get_uint32(tvb, beg+2, ENC_BIG_ENDIAN); |
315 | 6 | uint32_t t2 = tvb_get_uint32(tvb, beg+6, ENC_BIG_ENDIAN); |
316 | 6 | proto_tree_add_subtree_format(subtlv_tree, tvb, beg+2, |
317 | 6 | sublen, ett_timestamp, NULL, |
318 | 6 | "Timestamp origin : %s", |
319 | 6 | format_timestamp(t1)); |
320 | 6 | proto_tree_add_subtree_format(subtlv_tree, tvb, beg+6, |
321 | 6 | sublen, ett_timestamp, NULL, |
322 | 6 | "Timestamp receive: %s", |
323 | 6 | format_timestamp(t2)); |
324 | 6 | } else { |
325 | 0 | proto_tree_add_subtree_format(subtlv_tree, tvb, beg+2, sublen, |
326 | 0 | ett_timestamp, NULL, "Bogus"); |
327 | 0 | } |
328 | 6 | } |
329 | 6 | break; |
330 | 194 | } |
331 | 193 | beg += (sublen+2); |
332 | 193 | } |
333 | 22 | return end-beg; |
334 | 23 | } |
335 | | |
336 | | |
337 | | /* The following function is used to read the packet body and |
338 | | the packet trailer */ |
339 | | static int |
340 | | // NOLINTNEXTLINE(misc-no-recursion) |
341 | | dissect_babel_body(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
342 | | int offset, uint16_t bodylen) |
343 | 44 | { |
344 | 44 | proto_item *ti = NULL; |
345 | 44 | unsigned char v4_prefix[16] = {0}, v6_prefix[16] = {0}; |
346 | 44 | int i; |
347 | | |
348 | | |
349 | 44 | i = offset; |
350 | 1.36k | while (i-offset < bodylen) { |
351 | 1.32k | uint8_t type, len = 0; |
352 | 1.32k | uint16_t total_length; |
353 | 1.32k | proto_tree *message_tree = NULL; |
354 | 1.32k | int message = 4 + i; |
355 | | |
356 | 1.32k | type = tvb_get_uint8(tvb, message); |
357 | 1.32k | if (type == MESSAGE_PAD1) |
358 | 803 | total_length = 1; |
359 | 520 | else { |
360 | 520 | len = tvb_get_uint8(tvb, message + 1); |
361 | 520 | total_length = len + 2; |
362 | 520 | } |
363 | | |
364 | 1.32k | col_append_fstr(pinfo->cinfo, COL_INFO, " %s", |
365 | 1.32k | val_to_str_const(type, messages, "unknown")); |
366 | | |
367 | 1.32k | ti = proto_tree_add_uint_format(tree, hf_babel_message, |
368 | 1.32k | tvb, message, total_length, type, |
369 | 1.32k | "Message %s (%u)", |
370 | 1.32k | val_to_str_const(type, messages, "unknown"), |
371 | 1.32k | type); |
372 | | |
373 | 1.32k | if (tree) { |
374 | 1.30k | message_tree = proto_item_add_subtree(ti, ett_message); |
375 | 1.30k | proto_tree_add_item(message_tree, hf_babel_message_type, |
376 | 1.30k | tvb, message, 1, ENC_BIG_ENDIAN); |
377 | 1.30k | } |
378 | | |
379 | 1.32k | if (type == MESSAGE_PAD1) { |
380 | 803 | i++; |
381 | 803 | continue; |
382 | 803 | } |
383 | | |
384 | 520 | if (tree) { |
385 | 503 | proto_tree_add_item(message_tree, hf_babel_message_length, |
386 | 503 | tvb, message + 1, 1, ENC_BIG_ENDIAN); |
387 | 503 | if (type == MESSAGE_PADN) { |
388 | 345 | } else if (type == MESSAGE_ACK_REQ) { |
389 | 114 | proto_tree_add_item(message_tree, hf_babel_message_nonce, |
390 | 114 | tvb, message + 4, 2, ENC_BIG_ENDIAN); |
391 | 114 | proto_tree_add_item(message_tree, hf_babel_message_interval, |
392 | 114 | tvb, message + 6, 2, ENC_BIG_ENDIAN); |
393 | 231 | } else if (type == MESSAGE_ACK) { |
394 | 33 | proto_tree_add_item(message_tree, hf_babel_message_nonce, |
395 | 33 | tvb, message + 2, 2, ENC_BIG_ENDIAN); |
396 | 198 | } else if (type == MESSAGE_HELLO) { |
397 | 19 | uint8_t unicast = tvb_get_uint8(tvb, 2); |
398 | 19 | proto_tree_add_subtree_format(message_tree, |
399 | 19 | tvb, message + 2, 2, |
400 | 19 | ett_unicast, NULL, |
401 | 19 | "Unicast : %u", |
402 | 19 | unicast); |
403 | 19 | proto_tree_add_item(message_tree, hf_babel_message_seqno, |
404 | 19 | tvb, message + 4, 2, ENC_BIG_ENDIAN); |
405 | 19 | proto_tree_add_item(message_tree, hf_babel_message_interval, |
406 | 19 | tvb, message + 6, 2, ENC_BIG_ENDIAN); |
407 | 19 | if(len > 6) |
408 | 2 | dissect_babel_subtlvs(tvb, type, message + 8, |
409 | 2 | message + 2 + len, message_tree); |
410 | 179 | } else if (type == MESSAGE_IHU) { |
411 | 33 | proto_tree *subtree; |
412 | 33 | unsigned char addr_str[16]; |
413 | 33 | int rc = |
414 | 33 | network_address(tvb_get_uint8(tvb, message + 2), |
415 | 33 | tvb, message + 8, len - 6, addr_str); |
416 | 33 | proto_tree_add_item(message_tree, hf_babel_message_rxcost, |
417 | 33 | tvb, message + 4, 2, ENC_BIG_ENDIAN); |
418 | 33 | proto_tree_add_item(message_tree, hf_babel_message_interval, |
419 | 33 | tvb, message + 6, 2, ENC_BIG_ENDIAN); |
420 | 33 | subtree = proto_tree_add_subtree_format(message_tree, |
421 | 33 | tvb, message + 4, len - 2, |
422 | 33 | ett_subtree, NULL, "Address: %s", |
423 | 33 | format_address(pinfo->pool, |
424 | 33 | rc < 0 ? NULL : addr_str)); |
425 | 33 | proto_tree_add_item(subtree, hf_babel_message_ae, |
426 | 33 | tvb, message + 2, 1, ENC_BIG_ENDIAN); |
427 | 33 | proto_tree_add_item(subtree, hf_babel_message_prefix, |
428 | 33 | tvb, message + 4, len - 2, ENC_NA); |
429 | 33 | if (rc < len - 6) |
430 | 21 | dissect_babel_subtlvs(tvb, type, message + 8 + rc, |
431 | 21 | message + 2 + len, message_tree); |
432 | 146 | } else if (type == MESSAGE_ROUTER_ID) { |
433 | 6 | proto_tree_add_item(message_tree, hf_babel_message_routerid, |
434 | 6 | tvb, message + 4, 8, ENC_NA); |
435 | 140 | } else if (type == MESSAGE_NH) { |
436 | 11 | proto_tree *subtree; |
437 | 11 | unsigned char nh[16]; |
438 | 11 | int rc = |
439 | 11 | network_address(tvb_get_uint8(tvb, message + 2), |
440 | 11 | tvb, message + 4, len - 2, nh); |
441 | 11 | subtree = proto_tree_add_subtree_format(message_tree, |
442 | 11 | tvb, message + 4, len - 2, |
443 | 11 | ett_subtree, NULL, |
444 | 11 | "NH: %s", |
445 | 11 | format_address(pinfo->pool, |
446 | 11 | rc < 0 ? NULL : nh)); |
447 | 11 | proto_tree_add_item(subtree, hf_babel_message_ae, |
448 | 11 | tvb, message + 2, 1, ENC_BIG_ENDIAN); |
449 | 11 | proto_tree_add_item(subtree, hf_babel_message_prefix, |
450 | 11 | tvb, message + 4, len - 2, ENC_NA); |
451 | 129 | } else if (type == MESSAGE_UPDATE) { |
452 | 4 | proto_tree *subtree; |
453 | 4 | unsigned char p[16]; |
454 | 4 | uint8_t ae = tvb_get_uint8(tvb, message + 2); |
455 | 4 | uint8_t flags = tvb_get_uint8(tvb, message + 3); |
456 | 4 | uint8_t plen = tvb_get_uint8(tvb, message + 4); |
457 | 4 | int rc = |
458 | 4 | network_prefix(ae, plen, |
459 | 4 | tvb_get_uint8(tvb, message + 5), |
460 | 4 | tvb, message + 12, |
461 | 4 | ae == 1 ? v4_prefix : v6_prefix, |
462 | 4 | len - 10, p); |
463 | 4 | if (rc >= 0 && (flags & 0x80)) { |
464 | 0 | if (ae == 1) |
465 | 0 | memcpy(v4_prefix, p, 16); |
466 | 0 | else |
467 | 0 | memcpy(v6_prefix, p, 16); |
468 | 0 | } |
469 | | |
470 | 4 | proto_tree_add_item(message_tree, hf_babel_message_flags, |
471 | 4 | tvb, message + 3, 1, ENC_BIG_ENDIAN); |
472 | 4 | proto_tree_add_item(message_tree, hf_babel_message_interval, |
473 | 4 | tvb, message + 6, 2, ENC_BIG_ENDIAN); |
474 | 4 | proto_tree_add_item(message_tree, hf_babel_message_seqno, |
475 | 4 | tvb, message + 8, 2, ENC_BIG_ENDIAN); |
476 | 4 | proto_tree_add_item(message_tree, hf_babel_message_metric, |
477 | 4 | tvb, message + 10, 2, ENC_BIG_ENDIAN); |
478 | 4 | subtree = proto_tree_add_subtree_format(message_tree, |
479 | 4 | tvb, message + 12, len - 10, |
480 | 4 | ett_subtree, NULL, |
481 | 4 | "Prefix: %s", |
482 | 4 | format_prefix(pinfo->pool, |
483 | 4 | rc < 0 ? NULL : p, |
484 | 4 | plen)); |
485 | 4 | proto_tree_add_item(subtree, hf_babel_message_ae, |
486 | 4 | tvb, message + 2, 1, ENC_BIG_ENDIAN); |
487 | 4 | proto_tree_add_item(subtree, hf_babel_message_plen, |
488 | 4 | tvb, message + 4, 1, ENC_BIG_ENDIAN); |
489 | 4 | proto_tree_add_item(subtree, hf_babel_message_omitted, |
490 | 4 | tvb, message + 5, 1, ENC_BIG_ENDIAN); |
491 | 4 | proto_tree_add_item(subtree, hf_babel_message_prefix, |
492 | 4 | tvb, message + 12, len - 10, ENC_NA); |
493 | 4 | if (((uint8_t)rc) < len - 10) |
494 | 0 | dissect_babel_subtlvs(tvb, type, message + 12 + rc, |
495 | 0 | message + 2 + len, message_tree); |
496 | 125 | } else if (type == MESSAGE_REQUEST) { |
497 | 3 | proto_tree *subtree; |
498 | 3 | unsigned char p[16]; |
499 | 3 | uint8_t plen = tvb_get_uint8(tvb, message + 3); |
500 | 3 | int rc = |
501 | 3 | network_prefix(tvb_get_uint8(tvb, message + 2), plen, |
502 | 3 | 0, tvb, message + 4, NULL, |
503 | 3 | len - 2, p); |
504 | 3 | subtree = proto_tree_add_subtree_format(message_tree, |
505 | 3 | tvb, message + 4, len - 2, |
506 | 3 | ett_subtree, NULL, |
507 | 3 | "Prefix: %s", |
508 | 3 | format_prefix(pinfo->pool, |
509 | 3 | rc < 0 ? NULL : p, |
510 | 3 | plen)); |
511 | 3 | proto_tree_add_item(subtree, hf_babel_message_ae, |
512 | 3 | tvb, message + 2, 1, ENC_BIG_ENDIAN); |
513 | 3 | proto_tree_add_item(subtree, hf_babel_message_plen, |
514 | 3 | tvb, message + 3, 1, ENC_BIG_ENDIAN); |
515 | 3 | proto_tree_add_item(subtree, hf_babel_message_prefix, |
516 | 3 | tvb, message + 4, len - 2, ENC_NA); |
517 | 122 | } else if (type == MESSAGE_MH_REQUEST) { |
518 | 3 | proto_tree *subtree; |
519 | 3 | unsigned char p[16]; |
520 | 3 | uint8_t plen = tvb_get_uint8(tvb, message + 3); |
521 | 3 | int rc = |
522 | 3 | network_prefix(tvb_get_uint8(tvb, message + 2), plen, |
523 | 3 | 0, tvb, message + 16, NULL, |
524 | 3 | len - 14, p); |
525 | 3 | proto_tree_add_item(message_tree, hf_babel_message_seqno, |
526 | 3 | tvb, message + 4, 2, ENC_BIG_ENDIAN); |
527 | 3 | proto_tree_add_item(message_tree, hf_babel_message_hopcount, |
528 | 3 | tvb, message + 6, 1, ENC_BIG_ENDIAN); |
529 | 3 | proto_tree_add_item(message_tree, hf_babel_message_routerid, |
530 | 3 | tvb, message + 8, 8, ENC_NA); |
531 | 3 | subtree = proto_tree_add_subtree_format(message_tree, |
532 | 3 | tvb, message + 16, len - 14, |
533 | 3 | ett_subtree, NULL, |
534 | 3 | "Prefix: %s", |
535 | 3 | format_prefix(pinfo->pool, |
536 | 3 | rc < 0 ? NULL : p, |
537 | 3 | plen)); |
538 | 3 | proto_tree_add_item(subtree, hf_babel_message_ae, |
539 | 3 | tvb, message + 2, 1, ENC_BIG_ENDIAN); |
540 | 3 | proto_tree_add_item(subtree, hf_babel_message_plen, |
541 | 3 | tvb, message + 3, 1, ENC_BIG_ENDIAN); |
542 | 3 | proto_tree_add_item(subtree, hf_babel_message_prefix, |
543 | 3 | tvb, message + 16, len - 14, ENC_NA); |
544 | 119 | } else if (type == MESSAGE_PC){ |
545 | 0 | proto_tree_add_item(message_tree, hf_babel_message_index, |
546 | 0 | tvb, message + 2, 4, ENC_NA); |
547 | 0 | } |
548 | 503 | } |
549 | 520 | i += len + 2; |
550 | 520 | } |
551 | 44 | uint8_t packet_len = tvb_reported_length(tvb) - bodylen - 4; |
552 | 44 | if ((offset == 0) && (packet_len != 0)) { |
553 | 10 | proto_tree * subtree; |
554 | 10 | subtree = proto_tree_add_subtree_format(tree, tvb, 4+bodylen, packet_len, |
555 | 10 | ett_packet_trailer, NULL, |
556 | 10 | "Packet Trailer (%u)", packet_len); |
557 | 10 | increment_dissection_depth(pinfo); |
558 | 10 | dissect_babel_body(tvb, pinfo, subtree, bodylen, packet_len); |
559 | 10 | decrement_dissection_depth(pinfo); |
560 | 10 | } |
561 | 44 | return i; |
562 | 44 | } |
563 | | |
564 | | static int |
565 | | dissect_babel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
566 | 34 | { |
567 | 34 | proto_item *ti; |
568 | 34 | proto_tree *babel_tree = NULL; |
569 | 34 | uint8_t version; |
570 | 34 | uint16_t bodylen; |
571 | | |
572 | 34 | if (tvb_captured_length(tvb) < 4) |
573 | 0 | return 0; |
574 | | |
575 | 34 | if (tvb_get_uint8(tvb, 0) != 42) |
576 | 0 | return 0; |
577 | 34 | version = tvb_get_uint8(tvb, 1); |
578 | | |
579 | 34 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "Babel"); |
580 | 34 | col_set_str(pinfo->cinfo, COL_INFO, "Babel"); |
581 | | |
582 | 34 | if (version != 2) { |
583 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Version %u", version); |
584 | 0 | return 2; |
585 | 0 | } |
586 | | |
587 | 34 | if (tree) { |
588 | 34 | ti = proto_tree_add_item(tree, proto_babel, tvb, 0, -1, ENC_NA); |
589 | 34 | babel_tree = proto_item_add_subtree(ti, ett_babel); |
590 | | |
591 | 34 | proto_tree_add_item(babel_tree, hf_babel_magic, tvb, 0, 1, ENC_BIG_ENDIAN); |
592 | 34 | proto_tree_add_item(babel_tree, hf_babel_version, tvb, 1, 1, ENC_BIG_ENDIAN); |
593 | 34 | proto_tree_add_item(babel_tree, hf_babel_bodylen, |
594 | 34 | tvb, 2, 2, ENC_BIG_ENDIAN); |
595 | 34 | } |
596 | 34 | bodylen = tvb_get_ntohs(tvb, 2); |
597 | 34 | return dissect_babel_body(tvb, pinfo, babel_tree, 0, bodylen); |
598 | | |
599 | 34 | } |
600 | | |
601 | | void |
602 | | proto_register_babel(void) |
603 | 14 | { |
604 | 14 | static hf_register_info hf[] = { |
605 | 14 | { &hf_babel_magic, |
606 | 14 | { "Magic", "babel.magic", FT_UINT8, BASE_DEC, |
607 | 14 | NULL, 0, "Magic value 42", HFILL } |
608 | 14 | }, |
609 | 14 | { &hf_babel_version, |
610 | 14 | { "Version", "babel.version", FT_UINT8, BASE_DEC, |
611 | 14 | NULL, 0, "Version of the Babel protocol", HFILL } |
612 | 14 | }, |
613 | 14 | { &hf_babel_bodylen, |
614 | 14 | { "Body Length", "babel.bodylen", FT_UINT16, BASE_DEC, |
615 | 14 | NULL, 0, NULL, HFILL } |
616 | 14 | }, |
617 | 14 | { &hf_babel_message, |
618 | 14 | { "Message", "babel.message", FT_UINT8, BASE_DEC, |
619 | 14 | NULL, 0, "Babel Message", HFILL } |
620 | 14 | }, |
621 | 14 | { &hf_babel_message_type, |
622 | 14 | { "Message Type", "babel.message.type", FT_UINT8, BASE_DEC, |
623 | 14 | VALS(messages), 0, NULL, HFILL } |
624 | 14 | }, |
625 | 14 | { &hf_babel_message_length, |
626 | 14 | { "Message Length", "babel.message.length", FT_UINT8, BASE_DEC, |
627 | 14 | NULL, 0, NULL, HFILL } |
628 | 14 | }, |
629 | 14 | { &hf_babel_message_nonce, |
630 | 14 | { "Nonce", "babel.message.nonce", FT_UINT16, BASE_HEX, |
631 | 14 | NULL, 0, NULL, HFILL } |
632 | 14 | }, |
633 | 14 | { &hf_babel_message_interval, |
634 | 14 | { "Interval", "babel.message.interval", FT_UINT16, BASE_DEC, |
635 | 14 | NULL, 0, "Interval (in centiseconds)", HFILL } |
636 | 14 | }, |
637 | 14 | { &hf_babel_message_seqno, |
638 | 14 | { "Seqno", "babel.message.seqno", FT_UINT16, BASE_HEX, |
639 | 14 | NULL, 0, NULL, HFILL } |
640 | 14 | }, |
641 | 14 | { &hf_babel_message_ae, |
642 | 14 | { "Address Encoding", "babel.message.ae", FT_UINT8, BASE_DEC, |
643 | 14 | VALS(aes), 0, NULL, HFILL } |
644 | 14 | }, |
645 | 14 | { &hf_babel_message_prefix, |
646 | 14 | { "Raw Prefix", "babel.message.prefix", FT_BYTES, BASE_NONE, |
647 | 14 | NULL, 0, NULL, HFILL } |
648 | 14 | }, |
649 | 14 | { &hf_babel_message_rxcost, |
650 | 14 | { "Rxcost", "babel.message.rxcost", FT_UINT16, BASE_HEX, |
651 | 14 | NULL, 0, "Rxcost (from the point of vue of the sender)", HFILL } |
652 | 14 | }, |
653 | 14 | { &hf_babel_message_routerid, |
654 | 14 | { "Router ID", "babel.message.routerid", FT_BYTES, BASE_NONE, |
655 | 14 | NULL, 0, NULL, HFILL } |
656 | 14 | }, |
657 | 14 | { &hf_babel_message_flags, |
658 | 14 | { "Flags", "babel.message.flags", FT_UINT8, BASE_HEX, |
659 | 14 | NULL, 0, NULL, HFILL } |
660 | 14 | }, |
661 | 14 | { &hf_babel_message_plen, |
662 | 14 | { "Prefix Length", "babel.message.plen", FT_UINT8, BASE_DEC, |
663 | 14 | NULL, 0, NULL, HFILL } |
664 | 14 | }, |
665 | 14 | { &hf_babel_message_omitted, |
666 | 14 | { "Omitted Bytes", "babel.message.omitted", FT_UINT8, BASE_DEC, |
667 | 14 | NULL, 0, "Number of bytes omitted from the prefix", HFILL } |
668 | 14 | }, |
669 | 14 | { &hf_babel_message_metric, |
670 | 14 | { "Metric", "babel.message.metric", FT_UINT16, BASE_DEC, |
671 | 14 | NULL, 0, NULL, HFILL } |
672 | 14 | }, |
673 | 14 | { &hf_babel_message_hopcount, |
674 | 14 | { "Hop Count", "babel.message.hopcount", FT_UINT8, BASE_DEC, |
675 | 14 | NULL, 0, NULL, HFILL } |
676 | 14 | }, |
677 | 14 | { &hf_babel_message_index, |
678 | 14 | { "Index", "babel.message.index", FT_UINT32, BASE_DEC, |
679 | 14 | NULL, 0, NULL, HFILL } |
680 | 14 | }, |
681 | 14 | { &hf_babel_subtlv, |
682 | 14 | { "Sub-TLV", "babel.subtlv", FT_UINT8, BASE_DEC, |
683 | 14 | NULL, 0, "Babel Sub-TLV", HFILL } |
684 | 14 | }, |
685 | 14 | { &hf_babel_subtlv_type, |
686 | 14 | { "Sub-TLV Type", "babel.subtlv.type", FT_UINT8, BASE_DEC, |
687 | 14 | VALS(subtlvs), 0, NULL, HFILL } |
688 | 14 | }, |
689 | 14 | { &hf_babel_subtlv_len, |
690 | 14 | { "Sub-TLV Length", "babel.subtlv.length", FT_UINT8, BASE_DEC, |
691 | 14 | VALS(subtlvs), 0, NULL, HFILL } |
692 | 14 | }, |
693 | 14 | { &hf_babel_subtlv_diversity, |
694 | 14 | { "Channel", "babel.subtlv.diversity.channel", FT_UINT8, BASE_DEC, |
695 | 14 | NULL, 0, NULL, HFILL } |
696 | 14 | } |
697 | 14 | }; |
698 | | |
699 | 14 | static int *ett[] = { |
700 | 14 | &ett_babel, |
701 | 14 | &ett_message, |
702 | 14 | &ett_subtree, |
703 | 14 | &ett_packet_trailer, |
704 | 14 | &ett_unicast, |
705 | 14 | &ett_subtlv, |
706 | 14 | &ett_timestamp, |
707 | 14 | &ett_mandatory |
708 | 14 | }; |
709 | | |
710 | 14 | proto_babel = |
711 | 14 | proto_register_protocol("Babel Routing Protocol", "Babel", "babel"); |
712 | | |
713 | 14 | proto_register_field_array(proto_babel, hf, array_length(hf)); |
714 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
715 | | |
716 | 14 | babel_handle = register_dissector("babel", dissect_babel, proto_babel); |
717 | 14 | } |
718 | | |
719 | | void |
720 | | proto_reg_handoff_babel(void) |
721 | 14 | { |
722 | 14 | dissector_add_uint_range_with_preference("udp.port", UDP_PORT_RANGE_BABEL, babel_handle); |
723 | 14 | } |
724 | | |
725 | | /* |
726 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
727 | | * |
728 | | * Local variables: |
729 | | * c-basic-offset: 4 |
730 | | * tab-width: 8 |
731 | | * indent-tabs-mode: nil |
732 | | * End: |
733 | | * |
734 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
735 | | * :indentSize=4:tabSize=8:noTabs=true: |
736 | | */ |