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