3 * Auxiliary Security Header support and
4 * option to force TI CC24xx FCS format
5 * By Jean-Francois Wauthy <jfw@info.fundp.ac.be>
6 * Copyright 2009 The University of Namur, Belgium
8 * IEEE 802.15.4 Dissectors for Wireshark
9 * By Owen Kirby <osk@exegin.com>
10 * Copyright 2007 Exegin Technologies Limited
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 *------------------------------------------------------------
31 * In IEEE 802.15.4 packets, all fields are little endian. And
32 * Each byte is transmitted least significant bit first (reflected
34 *------------------------------------------------------------
36 * IEEE 802.15.4 Packets have the following format:
37 * | FCF |Seq No| Addressing | Data | FCS |
38 * |2 bytes|1 byte|0 to 20 bytes|Length-(Overhead) bytes|2 Bytes|
39 *------------------------------------------------------------
41 * CRC16 is calculated using the x^16 + x^12 + x^5 + 1 polynomial
42 * as specified by ITU-T, and is calculated over the IEEE 802.15.4
43 * packet (excluding the FCS) as transmitted over the air. Note,
44 * that because the least significan bits are transmitted first, this
45 * will require reversing the bit-order in each byte. Also, unlike
46 * most CRC algorithms, IEEE 802.15.4 uses an initial and final value
47 * of 0x0000, instead of 0xffff (which is used by the CCITT).
48 *------------------------------------------------------------
50 * This dissector supports both link-layer IEEE 802.15.4 captures
51 * and IEEE 802.15.4 packets encapsulated within other layers.
52 * Additionally, support has been provided for various formats
53 * of the frame check sequence:
54 * - IEEE 802.15.4 compliant FCS.
55 * - ChipCon/Texas Instruments CC24xx style FCS.
56 *------------------------------------------------------------
63 #include <epan/packet.h>
64 #include <epan/decode_as.h>
65 #include <epan/exceptions.h>
66 #include <epan/crc16-tvb.h>
67 #include <epan/expert.h>
68 #include <epan/addr_resolv.h>
69 #include <epan/address_types.h>
70 #include <epan/prefs.h>
72 #include <epan/strutil.h>
73 #include <epan/to_str.h>
74 #include <epan/show_exception.h>
75 #include <epan/proto_data.h>
77 #include <wsutil/pint.h>
79 /* Use libgcrypt for cipher libraries. */
80 #include <wsutil/wsgcrypt.h>
82 #include "packet-ieee802154.h"
83 #include "packet-sll.h"
85 void proto_register_ieee802154(void);
86 void proto_reg_handoff_ieee802154(void);
88 /* Dissection Options for dissect_ieee802154_common */
89 #define DISSECT_IEEE802154_OPTION_CC24xx 0x00000001 /* FCS field contains a TI CC24xx style FCS. */
90 #define DISSECT_IEEE802154_OPTION_LINUX 0x00000002 /* Addressing fields are padded DLT_IEEE802_15_4_LINUX, not implemented. */
91 #define DISSECT_IEEE802154_OPTION_ZBOSS 0x00000004 /* ZBOSS traffic dump */
93 /* ethertype for 802.15.4 tag - encapsulating an Ethernet packet */
94 static unsigned int ieee802154_ethertype = 0x809A;
96 /* boolean value set if the FCS field is using the TI CC24xx format */
97 static gboolean ieee802154_cc24xx = FALSE;
99 /* boolean value set if the FCS must be ok before payload is dissected */
100 static gboolean ieee802154_fcs_ok = TRUE;
102 /* User string with the decryption key. */
103 static const gchar *ieee802154_key_str = NULL;
104 static gboolean ieee802154_key_valid;
105 static guint8 ieee802154_key[IEEE802154_CIPHER_SIZE];
106 static const char *ieee802154_user = "User";
109 * Address Hash Tables
112 static ieee802154_map_tab_t ieee802154_map = { NULL, NULL };
115 * Static Address Mapping UAT
118 /* UAT entry structure. */
127 static uat_t *static_addr_uat = NULL;
128 static static_addr_t *static_addrs = NULL;
129 static guint num_static_addrs = 0;
131 /* Sanity-checks a UAT record. */
133 addr_uat_update_cb(void *r, char **err)
135 static_addr_t *map = (static_addr_t *)r;
136 /* Ensure a valid short address */
137 if (map->addr16 >= IEEE802154_NO_ADDR16) {
138 *err = g_strdup("Invalid short address");
141 /* Ensure a valid PAN identifier. */
142 if (map->pan >= IEEE802154_BCAST_PAN) {
143 *err = g_strdup("Invalid PAN identifier");
146 /* Ensure a valid EUI-64 length */
147 if (map->eui64_len != sizeof(guint64)) {
148 *err = g_strdup("Invalid EUI-64 length");
152 } /* ieee802154_addr_uat_update_cb */
154 /* Field callbacks. */
155 UAT_HEX_CB_DEF(addr_uat, addr16, static_addr_t)
156 UAT_HEX_CB_DEF(addr_uat, pan, static_addr_t)
157 UAT_BUFFER_CB_DEF(addr_uat, eui64, static_addr_t, eui64, eui64_len)
159 /*-------------------------------------
160 * Dissector Function Prototypes
161 *-------------------------------------
164 /* Dissection Routines. */
165 static int dissect_ieee802154_nonask_phy (tvbuff_t *, packet_info *, proto_tree *, void *);
166 static int dissect_ieee802154 (tvbuff_t *, packet_info *, proto_tree *, void *);
167 static int dissect_ieee802154_nofcs (tvbuff_t *, packet_info *, proto_tree *, void *);
168 static int dissect_ieee802154_cc24xx (tvbuff_t *, packet_info *, proto_tree *, void *);
169 static tvbuff_t *dissect_zboss_specific (tvbuff_t *, packet_info *, proto_tree *);
170 /*static void dissect_ieee802154_linux (tvbuff_t *, packet_info *, proto_tree *); TODO: Implement Me. */
171 static void dissect_ieee802154_common (tvbuff_t *, packet_info *, proto_tree *, guint);
173 /* Information Elements */
174 static void dissect_ieee802154_header_ie (tvbuff_t *, packet_info *, proto_tree *, guint *, ieee802154_packet *);
175 static int dissect_ieee802154_payload_mlme_sub_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset);
176 static int dissect_ieee802154_payload_ie (tvbuff_t *, packet_info *, proto_tree *, int offset);
177 static int dissect_ieee802154_vendor_ie (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset, gint pie_length);
178 static void dissect_802154_h_ie_time_correction (tvbuff_t *, proto_tree *, guint *);
179 static void dissect_802154_p_ie_sh_mlme_tsch_sync (tvbuff_t *, proto_tree *, guint, guint *);
180 static void dissect_802154_p_ie_sh_mlme_tsch_slotframe_link (tvbuff_t *, proto_tree *, guint16, guint *);
181 static void dissect_802154_p_ie_lg_mlme_channel_hopping(tvbuff_t *, proto_tree *, guint16, guint *);
182 static int dissect_ieee802154_6top (tvbuff_t *tvb, packet_info *pinfo, proto_tree *p_inf_elem_tree, guint offset, gint pie_length);
183 /* Sub-dissector helpers. */
184 static void dissect_ieee802154_fcf (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *, guint *);
185 static void dissect_ieee802154_command (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
186 static void dissect_ieee802154_assoc_req (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
187 static void dissect_ieee802154_assoc_rsp (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
188 static void dissect_ieee802154_disassoc (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
189 static void dissect_ieee802154_realign (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
190 static void dissect_ieee802154_gtsreq (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
192 /* Decryption helpers. */
194 DECRYPT_PACKET_SUCCEEDED,
195 DECRYPT_NOT_ENCRYPTED,
196 DECRYPT_VERSION_UNSUPPORTED,
197 DECRYPT_PACKET_TOO_SMALL,
198 DECRYPT_PACKET_NO_EXT_SRC_ADDR,
199 DECRYPT_PACKET_NO_KEY,
200 DECRYPT_PACKET_DECRYPT_FAILED,
201 DECRYPT_PACKET_MIC_CHECK_FAILED
204 static tvbuff_t *dissect_ieee802154_decrypt(tvbuff_t *, guint, packet_info *, ieee802154_packet *,
205 ws_decrypt_status *);
206 static void ccm_init_block (gchar *, gboolean, gint, guint64, ieee802154_packet *, gint);
207 static gboolean ccm_ctr_encrypt (const gchar *, const gchar *, gchar *, gchar *, gint);
208 static gboolean ccm_cbc_mac (const gchar *, const gchar *, const gchar *, gint, const gchar *, gint, gchar *);
210 /* Initialize Protocol and Registered fields */
211 static int proto_ieee802154_nonask_phy = -1;
212 static int hf_ieee802154_nonask_phy_preamble = -1;
213 static int hf_ieee802154_nonask_phy_sfd = -1;
214 static int hf_ieee802154_nonask_phy_length = -1;
215 static int hf_ieee802154_nonask_phr = -1;
217 static int proto_ieee802154 = -1;
218 static int hf_ieee802154_frame_length = -1;
219 static int hf_ieee802154_fcf = -1;
220 static int hf_ieee802154_frame_type = -1;
221 static int hf_ieee802154_security = -1;
222 static int hf_ieee802154_pending = -1;
223 static int hf_ieee802154_ack_request = -1;
224 static int hf_ieee802154_pan_id_compression = -1;
225 static int hf_ieee802154_seqno_suppression = -1;
226 static int hf_ieee802154_ie_present = -1;
227 static int hf_ieee802154_src_addr_mode = -1;
228 static int hf_ieee802154_version = -1;
229 static int hf_ieee802154_dst_addr_mode = -1;
230 static int hf_ieee802154_header_ie = -1;
231 static int hf_ieee802154_header_ie_type = -1;
232 static int hf_ieee802154_header_ie_id = -1;
233 static int hf_ieee802154_header_ie_length = -1;
234 static int hf_ieee802154_header_ie_data = -1;
235 static int hf_ieee802154_h_ie_time_correction1 = -1;
236 static int hf_ieee802154_h_ie_time_correction2 = -1;
237 static int hf_ieee802154_h_ie_time_correction3 = -1;
238 static int hf_ieee802154_h_ie_time_correction4 = -1;
239 static int hf_ieee802154_payload_ie = -1;
240 static int hf_ieee802154_payload_ie_type = -1;
241 static int hf_ieee802154_payload_ie_id = -1;
242 static int hf_ieee802154_payload_ie_length = -1;
243 static int hf_ieee802154_payload_ie_data = -1;
244 static int hf_ieee802154_payload_ie_vendor_oui = -1;
245 static int hf_ieee802154_mlme_ie_data = -1;
246 static int hf_ieee802154_psie_short = -1;
247 static int hf_ieee802154_psie_type_short = -1;
248 static int hf_ieee802154_psie_id_short = -1;
249 static int hf_ieee802154_psie_length_short = -1;
250 static int hf_ieee802154_psie_long = -1;
251 static int hf_ieee802154_psie_type_long = -1;
252 static int hf_ieee802154_psie_id_long = -1;
253 static int hf_ieee802154_psie_length_long = -1;
254 static int hf_ieee802154_p_ie_mlme_sh_tsch_asn = -1;
255 static int hf_ieee802154_p_ie_mlme_sh_tsch_join_p = -1;
256 static int hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_nb_slotf = -1;
257 static int hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_slotf_handle= -1;
258 static int hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_slotf_size = -1;
259 static int hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_nb_links = -1;
260 static int hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_timeslot = -1;
261 static int hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_channel_offset = -1;
262 static int hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_options = -1;
263 static int hf_ieee802154_p_ie_mlme_lg_hopping_sequence_id = -1;
264 static int hf_ieee802154_psie_eb_filter = -1;
265 static int hf_ieee802154_psie_eb_filter_pjoin = -1;
266 static int hf_ieee802154_psie_eb_filter_lqi = -1;
267 static int hf_ieee802154_psie_eb_filter_lqi_min = -1;
268 static int hf_ieee802154_psie_eb_filter_percent = -1;
269 static int hf_ieee802154_psie_eb_filter_percent_prob = -1;
270 static int hf_ieee802154_psie_eb_filter_attr_id = -1;
271 static int hf_ieee802154_psie_eb_filter_attr_id_bitmap = -1;
272 static int hf_ieee802154_p_ie_ietf_sub_id = -1;
273 static int hf_ieee802154_p_ie_6top_version = -1;
274 static int hf_ieee802154_p_ie_6top_type = -1;
275 static int hf_ieee802154_p_ie_6top_flags_reserved = -1;
276 static int hf_ieee802154_p_ie_6top_code = -1;
277 static int hf_ieee802154_p_ie_6top_sfid = -1;
278 static int hf_ieee802154_p_ie_6top_seqnum = -1;
279 static int hf_ieee802154_p_ie_6top_gab = -1;
280 static int hf_ieee802154_p_ie_6top_gba = -1;
281 static int hf_ieee802154_p_ie_6top_metadata = -1;
282 static int hf_ieee802154_p_ie_6top_cell_options = -1;
283 static int hf_ieee802154_p_ie_6top_cell_option_tx = -1;
284 static int hf_ieee802154_p_ie_6top_cell_option_rx = -1;
285 static int hf_ieee802154_p_ie_6top_cell_option_shared = -1;
286 static int hf_ieee802154_p_ie_6top_cell_option_reserved = -1;
287 static int hf_ieee802154_p_ie_6top_num_cells = -1;
288 static int hf_ieee802154_p_ie_6top_reserved = -1;
289 static int hf_ieee802154_p_ie_6top_offset = -1;
290 static int hf_ieee802154_p_ie_6top_max_num_cells = -1;
291 static int hf_ieee802154_p_ie_6top_slot_offset = -1;
292 static int hf_ieee802154_p_ie_6top_channel_offset = -1;
294 static int proto_zboss = -1;
295 static int zboss_direction = -1;
296 static int zboss_channel = -1;
297 static int zboss_trace_number = -1;
299 static int hf_ieee802154_seqno = -1;
300 static int hf_ieee802154_dst_panID = -1;
301 static int hf_ieee802154_dst16 = -1;
302 static int hf_ieee802154_dst64 = -1;
303 static int hf_ieee802154_src_panID = -1;
304 static int hf_ieee802154_src16 = -1;
305 static int hf_ieee802154_src64 = -1;
306 static int hf_ieee802154_src64_origin = -1;
307 static int hf_ieee802154_fcs = -1;
308 static int hf_ieee802154_rssi = -1;
309 static int hf_ieee802154_fcs_ok = -1;
310 static int hf_ieee802154_correlation = -1;
312 /* Registered fields for Command Packets */
313 static int hf_ieee802154_cmd_id = -1;
314 static int hf_ieee802154_cinfo_alt_coord = -1;
315 static int hf_ieee802154_cinfo_device_type = -1;
316 static int hf_ieee802154_cinfo_power_src = -1;
317 static int hf_ieee802154_cinfo_idle_rx = -1;
318 static int hf_ieee802154_cinfo_sec_capable = -1;
319 static int hf_ieee802154_cinfo_alloc_addr = -1;
320 static int hf_ieee802154_assoc_addr = -1;
321 static int hf_ieee802154_assoc_status = -1;
322 static int hf_ieee802154_disassoc_reason = -1;
323 static int hf_ieee802154_realign_pan = -1;
324 static int hf_ieee802154_realign_caddr = -1;
325 static int hf_ieee802154_realign_channel = -1;
326 static int hf_ieee802154_realign_addr = -1;
327 static int hf_ieee802154_realign_channel_page = -1;
328 static int hf_ieee802154_gtsreq_len = -1;
329 static int hf_ieee802154_gtsreq_dir = -1;
330 static int hf_ieee802154_gtsreq_type = -1;
332 /* Registered fields for Beacon Packets */
333 static int hf_ieee802154_beacon_order = -1;
334 static int hf_ieee802154_superframe_order = -1;
335 static int hf_ieee802154_cap = -1;
336 static int hf_ieee802154_superframe_battery_ext = -1;
337 static int hf_ieee802154_superframe_coord = -1;
338 static int hf_ieee802154_assoc_permit = -1;
339 static int hf_ieee802154_gts_count = -1;
340 static int hf_ieee802154_gts_permit = -1;
341 static int hf_ieee802154_gts_direction = -1;
342 static int hf_ieee802154_gts_address = -1;
343 static int hf_ieee802154_pending16 = -1;
344 static int hf_ieee802154_pending64 = -1;
346 /* Registered fields for Auxiliary Security Header */
347 static int hf_ieee802154_security_control_field = -1;
348 static int hf_ieee802154_security_level = -1;
349 static int hf_ieee802154_key_id_mode = -1;
350 static int hf_ieee802154_aux_sec_reserved = -1;
351 static int hf_ieee802154_aux_sec_frame_counter = -1;
352 static int hf_ieee802154_aux_sec_key_source = -1;
353 static int hf_ieee802154_aux_sec_key_index = -1;
355 /* 802.15.4-2003 security */
356 static int hf_ieee802154_sec_frame_counter = -1;
357 static int hf_ieee802154_sec_key_sequence_counter = -1;
359 /* Initialize Subtree Pointers */
360 static gint ett_ieee802154_nonask_phy = -1;
361 static gint ett_ieee802154_nonask_phy_phr = -1;
362 static gint ett_ieee802154 = -1;
363 static gint ett_ieee802154_fcf = -1;
364 static gint ett_ieee802154_auxiliary_security = -1;
365 static gint ett_ieee802154_aux_sec_control = -1;
366 static gint ett_ieee802154_aux_sec_key_id = -1;
367 static gint ett_ieee802154_fcs = -1;
368 static gint ett_ieee802154_cmd = -1;
369 static gint ett_ieee802154_superframe = -1;
370 static gint ett_ieee802154_gts = -1;
371 static gint ett_ieee802154_gts_direction = -1;
372 static gint ett_ieee802154_gts_descriptors = -1;
373 static gint ett_ieee802154_pendaddr = -1;
374 static gint ett_ieee802154_header = -1;
375 static gint ett_ieee802154_header_ie = -1;
376 static gint ett_ieee802154_h_ie_payload = -1;
377 static gint ett_ieee802154_payload = -1;
378 static gint ett_ieee802154_payload_ie = -1;
379 static gint ett_ieee802154_mlme_payload = -1;
380 static gint ett_ieee802154_mlme_payload_data = -1;
381 static gint ett_ieee802154_psie_short = -1;
382 static gint ett_ieee802154_psie_short_bitmap= -1;
383 static gint ett_ieee802154_psie_long = -1;
384 static gint ett_ieee802154_psie_long_bitmap = -1;
385 static gint ett_ieee802154_psie_enh_beacon_flt = -1;
386 static gint ett_ieee802154_psie_enh_beacon_flt_bitmap = -1;
387 static gint ett_ieee802154_psie_slotframe_link_slotframes = -1;
388 static gint ett_ieee802154_zigbee = -1;
389 static gint ett_ieee802154_zboss = -1;
390 static gint ett_ieee802154_p_ie_6top = -1;
391 static gint ett_ieee802154_p_ie_6top_version_type = -1;
392 static gint ett_ieee802154_p_ie_6top_seqnum_gab_gba = -1;
393 static gint ett_ieee802154_p_ie_6top_cell_options = -1;
394 static gint ett_ieee802154_p_ie_6top_cell_list = -1;
395 static gint ett_ieee802154_p_ie_6top_cell = -1;
397 static expert_field ei_ieee802154_invalid_addressing = EI_INIT;
398 /* static expert_field ei_ieee802154_invalid_panid_compression = EI_INIT; */
399 static expert_field ei_ieee802154_invalid_panid_compression2 = EI_INIT;
400 static expert_field ei_ieee802154_fcs = EI_INIT;
401 static expert_field ei_ieee802154_decrypt_error = EI_INIT;
402 static expert_field ei_ieee802154_dst = EI_INIT;
403 static expert_field ei_ieee802154_src = EI_INIT;
404 static expert_field ei_ieee802154_frame_ver = EI_INIT;
405 /* static expert_field ei_ieee802154_frame_type = EI_INIT; */
406 static expert_field ei_ieee802154_seqno_suppression = EI_INIT;
407 static expert_field ei_ieee802154_p_ie_6top_type = EI_INIT;
408 static expert_field ei_ieee802154_p_ie_6top_code = EI_INIT;
410 static int ieee802_15_4_short_address_type = -1;
413 * - beacon dissection is always heuristic.
414 * - the PANID table is for stateful dissectors only (ie: Decode-As)
415 * - otherwise, data dissectors fall back to the heuristic dissectors.
417 static dissector_table_t panid_dissector_table;
418 static heur_dissector_list_t ieee802154_beacon_subdissector_list;
419 static heur_dissector_list_t ieee802154_heur_subdissector_list;
421 static dissector_handle_t zigbee_beacon_handle;
422 static dissector_handle_t zigbee_ie_handle;
423 static dissector_handle_t zigbee_nwk_handle;
424 static dissector_handle_t ieee802154_handle;
425 static dissector_handle_t ieee802154_nonask_phy_handle;
426 static dissector_handle_t ieee802154_nofcs_handle;
429 static const value_string ieee802154_frame_versions[] = {
430 { IEEE802154_VERSION_2003, "IEEE Std 802.15.4-2003" },
431 { IEEE802154_VERSION_2006, "IEEE Std 802.15.4-2006" },
432 { IEEE802154_VERSION_2015, "IEEE Std 802.15.4-2015" },
433 { IEEE802154_VERSION_RESERVED, "Reserved" },
438 static const value_string ieee802154_frame_types[] = {
439 { IEEE802154_FCF_BEACON, "Beacon" },
440 { IEEE802154_FCF_DATA, "Data" },
441 { IEEE802154_FCF_ACK, "Ack" },
442 { IEEE802154_FCF_CMD, "Command" },
443 { IEEE802154_FCF_RESERVED, "Reserved" },
444 { IEEE802154_FCF_MULTIPURPOSE, "Multipurpose" },
445 { IEEE802154_FCF_FRAGMENT, "Fragment or Frak" },
446 { IEEE802154_FCF_EXTENDED, "Extended" },
450 static const value_string ieee802154_addr_modes[] = {
451 { IEEE802154_FCF_ADDR_NONE, "None" },
452 { IEEE802154_FCF_ADDR_RESERVED, "Reserved" },
453 { IEEE802154_FCF_ADDR_SHORT, "Short/16-bit" },
454 { IEEE802154_FCF_ADDR_EXT, "Long/64-bit" },
458 static const value_string ieee802154_cmd_names[] = {
459 { IEEE802154_CMD_ASSOC_REQ, "Association Request" },
460 { IEEE802154_CMD_ASSOC_RSP, "Association Response" },
461 { IEEE802154_CMD_DISASSOC_NOTIFY, "Disassociation Notification" },
462 { IEEE802154_CMD_DATA_RQ, "Data Request" },
463 { IEEE802154_CMD_PANID_CONFLICT, "PAN ID Conflict" },
464 { IEEE802154_CMD_ORPHAN_NOTIFY, "Orphan Notification" },
465 { IEEE802154_CMD_BEACON_REQ, "Beacon Request" },
466 { IEEE802154_CMD_COORD_REALIGN, "Coordinator Realignment" },
467 { IEEE802154_CMD_GTS_REQ, "GTS Request" },
468 { IEEE802154_CMD_TRLE_MGMT_REQ, "TRLE Management Request"},
469 { IEEE802154_CMD_TRLE_MGMT_RSP, "TRLE Management Response"},
470 { IEEE802154_CMD_DSME_ASSOC_REQ, "DSME Association Request"},
471 { IEEE802154_CMD_DSME_ASSOC_RSP, "DSME Association Response"},
472 { IEEE802154_CMD_DSME_GTS_REQ, "DSME GTS Request"},
473 { IEEE802154_CMD_DSME_GTS_RSP, "DSME GTS Response"},
474 { IEEE802154_CMD_DSME_GTS_NOTIFY, "DSME GTS Notify"},
475 { IEEE802154_CMD_DSME_INFO_REQ, "DSME Information Request"},
476 { IEEE802154_CMD_DSME_INFO_RSP, "DSME Information Response"},
477 { IEEE802154_CMD_DSME_BEACON_ALLOC_NOTIFY, "DSME Beacon Allocation Notification"},
478 { IEEE802154_CMD_DSME_BEACON_COLL_NOTIFY, "DSME Beacon Collision Notification"},
479 { IEEE802154_CMD_DSME_LINK_REPORT, "DSME Link Report"},
480 { IEEE802154_CMD_RIT_DATA_REQ, "RIT Data Request"},
481 { IEEE802154_CMD_DBS_REQ, "DBS Request"},
482 { IEEE802154_CMD_DBS_RSP, "DBS Response"},
486 static const value_string ieee802154_sec_level_names[] = {
487 { SECURITY_LEVEL_NONE, "No Security" },
488 { SECURITY_LEVEL_MIC_32, "32-bit Message Integrity Code" },
489 { SECURITY_LEVEL_MIC_64, "64-bit Message Integrity Code" },
490 { SECURITY_LEVEL_MIC_128, "128-bit Message Integrity Code" },
491 { SECURITY_LEVEL_ENC, "Encryption" },
492 { SECURITY_LEVEL_ENC_MIC_32, "Encryption with 32-bit Message Integrity Code" },
493 { SECURITY_LEVEL_ENC_MIC_64, "Encryption with 64-bit Message Integrity Code" },
494 { SECURITY_LEVEL_ENC_MIC_128, "Encryption with 128-bit Message Integrity Code" },
498 static const value_string ieee802154_key_id_mode_names[] = {
499 { KEY_ID_MODE_IMPLICIT, "Implicit Key" },
500 { KEY_ID_MODE_KEY_INDEX, "Indexed Key using the Default Key Source" },
501 { KEY_ID_MODE_KEY_EXPLICIT_4, "Explicit Key with 4-octet Key Source" },
502 { KEY_ID_MODE_KEY_EXPLICIT_8, "Explicit Key with 8-octet Key Source" },
506 static const true_false_string ieee802154_gts_direction_tfs = {
511 /* The 802.15.4-2003 security suites for the security preferences (only AES-CCM suites are supported). */
512 /* NOTE: The equivalent 2006 security level identifier enumerations are used to simplify 2003 & 2006 integration! */
513 static const enum_val_t ieee802154_2003_sec_suite_enums[] = {
514 { "AES-CCM-128", "AES-128 Encryption, 128-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_128 },
515 { "AES-CCM-64", "AES-128 Encryption, 64-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_64 },
516 { "AES-CCM-32", "AES-128 Encryption, 32-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_32 },
520 static const value_string ieee802154_ie_types[] = {
526 static const value_string ieee802154_psie_types[] = {
532 static const value_string ieee802154_header_ie_names[] = {
533 { IEEE802154_HEADER_VENDOR_SPECIFIC, "Vendor Specific IE" },
534 { IEEE802154_HEADER_IE_CSL, "CSL IE" },
535 { IEEE802154_HEADER_IE_RIT, "RIT IE" },
536 { IEEE802154_HEADER_IE_DSME_PAN, "DSME PAN descriptor IE" },
537 { IEEE802154_HEADER_IE_RENDEZVOUS, "Rendezvous Time IE" },
538 { IEEE802154_HEADER_IE_TIME_CORR, "Time Correction IE" },
539 { IEEE802154_HEADER_IE_EXT_DSME_PAN, "Extended DSME PAN descriptor IE" },
540 { IEEE802154_HEADER_IE_FSCD, "Fragment Sequence Context Description (FSCD) IE" },
541 { IEEE802154_HEADER_IE_SMPL_SUPER_FRM, "Simplified Superframe Specification IE" },
542 { IEEE802154_HEADER_IE_SMPL_GTS, "Simplified GTS Specification IE" },
543 { IEEE802154_HEADER_IE_LECIM, "LECIM Capabilities IE" },
544 { IEEE802154_HEADER_IE_TRLE, "TRLE Descriptor" },
545 { IEEE802154_HEADER_IE_RCC_CAP, "RCC Capabilities IE" },
546 { IEEE802154_HEADER_IE_RCCN, "RCCN Descriptor IE" },
547 { IEEE802154_HEADER_IE_GLOBAL_TIME, "Global Time IE" },
548 { IEEE802154_HEADER_IE_DA_IE, "DA IE" },
549 { IEEE802154_HEADER_IE_EID_TERM1, "Header Termination 1" },
550 { IEEE802154_HEADER_IE_EID_TERM2, "Header Termination 2" },
554 static const value_string ieee802154_payload_ie_names[] = {
555 { IEEE802154_PAYLOAD_IE_ESDU, "ESDU IE" },
556 { IEEE802154_PAYLOAD_IE_MLME, "MLME IE" },
557 { IEEE802154_PAYLOAD_IE_VENDOR, "Vendor Specific IE" },
558 { IEEE802154_PAYLOAD_IE_IETF, "IETF IE" },
559 { IEEE802154_PAYLOAD_IE_GID_TERM, "Payload Termination IE" },
563 static const value_string ieee802154_vendor_oui_names[] = {
564 { IEEE802154_VENDOR_OUI_ZIGBEE, "ZigBee" },
568 static const value_string ieee802154_psie_names[] = {
569 { IEEE802154_MLME_SUBIE_CHANNEL_HOPPING, "Channel Hopping IE" },
570 { IEEE802154_MLME_SUBIE_TSCH_SYNCH, "TSCH Synchronization IE" },
571 { IEEE802154_MLME_SUBIE_TSCH_SLOTFR_LINK, "TSCH Slotframe and Link IE" },
572 { IEEE802154_MLME_SUBIE_TSCH_TIMESLOT, "TSCH Timeslot IE" },
573 { IEEE802154_MLME_SUBIE_HOPPING_TIMING, "Hopping Timing IE" },
574 { IEEE802154_MLME_SUBIE_ENHANCED_BEACON_FILTER, "Enhanced Beacon Filter IE" },
575 { IEEE802154_MLME_SUBIE_MAC_METRICS, "MAC Metrics IE" },
576 { IEEE802154_MLME_SUBIE_ALL_MAC_METRICS, "All MAC Metrics IE" },
577 { IEEE802154_MLME_SUBIE_COEXISTENCE_SPEC, "Coexistence Specification IE" },
578 { IEEE802154_MLME_SUBIE_SUN_DEVICE_CAPABILITIES, "SUN Device Capabilities IE" },
579 { IEEE802154_MLME_SUBIE_SUN_FSK_GEN_PHY, "SUN FSK Generic PHY IE" },
580 { IEEE802154_MLME_SUBIE_MODE_SWITCH_PARAMETER, "Mode Switch Parameter IE" },
581 { IEEE802154_MLME_SUBIE_PHY_PARAMETER_CHANGE, "PHY Parameter Change IE" },
582 { IEEE802154_MLME_SUBIE_O_QPSK_PHY_MODE, "O-QPSY PHY Mode IE" },
583 { IEEE802154_MLME_SUBIE_PCA_ALLOCATION, "PCA Allocation IE" },
584 { IEEE802154_MLME_SUBIE_DSSS_OPER_MODE, "LECIM DSSS Operating Mode IE"},
585 { IEEE802154_MLME_SUBIE_FSK_OPER_MODE, "LECIM FSK Operating Mode IE" },
586 { IEEE802154_MLME_SUBIE_TVWS_PHY_OPE_MODE, "TVWS PHY Operating Mode Description IE" },
587 { IEEE802154_MLME_SUBIE_TVWS_DEVICE_CAPAB, "TVWS Device Capabilities IE" },
588 { IEEE802154_MLME_SUBIE_TVWS_DEVICE_CATEG, "TVWS Device Category IE" },
589 { IEEE802154_MLME_SUBIE_TVWS_DEVICE_IDENTIF, "TVWS Device Identification IE" },
590 { IEEE802154_MLME_SUBIE_TVWS_DEVICE_LOCATION, "TVWS Device Location IE" },
591 { IEEE802154_MLME_SUBIE_TVWS_CH_INFOR_QUERY, "TVWS Channel Information Query IE" },
592 { IEEE802154_MLME_SUBIE_TVWS_CH_INFOR_SOURCE, "TVWS Channel Information Source IE" },
593 { IEEE802154_MLME_SUBIE_CTM, "CTM IE" },
594 { IEEE802154_MLME_SUBIE_TIMESTAMP, "Timestamp IE" },
595 { IEEE802154_MLME_SUBIE_TIMESTAMP_DIFF, "Timestamp Difference IE"},
596 { IEEE802154_MLME_SUBIE_TMCP_SPECIFICATION, "TMCTP Specification IE" },
597 { IEEE802154_MLME_SUBIE_RCC_PHY_OPER_MODE, "RCC PHY Operating Mode IE" },
598 { IEEE802154_IETF_SUBIE_6TOP, "6top IE" },
602 static const value_string zboss_direction_names[] = {
608 static const value_string ietf_6top_types[] = {
609 { IETF_6TOP_TYPE_REQUEST, "Request" },
610 { IETF_6TOP_TYPE_RESPONSE, "Response" },
611 { IETF_6TOP_TYPE_CONFIRMATION, "Confirmation" },
615 static const value_string ietf_6top_command_identifiers[] = {
616 { IETF_6TOP_CMD_ADD, "Add" },
617 { IETF_6TOP_CMD_DELETE, "Delete" },
618 { IETF_6TOP_CMD_STATUS, "Status" },
619 { IETF_6TOP_CMD_LIST, "List" },
620 { IETF_6TOP_CMD_CLEAR, "Clear" },
624 static const value_string ietf_6top_return_codes[] = {
625 { IETF_6TOP_RC_SUCCESS, "SUCCESS" },
626 { IETF_6TOP_RC_ERR_VER, "ERR_VER" },
627 { IETF_6TOP_RC_ERR_SFID, "ERR_SFID" },
628 { IETF_6TOP_RC_ERR_GEN, "ERR_GEN" },
629 { IETF_6TOP_RC_ERR_BUSY, "ERR_BUSY" },
630 { IETF_6TOP_RC_ERR_NORES, "ERR_NORES" },
631 { IETF_6TOP_RC_ERR_RESET, "ERR_RESET" },
632 { IETF_6TOP_RC_ERR, "ERR" },
636 static const value_string ietf_6top_generation_numbers[] = {
644 static const value_string ietf_6top_cell_options[] = {
652 { 7, "TX|RX|SHARED" },
656 /* Preferences for 2003 security */
657 static gint ieee802154_sec_suite = SECURITY_LEVEL_ENC_MIC_64;
658 static gboolean ieee802154_extend_auth = TRUE;
660 /* Macro to check addressing, and throw a warning flag if incorrect. */
661 #define IEEE802154_CMD_ADDR_CHECK(_pinfo_, _item_, _cmdid_, _x_) \
663 expert_add_info_format(_pinfo_, _item_, &ei_ieee802154_invalid_addressing, \
664 "Invalid Addressing for %s", \
665 val_to_str_const(_cmdid_, ieee802154_cmd_names, "Unknown Command"))
667 /* CRC definitions. IEEE 802.15.4 CRCs vary from CCITT by using an initial value of
668 * 0x0000, and no XOR out. IEEE802154_CRC_XOR is defined as 0xFFFF in order to un-XOR
669 * the output from the CCITT CRC routines in Wireshark.
671 #define IEEE802154_CRC_SEED 0x0000
672 #define IEEE802154_CRC_XOROUT 0xFFFF
673 #define ieee802154_crc_tvb(tvb, offset) (crc16_ccitt_tvb_seed(tvb, offset, IEEE802154_CRC_SEED) ^ IEEE802154_CRC_XOROUT)
676 static int ieee802_15_4_short_address_to_str(const address* addr, gchar *buf, int buf_len)
678 guint16 ieee_802_15_4_short_addr = pletoh16(addr->data);
680 if (ieee_802_15_4_short_addr == 0xffff)
682 g_strlcpy(buf, "Broadcast", buf_len);
688 buf = word_to_hex(buf, ieee_802_15_4_short_addr);
689 *buf = '\0'; /* NULL terminate */
694 static int ieee802_15_4_short_address_str_len(const address* addr _U_)
699 static int ieee802_15_4_short_address_len(void)
705 * Dissector helper, parses and displays the frame control field.
707 *@param tvb pointer to buffer containing raw packet.
708 *@param pinfo pointer to packet information fields
709 *@param tree pointer to data tree wireshark uses to display packet.
710 *@param packet IEEE 802.15.4 packet information.
711 *@param offset offset into the tvb to find the FCF.
715 dissect_ieee802154_fcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet, guint *offset)
718 static const int * fields[] = {
719 &hf_ieee802154_frame_type,
720 &hf_ieee802154_security,
721 &hf_ieee802154_pending,
722 &hf_ieee802154_ack_request,
723 &hf_ieee802154_pan_id_compression,
724 &hf_ieee802154_seqno_suppression,
725 &hf_ieee802154_ie_present,
726 &hf_ieee802154_dst_addr_mode,
727 &hf_ieee802154_version,
728 &hf_ieee802154_src_addr_mode,
732 /* Get the FCF field. */
733 fcf = tvb_get_letohs(tvb, *offset);
735 /* Parse FCF Flags. */
736 packet->frame_type = (fcf & IEEE802154_FCF_TYPE_MASK);
737 packet->security_enable = (fcf & IEEE802154_FCF_SEC_EN) >> 3;
738 packet->frame_pending = (fcf & IEEE802154_FCF_FRAME_PND) >> 4;
739 packet->ack_request = (fcf & IEEE802154_FCF_ACK_REQ) >> 5;
740 packet->pan_id_compression = (fcf & IEEE802154_FCF_PAN_ID_COMPRESSION) >> 6;
742 packet->seqno_suppression = (fcf & IEEE802154_FCF_SEQNO_SUPPRESSION) >> 8;
743 packet->ie_present = (fcf & IEEE802154_FCF_IE_PRESENT) >> 9;
744 packet->dst_addr_mode = (fcf & IEEE802154_FCF_DADDR_MASK) >> 10;
745 packet->version = (fcf & IEEE802154_FCF_VERSION) >> 12;
746 packet->src_addr_mode = (fcf & IEEE802154_FCF_SADDR_MASK) >> 14;
748 if ((packet->version == IEEE802154_VERSION_2015) && (packet->frame_type == IEEE802154_FCF_BEACON)) {
749 proto_item_append_text(tree, " Enhanced Beacon");
750 col_set_str(pinfo->cinfo, COL_INFO, "Enhanced Beacon");
753 proto_item_append_text(tree, " %s", val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
754 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
757 proto_tree_add_bitmask(tree, tvb, *offset, hf_ieee802154_fcf,
758 ett_ieee802154_fcf, fields, ENC_LITTLE_ENDIAN);
761 } /* dissect_ieee802154_fcf */
764 *Dissector for IEEE 802.15.4 non-ASK PHY packet with an FCS containing a 16-bit CRC value.
766 *@param tvb pointer to buffer containing raw packet.
767 *@param pinfo pointer to packet information fields
768 *@param tree pointer to data tree wireshark uses to display packet.
771 dissect_ieee802154_nonask_phy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
773 proto_tree *ieee802154_tree = NULL;
774 proto_item *proto_root = NULL;
780 /* Create the protocol tree. */
782 proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154_nonask_phy, tvb, 0, tvb_captured_length(tvb), "IEEE 802.15.4 non-ASK PHY");
783 ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154_nonask_phy);
786 /* Add the protocol name. */
787 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4 non-ASK PHY");
788 /* Add the packet length. */
789 col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, "%i", tvb_captured_length(tvb));
791 phr=tvb_get_guint8(tvb,offset+4+1);
794 guint loffset=offset;
795 static const int * phr_fields[] = {
796 &hf_ieee802154_nonask_phy_length,
800 proto_tree_add_item(ieee802154_tree, hf_ieee802154_nonask_phy_preamble, tvb, loffset, 4, ENC_LITTLE_ENDIAN);
802 proto_tree_add_item(ieee802154_tree, hf_ieee802154_nonask_phy_sfd, tvb, loffset, 1, ENC_LITTLE_ENDIAN);
805 proto_tree_add_bitmask(ieee802154_tree, tvb, loffset, hf_ieee802154_nonask_phr, ett_ieee802154_nonask_phy_phr,
810 mac=tvb_new_subset_length_caplen(tvb,offset,-1, phr & IEEE802154_PHY_LENGTH_MASK);
812 /* Call the common dissector. */
813 dissect_ieee802154(mac, pinfo, ieee802154_tree, NULL);
814 return tvb_captured_length(tvb);
815 } /* dissect_ieee802154_nonask_phy */
818 *Dissector for IEEE 802.15.4 packet with an FCS containing a 16-bit CRC value.
820 *@param tvb pointer to buffer containing raw packet.
821 *@param pinfo pointer to packet information fields.
822 *@param tree pointer to data tree wireshark uses to display packet.
825 dissect_ieee802154(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
827 tvbuff_t *new_tvb = dissect_zboss_specific(tvb, pinfo, tree);
830 if (ieee802154_cc24xx)
832 options = DISSECT_IEEE802154_OPTION_CC24xx;
836 /* ZBOSS traffic dump: always TI FCS, always ZigBee */
837 options = (DISSECT_IEEE802154_OPTION_CC24xx | DISSECT_IEEE802154_OPTION_ZBOSS);
839 /* Call the common dissector. */
840 dissect_ieee802154_common(new_tvb, pinfo, tree, options);
841 return tvb_captured_length(tvb);
842 } /* dissect_ieee802154 */
845 * Dissector for IEEE 802.15.4 packet with no FCS present.
847 *@param tvb pointer to buffer containing raw packet.
848 *@param pinfo pointer to packet information fields
849 *@param tree pointer to data tree wireshark uses to display packet.
850 *@return captured length.
853 dissect_ieee802154_nofcs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
856 /* If there is no FCS present in the reported packet, then the length of
857 * the true IEEE 802.15.4 packet is actually 2 bytes longer. Re-create
858 * the buffer with an extended reported length so that the packet will
859 * be handled as though the FCS were truncated.
861 * Note, we can't just call tvb_set_reported_length(), because it includes
862 * checks to ensure that the new reported length is not longer than the old
863 * reported length (why?), and will throw an exception.
865 new_tvb = tvb_new_subset_length_caplen(tvb, 0, -1, tvb_reported_length(tvb)+IEEE802154_FCS_LEN);
866 /* Call the common dissector. */
867 dissect_ieee802154_common(new_tvb, pinfo, tree, 0);
868 return tvb_captured_length(tvb);
869 } /* dissect_ieee802154_nofcs */
872 * Dissector for IEEE 802.15.4 packet dump produced by ZBOSS
874 *@param tvb pointer to buffer containing raw packet.
875 *@param pinfo pointer to packet information fields
876 *@param tree pointer to data tree wireshark uses to display packet.
877 *@return new tvb subset if this is really ZBOSS dump, else oririnal tvb.
880 dissect_zboss_specific(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
882 if (tvb_captured_length(tvb) > 5)
885 if (tvb_get_guint8(tvb, off++) == 'Z'
886 && tvb_get_guint8(tvb, off++) == 'B'
887 && tvb_get_guint8(tvb, off++) == 'O'
888 && tvb_get_guint8(tvb, off++) == 'S'
889 && tvb_get_guint8(tvb, off++) == 'S')
891 proto_tree *zboss_tree = NULL;
892 proto_item *proto_root = NULL;
894 /* Create the protocol tree. */
896 proto_root = proto_tree_add_protocol_format(tree, proto_zboss, tvb, 0, tvb_captured_length(tvb), "ZBOSS dump");
897 zboss_tree = proto_item_add_subtree(proto_root, ett_ieee802154_zboss);
900 proto_tree_add_item(zboss_tree, zboss_direction, tvb, off, 1, ENC_NA);
901 proto_item_append_text(proto_root, ", %s", tvb_get_guint8(tvb, off) ? "OUT" : "IN");
903 proto_tree_add_item(zboss_tree, zboss_channel, tvb, off, 1, ENC_NA);
904 proto_item_append_text(proto_root, ", channel %u", tvb_get_guint8(tvb, off));
906 proto_tree_add_item(zboss_tree, zboss_trace_number, tvb, off, 4, ENC_LITTLE_ENDIAN);
909 return tvb_new_subset_length_caplen(tvb, off, tvb_captured_length(tvb) - off, tvb_captured_length(tvb) - off);
913 } /* dissect_zboss_heur */
916 *Dissector for IEEE 802.15.4 packet with a ChipCon/Texas
917 *Instruments compatible FCS. This is typically called by
918 *layers encapsulating an IEEE 802.15.4 packet.
920 *@param tvb pointer to buffer containing raw packet.
921 *@param pinfo pointer to packet information fields
922 *@param tree pointer to data tree wireshark uses to display packet.
925 dissect_ieee802154_cc24xx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
927 /* Call the common dissector. */
928 dissect_ieee802154_common(tvb, pinfo, tree, DISSECT_IEEE802154_OPTION_CC24xx);
929 return tvb_captured_length(tvb);
930 } /* dissect_ieee802154_cc24xx */
933 *IEEE 802.15.4 packet dissection routine for Wireshark.
935 *This function extracts all the information first before displaying.
936 *If payload exists, that portion will be passed into another dissector
937 *for further processing.
939 *This is called after the individual dissect_ieee802154* functions
940 *have been called to determine what sort of FCS is present.
941 *The dissect_ieee802154* functions will set the parameters
942 *in the ieee802154_packet structure, and pass it to this one
943 *through the data parameter.
945 *@param tvb pointer to buffer containing raw packet.
946 *@param pinfo pointer to packet information fields
947 *@param tree pointer to data tree wireshark uses to display packet.
948 *@param options bitwise or of dissector options (see DISSECT_IEEE802154_OPTION_xxx).
951 dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint options)
953 tvbuff_t *volatile payload_tvb;
954 proto_tree *volatile ieee802154_tree = NULL;
955 proto_item *volatile proto_root = NULL;
956 proto_item *hidden_item;
959 volatile gboolean fcs_ok = TRUE;
960 const char *saved_proto;
961 ws_decrypt_status status;
962 gboolean dstPanPresent = FALSE;
963 gboolean srcPanPresent = FALSE;
965 ieee802154_packet *packet = wmem_new0(wmem_packet_scope(), ieee802154_packet);
966 ieee802154_short_addr addr16;
967 ieee802154_hints_t *ieee_hints;
969 heur_dtbl_entry_t *hdtbl_entry;
971 packet->short_table = ieee802154_map.short_table;
973 /* Allocate frame data with hints for upper layers */
974 if(!pinfo->fd->flags.visited){
975 ieee_hints = wmem_new0(wmem_file_scope(), ieee802154_hints_t);
976 p_add_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0, ieee_hints);
978 ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
981 /* Create the protocol tree. */
983 proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154, tvb, 0, tvb_captured_length(tvb), "IEEE 802.15.4");
984 ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154);
986 /* Add the protocol name. */
987 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4");
988 /* Add the packet length. */
989 col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, "%i", tvb_captured_length(tvb));
991 /* Add the packet length to the filter field */
992 hidden_item = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_frame_length, NULL, 0, 0, tvb_reported_length(tvb));
993 PROTO_ITEM_SET_HIDDEN(hidden_item);
995 /* Frame Control Field */
996 dissect_ieee802154_fcf(tvb, pinfo, ieee802154_tree, packet, &offset);
998 /* Sequence Number */
999 if (packet->seqno_suppression) {
1000 if (packet->version != IEEE802154_VERSION_2015) {
1001 expert_add_info(pinfo, proto_root, &ei_ieee802154_seqno_suppression);
1003 } else { /* IEEE 802.15.4 Sequence Number Suppression */
1004 packet->seqno = tvb_get_guint8(tvb, offset);
1006 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_seqno, tvb, offset, 1, packet->seqno);
1007 /* For Ack packets display this in the root. */
1008 if (packet->frame_type == IEEE802154_FCF_ACK) {
1009 proto_item_append_text(proto_root, ", Sequence Number: %u", packet->seqno);
1018 /* Clear out the addressing strings. */
1019 clear_address(&pinfo->net_dst);
1020 clear_address(&pinfo->dl_dst);
1021 clear_address(&pinfo->dst);
1022 clear_address(&pinfo->net_src);
1023 clear_address(&pinfo->dl_src);
1024 clear_address(&pinfo->src);
1026 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_RESERVED) {
1027 /* Invalid Destination Address Mode. Abort Dissection. */
1028 expert_add_info(pinfo, proto_root, &ei_ieee802154_dst);
1032 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_RESERVED) {
1033 /* Invalid Source Address Mode. Abort Dissection. */
1034 expert_add_info(pinfo, proto_root, &ei_ieee802154_src);
1038 if (packet->version == IEEE802154_VERSION_RESERVED) {
1039 /* Unknown Frame Version. Abort Dissection. */
1040 expert_add_info(pinfo, proto_root, &ei_ieee802154_frame_ver);
1043 else if ((packet->version == IEEE802154_VERSION_2003) || /* For Frame Version 0b00 and */
1044 (packet->version == IEEE802154_VERSION_2006)) { /* 0b01 effect defined in section 7.2.1.5 */
1046 if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* if both destination and source */
1047 (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE)) { /* addressing information is present */
1048 if (packet->pan_id_compression == 1) { /* PAN IDs are identical */
1049 dstPanPresent = TRUE;
1050 srcPanPresent = FALSE; /* source PAN ID is omitted */
1052 else { /* PAN IDs are different, both shall be included in the frame */
1053 dstPanPresent = TRUE;
1054 srcPanPresent = TRUE;
1058 if (packet->pan_id_compression == 1) { /* all remaining cases pan_id_compression must be zero */
1059 expert_add_info(pinfo, proto_root, &ei_ieee802154_invalid_addressing);
1063 /* only either the destination or the source addressing information is present */
1064 if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
1065 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE)) { /* Not Present */
1066 dstPanPresent = TRUE;
1067 srcPanPresent = FALSE;
1069 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
1070 (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE)) { /* Present */
1071 dstPanPresent = FALSE;
1072 srcPanPresent = TRUE;
1074 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
1075 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE)) { /* Not Present */
1076 dstPanPresent = FALSE;
1077 srcPanPresent = FALSE;
1080 expert_add_info(pinfo, proto_root, &ei_ieee802154_invalid_addressing);
1086 else if (packet->version == IEEE802154_VERSION_2015) {
1087 /* for Frame Version 0b10 PAN Id Compression only applies to these frame types */
1088 if ((packet->frame_type == IEEE802154_FCF_BEACON) ||
1089 (packet->frame_type == IEEE802154_FCF_DATA) ||
1090 (packet->frame_type == IEEE802154_FCF_ACK) ||
1091 (packet->frame_type == IEEE802154_FCF_CMD) ) {
1093 /* Implements Table 7-6 of IEEE 802.15.4-2015
1095 * Destination Address Source Address Destination PAN ID Source PAN ID PAN ID Compression
1096 *-------------------------------------------------------------------------------------------------
1097 * 1. Not Present Not Present Not Present Not Present 0
1098 * 2. Not Present Not Present Present Not Present 1
1099 * 3. Present Not Present Present Not Present 0
1100 * 4. Present Not Present Not Present Not Present 1
1102 * 5. Not Present Present Not Present Present 0
1103 * 6. Not Present Present Not Present Not Present 1
1105 * 7. Extended Extended Present Not Present 0
1106 * 8. Extended Extended Not Present Not Present 1
1108 * 9. Short Short Present Present 0
1109 * 10. Short Extended Present Present 0
1110 * 11. Extended Short Present Present 0
1112 * 12. Short Extended Present Not Present 1
1113 * 13. Extended Short Present Not Present 1
1114 * 14. Short Short Present Not Present 1
1118 if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
1119 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
1120 (packet->pan_id_compression == 0)) {
1121 dstPanPresent = FALSE;
1122 srcPanPresent = FALSE;
1125 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
1126 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
1127 (packet->pan_id_compression == 1)) {
1128 dstPanPresent = TRUE;
1129 srcPanPresent = FALSE;
1132 else if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
1133 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
1134 (packet->pan_id_compression == 0)) {
1135 dstPanPresent = TRUE;
1136 srcPanPresent = FALSE;
1139 else if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
1140 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
1141 (packet->pan_id_compression == 1)) {
1142 dstPanPresent = FALSE;
1143 srcPanPresent = FALSE;
1146 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
1147 (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
1148 (packet->pan_id_compression == 0)) {
1149 dstPanPresent = FALSE;
1150 srcPanPresent = TRUE;
1153 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
1154 (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
1155 (packet->pan_id_compression == 1)) {
1156 dstPanPresent = FALSE;
1157 srcPanPresent = FALSE;
1160 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
1161 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
1162 (packet->pan_id_compression == 0)) {
1163 dstPanPresent = TRUE;
1164 srcPanPresent = FALSE;
1167 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
1168 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
1169 (packet->pan_id_compression == 1)) {
1170 dstPanPresent = FALSE;
1171 srcPanPresent = FALSE;
1174 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
1175 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
1176 (packet->pan_id_compression == 0)) {
1177 dstPanPresent = TRUE;
1178 srcPanPresent = TRUE;
1181 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
1182 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
1183 (packet->pan_id_compression == 0)) {
1184 dstPanPresent = TRUE;
1185 srcPanPresent = TRUE;
1188 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
1189 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
1190 (packet->pan_id_compression == 0)) {
1191 dstPanPresent = TRUE;
1192 srcPanPresent = TRUE;
1195 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
1196 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
1197 (packet->pan_id_compression == 1)) {
1198 dstPanPresent = TRUE;
1199 srcPanPresent = FALSE;
1202 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
1203 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
1204 (packet->pan_id_compression == 1)) {
1205 dstPanPresent = TRUE;
1206 srcPanPresent = FALSE;
1209 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
1210 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
1211 (packet->pan_id_compression == 1)) {
1212 dstPanPresent = TRUE;
1213 srcPanPresent = FALSE;
1216 expert_add_info(pinfo, proto_root, &ei_ieee802154_invalid_panid_compression2);
1220 else { /* Frame Type is neither Beacon, Data, Ack, nor Command: PAN ID Compression is not used */
1221 dstPanPresent = FALSE; /* no PAN ID will */
1222 srcPanPresent = FALSE; /* be present */
1226 /* Unknown Frame Version. Abort Dissection. */
1227 expert_add_info(pinfo, proto_root, &ei_ieee802154_frame_ver);
1235 /* Destination PAN Id */
1236 if (dstPanPresent) {
1237 packet->dst_pan = tvb_get_letohs(tvb, offset);
1238 if (ieee802154_tree) {
1239 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst_panID, tvb, offset, 2, packet->dst_pan);
1244 /* Destination Address */
1245 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1248 /* Get the address. */
1249 packet->dst16 = tvb_get_letohs(tvb, offset);
1251 /* Provide address hints to higher layers that need it. */
1253 ieee_hints->dst16 = packet->dst16;
1256 set_address_tvb(&pinfo->dl_dst, ieee802_15_4_short_address_type, 2, tvb, offset);
1257 copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
1258 dst_addr = address_to_str(wmem_packet_scope(), &pinfo->dst);
1260 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst16, tvb, offset, 2, packet->dst16);
1261 proto_item_append_text(proto_root, ", Dst: %s", dst_addr);
1263 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_addr);
1266 else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1267 guint64 *p_addr = (guint64 *)wmem_new(pinfo->pool, guint64);
1269 /* Get the address */
1270 packet->dst64 = tvb_get_letoh64(tvb, offset);
1272 /* Copy and convert the address to network byte order. */
1273 *p_addr = pntoh64(&(packet->dst64));
1275 /* Display the destination address. */
1276 /* XXX - OUI resolution doesn't happen when displaying resolved
1277 * EUI64 addresses; that should probably be fixed in
1278 * epan/addr_resolv.c.
1280 set_address(&pinfo->dl_dst, AT_EUI64, 8, p_addr);
1281 copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
1283 proto_tree_add_item(ieee802154_tree, hf_ieee802154_dst64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1284 proto_item_append_text(proto_root, ", Dst: %s", eui64_to_display(wmem_packet_scope(), packet->dst64));
1286 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", eui64_to_display(wmem_packet_scope(), packet->dst64));
1291 if (srcPanPresent) {
1292 packet->src_pan = tvb_get_letohs(tvb, offset);
1293 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src_panID, tvb, offset, 2, packet->src_pan);
1297 if (dstPanPresent) {
1298 packet->src_pan = packet->dst_pan;
1301 packet->src_pan = IEEE802154_BCAST_PAN;
1305 ieee_hints->src_pan = packet->src_pan;
1308 /* Source Address */
1309 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1312 /* Get the address. */
1313 packet->src16 = tvb_get_letohs(tvb, offset);
1315 if (!pinfo->fd->flags.visited) {
1316 /* If we know our extended source address from previous packets,
1317 * provide a pointer to it in a hint for upper layers */
1318 addr16.addr = packet->src16;
1319 addr16.pan = packet->src_pan;
1322 ieee_hints->src16 = packet->src16;
1323 ieee_hints->map_rec = (ieee802154_map_rec *)
1324 g_hash_table_lookup(ieee802154_map.short_table, &addr16);
1328 set_address_tvb(&pinfo->dl_src, ieee802_15_4_short_address_type, 2, tvb, offset);
1329 copy_address_shallow(&pinfo->src, &pinfo->dl_src);
1330 src_addr = address_to_str(wmem_packet_scope(), &pinfo->src);
1332 /* Add the addressing info to the tree. */
1334 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src16, tvb, offset, 2, packet->src16);
1335 proto_item_append_text(proto_root, ", Src: %s", src_addr);
1337 if (ieee_hints && ieee_hints->map_rec) {
1338 /* Display inferred source address info */
1339 ti = proto_tree_add_eui64(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 0,
1340 ieee_hints->map_rec->addr64);
1341 PROTO_ITEM_SET_GENERATED(ti);
1343 if ( ieee_hints->map_rec->start_fnum ) {
1344 ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src64_origin, tvb, 0, 0,
1345 ieee_hints->map_rec->start_fnum);
1348 ti = proto_tree_add_uint_format_value(ieee802154_tree, hf_ieee802154_src64_origin, tvb, 0, 0,
1349 ieee_hints->map_rec->start_fnum, "Pre-configured");
1351 PROTO_ITEM_SET_GENERATED(ti);
1355 col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_addr);
1359 else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1360 guint64 *p_addr = (guint64 *)wmem_new(pinfo->pool, guint64);
1362 /* Get the address. */
1363 packet->src64 = tvb_get_letoh64(tvb, offset);
1365 /* Copy and convert the address to network byte order. */
1366 *p_addr = pntoh64(&(packet->src64));
1368 /* Display the source address. */
1369 /* XXX - OUI resolution doesn't happen when displaying resolved
1370 * EUI64 addresses; that should probably be fixed in
1371 * epan/addr_resolv.c.
1373 set_address(&pinfo->dl_src, AT_EUI64, 8, p_addr);
1374 copy_address_shallow(&pinfo->src, &pinfo->dl_src);
1376 proto_tree_add_item(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1377 proto_item_append_text(proto_root, ", Src: %s", eui64_to_display(wmem_packet_scope(), packet->src64));
1380 col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", eui64_to_display(wmem_packet_scope(), packet->src64));
1385 /* Check, but don't display the FCS yet, otherwise the payload dissection
1386 * may be out of place in the tree. But we want to know if the FCS is OK in
1387 * case the CRC is bad (don't want to continue dissection to the NWK layer).
1389 if (tvb_bytes_exist(tvb, tvb_reported_length(tvb)-IEEE802154_FCS_LEN, IEEE802154_FCS_LEN)) {
1390 /* The FCS is in the last two bytes of the packet. */
1391 guint16 fcs = tvb_get_letohs(tvb, tvb_reported_length(tvb)-IEEE802154_FCS_LEN);
1392 /* Check if we are expecting a CC2420-style FCS*/
1393 if (options & DISSECT_IEEE802154_OPTION_CC24xx) {
1394 fcs_ok = (fcs & IEEE802154_CC24xx_CRC_OK);
1397 guint16 fcs_calc = ieee802154_crc_tvb(tvb, tvb_reported_length(tvb)-IEEE802154_FCS_LEN);
1398 fcs_ok = (fcs == fcs_calc);
1402 /* Existance of the Auxiliary Security Header is controlled by the Security Enabled Field */
1403 if (packet->security_enable) {
1404 proto_tree *header_tree, *field_tree;
1405 guint8 security_control;
1406 guint aux_length = 5; /* Minimum length of the auxiliary header. */
1407 static const int * security_fields[] = {
1408 &hf_ieee802154_security_level,
1409 &hf_ieee802154_key_id_mode,
1410 &hf_ieee802154_aux_sec_reserved,
1414 /* Parse the security control field. */
1415 security_control = tvb_get_guint8(tvb, offset);
1416 packet->security_level = (ieee802154_security_level)(security_control & IEEE802154_AUX_SEC_LEVEL_MASK);
1417 packet->key_id_mode = (ieee802154_key_id_mode)((security_control & IEEE802154_AUX_KEY_ID_MODE_MASK) >> IEEE802154_AUX_KEY_ID_MODE_SHIFT);
1419 /* Compute the length of the auxiliary header and create a subtree. */
1420 if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) aux_length++;
1421 if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) aux_length += 4;
1422 if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) aux_length += 8;
1423 header_tree = proto_tree_add_subtree(ieee802154_tree, tvb, offset, aux_length,
1424 ett_ieee802154_auxiliary_security, NULL, "Auxiliary Security Header");
1426 /* Security Control Field */
1427 proto_tree_add_bitmask(header_tree, tvb, offset, hf_ieee802154_security_control_field, ett_ieee802154_aux_sec_control, security_fields, ENC_NA);
1430 /* Frame Counter Field */
1431 packet->frame_counter = tvb_get_letohl (tvb, offset);
1432 proto_tree_add_uint(header_tree, hf_ieee802154_aux_sec_frame_counter, tvb, offset,4, packet->frame_counter);
1435 /* Key identifier field(s). */
1436 if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) {
1437 /* Create a subtree. */
1438 field_tree = proto_tree_add_subtree(header_tree, tvb, offset, 1,
1439 ett_ieee802154_aux_sec_key_id, &ti, "Key Identifier Field"); /* Will fix length later. */
1440 /* Add key source, if it exists. */
1441 if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) {
1442 packet->key_source.addr32 = tvb_get_ntohl(tvb, offset);
1443 proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, offset, 4, packet->key_source.addr32);
1444 proto_item_set_len(ti, 1 + 4);
1445 offset += (int)sizeof (guint32);
1447 if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) {
1448 packet->key_source.addr64 = tvb_get_ntoh64(tvb, offset);
1449 proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, offset, 8, packet->key_source.addr64);
1450 proto_item_set_len(ti, 1 + 8);
1453 /* Add key identifier. */
1454 packet->key_index = tvb_get_guint8(tvb, offset);
1455 proto_tree_add_uint(field_tree, hf_ieee802154_aux_sec_key_index, tvb, offset,1, packet->key_index);
1464 /* All of the beacon fields, except the beacon payload are considered nonpayload. */
1465 if ((packet->version == IEEE802154_VERSION_2003) || (packet->version == IEEE802154_VERSION_2006)) {
1466 if (packet->frame_type == IEEE802154_FCF_BEACON) { /* Regular Beacon. Some are not present in frame version (Enhanced) Beacons */
1467 dissect_ieee802154_superframe(tvb, pinfo, ieee802154_tree, &offset); /* superframe spec */
1468 dissect_ieee802154_gtsinfo(tvb, pinfo, ieee802154_tree, &offset); /* GTS information fields */
1469 dissect_ieee802154_pendaddr(tvb, pinfo, ieee802154_tree, &offset); /* Pending address list */
1472 if (packet->frame_type == IEEE802154_FCF_CMD) {
1474 * In IEEE802.15.4-2003 and 2006 the command identifier is considered to be part of the header
1475 * and is thus not encrypted. For IEEE802.15.4-2012e and later the command id is considered to be
1476 * part of the payload, is encrypted, and follows the payload IEs. Thus we only parse the command id
1477 * here for 2006 and earlier frames. */
1478 packet->command_id = tvb_get_guint8(tvb, offset);
1480 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_cmd_id, tvb, offset, 1, packet->command_id);
1484 /* Display the command identifier in the info column. */
1485 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
1489 if (packet->ie_present) {
1490 dissect_ieee802154_header_ie(tvb, pinfo, ieee802154_tree, &offset, packet);
1494 /* IEEE 802.15.4-2003 may have security information pre-pended to payload */
1495 if (packet->security_enable && (packet->version == IEEE802154_VERSION_2003)) {
1496 /* Store security suite preference in the 2006 security level identifier to simplify 2003 integration! */
1497 packet->security_level = (ieee802154_security_level)ieee802154_sec_suite;
1499 /* Frame Counter and Key Sequence Counter prepended to the payload of an encrypted frame */
1500 if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
1501 packet->frame_counter = tvb_get_letohl (tvb, offset);
1502 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_frame_counter, tvb, offset, (int)sizeof(guint32), packet->frame_counter);
1503 offset += (int)sizeof(guint32);
1505 packet->key_sequence_counter = tvb_get_guint8 (tvb, offset);
1506 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_key_sequence_counter, tvb, offset, (int)sizeof(guint8), packet->key_sequence_counter);
1507 offset += (int)sizeof(guint8);
1511 /* Encrypted Payload. */
1512 if (packet->security_enable) {
1513 payload_tvb = dissect_ieee802154_decrypt(tvb, offset, pinfo, packet, &status);
1515 /* Get the unencrypted data if decryption failed. */
1517 /* Deal with possible truncation and the FCS field at the end. */
1518 gint reported_len = tvb_reported_length(tvb)-offset-IEEE802154_FCS_LEN;
1519 gint captured_len = tvb_captured_length(tvb)-offset;
1520 if (reported_len < captured_len) captured_len = reported_len;
1521 payload_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
1524 /* Display the reason for failure, and abort if the error was fatal. */
1526 case DECRYPT_PACKET_SUCCEEDED:
1527 case DECRYPT_NOT_ENCRYPTED:
1531 case DECRYPT_VERSION_UNSUPPORTED:
1532 /* We don't support decryption with that version of the protocol */
1533 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "We don't support decryption with protocol version %u", packet->version);
1534 call_data_dissector(payload_tvb, pinfo, tree);
1535 goto dissect_ieee802154_fcs;
1537 case DECRYPT_PACKET_TOO_SMALL:
1538 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "Packet was too small to include the CRC and MIC");
1539 call_data_dissector(payload_tvb, pinfo, tree);
1540 goto dissect_ieee802154_fcs;
1542 case DECRYPT_PACKET_NO_EXT_SRC_ADDR:
1543 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "No extended source address - can't decrypt");
1544 call_data_dissector(payload_tvb, pinfo, tree);
1545 goto dissect_ieee802154_fcs;
1547 case DECRYPT_PACKET_NO_KEY:
1548 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "No encryption key set - can't decrypt");
1549 call_data_dissector(payload_tvb, pinfo, tree);
1550 goto dissect_ieee802154_fcs;
1552 case DECRYPT_PACKET_DECRYPT_FAILED:
1553 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "Decrypt failed");
1554 call_data_dissector(payload_tvb, pinfo, tree);
1555 goto dissect_ieee802154_fcs;
1557 case DECRYPT_PACKET_MIC_CHECK_FAILED:
1558 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "MIC check failed");
1560 * Abort only if the payload was encrypted, in which case we
1561 * probably didn't decrypt the packet right (eg: wrong key).
1563 if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
1564 call_data_dissector(payload_tvb, pinfo, tree);
1565 goto dissect_ieee802154_fcs;
1570 /* Plaintext Payload. */
1572 /* Deal with possible truncation and the FCS field at the end. */
1573 gint reported_len = tvb_reported_length(tvb)-offset-IEEE802154_FCS_LEN;
1574 gint captured_len = tvb_captured_length(tvb)-offset;
1575 if (reported_len < captured_len) captured_len = reported_len;
1576 payload_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
1579 /* presense of Payload IEs is defined by the termination of the Header IEs */
1581 if (packet->payload_ie_present) {
1582 offset += dissect_ieee802154_payload_ie(payload_tvb, pinfo, ieee802154_tree, offset);
1585 if ((packet->version == IEEE802154_VERSION_2015) && (packet->frame_type == IEEE802154_FCF_CMD)) {
1586 /* In 802.15.4e and later the Command Id follows the Payload IEs. */
1587 packet->command_id = tvb_get_guint8(payload_tvb, offset);
1589 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_cmd_id, payload_tvb, offset, 1, packet->command_id);
1593 /* Display the command identifier in the info column. */
1594 if ((packet->version == IEEE802154_VERSION_2015) && (packet->command_id == IEEE802154_CMD_BEACON_REQ)) {
1595 col_set_str(pinfo->cinfo, COL_INFO, "Enhanced Beacon Request");
1598 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
1603 payload_tvb = tvb_new_subset_remaining(payload_tvb, offset);
1607 /* If it is ok to dissect bad FCS, FCS might be absent, so still dissect
1608 * commands like Association request. */
1609 if ((!ieee802154_fcs_ok
1610 /* If either ZBOSS traffic dump or TI CC2{45}xx, FCS must be present. */
1611 && !(options & (DISSECT_IEEE802154_OPTION_ZBOSS | DISSECT_IEEE802154_OPTION_CC24xx)))
1612 || tvb_captured_length(payload_tvb) > 0) {
1614 * Wrap the sub-dissection in a try/catch block in case the payload is
1615 * broken. First we store the current protocol so we can fix it if an
1616 * exception is thrown by the subdissectors.
1618 saved_proto = pinfo->current_proto;
1619 /* Try to dissect the payload. */
1621 switch (packet->frame_type) {
1622 case IEEE802154_FCF_BEACON:
1623 if (!dissector_try_heuristic(ieee802154_beacon_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, packet)) {
1624 /* Could not subdissect, call the data dissector instead. */
1625 call_data_dissector(payload_tvb, pinfo, tree);
1629 case IEEE802154_FCF_CMD:
1630 dissect_ieee802154_command(payload_tvb, pinfo, ieee802154_tree, packet);
1633 case IEEE802154_FCF_DATA:
1635 if ((!fcs_ok && ieee802154_fcs_ok) || !tvb_reported_length(payload_tvb)) {
1636 call_data_dissector(payload_tvb, pinfo, tree);
1639 if (options & DISSECT_IEEE802154_OPTION_ZBOSS) {
1640 call_dissector_with_data(zigbee_nwk_handle, payload_tvb, pinfo, tree, packet);
1643 /* Try the PANID dissector table for stateful dissection. */
1644 if (dissector_try_uint_new(panid_dissector_table, packet->src_pan, payload_tvb, pinfo, tree, TRUE, packet)) {
1647 /* Try again with the destination PANID (if different) */
1648 if (((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) ||
1649 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)) &&
1650 (packet->dst_pan != packet->src_pan) &&
1651 dissector_try_uint_new(panid_dissector_table, packet->src_pan, payload_tvb, pinfo, tree, TRUE, packet)) {
1654 /* Try heuristic dissection. */
1655 if (dissector_try_heuristic(ieee802154_heur_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, packet)) break;
1656 /* Fall-through to dump undissectable payloads. */
1658 /* Could not subdissect, call the data dissector instead. */
1659 call_data_dissector(payload_tvb, pinfo, tree);
1664 * Someone encountered an error while dissecting the payload. But
1665 * we haven't yet finished processing all of our layer. Catch and
1666 * display the exception, then fall-through to finish displaying
1667 * the FCS (which we display last so the frame is ordered correctly
1670 show_exception(payload_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1671 pinfo->current_proto = saved_proto;
1676 * Frame Check Sequence (FCS)
1679 dissect_ieee802154_fcs:
1680 /* The FCS should be the last bytes of the reported packet. */
1681 offset = tvb_reported_length(tvb)-IEEE802154_FCS_LEN;
1682 /* Dissect the FCS only if it exists (captures which don't or can't get the
1683 * FCS will simply truncate the packet to omit it, but should still set the
1684 * reported length to cover the original packet length), so if the snapshot
1685 * is too short for an FCS don't make a fuss.
1687 if (tvb_bytes_exist(tvb, offset, IEEE802154_FCS_LEN) && (tree)) {
1688 proto_tree *field_tree;
1689 guint16 fcs = tvb_get_letohs(tvb, offset);
1691 /* Display the FCS depending on expected FCS format */
1692 if ((options & DISSECT_IEEE802154_OPTION_CC24xx)) {
1693 /* Create a subtree for the FCS. */
1694 field_tree = proto_tree_add_subtree_format(ieee802154_tree, tvb, offset, 2, ett_ieee802154_fcs, NULL,
1695 "Frame Check Sequence (TI CC24xx format): FCS %s", (fcs_ok) ? "OK" : "Bad");
1696 /* Display FCS contents. */
1697 proto_tree_add_int(field_tree, hf_ieee802154_rssi, tvb, offset++, 1, (gint8) (fcs & IEEE802154_CC24xx_RSSI));
1698 proto_tree_add_boolean(field_tree, hf_ieee802154_fcs_ok, tvb, offset, 1, (gboolean) (fcs & IEEE802154_CC24xx_CRC_OK));
1699 proto_tree_add_uint(field_tree, hf_ieee802154_correlation, tvb, offset, 1, (guint8) ((fcs & IEEE802154_CC24xx_CORRELATION) >> 8));
1702 ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_fcs, tvb, offset, 2, fcs);
1704 proto_item_append_text(ti, " (Correct)");
1707 proto_item_append_text(ti, " (Incorrect, expected FCS=0x%04x", ieee802154_crc_tvb(tvb, offset));
1709 /* To Help with filtering, add the fcs_ok field to the tree. */
1710 ti = proto_tree_add_boolean(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, offset, 2, fcs_ok);
1711 PROTO_ITEM_SET_HIDDEN(ti);
1715 /* Even if the FCS isn't present, add the fcs_ok field to the tree to
1716 * help with filter. Be sure not to make it visible though.
1718 ti = proto_tree_add_boolean_format_value(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, offset, 2, fcs_ok, "Unknown");
1719 PROTO_ITEM_SET_HIDDEN(ti);
1722 /* If the CRC is invalid, make a note of it in the info column. */
1724 col_append_str(pinfo->cinfo, COL_INFO, ", Bad FCS");
1725 if (tree) proto_item_append_text(proto_root, ", Bad FCS");
1727 /* Flag packet as having a bad crc. */
1728 expert_add_info(pinfo, proto_root, &ei_ieee802154_fcs);
1730 } /* dissect_ieee802154_common */
1733 *Subdissector command for the Header Information Element TSCH Time Correction
1735 *@param tvb pointer to buffer containing raw packet.
1736 *@param h_inf_elem_tree pointer to data tree wireshark uses to display packet.
1737 *@param offset offset into the tvbuff to begin dissection.
1740 dissect_802154_h_ie_time_correction(tvbuff_t *tvb, proto_tree *h_inf_elem_tree, guint *offset){
1742 guint16 time_correction;
1743 proto_tree *h_inf_elem_tree_payload = NULL;
1745 time_correction = tvb_get_letohs(tvb, *offset);
1747 h_inf_elem_tree_payload = proto_tree_add_subtree_format(h_inf_elem_tree, tvb, *offset, 2, ett_ieee802154_h_ie_payload, NULL,
1748 "Data: Time Correction IE, Content(0x%04x)", time_correction);
1750 if(time_correction <= 0x07ff) {
1751 proto_tree_add_item(h_inf_elem_tree_payload, hf_ieee802154_h_ie_time_correction1, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1753 else if ((time_correction >= 0x0800) && (time_correction <= 0x0fff)){
1754 proto_tree_add_item(h_inf_elem_tree_payload, hf_ieee802154_h_ie_time_correction2, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1756 else if ((time_correction >= 0x8000) && (time_correction <= 0x87ff)){
1757 proto_tree_add_item(h_inf_elem_tree_payload, hf_ieee802154_h_ie_time_correction3, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1759 else if ((time_correction >= 0x8800) && (time_correction <= 0x8fff )){
1760 proto_tree_add_item(h_inf_elem_tree_payload, hf_ieee802154_h_ie_time_correction4, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1763 } /* dissect_802154_h_ie_time_correction */
1766 *Subdissector command for the Payload Information Element MLME TSCH Channel Hopping
1768 *@param tvb pointer to buffer containing raw packet.
1769 *@param p_inf_elem_tree_mlme pointer to data tree wireshark uses to display packet.
1770 *@param psie_remaining size of the Information Element.
1771 *@param offset offset into the tvbuff to begin dissection.
1774 dissect_802154_p_ie_lg_mlme_channel_hopping(tvbuff_t *tvb, proto_tree *p_inf_elem_tree_mlme, guint16 psie_remaining, guint *offset){
1775 proto_tree *p_inf_elem_tree_mlme_payload = NULL;
1776 guint8 hopping_sequence_id;
1778 hopping_sequence_id = tvb_get_guint8(tvb, *offset);
1780 p_inf_elem_tree_mlme_payload = proto_tree_add_subtree_format(p_inf_elem_tree_mlme, tvb, *offset, 1, ett_ieee802154_mlme_payload, NULL,
1781 "Data: Channel Hopping IE (0x%0d)", hopping_sequence_id);
1783 proto_tree_add_uint(p_inf_elem_tree_mlme_payload, hf_ieee802154_p_ie_mlme_lg_hopping_sequence_id, tvb, (*offset), psie_remaining, hopping_sequence_id);
1785 if (psie_remaining > 1){
1786 proto_tree_add_item(p_inf_elem_tree_mlme_payload, hf_ieee802154_mlme_ie_data, tvb, *offset, psie_remaining, ENC_NA);
1788 *offset += psie_remaining;
1789 } /* dissect_802154_p_ie_lg_mlme_channel_hopping */
1792 *Subdissector command for the Payload Information Element MLME TSCH Synchronization
1794 *@param tvb pointer to buffer containing raw packet.
1795 *@param p_inf_elem_tree_mlme pointer to data tree wireshark uses to display packet.
1796 *@param psie_remaining size of the Information Element.
1797 *@param offset offset into the tvbuff to begin dissection.
1800 dissect_802154_p_ie_sh_mlme_tsch_sync(tvbuff_t *tvb, proto_tree *p_inf_elem_tree_mlme, guint psie_remaining, guint *offset){
1801 proto_tree *p_inf_elem_tree_mlme_payload = NULL;
1803 p_inf_elem_tree_mlme_payload = proto_tree_add_subtree_format(p_inf_elem_tree_mlme, tvb, *offset, psie_remaining, ett_ieee802154_mlme_payload, NULL,
1804 "Data: TSCH Synchronization IE");
1806 proto_tree_add_item(p_inf_elem_tree_mlme_payload, hf_ieee802154_p_ie_mlme_sh_tsch_asn, tvb, (*offset), 5, ENC_LITTLE_ENDIAN);
1807 proto_tree_add_item(p_inf_elem_tree_mlme_payload, hf_ieee802154_p_ie_mlme_sh_tsch_join_p, tvb, (*offset) + 5, 1, ENC_LITTLE_ENDIAN);
1809 }/* dissect_802154_p_ie_sh_mlme_tsch_sync*/
1812 *Subdissector command for the Payload Information Element MLME TSCH Slotframe and Link
1814 *@param tvb pointer to buffer containing raw packet.
1815 *@param p_inf_elem_tree_mlme pointer to data tree wireshark uses to display packet.
1816 *@param psie_remaining size of the Information Element.
1817 *@param offset offset into the tvbuff to begin dissection.
1820 dissect_802154_p_ie_sh_mlme_tsch_slotframe_link(tvbuff_t *tvb, proto_tree *p_inf_elem_tree_mlme, guint16 psie_remaining, guint *offset){
1821 guint8 nb_slotframes;
1822 guint8 nb_slotframes_aux;
1824 guint8 nb_links_aux;
1825 proto_tree *p_inf_elem_tree_mlme_payload = NULL;
1826 proto_tree *p_inf_elem_tree_mlme_payload_data = NULL;
1827 proto_tree *p_inf_elem_tree_psie_slotframe_link_slotframes = NULL;
1828 guint8 slotframe_index;
1829 nb_slotframes = tvb_get_guint8(tvb, *offset);
1830 nb_slotframes_aux = nb_slotframes;
1832 p_inf_elem_tree_mlme_payload = proto_tree_add_subtree_format(p_inf_elem_tree_mlme, tvb, *offset, psie_remaining, ett_ieee802154_mlme_payload, NULL,
1833 "Data: Slotframe and Link IE");
1834 proto_tree_add_item(p_inf_elem_tree_mlme_payload, hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_nb_slotf, tvb, (*offset), 1, ENC_LITTLE_ENDIAN);
1837 slotframe_index = 1;
1838 while ( nb_slotframes_aux > 0 ){
1839 nb_links = tvb_get_guint8(tvb, *offset+3);
1840 nb_links_aux = nb_links;
1842 p_inf_elem_tree_psie_slotframe_link_slotframes =
1843 proto_tree_add_subtree_format(p_inf_elem_tree_mlme_payload,
1844 tvb, *offset, 4 + 5 * nb_links_aux,
1845 ett_ieee802154_psie_slotframe_link_slotframes,
1846 NULL, "Slotframes [%u]", slotframe_index);
1847 slotframe_index += 1;
1849 proto_tree_add_item(p_inf_elem_tree_psie_slotframe_link_slotframes, hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_slotf_handle, tvb, (*offset), 1, ENC_LITTLE_ENDIAN);
1850 proto_tree_add_item(p_inf_elem_tree_psie_slotframe_link_slotframes, hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_slotf_size, tvb, (*offset) + 1, 2, ENC_LITTLE_ENDIAN);
1851 proto_tree_add_item(p_inf_elem_tree_psie_slotframe_link_slotframes, hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_nb_links, tvb, (*offset) + 3, 1, ENC_LITTLE_ENDIAN);
1853 nb_slotframes_aux -= 1;
1855 while (nb_links_aux > 0) {
1857 p_inf_elem_tree_mlme_payload_data = proto_tree_add_subtree_format(p_inf_elem_tree_psie_slotframe_link_slotframes, tvb, *offset, 5, ett_ieee802154_mlme_payload_data, NULL,
1858 "Data: Link Information");
1859 proto_tree_add_item(p_inf_elem_tree_mlme_payload_data, hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_timeslot, tvb, (*offset), 2, ENC_LITTLE_ENDIAN);
1860 proto_tree_add_item(p_inf_elem_tree_mlme_payload_data, hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_channel_offset, tvb, (*offset) + 2, 2, ENC_LITTLE_ENDIAN);
1861 proto_tree_add_item(p_inf_elem_tree_mlme_payload_data, hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_options, tvb, (*offset) + 4, 1, ENC_LITTLE_ENDIAN);
1866 }/* dissect_802154_p_ie_sh_mlme_tsch_slotframe_link */
1869 *Subdissector command for the 6TOP Protocol contained within the Payload Information Elements.
1871 *@param tvb pointer to buffer containing raw packet.
1872 *@param pinfo pointer to packet information fields.
1873 *@param p_inf_elem_tree pointer to data tree wireshark uses to display packet.
1874 *@param offset offset into the tvbuff to begin dissection.
1875 *@param pie_length size of the 6TOP message
1878 dissect_ieee802154_6top(tvbuff_t *tvb, packet_info *pinfo, proto_tree *p_inf_elem_tree, guint offset, gint pie_length)
1880 const guint8 supported_6p_version = 1;
1889 int orig_offset = offset;
1890 gboolean have_cell_list = FALSE;
1892 proto_tree *sixtop_tree = NULL;
1893 proto_tree *version_type_tree = NULL;
1894 proto_tree *seqnum_gab_gba_tree = NULL;
1895 proto_tree *cell_list_tree = NULL;
1896 proto_tree *cell_tree = NULL;
1897 proto_item *type_item = NULL;
1898 proto_item *code_item = NULL;
1899 const gchar *code_str = NULL;
1900 static const int * cell_options[] = {
1901 &hf_ieee802154_p_ie_6top_cell_option_tx,
1902 &hf_ieee802154_p_ie_6top_cell_option_rx,
1903 &hf_ieee802154_p_ie_6top_cell_option_shared,
1904 &hf_ieee802154_p_ie_6top_cell_option_reserved,
1908 if (pie_length < 5) {
1912 subie = tvb_get_guint8(tvb, offset);
1913 version = tvb_get_guint8(tvb, offset + 1) & IETF_6TOP_VERSION;
1915 if (subie != IEEE802154_IETF_SUBIE_6TOP || version != supported_6p_version) {
1919 type = (tvb_get_guint8(tvb, offset + 1) & IETF_6TOP_TYPE) >> 4;
1920 code = tvb_get_guint8(tvb, offset + 2);
1921 seqnum = tvb_get_guint8(tvb, offset + 4) & IETF_6TOP_SEQNUM;
1922 gab = (tvb_get_guint8(tvb, offset + 4) & IETF_6TOP_GAB) >> 4;
1923 gba = (tvb_get_guint8(tvb, offset + 4) & IETF_6TOP_GBA) >> 6;
1925 proto_tree_add_item(p_inf_elem_tree, hf_ieee802154_p_ie_ietf_sub_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1927 sixtop_tree = proto_tree_add_subtree_format(p_inf_elem_tree, tvb, offset, pie_length, ett_ieee802154_p_ie_6top, NULL, "6top IE Content");
1928 version_type_tree = proto_tree_add_subtree_format(sixtop_tree, tvb, offset + 1, 1, ett_ieee802154_p_ie_6top_version_type, NULL,
1929 "Version: %u, Type: %s", version, val_to_str_const(type, ietf_6top_types,"Unknown"));
1930 proto_tree_add_item(version_type_tree, hf_ieee802154_p_ie_6top_version, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
1931 type_item = proto_tree_add_item(version_type_tree, hf_ieee802154_p_ie_6top_type, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
1932 proto_tree_add_item(version_type_tree, hf_ieee802154_p_ie_6top_flags_reserved, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
1933 code_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_p_ie_6top_code, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
1934 proto_tree_add_item(sixtop_tree, hf_ieee802154_p_ie_6top_sfid, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
1935 seqnum_gab_gba_tree = proto_tree_add_subtree_format(sixtop_tree, tvb, offset + 4, 1, ett_ieee802154_p_ie_6top_seqnum_gab_gba, NULL,
1936 "Seqnum: %u, GAB: %u, GBA: %u", seqnum, gab, gba);
1937 proto_tree_add_item(seqnum_gab_gba_tree, hf_ieee802154_p_ie_6top_seqnum, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
1938 proto_tree_add_item(seqnum_gab_gba_tree, hf_ieee802154_p_ie_6top_gab, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
1939 proto_tree_add_item(seqnum_gab_gba_tree, hf_ieee802154_p_ie_6top_gba, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
1941 col_set_str(pinfo->cinfo, COL_PROTOCOL, "6top");
1942 if (type == IETF_6TOP_TYPE_REQUEST) {
1943 code_str = val_to_str_const(code, ietf_6top_command_identifiers,"Unknown");
1944 col_add_fstr(pinfo->cinfo, COL_INFO, "6P %s Request", code_str);
1946 code_str = val_to_str_const(code, ietf_6top_return_codes,"Unknown");
1947 col_add_fstr(pinfo->cinfo, COL_INFO, "6P %s (%s)",
1948 val_to_str_const(type, ietf_6top_types,"Unknown"), code_str);
1950 proto_item_append_text(code_item, " (%s)", code_str);
1955 if (type == IETF_6TOP_TYPE_REQUEST) {
1957 case IETF_6TOP_CMD_ADD:
1958 case IETF_6TOP_CMD_DELETE:
1959 if (pie_length < 4) {
1962 proto_tree_add_item(sixtop_tree, hf_ieee802154_p_ie_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1963 proto_tree_add_bitmask(sixtop_tree, tvb, offset + 2, hf_ieee802154_p_ie_6top_cell_options, ett_ieee802154_p_ie_6top_cell_options, cell_options, ENC_LITTLE_ENDIAN);
1964 proto_tree_add_item(sixtop_tree, hf_ieee802154_p_ie_6top_num_cells, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
1967 if (pie_length > 0 && (pie_length % 4) == 0) {
1968 have_cell_list = TRUE;
1971 case IETF_6TOP_CMD_STATUS:
1972 if (pie_length < 3) {
1975 proto_tree_add_item(sixtop_tree, hf_ieee802154_p_ie_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1976 proto_tree_add_bitmask(sixtop_tree, tvb, offset + 2, hf_ieee802154_p_ie_6top_cell_options, ett_ieee802154_p_ie_6top_cell_options, cell_options, ENC_LITTLE_ENDIAN);
1980 case IETF_6TOP_CMD_LIST:
1981 if (pie_length != 8) {
1984 proto_tree_add_item(sixtop_tree, hf_ieee802154_p_ie_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1985 proto_tree_add_bitmask(sixtop_tree, tvb, offset + 2, hf_ieee802154_p_ie_6top_cell_options, ett_ieee802154_p_ie_6top_cell_options, cell_options, ENC_LITTLE_ENDIAN);
1986 proto_tree_add_item(sixtop_tree, hf_ieee802154_p_ie_6top_reserved, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
1987 proto_tree_add_item(sixtop_tree, hf_ieee802154_p_ie_6top_offset, tvb, offset + 4, 2, ENC_LITTLE_ENDIAN);
1988 proto_tree_add_item(sixtop_tree, hf_ieee802154_p_ie_6top_max_num_cells, tvb, offset + 6, 2, ENC_LITTLE_ENDIAN);
1992 case IETF_6TOP_CMD_CLEAR:
1993 if (pie_length < 2) {
1996 proto_tree_add_item(sixtop_tree, hf_ieee802154_p_ie_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2001 /* unsupported command */
2002 expert_add_info(pinfo, code_item, &ei_ieee802154_p_ie_6top_code);
2005 } else if (type == IETF_6TOP_TYPE_RESPONSE || type == IETF_6TOP_TYPE_CONFIRMATION) {
2007 case IETF_6TOP_RC_SUCCESS:
2008 if (pie_length > 0) {
2009 if (pie_length == 1) {
2010 proto_tree_add_item(sixtop_tree, hf_ieee802154_p_ie_6top_num_cells, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2013 } else if ((pie_length % 4) == 0) {
2014 have_cell_list = TRUE;
2018 case IETF_6TOP_RC_ERR_VER:
2019 case IETF_6TOP_RC_ERR_SFID:
2020 case IETF_6TOP_RC_ERR_GEN:
2021 case IETF_6TOP_RC_ERR_BUSY:
2022 case IETF_6TOP_RC_ERR_NORES:
2023 case IETF_6TOP_RC_ERR_RESET:
2024 case IETF_6TOP_RC_ERR:
2025 /* They have no other field */
2028 /* unsupported return code */
2029 expert_add_info(pinfo, code_item, &ei_ieee802154_p_ie_6top_code);
2033 /* unsupported type */
2034 expert_add_info(pinfo, type_item, &ei_ieee802154_p_ie_6top_type);
2037 if (have_cell_list) {
2038 cell_list_tree = proto_tree_add_subtree_format(sixtop_tree, tvb, offset, pie_length, ett_ieee802154_p_ie_6top_cell_list, NULL,
2040 for (i = 0; pie_length > 0; pie_length -= 4, offset += 4, i++){
2041 cell_tree = proto_tree_add_subtree_format(cell_list_tree, tvb, offset, 4, ett_ieee802154_p_ie_6top_cell, NULL,
2043 proto_tree_add_item(cell_tree, hf_ieee802154_p_ie_6top_slot_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2044 proto_tree_add_item(cell_tree, hf_ieee802154_p_ie_6top_channel_offset, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
2048 return offset - orig_offset;
2049 } /* dissect_ieee802154_6top */
2052 *Subdissector command for the Superframe specification sub-field within the beacon frame.
2054 *@param tvb pointer to buffer containing raw packet.
2055 *@param pinfo pointer to packet information fields (unused).
2056 *@param tree pointer to command subtree.
2057 *@param offset offset into the tvbuff to begin dissection.
2060 dissect_ieee802154_superframe(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
2062 static const int * superframe[] = {
2063 &hf_ieee802154_beacon_order,
2064 &hf_ieee802154_superframe_order,
2066 &hf_ieee802154_superframe_battery_ext,
2067 &hf_ieee802154_superframe_coord,
2068 &hf_ieee802154_assoc_permit,
2072 proto_tree_add_bitmask_text(tree, tvb, *offset, 2, "Superframe Specification: ", NULL , ett_ieee802154_superframe, superframe, ENC_LITTLE_ENDIAN, BMT_NO_INT|BMT_NO_TFS);
2074 } /* dissect_ieee802154_superframe */
2077 *Subdissector command for the GTS information fields within the beacon frame.
2079 *@param tvb - pointer to buffer containing raw packet.
2080 *@param pinfo - pointer to packet information fields (unused).
2081 *@param tree - pointer to command subtree.
2082 *@param offset - offset into the tvbuff to begin dissection.
2085 dissect_ieee802154_gtsinfo(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
2087 proto_tree *field_tree = NULL;
2088 proto_tree *subtree = NULL;
2093 /* Get and display the GTS specification field */
2094 gts_spec = tvb_get_guint8(tvb, *offset);
2095 gts_count = gts_spec & IEEE802154_GTS_COUNT_MASK;
2097 /* Add Subtree for GTS information. */
2099 field_tree = proto_tree_add_subtree(tree, tvb, *offset, 2 + (gts_count * 3), ett_ieee802154_gts, NULL, "GTS");
2102 field_tree = proto_tree_add_subtree(tree, tvb, *offset, 1, ett_ieee802154_gts, NULL, "GTS");
2105 proto_tree_add_uint(field_tree, hf_ieee802154_gts_count, tvb, *offset, 1, gts_count);
2106 proto_tree_add_boolean(field_tree, hf_ieee802154_gts_permit, tvb, *offset, 1, gts_spec & IEEE802154_GTS_PERMIT_MASK);
2110 /* If the GTS descriptor count is nonzero, then the GTS directions mask and descriptor list are present. */
2112 guint8 gts_directions = tvb_get_guint8(tvb, *offset);
2116 /* Display the directions mask. */
2118 proto_tree *dir_tree;
2120 /* Create a subtree. */
2121 dir_tree = proto_tree_add_subtree(field_tree, tvb, *offset, 1, ett_ieee802154_gts_direction, &ti, "GTS Directions");
2123 /* Add the directions to the subtree. */
2124 for (i=0; i<gts_count; i++) {
2125 gboolean dir = gts_directions & IEEE802154_GTS_DIRECTION_SLOT(i);
2126 proto_tree_add_boolean_format(dir_tree, hf_ieee802154_gts_direction, tvb, *offset, 1, dir, "GTS Slot %i: %s", i+1, dir?"Receive Only":"Transmit Only");
2129 proto_item_append_text(ti, ": %i Receive & %i Transmit", gts_rx, gts_count - gts_rx);
2133 /* Create a subtree for the GTS descriptors. */
2134 subtree = proto_tree_add_subtree(field_tree, tvb, *offset, gts_count * 3, ett_ieee802154_gts_descriptors, NULL, "GTS Descriptors");
2136 /* Get and display the GTS descriptors. */
2137 for (i=0; i<gts_count; i++) {
2138 guint16 gts_addr = tvb_get_letohs(tvb, (*offset));
2139 guint8 gts_slot = tvb_get_guint8(tvb, (*offset)+2);
2140 guint8 gts_length = (gts_slot & IEEE802154_GTS_LENGTH_MASK) >> IEEE802154_GTS_LENGTH_SHIFT;
2142 gts_slot = (gts_slot & IEEE802154_GTS_SLOT_MASK);
2145 /* Add address, slot, and time length fields. */
2146 ti = proto_tree_add_uint(subtree, hf_ieee802154_gts_address, tvb, (*offset), 3, gts_addr);
2147 proto_item_append_text(ti, ", Slot: %i", gts_slot);
2148 proto_item_append_text(ti, ", Length: %i", gts_length);
2153 } /* dissect_ieee802154_gtsinfo */
2156 *Subdissector command for the pending address list fields within the beacon frame.
2158 *@param tvb pointer to buffer containing raw packet.
2159 *@param pinfo pointer to packet information fields (unused).
2160 *@param tree pointer to command subtree.
2161 *@offset offset into the tvbuff to begin dissection.
2164 dissect_ieee802154_pendaddr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
2166 proto_tree *subtree;
2172 /* Get the Pending Addresses specification fields */
2173 pend_spec = tvb_get_guint8(tvb, *offset);
2174 pend_num16 = pend_spec & IEEE802154_PENDADDR_SHORT_MASK;
2175 pend_num64 = (pend_spec & IEEE802154_PENDADDR_LONG_MASK) >> IEEE802154_PENDADDR_LONG_SHIFT;
2177 /* Add Subtree for the addresses */
2178 subtree = proto_tree_add_subtree_format(tree, tvb, *offset, 1 + 2*pend_num16 + 8*pend_num64,
2179 ett_ieee802154_pendaddr, NULL, "Pending Addresses: %i Short and %i Long", pend_num16, pend_num64);
2182 for (i=0; i<pend_num16; i++) {
2183 guint16 addr = tvb_get_letohs(tvb, *offset);
2184 proto_tree_add_uint(subtree, hf_ieee802154_pending16, tvb, *offset, 2, addr);
2187 for (i=0; i<pend_num64; i++) {
2188 proto_tree_add_item(subtree, hf_ieee802154_pending64, tvb, *offset, 8, ENC_LITTLE_ENDIAN);
2191 } /* dissect_ieee802154_pendaddr */
2194 *Subdissector for Header IEs (Information Elements)
2195 *Since the header is never encrypted and the payload may be encrypted,
2196 *we dissect header and payload IEs separately.
2197 *The termination of the Header IE tells us whether there are any
2198 *payload IEs to follow, so it is always set by the termination.
2200 *@param tvb pointer to buffer containing raw packet.
2201 *@param pinfo pointer to packet information fields (unused).
2202 *@param tree pointer to command subtree.
2203 *@param offset offset into the tvbuff to begin dissection.
2204 *@param packet IEEE 802.15.4 packet information.
2207 dissect_ieee802154_header_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset, ieee802154_packet *packet)
2209 proto_tree *subtree;
2213 GByteArray *gba = g_byte_array_new();
2215 static const int * fields[] = {
2216 &hf_ieee802154_header_ie_type,
2217 &hf_ieee802154_header_ie_id,
2218 &hf_ieee802154_header_ie_length,
2223 header_ie = tvb_get_letohs(tvb, *offset);
2224 id = (header_ie & IEEE802154_HEADER_IE_ID_MASK) >> 7;
2225 length = header_ie & IEEE802154_HEADER_IE_LENGTH_MASK;
2227 /* Create a subtree for this command frame. */
2228 subtree = proto_tree_add_subtree(tree, tvb, *offset, 2+length, ett_ieee802154_header, NULL, "Header IE");
2229 proto_item_append_text(subtree, ", Element ID: %s, Length: %d", val_to_str_const(id, ieee802154_header_ie_names, "Unknown IE"), length);
2231 proto_tree_add_bitmask(subtree, tvb, *offset, hf_ieee802154_header_ie,
2232 ett_ieee802154_header_ie, fields, ENC_LITTLE_ENDIAN);
2236 /* until the Header IEs are finalized, just use the data dissector */
2239 case IEEE802154_HEADER_IE_TIME_CORR:
2240 dissect_802154_h_ie_time_correction(tvb, subtree, offset);
2242 case IEEE802154_HEADER_VENDOR_SPECIFIC:
2243 case IEEE802154_HEADER_IE_CSL:
2244 case IEEE802154_HEADER_IE_RIT:
2245 case IEEE802154_HEADER_IE_DSME_PAN:
2246 case IEEE802154_HEADER_IE_RENDEZVOUS:
2247 case IEEE802154_HEADER_IE_EXT_DSME_PAN:
2248 case IEEE802154_HEADER_IE_FSCD:
2249 case IEEE802154_HEADER_IE_SMPL_SUPER_FRM:
2250 case IEEE802154_HEADER_IE_SMPL_GTS:
2251 case IEEE802154_HEADER_IE_LECIM:
2252 case IEEE802154_HEADER_IE_TRLE:
2253 case IEEE802154_HEADER_IE_RCC_CAP:
2254 case IEEE802154_HEADER_IE_RCCN:
2255 case IEEE802154_HEADER_IE_GLOBAL_TIME:
2256 case IEEE802154_HEADER_IE_DA_IE:
2258 proto_tree_add_bytes_item(subtree, hf_ieee802154_header_ie_data, tvb, *offset, length, ENC_NA, gba, NULL, NULL);
2263 } while ((tvb_reported_length_remaining(tvb, *offset) - IEEE802154_FCS_LEN > 1) &&
2264 (id != IEEE802154_HEADER_IE_EID_TERM1) &&
2265 (id != IEEE802154_HEADER_IE_EID_TERM2));
2267 /* Presense of Payload IEs is determined by how the Header IEs are terminated */
2268 if (id == IEEE802154_HEADER_IE_EID_TERM1) {
2269 packet->payload_ie_present = TRUE;
2272 packet->payload_ie_present = FALSE;
2275 } /* dissect_ieee802154_header_ie */
2278 *Subdissector command for MLME Payload Sub IEs (Information Elements)
2280 *@param tvb pointer to buffer containing raw packet.
2281 *@param pinfo pointer to packet information fields (unused).
2282 *@param tree pointer to command subtree.
2283 *@param offset offset into the tvbuff to begin dissection.
2286 dissect_ieee802154_payload_mlme_sub_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
2289 proto_tree *subtree;
2292 guint psie_remaining = 0;
2293 int orig_offset = offset;
2295 static const int * fields_short[] = {
2296 &hf_ieee802154_psie_type_short,
2297 &hf_ieee802154_psie_id_short,
2298 &hf_ieee802154_psie_length_short,
2302 static const int * fields_long[] = {
2303 &hf_ieee802154_psie_type_long,
2304 &hf_ieee802154_psie_id_long,
2305 &hf_ieee802154_psie_length_long,
2310 static const int * fields_eb_filter[] = {
2311 &hf_ieee802154_psie_eb_filter_pjoin,
2312 &hf_ieee802154_psie_eb_filter_lqi,
2313 &hf_ieee802154_psie_eb_filter_percent,
2314 &hf_ieee802154_psie_eb_filter_attr_id,
2319 psie_ie = tvb_get_letohs(tvb, offset);
2320 if (psie_ie & IEEE802154_PSIE_TYPE_MASK) { /* long format */
2321 psie_id = (psie_ie & IEEE802154_PSIE_ID_MASK_LONG) >> 11;
2322 psie_remaining = psie_ie & IEEE802154_PSIE_LENGTH_MASK_LONG;
2323 subtree = proto_tree_add_subtree(tree, tvb, offset, 2+psie_remaining, ett_ieee802154_psie_long, NULL, "Nested Sub IE (long)");
2324 proto_tree_add_bitmask(subtree, tvb, offset, hf_ieee802154_psie_long,
2325 ett_ieee802154_psie_long_bitmap, fields_long, ENC_LITTLE_ENDIAN);
2327 else { /* short format */
2328 psie_id = (psie_ie & IEEE802154_PSIE_ID_MASK_SHORT) >> 8;
2329 psie_remaining = psie_ie & IEEE802154_PSIE_LENGTH_MASK_SHORT;
2330 subtree = proto_tree_add_subtree(tree, tvb, offset, 2+psie_remaining, ett_ieee802154_psie_short, NULL, "Nested Sub IE (short)");
2331 proto_tree_add_bitmask(subtree, tvb, offset, hf_ieee802154_psie_short,
2332 ett_ieee802154_psie_short_bitmap, fields_short, ENC_LITTLE_ENDIAN);
2334 proto_item_append_text(subtree, ", Sub IE: %s, Length: %d", val_to_str_const(psie_id, ieee802154_psie_names, "Unknown IE"), psie_remaining);
2338 case IEEE802154_MLME_SUBIE_ENHANCED_BEACON_FILTER:
2342 guint32 attr_bitmap = 0;
2344 filter = tvb_get_guint8(tvb, offset);
2345 proto_tree_add_bitmask(subtree, tvb, offset, hf_ieee802154_psie_eb_filter,
2346 ett_ieee802154_psie_enh_beacon_flt_bitmap, fields_eb_filter,
2350 if (filter & IEEE802154_MLME_PSIE_EB_FLT_LQI) {
2351 proto_tree_add_item(subtree, hf_ieee802154_psie_eb_filter_lqi_min, tvb, offset, 1, ENC_NA);
2355 if (filter & IEEE802154_MLME_PSIE_EB_FLT_PERCENT) {
2356 proto_tree_add_item(subtree, hf_ieee802154_psie_eb_filter_percent_prob, tvb, offset, 1, ENC_NA);
2360 attr_len = (filter & IEEE802154_MLME_PSIE_EB_FLT_ATTR_LEN) >> 3;
2364 attr_bitmap = (guint32)tvb_get_guint8(tvb, offset);
2367 attr_bitmap = (guint32)tvb_get_ntohs(tvb, offset);
2370 attr_bitmap = tvb_get_ntoh24(tvb, offset);
2372 /* default: not reached, attr len is only 2 bits: 0x18 */
2375 /* just display in hex until we know how to decode */
2376 proto_tree_add_uint(subtree, hf_ieee802154_psie_eb_filter_attr_id_bitmap, tvb, offset,
2377 attr_len, attr_bitmap);
2383 case IEEE802154_MLME_SUBIE_TSCH_SYNCH:
2384 dissect_802154_p_ie_sh_mlme_tsch_sync(tvb, subtree, psie_remaining, &offset);
2386 case IEEE802154_MLME_SUBIE_TSCH_SLOTFR_LINK:
2387 dissect_802154_p_ie_sh_mlme_tsch_slotframe_link(tvb, subtree, psie_remaining, &offset);
2389 case IEEE802154_MLME_SUBIE_TSCH_TIMESLOT:
2390 if (psie_remaining) {
2391 proto_tree_add_item(subtree, hf_ieee802154_mlme_ie_data, tvb, offset, psie_remaining, ENC_NA);
2392 offset += psie_remaining;
2395 case IEEE802154_MLME_SUBIE_CHANNEL_HOPPING:
2396 dissect_802154_p_ie_lg_mlme_channel_hopping(tvb, subtree, psie_remaining, &offset);
2398 case IEEE802154_MLME_SUBIE_HOPPING_TIMING:
2399 case IEEE802154_MLME_SUBIE_MAC_METRICS:
2400 case IEEE802154_MLME_SUBIE_ALL_MAC_METRICS:
2401 case IEEE802154_MLME_SUBIE_COEXISTENCE_SPEC:
2402 case IEEE802154_MLME_SUBIE_SUN_DEVICE_CAPABILITIES:
2403 case IEEE802154_MLME_SUBIE_SUN_FSK_GEN_PHY:
2404 case IEEE802154_MLME_SUBIE_MODE_SWITCH_PARAMETER:
2405 case IEEE802154_MLME_SUBIE_PHY_PARAMETER_CHANGE:
2406 case IEEE802154_MLME_SUBIE_O_QPSK_PHY_MODE:
2407 case IEEE802154_MLME_SUBIE_PCA_ALLOCATION:
2408 case IEEE802154_MLME_SUBIE_DSSS_OPER_MODE:
2409 case IEEE802154_MLME_SUBIE_FSK_OPER_MODE:
2410 case IEEE802154_MLME_SUBIE_TVWS_PHY_OPE_MODE:
2411 case IEEE802154_MLME_SUBIE_TVWS_DEVICE_CAPAB:
2412 case IEEE802154_MLME_SUBIE_TVWS_DEVICE_CATEG:
2413 case IEEE802154_MLME_SUBIE_TVWS_DEVICE_IDENTIF:
2414 case IEEE802154_MLME_SUBIE_TVWS_DEVICE_LOCATION:
2415 case IEEE802154_MLME_SUBIE_TVWS_CH_INFOR_QUERY:
2416 case IEEE802154_MLME_SUBIE_TVWS_CH_INFOR_SOURCE:
2417 case IEEE802154_MLME_SUBIE_CTM:
2418 case IEEE802154_MLME_SUBIE_TIMESTAMP:
2419 case IEEE802154_MLME_SUBIE_TIMESTAMP_DIFF:
2420 case IEEE802154_MLME_SUBIE_TMCP_SPECIFICATION:
2421 case IEEE802154_MLME_SUBIE_RCC_PHY_OPER_MODE:
2424 if (psie_remaining) {
2425 proto_tree_add_item(subtree, hf_ieee802154_mlme_ie_data, tvb, offset, psie_remaining, ENC_NA);
2426 offset += psie_remaining;
2431 return (offset - orig_offset);
2435 *Subdissector command for Vendor Specific IEs (Information Elements)
2437 *@param tvb pointer to buffer containing the Vendor Specific IE
2438 *@param pinfo pointer to packet information fields (unused).
2439 *@param tree pointer to command subtree.
2440 *@param offset offset into the tvbuff to begin dissection.
2441 *@param pie_length the length of the Vendor Payload IE
2444 dissect_ieee802154_vendor_ie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, gint pie_length)
2449 vendor_oui = tvb_get_letoh24(tvb, offset);
2450 proto_item_append_text(tree, ", Vendor OUI: %06X (%s)", vendor_oui,
2451 val_to_str_const(vendor_oui, ieee802154_vendor_oui_names, "unknown"));
2452 proto_tree_add_uint_format_value(tree, hf_ieee802154_payload_ie_vendor_oui, tvb, offset, 3,
2453 vendor_oui, "%06X (%s)", vendor_oui, val_to_str_const(vendor_oui, ieee802154_vendor_oui_names, "unknown"));
2454 offset += 3; /* adjust for vendor OUI */
2456 next_tvb = tvb_new_subset_length(tvb, offset, pie_length);
2458 switch (vendor_oui) {
2459 case IEEE802154_VENDOR_OUI_ZIGBEE:
2460 call_dissector_with_data(zigbee_ie_handle, next_tvb, pinfo, tree, &pie_length);
2464 call_data_dissector(next_tvb, pinfo, tree);
2468 return pie_length + 3;
2472 *Subdissector command for Payload IEs (Information Elements)
2474 *@param tvb pointer to buffer containing raw packet.
2475 *@param pinfo pointer to packet information fields (unused).
2476 *@param tree pointer to command subtree.
2477 *@param offset offset into the tvbuff to begin dissection.
2480 dissect_ieee802154_payload_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
2482 proto_tree *subtree;
2488 static const int * fields[] = {
2489 &hf_ieee802154_payload_ie_type,
2490 &hf_ieee802154_payload_ie_id,
2491 &hf_ieee802154_payload_ie_length,
2495 orig_offset = offset;
2497 payload_ie = tvb_get_letohs(tvb, offset);
2498 pie_id = (payload_ie & IEEE802154_PAYLOAD_IE_ID_MASK) >> 11;
2499 pie_length = payload_ie & IEEE802154_PAYLOAD_IE_LENGTH_MASK;
2501 /* Create a subtree for this command frame. */
2502 subtree = proto_tree_add_subtree(tree, tvb, offset, pie_length + 2, ett_ieee802154_payload, NULL, "Payload IE");
2503 proto_item_append_text(subtree, ", %s, Length: %d", val_to_str_const(pie_id, ieee802154_payload_ie_names, "Unknown IE"), pie_length);
2504 proto_tree_add_bitmask(subtree, tvb, offset, hf_ieee802154_payload_ie,
2505 ett_ieee802154_payload_ie, fields, ENC_LITTLE_ENDIAN);
2509 case IEEE802154_PAYLOAD_IE_MLME:
2510 while (offset < (orig_offset + pie_length)) {
2511 offset += dissect_ieee802154_payload_mlme_sub_ie(tvb, pinfo, subtree, offset);
2515 case IEEE802154_PAYLOAD_IE_VENDOR:
2516 offset += dissect_ieee802154_vendor_ie(tvb, pinfo, subtree, offset, pie_length);
2519 case IEEE802154_PAYLOAD_IE_IETF:
2520 offset += dissect_ieee802154_6top(tvb, pinfo, subtree, offset, pie_length);
2523 default: /* just use the data dissector */
2524 if (pie_length > 0) {
2525 proto_tree_add_item(subtree, hf_ieee802154_payload_ie_data, tvb, offset, pie_length, ENC_NA);
2526 offset += pie_length;
2529 } while ((tvb_reported_length_remaining(tvb, offset) - IEEE802154_FCS_LEN > 1) && (pie_id != IEEE802154_PAYLOAD_IE_GID_TERM));
2531 return (offset - orig_offset);
2534 static const true_false_string tfs_cinfo_device_type = { "FFD", "RFD" };
2535 static const true_false_string tfs_cinfo_power_src = { "AC/Mains Power", "Battery" };
2538 *Command subdissector routine for the Association request command.
2540 *@param tvb pointer to buffer containing raw packet.
2541 *@param pinfo pointer to packet information fields.
2542 *@param tree pointer to protocol tree.
2543 *@param packet IEEE 802.15.4 packet information.
2547 dissect_ieee802154_assoc_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
2550 proto_tree *subtree;
2551 static const int * capability[] = {
2552 &hf_ieee802154_cinfo_alt_coord,
2553 &hf_ieee802154_cinfo_device_type,
2554 &hf_ieee802154_cinfo_power_src,
2555 &hf_ieee802154_cinfo_idle_rx,
2556 &hf_ieee802154_cinfo_sec_capable,
2557 &hf_ieee802154_cinfo_alloc_addr,
2561 cap = tvb_get_guint8(tvb, 0);
2562 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", (cap & IEEE802154_CMD_CINFO_DEVICE_TYPE) ? tfs_cinfo_device_type.true_string : tfs_cinfo_device_type.false_string);
2564 /* Create a subtree for this command frame. */
2565 subtree = proto_tree_add_subtree(tree, tvb, 0, 1, ett_ieee802154_cmd, NULL,
2566 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
2568 /* Get and display capability info. */
2569 proto_tree_add_bitmask_list(subtree, tvb, 0, 1, capability, ENC_NA);
2571 /* Call the data dissector for any leftover bytes. */
2572 if (tvb_reported_length(tvb) > 1) {
2573 call_data_dissector(tvb_new_subset_remaining(tvb, 1), pinfo, tree);
2575 } /* dissect_ieee802154_assoc_req */
2578 *Command subdissector routine for the Association response command.
2580 *@param tvb pointer to buffer containing raw packet.
2581 *@param pinfo pointer to packet information fields.
2582 *@param tree pointer to protocol tree.
2583 *@param packet IEEE 802.15.4 packet information.
2586 dissect_ieee802154_assoc_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
2588 proto_tree *subtree;
2594 /* Create a subtree for this command frame. */
2595 subtree = proto_tree_add_subtree(tree, tvb, offset, 3, ett_ieee802154_cmd, NULL,
2596 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
2598 /* Get and display the short address. */
2599 short_addr = tvb_get_letohs(tvb, offset);
2600 proto_tree_add_uint(subtree, hf_ieee802154_assoc_addr, tvb, offset, 2, short_addr);
2603 /* Get and display the status. */
2604 status = tvb_get_guint8(tvb, offset);
2606 ti = proto_tree_add_uint(subtree, hf_ieee802154_assoc_status, tvb, offset, 1, status);
2607 if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) proto_item_append_text(ti, " (Association Successful)");
2608 else if (status == IEEE802154_CMD_ASRSP_PAN_FULL) proto_item_append_text(ti, " (PAN Full)");
2609 else if (status == IEEE802154_CMD_ASRSP_PAN_DENIED) proto_item_append_text(ti, " (Association Denied)");
2610 else proto_item_append_text(ti, " (Reserved)");
2614 /* Update the info column. */
2615 if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) {
2616 /* Association was successful. */
2617 if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {
2618 col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", packet->dst_pan);
2620 if (short_addr != IEEE802154_NO_ADDR16) {
2621 col_append_fstr(pinfo->cinfo, COL_INFO, " Addr: 0x%04x", short_addr);
2625 /* Association was unsuccessful. */
2626 col_append_str(pinfo->cinfo, COL_INFO, ", Unsuccessful");
2629 /* Update the address table. */
2630 if ((status == IEEE802154_CMD_ASRSP_AS_SUCCESS) && (short_addr != IEEE802154_NO_ADDR16)) {
2631 ieee802154_addr_update(&ieee802154_map, short_addr, packet->dst_pan, packet->dst64,
2632 pinfo->current_proto, pinfo->num);
2635 /* Call the data dissector for any leftover bytes. */
2636 if (tvb_captured_length(tvb) > offset) {
2637 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
2639 } /* dissect_ieee802154_assoc_rsp */
2642 * Command subdissector routine for the Disassociate command.
2644 *@param tvb pointer to buffer containing raw packet.
2645 *@param pinfo pointer to packet information fields.
2646 *@param tree pointer to protocol tree.
2647 *@param packet IEEE 802.15.4 packet information.
2650 dissect_ieee802154_disassoc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
2652 proto_tree *subtree;
2656 /* Create a subtree for this command frame. */
2657 subtree = proto_tree_add_subtree(tree, tvb, 0, 1, ett_ieee802154_cmd, NULL,
2658 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
2660 /* Get and display the disassociation reason. */
2661 reason = tvb_get_guint8(tvb, 0);
2663 ti = proto_tree_add_uint(subtree, hf_ieee802154_disassoc_reason, tvb, 0, 1, reason);
2666 proto_item_append_text(ti, " (Coordinator requests device to leave)");
2670 proto_item_append_text(ti, " (Device wishes to leave)");
2674 proto_item_append_text(ti, " (Reserved)");
2679 if (!pinfo->fd->flags.visited) {
2680 /* Update the address tables */
2681 if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT ) {
2682 ieee802154_long_addr_invalidate(packet->dst64, pinfo->num);
2683 } else if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT ) {
2684 ieee802154_short_addr_invalidate(packet->dst16, packet->dst_pan, pinfo->num);
2688 /* Call the data dissector for any leftover bytes. */
2689 if (tvb_captured_length(tvb) > 1) {
2690 call_data_dissector(tvb_new_subset_remaining(tvb, 1), pinfo, tree);
2692 } /* dissect_ieee802154_disassoc */
2695 * Command subdissector routine for the Coordinator Realignment command.
2697 *@param tvb pointer to buffer containing raw packet.
2698 *@param pinfo pointer to packet information fields.
2699 *@param tree pointer to protocol tree.
2700 *@param packet IEEE 802.15.4 packet information.
2703 dissect_ieee802154_realign(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
2705 proto_tree *subtree;
2706 proto_item *subitem;
2713 /* Create a subtree for this command frame. */
2714 subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_ieee802154_cmd, &subitem,
2715 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
2717 /* Get and display the command PAN ID. */
2718 pan_id = tvb_get_letohs(tvb, offset);
2719 proto_tree_add_uint(subtree, hf_ieee802154_realign_pan, tvb, offset, 2, pan_id);
2720 col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", pan_id);
2723 /* Get and display the coordinator address. */
2724 coord_addr = tvb_get_letohs(tvb, offset);
2725 proto_tree_add_uint(subtree, hf_ieee802154_realign_caddr, tvb, offset, 2, coord_addr);
2726 col_append_fstr(pinfo->cinfo, COL_INFO, ", Coordinator: 0x%04x", coord_addr);
2729 /* Get and display the channel. */
2730 channel = tvb_get_guint8(tvb, offset);
2731 proto_tree_add_uint(subtree, hf_ieee802154_realign_channel, tvb, offset, 1, channel);
2732 col_append_fstr(pinfo->cinfo, COL_INFO, ", Channel: %u", channel);
2735 /* Get and display the short address. */
2736 short_addr = tvb_get_letohs(tvb, offset);
2737 if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_addr, tvb, offset, 2, short_addr);
2738 if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)
2739 && (short_addr != IEEE802154_NO_ADDR16)) {
2740 col_append_fstr(pinfo->cinfo, COL_INFO, ", Addr: 0x%04x", short_addr);
2743 /* Update the address table. */
2744 if ((short_addr != IEEE802154_NO_ADDR16) && (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)) {
2745 ieee802154_addr_update(&ieee802154_map, short_addr, packet->dst_pan, packet->dst64,
2746 pinfo->current_proto, pinfo->num);
2749 /* Get and display the channel page, if it exists. Added in IEEE802.15.4-2006 */
2750 if (tvb_bytes_exist(tvb, offset, 1)) {
2751 guint8 channel_page = tvb_get_guint8(tvb, offset);
2752 if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_channel_page, tvb, offset, 1, channel_page);
2756 /* Fix the length of the command subtree. */
2758 proto_item_set_len(subitem, offset);
2761 /* Call the data dissector for any leftover bytes. */
2762 if (tvb_captured_length(tvb) > offset) {
2763 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
2765 } /* dissect_ieee802154_realign */
2767 static const true_false_string tfs_gtsreq_dir = { "Receive", "Transmit" };
2768 static const true_false_string tfs_gtsreq_type= { "Allocate GTS", "Deallocate GTS" };
2771 *Command subdissector routine for the GTS request command.
2773 *Assumes that COL_INFO will be set to the command name,
2774 *command name will already be appended to the command subtree
2775 *and protocol root. In addition, assumes that the command ID
2776 *has already been parsed.
2778 *@param tvb pointer to buffer containing raw packet.
2779 *@param pinfo pointer to packet information fields (unused).
2780 *@param tree pointer to protocol tree.
2781 *@param packet IEEE 802.15.4 packet information (unused).
2785 dissect_ieee802154_gtsreq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
2787 proto_tree *subtree;
2788 static const int * characteristics[] = {
2789 &hf_ieee802154_gtsreq_len,
2790 &hf_ieee802154_gtsreq_dir,
2791 &hf_ieee802154_gtsreq_type,
2795 /* Create a subtree for this command frame. */
2796 subtree = proto_tree_add_subtree(tree, tvb, 0, 1, ett_ieee802154_cmd, NULL,
2797 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
2799 proto_tree_add_bitmask_list(subtree, tvb, 0, 1, characteristics, ENC_NA);
2801 /* Call the data dissector for any leftover bytes. */
2802 if (tvb_reported_length(tvb) > 1) {
2803 call_data_dissector(tvb_new_subset_remaining(tvb, 1), pinfo, tree);
2805 } /* dissect_ieee802154_gtsreq */
2808 * Subdissector routine all commands.
2810 *@param tvb pointer to buffer containing raw packet.
2811 *@param pinfo pointer to packet information fields (unused).
2812 *@param tree pointer to protocol tree.
2813 *@param packet IEEE 802.15.4 packet information (unused).
2816 dissect_ieee802154_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
2818 switch (packet->command_id) {
2819 case IEEE802154_CMD_ASSOC_REQ:
2820 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
2821 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
2822 (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
2823 dissect_ieee802154_assoc_req(tvb, pinfo, tree, packet);
2826 case IEEE802154_CMD_ASSOC_RSP:
2827 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
2828 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
2829 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
2830 dissect_ieee802154_assoc_rsp(tvb, pinfo, tree, packet);
2833 case IEEE802154_CMD_DISASSOC_NOTIFY:
2834 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
2835 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
2836 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
2837 dissect_ieee802154_disassoc(tvb, pinfo, tree, packet);
2840 case IEEE802154_CMD_DATA_RQ:
2841 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id, packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE);
2842 /* No payload expected. */
2845 case IEEE802154_CMD_PANID_CONFLICT:
2846 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
2847 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
2848 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
2849 /* No payload expected. */
2852 case IEEE802154_CMD_ORPHAN_NOTIFY:
2853 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
2854 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
2855 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
2856 (packet->dst16 == IEEE802154_BCAST_ADDR) &&
2857 (packet->src_pan == IEEE802154_BCAST_PAN) &&
2858 (packet->dst_pan == IEEE802154_BCAST_PAN));
2859 /* No payload expected. */
2862 case IEEE802154_CMD_BEACON_REQ:
2863 if ((packet->version == IEEE802154_VERSION_2003) || (packet->version == IEEE802154_VERSION_2006)) {
2864 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
2865 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
2866 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
2867 (packet->dst16 == IEEE802154_BCAST_ADDR) &&
2868 (packet->dst_pan == IEEE802154_BCAST_PAN));
2870 /* No payload expected. */
2873 case IEEE802154_CMD_COORD_REALIGN:
2874 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
2875 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
2876 (packet->dst_pan == IEEE802154_BCAST_PAN) &&
2877 (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
2878 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
2879 /* If directed to a 16-bit address, check that it is being broadcast. */
2880 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id, packet->dst16 == IEEE802154_BCAST_ADDR);
2882 dissect_ieee802154_realign(tvb, pinfo, tree, packet);
2885 case IEEE802154_CMD_GTS_REQ:
2886 /* Check that the addressing is correct for this command type. */
2887 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
2888 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
2889 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
2890 (packet->src16 != IEEE802154_BCAST_ADDR) &&
2891 (packet->src16 != IEEE802154_NO_ADDR16));
2892 dissect_ieee802154_gtsreq(tvb, pinfo, tree, packet);
2895 case IEEE802154_CMD_TRLE_MGMT_REQ:
2896 case IEEE802154_CMD_TRLE_MGMT_RSP:
2897 case IEEE802154_CMD_DSME_ASSOC_REQ:
2898 case IEEE802154_CMD_DSME_ASSOC_RSP:
2899 case IEEE802154_CMD_DSME_GTS_REQ:
2900 case IEEE802154_CMD_DSME_GTS_RSP:
2901 case IEEE802154_CMD_DSME_GTS_NOTIFY:
2902 case IEEE802154_CMD_DSME_INFO_REQ:
2903 case IEEE802154_CMD_DSME_INFO_RSP:
2904 case IEEE802154_CMD_DSME_BEACON_ALLOC_NOTIFY:
2905 case IEEE802154_CMD_DSME_BEACON_COLL_NOTIFY:
2906 case IEEE802154_CMD_DSME_LINK_REPORT:
2907 case IEEE802154_CMD_RIT_DATA_REQ:
2908 case IEEE802154_CMD_DBS_REQ:
2909 case IEEE802154_CMD_DBS_RSP:
2910 /* TODO add support for these commands, for now
2911 * if anything remains other than the FCS, dump it */
2912 if (tvb_captured_length_remaining(tvb, 0) > 2) {
2913 call_data_dissector(tvb, pinfo, tree);
2918 } /* dissect_ieee802154_command */
2921 *IEEE 802.15.4 decryption algorithm. Tries to find the
2922 *appropriate key from the information in the IEEE 802.15.4
2923 *packet structure and dissector config.
2925 *This function implements the security proceedures for the
2926 *2006 version of the spec only. IEEE 802.15.4-2003 is
2928 *@param tvb IEEE 802.15.4 packet.
2929 *@param pinfo Packet info structure.
2930 *@param offset Offset where the ciphertext 'c' starts.
2931 *@param packet IEEE 802.15.4 packet information.
2932 *@param status status of decryption returned through here on failure.
2933 *@return decrypted payload.
2936 dissect_ieee802154_decrypt(tvbuff_t *tvb, guint offset, packet_info *pinfo, ieee802154_packet *packet, ws_decrypt_status *status)
2938 tvbuff_t *ptext_tvb;
2939 gboolean have_mic = FALSE;
2941 unsigned char key[16];
2942 unsigned char tmp[16];
2943 unsigned char rx_mic[16];
2947 ieee802154_hints_t *ieee_hints;
2950 * Check the version; we only support IEEE 802.15.4-2003 and IEEE 802.15.4-2006.
2951 * We must do this first, as, if this isn't IEEE 802.15.4-2003 or IEEE 802.15.4-2006,
2952 * we don't have the Auxiliary Security Header, and haven't
2953 * filled in the information for it, and none of the stuff
2954 * we do afterwards, which uses that information, is doable.
2956 if ((packet->version != IEEE802154_VERSION_2006) && (packet->version != IEEE802154_VERSION_2003)) {
2957 *status = DECRYPT_VERSION_UNSUPPORTED;
2961 ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
2963 /* Get the captured and on-the-wire length of the payload. */
2964 M = IEEE802154_MIC_LENGTH(packet->security_level);
2965 reported_len = tvb_reported_length_remaining(tvb, offset) - IEEE802154_FCS_LEN - M;
2966 if (reported_len < 0) {
2967 *status = DECRYPT_PACKET_TOO_SMALL;
2970 /* Check of the payload is truncated. */
2971 if (tvb_bytes_exist(tvb, offset, reported_len)) {
2972 captured_len = reported_len;
2975 captured_len = tvb_captured_length_remaining(tvb, offset);
2978 /* Check if the MIC is present in the captured data. */
2979 have_mic = tvb_bytes_exist(tvb, offset + reported_len, M);
2981 tvb_memcpy(tvb, rx_mic, offset + reported_len, M);
2985 * Key Lookup - Need to find the appropriate key.
2989 * Oh God! The specification is so bad. This is the worst
2990 * case of design-by-committee I've ever seen in my life.
2991 * The IEEE has created an unintelligible mess in order
2992 * to decipher which key is used for which message.
2994 * Let's hope it's simpler to implement for dissecting only.
2996 * Also need to find the extended address of the sender.
2998 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
2999 /* The source EUI-64 is included in the headers. */
3000 srcAddr = packet->src64;
3002 else if (ieee_hints && ieee_hints->map_rec && ieee_hints->map_rec->addr64) {
3004 srcAddr = ieee_hints->map_rec->addr64;
3007 /* Lookup failed. */
3008 *status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
3012 /* Lookup the key. */
3014 * TODO: What this dissector really needs is a UAT to store multiple keys
3015 * and a variety of key configuration data. However, a single shared key
3016 * should be sufficient to get packet encryption off to a start.
3018 if (!ieee802154_key_valid) {
3019 *status = DECRYPT_PACKET_NO_KEY;
3022 memcpy(key, ieee802154_key, IEEE802154_CIPHER_SIZE);
3025 * CCM* - CTR mode payload encryption
3028 /* Create the CCM* initial block for decryption (Adata=0, M=0, counter=0). */
3029 ccm_init_block(tmp, FALSE, 0, srcAddr, packet, 0);
3031 /* Decrypt the ciphertext, and place the plaintext in a new tvb. */
3032 if (IEEE802154_IS_ENCRYPTED(packet->security_level) && captured_len) {
3035 * Make a copy of the ciphertext in heap memory.
3037 * We will decrypt the message in-place and then use the buffer as the
3038 * real data for the new tvb.
3040 text = (guint8 *)tvb_memdup(pinfo->pool, tvb, offset, captured_len);
3042 /* Perform CTR-mode transformation. */
3043 if (!ccm_ctr_encrypt(key, tmp, rx_mic, text, captured_len)) {
3045 *status = DECRYPT_PACKET_DECRYPT_FAILED;
3049 /* Create a tvbuff for the plaintext. */
3050 ptext_tvb = tvb_new_child_real_data(tvb, text, captured_len, reported_len);
3051 add_new_data_source(pinfo, ptext_tvb, "Decrypted IEEE 802.15.4 payload");
3052 *status = DECRYPT_PACKET_SUCCEEDED;
3054 /* There is no ciphertext. Wrap the plaintext in a new tvb. */
3056 /* Decrypt the MIC (if present). */
3057 if ((have_mic) && (!ccm_ctr_encrypt(key, tmp, rx_mic, NULL, 0))) {
3058 *status = DECRYPT_PACKET_DECRYPT_FAILED;
3062 /* Create a tvbuff for the plaintext. This might result in a zero-length tvbuff. */
3063 ptext_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
3064 *status = DECRYPT_PACKET_SUCCEEDED;
3068 * CCM* - CBC-mode message authentication
3071 /* We can only verify the message if the MIC wasn't truncated. */
3073 unsigned char dec_mic[16];
3074 guint l_m = captured_len;
3077 /* Adjust the lengths of the plaintext and additional data if unencrypted. */
3078 if (!IEEE802154_IS_ENCRYPTED(packet->security_level)) {
3082 else if ((packet->version == IEEE802154_VERSION_2003) && !ieee802154_extend_auth)
3083 l_a -= 5; /* Exclude Frame Counter (4 bytes) and Key Sequence Counter (1 byte) from authentication data */
3086 /* Create the CCM* initial block for authentication (Adata!=0, M!=0, counter=l(m)). */
3087 ccm_init_block(tmp, TRUE, M, srcAddr, packet, l_m);
3089 /* Compute CBC-MAC authentication tag. */
3091 * And yes, despite the warning in tvbuff.h, I think tvb_get_ptr is the
3092 * right function here since either A) the payload wasn't encrypted, in
3093 * which case l_m is zero, or B) the payload was encrypted, and the tvb
3094 * already points to contiguous memory, since we just allocated it in
3097 if (!ccm_cbc_mac(key, tmp, (const gchar *)tvb_memdup(wmem_packet_scope(), tvb, 0, l_a), l_a, tvb_get_ptr(ptext_tvb, 0, l_m), l_m, dec_mic)) {
3098 *status = DECRYPT_PACKET_MIC_CHECK_FAILED;
3100 /* Compare the received MIC with the one we generated. */
3101 else if (memcmp(rx_mic, dec_mic, M) != 0) {
3102 *status = DECRYPT_PACKET_MIC_CHECK_FAILED;
3108 } /* dissect_ieee802154_decrypt */
3111 *Creates the CCM* initial block value for IEEE 802.15.4.
3113 *@param block Output pointer for the initial block.
3114 *@param adata TRUE if additional auth data is present
3115 *@param M CCM* parameter M.
3116 *@param addr Source extended address.
3117 *@param packet IEEE 802.15.4 packet information.
3118 *@param ctr_val Value in the last L bytes of the block.
3121 ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, ieee802154_packet *packet, gint ctr_val)
3125 /* Flags: Reserved(0) || Adata || (M-2)/2 || (L-1) */
3126 block[i] = (0x2 - 1); /* (L-1) */
3127 if (M > 0) block[i] |= (((M-2)/2) << 3); /* (M-2)/2 */
3128 if (adata) block[i] |= (1 << 6); /* Adata */
3130 /* 2003 CCM Nonce: Source Address || Frame Counter || Key Sequence Counter */
3131 /* 2006 CCM* Nonce: Source Address || Frame Counter || Security Level */
3132 block[i++] = (guint8)((addr >> 56) & 0xff);
3133 block[i++] = (guint8)((addr >> 48) & 0xff);
3134 block[i++] = (guint8)((addr >> 40) & 0xff);
3135 block[i++] = (guint8)((addr >> 32) & 0xff);
3136 block[i++] = (guint8)((addr >> 24) & 0xff);
3137 block[i++] = (guint8)((addr >> 16) & 0xff);
3138 block[i++] = (guint8)((addr >> 8) & 0xff);
3139 block[i++] = (guint8)((addr >> 0) & 0xff);
3140 block[i++] = (guint8)((packet->frame_counter >> 24) & 0xff);
3141 block[i++] = (guint8)((packet->frame_counter >> 16) & 0xff);
3142 block[i++] = (guint8)((packet->frame_counter >> 8) & 0xff);
3143 block[i++] = (guint8)((packet->frame_counter >> 0) & 0xff);
3144 if (packet->version == IEEE802154_VERSION_2003)
3145 block[i++] = packet->key_sequence_counter;
3147 block[i++] = packet->security_level;
3148 /* Plaintext length. */
3149 block[i++] = (guint8)((ctr_val >> 8) & 0xff);
3150 block[i] = (guint8)((ctr_val >> 0) & 0xff);
3151 } /* ccm_init_block */
3154 * Perform an in-place CTR-mode encryption/decryption.
3156 *@param key Encryption Key.
3157 *@param iv Counter initial value.
3158 *@param mic MIC to encrypt/decrypt.
3159 *@param data Buffer to encrypt/decrypt.
3160 *@param length Length of the buffer.
3161 *@return TRUE on SUCCESS, FALSE on error.
3163 #ifdef HAVE_LIBGCRYPT
3165 ccm_ctr_encrypt(const gchar *key, const gchar *iv, gchar *mic, gchar *data, gint length)
3167 gcry_cipher_hd_t cipher_hd;
3169 /* Open the cipher. */
3170 if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0)) {
3174 /* Set the key and initial value. */
3175 if (gcry_cipher_setkey(cipher_hd, key, 16)) {
3176 gcry_cipher_close(cipher_hd);
3179 if (gcry_cipher_setctr(cipher_hd, iv, 16)) {
3180 gcry_cipher_close(cipher_hd);
3184 /* Decrypt the MIC. */
3185 if (gcry_cipher_encrypt(cipher_hd, mic, 16, NULL, 0)) {
3186 gcry_cipher_close(cipher_hd);
3189 /* Decrypt the payload. */
3190 if (gcry_cipher_encrypt(cipher_hd, data, length, NULL, 0)) {
3191 gcry_cipher_close(cipher_hd);
3195 /* Done with the cipher. */
3196 gcry_cipher_close(cipher_hd);
3198 } /* ccm_ctr_encrypt */
3201 ccm_ctr_encrypt(const gchar *key _U_, const gchar *iv _U_, gchar *mic _U_, gchar *data _U_, gint length _U_)
3205 #endif /* HAVE_LIBGCRYPT */
3208 *Generate a CBC-MAC of the decrypted payload and additional authentication headers.
3209 *@param key Encryption Key.
3210 *@param iv Counter initial value.
3211 *@param a Additional auth headers.
3212 *@param a_len Length of the additional headers.
3213 *@param m Plaintext message.
3214 *@param m_len Length of plaintext message.
3215 *@param mic Output for CBC-MAC.
3216 *@return TRUE on SUCCESS, FALSE on error.
3218 #ifdef HAVE_LIBGCRYPT
3220 ccm_cbc_mac(const gchar *key, const gchar *iv, const gchar *a, gint a_len, const gchar *m, gint m_len, gchar *mic)
3222 gcry_cipher_hd_t cipher_hd;
3224 unsigned char block[16];
3226 /* Open the cipher. */
3227 if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_MAC)) return FALSE;
3230 if (gcry_cipher_setkey(cipher_hd, key, 16)) {
3231 gcry_cipher_close(cipher_hd);
3235 /* Process the initial value. */
3236 if (gcry_cipher_encrypt(cipher_hd, mic, 16, iv, 16)) {
3237 gcry_cipher_close(cipher_hd);
3244 /* XXX: GINT_MAX is not defined so #if ... will always be false */
3245 #if (GINT_MAX >= (1LL << 32))
3246 if (a_len >= (1LL << 32)) {
3249 block[i++] = (a_len >> 56) & 0xff;
3250 block[i++] = (a_len >> 48) & 0xff;
3251 block[i++] = (a_len >> 40) & 0xff;
3252 block[i++] = (a_len >> 32) & 0xff;
3253 block[i++] = (a_len >> 24) & 0xff;
3254 block[i++] = (a_len >> 16) & 0xff;
3255 block[i++] = (a_len >> 8) & 0xff;
3256 block[i++] = (a_len >> 0) & 0xff;
3260 if (a_len >= ((1 << 16) - (1 << 8))) {
3263 block[i++] = (a_len >> 24) & 0xff;
3264 block[i++] = (a_len >> 16) & 0xff;
3265 block[i++] = (a_len >> 8) & 0xff;
3266 block[i++] = (a_len >> 0) & 0xff;
3269 block[i++] = (a_len >> 8) & 0xff;
3270 block[i++] = (a_len >> 0) & 0xff;
3272 /* Append a to get the first block of input (pad if we encounter the end of a). */
3273 while ((i < sizeof(block)) && (a_len-- > 0)) block[i++] = *a++;
3274 while (i < sizeof(block)) block[i++] = 0;
3276 /* Process the first block of AuthData. */
3277 if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, 16)) {
3278 gcry_cipher_close(cipher_hd);
3282 /* Transform and process the remainder of a. */
3285 if ((guint)a_len >= sizeof(block)) memcpy(block, a, sizeof(block));
3286 else {memcpy(block, a, a_len); memset(block+a_len, 0, sizeof(block)-a_len);}
3287 /* Adjust pointers. */
3289 a_len -= (int)sizeof(block);
3290 /* Execute the CBC-MAC algorithm. */
3291 if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, sizeof(block))) {
3292 gcry_cipher_close(cipher_hd);
3297 /* Process the message, m. */
3300 if ((guint)m_len >= sizeof(block)) memcpy(block, m, sizeof(block));
3301 else {memcpy(block, m, m_len); memset(block+m_len, 0, sizeof(block)-m_len);}
3302 /* Adjust pointers. */
3304 m_len -= (int)sizeof(block);
3305 /* Execute the CBC-MAC algorithm. */
3306 if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, sizeof(block))) {
3307 gcry_cipher_close(cipher_hd);
3312 /* Done with the cipher. */
3313 gcry_cipher_close(cipher_hd);
3318 ccm_cbc_mac(const gchar *key _U_, const gchar *iv _U_,
3319 const gchar *a _U_, gint a_len _U_, const gchar *m _U_, gint m_len _U_, gchar *mic _U_)
3323 #endif /* HAVE_LIBGCRYPT */
3325 /* Key hash function. */
3326 guint ieee802154_short_addr_hash(gconstpointer key)
3328 return (((const ieee802154_short_addr *)key)->addr) | (((const ieee802154_short_addr *)key)->pan << 16);
3331 /* Key equal function. */
3332 gboolean ieee802154_short_addr_equal(gconstpointer a, gconstpointer b)
3334 return (((const ieee802154_short_addr *)a)->pan == ((const ieee802154_short_addr *)b)->pan) &&
3335 (((const ieee802154_short_addr *)a)->addr == ((const ieee802154_short_addr *)b)->addr);
3338 /* Key hash function. */
3339 guint ieee802154_long_addr_hash(gconstpointer key)
3341 return (guint)(((const ieee802154_long_addr *)key)->addr) & 0xFFFFFFFF;
3344 /* Key equal function. */
3345 gboolean ieee802154_long_addr_equal(gconstpointer a, gconstpointer b)
3347 return (((const ieee802154_long_addr *)a)->addr == ((const ieee802154_long_addr *)b)->addr);
3351 *Creates a record that maps the given short address and pan to a long (extended) address.
3352 *@param short_addr 16-bit short address
3353 *@param pan 16-bit PAN id
3354 *@param long_addr 64-bit long (extended) address
3355 *@param proto pointer to name of current protocol
3356 *@param fnum Frame number this mapping became valid
3357 *@return TRUE Record was updated, FALSE Couldn't find it
3359 ieee802154_map_rec *ieee802154_addr_update(ieee802154_map_tab_t *au_ieee802154_map,
3360 guint16 short_addr, guint16 pan, guint64 long_addr, const char *proto, guint fnum)
3362 ieee802154_short_addr addr16;
3363 ieee802154_map_rec *p_map_rec;
3366 /* Look up short address hash */
3368 addr16.addr = short_addr;
3369 p_map_rec = (ieee802154_map_rec *)g_hash_table_lookup(au_ieee802154_map->short_table, &addr16);
3371 /* Update mapping record */
3373 /* record already exists */
3374 if ( p_map_rec->addr64 == long_addr ) {
3379 /* mark current mapping record invalid */
3380 p_map_rec->end_fnum = fnum;
3384 /* create a new mapping record */
3385 p_map_rec = wmem_new(wmem_file_scope(), ieee802154_map_rec);
3386 p_map_rec->proto = proto;
3387 p_map_rec->start_fnum = fnum;
3388 p_map_rec->end_fnum = 0;
3389 p_map_rec->addr64 = long_addr;
3391 /* link new mapping record to addr hash tables */
3392 if ( g_hash_table_lookup_extended(au_ieee802154_map->short_table, &addr16, &old_key, NULL) ) {
3393 /* update short addr hash table, reusing pointer to old key */
3394 g_hash_table_insert(au_ieee802154_map->short_table, old_key, p_map_rec);
3396 /* create new hash entry */
3397 g_hash_table_insert(au_ieee802154_map->short_table, wmem_memdup(wmem_file_scope(), &addr16, sizeof(addr16)), p_map_rec);
3400 if ( g_hash_table_lookup_extended(au_ieee802154_map->long_table, &long_addr, &old_key, NULL) ) {
3401 /* update long addr hash table, reusing pointer to old key */
3402 g_hash_table_insert(au_ieee802154_map->long_table, old_key, p_map_rec);
3404 /* create new hash entry */
3405 g_hash_table_insert(au_ieee802154_map->long_table, wmem_memdup(wmem_file_scope(), &long_addr, sizeof(long_addr)), p_map_rec);
3409 } /* ieee802154_addr_update */
3412 *Marks a mapping record associated with device with short_addr
3413 *as invalid at a certain frame number, typically when a
3414 *disassociation occurs.
3416 *@param short_addr 16-bit short address
3417 *@param pan 16-bit PAN id
3418 *@param fnum Frame number when mapping became invalid
3419 *@return TRUE Record was updated, FALSE Couldn't find it
3421 gboolean ieee802154_short_addr_invalidate(guint16 short_addr, guint16 pan, guint fnum)
3423 ieee802154_short_addr addr16;
3424 ieee802154_map_rec *map_rec;
3427 addr16.addr = short_addr;
3429 map_rec = (ieee802154_map_rec *)g_hash_table_lookup(ieee802154_map.short_table, &addr16);
3431 /* indicates this mapping is invalid at frame fnum */
3432 map_rec->end_fnum = fnum;
3437 } /* ieee802154_short_addr_invalidate */
3440 * Mark a mapping record associated with device with long_addr
3441 * as invalid at a certain frame number, typically when a
3442 * disassociation occurs.
3444 *@param long_addr 16-bit short address
3445 *@param fnum Frame number when mapping became invalid
3446 *@return TRUE If record was updated, FALSE otherwise
3448 gboolean ieee802154_long_addr_invalidate(guint64 long_addr, guint fnum)
3450 ieee802154_map_rec *map_rec;
3452 map_rec = (ieee802154_map_rec *)g_hash_table_lookup(ieee802154_map.long_table, &long_addr);
3454 /* indicates this mapping is invalid at frame fnum */
3455 map_rec->end_fnum = fnum;
3460 } /* ieee802154_long_addr_invalidate */
3463 * Init routine for the IEEE 802.15.4 dissector. Creates hash
3464 * tables for mapping between 16-bit to 64-bit addresses and
3465 * populates them with static address pairs from a UAT
3469 proto_init_ieee802154(void)
3473 ieee802154_map.short_table = g_hash_table_new(ieee802154_short_addr_hash, ieee802154_short_addr_equal);
3474 ieee802154_map.long_table = g_hash_table_new(ieee802154_long_addr_hash, ieee802154_long_addr_equal);
3475 /* Reload the hash table from the static address UAT. */
3476 for (i=0; (i<num_static_addrs) && (static_addrs); i++) {
3477 ieee802154_addr_update(&ieee802154_map,(guint16)static_addrs[i].addr16, (guint16)static_addrs[i].pan,
3478 pntoh64(static_addrs[i].eui64), ieee802154_user, IEEE802154_USER_MAPPING);
3480 } /* proto_init_ieee802154 */
3483 * Cleanup for the IEEE 802.15.4 dissector.
3486 proto_cleanup_ieee802154(void)
3488 g_hash_table_destroy(ieee802154_map.short_table);
3489 g_hash_table_destroy(ieee802154_map.long_table);
3492 /* Returns the prompt string for the Decode-As dialog. */
3493 static void ieee802154_da_prompt(packet_info *pinfo _U_, gchar* result)
3495 ieee802154_hints_t *hints;
3496 hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
3497 proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
3499 g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IEEE 802.15.4 PAN 0x%04x as", hints->src_pan);
3501 g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IEEE 802.15.4 PAN Unknown");
3502 } /* iee802154_da_prompt */
3504 /* Returns the value to index the panid decode table with (source PAN)*/
3505 static gpointer ieee802154_da_value(packet_info *pinfo _U_)
3507 ieee802154_hints_t *hints;
3508 hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo,
3509 proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN), 0);
3511 return GUINT_TO_POINTER((guint)(hints->src_pan));
3514 } /* iee802154_da_value */
3517 * IEEE 802.15.4 protocol registration routine.
3519 void proto_register_ieee802154(void)
3521 /* Protocol fields */
3522 static hf_register_info hf_phy[] = {
3525 { &hf_ieee802154_nonask_phy_preamble,
3526 { "Preamble", "wpan-nonask-phy.preamble", FT_UINT32, BASE_HEX, NULL, 0x0,
3529 { &hf_ieee802154_nonask_phy_sfd,
3530 { "Start of Frame Delimiter", "wpan-nonask-phy.sfd", FT_UINT8, BASE_HEX, NULL, 0x0,
3533 { &hf_ieee802154_nonask_phy_length,
3534 { "Frame Length", "wpan-nonask-phy.frame_length", FT_UINT8, BASE_HEX, NULL,
3535 IEEE802154_PHY_LENGTH_MASK, NULL, HFILL }},
3537 { &hf_ieee802154_nonask_phr,
3538 { "PHR", "wpan-nonask-phy.phr", FT_UINT8, BASE_HEX, NULL,
3539 0x0, NULL, HFILL }},
3542 static hf_register_info hf[] = {
3544 { &hf_ieee802154_frame_length,
3545 { "Frame Length", "wpan.frame_length", FT_UINT8, BASE_DEC, NULL, 0x0,
3546 "Frame Length as reported from lower layer", HFILL }},
3548 { &hf_ieee802154_fcf,
3549 { "Frame Control Field", "wpan.fcf", FT_UINT16, BASE_HEX, NULL,
3550 0x0, NULL, HFILL }},
3552 { &hf_ieee802154_frame_type,
3553 { "Frame Type", "wpan.frame_type", FT_UINT16, BASE_HEX, VALS(ieee802154_frame_types),
3554 IEEE802154_FCF_TYPE_MASK, NULL, HFILL }},
3556 { &hf_ieee802154_security,
3557 { "Security Enabled", "wpan.security", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_SEC_EN,
3558 "Whether security operations are performed at the MAC layer or not.", HFILL }},
3560 { &hf_ieee802154_pending,
3561 { "Frame Pending", "wpan.pending", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_FRAME_PND,
3562 "Indication of additional packets waiting to be transferred from the source device.", HFILL }},
3564 { &hf_ieee802154_ack_request,
3565 { "Acknowledge Request", "wpan.ack_request", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_ACK_REQ,
3566 "Whether the sender of this packet requests acknowledgment or not.", HFILL }},
3568 { &hf_ieee802154_pan_id_compression,
3569 { "PAN ID Compression", "wpan.pan_id_compression", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_PAN_ID_COMPRESSION,
3570 "Whether this packet contains the PAN ID or not.", HFILL }},
3572 { &hf_ieee802154_seqno_suppression,
3573 { "Sequence Number Suppression", "wpan.seqno_suppression", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_SEQNO_SUPPRESSION,
3574 "Whether this packet contains the Sequence Number or not.", HFILL }},
3576 { &hf_ieee802154_ie_present,
3577 { "Information Elements Present", "wpan.ie_present", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_IE_PRESENT,
3578 "Whether this packet contains the Information Elements or not.", HFILL }},
3580 { &hf_ieee802154_seqno,
3581 { "Sequence Number", "wpan.seq_no", FT_UINT8, BASE_DEC, NULL, 0x0,
3584 { &hf_ieee802154_dst_addr_mode,
3585 { "Destination Addressing Mode", "wpan.dst_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
3586 IEEE802154_FCF_DADDR_MASK, NULL, HFILL }},
3588 { &hf_ieee802154_src_addr_mode,
3589 { "Source Addressing Mode", "wpan.src_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
3590 IEEE802154_FCF_SADDR_MASK, NULL, HFILL }},
3592 { &hf_ieee802154_version,
3593 { "Frame Version", "wpan.version", FT_UINT16, BASE_DEC, VALS(ieee802154_frame_versions),
3594 IEEE802154_FCF_VERSION, NULL, HFILL }},
3596 { &hf_ieee802154_dst_panID,
3597 { "Destination PAN", "wpan.dst_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
3600 { &hf_ieee802154_dst16,
3601 { "Destination", "wpan.dst16", FT_UINT16, BASE_HEX, NULL, 0x0,
3604 { &hf_ieee802154_dst64,
3605 { "Destination", "wpan.dst64", FT_EUI64, BASE_NONE, NULL, 0x0,
3608 { &hf_ieee802154_src_panID,
3609 { "Source PAN", "wpan.src_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
3612 { &hf_ieee802154_src16,
3613 { "Source", "wpan.src16", FT_UINT16, BASE_HEX, NULL, 0x0,
3616 { &hf_ieee802154_src64,
3617 { "Extended Source", "wpan.src64", FT_EUI64, BASE_NONE, NULL, 0x0,
3620 { &hf_ieee802154_src64_origin,
3621 { "Origin", "wpan.src64.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3624 { &hf_ieee802154_fcs,
3625 { "FCS", "wpan.fcs", FT_UINT16, BASE_HEX, NULL, 0x0,
3628 { &hf_ieee802154_rssi,
3629 { "RSSI", "wpan.rssi", FT_INT8, BASE_DEC|BASE_UNIT_STRING, &units_decibels, 0x0,
3630 "Received Signal Strength", HFILL }},
3632 { &hf_ieee802154_fcs_ok,
3633 { "FCS Valid", "wpan.fcs_ok", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3636 { &hf_ieee802154_correlation,
3637 { "LQI Correlation Value", "wpan.correlation", FT_UINT8, BASE_DEC, NULL, 0x0,
3641 { &hf_ieee802154_header_ie,
3642 { "Header IE", "wpan.header_ie", FT_UINT16, BASE_HEX, NULL,
3643 0x0, NULL, HFILL }},
3645 { &hf_ieee802154_header_ie_type,
3646 { "Type", "wpan.header_ie.type", FT_UINT16, BASE_DEC, VALS(ieee802154_ie_types),
3647 IEEE802154_HEADER_IE_TYPE_MASK, NULL, HFILL }},
3649 { &hf_ieee802154_header_ie_id,
3650 { "Id", "wpan.header_ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_header_ie_names),
3651 IEEE802154_HEADER_IE_ID_MASK, NULL, HFILL }},
3653 { &hf_ieee802154_header_ie_length,
3654 { "Length", "wpan.header_ie.length", FT_UINT16, BASE_DEC, NULL,
3655 IEEE802154_HEADER_IE_LENGTH_MASK, NULL, HFILL }},
3657 { &hf_ieee802154_header_ie_data,
3658 { "Data", "wpan.header_ie.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3660 { &hf_ieee802154_h_ie_time_correction1,
3661 { "Ack - positive time correction", "wpan.h_ie_time_correction", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
3664 { &hf_ieee802154_h_ie_time_correction2,
3665 { "Ack - negative time correction", "wpan.h_ie_time_correction", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
3668 { &hf_ieee802154_h_ie_time_correction3,
3669 { "Non Ack - positive time correction", "wpan.h_ie_time_correction", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
3672 { &hf_ieee802154_h_ie_time_correction4,
3673 { "Non Ack - negative time correction", "wpan.h_ie_time_correction", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
3677 { &hf_ieee802154_payload_ie,
3678 { "Header", "wpan.payload_ie", FT_UINT16, BASE_HEX, NULL,
3679 0x0, NULL, HFILL }},
3681 { &hf_ieee802154_payload_ie_type,
3682 { "Type", "wpan.payload_ie.type", FT_UINT16, BASE_DEC, VALS(ieee802154_ie_types),
3683 IEEE802154_PAYLOAD_IE_TYPE_MASK, NULL, HFILL }},
3685 { &hf_ieee802154_payload_ie_id,
3686 { "Id", "wpan.payload_ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_payload_ie_names),
3687 IEEE802154_PAYLOAD_IE_ID_MASK, NULL, HFILL }},
3689 { &hf_ieee802154_payload_ie_length,
3690 { "Length", "wpan.payload_ie.length", FT_UINT16, BASE_DEC, NULL,
3691 IEEE802154_PAYLOAD_IE_LENGTH_MASK, NULL, HFILL }},
3693 { &hf_ieee802154_psie_short,
3694 { "Payload Sub IE (short)", "wpan.payload_sub_ie.short", FT_UINT16, BASE_HEX, NULL,
3695 0x0, NULL, HFILL }},
3697 { &hf_ieee802154_psie_type_short,
3698 { "Type", "wpan.payload_sub_ie.type_short", FT_UINT16, BASE_DEC, VALS(ieee802154_psie_types),
3699 IEEE802154_PSIE_TYPE_MASK, NULL, HFILL }},
3701 { &hf_ieee802154_psie_id_short,
3702 { "Sub Id (Short)", "wpan.payload_sub_ie.id_short", FT_UINT16, BASE_HEX, VALS(ieee802154_psie_names),
3703 IEEE802154_PSIE_ID_MASK_SHORT, NULL, HFILL }},
3705 { &hf_ieee802154_psie_length_short,
3706 { "Length", "wpan.payload_sub_ie.length_short", FT_UINT16, BASE_DEC, NULL,
3707 IEEE802154_PSIE_LENGTH_MASK_SHORT, NULL, HFILL }},
3709 { &hf_ieee802154_psie_long,
3710 { "Payload Sub IE (long)", "wpan.payload_sub_ie.long", FT_UINT16, BASE_HEX, NULL,
3711 0x0, NULL, HFILL }},
3713 { &hf_ieee802154_psie_type_long,
3714 { "Type", "wpan.payload_sub_ie.type_long", FT_UINT16, BASE_DEC, VALS(ieee802154_psie_types),
3715 IEEE802154_PSIE_TYPE_MASK, NULL, HFILL }},
3717 { &hf_ieee802154_psie_id_long,
3718 { "Sub Id (Long)", "wpan.payload_sub_ie.id_long", FT_UINT16, BASE_HEX, VALS(ieee802154_psie_names),
3719 IEEE802154_PSIE_ID_MASK_LONG, NULL, HFILL }},
3721 { &hf_ieee802154_psie_length_long,
3722 { "Length", "wpan.payload_sub_ie.length_long", FT_UINT16, BASE_DEC, NULL,
3723 IEEE802154_PSIE_LENGTH_MASK_LONG, NULL, HFILL }},
3725 { &hf_ieee802154_psie_eb_filter,
3726 { "Enhanced Beacon Filter", "wpan.payload_sub_ie.eb_filter", FT_UINT8, BASE_HEX, NULL,
3729 { &hf_ieee802154_p_ie_mlme_sh_tsch_asn,
3730 { "Absolute Slot Number", "wpan.p_ie_mlme_sh_asn", FT_UINT64, BASE_DEC, NULL, 0x0,
3733 { &hf_ieee802154_p_ie_mlme_sh_tsch_join_p,
3734 { "Join Priority", "wpan.p_ie_mlme_sh_joinp", FT_UINT8, BASE_DEC, NULL, 0x0,
3737 { &hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_nb_slotf,
3738 { "Number of Slotframes", "wpan.p_ie_mlme_sh_slotf_link_nb_slotf", FT_UINT8, BASE_DEC, NULL, 0x0,
3741 { &hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_slotf_handle,
3742 { "Slotframe handle", "wpan.p_ie_mlme_sh_slotf_link_slotf_handle", FT_UINT8, BASE_DEC, NULL, 0x0,
3745 { &hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_slotf_size,
3746 { "Slotframe size", "wpan.p_ie_mlme_sh_slotf_link_slotf_size", FT_UINT16, BASE_DEC, NULL, 0x0,
3749 { &hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_nb_links,
3750 { "Number of Links", "wpan.p_ie_mlme_sh_slotf_link_nb_links", FT_UINT8, BASE_DEC, NULL, 0x0,
3753 { &hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_timeslot,
3754 { "Timeslot", "wpan.p_ie_mlme_sh_slotf_link_timeslot", FT_UINT16, BASE_DEC, NULL, 0x0,
3757 { &hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_channel_offset,
3758 { "Channel Offset", "wpan.p_ie_mlme_sh_slotf_link_channel_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
3761 { &hf_ieee802154_p_ie_mlme_sh_tsch_slotf_link_options,
3762 { "Link Options", "wpan.p_ie_mlme_sh_slotf_link_options", FT_UINT8, BASE_DEC, NULL, 0x0,
3765 { &hf_ieee802154_p_ie_mlme_lg_hopping_sequence_id,
3766 { "Hopping Sequence ID", "wpan.p_ie_mlme_lg_hopping_sequence_id", FT_UINT8, BASE_HEX, NULL, 0x0,
3768 /* ------------------------------------------------------------------------------------------------------------------------------------- */
3770 { &hf_ieee802154_psie_eb_filter_pjoin,
3771 { "Permit Join Filter", "wpan.payload_sub_ie.eb_filter.pjoin", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
3772 IEEE802154_MLME_PSIE_EB_FLT_PJOIN, NULL, HFILL }},
3774 { &hf_ieee802154_psie_eb_filter_lqi,
3775 { "LQI Filter", "wpan.payload_sub_ie.eb_filter.lqi", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
3776 IEEE802154_MLME_PSIE_EB_FLT_LQI, NULL, HFILL }},
3778 { &hf_ieee802154_psie_eb_filter_lqi_min,
3779 { "Minimum LQI", "wpan.payload_sub_ie.eb_filter.lqi_minimum", FT_UINT8, BASE_DEC, NULL,
3780 0x0, NULL, HFILL }},
3782 { &hf_ieee802154_psie_eb_filter_percent,
3783 { "Probability to Respond", "wpan.payload_sub_ie.eb_filter.contains_prob", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
3784 IEEE802154_MLME_PSIE_EB_FLT_PERCENT, NULL, HFILL }},
3786 { &hf_ieee802154_psie_eb_filter_percent_prob,
3787 { "Response Probability Percentage", "wpan.payload_sub_ie.eb_filter.prob", FT_UINT8, BASE_DEC, NULL,
3788 0x0, NULL, HFILL }},
3790 { &hf_ieee802154_psie_eb_filter_attr_id,
3791 { "Requested Attribute Length", "wpan.payload_sub_ie.eb_filter.attr_id", FT_UINT8, BASE_DEC, NULL,
3792 IEEE802154_MLME_PSIE_EB_FLT_ATTR_LEN, NULL, HFILL }},
3794 { &hf_ieee802154_psie_eb_filter_attr_id_bitmap,
3795 { "Attribute ID Bitmap", "wpan.payload_sub_ie.eb_filter.attr_id_bits", FT_UINT24, BASE_HEX, NULL,
3796 0x0, NULL, HFILL }},
3798 { &hf_ieee802154_payload_ie_data,
3799 { "Data", "wpan.payload_ie.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3801 { &hf_ieee802154_payload_ie_vendor_oui,
3802 { "Vendor OUI", "wpan.payload_ie.vendor_oui", FT_UINT24, BASE_HEX, NULL,
3803 0x0, NULL, HFILL }},
3805 { &hf_ieee802154_mlme_ie_data,
3806 { "Data", "wpan.mlme_sub_ie.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3809 { &hf_ieee802154_p_ie_ietf_sub_id,
3810 { "Sub-ID", "wpan.ietf_ie.sub_id", FT_UINT8, BASE_DEC, NULL, 0,
3813 /* IETF IE - 6top IE */
3814 { &hf_ieee802154_p_ie_6top_version,
3815 { "6P Version", "wpan.ietf_ie.6top.version", FT_UINT8, BASE_DEC, NULL, IETF_6TOP_VERSION,
3818 { &hf_ieee802154_p_ie_6top_type,
3819 { "Type", "wpan.ietf_ie.6top.type", FT_UINT8, BASE_HEX, VALS(ietf_6top_types), IETF_6TOP_TYPE,
3822 { &hf_ieee802154_p_ie_6top_flags_reserved,
3823 { "Reserved", "wpan.ietf_ie.6top.flags.reserved", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_FLAGS_RESERVED,
3826 { &hf_ieee802154_p_ie_6top_code,
3827 { "Code", "wpan.ietf_ie.6top.code", FT_UINT8, BASE_HEX, NULL, 0x0,
3830 { &hf_ieee802154_p_ie_6top_sfid,
3831 { "SFID (6top Scheduling Fnction ID)", "wpan.ietf_ie.6top.sfid", FT_UINT8, BASE_HEX, NULL, 0x0,
3834 { &hf_ieee802154_p_ie_6top_seqnum,
3835 { "SeqNum", "wpan.ietf_ie.6top.seqnum", FT_UINT8, BASE_DEC, NULL, IETF_6TOP_SEQNUM,
3838 { &hf_ieee802154_p_ie_6top_gab,
3839 { "GAB", "wpan.ietf_ie.6top.gab", FT_UINT8, BASE_DEC, VALS(ietf_6top_generation_numbers), IETF_6TOP_GAB,
3842 { &hf_ieee802154_p_ie_6top_gba,
3843 { "GBA", "wpan.ietf_ie.6top.gba", FT_UINT8, BASE_DEC, VALS(ietf_6top_generation_numbers), IETF_6TOP_GBA,
3846 { &hf_ieee802154_p_ie_6top_metadata,
3847 { "Metadata", "wpan.ietf_ie.6top.metadata", FT_UINT16, BASE_HEX, NULL, 0x0,
3850 { &hf_ieee802154_p_ie_6top_cell_options,
3851 { "Cell Options", "wpan.ietf_ie.6top.cell_options", FT_UINT8, BASE_HEX, VALS(ietf_6top_cell_options), 0x0,
3854 { &hf_ieee802154_p_ie_6top_cell_option_tx,
3855 { "Transmit (TX) Cell", "wpan.ietf_ie.6top.cell_option_tx", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_TX,
3858 { &hf_ieee802154_p_ie_6top_cell_option_rx,
3859 { "Receive (RX) Cell", "wpan.ietf_ie.6top.cell_option_rx", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_RX,
3862 { &hf_ieee802154_p_ie_6top_cell_option_shared,
3863 { "SHARED Cell", "wpan.ietf_ie.6top.cell_option_shared", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_SHARED,
3866 { &hf_ieee802154_p_ie_6top_cell_option_reserved,
3867 { "Reserved", "wpan.ietf_ie.6top.cell_option_reserved", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_RESERVED,
3870 { &hf_ieee802154_p_ie_6top_num_cells,
3871 { "Number of Cells", "wpan.ietf_ie.6top.num_cells", FT_UINT16, BASE_DEC, NULL, 0x0,
3874 { &hf_ieee802154_p_ie_6top_reserved,
3875 { "Reserved", "wpan.ietf_ie.6top.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
3878 { &hf_ieee802154_p_ie_6top_offset,
3879 { "Offset", "wpan.ietf_ie.6top.offset", FT_UINT16, BASE_DEC, NULL, 0x0,
3882 { &hf_ieee802154_p_ie_6top_max_num_cells,
3883 { "Maximum Number of Requested Cells", "wpan.ietf_ie.6top.max_num_cells", FT_UINT16, BASE_DEC, NULL, 0x0,
3886 { &hf_ieee802154_p_ie_6top_slot_offset,
3887 { "Slot Offset", "wpan.ietf_ie.6top.cell.slot_offset", FT_UINT16, BASE_HEX, NULL, 0x0,
3890 { &hf_ieee802154_p_ie_6top_channel_offset,
3891 { "Channel Offset", "wpan.ietf_ie.6top.cell.channel_offset", FT_UINT16, BASE_HEX, NULL, 0x0,
3895 * Command Frame Specific Fields
3898 { &hf_ieee802154_cmd_id,
3899 { "Command Identifier", "wpan.cmd", FT_UINT8, BASE_HEX, VALS(ieee802154_cmd_names), 0x0,
3902 /* Capability Information Fields */
3903 { &hf_ieee802154_cinfo_alt_coord,
3904 { "Alternate PAN Coordinator", "wpan.cinfo.alt_coord", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALT_PAN_COORD,
3905 "Whether this device can act as a PAN coordinator or not.", HFILL }},
3907 { &hf_ieee802154_cinfo_device_type,
3908 { "Device Type", "wpan.cinfo.device_type", FT_BOOLEAN, 8, TFS(&tfs_cinfo_device_type), IEEE802154_CMD_CINFO_DEVICE_TYPE,
3909 "Whether this device is RFD (reduced-function device) or FFD (full-function device).", HFILL }},
3911 { &hf_ieee802154_cinfo_power_src,
3912 { "Power Source", "wpan.cinfo.power_src", FT_BOOLEAN, 8, TFS(&tfs_cinfo_power_src), IEEE802154_CMD_CINFO_POWER_SRC,
3913 "Whether this device is operating on AC/mains or battery power.", HFILL }},
3915 { &hf_ieee802154_cinfo_idle_rx,
3916 { "Receive On When Idle", "wpan.cinfo.idle_rx", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_IDLE_RX,
3917 "Whether this device can receive packets while idle or not.", HFILL }},
3919 { &hf_ieee802154_cinfo_sec_capable,
3920 { "Security Capability", "wpan.cinfo.sec_capable", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_SEC_CAPABLE,
3921 "Whether this device is capable of receiving encrypted packets.", HFILL }},
3923 { &hf_ieee802154_cinfo_alloc_addr,
3924 { "Allocate Address", "wpan.cinfo.alloc_addr", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALLOC_ADDR,
3925 "Whether this device wishes to use a 16-bit short address instead of its IEEE 802.15.4 64-bit long address.", HFILL }},
3927 /* Association response fields */
3928 { &hf_ieee802154_assoc_addr,
3929 { "Short Address", "wpan.asoc.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
3930 "The short address that the device should assume. An address of 0xfffe indicates that the device should use its IEEE 64-bit long address.", HFILL }},
3932 { &hf_ieee802154_assoc_status,
3933 { "Association Status", "wpan.assoc.status", FT_UINT8, BASE_HEX, NULL, 0x0,
3936 { &hf_ieee802154_disassoc_reason,
3937 { "Disassociation Reason", "wpan.disassoc.reason", FT_UINT8, BASE_HEX, NULL, 0x0,
3940 /* Coordinator Realignment fields */
3941 { &hf_ieee802154_realign_pan,
3942 { "PAN ID", "wpan.realign.pan", FT_UINT16, BASE_HEX, NULL, 0x0,
3943 "The PAN identifier the coordinator wishes to use for future communication.", HFILL }},
3945 { &hf_ieee802154_realign_caddr,
3946 { "Coordinator Short Address", "wpan.realign.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
3947 "The 16-bit address the coordinator wishes to use for future communication.", HFILL }},
3949 { &hf_ieee802154_realign_channel,
3950 { "Logical Channel", "wpan.realign.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
3951 "The logical channel the coordinator wishes to use for future communication.", HFILL }},
3953 { &hf_ieee802154_realign_addr,
3954 { "Short Address", "wpan.realign.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
3955 "A short-address that the orphaned device shall assume if applicable.", HFILL }},
3957 { &hf_ieee802154_realign_channel_page,
3958 { "Channel Page", "wpan.realign.channel_page", FT_UINT8, BASE_DEC, NULL, 0x0,
3959 "The logical channel page the coordinator wishes to use for future communication.", HFILL }},
3961 { &hf_ieee802154_gtsreq_len,
3962 { "GTS Length", "wpan.gtsreq.length", FT_UINT8, BASE_DEC, NULL, IEEE802154_CMD_GTS_REQ_LEN,
3963 "Number of superframe slots the device is requesting.", HFILL }},
3965 { &hf_ieee802154_gtsreq_dir,
3966 { "GTS Direction", "wpan.gtsreq.direction", FT_BOOLEAN, 8, TFS(&tfs_gtsreq_dir), IEEE802154_CMD_GTS_REQ_DIR,
3967 "The direction of traffic in the guaranteed timeslot.", HFILL }},
3969 { &hf_ieee802154_gtsreq_type,
3970 { "Characteristic Type", "wpan.gtsreq.type", FT_BOOLEAN, 8, TFS(&tfs_gtsreq_type), IEEE802154_CMD_GTS_REQ_TYPE,
3971 "Whether this request is to allocate or deallocate a timeslot.", HFILL }},
3974 * Beacon Frame Specific Fields
3976 { &hf_ieee802154_beacon_order,
3977 { "Beacon Interval", "wpan.beacon_order", FT_UINT16, BASE_DEC, NULL, IEEE802154_BEACON_ORDER_MASK,
3978 "Specifies the transmission interval of the beacons.", HFILL }},
3980 { &hf_ieee802154_superframe_order,
3981 { "Superframe Interval", "wpan.superframe_order", FT_UINT16, BASE_DEC, NULL,
3982 IEEE802154_SUPERFRAME_ORDER_MASK,
3983 "Specifies the length of time the coordinator will interact with the PAN.", HFILL }},
3985 { &hf_ieee802154_cap,
3986 { "Final CAP Slot", "wpan.cap", FT_UINT16, BASE_DEC, NULL, IEEE802154_SUPERFRAME_CAP_MASK,
3987 "Specifies the final superframe slot used by the CAP.", HFILL }},
3989 { &hf_ieee802154_superframe_battery_ext,
3990 { "Battery Extension", "wpan.battery_ext", FT_BOOLEAN, 16, NULL, IEEE802154_BATT_EXTENSION_MASK,
3991 "Whether transmissions may not extend past the length of the beacon frame.", HFILL }},
3993 { &hf_ieee802154_superframe_coord,
3994 { "PAN Coordinator", "wpan.bcn_coord", FT_BOOLEAN, 16, NULL, IEEE802154_SUPERFRAME_COORD_MASK,
3995 "Whether this beacon frame is being transmitted by the PAN coordinator or not.", HFILL }},
3997 { &hf_ieee802154_assoc_permit,
3998 { "Association Permit", "wpan.assoc_permit", FT_BOOLEAN, 16, NULL, IEEE802154_ASSOC_PERMIT_MASK,
3999 "Whether this PAN is accepting association requests or not.", HFILL }},
4001 { &hf_ieee802154_gts_count,
4002 { "GTS Descriptor Count", "wpan.gts.count", FT_UINT8, BASE_DEC, NULL, 0x0,
4003 "The number of GTS descriptors present in this beacon frame.", HFILL }},
4005 { &hf_ieee802154_gts_permit,
4006 { "GTS Permit", "wpan.gts.permit", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4007 "Whether the PAN coordinator is accepting GTS requests or not.", HFILL }},
4009 { &hf_ieee802154_gts_direction,
4010 { "Direction", "wpan.gts.direction", FT_BOOLEAN, BASE_NONE, TFS(&ieee802154_gts_direction_tfs), 0x0,
4011 "A flag defining the direction of the GTS Slot.", HFILL }},
4013 { &hf_ieee802154_gts_address,
4014 { "Address", "wpan.gts.address", FT_UINT16, BASE_HEX, NULL, 0x0,
4017 { &hf_ieee802154_pending16,
4018 { "Address", "wpan.pending16", FT_UINT16, BASE_HEX, NULL, 0x0,
4019 "Device with pending data to receive.", HFILL }},
4021 { &hf_ieee802154_pending64,
4022 { "Address", "wpan.pending64", FT_EUI64, BASE_NONE, NULL, 0x0,
4023 "Device with pending data to receive.", HFILL }},
4026 * Auxiliary Security Header Fields
4029 { &hf_ieee802154_security_level,
4030 { "Security Level", "wpan.aux_sec.sec_level", FT_UINT8, BASE_HEX, VALS(ieee802154_sec_level_names),
4031 IEEE802154_AUX_SEC_LEVEL_MASK, "The Security Level of the frame", HFILL }},
4033 { &hf_ieee802154_security_control_field,
4034 { "Security Control Field", "wpan.aux_sec.security_control_field", FT_UINT8, BASE_HEX, NULL,
4035 0x0, NULL, HFILL }},
4037 { &hf_ieee802154_key_id_mode,
4038 { "Key Identifier Mode", "wpan.aux_sec.key_id_mode", FT_UINT8, BASE_HEX, VALS(ieee802154_key_id_mode_names),
4039 IEEE802154_AUX_KEY_ID_MODE_MASK,
4040 "The scheme to use by the recipient to lookup the key in its key table", HFILL }},
4042 { &hf_ieee802154_aux_sec_reserved,
4043 { "Reserved", "wpan.aux_sec.reserved", FT_UINT8, BASE_HEX, NULL, IEEE802154_AUX_KEY_RESERVED_MASK,
4046 { &hf_ieee802154_aux_sec_frame_counter,
4047 { "Frame Counter", "wpan.aux_sec.frame_counter", FT_UINT32, BASE_DEC, NULL, 0x0,
4048 "Frame counter of the originator of the protected frame", HFILL }},
4050 { &hf_ieee802154_aux_sec_key_source,
4051 { "Key Source", "wpan.aux_sec.key_source", FT_UINT64, BASE_HEX, NULL, 0x0,
4052 "Key Source for processing of the protected frame", HFILL }},
4054 { &hf_ieee802154_aux_sec_key_index,
4055 { "Key Index", "wpan.aux_sec.key_index", FT_UINT8, BASE_HEX, NULL, 0x0,
4056 "Key Index for processing of the protected frame", HFILL }},
4058 /* IEEE 802.15.4-2003 Security Header Fields */
4059 { &hf_ieee802154_sec_frame_counter,
4060 { "Frame Counter", "wpan.sec_frame_counter", FT_UINT32, BASE_HEX, NULL, 0x0,
4061 "Frame counter of the originator of the protected frame (802.15.4-2003)", HFILL }},
4063 { &hf_ieee802154_sec_key_sequence_counter,
4064 { "Key Sequence Counter", "wpan.sec_key_sequence_counter", FT_UINT8, BASE_HEX, NULL, 0x0,
4065 "Key Sequence counter of the originator of the protected frame (802.15.4-2003)", HFILL }},
4069 { "Channel", "wpan.zboss.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
4070 "Channel number", HFILL }},
4073 { "ZBOSS Direction", "wpan.zboss.direction", FT_UINT8, BASE_HEX, VALS(zboss_direction_names), 0x0,
4074 "ZBOSS Packet Direction", HFILL }},
4076 { &zboss_trace_number,
4077 { "Trace number", "wpan.zboss.trace", FT_UINT32, BASE_DEC, NULL, 0x0,
4078 "Trace item number", HFILL }},
4082 static gint *ett[] = {
4083 &ett_ieee802154_nonask_phy,
4084 &ett_ieee802154_nonask_phy_phr,
4086 &ett_ieee802154_fcf,
4087 &ett_ieee802154_auxiliary_security,
4088 &ett_ieee802154_aux_sec_control,
4089 &ett_ieee802154_aux_sec_key_id,
4090 &ett_ieee802154_fcs,
4091 &ett_ieee802154_cmd,
4092 &ett_ieee802154_superframe,
4093 &ett_ieee802154_gts,
4094 &ett_ieee802154_gts_direction,
4095 &ett_ieee802154_gts_descriptors,
4096 &ett_ieee802154_pendaddr,
4097 &ett_ieee802154_header,
4098 &ett_ieee802154_header_ie,
4099 &ett_ieee802154_h_ie_payload,
4100 &ett_ieee802154_payload,
4101 &ett_ieee802154_payload_ie,
4102 &ett_ieee802154_mlme_payload,
4103 &ett_ieee802154_mlme_payload_data,
4104 &ett_ieee802154_psie_short,
4105 &ett_ieee802154_psie_short_bitmap,
4106 &ett_ieee802154_psie_long,
4107 &ett_ieee802154_psie_long_bitmap,
4108 &ett_ieee802154_psie_enh_beacon_flt,
4109 &ett_ieee802154_psie_enh_beacon_flt_bitmap,
4110 &ett_ieee802154_psie_slotframe_link_slotframes,
4111 &ett_ieee802154_zigbee,
4112 &ett_ieee802154_zboss,
4113 &ett_ieee802154_p_ie_6top,
4114 &ett_ieee802154_p_ie_6top_version_type,
4115 &ett_ieee802154_p_ie_6top_seqnum_gab_gba,
4116 &ett_ieee802154_p_ie_6top_cell_options,
4117 &ett_ieee802154_p_ie_6top_cell_list,
4118 &ett_ieee802154_p_ie_6top_cell
4121 static ei_register_info ei[] = {
4122 { &ei_ieee802154_invalid_addressing, { "wpan.invalid_addressing", PI_MALFORMED, PI_WARN,
4123 "Invalid Addressing", EXPFILL }},
4125 { &ei_ieee802154_invalid_panid_compression, { "wpan.invalid_panid_compression", PI_MALFORMED, PI_ERROR,
4126 "Invalid Setting for PAN ID Compression", EXPFILL }},
4128 { &ei_ieee802154_invalid_panid_compression2, { "wpan.seqno_supression_fv2_invalid", PI_MALFORMED, PI_WARN,
4129 "Invalid Pan ID Compression and addressing combination for Frame Version 2", EXPFILL }},
4130 { &ei_ieee802154_dst, { "wpan.dst_invalid", PI_MALFORMED, PI_ERROR,
4131 "Invalid Destination Address Mode", EXPFILL }},
4132 { &ei_ieee802154_src, { "wpan.src_invalid", PI_MALFORMED, PI_ERROR,
4133 "Invalid Source Address Mode", EXPFILL }},
4134 { &ei_ieee802154_frame_ver, { "wpan.frame_version_unknown", PI_MALFORMED, PI_ERROR,
4135 "Frame Version Unknown Cannot Dissect", EXPFILL }},
4137 { &ei_ieee802154_frame_type, { "wpan.frame_type_unknown", PI_MALFORMED, PI_ERROR,
4138 "Frame Type Unknown Cannot Dissect", EXPFILL }},
4140 { &ei_ieee802154_decrypt_error, { "wpan.decrypt_error", PI_UNDECODED, PI_WARN,
4141 "Decryption error", EXPFILL }},
4142 { &ei_ieee802154_fcs, { "wpan.fcs.bad", PI_CHECKSUM, PI_WARN,
4143 "Bad FCS", EXPFILL }},
4144 { &ei_ieee802154_seqno_suppression, { "wpan.seqno_supression_invalid", PI_MALFORMED, PI_WARN,
4145 "Sequence Number Suppression invalid for 802.15.4-2003 and 2006", EXPFILL }},
4146 { &ei_ieee802154_p_ie_6top_type, { "wpan.ietf_ie.6top.type.unsupported", PI_PROTOCOL, PI_WARN,
4147 "Unsupported Type of Message", EXPFILL }},
4148 { &ei_ieee802154_p_ie_6top_code, { "wpan.ietf_ie.6top.code.unsupported", PI_PROTOCOL, PI_WARN,
4149 "Unsupported Request Command or Return Code", EXPFILL }},
4154 module_t *ieee802154_module;
4155 expert_module_t* expert_ieee802154;
4157 static uat_field_t addr_uat_flds[] = {
4158 UAT_FLD_HEX(addr_uat,addr16,"Short Address",
4159 "16-bit short address in hexadecimal."),
4160 UAT_FLD_HEX(addr_uat,pan,"PAN Identifier",
4161 "16-bit PAN identifier in hexadecimal."),
4162 UAT_FLD_BUFFER(addr_uat,eui64,"EUI-64",
4163 "64-bit extended unique identifier."),
4167 static build_valid_func ieee802154_da_build_value[1] = {ieee802154_da_value};
4168 static decode_as_value_t ieee802154_da_values = {ieee802154_da_prompt, 1, ieee802154_da_build_value};
4169 static decode_as_t ieee802154_da = {
4170 IEEE802154_PROTOABBREV_WPAN, "PAN", IEEE802154_PROTOABBREV_WPAN_PANID,
4171 1, 0, &ieee802154_da_values, NULL, NULL,
4172 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL
4175 /* Register the init routine. */
4176 register_init_routine(proto_init_ieee802154);
4177 register_cleanup_routine(proto_cleanup_ieee802154);
4179 /* Register Protocol name and description. */
4180 proto_ieee802154 = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN", "IEEE 802.15.4",
4181 IEEE802154_PROTOABBREV_WPAN);
4182 proto_ieee802154_nonask_phy = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN non-ASK PHY",
4183 "IEEE 802.15.4 non-ASK PHY", "wpan-nonask-phy");
4184 proto_zboss = proto_register_protocol("ZBOSS IEEE 802.15.4 dump",
4185 "ZBOSS dump", "wpan-zboss");
4187 /* Register header fields and subtrees. */
4188 proto_register_field_array(proto_ieee802154, hf, array_length(hf));
4189 proto_register_field_array(proto_ieee802154, hf_phy, array_length(hf_phy));
4191 proto_register_subtree_array(ett, array_length(ett));
4193 expert_ieee802154 = expert_register_protocol(proto_ieee802154);
4194 expert_register_field_array(expert_ieee802154, ei, array_length(ei));
4196 ieee802_15_4_short_address_type = address_type_dissector_register("AT_IEEE_802_15_4_SHORT", "IEEE 802.15.4 16-bit short address",
4197 ieee802_15_4_short_address_to_str, ieee802_15_4_short_address_str_len, NULL, NULL, ieee802_15_4_short_address_len, NULL, NULL);
4199 /* add a user preference to set the 802.15.4 ethertype */
4200 ieee802154_module = prefs_register_protocol(proto_ieee802154,
4201 proto_reg_handoff_ieee802154);
4202 prefs_register_uint_preference(ieee802154_module, "802154_ethertype",
4203 "802.15.4 Ethertype (in hex)",
4204 "(Hexadecimal) Ethertype used to indicate IEEE 802.15.4 frame.",
4205 16, &ieee802154_ethertype);
4206 prefs_register_bool_preference(ieee802154_module, "802154_cc24xx",
4207 "TI CC24xx FCS format",
4208 "Set if the FCS field is in TI CC24xx format.",
4209 &ieee802154_cc24xx);
4210 prefs_register_bool_preference(ieee802154_module, "802154_fcs_ok",
4211 "Dissect only good FCS",
4212 "Dissect payload only if FCS is valid.",
4213 &ieee802154_fcs_ok);
4215 /* Create a UAT for static address mappings. */
4216 static_addr_uat = uat_new("Static Addresses",
4217 sizeof(static_addr_t), /* record size */
4218 "802154_addresses", /* filename */
4219 TRUE, /* from_profile */
4220 &static_addrs, /* data_ptr */
4221 &num_static_addrs, /* numitems_ptr */
4222 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
4224 NULL, /* copy callback */
4225 addr_uat_update_cb, /* update callback */
4226 NULL, /* free callback */
4227 NULL, /* post update callback */
4228 NULL, /* reset callback */
4229 addr_uat_flds); /* UAT field definitions */
4230 prefs_register_uat_preference(ieee802154_module, "static_addr",
4232 "A table of static address mappings between 16-bit short addressing and EUI-64 addresses",
4235 /* Register preferences for a decryption key */
4236 /* TODO: Implement a UAT for multiple keys, and with more advanced key management. */
4237 prefs_register_string_preference(ieee802154_module, "802154_key", "Decryption key",
4238 "128-bit decryption key in hexadecimal format", (const char **)&ieee802154_key_str);
4240 prefs_register_enum_preference(ieee802154_module, "802154_sec_suite",
4241 "Security Suite (802.15.4-2003)",
4242 "Specifies the security suite to use for 802.15.4-2003 secured frames"
4243 " (only supported suites are listed). Option ignored for 802.15.4-2006"
4244 " and unsecured frames.",
4245 &ieee802154_sec_suite, ieee802154_2003_sec_suite_enums, FALSE);
4247 prefs_register_bool_preference(ieee802154_module, "802154_extend_auth",
4248 "Extend authentication data (802.15.4-2003)",
4249 "Set if the manufacturer extends the authentication data with the"
4250 " security header. Option ignored for 802.15.4-2006 and unsecured frames.",
4251 &ieee802154_extend_auth);
4253 /* Register the subdissector list */
4254 panid_dissector_table = register_dissector_table(IEEE802154_PROTOABBREV_WPAN_PANID, "IEEE 802.15.4 PANID", proto_ieee802154, FT_UINT16, BASE_HEX);
4255 ieee802154_heur_subdissector_list = register_heur_dissector_list(IEEE802154_PROTOABBREV_WPAN, proto_ieee802154);
4256 ieee802154_beacon_subdissector_list = register_heur_dissector_list(IEEE802154_PROTOABBREV_WPAN_BEACON, proto_ieee802154);
4258 /* Register dissectors with Wireshark. */
4259 ieee802154_handle = register_dissector(IEEE802154_PROTOABBREV_WPAN, dissect_ieee802154, proto_ieee802154);
4260 ieee802154_nofcs_handle = register_dissector("wpan_nofcs", dissect_ieee802154_nofcs, proto_ieee802154);
4261 register_dissector("wpan_cc24xx", dissect_ieee802154_cc24xx, proto_ieee802154);
4262 ieee802154_nonask_phy_handle = register_dissector("wpan-nonask-phy", dissect_ieee802154_nonask_phy, proto_ieee802154_nonask_phy);
4264 /* Register a Decode-As handler. */
4265 register_decode_as(&ieee802154_da);
4266 } /* proto_register_ieee802154 */
4270 * Registers the IEEE 802.15.4 dissector with Wireshark.
4271 * Will be called every time 'apply' is pressed in the preferences menu.
4272 * as well as during Wireshark initialization
4274 void proto_reg_handoff_ieee802154(void)
4276 static gboolean prefs_initialized = FALSE;
4277 static unsigned int old_ieee802154_ethertype;
4281 if (!prefs_initialized){
4282 /* Get the dissector handles. */
4283 zigbee_beacon_handle = find_dissector_add_dependency("zbee_beacon", proto_ieee802154);
4284 zigbee_ie_handle = find_dissector_add_dependency("zbee_ie", proto_ieee802154);
4285 zigbee_nwk_handle = find_dissector("zbee_nwk");
4287 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4, ieee802154_handle);
4288 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_NONASK_PHY, ieee802154_nonask_phy_handle);
4289 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_NOFCS, ieee802154_nofcs_handle);
4290 dissector_add_uint("sll.ltype", LINUX_SLL_P_IEEE802154, ieee802154_handle);
4292 prefs_initialized = TRUE;
4294 dissector_delete_uint("ethertype", old_ieee802154_ethertype, ieee802154_handle);
4297 old_ieee802154_ethertype = ieee802154_ethertype;
4299 /* Get the IEEE 802.15.4 decryption key. */
4300 bytes = g_byte_array_new();
4301 res = hex_str_to_bytes(ieee802154_key_str, bytes, FALSE);
4302 ieee802154_key_valid = (res && bytes->len >= IEEE802154_CIPHER_SIZE);
4303 if (ieee802154_key_valid) {
4304 memcpy(ieee802154_key, bytes->data, IEEE802154_CIPHER_SIZE);
4306 g_byte_array_free(bytes, TRUE);
4308 /* Register dissector handles. */
4309 dissector_add_uint("ethertype", ieee802154_ethertype, ieee802154_handle);
4310 } /* proto_reg_handoff_ieee802154 */