1 /* packet-mle.c
2 * Routines for MLE packet dissection
3 *
4 * Colin O'Flynn <coflynn@newae.com>
5 *
6 * The entire security section of this is lifted from the IEEE 802.15.4
7 * dissectory, as this is done the same way. Should eventually make the
8 * two use some common functions or something. But that section is:
9 * By Owen Kirby <osk@exegin.com>
10 * Copyright 2007 Exegin Technologies Limited
11 *
12 * Thread parts added by Robert Cragie <robert.cragie@arm.com>
13 *
14 * Wireshark - Network traffic analyzer
15 * By Gerald Combs <gerald@wireshark.org>
16 * Copyright 1998 Gerald Combs
17 *
18 * SPDX-License-Identifier: GPL-2.0-or-later
19 */
20
21 #include "config.h"
22
23 #include <math.h>
24 #include <epan/packet.h>
25 #include <epan/conversation.h>
26 #include <epan/proto_data.h>
27 #include <epan/wmem_scopes.h>
28 #include <epan/expert.h>
29 #include <epan/prefs.h>
30 #include <epan/strutil.h>
31 #include <epan/to_str.h>
32 #include "packet-ieee802154.h"
33 #include "packet-mle.h"
34
35 #define MLE_32768_TO_NSEC_FACTOR ((double)30517.578125)
36
37 /* Forward declarations */
38 void proto_register_mle(void);
39 void proto_reg_handoff_mle(void);
40
41 static int proto_mle = -1;
42 static int proto_ieee802154 = -1; /* cache 802.15.4 protocol ID */
43
44 /* Registered fields for Auxiliary Security Header */
45 static int hf_mle_security_suite = -1;
46 static int hf_mle_mic = -1;
47
48 static int hf_mle_command = -1;
49 static int hf_mle_tlv = -1;
50 static int hf_mle_tlv_type = -1;
51 static int hf_mle_tlv_length = -1;
52 static int hf_mle_tlv_source_addr = -1;
53 static int hf_mle_tlv_mode_device_type = -1;
54 static int hf_mle_tlv_mode_idle_rx = -1;
55 static int hf_mle_tlv_mode_sec_data_req = -1;
56 static int hf_mle_tlv_mode_nwk_data = -1;
57 static int hf_mle_tlv_timeout = -1;
58 static int hf_mle_tlv_challenge = -1;
59 static int hf_mle_tlv_response = -1;
60 static int hf_mle_tlv_ll_frm_cntr = -1;
61 static int hf_mle_tlv_lqi_c = -1;
62 static int hf_mle_tlv_lqi_size = -1;
63 static int hf_mle_tlv_neighbor = -1;
64 static int hf_mle_tlv_neighbor_flagI = -1;
65 static int hf_mle_tlv_neighbor_flagO = -1;
66 static int hf_mle_tlv_neighbor_flagP = -1;
67 static int hf_mle_tlv_neighbor_idr = -1;
68 static int hf_mle_tlv_neighbor_addr = -1;
69 static int hf_mle_tlv_network_param_id = -1;
70 static int hf_mle_tlv_network_delay = -1;
71 static int hf_mle_tlv_network_channel = -1;
72 static int hf_mle_tlv_network_pan_id = -1;
73 static int hf_mle_tlv_network_pmt_join = -1;
74 static int hf_mle_tlv_network_bcn_payload = -1;
75 static int hf_mle_tlv_network_unknown = -1;
76 static int hf_mle_tlv_mle_frm_cntr = -1;
77 static int hf_mle_tlv_unknown = -1;
78 static int hf_mle_tlv_route64_id_seq = -1;
79 static int hf_mle_tlv_route64_id_mask = -1;
80 static int hf_mle_tlv_route64_entry = -1;
81 static int hf_mle_tlv_route64_nbr_out = -1;
82 static int hf_mle_tlv_route64_nbr_in = -1;
83 static int hf_mle_tlv_route64_cost = -1;
84 #if 0
85 static int hf_mle_tlv_route64_unknown = -1;
86 #endif
87 static int hf_mle_tlv_addr16 = -1;
88 static int hf_mle_tlv_leader_data_partition_id = -1;
89 static int hf_mle_tlv_leader_data_weighting = -1;
90 static int hf_mle_tlv_leader_data_version = -1;
91 static int hf_mle_tlv_leader_data_stable_version = -1;
92 static int hf_mle_tlv_leader_data_router_id = -1;
93 #if 0
94 static int hf_mle_tlv_network_data = -1;
95 #endif
96 static int hf_mle_tlv_scan_mask_r = -1;
97 static int hf_mle_tlv_scan_mask_e = -1;
98 static int hf_mle_tlv_conn_flags = -1;
99 static int hf_mle_tlv_conn_flags_pp = -1;
100 static int hf_mle_tlv_conn_lq3 = -1;
101 static int hf_mle_tlv_conn_lq2 = -1;
102 static int hf_mle_tlv_conn_lq1 = -1;
103 static int hf_mle_tlv_conn_leader_cost = -1;
104 static int hf_mle_tlv_conn_id_seq = -1;
105 static int hf_mle_tlv_conn_active_rtrs = -1;
106 static int hf_mle_tlv_conn_sed_buf_size = -1;
107 static int hf_mle_tlv_conn_sed_dgram_cnt = -1;
108 static int hf_mle_tlv_link_margin = -1;
109 static int hf_mle_tlv_status = -1;
110 static int hf_mle_tlv_version = -1;
111 static int hf_mle_tlv_addr_reg_entry = -1;
112 static int hf_mle_tlv_addr_reg_iid_type = -1;
113 static int hf_mle_tlv_addr_reg_cid = -1;
114 static int hf_mle_tlv_addr_reg_iid = -1;
115 static int hf_mle_tlv_addr_reg_ipv6 = -1;
116 #if 0
117 static int hf_mle_tlv_hold_time = -1;
118 #endif
119 static int hf_mle_tlv_channel_page = -1; /* v1.1-draft-2 */
120 static int hf_mle_tlv_channel = -1; /* v1.1-draft-2 */
121 static int hf_mle_tlv_pan_id = -1; /* v1.1-draft-2 */
122 static int hf_mle_tlv_active_tstamp = -1; /* SPEC-472 */
123 static int hf_mle_tlv_pending_tstamp = -1; /* SPEC-472 */
124 #if 0
125 static int hf_mle_tlv_active_op_dataset = -1; /* SPEC-472 */
126 static int hf_mle_tlv_pending_op_dataset = -1; /* SPEC-472 */
127 #endif
128
129 static gint ett_mle = -1;
130 static gint ett_mle_tlv = -1;
131 static gint ett_mle_neighbor = -1;
132 static gint ett_mle_router = -1;
133 static gint ett_mle_addr_reg = -1;
134 static gint ett_mle_conn_flg = -1;
135 static gint ett_mle_thread_nwd = -1;
136 static gint ett_mle_auxiliary_security = -1;
137 static gint ett_mle_aux_sec_control = -1;
138 static gint ett_mle_aux_sec_key_id = -1;
139
140 static expert_field ei_mle_cbc_mac_failed = EI_INIT;
141 static expert_field ei_mle_packet_too_small = EI_INIT;
142 static expert_field ei_mle_no_key = EI_INIT;
143 static expert_field ei_mle_decrypt_failed = EI_INIT;
144 static expert_field ei_mle_mic_check_failed = EI_INIT;
145 static expert_field ei_mle_tlv_length_failed = EI_INIT;
146 static expert_field ei_mle_len_size_mismatch = EI_INIT;
147
148 static dissector_handle_t mle_handle;
149 static dissector_handle_t thread_nwd_handle;
150 static dissector_handle_t thread_mc_handle;
151
152 #define UDP_PORT_MLE_RANGE "19788" /* IANA registered */
153
154 /* boolean value set if the MIC must be ok before payload is dissected */
155 static gboolean mle_mic_ok = FALSE;
156
157 static wmem_tree_t* mle_key_hash_handlers;
158
159 static const value_string mle_sec_suite_names[] = {
160 { 0, "802.15.4 Security" },
161 { 255, "No Security" },
162 { 0, NULL }
163 };
164
165 static const value_string mle_status_tlv_enums[] = {
166 { 1, "Error" },
167 { 2, "Duplicate Address Detected" },
168 { 0, NULL }
169 };
170
171 static const value_string mle_conn_tlv_flags_pp_enums[] = {
172 { 1, "High" },
173 { 0, "Medium" },
174 { -1, "Low" },
175 { 0, NULL }
176 };
177
178 #define MLE_CMD_REQUEST 0
179 #define MLE_CMD_ACCEPT 1
180 #define MLE_CMD_ACCEPTREQ 2
181 #define MLE_CMD_REJECT 3
182 #define MLE_CMD_ADVERTISE 4
183 #define MLE_CMD_UPDATE 5
184 #define MLE_CMD_UPDATE_REQUEST 6
185 #define MLE_CMD_DATA_REQUEST 7
186 #define MLE_CMD_DATA_RESPONSE 8
187 #define MLE_CMD_PARENT_REQUEST 9
188 #define MLE_CMD_PARENT_RESPONSE 10
189 #define MLE_CMD_CHILD_ID_REQUEST 11
190 #define MLE_CMD_CHILD_ID_RESPONSE 12
191 #define MLE_CMD_CHILD_UPDATE_REQUEST 13
192 #define MLE_CMD_CHILD_UPDATE_RESPONSE 14
193 #define MLE_CMD_ANNOUNCE 15
194 #define MLE_CMD_DISCOVERY_REQUEST 16
195 #define MLE_CMD_DISCOVERY_RESPONSE 17
196
197 static const value_string mle_command_vals[] = {
198 { MLE_CMD_REQUEST, "Link Request" },
199 { MLE_CMD_ACCEPT, "Link Accept" },
200 { MLE_CMD_ACCEPTREQ, "Link Accept and Request" },
201 { MLE_CMD_REJECT, "Link Reject" },
202 { MLE_CMD_ADVERTISE, "Advertisement" },
203 { MLE_CMD_UPDATE, "Update" },
204 { MLE_CMD_UPDATE_REQUEST, "Update Request" },
205 { MLE_CMD_DATA_REQUEST, "Data Request" },
206 { MLE_CMD_DATA_RESPONSE, "Data Response" },
207 { MLE_CMD_PARENT_REQUEST, "Parent Request" },
208 { MLE_CMD_PARENT_RESPONSE, "Parent Response" },
209 { MLE_CMD_CHILD_ID_REQUEST, "Child ID Request" },
210 { MLE_CMD_CHILD_ID_RESPONSE, "Child ID Response" },
211 { MLE_CMD_CHILD_UPDATE_REQUEST, "Child Update Request" },
212 { MLE_CMD_CHILD_UPDATE_RESPONSE, "Child Update Response" },
213 { MLE_CMD_ANNOUNCE, "Announce" },
214 { MLE_CMD_DISCOVERY_REQUEST, "Discovery Request" },
215 { MLE_CMD_DISCOVERY_RESPONSE, "Discovery Response" },
216 { 0, NULL}
217 };
218
219 #define MLE_TLV_SOURCE_ADDRESS 0
220 #define MLE_TLV_MODE 1 /* Modified in Ch04_Mesh Link Establishment */
221 #define MLE_TLV_TIMEOUT 2
222 #define MLE_TLV_CHALLENGE 3
223 #define MLE_TLV_RESPONSE 4
224 #define MLE_TLV_LINK_LAYER_FRAME_COUNTER 5
225 #define MLE_TLV_LINK_QUALITY 6
226 #define MLE_TLV_NETWORK_PARAMETER 7
227 #define MLE_TLV_MLE_FRAME_COUNTER 8
228 #define MLE_TLV_ROUTE64 9 /* Defined in Ch05_Network Layer v1.1-rc1 */
229 #define MLE_TLV_ADDRESS16 10 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
230 #define MLE_TLV_LEADER_DATA 11 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
231 #define MLE_TLV_NETWORK_DATA 12 /* Defined in Ch05_Network Layer v1.1-rc1 */
232 #define MLE_TLV_TLV_REQUEST 13 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
233 #define MLE_TLV_SCAN_MASK 14 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
234 #define MLE_TLV_CONNECTIVITY 15 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
235 #define MLE_TLV_LINK_MARGIN 16 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
236 #define MLE_TLV_STATUS 17 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
237 #define MLE_TLV_VERSION 18 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
238 #define MLE_TLV_ADDRESS_REGISTRATION 19 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
239 #define MLE_TLV_CHANNEL 20 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
240 #define MLE_TLV_PAN_ID 21 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
241 #define MLE_TLV_ACTIVE_TSTAMP 22 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
242 #define MLE_TLV_PENDING_TSTAMP 23 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
243 #define MLE_TLV_ACTIVE_OP_DATASET 24 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
244 #define MLE_TLV_PENDING_OP_DATASET 25 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
245 #define MLE_TLV_THREAD_DISCOVERY 26 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
246
247 static const value_string mle_tlv_vals[] = {
248 { MLE_TLV_SOURCE_ADDRESS, "Source Address" },
249 { MLE_TLV_MODE, "Mode" },
250 { MLE_TLV_TIMEOUT, "Timeout" },
251 { MLE_TLV_CHALLENGE, "Challenge" },
252 { MLE_TLV_RESPONSE, "Response" },
253 { MLE_TLV_LINK_LAYER_FRAME_COUNTER, "Link Layer Frame Counter"},
254 { MLE_TLV_LINK_QUALITY, "Link Quality"},
255 { MLE_TLV_NETWORK_PARAMETER, "Network Parameter"},
256 { MLE_TLV_MLE_FRAME_COUNTER, "MLE Frame Counter"},
257 { MLE_TLV_ROUTE64, "Route64"},
258 { MLE_TLV_ADDRESS16, "Address16"},
259 { MLE_TLV_LEADER_DATA, "Leader Data"},
260 { MLE_TLV_NETWORK_DATA, "Network Data"},
261 { MLE_TLV_TLV_REQUEST, "TLV Request"},
262 { MLE_TLV_SCAN_MASK, "Scan Mask"},
263 { MLE_TLV_CONNECTIVITY, "Connectivity"},
264 { MLE_TLV_LINK_MARGIN, "Link Margin"},
265 { MLE_TLV_STATUS, "Status"},
266 { MLE_TLV_VERSION, "Version"},
267 { MLE_TLV_ADDRESS_REGISTRATION, "Address Registration"},
268 { MLE_TLV_CHANNEL, "Channel"},
269 { MLE_TLV_PAN_ID, "PAN ID"},
270 { MLE_TLV_ACTIVE_TSTAMP, "Active Timestamp"},
271 { MLE_TLV_PENDING_TSTAMP, "Pending Timestamp"},
272 { MLE_TLV_ACTIVE_OP_DATASET, "Active Operational Dataset"},
273 { MLE_TLV_PENDING_OP_DATASET, "Pending Operational Dataset"},
274 { MLE_TLV_THREAD_DISCOVERY, "Thread Discovery"},
275 { 0, NULL}
276 };
277
278 #define LQI_FLAGS_C 0x80
279 #define LQI_FLAGS_SIZE 0x0F
280
281 #define NEIGHBOR_FLAG_I 0x80
282 #define NEIGHBOR_FLAG_O 0x40
283 #define NEIGHBOR_FLAG_P 0x20
284
285 #define NETWORK_PARAM_ID_CHANNEL 0
286 #define NETWORK_PARAM_ID_PAN_ID 1
287 #define NETWORK_PARAM_ID_PERMIT_JOIN 2
288 #define NETWORK_PARAM_ID_BCN_PAYLOAD 3
289
290 static const value_string mle_tlv_nwk_param_vals[] = {
291 { NETWORK_PARAM_ID_CHANNEL, "Channel" },
292 { NETWORK_PARAM_ID_PAN_ID, "PAN ID" },
293 { NETWORK_PARAM_ID_PERMIT_JOIN, "Permit Join" },
294 { NETWORK_PARAM_ID_BCN_PAYLOAD, "Beacon Payload" },
295 { 0, NULL}
296 };
297
298 static const true_false_string mle_tlv_mode_device_type = {
299 "FFD",
300 "RFD"
301 };
302 static const true_false_string mle_tlv_mode_nwk_data = {
303 "Full",
304 "Stable"
305 };
306 static const true_false_string mle_tlv_addr_reg_iid_type = {
307 "Compressed",
308 "Full"
309 };
310
311 #define ROUTE_TBL_OUT_MASK 0xC0
312 #define ROUTE_TBL_IN_MASK 0x30
313 #define ROUTE_TBL_COST_MASK 0x0F
314
315 #define SCAN_MASK_R_MASK 0x80
316 #define SCAN_MASK_D_MASK 0x40
317
318 #define CONN_MASK_FLAGS_PP_MASK 0xC0
319
320 #define ADDR_REG_MASK_IID_TYPE_MASK 0x80
321 #define ADDR_REG_MASK_CID_MASK 0x0F
322
323 #define MLE_CMD_CINFO_SEC_DATA_REQ 0x04
324 #define MLE_CMD_CINFO_NWK_DATA 0x01
325
326 /*FUNCTION:------------------------------------------------------
327 * NAME
328 * dissect_mle_decrypt
329 * DESCRIPTION
330 * MLE dissector.
331 * PARAMETERS
332 * tvbuff_t *tvb - IEEE 802.15.4 packet.
333 * packet_info * pinfo - Packet info structure.
334 * guint offset - Offset where the ciphertext 'c' starts.
335 * ieee802154_packet *packet - IEEE 802.15.4 packet information.
336 * ws_decrypt_status *status - status of decryption returned through here on failure.
337 * RETURNS
338 * tvbuff_t * - Decrypted payload.
339 *---------------------------------------------------------------
340 */
341 static tvbuff_t *
dissect_mle_decrypt(tvbuff_t * tvb,guint offset,packet_info * pinfo,ieee802154_packet * packet,ieee802154_decrypt_info_t * decrypt_info)342 dissect_mle_decrypt(tvbuff_t * tvb,
343 guint offset,
344 packet_info * pinfo,
345 ieee802154_packet * packet,
346 ieee802154_decrypt_info_t* decrypt_info)
347 {
348 tvbuff_t * ptext_tvb;
349 gboolean have_mic = FALSE;
350 guint64 srcAddr;
351 unsigned char tmp[16];
352 guint M;
353 gint captured_len;
354 gint reported_len;
355
356 *decrypt_info->rx_mic_length = 0;
357 memset(decrypt_info->rx_mic, 0, 16);
358
359 /* Get the captured and on-the-wire length of the payload. */
360 if (packet->security_level > 0) {
361 M = IEEE802154_MIC_LENGTH(packet->security_level);
362 }
363 else {
364 M = 0;
365 }
366
367 reported_len = tvb_reported_length_remaining(tvb, offset) - M;
368 if (reported_len < 0) {
369 *decrypt_info->status = DECRYPT_PACKET_TOO_SMALL;
370 return NULL;
371 }
372 /* Check if the payload is truncated. */
373 if (tvb_bytes_exist(tvb, offset, reported_len)) {
374 captured_len = reported_len;
375 }
376 else {
377 captured_len = tvb_captured_length_remaining(tvb, offset);
378 }
379
380 if (packet->security_level > 0) {
381 /* Check if the MIC is present in the captured data. */
382 have_mic = tvb_bytes_exist(tvb, offset + reported_len, M);
383 if (have_mic) {
384 tvb_memcpy(tvb, decrypt_info->rx_mic, offset + reported_len, M);
385 }
386 }
387
388 /*=====================================================
389 * Key Lookup - Need to find the appropriate key.
390 *=====================================================
391 */
392 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
393 /* The source EUI-64 is included in the headers. */
394 srcAddr = packet->src64; /* GUINT64_SWAP_LE_BE(packet->src64); */
395 }
396 else {
397 /* Lookup failed. */
398 *decrypt_info->status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
399 return NULL;
400 }
401
402 /*=====================================================
403 * CCM* - CTR mode payload encryption
404 *=====================================================
405 */
406 /* Create the CCM* initial block for decryption (Adata=0, M=0, counter=0). */
407 ccm_init_block(tmp, FALSE, 0, srcAddr, packet->frame_counter, packet->security_level, 0, NULL);
408
409 /* Decrypt the ciphertext, and place the plaintext in a new tvb. */
410 if (IEEE802154_IS_ENCRYPTED(packet->security_level) && captured_len) {
411 gchar *text;
412
413 /*
414 * Make a copy of the ciphertext in heap memory.
415 *
416 * We will decrypt the message in-place and then use the buffer as the
417 * real data for the new tvb.
418 */
419 text = (gchar *)tvb_memdup(pinfo->pool, tvb, offset, captured_len);
420
421 /* Perform CTR-mode transformation. Try both the likely key and the alternate key */
422 if (!ccm_ctr_encrypt(decrypt_info->key, tmp, decrypt_info->rx_mic, text, captured_len)) {
423 *decrypt_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
424 return NULL;
425 }
426
427 /* Create a tvbuff for the plaintext. */
428 ptext_tvb = tvb_new_real_data((const guint8 *)text, captured_len, reported_len);
429 tvb_set_child_real_data_tvbuff(tvb, ptext_tvb);
430 add_new_data_source(pinfo, ptext_tvb, "Decrypted MLE payload");
431 *decrypt_info->status = DECRYPT_PACKET_SUCCEEDED;
432 }
433 /* There is no ciphertext. Wrap the plaintext in a new tvb. */
434 else {
435 /* Decrypt the MIC (if present). */
436 if (have_mic) {
437 if (!ccm_ctr_encrypt(decrypt_info->key, tmp, decrypt_info->rx_mic, NULL, 0)) {
438 *decrypt_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
439 return NULL;
440 }
441 }
442
443 /* Create a tvbuff for the plaintext. This might result in a zero-length tvbuff. */
444 ptext_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
445 *decrypt_info->status = DECRYPT_PACKET_SUCCEEDED;
446 }
447
448 /*=====================================================
449 * CCM* - CBC-mode message authentication
450 *=====================================================
451 */
452 /* We can only verify the message if the MIC wasn't truncated. */
453 if (have_mic) {
454 unsigned char dec_mic[16];
455 guint l_m = captured_len;
456 guint l_a;
457 guint8 d_a[256];
458
459 DISSECTOR_ASSERT(pinfo->src.len == 16);
460 DISSECTOR_ASSERT(pinfo->dst.len == 16);
461 memcpy(d_a, pinfo->src.data, pinfo->src.len);
462 memcpy(d_a+16, pinfo->dst.data, pinfo->dst.len);
463
464 tvb_memcpy(tvb, d_a+32, decrypt_info->aux_offset, decrypt_info->aux_length);
465 l_a = 32 + decrypt_info->aux_length;
466
467 /* Adjust the lengths of the plantext and additional data if unencrypted. */
468 if (!IEEE802154_IS_ENCRYPTED(packet->security_level)) {
469 l_a += l_m;
470 l_m = 0;
471 }
472
473 /* Create the CCM* initial block for authentication (Adata!=0, M!=0, counter=l(m)). */
474 ccm_init_block(tmp, TRUE, M, srcAddr, packet->frame_counter, packet->security_level, l_m, NULL);
475
476 /* Compute CBC-MAC authentication tag. */
477 /*
478 * And yes, despite the warning in tvbuff.h, I think tvb_get_ptr is the
479 * right function here since either A) the payload wasn't encrypted, in
480 * which case l_m is zero, or B) the payload was encrypted, and the tvb
481 * already points to contiguous memory, since we just allocated it in
482 * decryption phase.
483 */
484 if (!ccm_cbc_mac(decrypt_info->key, tmp, d_a, l_a, tvb_get_ptr(ptext_tvb, 0, l_m), l_m, dec_mic)) {
485 *decrypt_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
486 }
487 /* Compare the received MIC with the one we generated. */
488 else if (memcmp(decrypt_info->rx_mic, dec_mic, M) != 0) {
489 *decrypt_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
490 }
491 }
492
493 *decrypt_info->rx_mic_length = M;
494
495 /* Done! */
496 return ptext_tvb;
497 } /* dissect_mle_decrypt */
498
register_mle_key_hash_handler(guint hash_identifier,ieee802154_set_key_func key_func)499 void register_mle_key_hash_handler(guint hash_identifier, ieee802154_set_key_func key_func)
500 {
501 /* Ensure no duplication */
502 DISSECTOR_ASSERT(wmem_tree_lookup32(mle_key_hash_handlers, hash_identifier) == NULL);
503
504 wmem_tree_insert32(mle_key_hash_handlers, hash_identifier, (void*)key_func);
505 }
506
507 /* Set MLE key function. */
ieee802154_set_mle_key(ieee802154_packet * packet,unsigned char * key,unsigned char * alt_key,ieee802154_key_t * uat_key)508 static guint ieee802154_set_mle_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t *uat_key)
509 {
510 ieee802154_set_key_func func = (ieee802154_set_key_func)wmem_tree_lookup32(mle_key_hash_handlers, uat_key->hash_type);
511
512 if (func != NULL)
513 return func(packet, key, alt_key, uat_key);
514
515 /* Right now, KEY_HASH_NONE and KEY_HASH_ZIP are not registered because they
516 work with this "default" behavior */
517 if (packet->key_index == uat_key->key_index)
518 {
519 memcpy(key, uat_key->key, IEEE802154_CIPHER_SIZE);
520 return 1;
521 }
522
523 return 0;
524 }
525
526 static int
dissect_mle(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)527 dissect_mle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
528 {
529 tvbuff_t *volatile payload_tvb = NULL;
530 proto_tree *volatile mle_tree = NULL;
531 proto_item *volatile proto_root = NULL;
532
533 guint offset = 0;
534 guint aux_header_offset = 0;
535 ieee802154_decrypt_status status;
536
537 proto_item *ti;
538 proto_item *mic_item = NULL;
539 proto_tree *header_tree = NULL;
540 guint8 security_suite;
541 guint aux_length = 0;
542 ieee802154_packet *packet;
543 ieee802154_packet *original_packet;
544 ieee802154_decrypt_info_t decrypt_info;
545 ieee802154_hints_t *ieee_hints;
546 gboolean mic_ok=TRUE;
547
548 unsigned char rx_mic[16];
549 unsigned int rx_mic_len = 0;
550
551 guint8 cmd;
552 guint8 tlv_type, tlv_len;
553 proto_tree *tlv_tree;
554
555 ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
556 if (ieee_hints == NULL) {
557 /* For now, MLE only supported with IEEE802.15.4 as an underlying layer */
558 return 0;
559 }
560 original_packet = (ieee802154_packet *)ieee_hints->packet;
561
562 packet = wmem_new0(pinfo->pool, ieee802154_packet);
563
564 /* Copy IEEE 802.15.4 Source Address */
565 packet->src_addr_mode = original_packet->src_addr_mode;
566 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
567 packet->src64 = original_packet->src64;
568 } else {
569 packet->src16 = original_packet->src16;
570 }
571
572 /* Copy IEEE 802.15.4 Source PAN ID */
573 packet->src_pan = original_packet->src_pan;
574
575 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MLE");
576 col_clear(pinfo->cinfo, COL_INFO);
577
578 /* Create the protocol tree. */
579 proto_root = proto_tree_add_item(tree, proto_mle, tvb, 0, tvb_reported_length(tvb), ENC_NA);
580 mle_tree = proto_item_add_subtree(proto_root, ett_mle);
581
582 /* Parse the security suite field. */
583 /* Security Suite Field */
584 security_suite = tvb_get_guint8(tvb, offset);
585 proto_tree_add_item(mle_tree, hf_mle_security_suite, tvb, offset, 1, ENC_NA);
586 offset++;
587
588 aux_header_offset = offset;
589
590 /* Security material present if security suite = 0 */
591 if (security_suite == 0) {
592 dissect_ieee802154_aux_sec_header_and_key(tvb, pinfo, mle_tree, packet, &offset);
593 aux_length = offset-aux_header_offset;
594 } else {
595 packet->security_level = SECURITY_LEVEL_NONE;
596 }
597
598 decrypt_info.key_number = 0;
599
600 /* Add additional fields for security level > SECURITY_LEVEL_NONE */
601 if (packet->security_level > SECURITY_LEVEL_NONE) {
602
603 /* Pass to decryption process */
604 decrypt_info.rx_mic = rx_mic;
605 decrypt_info.rx_mic_length = &rx_mic_len;
606 decrypt_info.aux_offset = aux_header_offset;
607 decrypt_info.aux_length = aux_length;
608 decrypt_info.status = &status;
609 decrypt_info.key = NULL; /* payload function will fill that in */
610
611 payload_tvb = decrypt_ieee802154_payload(tvb, offset, pinfo, header_tree, packet, &decrypt_info,
612 ieee802154_set_mle_key, dissect_mle_decrypt);
613 if (status == DECRYPT_PACKET_MIC_CHECK_FAILED)
614 expert_add_info(pinfo, proto_root, &ei_mle_cbc_mac_failed);
615
616 /* MIC */
617 if (rx_mic_len) {
618 mic_item = proto_tree_add_bytes(header_tree, hf_mle_mic, tvb, 0, rx_mic_len, rx_mic);
619 proto_item_set_generated(mic_item);
620 }
621 } else {
622 status = DECRYPT_NOT_ENCRYPTED;
623 }
624
625 /* Get the unencrypted data if decryption failed. */
626 if (!payload_tvb) {
627 /* Deal with possible truncation and the FCS field at the end. */
628 gint reported_len = tvb_reported_length_remaining(tvb, offset);
629 gint captured_len = tvb_captured_length_remaining(tvb, offset);
630 if (reported_len < captured_len) captured_len = reported_len;
631 payload_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
632 }
633
634 /* Display the reason for failure, and abort if the error was fatal. */
635 switch (status) {
636 case DECRYPT_PACKET_SUCCEEDED:
637 /* No problem. */
638 proto_item_append_text(mic_item, " [correct (key no. %d)]", decrypt_info.key_number);
639 break;
640
641 case DECRYPT_PACKET_TOO_SMALL:
642 expert_add_info(pinfo, proto_root, &ei_mle_packet_too_small);
643 call_data_dissector(payload_tvb, pinfo, tree);
644 return tvb_captured_length(tvb);
645
646 case DECRYPT_PACKET_NO_KEY:
647 expert_add_info(pinfo, proto_root, &ei_mle_no_key);
648 call_data_dissector(payload_tvb, pinfo, tree);
649 return tvb_captured_length(tvb);
650
651 case DECRYPT_PACKET_DECRYPT_FAILED:
652 expert_add_info(pinfo, proto_root, &ei_mle_decrypt_failed);
653 call_data_dissector(payload_tvb, pinfo, tree);
654 return tvb_captured_length(tvb);
655
656 case DECRYPT_PACKET_MIC_CHECK_FAILED:
657 expert_add_info(pinfo, proto_root, &ei_mle_mic_check_failed);
658 proto_item_append_text(mic_item, " [incorrect]");
659 /*
660 * Abort only if the payload was encrypted, in which case we
661 * probably didn't decrypt the packet right (eg: wrong key).
662 */
663 if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
664 mic_ok = FALSE;
665 }
666 break;
667 case DECRYPT_NOT_ENCRYPTED:
668 default:
669 break;
670 }
671 /* This can cause a lot of problems so remove it by default */
672 if (!mic_ok && mle_mic_ok) {
673 call_data_dissector(payload_tvb, pinfo, tree);
674 col_add_fstr(pinfo->cinfo, COL_INFO, "MIC Failed");
675 return tvb_captured_length(tvb);
676 }
677
678 /***** NEW CODE HERE ****/
679 /* If we're good, carry on and display the MLE payload */
680 offset = 0;
681
682 /* MLE Command */
683 proto_tree_add_item(mle_tree, hf_mle_command, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
684
685 cmd = tvb_get_guint8(payload_tvb, offset);
686 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(cmd, mle_command_vals, "Unknown (%x)"));
687
688 offset++;
689
690 /* MLE TLVs */
691 while (tvb_offset_exists(payload_tvb, offset)) {
692
693 /* Get the length ahead of time to pass to next function so we can highlight
694 proper amount of bytes */
695 tlv_len = tvb_get_guint8(payload_tvb, offset+1);
696
697 ti = proto_tree_add_item(mle_tree, hf_mle_tlv, payload_tvb, offset, tlv_len+2, ENC_NA);
698 tlv_tree = proto_item_add_subtree(ti, ett_mle_tlv);
699
700 /* Type */
701 proto_tree_add_item(tlv_tree, hf_mle_tlv_type, payload_tvb, offset, 1, ENC_NA);
702 tlv_type = tvb_get_guint8(payload_tvb, offset);
703 offset++;
704
705 /* Add value name to value root label */
706 proto_item_append_text(ti, " (%s", val_to_str(tlv_type, mle_tlv_vals, "Unknown (%d)"));
707
708 /* Length */
709 proto_tree_add_item(tlv_tree, hf_mle_tlv_length, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
710 offset++;
711
712 switch(tlv_type){
713 case MLE_TLV_SOURCE_ADDRESS:
714 {
715 gboolean haveShortTLV = FALSE;
716 guint16 shortAddr = 0;
717
718 if (!((tlv_len == 2) || (tlv_len == 8))) {
719 /* TLV Length must be 2 or 8 */
720 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
721 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
722 offset += tlv_len;
723 } else {
724 if (tlv_len == 2) {
725 haveShortTLV = TRUE;
726 shortAddr = tvb_get_ntohs(payload_tvb, offset);
727 }
728
729 proto_tree_add_item(tlv_tree, hf_mle_tlv_source_addr, payload_tvb, offset, tlv_len, ENC_NA);
730 proto_item_append_text(ti, " = ");
731 while (tlv_len) {
732 guint8 addr;
733 addr = tvb_get_guint8(payload_tvb, offset);
734 proto_item_append_text(ti, "%02x", addr);
735 if (--tlv_len) {
736 proto_item_append_text(ti, ":");
737 }
738 offset++;
739 }
740 if ((original_packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && haveShortTLV) {
741 /* Source TLV: use this to update src/long mapping */
742 ieee802154_addr_update(&ieee802154_map, shortAddr, original_packet->src_pan, original_packet->src64, pinfo->current_proto, pinfo->fd->num);
743 }
744 }
745 proto_item_append_text(ti, ")");
746 }
747 break;
748
749 case MLE_TLV_MODE:
750 if (tlv_len == 1) {
751 guint8 capability;
752
753 capability = tvb_get_guint8(payload_tvb, offset);
754 proto_item_append_text(ti, " = %02x)", capability);
755 /* Get and display capability info. (blatantly plagiarised from packet-ieee802154.c */
756 proto_tree_add_item(tlv_tree, hf_mle_tlv_mode_nwk_data, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
757 proto_tree_add_item(tlv_tree, hf_mle_tlv_mode_device_type, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
758 proto_tree_add_item(tlv_tree, hf_mle_tlv_mode_sec_data_req, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
759 proto_tree_add_item(tlv_tree, hf_mle_tlv_mode_idle_rx, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
760 }
761 else {
762 /* TLV Length must be 1 */
763 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
764 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
765 }
766 offset += tlv_len;
767 break;
768
769 case MLE_TLV_TIMEOUT:
770 if (tlv_len != 4) {
771 /* TLV Length must be 4 */
772 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
773 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
774 } else {
775 guint32 to_data = 0;
776 proto_tree_add_item_ret_uint(tlv_tree, hf_mle_tlv_timeout, payload_tvb, offset, 4, ENC_BIG_ENDIAN, &to_data);
777 proto_item_append_text(ti, " = %d", (guint16)to_data);
778 }
779 proto_item_append_text(ti, ")");
780 offset += tlv_len;
781 break;
782
783 case MLE_TLV_CHALLENGE:
784 proto_tree_add_item(tlv_tree, hf_mle_tlv_challenge, payload_tvb, offset, tlv_len, ENC_NA);
785 proto_item_append_text(ti, " = %s)", tvb_bytes_to_str(pinfo->pool, payload_tvb, offset, tlv_len));
786 offset += tlv_len;
787 break;
788
789 case MLE_TLV_RESPONSE:
790 proto_tree_add_item(tlv_tree, hf_mle_tlv_response, payload_tvb, offset, tlv_len, ENC_NA);
791 proto_item_append_text(ti, " = %s)", tvb_bytes_to_str(pinfo->pool, payload_tvb, offset, tlv_len));
792 offset += tlv_len;
793 break;
794
795 case MLE_TLV_LINK_LAYER_FRAME_COUNTER:
796 case MLE_TLV_MLE_FRAME_COUNTER:
797 if (tlv_len != 4) {
798 /* TLV Length must be 4 */
799 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
800 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
801 } else {
802 guint32 cntr;
803
804 if (tlv_type == MLE_TLV_LINK_LAYER_FRAME_COUNTER) {
805 proto_tree_add_item_ret_uint(tlv_tree, hf_mle_tlv_ll_frm_cntr, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN, &cntr);
806 } else {
807 proto_tree_add_item_ret_uint(tlv_tree, hf_mle_tlv_mle_frm_cntr, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN, &cntr);
808 }
809 proto_item_append_text(ti, " = %u", cntr);
810 }
811 proto_item_append_text(ti, ")");
812 offset += tlv_len;
813 break;
814
815 case MLE_TLV_LINK_QUALITY:
816 {
817 guint numNeighbors;
818 guint8 size = tvb_get_guint8(payload_tvb, offset) & LQI_FLAGS_SIZE;
819 proto_tree *neig_tree;
820 proto_tree_add_item(tlv_tree, hf_mle_tlv_lqi_c, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
821 proto_tree_add_item(tlv_tree, hf_mle_tlv_lqi_size, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
822 offset++;
823
824 if ((tlv_len - 1) % (size + 3)) {
825 expert_add_info(pinfo, proto_root, &ei_mle_len_size_mismatch);
826 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
827 numNeighbors = 0;
828 } else {
829 numNeighbors = (tlv_len - 1) / (size + 3);
830 }
831
832 if (numNeighbors == 0) {
833 proto_item_append_text(ti, ")");
834 } else if (numNeighbors == 1) {
835 proto_item_append_text(ti, ": 1 Neighbor)");
836 } else {
837 proto_item_append_text(ti, ": %d Neighbors)", numNeighbors);
838 }
839
840 /* Add subtrees */
841
842 //Size is off by 1
843 size++;
844
845 while (numNeighbors) {
846 ti = proto_tree_add_item(tlv_tree, hf_mle_tlv_neighbor, payload_tvb, offset, size+2, ENC_NA);
847 neig_tree = proto_item_add_subtree(ti, ett_mle_neighbor);
848
849 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_flagI, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
850 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_flagO, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
851 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_flagP, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
852 offset++;
853
854 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_idr, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
855 offset++;
856
857 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_addr, payload_tvb, offset,size, ENC_NA);
858 offset += size;
859
860 numNeighbors--;
861 }
862 }
863 break;
864
865 case MLE_TLV_NETWORK_PARAMETER:
866 {
867 guint8 param_id = tvb_get_guint8(payload_tvb, offset);
868
869 proto_item_append_text(ti, " = %s)", val_to_str(param_id, mle_tlv_nwk_param_vals, "Unknown (%d)"));
870
871 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_param_id, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
872 offset++;
873 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_delay, payload_tvb, offset, 4, ENC_BIG_ENDIAN);
874 offset += 4;
875
876 switch (param_id) {
877 case NETWORK_PARAM_ID_CHANNEL:
878 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_channel, payload_tvb, offset, 2, ENC_BIG_ENDIAN);
879 offset += 2;
880 break;
881 case NETWORK_PARAM_ID_PAN_ID:
882 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_pan_id, payload_tvb, offset, 2, ENC_BIG_ENDIAN);
883 offset += 2;
884 break;
885 case NETWORK_PARAM_ID_PERMIT_JOIN:
886 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_pmt_join, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
887 offset++;
888 break;
889 case NETWORK_PARAM_ID_BCN_PAYLOAD:
890 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_bcn_payload, payload_tvb, offset, tlv_len-5, ENC_NA);
891 offset += tlv_len-5;
892 break;
893 default:
894 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_unknown, payload_tvb, offset, tlv_len-5, ENC_NA);
895 offset += tlv_len-5;
896 break;
897 }
898 }
899 break;
900
901 case MLE_TLV_ROUTE64:
902 {
903 proto_tree *rtr_tree;
904 guint i, j;
905 guint8 count;
906 guint64 id_mask, test_mask;
907
908 proto_item_append_text(ti, ")");
909 proto_tree_add_item(tlv_tree, hf_mle_tlv_route64_id_seq, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
910 offset++;
911
912 /* Count number of table entries */
913 count = 0;
914 for (i = 0; i < 8; i++) { /* TODO magic - number of routers/8 */
915 guint8 id_mask_octet = tvb_get_guint8(payload_tvb, offset + i);
916 for (j = 0; j < 8; j++) {
917 if (id_mask_octet & (1 << j)) {
918 count++;
919 }
920 }
921 }
922
923 /*
924 * | | | | | | | | | | |1|1|1|1|1|1|...|6|
925 * |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|...|3|
926 * ---------------------------------------
927 * |1|0|1|1|1|0|0|0|1|1|0|0|0|1|0|1|...
928 *
929 * is sent as 0xb8, 0xc5
930 * and represents table entry for routers 0, 2, 3, 4, 8, 9, 13, 15...
931 */
932 /* Get the ID mask as a 64-bit number (BE) */
933 id_mask = tvb_get_ntoh64(payload_tvb, offset);
934
935 /* Just show the string of octets - best representation for a bit mask */
936 proto_tree_add_item(tlv_tree, hf_mle_tlv_route64_id_mask, payload_tvb, offset, 8, ENC_NA);
937 offset += 8;
938
939 if (count != (tlv_len - 9))
940 {
941 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
942 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
943 offset += (tlv_len - 9);
944 } else {
945 /* Add subtrees */
946 for (i = 0; i < count; i++) {
947 /* Find first bit set */
948 for (j = 0, test_mask = (G_GUINT64_CONSTANT(1) << 63); test_mask != 1; test_mask >>= 1, j++) {
949 if (test_mask & id_mask) {
950 id_mask &= ~test_mask;
951 break;
952 }
953 }
954 ti = proto_tree_add_item(tlv_tree, hf_mle_tlv_route64_entry, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
955 proto_item_append_text(ti, " (%d)", j);
956 rtr_tree = proto_item_add_subtree(ti, ett_mle_router);
957
958 proto_tree_add_item(rtr_tree, hf_mle_tlv_route64_nbr_out, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
959 proto_tree_add_item(rtr_tree, hf_mle_tlv_route64_nbr_in, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
960 proto_tree_add_item(rtr_tree, hf_mle_tlv_route64_cost, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
961 offset++;
962 }
963 }
964 }
965 break;
966
967 case MLE_TLV_ADDRESS16:
968 if (tlv_len != 2) {
969 /* TLV Length must be 2 */
970 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
971 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
972 } else {
973 guint16 addr16 = tvb_get_ntohs(payload_tvb, offset);
974 proto_item_append_text(ti, " = ");
975 {
976 guint8 a16_len = 2; /* Fix it at 2 */
977 guint stroffset = offset;
978
979 while (a16_len) {
980 guint8 a16_data;
981 a16_data = tvb_get_guint8(payload_tvb, stroffset);
982 proto_item_append_text(ti, "%02x", a16_data);
983 if (--a16_len) {
984 proto_item_append_text(ti, ":");
985 }
986 stroffset++;
987 }
988 }
989 proto_tree_add_item(tlv_tree, hf_mle_tlv_addr16, payload_tvb, offset, 2, ENC_NA);
990 if (original_packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
991 /* Allocated Address16 TLV: use this to update dst/long mapping */
992 ieee802154_addr_update(&ieee802154_map, addr16, original_packet->dst_pan, original_packet->dst64, pinfo->current_proto, pinfo->fd->num);
993 }
994 }
995 proto_item_append_text(ti, ")");
996 offset += tlv_len;
997 break;
998
999 case MLE_TLV_LEADER_DATA:
1000 proto_item_append_text(ti, ")");
1001 if (tlv_len != 8) {
1002 /* TLV Length must be 8 */
1003 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1004 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1005 offset += tlv_len;
1006 } else {
1007 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_partition_id, payload_tvb, offset, 4, ENC_BIG_ENDIAN);
1008 offset += 4;
1009 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_weighting, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1010 offset++;
1011 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_version, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1012 offset++;
1013 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_stable_version, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1014 offset++;
1015 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_router_id, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1016 offset++;
1017 }
1018 break;
1019
1020 case MLE_TLV_NETWORK_DATA:
1021 {
1022 tvbuff_t *sub_tvb;
1023 proto_item_append_text(ti, ")");
1024 if (tlv_len > 0) {
1025 sub_tvb = tvb_new_subset_length(payload_tvb, offset, tlv_len);
1026 call_dissector(thread_nwd_handle, sub_tvb, pinfo, tlv_tree);
1027 }
1028 offset += tlv_len;
1029 }
1030 break;
1031
1032 case MLE_TLV_ACTIVE_OP_DATASET:
1033 case MLE_TLV_PENDING_OP_DATASET:
1034 case MLE_TLV_THREAD_DISCOVERY:
1035 {
1036 tvbuff_t *sub_tvb;
1037 proto_item_append_text(ti, ")");
1038 if (tlv_len > 0) {
1039 sub_tvb = tvb_new_subset_length(payload_tvb, offset, tlv_len);
1040 call_dissector(thread_mc_handle, sub_tvb, pinfo, tlv_tree);
1041 }
1042 offset += tlv_len;
1043 }
1044 break;
1045
1046 case MLE_TLV_TLV_REQUEST:
1047 proto_item_append_text(ti, ")");
1048 while (tlv_len) {
1049 proto_tree_add_item(tlv_tree, hf_mle_tlv_type, payload_tvb, offset, 1, ENC_NA);
1050 offset++;
1051 tlv_len--;
1052 }
1053 break;
1054
1055 case MLE_TLV_SCAN_MASK:
1056 if (tlv_len != 1) {
1057 /* TLV Length must be 1 */
1058 proto_item_append_text(ti, ")");
1059 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1060 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1061 } else {
1062 guint8 mask;
1063
1064 mask = tvb_get_guint8(payload_tvb, offset);
1065 proto_item_append_text(ti, " = %02x)", mask);
1066 proto_tree_add_item(tlv_tree, hf_mle_tlv_scan_mask_r, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1067 proto_tree_add_item(tlv_tree, hf_mle_tlv_scan_mask_e, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1068 }
1069 offset += tlv_len;
1070 break;
1071
1072 case MLE_TLV_CONNECTIVITY:
1073 proto_item_append_text(ti, ")");
1074 if ((tlv_len == 7) || (tlv_len == 10)) {
1075 proto_tree *fl_tree;
1076
1077 ti = proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_flags, payload_tvb, offset, 1, ENC_NA);
1078 fl_tree = proto_item_add_subtree(ti, ett_mle_conn_flg);
1079 proto_tree_add_item(fl_tree, hf_mle_tlv_conn_flags_pp, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1080 offset++;
1081 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_lq3, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1082 offset++;
1083 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_lq2, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1084 offset++;
1085 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_lq1, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1086 offset++;
1087 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_leader_cost, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1088 offset++;
1089 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_id_seq, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1090 offset++;
1091 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_active_rtrs, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1092 offset++;
1093 if (tlv_len == 10) {
1094 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_sed_buf_size, payload_tvb, offset, 2, ENC_BIG_ENDIAN);
1095 offset += 2;
1096 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_sed_dgram_cnt, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1097 offset++;
1098 }
1099 } else {
1100 /* TLV Length must be 7 (old style) or 10 */
1101 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1102 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1103 offset += tlv_len;
1104 }
1105 break;
1106
1107 case MLE_TLV_LINK_MARGIN:
1108 if (tlv_len != 1) {
1109 /* TLV Length must be 1 */
1110 proto_item_append_text(ti, ")");
1111 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1112 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1113 } else {
1114 guint8 link_margin;
1115
1116 link_margin = tvb_get_guint8(payload_tvb, offset);
1117 proto_item_append_text(ti, " = %udB)", link_margin);
1118 proto_tree_add_item(tlv_tree, hf_mle_tlv_link_margin, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1119 }
1120 offset += tlv_len;
1121 break;
1122
1123 case MLE_TLV_STATUS:
1124 if (tlv_len != 1) {
1125 /* TLV Length must be 1 */
1126 proto_item_append_text(ti, ")");
1127 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1128 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1129 } else {
1130 guint8 stat;
1131
1132 stat = tvb_get_guint8(payload_tvb, offset);
1133 proto_item_append_text(ti, " = %d)", stat);
1134 proto_tree_add_item(tlv_tree, hf_mle_tlv_status, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1135 }
1136 offset += tlv_len;
1137 break;
1138
1139 case MLE_TLV_VERSION:
1140 if (tlv_len != 2) {
1141 /* TLV Length must be 2 */
1142 proto_item_append_text(ti, ")");
1143 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1144 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1145 } else {
1146 guint16 version;
1147
1148 version = tvb_get_ntohs(payload_tvb, offset);
1149 proto_item_append_text(ti, " = %d)", version);
1150 proto_tree_add_item(tlv_tree, hf_mle_tlv_version, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1151 }
1152 offset += tlv_len;
1153 break;
1154
1155 case MLE_TLV_ADDRESS_REGISTRATION:
1156 {
1157 guint8 iid_type, i;
1158 guint8 entries = 0;
1159 gint16 check_len = tlv_len;
1160 guint check_offset = offset;
1161
1162 /* Check consistency of entries */
1163 while (check_len > 0) {
1164 guint8 ar_len;
1165
1166 iid_type = tvb_get_guint8(payload_tvb, check_offset);
1167 if (iid_type & ADDR_REG_MASK_IID_TYPE_MASK) {
1168 ar_len = 9;
1169 } else {
1170 ar_len = 17;
1171 }
1172 check_offset += ar_len;
1173 check_len -= ar_len;
1174 entries++;
1175 }
1176
1177 proto_item_append_text(ti, ")");
1178 if (check_len != 0) {
1179 /* Not an integer number of entries */
1180 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1181 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1182 offset += tlv_len;
1183 } else {
1184 for (i = 0; i < entries; i++) {
1185 proto_tree *ar_tree;
1186
1187 ti = proto_tree_add_item(tlv_tree, hf_mle_tlv_addr_reg_entry, payload_tvb, offset, 1, ENC_NA);
1188 ar_tree = proto_item_add_subtree(ti, ett_mle_addr_reg);
1189 iid_type = tvb_get_guint8(payload_tvb, offset);
1190 if (iid_type & ADDR_REG_MASK_IID_TYPE_MASK) {
1191 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_iid_type, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1192 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_cid, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1193 offset++;
1194 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_iid, payload_tvb, offset, 8, ENC_NA);
1195 offset += 8;
1196 } else {
1197 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_iid_type, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1198 offset++;
1199 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_ipv6, payload_tvb, offset, 16, ENC_NA);
1200 offset += 16;
1201 }
1202 }
1203 }
1204 }
1205 break;
1206
1207 case MLE_TLV_CHANNEL:
1208 {
1209 proto_item_append_text(ti, ")");
1210
1211 /* Check length is consistent */
1212 if (tlv_len != 3) {
1213 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1214 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1215 } else {
1216 /* Channel page */
1217 proto_tree_add_item(tlv_tree, hf_mle_tlv_channel_page, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1218 /* Channel */
1219 proto_tree_add_item(tlv_tree, hf_mle_tlv_channel, payload_tvb, offset+1, 2, ENC_BIG_ENDIAN);
1220 }
1221 offset += tlv_len;
1222 }
1223 break;
1224
1225 case MLE_TLV_PAN_ID:
1226 {
1227 proto_item_append_text(ti, ")");
1228
1229 /* Check length is consistent */
1230 if (tlv_len != 2) {
1231 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1232 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1233 } else {
1234 /* PAN ID */
1235 proto_tree_add_item(tlv_tree, hf_mle_tlv_pan_id, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1236 }
1237 offset += tlv_len;
1238 }
1239 break;
1240
1241 case MLE_TLV_ACTIVE_TSTAMP:
1242 case MLE_TLV_PENDING_TSTAMP:
1243 {
1244 nstime_t timestamp;
1245
1246 proto_item_append_text(ti, ")");
1247
1248 if (tlv_len != 8) {
1249 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1250 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1251 } else {
1252 /* Fill in the nstime_t structure */
1253 timestamp.secs = (time_t)tvb_get_ntoh48(payload_tvb, offset);
1254 timestamp.nsecs = (int)lround((double)(tvb_get_ntohs(payload_tvb, offset + 6) >> 1) * MLE_32768_TO_NSEC_FACTOR);
1255 if (tlv_type == MLE_TLV_ACTIVE_TSTAMP) {
1256 proto_tree_add_time(tlv_tree, hf_mle_tlv_active_tstamp, payload_tvb, offset, 8, ×tamp);
1257 } else {
1258 proto_tree_add_time(tlv_tree, hf_mle_tlv_pending_tstamp, payload_tvb, offset, 8, ×tamp);
1259 }
1260 }
1261 offset += tlv_len;
1262 }
1263 break;
1264
1265 default:
1266 proto_item_append_text(ti, ")");
1267 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1268 offset += tlv_len;
1269 }
1270 }
1271
1272 return tvb_captured_length(tvb);
1273 }
1274
1275 void
proto_register_mle(void)1276 proto_register_mle(void)
1277 {
1278 static hf_register_info hf[] = {
1279
1280 /* Auxiliary Security Header Fields */
1281 /*----------------------------------*/
1282 { &hf_mle_security_suite,
1283 { "Security Suite",
1284 "mle.sec_suite",
1285 FT_UINT8, BASE_HEX, VALS(mle_sec_suite_names), 0x0,
1286 "The Security Suite of the frame",
1287 HFILL
1288 }
1289 },
1290
1291 { &hf_mle_mic,
1292 { "Decrypted MIC",
1293 "mle.mic",
1294 FT_BYTES, BASE_NONE, NULL, 0x0,
1295 "The decrypted MIC",
1296 HFILL
1297 }
1298 },
1299
1300 /*MLE Command*/
1301 { &hf_mle_command,
1302 { "Command",
1303 "mle.cmd",
1304 FT_UINT8, BASE_DEC, VALS(mle_command_vals), 0x0,
1305 "MLE command type",
1306 HFILL
1307 }
1308 },
1309
1310 /* Generic TLV */
1311 { &hf_mle_tlv,
1312 { "TLV",
1313 "mle.tlv",
1314 FT_NONE, BASE_NONE, NULL, 0x0,
1315 "Type-Length-Value",
1316 HFILL
1317 }
1318 },
1319
1320 { &hf_mle_tlv_type,
1321 { "Type",
1322 "mle.tlv.type",
1323 FT_UINT8, BASE_DEC, VALS(mle_tlv_vals), 0x0,
1324 "Type of value",
1325 HFILL
1326 }
1327 },
1328
1329 { &hf_mle_tlv_length,
1330 { "Length",
1331 "mle.tlv.len",
1332 FT_UINT8, BASE_DEC, NULL, 0x0,
1333 "Length of value",
1334 HFILL
1335 }
1336 },
1337
1338 /* Type-Specific TLV Fields */
1339 { &hf_mle_tlv_source_addr,
1340 { "Address",
1341 "mle.tlv.source_addr",
1342 FT_BYTES, BASE_NONE, NULL, 0x0,
1343 "Source address",
1344 HFILL
1345 }
1346 },
1347
1348 /* Capability Information Fields */
1349 { &hf_mle_tlv_mode_nwk_data,
1350 { "Network Data",
1351 "mle.tlv.mode.nwk_data",
1352 FT_BOOLEAN, 8, TFS(&mle_tlv_mode_nwk_data), MLE_CMD_CINFO_NWK_DATA,
1353 NULL,
1354 HFILL
1355 }
1356 },
1357
1358 { &hf_mle_tlv_mode_device_type,
1359 { "Device Type",
1360 "mle.tlv.mode.device_type",
1361 FT_BOOLEAN, 8, TFS(&mle_tlv_mode_device_type), IEEE802154_CMD_CINFO_DEVICE_TYPE,
1362 NULL,
1363 HFILL
1364 }
1365 },
1366
1367 { &hf_mle_tlv_mode_sec_data_req,
1368 { "Secure Data Requests",
1369 "mle.tlv.mode.sec_data_req",
1370 FT_BOOLEAN, 8, NULL, MLE_CMD_CINFO_SEC_DATA_REQ,
1371 NULL,
1372 HFILL
1373 }
1374 },
1375
1376 { &hf_mle_tlv_mode_idle_rx,
1377 { "Receive On When Idle",
1378 "mle.tlv.mode.idle_rx",
1379 FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_IDLE_RX,
1380 NULL,
1381 HFILL
1382 }
1383 },
1384
1385 { &hf_mle_tlv_timeout,
1386 { "Timeout",
1387 "mle.tlv.timeout",
1388 FT_UINT32, BASE_DEC, NULL, 0x0,
1389 "Expected interval between transmissions in seconds",
1390 HFILL
1391 }
1392 },
1393
1394 { &hf_mle_tlv_challenge,
1395 { "Challenge",
1396 "mle.tlv.challenge",
1397 FT_BYTES, BASE_NONE, NULL, 0x0,
1398 "Challenge to be echoed back",
1399 HFILL
1400 }
1401 },
1402
1403 { &hf_mle_tlv_response,
1404 { "Response",
1405 "mle.tlv.response",
1406 FT_BYTES, BASE_NONE, NULL, 0x0,
1407 "Response to a challenge",
1408 HFILL
1409 }
1410 },
1411
1412 { &hf_mle_tlv_ll_frm_cntr,
1413 { "Link Layer Frame Counter",
1414 "mle.tlv.ll_frm_cntr",
1415 FT_UINT32, BASE_DEC, NULL, 0x0,
1416 "The Link layer frame counter",
1417 HFILL
1418 }
1419 },
1420
1421 { &hf_mle_tlv_mle_frm_cntr,
1422 { "MLE Frame Counter",
1423 "mle.tlv.mle_frm_cntr",
1424 FT_UINT32, BASE_DEC, NULL, 0x0,
1425 "The MLE frame counter",
1426 HFILL
1427 }
1428 },
1429
1430 { &hf_mle_tlv_unknown,
1431 { "Unknown",
1432 "mle.tlv.unknown",
1433 FT_BYTES, BASE_NONE, NULL, 0x0,
1434 "Unknown TLV, raw value",
1435 HFILL
1436 }
1437 },
1438
1439 { &hf_mle_tlv_lqi_c,
1440 { "Complete Flag",
1441 "mle.tlv.lqi.complete",
1442 FT_BOOLEAN, 8, NULL, LQI_FLAGS_C,
1443 NULL,
1444 HFILL
1445 }
1446 },
1447
1448 { &hf_mle_tlv_lqi_size,
1449 { "Address Size",
1450 "mle.tlv.lqi.size",
1451 FT_UINT8, BASE_DEC, NULL, LQI_FLAGS_SIZE,
1452 NULL,
1453 HFILL
1454 }
1455 },
1456
1457 { &hf_mle_tlv_neighbor,
1458 { "Neighbor Record",
1459 "mle.tlv.neighbor",
1460 FT_NONE, BASE_NONE, NULL, 0x0,
1461 NULL,
1462 HFILL
1463 }
1464 },
1465
1466 { &hf_mle_tlv_neighbor_flagI,
1467 { "Incoming",
1468 "mle.tlv.neighbor.flagI",
1469 FT_BOOLEAN, 8, NULL, NEIGHBOR_FLAG_I,
1470 "Set if the sender has configured its link with this neighbor and will accept incoming messages from them.",
1471 HFILL
1472 }
1473 },
1474
1475 { &hf_mle_tlv_neighbor_flagO,
1476 { "Outgoing",
1477 "mle.tlv.neighbor.flagO",
1478 FT_BOOLEAN, 8, NULL, NEIGHBOR_FLAG_O,
1479 "Set if the sender believes that the neighbor has configured its link with the sender and will accept incoming messages from the sender.",
1480 HFILL
1481 }
1482 },
1483
1484 { &hf_mle_tlv_neighbor_flagP,
1485 { "Priority",
1486 "mle.tlv.neighbor.flagP",
1487 FT_BOOLEAN, 8, NULL, NEIGHBOR_FLAG_P,
1488 "Set if the sender expects to use this link for sending messages to this neighbor.",
1489 HFILL
1490 }
1491 },
1492
1493 { &hf_mle_tlv_neighbor_idr,
1494 { "Inverse Delivery Ratio",
1495 "mle.tlv.neighbor.idr",
1496 FT_UINT8, BASE_DEC, NULL, 0x0,
1497 NULL,
1498 HFILL
1499 }
1500 },
1501
1502 { &hf_mle_tlv_neighbor_addr,
1503 { "Address",
1504 "mle.tlv.neighbor.addr",
1505 FT_BYTES, BASE_NONE, NULL, 0x0,
1506 NULL,
1507 HFILL
1508 }
1509 },
1510
1511 { &hf_mle_tlv_network_param_id,
1512 { "Parameter ID",
1513 "mle.tlv.network.param_id",
1514 FT_UINT8, BASE_DEC, NULL, 0x0,
1515 NULL,
1516 HFILL
1517 }
1518 },
1519
1520 { &hf_mle_tlv_network_delay,
1521 { "Delay",
1522 "mle.tlv.network.delay",
1523 FT_UINT32, BASE_DEC, NULL, 0x0,
1524 NULL,
1525 HFILL
1526 }
1527 },
1528
1529 { &hf_mle_tlv_network_channel,
1530 { "Channel",
1531 "mle.tlv.network.channel",
1532 FT_UINT16, BASE_DEC, NULL, 0x0,
1533 NULL,
1534 HFILL
1535 }
1536 },
1537
1538 { &hf_mle_tlv_network_pan_id,
1539 { "PAN ID",
1540 "mle.tlv.network.pan_id",
1541 FT_UINT16, BASE_HEX, NULL, 0x0,
1542 NULL,
1543 HFILL
1544 }
1545 },
1546
1547 { &hf_mle_tlv_network_pmt_join,
1548 { "Permit Join",
1549 "mle.tlv.network.pmt_join",
1550 FT_BOOLEAN, 8, NULL, 0x1,
1551 NULL,
1552 HFILL
1553 }
1554 },
1555
1556 { &hf_mle_tlv_network_bcn_payload,
1557 { "Beacon Payload",
1558 "mle.tlv.network.bcn_payload",
1559 FT_BYTES, BASE_NONE, NULL, 0x0,
1560 NULL,
1561 HFILL
1562 }
1563 },
1564
1565 { &hf_mle_tlv_route64_id_seq,
1566 { "ID Sequence",
1567 "mle.tlv.route64.id_seq",
1568 FT_UINT8, BASE_DEC, NULL, 0x0,
1569 NULL,
1570 HFILL
1571 }
1572 },
1573
1574 { &hf_mle_tlv_route64_id_mask,
1575 { "Assigned Router ID Mask",
1576 "mle.tlv.route64.id_mask",
1577 FT_BYTES, BASE_NONE, NULL, 0x0,
1578 NULL,
1579 HFILL
1580 }
1581 },
1582
1583 { &hf_mle_tlv_route64_entry,
1584 { "Routing Table Entry",
1585 "mle.tlv.route64",
1586 FT_UINT8, BASE_HEX, NULL, 0x0,
1587 NULL,
1588 HFILL
1589 }
1590 },
1591
1592 { &hf_mle_tlv_route64_nbr_out,
1593 { "Neighbor Out Link Quality",
1594 "mle.tlv.route64.nbr_out",
1595 FT_UINT8, BASE_DEC, NULL, ROUTE_TBL_OUT_MASK,
1596 NULL,
1597 HFILL
1598 }
1599 },
1600
1601 { &hf_mle_tlv_route64_nbr_in,
1602 { "Neighbor In Link Quality",
1603 "mle.tlv.route64.nbr_in",
1604 FT_UINT8, BASE_DEC, NULL, ROUTE_TBL_IN_MASK,
1605 NULL,
1606 HFILL
1607 }
1608 },
1609
1610 { &hf_mle_tlv_route64_cost,
1611 { "Router Cost",
1612 "mle.tlv.route64.cost",
1613 FT_UINT8, BASE_DEC, NULL, ROUTE_TBL_COST_MASK,
1614 NULL,
1615 HFILL
1616 }
1617 },
1618 #if 0
1619 { &hf_mle_tlv_route64_unknown,
1620 { "(unknown)",
1621 "mle.tlv.route64.unknown",
1622 FT_BYTES, BASE_NONE, NULL, 0x0,
1623 NULL,
1624 HFILL
1625 }
1626 },
1627 #endif
1628 { &hf_mle_tlv_addr16,
1629 { "Address16",
1630 "mle.tlv.addr16",
1631 FT_BYTES, BASE_NONE, NULL, 0x0,
1632 NULL,
1633 HFILL
1634 }
1635 },
1636
1637 { &hf_mle_tlv_leader_data_partition_id,
1638 { "Partition ID",
1639 "mle.tlv.leader_data.partition_id",
1640 FT_UINT32, BASE_HEX, NULL, 0x0,
1641 NULL,
1642 HFILL
1643 }
1644 },
1645
1646 { &hf_mle_tlv_leader_data_weighting,
1647 { "Weighting",
1648 "mle.tlv.leader_data.weighting",
1649 FT_UINT8, BASE_DEC, NULL, 0x0,
1650 NULL,
1651 HFILL
1652 }
1653 },
1654
1655 { &hf_mle_tlv_leader_data_version,
1656 { "Data Version",
1657 "mle.tlv.leader_data.data_version",
1658 FT_UINT8, BASE_DEC, NULL, 0x0,
1659 NULL,
1660 HFILL
1661 }
1662 },
1663
1664 { &hf_mle_tlv_leader_data_stable_version,
1665 { "Stable Data Version",
1666 "mle.tlv.leader_data.stable_data_version",
1667 FT_UINT8, BASE_DEC, NULL, 0x0,
1668 NULL,
1669 HFILL
1670 }
1671 },
1672
1673 { &hf_mle_tlv_leader_data_router_id,
1674 { "Leader Router ID",
1675 "mle.tlv.leader_data.router_id",
1676 FT_UINT8, BASE_DEC, NULL, 0x0,
1677 NULL,
1678 HFILL
1679 }
1680 },
1681 #if 0
1682 { &hf_mle_tlv_network_data,
1683 { "Network Data",
1684 "mle.tlv.network_data",
1685 FT_BYTES, BASE_NONE, NULL, 0x0,
1686 "Network data (opaque data)",
1687 HFILL
1688 }
1689 },
1690 #endif
1691 { &hf_mle_tlv_scan_mask_r,
1692 { "Router",
1693 "mle.tlv.scan_mask.r",
1694 FT_BOOLEAN, 8, NULL, SCAN_MASK_R_MASK,
1695 NULL,
1696 HFILL
1697 }
1698 },
1699
1700 { &hf_mle_tlv_scan_mask_e,
1701 { "End Device",
1702 "mle.tlv.scan_mask.e",
1703 FT_BOOLEAN, 8, NULL, SCAN_MASK_D_MASK,
1704 NULL,
1705 HFILL
1706 }
1707 },
1708
1709 { &hf_mle_tlv_conn_flags,
1710 { "Flags",
1711 "mle.tlv.conn.flags",
1712 FT_NONE, BASE_NONE, NULL, 0x0,
1713 NULL,
1714 HFILL
1715 }
1716 },
1717
1718 { &hf_mle_tlv_conn_flags_pp,
1719 { "Parent Priority",
1720 "mle.tlv.conn.flags.pp",
1721 FT_INT8, BASE_DEC, VALS(mle_conn_tlv_flags_pp_enums), CONN_MASK_FLAGS_PP_MASK,
1722 NULL,
1723 HFILL
1724 }
1725 },
1726
1727 { &hf_mle_tlv_conn_lq3,
1728 { "Link Quality 3",
1729 "mle.tlv.conn.lq3",
1730 FT_UINT8, BASE_DEC, NULL, 0x0,
1731 NULL,
1732 HFILL
1733 }
1734 },
1735
1736 { &hf_mle_tlv_conn_lq2,
1737 { "Link Quality 2",
1738 "mle.tlv.conn.lq2",
1739 FT_UINT8, BASE_DEC, NULL, 0x0,
1740 NULL,
1741 HFILL
1742 }
1743 },
1744
1745 { &hf_mle_tlv_conn_lq1,
1746 { "Link Quality 1",
1747 "mle.tlv.conn.lq1",
1748 FT_UINT8, BASE_DEC, NULL, 0x0,
1749 NULL,
1750 HFILL
1751 }
1752 },
1753
1754 { &hf_mle_tlv_conn_leader_cost,
1755 { "Leader Cost",
1756 "mle.tlv.conn.leader_cost",
1757 FT_UINT8, BASE_DEC, NULL, 0x0,
1758 NULL,
1759 HFILL
1760 }
1761 },
1762
1763 { &hf_mle_tlv_conn_id_seq,
1764 { "ID Sequence",
1765 "mle.tlv.conn.id_seq",
1766 FT_UINT8, BASE_DEC, NULL, 0x0,
1767 NULL,
1768 HFILL
1769 }
1770 },
1771
1772 { &hf_mle_tlv_conn_active_rtrs,
1773 { "Active Routers",
1774 "mle.tlv.conn.active_rtrs",
1775 FT_UINT8, BASE_DEC, NULL, 0x0,
1776 NULL,
1777 HFILL
1778 }
1779 },
1780
1781 { &hf_mle_tlv_conn_sed_buf_size,
1782 { "SED Buffer Size",
1783 "mle.tlv.conn.sed_buf_size",
1784 FT_UINT16, BASE_DEC, NULL, 0x0,
1785 NULL,
1786 HFILL
1787 }
1788 },
1789
1790 { &hf_mle_tlv_conn_sed_dgram_cnt,
1791 { "SED Datagram Count",
1792 "mle.tlv.conn.sed_dgram_cnt",
1793 FT_UINT8, BASE_DEC, NULL, 0x0,
1794 NULL,
1795 HFILL
1796 }
1797 },
1798
1799 { &hf_mle_tlv_link_margin,
1800 { "Link Margin",
1801 "mle.tlv.link_margin",
1802 FT_UINT8, BASE_DEC, NULL, 0,
1803 "Link margin in dB",
1804 HFILL
1805 }
1806 },
1807
1808 { &hf_mle_tlv_status,
1809 { "Status",
1810 "mle.tlv.status",
1811 FT_UINT8, BASE_DEC, VALS(mle_status_tlv_enums), 0,
1812 NULL,
1813 HFILL
1814 }
1815 },
1816
1817 { &hf_mle_tlv_version,
1818 { "Version",
1819 "mle.tlv.version",
1820 FT_UINT16, BASE_DEC, NULL, 0,
1821 NULL,
1822 HFILL
1823 }
1824 },
1825
1826 { &hf_mle_tlv_addr_reg_entry,
1827 { "Address Registration Entry",
1828 "mle.tlv.addr_reg",
1829 FT_NONE, BASE_NONE, NULL, 0x0,
1830 NULL,
1831 HFILL
1832 }
1833 },
1834
1835 { &hf_mle_tlv_addr_reg_iid_type,
1836 { "IID type",
1837 "mle.tlv.addr_reg_iid_type",
1838 FT_BOOLEAN, 8, TFS(&mle_tlv_addr_reg_iid_type), ADDR_REG_MASK_IID_TYPE_MASK,
1839 "Context ID",
1840 HFILL
1841 }
1842 },
1843
1844 { &hf_mle_tlv_addr_reg_cid,
1845 { "Context ID",
1846 "mle.tlv.addr_reg_cid",
1847 FT_UINT8, BASE_DEC, NULL, ADDR_REG_MASK_CID_MASK,
1848 "6LoWPAN Context ID",
1849 HFILL
1850 }
1851 },
1852
1853 { &hf_mle_tlv_addr_reg_iid,
1854 { "IID",
1855 "mle.tlv.addr_reg_iid",
1856 FT_BYTES, BASE_NONE, NULL, 0x0,
1857 "Interface identifier",
1858 HFILL
1859 }
1860 },
1861
1862 { &hf_mle_tlv_addr_reg_ipv6,
1863 { "IPv6 Address",
1864 "mle.tlv.addr_reg_ipv6",
1865 FT_IPv6, BASE_NONE, NULL, 0x0,
1866 "IID",
1867 HFILL
1868 }
1869 },
1870 #if 0
1871 { &hf_mle_tlv_hold_time,
1872 { "Hold Time",
1873 "mle.tlv.hold_time",
1874 FT_UINT16, BASE_DEC, NULL, 0,
1875 NULL,
1876 HFILL
1877 }
1878 },
1879 #endif
1880 { &hf_mle_tlv_network_unknown,
1881 { "(unknown)",
1882 "mle.tlv.network.unknown",
1883 FT_BYTES, BASE_NONE, NULL, 0x0,
1884 NULL,
1885 HFILL
1886 }
1887 },
1888
1889 { &hf_mle_tlv_channel_page,
1890 { "Channel Page",
1891 "mle.tlv.channel_page",
1892 FT_UINT8, BASE_DEC, NULL, 0x0,
1893 NULL,
1894 HFILL
1895 }
1896 },
1897
1898 { &hf_mle_tlv_channel,
1899 { "Channel",
1900 "mle.tlv.channel",
1901 FT_UINT16, BASE_DEC, NULL, 0x0,
1902 NULL,
1903 HFILL
1904 }
1905 },
1906
1907 { &hf_mle_tlv_pan_id,
1908 { "PAN ID",
1909 "mle.tlv.pan_id",
1910 FT_UINT16, BASE_HEX, NULL, 0x0,
1911 NULL,
1912 HFILL
1913 }
1914 },
1915
1916 { &hf_mle_tlv_active_tstamp,
1917 { "Active Timestamp",
1918 "mle.tlv.active_tstamp",
1919 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
1920 NULL,
1921 HFILL
1922 }
1923 },
1924
1925 { &hf_mle_tlv_pending_tstamp,
1926 { "Pending Timestamp",
1927 "mle.tlv.pending_tstamp",
1928 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
1929 NULL,
1930 HFILL
1931 }
1932 },
1933 #if 0
1934 { &hf_mle_tlv_active_op_dataset,
1935 { "Active Operational Dataset",
1936 "mle.tlv.active_op_dataset",
1937 FT_BYTES, BASE_NONE, NULL, 0x0,
1938 "Thread Active Operational Dataset",
1939 HFILL
1940 }
1941 },
1942 { &hf_mle_tlv_pending_op_dataset,
1943 { "Pending Operational Dataset",
1944 "mle.tlv.pending_op_dataset",
1945 FT_BYTES, BASE_NONE, NULL, 0x0,
1946 "Thread Pending Operational Dataset",
1947 HFILL
1948 }
1949 },
1950 #endif
1951 };
1952
1953 static gint *ett[] = {
1954 &ett_mle,
1955 &ett_mle_auxiliary_security,
1956 &ett_mle_aux_sec_control,
1957 &ett_mle_aux_sec_key_id,
1958 &ett_mle_tlv,
1959 &ett_mle_neighbor,
1960 &ett_mle_router,
1961 &ett_mle_addr_reg,
1962 &ett_mle_conn_flg,
1963 &ett_mle_thread_nwd
1964 };
1965
1966 static ei_register_info ei[] = {
1967 { &ei_mle_cbc_mac_failed, { "mle.cbc_mac_failed", PI_UNDECODED, PI_WARN, "Call to ccm_cbc_mac() failed", EXPFILL }},
1968 { &ei_mle_packet_too_small, { "mle.packet_too_small", PI_UNDECODED, PI_WARN, "Packet was too small to include the CRC and MIC", EXPFILL }},
1969 { &ei_mle_no_key, { "mle.no_key", PI_UNDECODED, PI_WARN, "No encryption key set - can't decrypt", EXPFILL }},
1970 { &ei_mle_decrypt_failed, { "mle.decrypt_failed", PI_UNDECODED, PI_WARN, "Decrypt failed", EXPFILL }},
1971 { &ei_mle_mic_check_failed, { "mle.mic_check_failed", PI_UNDECODED, PI_WARN, "MIC check failed", EXPFILL }},
1972 { &ei_mle_tlv_length_failed, { "mle.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
1973 { &ei_mle_len_size_mismatch, { "mle.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
1974 };
1975
1976 module_t *mle_module;
1977 expert_module_t* expert_mle;
1978
1979 proto_mle = proto_register_protocol("Mesh Link Establishment", "MLE", "mle");
1980 proto_register_field_array(proto_mle, hf, array_length(hf));
1981 proto_register_subtree_array(ett, array_length(ett));
1982 expert_mle = expert_register_protocol(proto_mle);
1983 expert_register_field_array(expert_mle, ei, array_length(ei));
1984
1985 mle_handle = register_dissector("mle", dissect_mle, proto_mle);
1986
1987 mle_module = prefs_register_protocol(proto_mle, NULL);
1988
1989 prefs_register_bool_preference(mle_module, "meshlink_mic_ok",
1990 "Dissect only good MIC",
1991 "Dissect payload only if MIC is valid.",
1992 &mle_mic_ok);
1993
1994 /* setup registration for other dissectors to provide mle key hash algorithms */
1995 mle_key_hash_handlers = wmem_tree_new(wmem_epan_scope());
1996 }
1997
1998 void
proto_reg_handoff_mle(void)1999 proto_reg_handoff_mle(void)
2000 {
2001 thread_nwd_handle = find_dissector_add_dependency("thread_nwd", proto_mle);
2002 thread_mc_handle = find_dissector_add_dependency("thread_meshcop", proto_mle);
2003
2004 //heur_dissector_add("stun", dissect_embeddedmle_heur, proto_mle);
2005
2006 dissector_add_uint_range_with_preference("udp.port", UDP_PORT_MLE_RANGE, mle_handle);
2007
2008 proto_ieee802154 = proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN);
2009 }
2010
2011 /*
2012 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2013 *
2014 * Local variables:
2015 * c-basic-offset: 2
2016 * tab-width: 8
2017 * indent-tabs-mode: nil
2018 * End:
2019 *
2020 * vi: set shiftwidth=2 tabstop=8 expandtab
2021 * :indentSize=2:tabSize=8:noTabs=true:
2022 */
2023