Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-mle.c
blob7f162016fcd8756f0934241ac5b02d01fef4c540
1 /* packet-mle.c
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
21 #include "config.h"
23 #include <math.h>
24 #include <epan/packet.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/tfs.h>
31 #include <wsutil/array.h>
32 #include "packet-ieee802154.h"
33 #include "packet-mle.h"
35 #define MLE_32768_TO_NSEC_FACTOR ((double)30517.578125)
37 /* Forward declarations */
38 void proto_register_mle(void);
39 void proto_reg_handoff_mle(void);
41 static int proto_mle;
42 static int proto_ieee802154; /* cache 802.15.4 protocol ID */
44 /* Registered fields for Auxiliary Security Header */
45 static int hf_mle_security_suite;
46 static int hf_mle_mic;
48 static int hf_mle_command;
49 static int hf_mle_tlv;
50 static int hf_mle_tlv_type;
51 static int hf_mle_tlv_length;
52 static int hf_mle_tlv_source_addr;
53 static int hf_mle_tlv_mode_device_type;
54 static int hf_mle_tlv_mode_idle_rx;
55 static int hf_mle_tlv_mode_sec_data_req;
56 static int hf_mle_tlv_mode_receiver_on_idle;
57 static int hf_mle_tlv_mode_reserved1;
58 static int hf_mle_tlv_mode_reserved2;
59 static int hf_mle_tlv_mode_device_type_bit;
60 static int hf_mle_tlv_mode_network_data;
61 static int hf_mle_tlv_mode_nwk_data;
62 static int hf_mle_tlv_timeout;
63 static int hf_mle_tlv_challenge;
64 static int hf_mle_tlv_response;
65 static int hf_mle_tlv_ll_frm_cntr;
66 static int hf_mle_tlv_lqi_c;
67 static int hf_mle_tlv_lqi_size;
68 static int hf_mle_tlv_neighbor;
69 static int hf_mle_tlv_neighbor_flagI;
70 static int hf_mle_tlv_neighbor_flagO;
71 static int hf_mle_tlv_neighbor_flagP;
72 static int hf_mle_tlv_neighbor_idr;
73 static int hf_mle_tlv_neighbor_addr;
74 static int hf_mle_tlv_network_param_id;
75 static int hf_mle_tlv_network_delay;
76 static int hf_mle_tlv_network_channel;
77 static int hf_mle_tlv_network_pan_id;
78 static int hf_mle_tlv_network_pmt_join;
79 static int hf_mle_tlv_network_bcn_payload;
80 static int hf_mle_tlv_network_unknown;
81 static int hf_mle_tlv_mle_frm_cntr;
82 static int hf_mle_tlv_unknown;
83 static int hf_mle_tlv_route64_id_seq;
84 static int hf_mle_tlv_route64_id_mask;
85 static int hf_mle_tlv_route64_entry;
86 static int hf_mle_tlv_route64_nbr_out;
87 static int hf_mle_tlv_route64_nbr_in;
88 static int hf_mle_tlv_route64_cost;
89 #if 0
90 static int hf_mle_tlv_route64_unknown;
91 #endif
92 static int hf_mle_tlv_addr16;
93 static int hf_mle_tlv_leader_data_partition_id;
94 static int hf_mle_tlv_leader_data_weighting;
95 static int hf_mle_tlv_leader_data_version;
96 static int hf_mle_tlv_leader_data_stable_version;
97 static int hf_mle_tlv_leader_data_router_id;
98 #if 0
99 static int hf_mle_tlv_network_data;
100 #endif
101 static int hf_mle_tlv_scan_mask_r;
102 static int hf_mle_tlv_scan_mask_e;
103 static int hf_mle_tlv_conn_flags;
104 static int hf_mle_tlv_conn_flags_pp;
105 static int hf_mle_tlv_conn_lq3;
106 static int hf_mle_tlv_conn_lq2;
107 static int hf_mle_tlv_conn_lq1;
108 static int hf_mle_tlv_conn_leader_cost;
109 static int hf_mle_tlv_conn_id_seq;
110 static int hf_mle_tlv_conn_active_rtrs;
111 static int hf_mle_tlv_conn_sed_buf_size;
112 static int hf_mle_tlv_conn_sed_dgram_cnt;
113 static int hf_mle_tlv_link_margin;
114 static int hf_mle_tlv_status;
115 static int hf_mle_tlv_version;
116 static int hf_mle_tlv_addr_reg_entry;
117 static int hf_mle_tlv_addr_reg_iid_type;
118 static int hf_mle_tlv_addr_reg_cid;
119 static int hf_mle_tlv_addr_reg_iid;
120 static int hf_mle_tlv_addr_reg_ipv6;
121 #if 0
122 static int hf_mle_tlv_hold_time;
123 #endif
124 static int hf_mle_tlv_channel_page; /* v1.1-draft-2 */
125 static int hf_mle_tlv_channel; /* v1.1-draft-2 */
126 static int hf_mle_tlv_csl_accuracy; /* v1.2-draft-5 */
127 static int hf_mle_tlv_csl_synchronied_timeout; /* v1.2-draft-5 */
128 static int hf_mle_tlv_csl_clock_accuracy; /* v1.2-draft-5 */
129 static int hf_mle_tlv_csl_uncertainty;
130 static int hf_mle_tlv_pan_id; /* v1.1-draft-2 */
131 static int hf_mle_tlv_active_tstamp; /* SPEC-472 */
132 static int hf_mle_tlv_pending_tstamp; /* SPEC-472 */
133 static int hf_mle_tlv_supervision_interval;
134 #if 0
135 static int hf_mle_tlv_active_op_dataset; /* SPEC-472 */
136 static int hf_mle_tlv_pending_op_dataset; /* SPEC-472 */
137 #endif
139 //Added for Thread 1.2 support
140 /* New suppport*/
141 static int hf_mle_tlv_metric_type_id_flags;
142 static int hf_mle_tlv_metric_type_id_flags_l;
143 static int hf_mle_tlv_metric_type_id_flags_e;
144 static int hf_mle_tlv_metric_type_id_flags_type;
145 static int hf_mle_tlv_metric_type_id_flags_metric;
146 static int hf_mle_tlv_value;
147 static int hf_mle_tlv_query_id;
148 static int hf_mle_tlv_link_sub_tlv;
149 static int hf_mle_tlv_link_status;
150 static int hf_mle_tlv_link_status_sub_tlv;
152 /*Link TLVs*/
153 static int hf_mle_tlv_link_query_options;
154 static int hf_mle_tlv_link_enh_ack_flags;
155 static int hf_mle_tlv_link_requested_type_id_flags;
156 static int hf_mle_tlv_csl_sychronized_timeout;
157 static int hf_mle_tlv_link_forward_series;
158 static int hf_mle_tlv_link_concatenation_link_metric_typeid_flags;
159 static int hf_mle_tlv_link_timeout;
160 static int hf_mle_tlv_link_forward_series_flags;
163 /* End of New support */
166 static int ett_mle;
167 static int ett_mle_tlv;
168 static int ett_mle_neighbor;
169 static int ett_mle_router;
170 static int ett_mle_addr_reg;
171 static int ett_mle_conn_flg;
172 static int ett_mle_thread_nwd;
173 static int ett_mle_auxiliary_security;
174 static int ett_mle_aux_sec_control;
175 static int ett_mle_aux_sec_key_id;
177 static expert_field ei_mle_cbc_mac_failed;
178 static expert_field ei_mle_packet_too_small;
179 static expert_field ei_mle_no_key;
180 static expert_field ei_mle_decrypt_failed;
181 static expert_field ei_mle_mic_check_failed;
182 static expert_field ei_mle_tlv_length_failed;
183 static expert_field ei_mle_len_size_mismatch;
185 static dissector_handle_t mle_handle;
186 static dissector_handle_t thread_nwd_handle;
187 static dissector_handle_t thread_mc_handle;
189 #define UDP_PORT_MLE_RANGE "19788" /* IANA registered */
191 /* boolean value set if the MIC must be ok before payload is dissected */
192 static bool mle_mic_ok;
194 static wmem_tree_t* mle_key_hash_handlers;
196 static const value_string mle_sec_suite_names[] = {
197 { 0, "802.15.4 Security" },
198 { 255, "No Security" },
199 { 0, NULL }
202 static const value_string mle_status_tlv_enums[] = {
203 { 1, "Error" },
204 { 2, "Duplicate Address Detected" },
205 { 0, NULL }
208 static const value_string mle_conn_tlv_flags_pp_enums[] = {
209 { 1, "High" },
210 { 0, "Medium" },
211 { -1, "Low" },
212 { 0, NULL }
215 #define MLE_CMD_REQUEST 0
216 #define MLE_CMD_ACCEPT 1
217 #define MLE_CMD_ACCEPTREQ 2
218 #define MLE_CMD_REJECT 3
219 #define MLE_CMD_ADVERTISE 4
220 #define MLE_CMD_UPDATE 5
221 #define MLE_CMD_UPDATE_REQUEST 6
222 #define MLE_CMD_DATA_REQUEST 7
223 #define MLE_CMD_DATA_RESPONSE 8
224 #define MLE_CMD_PARENT_REQUEST 9
225 #define MLE_CMD_PARENT_RESPONSE 10
226 #define MLE_CMD_CHILD_ID_REQUEST 11
227 #define MLE_CMD_CHILD_ID_RESPONSE 12
228 #define MLE_CMD_CHILD_UPDATE_REQUEST 13
229 #define MLE_CMD_CHILD_UPDATE_RESPONSE 14
230 #define MLE_CMD_ANNOUNCE 15
231 #define MLE_CMD_DISCOVERY_REQUEST 16
232 #define MLE_CMD_DISCOVERY_RESPONSE 17
234 //Added new for Thread 1.2
235 #define MLE_CMD_LINK_METRICS_MANAGEMENT_REQUEST 18
236 #define MLE_CMD_LINK_METRICS_MANAGEMENT_RESPONSE 19
237 #define MLE_CMD_LINK_PROBE 20
238 #define MLE_CMD_CIM_DISCOVERY_REQUEST 21
239 #define MLE_CMD_CIM_DISCOVERY_RESPONSE 22
240 #define MLE_CMD_CIM_ANNOUNCE 23
242 static const value_string mle_command_vals[] = {
243 { MLE_CMD_REQUEST, "Link Request" },
244 { MLE_CMD_ACCEPT, "Link Accept" },
245 { MLE_CMD_ACCEPTREQ, "Link Accept and Request" },
246 { MLE_CMD_REJECT, "Link Reject" },
247 { MLE_CMD_ADVERTISE, "Advertisement" },
248 { MLE_CMD_UPDATE, "Update" },
249 { MLE_CMD_UPDATE_REQUEST, "Update Request" },
250 { MLE_CMD_DATA_REQUEST, "Data Request" },
251 { MLE_CMD_DATA_RESPONSE, "Data Response" },
252 { MLE_CMD_PARENT_REQUEST, "Parent Request" },
253 { MLE_CMD_PARENT_RESPONSE, "Parent Response" },
254 { MLE_CMD_CHILD_ID_REQUEST, "Child ID Request" },
255 { MLE_CMD_CHILD_ID_RESPONSE, "Child ID Response" },
256 { MLE_CMD_CHILD_UPDATE_REQUEST, "Child Update Request" },
257 { MLE_CMD_CHILD_UPDATE_RESPONSE, "Child Update Response" },
258 { MLE_CMD_ANNOUNCE, "Announce" },
259 { MLE_CMD_DISCOVERY_REQUEST, "Discovery Request" },
260 { MLE_CMD_DISCOVERY_RESPONSE, "Discovery Response" },
261 { MLE_CMD_LINK_METRICS_MANAGEMENT_REQUEST, "Link Metrics Management Request" },
262 { MLE_CMD_LINK_METRICS_MANAGEMENT_RESPONSE, "Link Metrics Management Response" },
263 { MLE_CMD_LINK_PROBE, "Link Probe" },
264 { MLE_CMD_CIM_DISCOVERY_REQUEST, "CIM Discovery Request" },
265 { MLE_CMD_CIM_DISCOVERY_RESPONSE, "CIM Discovery Response" },
266 { MLE_CMD_CIM_ANNOUNCE, "CIM Announce" },
267 { 0, NULL}
270 #define MLE_TLV_SOURCE_ADDRESS 0
271 #define MLE_TLV_MODE 1 /* Modified in Ch04_Mesh Link Establishment */
272 #define MLE_TLV_TIMEOUT 2
273 #define MLE_TLV_CHALLENGE 3
274 #define MLE_TLV_RESPONSE 4
275 #define MLE_TLV_LINK_LAYER_FRAME_COUNTER 5
276 #define MLE_TLV_LINK_QUALITY 6
277 #define MLE_TLV_NETWORK_PARAMETER 7
278 #define MLE_TLV_MLE_FRAME_COUNTER 8
279 #define MLE_TLV_ROUTE64 9 /* Defined in Ch05_Network Layer v1.1-rc1 */
280 #define MLE_TLV_ADDRESS16 10 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
281 #define MLE_TLV_LEADER_DATA 11 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
282 #define MLE_TLV_NETWORK_DATA 12 /* Defined in Ch05_Network Layer v1.1-rc1 */
283 #define MLE_TLV_TLV_REQUEST 13 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
284 #define MLE_TLV_SCAN_MASK 14 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
285 #define MLE_TLV_CONNECTIVITY 15 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
286 #define MLE_TLV_LINK_MARGIN 16 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
287 #define MLE_TLV_STATUS 17 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
288 #define MLE_TLV_VERSION 18 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
289 #define MLE_TLV_ADDRESS_REGISTRATION 19 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
290 #define MLE_TLV_CHANNEL 20 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
291 #define MLE_TLV_PAN_ID 21 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
292 #define MLE_TLV_ACTIVE_TSTAMP 22 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
293 #define MLE_TLV_PENDING_TSTAMP 23 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
294 #define MLE_TLV_ACTIVE_OP_DATASET 24 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
295 #define MLE_TLV_PENDING_OP_DATASET 25 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
296 #define MLE_TLV_THREAD_DISCOVERY 26 /* Defined in Ch04_Mesh Link Establishment v1.1-rc1 */
297 #define MLE_TLV_SUPERVISION_INTERVAL 27 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
298 #define MLE_TLV_CIM_PROVISIONER_INTERFACE_DATA 28 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
299 #define MLE_TLV_CIM_PROVISIONING_DATASET 29 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
300 #define MLE_TLV_CIM_DISCOVERY_REQUEST 30 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
301 #define MLE_TLV_SECURE_DISSEMINATION 31 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
303 #define MLE_TLV_CSL_CHANNEL 80 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
304 #define MLE_TLV_CSL_SYNCHRONIZED_TIMEOUT 85 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
305 #define MLE_TLV_CSL_ACCURACY 86 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
306 #define MLE_TLV_LINK_METRICS_QUERY 87 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
307 #define MLE_TLV_LINK_METRICS_MANAGEMENT 88 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
308 #define MLE_TLV_LINK_METRICS_REPORT 89 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
309 #define MLE_TLV_LINK_PROBE 90 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
312 #define MLE_TLV_CIM_DEVICE_INTERFACE_DATA 27 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
313 #define MLE_TLV_CIM_PROVISIONER_INTERFACE_DATA 28 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
314 #define MLE_TLV_CIM_PROVISIONING_DATASET 29 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
315 #define MLE_TLV_CIM_DISCOVERY_REQUEST 30 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
316 #define MLE_TLV_SECURE_DISSEMINATION 31 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
318 #define MLE_TLV_CSL_CHANNEL 80 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
319 #define MLE_TLV_CSL_SYNCHRONIZED_TIMEOUT 85 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
320 #define MLE_TLV_CSL_ACCURACY 86 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
321 #define MLE_TLV_LINK_METRICS_QUERY 87 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
322 #define MLE_TLV_LINK_METRICS_MANAGEMENT 88 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
323 #define MLE_TLV_LINK_METRICS_REPORT 89 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
324 #define MLE_TLV_LINK_PROBE 90 /* Defined in Ch04_Mesh Link Establishment v1.2-Draft3 */
326 static const value_string mle_tlv_vals[] = {
327 { MLE_TLV_SOURCE_ADDRESS, "Source Address" },
328 { MLE_TLV_MODE, "Mode" },
329 { MLE_TLV_TIMEOUT, "Timeout" },
330 { MLE_TLV_CHALLENGE, "Challenge" },
331 { MLE_TLV_RESPONSE, "Response" },
332 { MLE_TLV_LINK_LAYER_FRAME_COUNTER, "Link Layer Frame Counter"},
333 { MLE_TLV_LINK_QUALITY, "Link Quality"},
334 { MLE_TLV_NETWORK_PARAMETER, "Network Parameter"},
335 { MLE_TLV_MLE_FRAME_COUNTER, "MLE Frame Counter"},
336 { MLE_TLV_ROUTE64, "Route64"},
337 { MLE_TLV_ADDRESS16, "Address16"},
338 { MLE_TLV_LEADER_DATA, "Leader Data"},
339 { MLE_TLV_NETWORK_DATA, "Network Data"},
340 { MLE_TLV_TLV_REQUEST, "TLV Request"},
341 { MLE_TLV_SCAN_MASK, "Scan Mask"},
342 { MLE_TLV_CONNECTIVITY, "Connectivity"},
343 { MLE_TLV_LINK_MARGIN, "Link Margin"},
344 { MLE_TLV_STATUS, "Status"},
345 { MLE_TLV_VERSION, "Version"},
346 { MLE_TLV_ADDRESS_REGISTRATION, "Address Registration"},
347 { MLE_TLV_CHANNEL, "Channel"},
348 { MLE_TLV_PAN_ID, "PAN ID"},
349 { MLE_TLV_ACTIVE_TSTAMP, "Active Timestamp"},
350 { MLE_TLV_PENDING_TSTAMP, "Pending Timestamp"},
351 { MLE_TLV_ACTIVE_OP_DATASET, "Active Operational Dataset"},
352 { MLE_TLV_PENDING_OP_DATASET, "Pending Operational Dataset"},
353 { MLE_TLV_THREAD_DISCOVERY, "Thread Discovery"},
354 { MLE_TLV_SUPERVISION_INTERVAL, "Supervision Interval"},
355 { MLE_TLV_CSL_CHANNEL, "CSL Channel"},
356 { MLE_TLV_CSL_SYNCHRONIZED_TIMEOUT, "CSL Synchronized Timeout"},
357 { MLE_TLV_CSL_ACCURACY, "CSL Accuracy"},
358 { MLE_TLV_LINK_METRICS_QUERY, "Link Metrics Query"},
359 { MLE_TLV_LINK_METRICS_MANAGEMENT, "Link Metrics Management"},
360 { MLE_TLV_LINK_METRICS_REPORT, "Link Metrics Report"},
361 { MLE_TLV_LINK_PROBE, "Link Probe"},
362 { 0, NULL}
365 /*Link Metrics*/
366 #define LINK_METRICS_REPORT_SUB_TLV 0
367 #define LINK_METRICS_QUERY_ID_SUB_TLV 1
368 #define LINK_METRICS_QUERY_OPTIONS_SUB_TLV 2
369 #define FORWARD_PROBING_REGISTRATION_SUB_TLV 3
370 //#define REVERSE_PROBING_REGISTRATION_SUB_TLV 4
371 #define LINK_METRICS_STATUS_SUB_TLV 5
372 //#define LINK_METRICS_TRACKING_CAPABILITIES_SUB_TLV 6
373 #define ENHANCED_ACK_LINK_METRICS_CONFIGURATION_SUB_TLV 7
375 static const value_string mle_tlv_link_param_vals[] = {
376 { LINK_METRICS_REPORT_SUB_TLV, "Links Metrics Report" },
377 { LINK_METRICS_QUERY_ID_SUB_TLV, "Link Metrics Query" },
378 { LINK_METRICS_QUERY_OPTIONS_SUB_TLV, "Link Metrics Query Options" },
379 { FORWARD_PROBING_REGISTRATION_SUB_TLV , "Forward Probing Registration" },
380 { LINK_METRICS_STATUS_SUB_TLV , "Link Metrics Status" },
381 { ENHANCED_ACK_LINK_METRICS_CONFIGURATION_SUB_TLV , "Enhance Ack Link Metrics Configuration" },
382 { 0, NULL}
385 #define LINK_SUCCESS 0
386 #define LINK_FAILURE_CANNOT_SUPPORT_NEW_SERIES_REGISTRATION 1
387 #define LINK_FAILURE_SERIES_ID_ALREADY_REGISTERED 2
388 #define LINK_FAILURE_SERIES_ID_NOT_RECOGNIZED 3
389 #define LINK_FAILURE_NO_MATCHING_FRAMES_RECEIVED 4
390 #define LINK_FAILURE_OTHER_FAILURE 254
392 static const value_string mle_tlv_link_sub_tlv_vals[] = {
393 { LINK_SUCCESS, "Success" },
394 { LINK_FAILURE_CANNOT_SUPPORT_NEW_SERIES_REGISTRATION, " Failure - Cannot Support New Series Registration" },
395 { LINK_FAILURE_SERIES_ID_ALREADY_REGISTERED , "Failure - Series ID Already Registered" },
396 { LINK_FAILURE_SERIES_ID_NOT_RECOGNIZED , "Failure - Series ID not Recognized" },
397 { LINK_FAILURE_NO_MATCHING_FRAMES_RECEIVED , "Failure - No matching frames received" },
398 { LINK_FAILURE_OTHER_FAILURE , "Failure - Other Failure" },
399 { 0, NULL}
402 #define CLEAR_ENHANCED_ACK_LINK_METRICS_CONFIGURATION 0
403 #define REGISTER_ENHANCED_ACK_LINK_METRICS_CONFIGURATION 1
405 static const value_string mle_tlv_link_enh_ack_flags_vals[] = {
406 { CLEAR_ENHANCED_ACK_LINK_METRICS_CONFIGURATION, "Clear Enhanced ACK Link Metrics Configuration" },
407 { REGISTER_ENHANCED_ACK_LINK_METRICS_CONFIGURATION, "Register Enhanced ACK Link Metrics Configuration" },
408 { 0, NULL}
411 /* Link Metrics End*/
413 #define LINK_SUCCESS 0
414 #define LINK_FAILURE_CANNOT_SUPPORT_NEW_SERIES_REGISTRATION 1
415 #define LINK_FAILURE_SERIES_ID_ALREADY_REGISTERED 2
416 #define LINK_FAILURE_SERIES_ID_NOT_RECOGNIZED 3
417 #define LINK_FAILURE_NO_MATCHING_FRAMES_RECEIVED 4
418 #define LINK_FAILURE_OTHER_FAILURE 254
420 #define LQI_FLAGS_C 0x80
421 #define LQI_FLAGS_SIZE 0x0F
423 #define NEIGHBOR_FLAG_I 0x80
424 #define NEIGHBOR_FLAG_O 0x40
425 #define NEIGHBOR_FLAG_P 0x20
427 #define NETWORK_PARAM_ID_CHANNEL 0
428 #define NETWORK_PARAM_ID_PAN_ID 1
429 #define NETWORK_PARAM_ID_PERMIT_JOIN 2
430 #define NETWORK_PARAM_ID_BCN_PAYLOAD 3
432 static const value_string mle_tlv_nwk_param_vals[] = {
433 { NETWORK_PARAM_ID_CHANNEL, "Channel" },
434 { NETWORK_PARAM_ID_PAN_ID, "PAN ID" },
435 { NETWORK_PARAM_ID_PERMIT_JOIN, "Permit Join" },
436 { NETWORK_PARAM_ID_BCN_PAYLOAD, "Beacon Payload" },
437 { 0, NULL}
440 static const true_false_string mle_tlv_mode_device_type = {
441 "FFD",
442 "RFD"
444 static const true_false_string mle_tlv_mode_nwk_data = {
445 "Full",
446 "Stable"
448 static const true_false_string mle_tlv_addr_reg_iid_type = {
449 "Compressed",
450 "Full"
453 #define ROUTE_TBL_OUT_MASK 0xC0
454 #define ROUTE_TBL_IN_MASK 0x30
455 #define ROUTE_TBL_COST_MASK 0x0F
457 #define SCAN_MASK_R_MASK 0x80
458 #define SCAN_MASK_D_MASK 0x40
460 #define CONN_MASK_FLAGS_PP_MASK 0xC0
462 #define ADDR_REG_MASK_IID_TYPE_MASK 0x80
463 #define ADDR_REG_MASK_CID_MASK 0x0F
465 #define MLE_CMD_CINFO_SEC_DATA_REQ 0x04
466 #define MLE_CMD_CINFO_NWK_DATA 0x01
468 /*FUNCTION:------------------------------------------------------
469 * NAME
470 * dissect_mle_decrypt
471 * DESCRIPTION
472 * MLE dissector.
473 * PARAMETERS
474 * tvbuff_t *tvb - IEEE 802.15.4 packet.
475 * packet_info * pinfo - Packet info structure.
476 * unsigned offset - Offset where the ciphertext 'c' starts.
477 * ieee802154_packet *packet - IEEE 802.15.4 packet information.
478 * ws_decrypt_status *status - status of decryption returned through here on failure.
479 * RETURNS
480 * tvbuff_t * - Decrypted payload.
481 *---------------------------------------------------------------
483 static tvbuff_t *
484 dissect_mle_decrypt(tvbuff_t * tvb,
485 unsigned offset,
486 packet_info * pinfo,
487 ieee802154_packet * packet,
488 ieee802154_decrypt_info_t* decrypt_info)
490 tvbuff_t * ptext_tvb;
491 bool have_mic = false;
492 uint64_t srcAddr;
493 unsigned char tmp[16];
494 unsigned M;
495 int captured_len;
496 int reported_len;
498 *decrypt_info->rx_mic_length = 0;
499 memset(decrypt_info->rx_mic, 0, 16);
501 /* Get the captured and on-the-wire length of the payload. */
502 if (packet->security_level > 0) {
503 M = IEEE802154_MIC_LENGTH(packet->security_level);
505 else {
506 M = 0;
509 reported_len = tvb_reported_length_remaining(tvb, offset) - M;
510 if (reported_len < 0) {
511 *decrypt_info->status = DECRYPT_PACKET_TOO_SMALL;
512 return NULL;
514 /* Check if the payload is truncated. */
515 if (tvb_bytes_exist(tvb, offset, reported_len)) {
516 captured_len = reported_len;
518 else {
519 captured_len = tvb_captured_length_remaining(tvb, offset);
522 if (packet->security_level > 0) {
523 /* Check if the MIC is present in the captured data. */
524 have_mic = tvb_bytes_exist(tvb, offset + reported_len, M);
525 if (have_mic) {
526 tvb_memcpy(tvb, decrypt_info->rx_mic, offset + reported_len, M);
530 /*=====================================================
531 * Key Lookup - Need to find the appropriate key.
532 *=====================================================
534 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
535 /* The source EUI-64 is included in the headers. */
536 srcAddr = packet->src64; /* GUINT64_SWAP_LE_BE(packet->src64); */
538 else {
539 /* Lookup failed. */
540 *decrypt_info->status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
541 return NULL;
544 /*=====================================================
545 * CCM* - CTR mode payload encryption
546 *=====================================================
548 /* Create the CCM* initial block for decryption (Adata=0, M=0, counter=0). */
549 ccm_init_block(tmp, false, 0, srcAddr, packet->frame_counter, packet->security_level, 0, NULL);
551 /* Decrypt the ciphertext, and place the plaintext in a new tvb. */
552 if (IEEE802154_IS_ENCRYPTED(packet->security_level) && captured_len) {
553 char *text;
556 * Make a copy of the ciphertext in heap memory.
558 * We will decrypt the message in-place and then use the buffer as the
559 * real data for the new tvb.
561 text = (char *)tvb_memdup(pinfo->pool, tvb, offset, captured_len);
563 /* Perform CTR-mode transformation. Try both the likely key and the alternate key */
564 if (!ccm_ctr_encrypt(decrypt_info->key, tmp, decrypt_info->rx_mic, text, captured_len)) {
565 *decrypt_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
566 return NULL;
569 /* Create a tvbuff for the plaintext. */
570 ptext_tvb = tvb_new_real_data((const uint8_t *)text, captured_len, reported_len);
571 tvb_set_child_real_data_tvbuff(tvb, ptext_tvb);
572 add_new_data_source(pinfo, ptext_tvb, "Decrypted MLE payload");
573 *decrypt_info->status = DECRYPT_PACKET_SUCCEEDED;
575 /* There is no ciphertext. Wrap the plaintext in a new tvb. */
576 else {
577 /* Decrypt the MIC (if present). */
578 if (have_mic) {
579 if (!ccm_ctr_encrypt(decrypt_info->key, tmp, decrypt_info->rx_mic, NULL, 0)) {
580 *decrypt_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
581 return NULL;
585 /* Create a tvbuff for the plaintext. This might result in a zero-length tvbuff. */
586 ptext_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
587 *decrypt_info->status = DECRYPT_PACKET_SUCCEEDED;
590 /*=====================================================
591 * CCM* - CBC-mode message authentication
592 *=====================================================
594 /* We can only verify the message if the MIC wasn't truncated. */
595 if (have_mic) {
596 unsigned char dec_mic[16];
597 unsigned l_m = captured_len;
598 unsigned l_a;
599 uint8_t d_a[256];
601 DISSECTOR_ASSERT(pinfo->src.len == 16);
602 DISSECTOR_ASSERT(pinfo->dst.len == 16);
603 memcpy(d_a, pinfo->src.data, pinfo->src.len);
604 memcpy(d_a+16, pinfo->dst.data, pinfo->dst.len);
606 tvb_memcpy(tvb, d_a+32, decrypt_info->aux_offset, decrypt_info->aux_length);
607 l_a = 32 + decrypt_info->aux_length;
609 /* Adjust the lengths of the plantext and additional data if unencrypted. */
610 if (!IEEE802154_IS_ENCRYPTED(packet->security_level)) {
611 l_a += l_m;
612 l_m = 0;
615 /* Create the CCM* initial block for authentication (Adata!=0, M!=0, counter=l(m)). */
616 ccm_init_block(tmp, true, M, srcAddr, packet->frame_counter, packet->security_level, l_m, NULL);
618 /* Compute CBC-MAC authentication tag. */
620 * And yes, despite the warning in tvbuff.h, I think tvb_get_ptr is the
621 * right function here since either A) the payload wasn't encrypted, in
622 * which case l_m is zero, or B) the payload was encrypted, and the tvb
623 * already points to contiguous memory, since we just allocated it in
624 * decryption phase.
626 if (!ccm_cbc_mac(decrypt_info->key, tmp, d_a, l_a, tvb_get_ptr(ptext_tvb, 0, l_m), l_m, dec_mic)) {
627 *decrypt_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
629 /* Compare the received MIC with the one we generated. */
630 else if (memcmp(decrypt_info->rx_mic, dec_mic, M) != 0) {
631 *decrypt_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
635 *decrypt_info->rx_mic_length = M;
637 /* Done! */
638 return ptext_tvb;
639 } /* dissect_mle_decrypt */
641 void register_mle_key_hash_handler(unsigned hash_identifier, ieee802154_set_key_func key_func)
643 /* Ensure no duplication */
644 DISSECTOR_ASSERT(wmem_tree_lookup32(mle_key_hash_handlers, hash_identifier) == NULL);
646 wmem_tree_insert32(mle_key_hash_handlers, hash_identifier, (void*)key_func);
649 /* Set MLE key function. */
650 static unsigned ieee802154_set_mle_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t *uat_key)
652 ieee802154_set_key_func func = (ieee802154_set_key_func)wmem_tree_lookup32(mle_key_hash_handlers, uat_key->hash_type);
654 if (func != NULL)
655 return func(packet, key, alt_key, uat_key);
657 /* Right now, KEY_HASH_NONE and KEY_HASH_ZIP are not registered because they
658 work with this "default" behavior */
659 if (packet->key_index == uat_key->key_index)
661 memcpy(key, uat_key->key, IEEE802154_CIPHER_SIZE);
662 return 1;
665 return 0;
668 static int
669 dissect_mle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
671 tvbuff_t *volatile payload_tvb = NULL;
672 proto_tree *volatile mle_tree = NULL;
673 proto_item *volatile proto_root = NULL;
675 unsigned offset = 0;
676 unsigned aux_header_offset = 0;
677 ieee802154_decrypt_status status;
679 proto_item *ti;
680 proto_item *mic_item = NULL;
681 proto_tree *header_tree = NULL;
682 uint8_t security_suite;
683 unsigned aux_length = 0;
684 ieee802154_packet *packet;
685 ieee802154_packet *original_packet;
686 ieee802154_decrypt_info_t decrypt_info;
687 ieee802154_hints_t *ieee_hints;
688 bool mic_ok=true;
690 unsigned char rx_mic[16];
691 unsigned int rx_mic_len = 0;
693 uint8_t cmd;
694 uint8_t tlv_type, tlv_len;
695 proto_tree *tlv_tree;
697 ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
698 if (ieee_hints == NULL) {
699 /* For now, MLE only supported with IEEE802.15.4 as an underlying layer */
700 return 0;
702 original_packet = (ieee802154_packet *)ieee_hints->packet;
704 packet = wmem_new0(pinfo->pool, ieee802154_packet);
706 /* Copy IEEE 802.15.4 Source Address */
707 packet->src_addr_mode = original_packet->src_addr_mode;
708 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
709 packet->src64 = original_packet->src64;
710 } else {
711 packet->src16 = original_packet->src16;
714 /* Copy IEEE 802.15.4 Source PAN ID */
715 packet->src_pan = original_packet->src_pan;
717 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MLE");
718 col_clear(pinfo->cinfo, COL_INFO);
720 /* Create the protocol tree. */
721 proto_root = proto_tree_add_item(tree, proto_mle, tvb, 0, tvb_reported_length(tvb), ENC_NA);
722 mle_tree = proto_item_add_subtree(proto_root, ett_mle);
724 /* Parse the security suite field. */
725 /* Security Suite Field */
726 security_suite = tvb_get_uint8(tvb, offset);
727 proto_tree_add_item(mle_tree, hf_mle_security_suite, tvb, offset, 1, ENC_NA);
728 offset++;
730 aux_header_offset = offset;
732 /* Security material present if security suite = 0 */
733 if (security_suite == 0) {
734 dissect_ieee802154_aux_sec_header_and_key(tvb, pinfo, mle_tree, packet, &offset);
735 aux_length = offset-aux_header_offset;
736 } else {
737 packet->security_level = SECURITY_LEVEL_NONE;
740 decrypt_info.key_number = 0;
742 /* Add additional fields for security level > SECURITY_LEVEL_NONE */
743 if (packet->security_level > SECURITY_LEVEL_NONE) {
745 /* Pass to decryption process */
746 decrypt_info.rx_mic = rx_mic;
747 decrypt_info.rx_mic_length = &rx_mic_len;
748 decrypt_info.aux_offset = aux_header_offset;
749 decrypt_info.aux_length = aux_length;
750 decrypt_info.status = &status;
751 decrypt_info.key = NULL; /* payload function will fill that in */
753 payload_tvb = decrypt_ieee802154_payload(tvb, offset, pinfo, header_tree, packet, &decrypt_info,
754 ieee802154_set_mle_key, dissect_mle_decrypt);
755 if (status == DECRYPT_PACKET_MIC_CHECK_FAILED)
756 expert_add_info(pinfo, proto_root, &ei_mle_cbc_mac_failed);
758 /* MIC */
759 if (rx_mic_len) {
760 mic_item = proto_tree_add_bytes(header_tree, hf_mle_mic, tvb, 0, rx_mic_len, rx_mic);
761 proto_item_set_generated(mic_item);
763 } else {
764 status = DECRYPT_NOT_ENCRYPTED;
767 /* Get the unencrypted data if decryption failed. */
768 if (!payload_tvb) {
769 /* Deal with possible truncation and the FCS field at the end. */
770 int reported_len = tvb_reported_length_remaining(tvb, offset);
771 int captured_len = tvb_captured_length_remaining(tvb, offset);
772 if (reported_len < captured_len) captured_len = reported_len;
773 payload_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
776 /* Display the reason for failure, and abort if the error was fatal. */
777 switch (status) {
778 case DECRYPT_PACKET_SUCCEEDED:
779 /* No problem. */
780 proto_item_append_text(mic_item, " [correct (key no. %d)]", decrypt_info.key_number);
781 break;
783 case DECRYPT_PACKET_TOO_SMALL:
784 expert_add_info(pinfo, proto_root, &ei_mle_packet_too_small);
785 call_data_dissector(payload_tvb, pinfo, tree);
786 return tvb_captured_length(tvb);
788 case DECRYPT_PACKET_NO_KEY:
789 expert_add_info(pinfo, proto_root, &ei_mle_no_key);
790 call_data_dissector(payload_tvb, pinfo, tree);
791 return tvb_captured_length(tvb);
793 case DECRYPT_PACKET_DECRYPT_FAILED:
794 expert_add_info(pinfo, proto_root, &ei_mle_decrypt_failed);
795 call_data_dissector(payload_tvb, pinfo, tree);
796 return tvb_captured_length(tvb);
798 case DECRYPT_PACKET_MIC_CHECK_FAILED:
799 expert_add_info(pinfo, proto_root, &ei_mle_mic_check_failed);
800 proto_item_append_text(mic_item, " [incorrect]");
802 * Abort only if the payload was encrypted, in which case we
803 * probably didn't decrypt the packet right (eg: wrong key).
805 if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
806 mic_ok = false;
808 break;
809 case DECRYPT_NOT_ENCRYPTED:
810 default:
811 break;
813 /* This can cause a lot of problems so remove it by default */
814 if (!mic_ok && mle_mic_ok) {
815 call_data_dissector(payload_tvb, pinfo, tree);
816 col_set_str(pinfo->cinfo, COL_INFO, "MIC Failed");
817 return tvb_captured_length(tvb);
820 /***** NEW CODE HERE ****/
821 /* If we're good, carry on and display the MLE payload */
822 offset = 0;
824 /* MLE Command */
825 proto_tree_add_item(mle_tree, hf_mle_command, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
827 cmd = tvb_get_uint8(payload_tvb, offset);
828 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(cmd, mle_command_vals, "Unknown (%x)"));
830 offset++;
832 /* MLE TLVs */
833 while (tvb_offset_exists(payload_tvb, offset)) {
835 /* Get the length ahead of time to pass to next function so we can highlight
836 proper amount of bytes */
837 tlv_len = tvb_get_uint8(payload_tvb, offset+1);
839 ti = proto_tree_add_item(mle_tree, hf_mle_tlv, payload_tvb, offset, tlv_len+2, ENC_NA);
840 tlv_tree = proto_item_add_subtree(ti, ett_mle_tlv);
842 /* Type */
843 proto_tree_add_item(tlv_tree, hf_mle_tlv_type, payload_tvb, offset, 1, ENC_NA);
844 tlv_type = tvb_get_uint8(payload_tvb, offset);
845 offset++;
847 /* Add value name to value root label */
848 proto_item_append_text(ti, " (%s", val_to_str(tlv_type, mle_tlv_vals, "Unknown (%d)"));
850 /* Length */
851 proto_tree_add_item(tlv_tree, hf_mle_tlv_length, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
852 offset++;
854 switch(tlv_type){
855 case MLE_TLV_SOURCE_ADDRESS:
857 bool haveShortTLV = false;
858 uint16_t shortAddr = 0;
860 if (!((tlv_len == 2) || (tlv_len == 8))) {
861 /* TLV Length must be 2 or 8 */
862 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
863 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
864 offset += tlv_len;
865 } else {
866 if (tlv_len == 2) {
867 haveShortTLV = true;
868 shortAddr = tvb_get_ntohs(payload_tvb, offset);
871 proto_tree_add_item(tlv_tree, hf_mle_tlv_source_addr, payload_tvb, offset, tlv_len, ENC_NA);
872 proto_item_append_text(ti, " = ");
873 while (tlv_len) {
874 uint8_t addr;
875 addr = tvb_get_uint8(payload_tvb, offset);
876 proto_item_append_text(ti, "%02x", addr);
877 if (--tlv_len) {
878 proto_item_append_text(ti, ":");
880 offset++;
882 if ((original_packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && haveShortTLV) {
883 /* Source TLV: use this to update src/long mapping */
884 ieee802154_addr_update(&ieee802154_map, shortAddr, original_packet->src_pan, original_packet->src64, pinfo->current_proto, pinfo->fd->num);
887 proto_item_append_text(ti, ")");
889 break;
891 case MLE_TLV_MODE:
892 if (tlv_len == 1) {
893 uint8_t capability;
895 capability = tvb_get_uint8(payload_tvb, offset);
896 proto_item_append_text(ti, " = %02x)", capability);
897 /* Get and display capability info. (blatantly plagiarised from packet-ieee802154.c */
898 proto_tree_add_bits_item(tlv_tree, hf_mle_tlv_mode_reserved1, payload_tvb, (offset * 8) + 0, 4, ENC_NA);//R1
899 proto_tree_add_bits_item(tlv_tree, hf_mle_tlv_mode_receiver_on_idle, payload_tvb, (offset * 8) + 4, 1, ENC_NA);//Receiver
900 proto_tree_add_bits_item(tlv_tree, hf_mle_tlv_mode_reserved2, payload_tvb, (offset * 8) + 5, 1, ENC_NA);//R2
901 proto_tree_add_bits_item(tlv_tree, hf_mle_tlv_mode_device_type_bit, payload_tvb, (offset * 8) +6, 1, ENC_NA);//Device Type
902 proto_tree_add_bits_item(tlv_tree, hf_mle_tlv_mode_network_data, payload_tvb, (offset * 8) +7, 1, ENC_NA);//Network Data
904 else {
905 /* TLV Length must be 1 */
906 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
907 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
909 offset += tlv_len;
910 break;
912 case MLE_TLV_TIMEOUT:
913 if (tlv_len != 4) {
914 /* TLV Length must be 4 */
915 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
916 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
917 } else {
918 uint32_t to_data = 0;
919 proto_tree_add_item_ret_uint(tlv_tree, hf_mle_tlv_timeout, payload_tvb, offset, 4, ENC_BIG_ENDIAN, &to_data);
920 proto_item_append_text(ti, " = %u", to_data);
922 proto_item_append_text(ti, ")");
923 offset += tlv_len;
924 break;
926 case MLE_TLV_CHALLENGE:
927 proto_tree_add_item(tlv_tree, hf_mle_tlv_challenge, payload_tvb, offset, tlv_len, ENC_NA);
928 if (tlv_len) {
929 proto_item_append_text(ti, " = %s)", tvb_bytes_to_str(pinfo->pool, payload_tvb, offset, tlv_len));
931 offset += tlv_len;
932 break;
934 case MLE_TLV_RESPONSE:
935 proto_tree_add_item(tlv_tree, hf_mle_tlv_response, payload_tvb, offset, tlv_len, ENC_NA);
936 if (tlv_len) {
937 proto_item_append_text(ti, " = %s)", tvb_bytes_to_str(pinfo->pool, payload_tvb, offset, tlv_len));
939 offset += tlv_len;
940 break;
942 case MLE_TLV_LINK_LAYER_FRAME_COUNTER:
943 case MLE_TLV_MLE_FRAME_COUNTER:
944 if (tlv_len != 4) {
945 /* TLV Length must be 4 */
946 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
947 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
948 } else {
949 uint32_t cntr;
951 if (tlv_type == MLE_TLV_LINK_LAYER_FRAME_COUNTER) {
952 proto_tree_add_item_ret_uint(tlv_tree, hf_mle_tlv_ll_frm_cntr, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN, &cntr);
953 } else {
954 proto_tree_add_item_ret_uint(tlv_tree, hf_mle_tlv_mle_frm_cntr, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN, &cntr);
956 proto_item_append_text(ti, " = %u", cntr);
958 proto_item_append_text(ti, ")");
959 offset += tlv_len;
960 break;
962 case MLE_TLV_LINK_QUALITY:
964 unsigned numNeighbors;
965 uint8_t size = tvb_get_uint8(payload_tvb, offset) & LQI_FLAGS_SIZE;
966 proto_tree *neig_tree;
967 proto_tree_add_item(tlv_tree, hf_mle_tlv_lqi_c, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
968 proto_tree_add_item(tlv_tree, hf_mle_tlv_lqi_size, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
969 offset++;
971 if ((tlv_len - 1) % (size + 3)) {
972 expert_add_info(pinfo, proto_root, &ei_mle_len_size_mismatch);
973 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
974 numNeighbors = 0;
975 } else {
976 numNeighbors = (tlv_len - 1) / (size + 3);
979 if (numNeighbors == 0) {
980 proto_item_append_text(ti, ")");
981 } else if (numNeighbors == 1) {
982 proto_item_append_text(ti, ": 1 Neighbor)");
983 } else {
984 proto_item_append_text(ti, ": %d Neighbors)", numNeighbors);
987 /* Add subtrees */
989 //Size is off by 1
990 size++;
992 while (numNeighbors) {
993 ti = proto_tree_add_item(tlv_tree, hf_mle_tlv_neighbor, payload_tvb, offset, size+2, ENC_NA);
994 neig_tree = proto_item_add_subtree(ti, ett_mle_neighbor);
996 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_flagI, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
997 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_flagO, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
998 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_flagP, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
999 offset++;
1001 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_idr, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1002 offset++;
1004 proto_tree_add_item(neig_tree, hf_mle_tlv_neighbor_addr, payload_tvb, offset,size, ENC_NA);
1005 offset += size;
1007 numNeighbors--;
1010 break;
1012 case MLE_TLV_NETWORK_PARAMETER:
1014 uint8_t param_id = tvb_get_uint8(payload_tvb, offset);
1016 proto_item_append_text(ti, " = %s)", val_to_str(param_id, mle_tlv_nwk_param_vals, "Unknown (%d)"));
1018 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_param_id, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1019 offset++;
1020 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_delay, payload_tvb, offset, 4, ENC_BIG_ENDIAN);
1021 offset += 4;
1023 switch (param_id) {
1024 case NETWORK_PARAM_ID_CHANNEL:
1025 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_channel, payload_tvb, offset, 2, ENC_BIG_ENDIAN);
1026 offset += 2;
1027 break;
1028 case NETWORK_PARAM_ID_PAN_ID:
1029 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_pan_id, payload_tvb, offset, 2, ENC_BIG_ENDIAN);
1030 offset += 2;
1031 break;
1032 case NETWORK_PARAM_ID_PERMIT_JOIN:
1033 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_pmt_join, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1034 offset++;
1035 break;
1036 case NETWORK_PARAM_ID_BCN_PAYLOAD:
1037 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_bcn_payload, payload_tvb, offset, tlv_len-5, ENC_NA);
1038 offset += tlv_len-5;
1039 break;
1040 default:
1041 proto_tree_add_item(tlv_tree, hf_mle_tlv_network_unknown, payload_tvb, offset, tlv_len-5, ENC_NA);
1042 offset += tlv_len-5;
1043 break;
1046 break;
1048 case MLE_TLV_ROUTE64:
1050 proto_tree *rtr_tree;
1051 unsigned i, j;
1052 uint8_t count;
1053 uint64_t id_mask, test_mask;
1055 proto_item_append_text(ti, ")");
1056 proto_tree_add_item(tlv_tree, hf_mle_tlv_route64_id_seq, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1057 offset++;
1059 /* Count number of table entries */
1060 count = 0;
1061 for (i = 0; i < 8; i++) { /* TODO magic - number of routers/8 */
1062 uint8_t id_mask_octet = tvb_get_uint8(payload_tvb, offset + i);
1063 for (j = 0; j < 8; j++) {
1064 if (id_mask_octet & (1 << j)) {
1065 count++;
1071 * | | | | | | | | | | |1|1|1|1|1|1|...|6|
1072 * |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|...|3|
1073 * ---------------------------------------
1074 * |1|0|1|1|1|0|0|0|1|1|0|0|0|1|0|1|...
1076 * is sent as 0xb8, 0xc5
1077 * and represents table entry for routers 0, 2, 3, 4, 8, 9, 13, 15...
1079 /* Get the ID mask as a 64-bit number (BE) */
1080 id_mask = tvb_get_ntoh64(payload_tvb, offset);
1082 /* Just show the string of octets - best representation for a bit mask */
1083 proto_tree_add_item(tlv_tree, hf_mle_tlv_route64_id_mask, payload_tvb, offset, 8, ENC_NA);
1084 offset += 8;
1086 if (count != (tlv_len - 9))
1088 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1089 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1090 offset += (tlv_len - 9);
1091 } else {
1092 /* Add subtrees */
1093 for (i = 0; i < count; i++) {
1094 /* Find first bit set */
1095 for (j = 0, test_mask = (UINT64_C(1) << 63); test_mask != 1; test_mask >>= 1, j++) {
1096 if (test_mask & id_mask) {
1097 id_mask &= ~test_mask;
1098 break;
1101 ti = proto_tree_add_item(tlv_tree, hf_mle_tlv_route64_entry, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1102 proto_item_append_text(ti, " (%d)", j);
1103 rtr_tree = proto_item_add_subtree(ti, ett_mle_router);
1105 proto_tree_add_item(rtr_tree, hf_mle_tlv_route64_nbr_out, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1106 proto_tree_add_item(rtr_tree, hf_mle_tlv_route64_nbr_in, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1107 proto_tree_add_item(rtr_tree, hf_mle_tlv_route64_cost, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1108 offset++;
1112 break;
1114 case MLE_TLV_ADDRESS16:
1115 if (tlv_len != 2) {
1116 /* TLV Length must be 2 */
1117 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1118 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1119 } else {
1120 uint16_t addr16 = tvb_get_ntohs(payload_tvb, offset);
1121 proto_item_append_text(ti, " = ");
1123 uint8_t a16_len = 2; /* Fix it at 2 */
1124 unsigned stroffset = offset;
1126 while (a16_len) {
1127 uint8_t a16_data;
1128 a16_data = tvb_get_uint8(payload_tvb, stroffset);
1129 proto_item_append_text(ti, "%02x", a16_data);
1130 if (--a16_len) {
1131 proto_item_append_text(ti, ":");
1133 stroffset++;
1136 proto_tree_add_item(tlv_tree, hf_mle_tlv_addr16, payload_tvb, offset, 2, ENC_NA);
1137 if (original_packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1138 /* Allocated Address16 TLV: use this to update dst/long mapping */
1139 ieee802154_addr_update(&ieee802154_map, addr16, original_packet->dst_pan, original_packet->dst64, pinfo->current_proto, pinfo->fd->num);
1142 proto_item_append_text(ti, ")");
1143 offset += tlv_len;
1144 break;
1146 case MLE_TLV_LEADER_DATA:
1147 proto_item_append_text(ti, ")");
1148 if (tlv_len != 8) {
1149 /* TLV Length must be 8 */
1150 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1151 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1152 offset += tlv_len;
1153 } else {
1154 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_partition_id, payload_tvb, offset, 4, ENC_BIG_ENDIAN);
1155 offset += 4;
1156 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_weighting, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1157 offset++;
1158 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_version, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1159 offset++;
1160 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_stable_version, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1161 offset++;
1162 proto_tree_add_item(tlv_tree, hf_mle_tlv_leader_data_router_id, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1163 offset++;
1165 break;
1167 case MLE_TLV_NETWORK_DATA:
1169 tvbuff_t *sub_tvb;
1170 proto_item_append_text(ti, ")");
1171 if (tlv_len > 0) {
1172 sub_tvb = tvb_new_subset_length(payload_tvb, offset, tlv_len);
1173 call_dissector(thread_nwd_handle, sub_tvb, pinfo, tlv_tree);
1175 offset += tlv_len;
1177 break;
1179 case MLE_TLV_ACTIVE_OP_DATASET:
1180 case MLE_TLV_PENDING_OP_DATASET:
1181 case MLE_TLV_THREAD_DISCOVERY:
1183 tvbuff_t *sub_tvb;
1184 proto_item_append_text(ti, ")");
1185 if (tlv_len > 0) {
1186 sub_tvb = tvb_new_subset_length(payload_tvb, offset, tlv_len);
1187 call_dissector(thread_mc_handle, sub_tvb, pinfo, tlv_tree);
1189 offset += tlv_len;
1191 break;
1193 case MLE_TLV_TLV_REQUEST:
1194 proto_item_append_text(ti, ")");
1195 while (tlv_len) {
1196 proto_tree_add_item(tlv_tree, hf_mle_tlv_type, payload_tvb, offset, 1, ENC_NA);
1197 offset++;
1198 tlv_len--;
1200 break;
1202 case MLE_TLV_SCAN_MASK:
1203 if (tlv_len != 1) {
1204 /* TLV Length must be 1 */
1205 proto_item_append_text(ti, ")");
1206 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1207 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1208 } else {
1209 uint8_t mask;
1211 mask = tvb_get_uint8(payload_tvb, offset);
1212 proto_item_append_text(ti, " = %02x)", mask);
1213 proto_tree_add_item(tlv_tree, hf_mle_tlv_scan_mask_r, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1214 proto_tree_add_item(tlv_tree, hf_mle_tlv_scan_mask_e, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1216 offset += tlv_len;
1217 break;
1219 case MLE_TLV_CONNECTIVITY:
1220 proto_item_append_text(ti, ")");
1221 if ((tlv_len == 7) || (tlv_len == 10)) {
1222 proto_tree *fl_tree;
1224 ti = proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_flags, payload_tvb, offset, 1, ENC_NA);
1225 fl_tree = proto_item_add_subtree(ti, ett_mle_conn_flg);
1226 proto_tree_add_item(fl_tree, hf_mle_tlv_conn_flags_pp, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1227 offset++;
1228 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_lq3, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1229 offset++;
1230 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_lq2, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1231 offset++;
1232 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_lq1, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1233 offset++;
1234 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_leader_cost, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1235 offset++;
1236 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_id_seq, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1237 offset++;
1238 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_active_rtrs, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1239 offset++;
1240 if (tlv_len == 10) {
1241 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_sed_buf_size, payload_tvb, offset, 2, ENC_BIG_ENDIAN);
1242 offset += 2;
1243 proto_tree_add_item(tlv_tree, hf_mle_tlv_conn_sed_dgram_cnt, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1244 offset++;
1246 } else {
1247 /* TLV Length must be 7 (old style) or 10 */
1248 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1249 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1250 offset += tlv_len;
1252 break;
1254 case MLE_TLV_LINK_MARGIN:
1255 if (tlv_len != 1) {
1256 /* TLV Length must be 1 */
1257 proto_item_append_text(ti, ")");
1258 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1259 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1260 } else {
1261 uint8_t link_margin;
1263 link_margin = tvb_get_uint8(payload_tvb, offset);
1264 proto_item_append_text(ti, " = %udB)", link_margin);
1265 proto_tree_add_item(tlv_tree, hf_mle_tlv_link_margin, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1267 offset += tlv_len;
1268 break;
1270 case MLE_TLV_STATUS:
1271 if (tlv_len != 1) {
1272 /* TLV Length must be 1 */
1273 proto_item_append_text(ti, ")");
1274 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1275 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1276 } else {
1277 uint8_t stat;
1279 stat = tvb_get_uint8(payload_tvb, offset);
1280 proto_item_append_text(ti, " = %d)", stat);
1281 proto_tree_add_item(tlv_tree, hf_mle_tlv_status, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1283 offset += tlv_len;
1284 break;
1286 case MLE_TLV_VERSION:
1287 if (tlv_len != 2) {
1288 /* TLV Length must be 2 */
1289 proto_item_append_text(ti, ")");
1290 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1291 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1292 } else {
1293 uint16_t version;
1295 version = tvb_get_ntohs(payload_tvb, offset);
1296 proto_item_append_text(ti, " = %d)", version);
1297 proto_tree_add_item(tlv_tree, hf_mle_tlv_version, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1299 offset += tlv_len;
1300 break;
1302 case MLE_TLV_ADDRESS_REGISTRATION:
1304 uint8_t iid_type, i;
1305 uint8_t entries = 0;
1306 int16_t check_len = tlv_len;
1307 unsigned check_offset = offset;
1309 /* Check consistency of entries */
1310 while (check_len > 0) {
1311 uint8_t ar_len;
1313 iid_type = tvb_get_uint8(payload_tvb, check_offset);
1314 if (iid_type & ADDR_REG_MASK_IID_TYPE_MASK) {
1315 ar_len = 9;
1316 } else {
1317 ar_len = 17;
1319 check_offset += ar_len;
1320 check_len -= ar_len;
1321 entries++;
1324 proto_item_append_text(ti, ")");
1325 if (check_len != 0) {
1326 /* Not an integer number of entries */
1327 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1328 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1329 offset += tlv_len;
1330 } else {
1331 for (i = 0; i < entries; i++) {
1332 proto_tree *ar_tree;
1334 ti = proto_tree_add_item(tlv_tree, hf_mle_tlv_addr_reg_entry, payload_tvb, offset, 1, ENC_NA);
1335 ar_tree = proto_item_add_subtree(ti, ett_mle_addr_reg);
1336 iid_type = tvb_get_uint8(payload_tvb, offset);
1337 if (iid_type & ADDR_REG_MASK_IID_TYPE_MASK) {
1338 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_iid_type, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1339 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_cid, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1340 offset++;
1341 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_iid, payload_tvb, offset, 8, ENC_NA);
1342 offset += 8;
1343 } else {
1344 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_iid_type, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1345 offset++;
1346 proto_tree_add_item(ar_tree, hf_mle_tlv_addr_reg_ipv6, payload_tvb, offset, 16, ENC_NA);
1347 offset += 16;
1352 break;
1354 case MLE_TLV_CHANNEL:
1356 proto_item_append_text(ti, ")");
1358 /* Check length is consistent */
1359 if (tlv_len != 3) {
1360 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1361 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1362 } else {
1363 /* Channel page */
1364 proto_tree_add_item(tlv_tree, hf_mle_tlv_channel_page, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1365 /* Channel */
1366 proto_tree_add_item(tlv_tree, hf_mle_tlv_channel, payload_tvb, offset+1, 2, ENC_BIG_ENDIAN);
1368 offset += tlv_len;
1370 break;
1372 case MLE_TLV_PAN_ID:
1374 proto_item_append_text(ti, ")");
1376 /* Check length is consistent */
1377 if (tlv_len != 2) {
1378 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1379 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1380 } else {
1381 /* PAN ID */
1382 proto_tree_add_item(tlv_tree, hf_mle_tlv_pan_id, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1384 offset += tlv_len;
1386 break;
1388 case MLE_TLV_ACTIVE_TSTAMP:
1389 case MLE_TLV_PENDING_TSTAMP:
1391 nstime_t timestamp;
1393 proto_item_append_text(ti, ")");
1395 if (tlv_len != 8) {
1396 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1397 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1398 } else {
1399 /* Fill in the nstime_t structure */
1400 timestamp.secs = (time_t)tvb_get_ntoh48(payload_tvb, offset);
1401 timestamp.nsecs = (int)lround((double)(tvb_get_ntohs(payload_tvb, offset + 6) >> 1) * MLE_32768_TO_NSEC_FACTOR);
1402 if (tlv_type == MLE_TLV_ACTIVE_TSTAMP) {
1403 proto_tree_add_time(tlv_tree, hf_mle_tlv_active_tstamp, payload_tvb, offset, 8, &timestamp);
1404 } else {
1405 proto_tree_add_time(tlv_tree, hf_mle_tlv_pending_tstamp, payload_tvb, offset, 8, &timestamp);
1408 offset += tlv_len;
1410 break;
1412 case MLE_TLV_CSL_CHANNEL:
1414 /* Check length is consistent */
1415 if (tlv_len != 3) {
1416 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1417 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1418 } else {
1419 /* Channel page */
1420 proto_tree_add_item(tlv_tree, hf_mle_tlv_channel_page, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1421 /* Channel */
1422 proto_tree_add_item(tlv_tree, hf_mle_tlv_channel, payload_tvb, offset+1, 2, ENC_BIG_ENDIAN);
1424 offset += tlv_len;
1426 break;
1428 case MLE_TLV_CSL_SYNCHRONIZED_TIMEOUT:/*Defined in Ch04_Mesh Link Establishment v1.2*/
1429 /* Check length is consistent */
1430 if (tlv_len != 4) {
1431 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1432 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1433 } else {
1434 /* CSL synchronized timeout */
1435 uint32_t to_data = 0;
1436 proto_tree_add_item_ret_uint(tlv_tree, hf_mle_tlv_csl_synchronied_timeout, payload_tvb, offset, 4, ENC_BIG_ENDIAN, &to_data);
1437 proto_item_append_text(ti, " = %u", to_data);
1439 proto_item_append_text(ti, ")");
1440 offset += tlv_len;
1441 break;
1442 case MLE_TLV_CSL_ACCURACY:
1443 proto_item_append_text(ti, ")");
1444 if (tlv_len != 2) {
1445 /* TLV Length must be 2 */
1446 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1447 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1448 } else {
1449 proto_tree_add_item(tlv_tree, hf_mle_tlv_csl_clock_accuracy, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1450 offset++;
1451 proto_tree_add_item(tlv_tree, hf_mle_tlv_csl_uncertainty, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1452 offset++;
1454 break;
1455 case MLE_TLV_LINK_METRICS_QUERY:
1456 case MLE_TLV_LINK_METRICS_MANAGEMENT:
1457 case MLE_TLV_LINK_METRICS_REPORT:
1459 proto_item_append_text(ti, ")");
1460 proto_item *sub_item;
1461 proto_tree *sub_tree;
1462 uint8_t metrics_tlv;
1463 while (tvb_offset_exists(payload_tvb, offset)) {
1464 uint8_t sub_tlv = tvb_get_uint8(payload_tvb, offset);
1466 sub_tree = proto_tree_add_subtree(tlv_tree, payload_tvb, offset, -1, 1, &sub_item, "Sub TLV");
1467 sub_item = proto_tree_add_item(sub_tree, hf_mle_tlv_link_sub_tlv, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1468 offset++;
1469 /* Length */
1470 proto_tree_add_item(sub_tree, hf_mle_tlv_length, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1471 uint8_t length_sub_tlv = tvb_get_uint8(payload_tvb,offset);
1472 offset++;
1473 switch (sub_tlv) {
1474 case LINK_METRICS_REPORT_SUB_TLV:
1475 metrics_tlv = tvb_get_uint8(payload_tvb, offset);
1476 /* Type ID Flags */
1477 proto_tree_add_bits_item(sub_tree, hf_mle_tlv_metric_type_id_flags_e, payload_tvb, (offset * 8) + 0, 1, ENC_NA);//E
1478 proto_tree_add_bits_item(sub_tree, hf_mle_tlv_metric_type_id_flags_l, payload_tvb, (offset * 8) + 1, 1, ENC_NA);//L
1479 proto_tree_add_bits_item(sub_tree, hf_mle_tlv_metric_type_id_flags_type, payload_tvb, (offset * 8) + 2, 3, ENC_NA);//Type enum
1480 proto_tree_add_bits_item(sub_tree, hf_mle_tlv_metric_type_id_flags_metric, payload_tvb, (offset * 8) + 5, 3, ENC_NA);//Metric enum
1481 /* Type ID Flags */
1482 offset++;
1483 //latest draft the length is 1 indicates that the extended value is 4 else 1
1484 if((metrics_tlv & 0x40) == 0x40)
1486 sub_item = proto_tree_add_item(sub_tree, hf_mle_tlv_value, payload_tvb, offset, 4, ENC_NA);
1487 offset+=4;
1489 else
1491 sub_item = proto_tree_add_item(sub_tree, hf_mle_tlv_value, payload_tvb, offset, 1, ENC_NA);
1492 offset++;
1494 break;
1495 case LINK_METRICS_QUERY_ID_SUB_TLV:
1496 /* Query ID */
1497 proto_tree_add_item(sub_tree, hf_mle_tlv_query_id, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1498 offset++;
1499 break;
1500 case LINK_METRICS_QUERY_OPTIONS_SUB_TLV:
1501 proto_tree_add_item(sub_tree, hf_mle_tlv_link_query_options, payload_tvb, offset, length_sub_tlv, ENC_NA);
1502 offset+= length_sub_tlv;
1503 break;
1504 case FORWARD_PROBING_REGISTRATION_SUB_TLV:
1505 proto_tree_add_item(sub_tree, hf_mle_tlv_link_forward_series, payload_tvb, offset, 1, ENC_NA);
1506 offset++;
1507 proto_tree_add_item(sub_tree, hf_mle_tlv_link_forward_series_flags, payload_tvb, offset, 1, ENC_NA);
1508 uint8_t forward_series_flag = tvb_get_uint8(payload_tvb, offset);
1509 offset++;
1510 if (forward_series_flag > 0)
1512 proto_tree_add_bits_item(sub_tree, hf_mle_tlv_metric_type_id_flags_e, payload_tvb, (offset * 8) + 0, 1, ENC_NA);//Receiver
1513 proto_tree_add_bits_item(sub_tree, hf_mle_tlv_metric_type_id_flags_l, payload_tvb, (offset * 8) + 1, 1, ENC_NA);//Receiver
1514 proto_tree_add_bits_item(sub_tree, hf_mle_tlv_metric_type_id_flags_type, payload_tvb, (offset * 8) + 2, 3, ENC_NA);//Receiver
1515 proto_tree_add_bits_item(sub_tree, hf_mle_tlv_metric_type_id_flags_metric, payload_tvb, (offset * 8) + 5, 3, ENC_NA);//Receiver
1516 offset+=1;
1518 break;
1519 case LINK_METRICS_STATUS_SUB_TLV:
1520 proto_tree_add_item(sub_tree, hf_mle_tlv_link_status_sub_tlv, payload_tvb, offset, 1, ENC_NA);
1521 offset++;
1522 break;
1523 case ENHANCED_ACK_LINK_METRICS_CONFIGURATION_SUB_TLV:
1524 if(length_sub_tlv == 1)
1526 sub_item = proto_tree_add_item(sub_tree, hf_mle_tlv_link_enh_ack_flags, payload_tvb, offset, 1, ENC_NA);
1528 else
1530 sub_item = proto_tree_add_item(sub_tree, hf_mle_tlv_link_enh_ack_flags, payload_tvb, offset, 1, ENC_NA);
1531 sub_item = proto_tree_add_item(sub_tree, hf_mle_tlv_link_requested_type_id_flags, payload_tvb, offset+1, (length_sub_tlv-1), ENC_NA);
1533 offset+= length_sub_tlv;
1534 break;
1538 break;
1539 case MLE_TLV_LINK_PROBE:
1541 proto_item_append_text(ti, ")");
1542 proto_tree_add_item(tlv_tree, hf_mle_tlv_link_status, payload_tvb, offset, 1, ENC_BIG_ENDIAN);
1543 offset++;
1545 break;
1546 case MLE_TLV_SUPERVISION_INTERVAL:
1547 if (tlv_len != 2) {
1548 /* TLV Length must be 2 */
1549 proto_item_append_text(ti, ")");
1550 expert_add_info(pinfo, proto_root, &ei_mle_tlv_length_failed);
1551 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1553 else {
1554 uint16_t interval;
1556 interval = tvb_get_ntohs(payload_tvb, offset);
1557 proto_item_append_text(ti, " = %d)", interval);
1558 proto_tree_add_item(tlv_tree, hf_mle_tlv_supervision_interval, payload_tvb, offset, tlv_len, ENC_BIG_ENDIAN);
1560 offset += tlv_len;
1561 break;
1562 case MLE_TLV_CIM_PROVISIONER_INTERFACE_DATA:
1563 case MLE_TLV_CIM_PROVISIONING_DATASET:
1564 case MLE_TLV_CIM_DISCOVERY_REQUEST:
1565 case MLE_TLV_SECURE_DISSEMINATION:
1567 default:
1568 proto_item_append_text(ti, ")");
1569 proto_tree_add_item(tlv_tree, hf_mle_tlv_unknown, payload_tvb, offset, tlv_len, ENC_NA);
1570 offset += tlv_len;
1574 return tvb_captured_length(tvb);
1577 void
1578 proto_register_mle(void)
1580 static hf_register_info hf[] = {
1582 /* Auxiliary Security Header Fields */
1583 /*----------------------------------*/
1584 { &hf_mle_security_suite,
1585 { "Security Suite",
1586 "mle.sec_suite",
1587 FT_UINT8, BASE_HEX, VALS(mle_sec_suite_names), 0x0,
1588 "The Security Suite of the frame",
1589 HFILL
1592 { &hf_mle_mic,
1593 { "Decrypted MIC",
1594 "mle.mic",
1595 FT_BYTES, BASE_NONE, NULL, 0x0,
1596 "The decrypted MIC",
1597 HFILL
1600 /*MLE Command*/
1601 { &hf_mle_command,
1602 { "Command",
1603 "mle.cmd",
1604 FT_UINT8, BASE_DEC, VALS(mle_command_vals), 0x0,
1605 "MLE command type",
1606 HFILL
1609 /* Generic TLV */
1610 { &hf_mle_tlv,
1611 { "TLV",
1612 "mle.tlv",
1613 FT_NONE, BASE_NONE, NULL, 0x0,
1614 "Type-Length-Value",
1615 HFILL
1618 { &hf_mle_tlv_type,
1619 { "Type",
1620 "mle.tlv.type",
1621 FT_UINT8, BASE_DEC, VALS(mle_tlv_vals), 0x0,
1622 "Type of value",
1623 HFILL
1626 { &hf_mle_tlv_length,
1627 { "Length",
1628 "mle.tlv.len",
1629 FT_UINT8, BASE_DEC, NULL, 0x0,
1630 "Length of value",
1631 HFILL
1634 /* Type-Specific TLV Fields */
1635 { &hf_mle_tlv_source_addr,
1636 { "Address",
1637 "mle.tlv.source_addr",
1638 FT_BYTES, BASE_NONE, NULL, 0x0,
1639 "Source address",
1640 HFILL
1643 /* Capability Information Fields */
1644 { &hf_mle_tlv_mode_nwk_data,
1645 { "Network Data",
1646 "mle.tlv.mode.nwk_data",
1647 FT_BOOLEAN, 8, TFS(&mle_tlv_mode_nwk_data), MLE_CMD_CINFO_NWK_DATA,
1648 NULL,
1649 HFILL
1652 { &hf_mle_tlv_mode_device_type,
1653 { "Device Type",
1654 "mle.tlv.mode.device_type",
1655 FT_BOOLEAN, 8, TFS(&mle_tlv_mode_device_type), IEEE802154_CMD_CINFO_DEVICE_TYPE,
1656 NULL,
1657 HFILL
1660 { &hf_mle_tlv_mode_sec_data_req,
1661 { "Secure Data Requests",
1662 "mle.tlv.mode.sec_data_req",
1663 FT_BOOLEAN, 8, NULL, MLE_CMD_CINFO_SEC_DATA_REQ,
1664 NULL,
1665 HFILL
1668 { &hf_mle_tlv_mode_receiver_on_idle,
1669 { "R(Receiver/rx)-on-idle",
1670 "mle.tlv.mode.receiver_on_idle",
1671 FT_UINT8, BASE_HEX, NULL, 0x0,
1672 NULL,
1673 HFILL
1676 { &hf_mle_tlv_mode_reserved1,
1677 { "R1(Reserved)",
1678 "mle.tlv.mode.reserved1",
1679 FT_UINT8, BASE_HEX, NULL, 0x0,
1680 NULL,
1681 HFILL
1684 { &hf_mle_tlv_mode_reserved2,
1685 { "R2(Reserved)",
1686 "mle.tlv.mode.reserved2",
1687 FT_UINT8, BASE_HEX, NULL, 0x0,
1688 NULL,
1689 HFILL
1692 { &hf_mle_tlv_mode_device_type_bit,
1693 { "D(Device Type)",
1694 "mle.tlv.mode.device_type_bit",
1695 FT_UINT8, BASE_HEX, NULL, 0x0,
1696 NULL,
1697 HFILL
1700 { &hf_mle_tlv_mode_network_data,
1701 { "N(Network Data)",
1702 "mle.tlv.mode.network_data",
1703 FT_UINT8, BASE_HEX, NULL, 0x0,
1704 NULL,
1705 HFILL
1708 { &hf_mle_tlv_mode_idle_rx,
1709 { "Receive On When Idle",
1710 "mle.tlv.mode.idle_rx",
1711 FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_IDLE_RX,
1712 NULL,
1713 HFILL
1716 { &hf_mle_tlv_timeout,
1717 { "Timeout",
1718 "mle.tlv.timeout",
1719 FT_UINT32, BASE_DEC, NULL, 0x0,
1720 "Expected interval between transmissions in seconds",
1721 HFILL
1724 { &hf_mle_tlv_challenge,
1725 { "Challenge",
1726 "mle.tlv.challenge",
1727 FT_BYTES, BASE_NONE, NULL, 0x0,
1728 "Challenge to be echoed back",
1729 HFILL
1732 { &hf_mle_tlv_response,
1733 { "Response",
1734 "mle.tlv.response",
1735 FT_BYTES, BASE_NONE, NULL, 0x0,
1736 "Response to a challenge",
1737 HFILL
1740 { &hf_mle_tlv_ll_frm_cntr,
1741 { "Link Layer Frame Counter",
1742 "mle.tlv.ll_frm_cntr",
1743 FT_UINT32, BASE_DEC, NULL, 0x0,
1744 "The Link layer frame counter",
1745 HFILL
1748 { &hf_mle_tlv_mle_frm_cntr,
1749 { "MLE Frame Counter",
1750 "mle.tlv.mle_frm_cntr",
1751 FT_UINT32, BASE_DEC, NULL, 0x0,
1752 "The MLE frame counter",
1753 HFILL
1756 { &hf_mle_tlv_unknown,
1757 { "Unknown",
1758 "mle.tlv.unknown",
1759 FT_BYTES, BASE_NONE, NULL, 0x0,
1760 "Unknown TLV, raw value",
1761 HFILL
1764 { &hf_mle_tlv_lqi_c,
1765 { "Complete Flag",
1766 "mle.tlv.lqi.complete",
1767 FT_BOOLEAN, 8, NULL, LQI_FLAGS_C,
1768 NULL,
1769 HFILL
1772 { &hf_mle_tlv_lqi_size,
1773 { "Address Size",
1774 "mle.tlv.lqi.size",
1775 FT_UINT8, BASE_DEC, NULL, LQI_FLAGS_SIZE,
1776 NULL,
1777 HFILL
1780 { &hf_mle_tlv_neighbor,
1781 { "Neighbor Record",
1782 "mle.tlv.neighbor",
1783 FT_NONE, BASE_NONE, NULL, 0x0,
1784 NULL,
1785 HFILL
1788 { &hf_mle_tlv_neighbor_flagI,
1789 { "Incoming",
1790 "mle.tlv.neighbor.flagI",
1791 FT_BOOLEAN, 8, NULL, NEIGHBOR_FLAG_I,
1792 "Set if the sender has configured its link with this neighbor and will accept incoming messages from them.",
1793 HFILL
1796 { &hf_mle_tlv_neighbor_flagO,
1797 { "Outgoing",
1798 "mle.tlv.neighbor.flagO",
1799 FT_BOOLEAN, 8, NULL, NEIGHBOR_FLAG_O,
1800 "Set if the sender believes that the neighbor has configured its link with the sender and will accept incoming messages from the sender.",
1801 HFILL
1804 { &hf_mle_tlv_neighbor_flagP,
1805 { "Priority",
1806 "mle.tlv.neighbor.flagP",
1807 FT_BOOLEAN, 8, NULL, NEIGHBOR_FLAG_P,
1808 "Set if the sender expects to use this link for sending messages to this neighbor.",
1809 HFILL
1812 { &hf_mle_tlv_neighbor_idr,
1813 { "Inverse Delivery Ratio",
1814 "mle.tlv.neighbor.idr",
1815 FT_UINT8, BASE_DEC, NULL, 0x0,
1816 NULL,
1817 HFILL
1820 { &hf_mle_tlv_neighbor_addr,
1821 { "Address",
1822 "mle.tlv.neighbor.addr",
1823 FT_BYTES, BASE_NONE, NULL, 0x0,
1824 NULL,
1825 HFILL
1828 { &hf_mle_tlv_network_param_id,
1829 { "Parameter ID",
1830 "mle.tlv.network.param_id",
1831 FT_UINT8, BASE_DEC, NULL, 0x0,
1832 NULL,
1833 HFILL
1836 { &hf_mle_tlv_network_delay,
1837 { "Delay",
1838 "mle.tlv.network.delay",
1839 FT_UINT32, BASE_DEC, NULL, 0x0,
1840 NULL,
1841 HFILL
1844 { &hf_mle_tlv_network_channel,
1845 { "Channel",
1846 "mle.tlv.network.channel",
1847 FT_UINT16, BASE_DEC, NULL, 0x0,
1848 NULL,
1849 HFILL
1852 { &hf_mle_tlv_network_pan_id,
1853 { "PAN ID",
1854 "mle.tlv.network.pan_id",
1855 FT_UINT16, BASE_HEX, NULL, 0x0,
1856 NULL,
1857 HFILL
1860 { &hf_mle_tlv_network_pmt_join,
1861 { "Permit Join",
1862 "mle.tlv.network.pmt_join",
1863 FT_BOOLEAN, 8, NULL, 0x1,
1864 NULL,
1865 HFILL
1868 { &hf_mle_tlv_network_bcn_payload,
1869 { "Beacon Payload",
1870 "mle.tlv.network.bcn_payload",
1871 FT_BYTES, BASE_NONE, NULL, 0x0,
1872 NULL,
1873 HFILL
1876 { &hf_mle_tlv_route64_id_seq,
1877 { "ID Sequence",
1878 "mle.tlv.route64.id_seq",
1879 FT_UINT8, BASE_DEC, NULL, 0x0,
1880 NULL,
1881 HFILL
1884 { &hf_mle_tlv_route64_id_mask,
1885 { "Assigned Router ID Mask",
1886 "mle.tlv.route64.id_mask",
1887 FT_BYTES, BASE_NONE, NULL, 0x0,
1888 NULL,
1889 HFILL
1892 { &hf_mle_tlv_route64_entry,
1893 { "Routing Table Entry",
1894 "mle.tlv.route64",
1895 FT_UINT8, BASE_HEX, NULL, 0x0,
1896 NULL,
1897 HFILL
1900 { &hf_mle_tlv_route64_nbr_out,
1901 { "Neighbor Out Link Quality",
1902 "mle.tlv.route64.nbr_out",
1903 FT_UINT8, BASE_DEC, NULL, ROUTE_TBL_OUT_MASK,
1904 NULL,
1905 HFILL
1908 { &hf_mle_tlv_route64_nbr_in,
1909 { "Neighbor In Link Quality",
1910 "mle.tlv.route64.nbr_in",
1911 FT_UINT8, BASE_DEC, NULL, ROUTE_TBL_IN_MASK,
1912 NULL,
1913 HFILL
1916 { &hf_mle_tlv_route64_cost,
1917 { "Router Cost",
1918 "mle.tlv.route64.cost",
1919 FT_UINT8, BASE_DEC, NULL, ROUTE_TBL_COST_MASK,
1920 NULL,
1921 HFILL
1924 #if 0
1925 { &hf_mle_tlv_route64_unknown,
1926 { "(unknown)",
1927 "mle.tlv.route64.unknown",
1928 FT_BYTES, BASE_NONE, NULL, 0x0,
1929 NULL,
1930 HFILL
1933 #endif
1934 { &hf_mle_tlv_metric_type_id_flags_l,
1935 { "L",
1936 "mle.tlv.metric_type_id_flags.l",
1937 FT_UINT8, BASE_HEX, NULL, 0x0,
1938 NULL,
1939 HFILL
1942 { &hf_mle_tlv_metric_type_id_flags_e,
1943 { "E",
1944 "mle.tlv.metric_type_id_flags.e",
1945 FT_UINT8, BASE_HEX, NULL, 0x0,
1946 NULL,
1947 HFILL
1950 { &hf_mle_tlv_metric_type_id_flags_type,
1951 { "Type/average enum",
1952 "mle.tlv.metric_type_id_flags.type",
1953 FT_UINT8, BASE_HEX, NULL, 0x0,
1954 NULL,
1955 HFILL
1958 { &hf_mle_tlv_metric_type_id_flags_metric,
1959 { "Metric enum",
1960 "mle.tlv.metric_type_id_flags.metric",
1961 FT_UINT8, BASE_HEX, NULL, 0x0,
1962 NULL,
1963 HFILL
1966 { &hf_mle_tlv_addr16,
1967 { "Address16",
1968 "mle.tlv.addr16",
1969 FT_BYTES, BASE_NONE, NULL, 0x0,
1970 NULL,
1971 HFILL
1974 { &hf_mle_tlv_leader_data_partition_id,
1975 { "Partition ID",
1976 "mle.tlv.leader_data.partition_id",
1977 FT_UINT32, BASE_HEX, NULL, 0x0,
1978 NULL,
1979 HFILL
1982 { &hf_mle_tlv_leader_data_weighting,
1983 { "Weighting",
1984 "mle.tlv.leader_data.weighting",
1985 FT_UINT8, BASE_DEC, NULL, 0x0,
1986 NULL,
1987 HFILL
1990 { &hf_mle_tlv_leader_data_version,
1991 { "Data Version",
1992 "mle.tlv.leader_data.data_version",
1993 FT_UINT8, BASE_DEC, NULL, 0x0,
1994 NULL,
1995 HFILL
1998 { &hf_mle_tlv_leader_data_stable_version,
1999 { "Stable Data Version",
2000 "mle.tlv.leader_data.stable_data_version",
2001 FT_UINT8, BASE_DEC, NULL, 0x0,
2002 NULL,
2003 HFILL
2006 { &hf_mle_tlv_leader_data_router_id,
2007 { "Leader Router ID",
2008 "mle.tlv.leader_data.router_id",
2009 FT_UINT8, BASE_DEC, NULL, 0x0,
2010 NULL,
2011 HFILL
2014 #if 0
2015 { &hf_mle_tlv_network_data,
2016 { "Network Data",
2017 "mle.tlv.network_data",
2018 FT_BYTES, BASE_NONE, NULL, 0x0,
2019 "Network data (opaque data)",
2020 HFILL
2023 #endif
2024 { &hf_mle_tlv_scan_mask_r,
2025 { "Router",
2026 "mle.tlv.scan_mask.r",
2027 FT_BOOLEAN, 8, NULL, SCAN_MASK_R_MASK,
2028 NULL,
2029 HFILL
2032 { &hf_mle_tlv_scan_mask_e,
2033 { "End Device",
2034 "mle.tlv.scan_mask.e",
2035 FT_BOOLEAN, 8, NULL, SCAN_MASK_D_MASK,
2036 NULL,
2037 HFILL
2040 { &hf_mle_tlv_conn_flags,
2041 { "Flags",
2042 "mle.tlv.conn.flags",
2043 FT_NONE, BASE_NONE, NULL, 0x0,
2044 NULL,
2045 HFILL
2048 { &hf_mle_tlv_conn_flags_pp,
2049 { "Parent Priority",
2050 "mle.tlv.conn.flags.pp",
2051 FT_INT8, BASE_DEC, VALS(mle_conn_tlv_flags_pp_enums), CONN_MASK_FLAGS_PP_MASK,
2052 NULL,
2053 HFILL
2056 { &hf_mle_tlv_conn_lq3,
2057 { "Link Quality 3",
2058 "mle.tlv.conn.lq3",
2059 FT_UINT8, BASE_DEC, NULL, 0x0,
2060 NULL,
2061 HFILL
2064 { &hf_mle_tlv_conn_lq2,
2065 { "Link Quality 2",
2066 "mle.tlv.conn.lq2",
2067 FT_UINT8, BASE_DEC, NULL, 0x0,
2068 NULL,
2069 HFILL
2072 { &hf_mle_tlv_conn_lq1,
2073 { "Link Quality 1",
2074 "mle.tlv.conn.lq1",
2075 FT_UINT8, BASE_DEC, NULL, 0x0,
2076 NULL,
2077 HFILL
2080 { &hf_mle_tlv_conn_leader_cost,
2081 { "Leader Cost",
2082 "mle.tlv.conn.leader_cost",
2083 FT_UINT8, BASE_DEC, NULL, 0x0,
2084 NULL,
2085 HFILL
2088 { &hf_mle_tlv_conn_id_seq,
2089 { "ID Sequence",
2090 "mle.tlv.conn.id_seq",
2091 FT_UINT8, BASE_DEC, NULL, 0x0,
2092 NULL,
2093 HFILL
2096 { &hf_mle_tlv_conn_active_rtrs,
2097 { "Active Routers",
2098 "mle.tlv.conn.active_rtrs",
2099 FT_UINT8, BASE_DEC, NULL, 0x0,
2100 NULL,
2101 HFILL
2104 { &hf_mle_tlv_conn_sed_buf_size,
2105 { "SED Buffer Size",
2106 "mle.tlv.conn.sed_buf_size",
2107 FT_UINT16, BASE_DEC, NULL, 0x0,
2108 NULL,
2109 HFILL
2112 { &hf_mle_tlv_conn_sed_dgram_cnt,
2113 { "SED Datagram Count",
2114 "mle.tlv.conn.sed_dgram_cnt",
2115 FT_UINT8, BASE_DEC, NULL, 0x0,
2116 NULL,
2117 HFILL
2120 { &hf_mle_tlv_link_margin,
2121 { "Link Margin",
2122 "mle.tlv.link_margin",
2123 FT_UINT8, BASE_DEC, NULL, 0,
2124 "Link margin in dB",
2125 HFILL
2128 { &hf_mle_tlv_status,
2129 { "Status",
2130 "mle.tlv.status",
2131 FT_UINT8, BASE_DEC, VALS(mle_status_tlv_enums), 0,
2132 NULL,
2133 HFILL
2136 { &hf_mle_tlv_version,
2137 { "Version",
2138 "mle.tlv.version",
2139 FT_UINT16, BASE_DEC, NULL, 0,
2140 NULL,
2141 HFILL
2144 { &hf_mle_tlv_supervision_interval,
2145 { "Supervision Interval",
2146 "mle.tlv.supervision_interval",
2147 FT_UINT16, BASE_DEC, NULL, 0,
2148 NULL,
2149 HFILL
2152 { &hf_mle_tlv_addr_reg_entry,
2153 { "Address Registration Entry",
2154 "mle.tlv.addr_reg",
2155 FT_NONE, BASE_NONE, NULL, 0x0,
2156 NULL,
2157 HFILL
2160 { &hf_mle_tlv_addr_reg_iid_type,
2161 { "IID type",
2162 "mle.tlv.addr_reg_iid_type",
2163 FT_BOOLEAN, 8, TFS(&mle_tlv_addr_reg_iid_type), ADDR_REG_MASK_IID_TYPE_MASK,
2164 "Context ID",
2165 HFILL
2168 { &hf_mle_tlv_addr_reg_cid,
2169 { "Context ID",
2170 "mle.tlv.addr_reg_cid",
2171 FT_UINT8, BASE_DEC, NULL, ADDR_REG_MASK_CID_MASK,
2172 "6LoWPAN Context ID",
2173 HFILL
2176 { &hf_mle_tlv_addr_reg_iid,
2177 { "IID",
2178 "mle.tlv.addr_reg_iid",
2179 FT_BYTES, BASE_NONE, NULL, 0x0,
2180 "Interface identifier",
2181 HFILL
2184 { &hf_mle_tlv_addr_reg_ipv6,
2185 { "IPv6 Address",
2186 "mle.tlv.addr_reg_ipv6",
2187 FT_IPv6, BASE_NONE, NULL, 0x0,
2188 "IID",
2189 HFILL
2192 #if 0
2193 { &hf_mle_tlv_hold_time,
2194 { "Hold Time",
2195 "mle.tlv.hold_time",
2196 FT_UINT16, BASE_DEC, NULL, 0,
2197 NULL,
2198 HFILL
2201 #endif
2202 { &hf_mle_tlv_network_unknown,
2203 { "(unknown)",
2204 "mle.tlv.network.unknown",
2205 FT_BYTES, BASE_NONE, NULL, 0x0,
2206 NULL,
2207 HFILL
2210 { &hf_mle_tlv_channel_page,
2211 { "Channel Page",
2212 "mle.tlv.channel_page",
2213 FT_UINT8, BASE_DEC, NULL, 0x0,
2214 NULL,
2215 HFILL
2218 { &hf_mle_tlv_channel,
2219 { "Channel",
2220 "mle.tlv.channel",
2221 FT_UINT16, BASE_DEC, NULL, 0x0,
2222 NULL,
2223 HFILL
2226 { &hf_mle_tlv_csl_accuracy,
2227 { "CSL Accuracy",
2228 "mle.tlv.csl_accuracy",
2229 FT_UINT8, BASE_DEC, NULL, 0x0,
2230 NULL,
2231 HFILL
2234 { &hf_mle_tlv_csl_clock_accuracy,
2235 { "CSL Clock Accuracy",
2236 "mle.tlv.csl_clock_accuracy",
2237 FT_UINT8, BASE_DEC, NULL, 0x0,
2238 NULL,
2239 HFILL
2242 { &hf_mle_tlv_csl_uncertainty,
2243 { "CSL Uncertainty",
2244 "mle.tlv.csl_uncertainty",
2245 FT_UINT8, BASE_DEC, NULL, 0x0,
2246 NULL,
2247 HFILL
2250 { &hf_mle_tlv_pan_id,
2251 { "PAN ID",
2252 "mle.tlv.pan_id",
2253 FT_UINT16, BASE_HEX, NULL, 0x0,
2254 NULL,
2255 HFILL
2258 { &hf_mle_tlv_active_tstamp,
2259 { "Active Timestamp",
2260 "mle.tlv.active_tstamp",
2261 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2262 NULL,
2263 HFILL
2266 { &hf_mle_tlv_pending_tstamp,
2267 { "Pending Timestamp",
2268 "mle.tlv.pending_tstamp",
2269 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2270 NULL,
2271 HFILL
2274 #if 0
2275 { &hf_mle_tlv_active_op_dataset,
2276 { "Active Operational Dataset",
2277 "mle.tlv.active_op_dataset",
2278 FT_BYTES, BASE_NONE, NULL, 0x0,
2279 "Thread Active Operational Dataset",
2280 HFILL
2283 { &hf_mle_tlv_pending_op_dataset,
2284 { "Pending Operational Dataset",
2285 "mle.tlv.pending_op_dataset",
2286 FT_BYTES, BASE_NONE, NULL, 0x0,
2287 "Thread Pending Operational Dataset",
2288 HFILL
2291 #endif
2292 { &hf_mle_tlv_link_query_options,
2293 { "Link Query options",
2294 "mle.tlv.link_query_options",
2295 FT_BYTES, BASE_NONE, NULL, 0x0,
2296 "Link Sub TLV",
2297 HFILL
2300 { &hf_mle_tlv_csl_sychronized_timeout,
2301 { "CSL Synchronized Timeout",
2302 "mle.tlv.link_csl_synchronized_timeout",
2303 FT_UINT32, BASE_HEX, NULL, 0x0,
2304 "Thread CSL Synchronized Timeout",
2305 HFILL
2308 { &hf_mle_tlv_link_enh_ack_flags,
2309 { "Enh-ACK Flags",
2310 "mle.tlv.link_enh_ack_flags",
2311 FT_UINT8, BASE_DEC, VALS(mle_tlv_link_enh_ack_flags_vals), 0x0,
2312 "Thread Enh-ACK Flags",
2313 HFILL
2316 { &hf_mle_tlv_link_requested_type_id_flags,
2317 { "Requested Type ID flags",
2318 "mle.tlv.link_requested_type_id_flags",
2319 FT_BYTES, BASE_NONE, NULL, 0x0,
2320 "Thread Requested Type ID flags",
2321 HFILL
2324 { &hf_mle_tlv_link_forward_series,
2325 { "Link Forward Series",
2326 "mle.tlv.link_forward_series",
2327 FT_UINT8, BASE_DEC, NULL, 0x0,
2328 "Link Sub TLV",
2329 HFILL
2332 { &hf_mle_tlv_link_forward_series_flags,
2333 { "Link Forward Series Flags",
2334 "mle.tlv.link_forward_series_flags",
2335 FT_UINT8, BASE_DEC, NULL, 0x0,
2336 "Link Sub TLV",
2337 HFILL
2340 { &hf_mle_tlv_link_timeout,
2341 { "Link Timeout",
2342 "mle.tlv.link_timeout",
2343 FT_UINT8, BASE_DEC, NULL, 0x0,
2344 "Link Sub TLV",
2345 HFILL
2348 { &hf_mle_tlv_link_concatenation_link_metric_typeid_flags,
2349 { "Concatenation of Link Metric Type ID Flags",
2350 "mle.tlv.link_concatenation_link_metric_typeid_flags",
2351 FT_UINT8, BASE_DEC, NULL, 0x0,
2352 "Link Sub TLV",
2353 HFILL
2356 { &hf_mle_tlv_link_status,
2357 { "Link Status",
2358 "mle.tlv.link_status",
2359 FT_UINT8, BASE_DEC, VALS(mle_tlv_link_param_vals), 0x0,
2360 "Link Sub TLV",
2361 HFILL
2364 { &hf_mle_tlv_link_status_sub_tlv,
2365 { "Link Sub TLV Status",
2366 "mle.tlv.link_status_sub_tlv",
2367 FT_UINT8, BASE_DEC, VALS(mle_tlv_link_sub_tlv_vals), 0x0,
2368 "Thread Link Sub TLV Status",
2369 HFILL
2372 { &hf_mle_tlv_link_sub_tlv,
2373 { "Link Metrics Sub TLV",
2374 "mle.tlv.link_sub_tlv",
2375 FT_UINT8, BASE_DEC, VALS(mle_tlv_link_param_vals), 0x0,
2376 NULL,
2377 HFILL
2380 { &hf_mle_tlv_metric_type_id_flags,
2381 { "Metric Type ID Flags",
2382 "mle.tlv.metric_type_id_flags",
2383 FT_BYTES, BASE_NONE, NULL, 0x0,
2384 "Thread Metric Type ID Flags",
2385 HFILL
2388 { &hf_mle_tlv_value,
2389 { "Value",
2390 "mle.tlv.value",
2391 FT_BYTES, BASE_NONE, NULL, 0x0,
2392 "Thread Value",
2393 HFILL
2396 { &hf_mle_tlv_query_id,
2397 { "Query ID",
2398 "mle.tlv.query_id",
2399 FT_UINT8, BASE_HEX, NULL, 0x0,
2400 "Thread Query ID",
2401 HFILL
2407 static int *ett[] = {
2408 &ett_mle,
2409 &ett_mle_auxiliary_security,
2410 &ett_mle_aux_sec_control,
2411 &ett_mle_aux_sec_key_id,
2412 &ett_mle_tlv,
2413 &ett_mle_neighbor,
2414 &ett_mle_router,
2415 &ett_mle_addr_reg,
2416 &ett_mle_conn_flg,
2417 &ett_mle_thread_nwd
2420 static ei_register_info ei[] = {
2421 { &ei_mle_cbc_mac_failed, { "mle.cbc_mac_failed", PI_UNDECODED, PI_WARN, "Call to ccm_cbc_mac() failed", EXPFILL }},
2422 { &ei_mle_packet_too_small, { "mle.packet_too_small", PI_UNDECODED, PI_WARN, "Packet was too small to include the CRC and MIC", EXPFILL }},
2423 { &ei_mle_no_key, { "mle.no_key", PI_UNDECODED, PI_WARN, "No encryption key set - can't decrypt", EXPFILL }},
2424 { &ei_mle_decrypt_failed, { "mle.decrypt_failed", PI_UNDECODED, PI_WARN, "Decrypt failed", EXPFILL }},
2425 { &ei_mle_mic_check_failed, { "mle.mic_check_failed", PI_UNDECODED, PI_WARN, "MIC check failed", EXPFILL }},
2426 { &ei_mle_tlv_length_failed, { "mle.tlv_length_failed", PI_UNDECODED, PI_WARN, "TLV Length inconsistent", EXPFILL }},
2427 { &ei_mle_len_size_mismatch, { "mle.len_size_mismatch", PI_UNDECODED, PI_WARN, "TLV Length & Size field disagree", EXPFILL }},
2430 module_t *mle_module;
2431 expert_module_t* expert_mle;
2433 proto_mle = proto_register_protocol("Mesh Link Establishment", "MLE", "mle");
2434 proto_register_field_array(proto_mle, hf, array_length(hf));
2435 proto_register_subtree_array(ett, array_length(ett));
2436 expert_mle = expert_register_protocol(proto_mle);
2437 expert_register_field_array(expert_mle, ei, array_length(ei));
2439 mle_handle = register_dissector("mle", dissect_mle, proto_mle);
2441 mle_module = prefs_register_protocol(proto_mle, NULL);
2443 prefs_register_bool_preference(mle_module, "meshlink_mic_ok",
2444 "Dissect only good MIC",
2445 "Dissect payload only if MIC is valid.",
2446 &mle_mic_ok);
2448 /* setup registration for other dissectors to provide mle key hash algorithms */
2449 mle_key_hash_handlers = wmem_tree_new(wmem_epan_scope());
2452 void
2453 proto_reg_handoff_mle(void)
2455 thread_nwd_handle = find_dissector_add_dependency("thread_nwd", proto_mle);
2456 thread_mc_handle = find_dissector_add_dependency("thread_meshcop", proto_mle);
2458 //heur_dissector_add("stun", dissect_embeddedmle_heur, proto_mle);
2460 dissector_add_uint_range_with_preference("udp.port", UDP_PORT_MLE_RANGE, mle_handle);
2462 proto_ieee802154 = proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN);
2466 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2468 * Local variables:
2469 * c-basic-offset: 2
2470 * tab-width: 8
2471 * indent-tabs-mode: nil
2472 * End:
2474 * vi: set shiftwidth=2 tabstop=8 expandtab
2475 * :indentSize=2:tabSize=8:noTabs=true: