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