2 * Routines for MLE packet dissection
4 * Colin O'Flynn <coflynn@newae.com>
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
12 * Thread parts added by Robert Cragie <robert.cragie@arm.com>
14 * Wireshark - Network traffic analyzer
15 * By Gerald Combs <gerald@wireshark.org>
16 * Copyright 1998 Gerald Combs
18 * SPDX-License-Identifier: GPL-2.0-or-later
25 #include <epan/packet.h>
26 #include <epan/conversation.h>
27 #include <epan/proto_data.h>
28 #include <epan/wmem/wmem.h>
29 #include <epan/expert.h>
30 #include <epan/prefs.h>
31 #include <epan/strutil.h>
32 #include <epan/to_str.h>
33 #include "packet-ieee802154.h"
34 #include "packet-mle.h"
36 #define MLE_32768_TO_NSEC_FACTOR ((double)30517.578125)
38 /* Forward declarations */
39 void proto_register_mle(void);
40 void proto_reg_handoff_mle(void);
42 static int proto_mle = -1;
43 static int proto_ieee802154 = -1; /* cache 802.15.4 protocol ID */
45 /* Registered fields for Auxiliary Security Header */
46 static int hf_mle_security_suite = -1;
47 static int hf_mle_mic = -1;
49 static int hf_mle_command = -1;
50 static int hf_mle_tlv = -1;
51 static int hf_mle_tlv_type = -1;
52 static int hf_mle_tlv_length = -1;
53 static int hf_mle_tlv_source_addr = -1;
54 static int hf_mle_tlv_mode_device_type = -1;
55 static int hf_mle_tlv_mode_idle_rx = -1;
56 static int hf_mle_tlv_mode_sec_data_req = -1;
57 static int hf_mle_tlv_mode_nwk_data = -1;
58 static int hf_mle_tlv_timeout = -1;
59 static int hf_mle_tlv_challenge = -1;
60 static int hf_mle_tlv_response = -1;
61 static int hf_mle_tlv_ll_frm_cntr = -1;
62 static int hf_mle_tlv_lqi_c = -1;
63 static int hf_mle_tlv_lqi_size = -1;
64 static int hf_mle_tlv_neighbor = -1;
65 static int hf_mle_tlv_neighbor_flagI = -1;
66 static int hf_mle_tlv_neighbor_flagO = -1;
67 static int hf_mle_tlv_neighbor_flagP = -1;
68 static int hf_mle_tlv_neighbor_idr = -1;
69 static int hf_mle_tlv_neighbor_addr = -1;
70 static int hf_mle_tlv_network_param_id = -1;
71 static int hf_mle_tlv_network_delay = -1;
72 static int hf_mle_tlv_network_channel = -1;
73 static int hf_mle_tlv_network_pan_id = -1;
74 static int hf_mle_tlv_network_pmt_join = -1;
75 static int hf_mle_tlv_network_bcn_payload = -1;
76 static int hf_mle_tlv_network_unknown = -1;
77 static int hf_mle_tlv_mle_frm_cntr = -1;
78 static int hf_mle_tlv_unknown = -1;
79 static int hf_mle_tlv_route64_id_seq = -1;
80 static int hf_mle_tlv_route64_id_mask = -1;
81 static int hf_mle_tlv_route64_entry = -1;
82 static int hf_mle_tlv_route64_nbr_out = -1;
83 static int hf_mle_tlv_route64_nbr_in = -1;
84 static int hf_mle_tlv_route64_cost = -1;
86 static int hf_mle_tlv_route64_unknown = -1;
88 static int hf_mle_tlv_addr16 = -1;
89 static int hf_mle_tlv_leader_data_partition_id = -1;
90 static int hf_mle_tlv_leader_data_weighting = -1;
91 static int hf_mle_tlv_leader_data_version = -1;
92 static int hf_mle_tlv_leader_data_stable_version = -1;
93 static int hf_mle_tlv_leader_data_router_id = -1;
95 static int hf_mle_tlv_network_data = -1;
97 static int hf_mle_tlv_scan_mask_r = -1;
98 static int hf_mle_tlv_scan_mask_e = -1;
99 static int hf_mle_tlv_conn_flags = -1;
100 static int hf_mle_tlv_conn_flags_pp = -1;
101 static int hf_mle_tlv_conn_lq3 = -1;
102 static int hf_mle_tlv_conn_lq2 = -1;
103 static int hf_mle_tlv_conn_lq1 = -1;
104 static int hf_mle_tlv_conn_leader_cost = -1;
105 static int hf_mle_tlv_conn_id_seq = -1;
106 static int hf_mle_tlv_conn_active_rtrs = -1;
107 static int hf_mle_tlv_conn_sed_buf_size = -1;
108 static int hf_mle_tlv_conn_sed_dgram_cnt = -1;
109 static int hf_mle_tlv_link_margin = -1;
110 static int hf_mle_tlv_status = -1;
111 static int hf_mle_tlv_version = -1;
112 static int hf_mle_tlv_addr_reg_entry = -1;
113 static int hf_mle_tlv_addr_reg_iid_type = -1;
114 static int hf_mle_tlv_addr_reg_cid = -1;
115 static int hf_mle_tlv_addr_reg_iid = -1;
116 static int hf_mle_tlv_addr_reg_ipv6 = -1;
118 static int hf_mle_tlv_hold_time = -1;
120 static int hf_mle_tlv_channel_page = -1; /* v1.1-draft-2 */
121 static int hf_mle_tlv_channel = -1; /* v1.1-draft-2 */
122 static int hf_mle_tlv_pan_id = -1; /* v1.1-draft-2 */
123 static int hf_mle_tlv_active_tstamp = -1; /* SPEC-472 */
124 static int hf_mle_tlv_pending_tstamp = -1; /* SPEC-472 */
126 static int hf_mle_tlv_active_op_dataset = -1; /* SPEC-472 */
127 static int hf_mle_tlv_pending_op_dataset = -1; /* SPEC-472 */
130 static gint ett_mle = -1;
131 static gint ett_mle_tlv = -1;
132 static gint ett_mle_neighbor = -1;
133 static gint ett_mle_router = -1;
134 static gint ett_mle_addr_reg = -1;
135 static gint ett_mle_conn_flg = -1;
136 static gint ett_mle_thread_nwd = -1;
137 static gint ett_mle_auxiliary_security = -1;
138 static gint ett_mle_aux_sec_control = -1;
139 static gint ett_mle_aux_sec_key_id = -1;
141 static expert_field ei_mle_cbc_mac_failed = EI_INIT;
142 static expert_field ei_mle_packet_too_small = EI_INIT;
143 static expert_field ei_mle_no_key = EI_INIT;
144 static expert_field ei_mle_decrypt_failed = EI_INIT;
145 static expert_field ei_mle_mic_check_failed = EI_INIT;
146 static expert_field ei_mle_tlv_length_failed = EI_INIT;
147 static expert_field ei_mle_len_size_mismatch = EI_INIT;
149 static dissector_handle_t mle_handle;
150 static dissector_handle_t thread_nwd_handle;
151 static dissector_handle_t thread_mc_handle;
153 #define UDP_PORT_MLE_RANGE "19788" /* IANA registered */
155 /* boolean value set if the MIC must be ok before payload is dissected */
156 static gboolean mle_mic_ok = FALSE;
158 static wmem_tree_t* mle_key_hash_handlers;
160 static const value_string mle_sec_suite_names[] = {
161 { 0, "802.15.4 Security" },
162 { 255, "No Security" },
166 static const value_string mle_status_tlv_enums[] = {
168 { 2, "Duplicate Address Detected" },
172 static const value_string mle_conn_tlv_flags_pp_enums[] = {
179 #define MLE_CMD_REQUEST 0
180 #define MLE_CMD_ACCEPT 1
181 #define MLE_CMD_ACCEPTREQ 2
182 #define MLE_CMD_REJECT 3
183 #define MLE_CMD_ADVERTISE 4
184 #define MLE_CMD_UPDATE 5
185 #define MLE_CMD_UPDATE_REQUEST 6
186 #define MLE_CMD_DATA_REQUEST 7
187 #define MLE_CMD_DATA_RESPONSE 8
188 #define MLE_CMD_PARENT_REQUEST 9
189 #define MLE_CMD_PARENT_RESPONSE 10
190 #define MLE_CMD_CHILD_ID_REQUEST 11
191 #define MLE_CMD_CHILD_ID_RESPONSE 12
192 #define MLE_CMD_CHILD_UPDATE_REQUEST 13
193 #define MLE_CMD_CHILD_UPDATE_RESPONSE 14
194 #define MLE_CMD_ANNOUNCE 15
195 #define MLE_CMD_DISCOVERY_REQUEST 16
196 #define MLE_CMD_DISCOVERY_RESPONSE 17
198 static const value_string mle_command_vals[] = {
199 { MLE_CMD_REQUEST, "Link Request" },
200 { MLE_CMD_ACCEPT, "Link Accept" },
201 { MLE_CMD_ACCEPTREQ, "Link Accept and Request" },
202 { MLE_CMD_REJECT, "Link Reject" },
203 { MLE_CMD_ADVERTISE, "Advertisement" },
204 { MLE_CMD_UPDATE, "Update" },
205 { MLE_CMD_UPDATE_REQUEST, "Update Request" },
206 { MLE_CMD_DATA_REQUEST, "Data Request" },
207 { MLE_CMD_DATA_RESPONSE, "Data Response" },
208 { MLE_CMD_PARENT_REQUEST, "Parent Request" },
209 { MLE_CMD_PARENT_RESPONSE, "Parent Response" },
210 { MLE_CMD_CHILD_ID_REQUEST, "Child ID Request" },
211 { MLE_CMD_CHILD_ID_RESPONSE, "Child ID Response" },
212 { MLE_CMD_CHILD_UPDATE_REQUEST, "Child Update Request" },
213 { MLE_CMD_CHILD_UPDATE_RESPONSE, "Child Update Response" },
214 { MLE_CMD_ANNOUNCE, "Announce" },
215 { MLE_CMD_DISCOVERY_REQUEST, "Discovery Request" },
216 { MLE_CMD_DISCOVERY_RESPONSE, "Discovery Response" },
220 #define MLE_TLV_SOURCE_ADDRESS 0
221 #define MLE_TLV_MODE 1 /* Modified in Ch04_Mesh Link Establishment */
222 #define MLE_TLV_TIMEOUT 2
223 #define MLE_TLV_CHALLENGE 3
224 #define MLE_TLV_RESPONSE 4
225 #define MLE_TLV_LINK_LAYER_FRAME_COUNTER 5
226 #define MLE_TLV_LINK_QUALITY 6
227 #define MLE_TLV_NETWORK_PARAMETER 7
228 #define MLE_TLV_MLE_FRAME_COUNTER 8
229 #define MLE_TLV_ROUTE64 9 /* Defined in Ch05_Network Layer v1.1-rc1 */
230 #define MLE_TLV_ADDRESS16 10 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
231 #define MLE_TLV_LEADER_DATA 11 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
232 #define MLE_TLV_NETWORK_DATA 12 /* Defined in Ch05_Network Layer v1.1-rc1 */
233 #define MLE_TLV_TLV_REQUEST 13 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
234 #define MLE_TLV_SCAN_MASK 14 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
235 #define MLE_TLV_CONNECTIVITY 15 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
236 #define MLE_TLV_LINK_MARGIN 16 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
237 #define MLE_TLV_STATUS 17 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
238 #define MLE_TLV_VERSION 18 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
239 #define MLE_TLV_ADDRESS_REGISTRATION 19 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
240 #define MLE_TLV_CHANNEL 20 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
241 #define MLE_TLV_PAN_ID 21 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
242 #define MLE_TLV_ACTIVE_TSTAMP 22 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
243 #define MLE_TLV_PENDING_TSTAMP 23 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
244 #define MLE_TLV_ACTIVE_OP_DATASET 24 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
245 #define MLE_TLV_PENDING_OP_DATASET 25 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
246 #define MLE_TLV_THREAD_DISCOVERY 26 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
248 static const value_string mle_tlv_vals[] = {
249 { MLE_TLV_SOURCE_ADDRESS, "Source Address" },
250 { MLE_TLV_MODE, "Mode" },
251 { MLE_TLV_TIMEOUT, "Timeout" },
252 { MLE_TLV_CHALLENGE, "Challenge" },
253 { MLE_TLV_RESPONSE, "Response" },
254 { MLE_TLV_LINK_LAYER_FRAME_COUNTER, "Link Layer Frame Counter"},
255 { MLE_TLV_LINK_QUALITY, "Link Quality"},
256 { MLE_TLV_NETWORK_PARAMETER, "Network Parameter"},
257 { MLE_TLV_MLE_FRAME_COUNTER, "MLE Frame Counter"},
258 { MLE_TLV_ROUTE64, "Route64"},
259 { MLE_TLV_ADDRESS16, "Address16"},
260 { MLE_TLV_LEADER_DATA, "Leader Data"},
261 { MLE_TLV_NETWORK_DATA, "Network Data"},
262 { MLE_TLV_TLV_REQUEST, "TLV Request"},
263 { MLE_TLV_SCAN_MASK, "Scan Mask"},
264 { MLE_TLV_CONNECTIVITY, "Connectivity"},
265 { MLE_TLV_LINK_MARGIN, "Link Margin"},
266 { MLE_TLV_STATUS, "Status"},
267 { MLE_TLV_VERSION, "Version"},
268 { MLE_TLV_ADDRESS_REGISTRATION, "Address Registration"},
269 { MLE_TLV_CHANNEL, "Channel"},
270 { MLE_TLV_PAN_ID, "PAN ID"},
271 { MLE_TLV_ACTIVE_TSTAMP, "Active Timestamp"},
272 { MLE_TLV_PENDING_TSTAMP, "Pending Timestamp"},
273 { MLE_TLV_ACTIVE_OP_DATASET, "Active Operational Dataset"},
274 { MLE_TLV_PENDING_OP_DATASET, "Pending Operational Dataset"},
275 { MLE_TLV_THREAD_DISCOVERY, "Thread Discovery"},
279 #define LQI_FLAGS_C 0x80
280 #define LQI_FLAGS_SIZE 0x0F
282 #define NEIGHBOR_FLAG_I 0x80
283 #define NEIGHBOR_FLAG_O 0x40
284 #define NEIGHBOR_FLAG_P 0x20
286 #define NETWORK_PARAM_ID_CHANNEL 0
287 #define NETWORK_PARAM_ID_PAN_ID 1
288 #define NETWORK_PARAM_ID_PERMIT_JOIN 2
289 #define NETWORK_PARAM_ID_BCN_PAYLOAD 3
291 static const value_string mle_tlv_nwk_param_vals[] = {
292 { NETWORK_PARAM_ID_CHANNEL, "Channel" },
293 { NETWORK_PARAM_ID_PAN_ID, "PAN ID" },
294 { NETWORK_PARAM_ID_PERMIT_JOIN, "Permit Join" },
295 { NETWORK_PARAM_ID_BCN_PAYLOAD, "Beacon Payload" },
299 static const true_false_string mle_tlv_mode_device_type = {
303 static const true_false_string mle_tlv_mode_nwk_data = {
307 static const true_false_string mle_tlv_addr_reg_iid_type = {
312 #define ROUTE_TBL_OUT_MASK 0xC0
313 #define ROUTE_TBL_IN_MASK 0x30
314 #define ROUTE_TBL_COST_MASK 0x0F
316 #define SCAN_MASK_R_MASK 0x80
317 #define SCAN_MASK_D_MASK 0x40
319 #define CONN_MASK_FLAGS_PP_MASK 0xC0
321 #define ADDR_REG_MASK_IID_TYPE_MASK 0x80
322 #define ADDR_REG_MASK_CID_MASK 0x0F
324 #define MLE_CMD_CINFO_SEC_DATA_REQ 0x04
325 #define MLE_CMD_CINFO_NWK_DATA 0x01
327 /*FUNCTION:------------------------------------------------------
329 * dissect_mle_decrypt
333 * tvbuff_t *tvb - IEEE 802.15.4 packet.
334 * packet_info * pinfo - Packet info structure.
335 * guint offset - Offset where the ciphertext 'c' starts.
336 * ieee802154_packet *packet - IEEE 802.15.4 packet information.
337 * ws_decrypt_status *status - status of decryption returned through here on failure.
339 * tvbuff_t * - Decrypted payload.
340 *---------------------------------------------------------------
343 dissect_mle_decrypt(tvbuff_t * tvb,
346 ieee802154_packet * packet,
347 ieee802154_decrypt_info_t* decrypt_info)
349 tvbuff_t * ptext_tvb;
350 gboolean have_mic = FALSE;
352 unsigned char tmp[16];
357 *decrypt_info->rx_mic_length = 0;
358 memset(decrypt_info->rx_mic, 0, 16);
360 /* Get the captured and on-the-wire length of the payload. */
361 if (packet->security_level > 0) {
362 M = IEEE802154_MIC_LENGTH(packet->security_level);
368 reported_len = tvb_reported_length_remaining(tvb, offset) - M;
369 if (reported_len < 0) {
370 *decrypt_info->status = DECRYPT_PACKET_TOO_SMALL;
373 /* Check if the payload is truncated. */
374 if (tvb_bytes_exist(tvb, offset, reported_len)) {
375 captured_len = reported_len;
378 captured_len = tvb_captured_length_remaining(tvb, offset);
381 if (packet->security_level > 0) {
382 /* Check if the MIC is present in the captured data. */
383 have_mic = tvb_bytes_exist(tvb, offset + reported_len, M);
385 tvb_memcpy(tvb, decrypt_info->rx_mic, offset + reported_len, M);
389 /*=====================================================
390 * Key Lookup - Need to find the appropriate key.
391 *=====================================================
393 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
394 /* The source EUI-64 is included in the headers. */
395 srcAddr = packet->src64; /* GUINT64_SWAP_LE_BE(packet->src64); */
399 *decrypt_info->status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
403 /*=====================================================
404 * CCM* - CTR mode payload encryption
405 *=====================================================
407 /* Create the CCM* initial block for decryption (Adata=0, M=0, counter=0). */
408 ccm_init_block(tmp, FALSE, 0, srcAddr, packet->frame_counter, packet->security_level, 0, NULL);
410 /* Decrypt the ciphertext, and place the plaintext in a new tvb. */
411 if (IEEE802154_IS_ENCRYPTED(packet->security_level) && captured_len) {
415 * Make a copy of the ciphertext in heap memory.
417 * We will decrypt the message in-place and then use the buffer as the
418 * real data for the new tvb.
420 text = (gchar *)tvb_memdup(pinfo->pool, tvb, offset, captured_len);
422 /* Perform CTR-mode transformation. Try both the likely key and the alternate key */
423 if (!ccm_ctr_encrypt(decrypt_info->key, tmp, decrypt_info->rx_mic, text, captured_len)) {
424 *decrypt_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
428 /* Create a tvbuff for the plaintext. */
429 ptext_tvb = tvb_new_real_data((const guint8 *)text, captured_len, reported_len);
430 tvb_set_child_real_data_tvbuff(tvb, ptext_tvb);
431 add_new_data_source(pinfo, ptext_tvb, "Decrypted MLE payload");
432 *decrypt_info->status = DECRYPT_PACKET_SUCCEEDED;
434 /* There is no ciphertext. Wrap the plaintext in a new tvb. */
436 /* Decrypt the MIC (if present). */
438 if (!ccm_ctr_encrypt(decrypt_info->key, tmp, decrypt_info->rx_mic, NULL, 0)) {
439 *decrypt_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
444 /* Create a tvbuff for the plaintext. This might result in a zero-length tvbuff. */
445 ptext_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
446 *decrypt_info->status = DECRYPT_PACKET_SUCCEEDED;
449 /*=====================================================
450 * CCM* - CBC-mode message authentication
451 *=====================================================
453 /* We can only verify the message if the MIC wasn't truncated. */
455 unsigned char dec_mic[16];
456 guint l_m = captured_len;
460 DISSECTOR_ASSERT(pinfo->src.len == 16);
461 DISSECTOR_ASSERT(pinfo->dst.len == 16);
462 memcpy(d_a, pinfo->src.data, pinfo->src.len);
463 memcpy(d_a+16, pinfo->dst.data, pinfo->dst.len);
465 tvb_memcpy(tvb, d_a+32, decrypt_info->aux_offset, decrypt_info->aux_length);
466 l_a = 32 + decrypt_info->aux_length;
468 /* Adjust the lengths of the plantext and additional data if unencrypted. */
469 if (!IEEE802154_IS_ENCRYPTED(packet->security_level)) {
474 /* Create the CCM* initial block for authentication (Adata!=0, M!=0, counter=l(m)). */
475 ccm_init_block(tmp, TRUE, M, srcAddr, packet->frame_counter, packet->security_level, l_m, NULL);
477 /* Compute CBC-MAC authentication tag. */
479 * And yes, despite the warning in tvbuff.h, I think tvb_get_ptr is the
480 * right function here since either A) the payload wasn't encrypted, in
481 * which case l_m is zero, or B) the payload was encrypted, and the tvb
482 * already points to contiguous memory, since we just allocated it in
485 if (!ccm_cbc_mac(decrypt_info->key, tmp, d_a, l_a, tvb_get_ptr(ptext_tvb, 0, l_m), l_m, dec_mic)) {
486 *decrypt_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
488 /* Compare the received MIC with the one we generated. */
489 else if (memcmp(decrypt_info->rx_mic, dec_mic, M) != 0) {
490 *decrypt_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
494 *decrypt_info->rx_mic_length = M;
498 } /* dissect_mle_decrypt */
500 void register_mle_key_hash_handler(guint hash_identifier, ieee802154_set_key_func key_func)
502 /* Ensure no duplication */
503 DISSECTOR_ASSERT(wmem_tree_lookup32(mle_key_hash_handlers, hash_identifier) == NULL);
505 wmem_tree_insert32(mle_key_hash_handlers, hash_identifier, (void*)key_func);
508 /* Set MLE key function. */
509 static guint ieee802154_set_mle_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t *uat_key)
511 ieee802154_set_key_func func = (ieee802154_set_key_func)wmem_tree_lookup32(mle_key_hash_handlers, uat_key->hash_type);
514 return func(packet, key, alt_key, uat_key);
516 /* Right now, KEY_HASH_NONE and KEY_HASH_ZIP are not registered because they
517 work with this "default" behavior */
518 if (packet->key_index == uat_key->key_index)
520 memcpy(key, uat_key->key, IEEE802154_CIPHER_SIZE);
528 dissect_mle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
530 tvbuff_t *volatile payload_tvb = NULL;
531 proto_tree *volatile mle_tree = NULL;
532 proto_item *volatile proto_root = NULL;
535 guint aux_header_offset = 0;
536 ieee802154_decrypt_status status;
539 proto_item *mic_item = NULL;
540 proto_tree *header_tree = NULL;
541 guint8 security_suite;
542 guint aux_length = 0;
543 ieee802154_packet *packet;
544 ieee802154_packet *original_packet;
545 ieee802154_decrypt_info_t decrypt_info;
546 ieee802154_hints_t *ieee_hints;
547 gboolean mic_ok=TRUE;
549 unsigned char rx_mic[16];
550 unsigned int rx_mic_len = 0;
553 guint8 tlv_type, tlv_len;
554 proto_tree *tlv_tree;
556 ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
557 if (ieee_hints == NULL) {
558 /* For now, MLE only supported with IEEE802.15.4 as an underlying layer */
561 original_packet = (ieee802154_packet *)ieee_hints->packet;
563 packet = wmem_new0(wmem_packet_scope(), ieee802154_packet);
565 /* Copy IEEE 802.15.4 Source Address */
566 packet->src_addr_mode = original_packet->src_addr_mode;
567 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
568 packet->src64 = original_packet->src64;
570 packet->src16 = original_packet->src16;
573 /* Copy IEEE 802.15.4 Source PAN ID */
574 packet->src_pan = original_packet->src_pan;
576 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MLE");
577 col_clear(pinfo->cinfo, COL_INFO);
579 /* Create the protocol tree. */
580 proto_root = proto_tree_add_item(tree, proto_mle, tvb, 0, tvb_reported_length(tvb), ENC_NA);
581 mle_tree = proto_item_add_subtree(proto_root, ett_mle);
583 /* Parse the security suite field. */
584 /* Security Suite Field */
585 security_suite = tvb_get_guint8(tvb, offset);
586 proto_tree_add_item(mle_tree, hf_mle_security_suite, tvb, offset, 1, ENC_NA);
589 aux_header_offset = offset;
591 /* Security material present if security suite = 0 */
592 if (security_suite == 0) {
593 dissect_ieee802154_aux_sec_header_and_key(tvb, pinfo, mle_tree, packet, &offset);
594 aux_length = offset-aux_header_offset;
596 packet->security_level = SECURITY_LEVEL_NONE;
599 decrypt_info.key_number = 0;
601 /* Add additional fields for security level > SECURITY_LEVEL_NONE */
602 if (packet->security_level > SECURITY_LEVEL_NONE) {
604 /* Pass to decryption process */
605 decrypt_info.rx_mic = rx_mic;
606 decrypt_info.rx_mic_length = &rx_mic_len;
607 decrypt_info.aux_offset = aux_header_offset;
608 decrypt_info.aux_length = aux_length;
609 decrypt_info.status = &status;
610 decrypt_info.key = NULL; /* payload function will fill that in */
612 payload_tvb = decrypt_ieee802154_payload(tvb, offset, pinfo, header_tree, packet, &decrypt_info,
613 ieee802154_set_mle_key, dissect_mle_decrypt);
614 if (status == DECRYPT_PACKET_MIC_CHECK_FAILED)
615 expert_add_info(pinfo, proto_root, &ei_mle_cbc_mac_failed);
619 mic_item = proto_tree_add_bytes(header_tree, hf_mle_mic, tvb, 0, rx_mic_len, rx_mic);
620 proto_item_set_generated(mic_item);
623 status = DECRYPT_NOT_ENCRYPTED;
626 /* Get the unencrypted data if decryption failed. */
628 /* Deal with possible truncation and the FCS field at the end. */
629 gint reported_len = tvb_reported_length_remaining(tvb, offset);
630 gint captured_len = tvb_captured_length_remaining(tvb, offset);
631 if (reported_len < captured_len) captured_len = reported_len;
632 payload_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
635 /* Display the reason for failure, and abort if the error was fatal. */
637 case DECRYPT_PACKET_SUCCEEDED:
639 proto_item_append_text(mic_item, " [correct (key no. %d)]", decrypt_info.key_number);
642 case DECRYPT_PACKET_TOO_SMALL:
643 expert_add_info(pinfo, proto_root, &ei_mle_packet_too_small);
644 call_data_dissector(payload_tvb, pinfo, tree);
645 return tvb_captured_length(tvb);
647 case DECRYPT_PACKET_NO_KEY:
648 expert_add_info(pinfo, proto_root, &ei_mle_no_key);
649 call_data_dissector(payload_tvb, pinfo, tree);
650 return tvb_captured_length(tvb);
652 case DECRYPT_PACKET_DECRYPT_FAILED:
653 expert_add_info(pinfo, proto_root, &ei_mle_decrypt_failed);
654 call_data_dissector(payload_tvb, pinfo, tree);
655 return tvb_captured_length(tvb);
657 case DECRYPT_PACKET_MIC_CHECK_FAILED:
658 expert_add_info(pinfo, proto_root, &ei_mle_mic_check_failed);
659 proto_item_append_text(mic_item, " [incorrect]");
661 * Abort only if the payload was encrypted, in which case we
662 * probably didn't decrypt the packet right (eg: wrong key).
664 if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
668 case DECRYPT_NOT_ENCRYPTED:
672 /* This can cause a lot of problems so remove it by default */
673 if (!mic_ok && mle_mic_ok) {
674 call_data_dissector(payload_tvb, pinfo, tree);
675 col_add_fstr(pinfo->cinfo, COL_INFO, "MIC Failed");
676 return tvb_captured_length(tvb);
679 /***** NEW CODE HERE ****/
680 /* If we're good, carry on and display the MLE payload */
684 proto_tree_add_item(mle_tree, hf_mle_command, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
686 cmd = tvb_get_guint8(payload_tvb, offset);
687 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(cmd, mle_command_vals, "Unknown (%x)"));
692 while (tvb_offset_exists(payload_tvb, offset)) {
694 /* Get the length ahead of time to pass to next function so we can highlight
695 proper amount of bytes */
696 tlv_len = tvb_get_guint8(payload_tvb, offset+1);
698 ti = proto_tree_add_item(mle_tree, hf_mle_tlv, payload_tvb, offset, tlv_len+2, ENC_NA);
699 tlv_tree = proto_item_add_subtree(ti, ett_mle_tlv);
702 proto_tree_add_item(tlv_tree, hf_mle_tlv_type, payload_tvb, offset, 1, ENC_NA);
703 tlv_type = tvb_get_guint8(payload_tvb, offset);
706 /* Add value name to value root label */
707 proto_item_append_text(ti, " (%s", val_to_str(tlv_type, mle_tlv_vals, "Unknown (%d)"));
710 proto_tree_add_item(tlv_tree, hf_mle_tlv_length, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
714 case MLE_TLV_SOURCE_ADDRESS:
716 gboolean haveShortTLV = FALSE;
717 guint16 shortAddr = 0;
719 if (!((tlv_len == 2) || (tlv_len == 8))) {
720 /* TLV Length must be 2 or 8 */
721 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
722 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
727 shortAddr = tvb_get_ntohs(payload_tvb, offset);
730 proto_tree_add_item(tlv_tree, hf_mle_tlv_source_addr, payload_tvb, offset, tlv_len, ENC_NA);
731 proto_item_append_text(ti, " = ");
734 addr = tvb_get_guint8(payload_tvb, offset);
735 proto_item_append_text(ti, "%02x", addr);
737 proto_item_append_text(ti, ":");
741 if ((original_packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && haveShortTLV) {
742 /* Source TLV: use this to update src/long mapping */
743 ieee802154_addr_update(&ieee802154_map, shortAddr, original_packet->src_pan, original_packet->src64, pinfo->current_proto, pinfo->fd->num);
746 proto_item_append_text(ti, ")");
754 capability = tvb_get_guint8(payload_tvb, offset);
755 proto_item_append_text(ti, " = %02x)", capability);
756 /* Get and display capability info. (blatantly plagiarised from packet-ieee802154.c */
757 proto_tree_add_item(tlv_tree, hf_mle_tlv_mode_nwk_data, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
758 proto_tree_add_item(tlv_tree, hf_mle_tlv_mode_device_type, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
759 proto_tree_add_item(tlv_tree, hf_mle_tlv_mode_sec_data_req, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
760 proto_tree_add_item(tlv_tree, hf_mle_tlv_mode_idle_rx, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
763 /* TLV Length must be 1 */
764 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
765 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
770 case MLE_TLV_TIMEOUT:
772 /* TLV Length must be 4 */
773 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
774 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
777 proto_tree_add_item_ret_uint(tlv_tree, hf_mle_tlv_timeout, payload_tvb, offset, 4, ENC_BIG_ENDIAN, &to_data);
778 proto_item_append_text(ti, " = %d", (guint16)to_data);
780 proto_item_append_text(ti, ")");
784 case MLE_TLV_CHALLENGE:
785 proto_tree_add_item(tlv_tree, hf_mle_tlv_challenge, payload_tvb, offset, tlv_len, ENC_NA);
786 proto_item_append_text(ti, " = %s)", tvb_bytes_to_str(wmem_packet_scope(), payload_tvb, offset, tlv_len));
790 case MLE_TLV_RESPONSE:
791 proto_tree_add_item(tlv_tree, hf_mle_tlv_response, payload_tvb, offset, tlv_len, ENC_NA);
792 proto_item_append_text(ti, " = %s)", tvb_bytes_to_str(wmem_packet_scope(), payload_tvb, offset, tlv_len));
796 case MLE_TLV_LINK_LAYER_FRAME_COUNTER:
797 case MLE_TLV_MLE_FRAME_COUNTER:
799 /* TLV Length must be 4 */
800 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
801 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
805 if (tlv_type == MLE_TLV_LINK_LAYER_FRAME_COUNTER) {
806 proto_tree_add_item_ret_uint(tlv_tree, hf_mle_tlv_ll_frm_cntr, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN, &cntr);
808 proto_tree_add_item_ret_uint(tlv_tree, hf_mle_tlv_mle_frm_cntr, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN, &cntr);
810 proto_item_append_text(ti, " = %u", cntr);
812 proto_item_append_text(ti, ")");
816 case MLE_TLV_LINK_QUALITY:
819 guint8 size = tvb_get_guint8(payload_tvb, offset) & LQI_FLAGS_SIZE;
820 proto_tree *neig_tree;
821 proto_tree_add_item(tlv_tree, hf_mle_tlv_lqi_c, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
822 proto_tree_add_item(tlv_tree, hf_mle_tlv_lqi_size, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
825 if ((tlv_len - 1) % (size + 3)) {
826 expert_add_info(pinfo, proto_root, &ei_mle_len_size_mismatch);
827 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
830 numNeighbors = (tlv_len - 1) / (size + 3);
833 if (numNeighbors == 0) {
834 proto_item_append_text(ti, ")");
835 } else if (numNeighbors == 1) {
836 proto_item_append_text(ti, ": 1 Neighbor)");
838 proto_item_append_text(ti, ": %d Neighbors)", numNeighbors);
846 while (numNeighbors) {
847 ti = proto_tree_add_item(tlv_tree, hf_mle_tlv_neighbor, payload_tvb, offset, size+2, ENC_NA);
848 neig_tree = proto_item_add_subtree(ti, ett_mle_neighbor);
850 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_flagI, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
851 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_flagO, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
852 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_flagP, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
855 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_idr, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
858 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_addr, payload_tvb, offset,size, ENC_NA);
866 case MLE_TLV_NETWORK_PARAMETER:
868 guint8 param_id = tvb_get_guint8(payload_tvb, offset);
870 proto_item_append_text(ti, " = %s)", val_to_str(param_id, mle_tlv_nwk_param_vals, "Unknown (%d)"));
872 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_param_id, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
874 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_delay, payload_tvb, offset, 4, ENC_BIG_ENDIAN);
878 case NETWORK_PARAM_ID_CHANNEL:
879 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_channel, payload_tvb, offset, 2, ENC_BIG_ENDIAN);
882 case NETWORK_PARAM_ID_PAN_ID:
883 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_pan_id, payload_tvb, offset, 2, ENC_BIG_ENDIAN);
886 case NETWORK_PARAM_ID_PERMIT_JOIN:
887 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_pmt_join, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
890 case NETWORK_PARAM_ID_BCN_PAYLOAD:
891 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_bcn_payload, payload_tvb, offset, tlv_len-5, ENC_NA);
895 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_unknown, payload_tvb, offset, tlv_len-5, ENC_NA);
902 case MLE_TLV_ROUTE64:
904 proto_tree *rtr_tree;
907 guint64 id_mask, test_mask;
909 proto_item_append_text(ti, ")");
910 proto_tree_add_item(tlv_tree, hf_mle_tlv_route64_id_seq, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
913 /* Count number of table entries */
915 for (i = 0; i < 8; i++) { /* TODO magic - number of routers/8 */
916 guint8 id_mask_octet = tvb_get_guint8(payload_tvb, offset + i);
917 for (j = 0; j < 8; j++) {
918 if (id_mask_octet & (1 << j)) {
925 * | | | | | | | | | | |1|1|1|1|1|1|...|6|
926 * |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|...|3|
927 * ---------------------------------------
928 * |1|0|1|1|1|0|0|0|1|1|0|0|0|1|0|1|...
930 * is sent as 0xb8, 0xc5
931 * and represents table entry for routers 0, 2, 3, 4, 8, 9, 13, 15...
933 /* Get the ID mask as a 64-bit number (BE) */
934 id_mask = tvb_get_ntoh64(payload_tvb, offset);
936 /* Just show the string of octets - best representation for a bit mask */
937 proto_tree_add_item(tlv_tree, hf_mle_tlv_route64_id_mask, payload_tvb, offset, 8, ENC_NA);
940 if (count != (tlv_len - 9))
942 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
943 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
944 offset += (tlv_len - 9);
947 for (i = 0; i < count; i++) {
948 /* Find first bit set */
949 for (j = 0, test_mask = (G_GUINT64_CONSTANT(1) << 63); test_mask != 1; test_mask >>= 1, j++) {
950 if (test_mask & id_mask) {
951 id_mask &= ~test_mask;
955 ti = proto_tree_add_item(tlv_tree, hf_mle_tlv_route64_entry, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
956 proto_item_append_text(ti, " (%d)", j);
957 rtr_tree = proto_item_add_subtree(ti, ett_mle_router);
959 proto_tree_add_item(rtr_tree, hf_mle_tlv_route64_nbr_out, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
960 proto_tree_add_item(rtr_tree, hf_mle_tlv_route64_nbr_in, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
961 proto_tree_add_item(rtr_tree, hf_mle_tlv_route64_cost, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
968 case MLE_TLV_ADDRESS16:
970 /* TLV Length must be 2 */
971 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
972 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
974 guint16 addr16 = tvb_get_ntohs(payload_tvb, offset);
975 proto_item_append_text(ti, " = ");
977 guint8 a16_len = 2; /* Fix it at 2 */
978 guint stroffset = offset;
982 a16_data = tvb_get_guint8(payload_tvb, stroffset);
983 proto_item_append_text(ti, "%02x", a16_data);
985 proto_item_append_text(ti, ":");
990 proto_tree_add_item(tlv_tree, hf_mle_tlv_addr16, payload_tvb, offset, 2, ENC_NA);
991 if (original_packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
992 /* Allocated Address16 TLV: use this to update dst/long mapping */
993 ieee802154_addr_update(&ieee802154_map, addr16, original_packet->dst_pan, original_packet->dst64, pinfo->current_proto, pinfo->fd->num);
996 proto_item_append_text(ti, ")");
1000 case MLE_TLV_LEADER_DATA:
1001 proto_item_append_text(ti, ")");
1003 /* TLV Length must be 8 */
1004 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1005 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1008 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_partition_id, payload_tvb, offset, 4, ENC_BIG_ENDIAN);
1010 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_weighting, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1012 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_version, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1014 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_stable_version, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1016 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_router_id, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1021 case MLE_TLV_NETWORK_DATA:
1024 proto_item_append_text(ti, ")");
1026 sub_tvb = tvb_new_subset_length(payload_tvb, offset, tlv_len);
1027 call_dissector(thread_nwd_handle, sub_tvb, pinfo, tlv_tree);
1033 case MLE_TLV_ACTIVE_OP_DATASET:
1034 case MLE_TLV_PENDING_OP_DATASET:
1035 case MLE_TLV_THREAD_DISCOVERY:
1038 proto_item_append_text(ti, ")");
1040 sub_tvb = tvb_new_subset_length(payload_tvb, offset, tlv_len);
1041 call_dissector(thread_mc_handle, sub_tvb, pinfo, tlv_tree);
1047 case MLE_TLV_TLV_REQUEST:
1048 proto_item_append_text(ti, ")");
1050 proto_tree_add_item(tlv_tree, hf_mle_tlv_type, payload_tvb, offset, 1, ENC_NA);
1056 case MLE_TLV_SCAN_MASK:
1058 /* TLV Length must be 1 */
1059 proto_item_append_text(ti, ")");
1060 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1061 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1065 mask = tvb_get_guint8(payload_tvb, offset);
1066 proto_item_append_text(ti, " = %02x)", mask);
1067 proto_tree_add_item(tlv_tree, hf_mle_tlv_scan_mask_r, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1068 proto_tree_add_item(tlv_tree, hf_mle_tlv_scan_mask_e, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1073 case MLE_TLV_CONNECTIVITY:
1074 proto_item_append_text(ti, ")");
1075 if ((tlv_len == 7) || (tlv_len == 10)) {
1076 proto_tree *fl_tree;
1078 ti = proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_flags, payload_tvb, offset, 1, ENC_NA);
1079 fl_tree = proto_item_add_subtree(ti, ett_mle_conn_flg);
1080 proto_tree_add_item(fl_tree, hf_mle_tlv_conn_flags_pp, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1082 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_lq3, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1084 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_lq2, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1086 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_lq1, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1088 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_leader_cost, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1090 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_id_seq, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1092 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_active_rtrs, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1094 if (tlv_len == 10) {
1095 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_sed_buf_size, payload_tvb, offset, 2, ENC_BIG_ENDIAN);
1097 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_sed_dgram_cnt, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1101 /* TLV Length must be 7 (old style) or 10 */
1102 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1103 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1108 case MLE_TLV_LINK_MARGIN:
1110 /* TLV Length must be 1 */
1111 proto_item_append_text(ti, ")");
1112 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1113 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1117 link_margin = tvb_get_guint8(payload_tvb, offset);
1118 proto_item_append_text(ti, " = %udB)", link_margin);
1119 proto_tree_add_item(tlv_tree, hf_mle_tlv_link_margin, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1124 case MLE_TLV_STATUS:
1126 /* TLV Length must be 1 */
1127 proto_item_append_text(ti, ")");
1128 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1129 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1133 stat = tvb_get_guint8(payload_tvb, offset);
1134 proto_item_append_text(ti, " = %d)", stat);
1135 proto_tree_add_item(tlv_tree, hf_mle_tlv_status, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1140 case MLE_TLV_VERSION:
1142 /* TLV Length must be 2 */
1143 proto_item_append_text(ti, ")");
1144 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1145 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1149 version = tvb_get_ntohs(payload_tvb, offset);
1150 proto_item_append_text(ti, " = %d)", version);
1151 proto_tree_add_item(tlv_tree, hf_mle_tlv_version, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1156 case MLE_TLV_ADDRESS_REGISTRATION:
1160 gint16 check_len = tlv_len;
1161 guint check_offset = offset;
1163 /* Check consistency of entries */
1164 while (check_len > 0) {
1167 iid_type = tvb_get_guint8(payload_tvb, check_offset);
1168 if (iid_type & ADDR_REG_MASK_IID_TYPE_MASK) {
1173 check_offset += ar_len;
1174 check_len -= ar_len;
1178 proto_item_append_text(ti, ")");
1179 if (check_len != 0) {
1180 /* Not an integer number of entries */
1181 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1182 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1185 for (i = 0; i < entries; i++) {
1186 proto_tree *ar_tree;
1188 ti = proto_tree_add_item(tlv_tree, hf_mle_tlv_addr_reg_entry, payload_tvb, offset, 1, ENC_NA);
1189 ar_tree = proto_item_add_subtree(ti, ett_mle_addr_reg);
1190 iid_type = tvb_get_guint8(payload_tvb, offset);
1191 if (iid_type & ADDR_REG_MASK_IID_TYPE_MASK) {
1192 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_iid_type, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1193 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_cid, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1195 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_iid, payload_tvb, offset, 8, ENC_NA);
1198 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_iid_type, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1200 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_ipv6, payload_tvb, offset, 16, ENC_NA);
1208 case MLE_TLV_CHANNEL:
1210 proto_item_append_text(ti, ")");
1212 /* Check length is consistent */
1214 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1215 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1218 proto_tree_add_item(tlv_tree, hf_mle_tlv_channel_page, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1220 proto_tree_add_item(tlv_tree, hf_mle_tlv_channel, payload_tvb, offset+1, 2, ENC_BIG_ENDIAN);
1226 case MLE_TLV_PAN_ID:
1228 proto_item_append_text(ti, ")");
1230 /* Check length is consistent */
1232 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1233 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1236 proto_tree_add_item(tlv_tree, hf_mle_tlv_pan_id, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1242 case MLE_TLV_ACTIVE_TSTAMP:
1243 case MLE_TLV_PENDING_TSTAMP:
1247 proto_item_append_text(ti, ")");
1250 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1251 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1253 /* Fill in the nstime_t structure */
1254 timestamp.secs = (time_t)tvb_get_ntoh48(payload_tvb, offset);
1255 timestamp.nsecs = (int)lround((double)(tvb_get_ntohs(payload_tvb, offset + 6) >> 1) * MLE_32768_TO_NSEC_FACTOR);
1256 if (tlv_type == MLE_TLV_ACTIVE_TSTAMP) {
1257 proto_tree_add_time(tlv_tree, hf_mle_tlv_active_tstamp, payload_tvb, offset, 8, ×tamp);
1259 proto_tree_add_time(tlv_tree, hf_mle_tlv_pending_tstamp, payload_tvb, offset, 8, ×tamp);
1267 proto_item_append_text(ti, ")");
1268 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1273 return tvb_captured_length(tvb);
1277 proto_register_mle(void)
1279 static hf_register_info hf[] = {
1281 /* Auxiliary Security Header Fields */
1282 /*----------------------------------*/
1283 { &hf_mle_security_suite,
1286 FT_UINT8, BASE_HEX, VALS(mle_sec_suite_names), 0x0,
1287 "The Security Suite of the frame",
1295 FT_BYTES, BASE_NONE, NULL, 0x0,
1296 "The decrypted MIC",
1305 FT_UINT8, BASE_DEC, VALS(mle_command_vals), 0x0,
1315 FT_NONE, BASE_NONE, NULL, 0x0,
1316 "Type-Length-Value",
1324 FT_UINT8, BASE_DEC, VALS(mle_tlv_vals), 0x0,
1330 { &hf_mle_tlv_length,
1333 FT_UINT8, BASE_DEC, NULL, 0x0,
1339 /* Type-Specific TLV Fields */
1340 { &hf_mle_tlv_source_addr,
1342 "mle.tlv.source_addr",
1343 FT_BYTES, BASE_NONE, NULL, 0x0,
1349 /* Capability Information Fields */
1350 { &hf_mle_tlv_mode_nwk_data,
1352 "mle.tlv.mode.nwk_data",
1353 FT_BOOLEAN, 8, TFS(&mle_tlv_mode_nwk_data), MLE_CMD_CINFO_NWK_DATA,
1359 { &hf_mle_tlv_mode_device_type,
1361 "mle.tlv.mode.device_type",
1362 FT_BOOLEAN, 8, TFS(&mle_tlv_mode_device_type), IEEE802154_CMD_CINFO_DEVICE_TYPE,
1368 { &hf_mle_tlv_mode_sec_data_req,
1369 { "Secure Data Requests",
1370 "mle.tlv.mode.sec_data_req",
1371 FT_BOOLEAN, 8, NULL, MLE_CMD_CINFO_SEC_DATA_REQ,
1377 { &hf_mle_tlv_mode_idle_rx,
1378 { "Receive On When Idle",
1379 "mle.tlv.mode.idle_rx",
1380 FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_IDLE_RX,
1386 { &hf_mle_tlv_timeout,
1389 FT_UINT32, BASE_DEC, NULL, 0x0,
1390 "Expected interval between transmissions in seconds",
1395 { &hf_mle_tlv_challenge,
1397 "mle.tlv.challenge",
1398 FT_BYTES, BASE_NONE, NULL, 0x0,
1399 "Challenge to be echoed back",
1404 { &hf_mle_tlv_response,
1407 FT_BYTES, BASE_NONE, NULL, 0x0,
1408 "Response to a challenge",
1413 { &hf_mle_tlv_ll_frm_cntr,
1414 { "Link Layer Frame Counter",
1415 "mle.tlv.ll_frm_cntr",
1416 FT_UINT32, BASE_DEC, NULL, 0x0,
1417 "The Link layer frame counter",
1422 { &hf_mle_tlv_mle_frm_cntr,
1423 { "MLE Frame Counter",
1424 "mle.tlv.mle_frm_cntr",
1425 FT_UINT32, BASE_DEC, NULL, 0x0,
1426 "The MLE frame counter",
1431 { &hf_mle_tlv_unknown,
1434 FT_BYTES, BASE_NONE, NULL, 0x0,
1435 "Unknown TLV, raw value",
1440 { &hf_mle_tlv_lqi_c,
1442 "mle.tlv.lqi.complete",
1443 FT_BOOLEAN, 8, NULL, LQI_FLAGS_C,
1449 { &hf_mle_tlv_lqi_size,
1452 FT_UINT8, BASE_DEC, NULL, LQI_FLAGS_SIZE,
1458 { &hf_mle_tlv_neighbor,
1459 { "Neighbor Record",
1461 FT_NONE, BASE_NONE, NULL, 0x0,
1467 { &hf_mle_tlv_neighbor_flagI,
1469 "mle.tlv.neighbor.flagI",
1470 FT_BOOLEAN, 8, NULL, NEIGHBOR_FLAG_I,
1471 "Set if the sender has configured its link with this neighbor and will accept incoming messages from them.",
1476 { &hf_mle_tlv_neighbor_flagO,
1478 "mle.tlv.neighbor.flagO",
1479 FT_BOOLEAN, 8, NULL, NEIGHBOR_FLAG_O,
1480 "Set if the sender believes that the neighbor has configured its link with the sender and will accept incoming messages from the sender.",
1485 { &hf_mle_tlv_neighbor_flagP,
1487 "mle.tlv.neighbor.flagP",
1488 FT_BOOLEAN, 8, NULL, NEIGHBOR_FLAG_P,
1489 "Set if the sender expects to use this link for sending messages to this neighbor.",
1494 { &hf_mle_tlv_neighbor_idr,
1495 { "Inverse Delivery Ratio",
1496 "mle.tlv.neighbor.idr",
1497 FT_UINT8, BASE_DEC, NULL, 0x0,
1503 { &hf_mle_tlv_neighbor_addr,
1505 "mle.tlv.neighbor.addr",
1506 FT_BYTES, BASE_NONE, NULL, 0x0,
1512 { &hf_mle_tlv_network_param_id,
1514 "mle.tlv.network.param_id",
1515 FT_UINT8, BASE_DEC, NULL, 0x0,
1521 { &hf_mle_tlv_network_delay,
1523 "mle.tlv.network.delay",
1524 FT_UINT32, BASE_DEC, NULL, 0x0,
1530 { &hf_mle_tlv_network_channel,
1532 "mle.tlv.network.channel",
1533 FT_UINT16, BASE_DEC, NULL, 0x0,
1539 { &hf_mle_tlv_network_pan_id,
1541 "mle.tlv.network.pan_id",
1542 FT_UINT16, BASE_HEX, NULL, 0x0,
1548 { &hf_mle_tlv_network_pmt_join,
1550 "mle.tlv.network.pmt_join",
1551 FT_BOOLEAN, 8, NULL, 0x1,
1557 { &hf_mle_tlv_network_bcn_payload,
1559 "mle.tlv.network.bcn_payload",
1560 FT_BYTES, BASE_NONE, NULL, 0x0,
1566 { &hf_mle_tlv_route64_id_seq,
1568 "mle.tlv.route64.id_seq",
1569 FT_UINT8, BASE_DEC, NULL, 0x0,
1575 { &hf_mle_tlv_route64_id_mask,
1576 { "Assigned Router ID Mask",
1577 "mle.tlv.route64.id_mask",
1578 FT_BYTES, BASE_NONE, NULL, 0x0,
1584 { &hf_mle_tlv_route64_entry,
1585 { "Routing Table Entry",
1587 FT_UINT8, BASE_HEX, NULL, 0x0,
1593 { &hf_mle_tlv_route64_nbr_out,
1594 { "Neighbor Out Link Quality",
1595 "mle.tlv.route64.nbr_out",
1596 FT_UINT8, BASE_DEC, NULL, ROUTE_TBL_OUT_MASK,
1602 { &hf_mle_tlv_route64_nbr_in,
1603 { "Neighbor In Link Quality",
1604 "mle.tlv.route64.nbr_in",
1605 FT_UINT8, BASE_DEC, NULL, ROUTE_TBL_IN_MASK,
1611 { &hf_mle_tlv_route64_cost,
1613 "mle.tlv.route64.cost",
1614 FT_UINT8, BASE_DEC, NULL, ROUTE_TBL_COST_MASK,
1620 { &hf_mle_tlv_route64_unknown,
1622 "mle.tlv.route64.unknown",
1623 FT_BYTES, BASE_NONE, NULL, 0x0,
1629 { &hf_mle_tlv_addr16,
1632 FT_BYTES, BASE_NONE, NULL, 0x0,
1638 { &hf_mle_tlv_leader_data_partition_id,
1640 "mle.tlv.leader_data.partition_id",
1641 FT_UINT32, BASE_HEX, NULL, 0x0,
1647 { &hf_mle_tlv_leader_data_weighting,
1649 "mle.tlv.leader_data.weighting",
1650 FT_UINT8, BASE_DEC, NULL, 0x0,
1656 { &hf_mle_tlv_leader_data_version,
1658 "mle.tlv.leader_data.data_version",
1659 FT_UINT8, BASE_DEC, NULL, 0x0,
1665 { &hf_mle_tlv_leader_data_stable_version,
1666 { "Stable Data Version",
1667 "mle.tlv.leader_data.stable_data_version",
1668 FT_UINT8, BASE_DEC, NULL, 0x0,
1674 { &hf_mle_tlv_leader_data_router_id,
1675 { "Leader Router ID",
1676 "mle.tlv.leader_data.router_id",
1677 FT_UINT8, BASE_DEC, NULL, 0x0,
1683 { &hf_mle_tlv_network_data,
1685 "mle.tlv.network_data",
1686 FT_BYTES, BASE_NONE, NULL, 0x0,
1687 "Network data (opaque data)",
1692 { &hf_mle_tlv_scan_mask_r,
1694 "mle.tlv.scan_mask.r",
1695 FT_BOOLEAN, 8, NULL, SCAN_MASK_R_MASK,
1701 { &hf_mle_tlv_scan_mask_e,
1703 "mle.tlv.scan_mask.e",
1704 FT_BOOLEAN, 8, NULL, SCAN_MASK_D_MASK,
1710 { &hf_mle_tlv_conn_flags,
1712 "mle.tlv.conn.flags",
1713 FT_NONE, BASE_NONE, NULL, 0x0,
1719 { &hf_mle_tlv_conn_flags_pp,
1720 { "Parent Priority",
1721 "mle.tlv.conn.flags.pp",
1722 FT_INT8, BASE_DEC, VALS(mle_conn_tlv_flags_pp_enums), CONN_MASK_FLAGS_PP_MASK,
1728 { &hf_mle_tlv_conn_lq3,
1731 FT_UINT8, BASE_DEC, NULL, 0x0,
1737 { &hf_mle_tlv_conn_lq2,
1740 FT_UINT8, BASE_DEC, NULL, 0x0,
1746 { &hf_mle_tlv_conn_lq1,
1749 FT_UINT8, BASE_DEC, NULL, 0x0,
1755 { &hf_mle_tlv_conn_leader_cost,
1757 "mle.tlv.conn.leader_cost",
1758 FT_UINT8, BASE_DEC, NULL, 0x0,
1764 { &hf_mle_tlv_conn_id_seq,
1766 "mle.tlv.conn.id_seq",
1767 FT_UINT8, BASE_DEC, NULL, 0x0,
1773 { &hf_mle_tlv_conn_active_rtrs,
1775 "mle.tlv.conn.active_rtrs",
1776 FT_UINT8, BASE_DEC, NULL, 0x0,
1782 { &hf_mle_tlv_conn_sed_buf_size,
1783 { "SED Buffer Size",
1784 "mle.tlv.conn.sed_buf_size",
1785 FT_UINT16, BASE_DEC, NULL, 0x0,
1791 { &hf_mle_tlv_conn_sed_dgram_cnt,
1792 { "SED Datagram Count",
1793 "mle.tlv.conn.sed_dgram_cnt",
1794 FT_UINT8, BASE_DEC, NULL, 0x0,
1800 { &hf_mle_tlv_link_margin,
1802 "mle.tlv.link_margin",
1803 FT_UINT8, BASE_DEC, NULL, 0,
1804 "Link margin in dB",
1809 { &hf_mle_tlv_status,
1812 FT_UINT8, BASE_DEC, VALS(mle_status_tlv_enums), 0,
1818 { &hf_mle_tlv_version,
1821 FT_UINT16, BASE_DEC, NULL, 0,
1827 { &hf_mle_tlv_addr_reg_entry,
1828 { "Address Registration Entry",
1830 FT_NONE, BASE_NONE, NULL, 0x0,
1836 { &hf_mle_tlv_addr_reg_iid_type,
1838 "mle.tlv.addr_reg_iid_type",
1839 FT_BOOLEAN, 8, TFS(&mle_tlv_addr_reg_iid_type), ADDR_REG_MASK_IID_TYPE_MASK,
1845 { &hf_mle_tlv_addr_reg_cid,
1847 "mle.tlv.addr_reg_cid",
1848 FT_UINT8, BASE_DEC, NULL, ADDR_REG_MASK_CID_MASK,
1849 "6LoWPAN Context ID",
1854 { &hf_mle_tlv_addr_reg_iid,
1856 "mle.tlv.addr_reg_iid",
1857 FT_BYTES, BASE_NONE, NULL, 0x0,
1858 "Interface identifier",
1863 { &hf_mle_tlv_addr_reg_ipv6,
1865 "mle.tlv.addr_reg_ipv6",
1866 FT_IPv6, BASE_NONE, NULL, 0x0,
1872 { &hf_mle_tlv_hold_time,
1874 "mle.tlv.hold_time",
1875 FT_UINT16, BASE_DEC, NULL, 0,
1881 { &hf_mle_tlv_network_unknown,
1883 "mle.tlv.network.unknown",
1884 FT_BYTES, BASE_NONE, NULL, 0x0,
1890 { &hf_mle_tlv_channel_page,
1892 "mle.tlv.channel_page",
1893 FT_UINT8, BASE_DEC, NULL, 0x0,
1899 { &hf_mle_tlv_channel,
1902 FT_UINT16, BASE_DEC, NULL, 0x0,
1908 { &hf_mle_tlv_pan_id,
1911 FT_UINT16, BASE_HEX, NULL, 0x0,
1917 { &hf_mle_tlv_active_tstamp,
1918 { "Active Timestamp",
1919 "mle.tlv.active_tstamp",
1920 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
1926 { &hf_mle_tlv_pending_tstamp,
1927 { "Pending Timestamp",
1928 "mle.tlv.pending_tstamp",
1929 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
1935 { &hf_mle_tlv_active_op_dataset,
1936 { "Active Operational Dataset",
1937 "mle.tlv.active_op_dataset",
1938 FT_BYTES, BASE_NONE, NULL, 0x0,
1939 "Thread Active Operational Dataset",
1943 { &hf_mle_tlv_pending_op_dataset,
1944 { "Pending Operational Dataset",
1945 "mle.tlv.active_op_dataset",
1946 FT_BYTES, BASE_NONE, NULL, 0x0,
1947 "Thread Pending Operational Dataset",
1954 static gint *ett[] = {
1956 &ett_mle_auxiliary_security,
1957 &ett_mle_aux_sec_control,
1958 &ett_mle_aux_sec_key_id,
1967 static ei_register_info ei[] = {
1968 { &ei_mle_cbc_mac_failed, { "mle.cbc_mac_failed", PI_UNDECODED, PI_WARN, "Call to ccm_cbc_mac() failed", EXPFILL }},
1969 { &ei_mle_packet_too_small, { "mle.packet_too_small", PI_UNDECODED, PI_WARN, "Packet was too small to include the CRC and MIC", EXPFILL }},
1970 { &ei_mle_no_key, { "mle.no_key", PI_UNDECODED, PI_WARN, "No encryption key set - can't decrypt", EXPFILL }},
1971 { &ei_mle_decrypt_failed, { "mle.decrypt_failed", PI_UNDECODED, PI_WARN, "Decrypt failed", EXPFILL }},
1972 { &ei_mle_mic_check_failed, { "mle.mic_check_failed", PI_UNDECODED, PI_WARN, "MIC check failed", EXPFILL }},
1973 { &ei_mle_tlv_length_failed, { "mle.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
1974 { &ei_mle_len_size_mismatch, { "mle.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
1977 module_t *mle_module;
1978 expert_module_t* expert_mle;
1980 proto_mle = proto_register_protocol("Mesh Link Establishment", "MLE", "mle");
1981 proto_register_field_array(proto_mle, hf, array_length(hf));
1982 proto_register_subtree_array(ett, array_length(ett));
1983 expert_mle = expert_register_protocol(proto_mle);
1984 expert_register_field_array(expert_mle, ei, array_length(ei));
1986 mle_handle = register_dissector("mle", dissect_mle, proto_mle);
1988 mle_module = prefs_register_protocol(proto_mle, NULL);
1990 prefs_register_bool_preference(mle_module, "meshlink_mic_ok",
1991 "Dissect only good MIC",
1992 "Dissect payload only if MIC is valid.",
1995 /* setup registration for other dissectors to provide mle key hash algorithms */
1996 mle_key_hash_handlers = wmem_tree_new(wmem_epan_scope());
2000 proto_reg_handoff_mle(void)
2002 thread_nwd_handle = find_dissector_add_dependency("thread_nwd", proto_mle);
2003 thread_mc_handle = find_dissector_add_dependency("thread_meshcop", proto_mle);
2005 //heur_dissector_add("stun", dissect_embeddedmle_heur, proto_mle);
2007 dissector_add_uint_range_with_preference("udp.port", UDP_PORT_MLE_RANGE, mle_handle);
2009 proto_ieee802154 = proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN);
2013 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2018 * indent-tabs-mode: nil
2021 * vi: set shiftwidth=2 tabstop=8 expandtab
2022 * :indentSize=2:tabSize=8:noTabs=true: