Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-ieee802154.c
blobab8955535788fdbfe548fa8df10a7ff942837b59
1 /* packet-ieee802154.c
3 * Multipurpose frame support
4 * By Devan Lai <devanl@davisinstruments.com>
5 * Copyright 2019 Davis Instruments
7 * IEEE 802.15.4-2015 CCM* nonce for TSCH mode
8 * By Maxime Brunelle <Maxime.Brunelle@trilliant.com>
9 * Copyright 2019 Trilliant Inc.
11 * IEEE802154 TAP link type
12 * By James Ko <jck@exegin.com>
13 * Copyright 2019 Exegin Technologies Limited
15 * 4-byte FCS support and ACK tracking
16 * By Carl Levesque Imbeault <carl.levesque@trilliant.com>
17 * Copyright 2018 Trilliant Inc.
18 * Integrated and added FCS type enum
19 * by James Ko <jck@exegin.com>
20 * Copyright 2019 Exegin Technologies Limited
22 * Auxiliary Security Header support and
23 * option to force TI CC24xx FCS format
24 * By Jean-Francois Wauthy <jfw@info.fundp.ac.be>
25 * Copyright 2009 The University of Namur, Belgium
27 * IEEE 802.15.4 Dissectors for Wireshark
28 * By Owen Kirby <osk@exegin.com>
29 * Copyright 2007 Exegin Technologies Limited
31 * Wireshark - Network traffic analyzer
32 * By Gerald Combs <gerald@wireshark.org>
33 * Copyright 1998 Gerald Combs
35 * SPDX-License-Identifier: GPL-2.0-or-later
36 *------------------------------------------------------------
38 * In IEEE 802.15.4 packets, all fields are little endian. And
39 * Each byte is transmitted least significant bit first (reflected
40 * bit ordering).
41 *------------------------------------------------------------
43 * Most IEEE 802.15.4 Packets have the following format:
44 * | FCF |Seq No| Addressing | Data | FCS |
45 * |2 bytes|1 byte|0 to 20 bytes|Length-(Overhead) bytes|2/4 Bytes|
46 *------------------------------------------------------------
48 * Multipurpose frame packets have the following format:
49 * | FCF | Seq No | Addressing | Data | FCS |
50 * |1/2 bytes|0/1 bytes|0 to 20 bytes|Length-(Overhead) bytes|2 bytes|
51 *------------------------------------------------------------
53 * CRC16 is calculated using the x^16 + x^12 + x^5 + 1 polynomial
54 * as specified by ITU-T, and is calculated over the IEEE 802.15.4
55 * packet (excluding the FCS) as transmitted over the air. Note,
56 * that because the least significan bits are transmitted first, this
57 * will require reversing the bit-order in each byte. Also, unlike
58 * most CRC algorithms, IEEE 802.15.4 uses an initial and final value
59 * of 0x0000, instead of 0xffff (which is used by the ITU-T).
61 * For a 4-byte FCS, CRC32 is calculated using the ITU-T CRC32.
63 * (Fun fact: the reference to "a 32-bit CRC equivalent to ANSI X3.66-1979"
64 * in IEEE Std 802.15.4-2015 nonwithstanding, ANSI X3.66-1979 does not
65 * describe any 32-bit CRC, only a 16-bit CRC from ITU-T V.41. ITU-T
66 * V.42 describes both a 16-bit and 32-bit CRC; all the 16-bit CRCs
67 * floating around seem to use the same generator polynomial,
68 * x^16 + x^12 + x^5 + 1, but have different initial conditions and
69 * no-error final remainder; the 32-bit CRC from V.42 and the one
70 * described in IEEE Std 802.15.4-2015 also use the same generator
71 * polynomial.)
72 *------------------------------------------------------------
74 * This dissector supports both link-layer IEEE 802.15.4 captures
75 * and IEEE 802.15.4 packets encapsulated within other layers.
76 * Additionally, support has been provided for 16-bit and 32-bit
77 * FCS, as well as for frames with no FCS but with a 16-bit
78 * ChipCon/Texas Instruments CC24xx-style metadata field.
79 *------------------------------------------------------------
82 /* Include files */
83 #include "config.h"
84 #include <epan/packet.h>
85 #include <epan/decode_as.h>
86 #include <epan/exceptions.h>
87 #include <epan/crc16-tvb.h>
88 #include <epan/crc32-tvb.h>
89 #include <epan/expert.h>
90 #include <epan/addr_resolv.h>
91 #include <epan/address_types.h>
92 #include <epan/conversation.h>
93 #include <epan/conversation_table.h>
94 #include <epan/conversation_filter.h>
95 #include <epan/prefs.h>
96 #include <epan/uat.h>
97 #include <epan/strutil.h>
98 #include <epan/to_str.h>
99 #include <epan/show_exception.h>
100 #include <epan/proto_data.h>
101 #include <epan/etypes.h>
102 #include <epan/oui.h>
103 #include <epan/tap.h>
104 #include <epan/tfs.h>
105 #include <epan/unit_strings.h>
106 #include <wsutil/pint.h>
108 /* Use libgcrypt for cipher libraries. */
109 #include <wsutil/wsgcrypt.h>
111 #include "packet-ieee802154.h"
112 #include "packet-sll.h"
113 #include "packet-zbee-tlv.h"
115 void proto_register_ieee802154(void);
116 void proto_reg_handoff_ieee802154(void);
118 /* Dissection Options for dissect_ieee802154_common */
119 #define DISSECT_IEEE802154_OPTION_CC24xx 0x00000001 /* Frame has TI CC24xx metadata, not an FCS, at the end */
120 #define DISSECT_IEEE802154_OPTION_ZBOSS 0x00000002 /* ZBOSS traffic dump */
122 /* ethertype for 802.15.4 tag - encapsulating an Ethernet packet */
123 static unsigned int ieee802154_ethertype = 0x809A;
125 /* FCS Types used by user configuration */
126 #define IEEE802154_CC24XX_METADATA 0 /* Not an FCS, but TI CC24xx metadata */
127 #define IEEE802154_FCS_16_BIT 1 /* ITU-T CRC16 */
128 #define IEEE802154_FCS_32_BIT 2 /* ITU-T CRC32 */
130 static int ieee802154_fcs_type = IEEE802154_FCS_16_BIT;
132 /* 802.15.4 TAP Fields */
133 typedef enum {
134 IEEE802154_TAP_FCS_TYPE = 0x0000,
135 IEEE802154_TAP_RSS = 0x0001,
136 IEEE802154_TAP_BIT_RATE = 0x0002,
137 IEEE802154_TAP_CHANNEL_ASSIGNMENT = 0x0003,
138 IEEE802154_TAP_SUN_PHY_INFO = 0x0004,
139 IEEE802154_TAP_START_OF_FRAME_TS = 0x0005,
140 IEEE802154_TAP_END_OF_FRAME_TS = 0x0006,
141 IEEE802154_TAP_ASN = 0x0007,
142 IEEE802154_TAP_SLOT_START_TS = 0x0008,
143 IEEE802154_TAP_TIMESLOT_LENGTH = 0x0009,
144 IEEE802154_TAP_LQI = 0x000A,
145 IEEE802154_TAP_CHANNEL_FREQUENCY = 0x000B,
146 IEEE802154_TAP_CHANNEL_PLAN = 0x000C,
147 IEEE802154_TAP_PHY_HEADER = 0x000D,
148 } ieee802154_info_type_t;
150 typedef enum {
151 PHR_RAW = 0,
152 PHR_O_QPSK = 1,
153 PHR_CSS = 2,
154 PHR_HRP_UWB = 3,
155 PHR_MSK = 4,
156 PHR_LRP_UWB = 5,
157 PHR_SUN_FSK = 6,
158 PHR_SUN_OFDM = 7,
159 PHR_SUN_O_QPSK = 8,
160 PHR_LECIM_FSK = 9,
161 PHR_TVWS_FSK = 10,
162 PHR_TVWS_OFDM = 11,
163 PHR_TVWS_NB_OFDM = 12,
164 PHR_RCC_LMR = 13,
165 PHR_CMB_O_QPSK = 14,
166 PHR_CMB_GFSK = 15,
167 PHR_TASK = 16,
168 PHR_RS_GFSK = 17,
169 PHR_WISUN_FSK_MS = 18,
170 } ieee802154_tap_phr_type_t;
172 typedef enum {
173 IEEE802154_FCS_TYPE_NONE = 0,
174 IEEE802154_FCS_TYPE_16_BIT = 1, /* ITU-T CRC16 */
175 IEEE802154_FCS_TYPE_32_BIT = 2, /* ITU-T CRC32 */
176 } ieee802154_fcs_type_t;
178 typedef enum {
179 IEEE802154_SUN_TYPE_FSK_A = 0x00,
180 IEEE802154_SUN_TYPE_FSK_B = 0x01,
181 IEEE802154_SUN_TYPE_OQPSK_A = 0x02,
182 IEEE802154_SUN_TYPE_OQPSK_B = 0x03,
183 IEEE802154_SUN_TYPE_OQPSK_C = 0x04,
184 IEEE802154_SUN_TYPE_OFDM_OPT1 = 0x05,
185 IEEE802154_SUN_TYPE_OFDM_OPT2 = 0x06,
186 IEEE802154_SUN_TYPE_OFDM_OPT3 = 0x07,
187 IEEE802154_SUN_TYPE_OFDM_OPT4 = 0x08,
188 } ieee802154_sun_type_t;
190 /* boolean value set if the FCS must be ok before payload is dissected */
191 static bool ieee802154_fcs_ok = true;
193 /* boolean value set to enable ack tracking */
194 static bool ieee802154_ack_tracking;
196 /* boolean value set to enable 802.15.4e dissection compatibility */
197 static bool ieee802154e_compatibility;
199 /* TSCH ASN for nonce in decryption */
200 static uint64_t ieee802154_tsch_asn;
202 static const char *ieee802154_user = "User";
204 static wmem_tree_t* mac_key_hash_handlers;
206 #ifndef ROUND_UP
207 #define ROUND_UP(_offset_, _align_) (((_offset_) + (_align_) - 1) / (_align_) * (_align_))
208 #endif
211 * Address Hash Tables
214 ieee802154_map_tab_t ieee802154_map = { NULL, NULL };
217 * Static Address Mapping UAT
220 /* UAT entry structure. */
221 typedef struct {
222 unsigned char *eui64;
223 unsigned eui64_len;
224 unsigned addr16;
225 unsigned pan;
226 } static_addr_t;
228 /* UAT variables */
229 static uat_t *static_addr_uat;
230 static static_addr_t *static_addrs;
231 static unsigned num_static_addrs;
233 static void*
234 addr_uat_copy_cb(void *dest, const void *source, size_t len _U_)
236 const static_addr_t* o = (const static_addr_t*)source;
237 static_addr_t* d = (static_addr_t*)dest;
239 d->eui64 = (unsigned char *)g_memdup2(o->eui64, o->eui64_len);
240 d->eui64_len = o->eui64_len;
241 d->addr16 = o->addr16;
242 d->pan = o->pan;
244 return dest;
247 /* Sanity-checks a UAT record. */
248 static bool
249 addr_uat_update_cb(void *r, char **err)
251 static_addr_t *map = (static_addr_t *)r;
252 /* Ensure a valid short address */
253 if (map->addr16 >= IEEE802154_NO_ADDR16) {
254 *err = g_strdup("Invalid short address");
255 return false;
257 /* Ensure a valid PAN identifier. */
258 if (map->pan >= IEEE802154_BCAST_PAN) {
259 *err = g_strdup("Invalid PAN identifier");
260 return false;
262 /* Ensure a valid EUI-64 length */
263 if (map->eui64_len != sizeof(uint64_t)) {
264 *err = g_strdup("Invalid EUI-64 length");
265 return false;
267 return true;
268 } /* ieee802154_addr_uat_update_cb */
270 static void
271 addr_uat_free_cb(void *r)
273 static_addr_t *rec = (static_addr_t *)r;
274 g_free(rec->eui64);
277 /* Field callbacks. */
278 UAT_HEX_CB_DEF(addr_uat, addr16, static_addr_t)
279 UAT_HEX_CB_DEF(addr_uat, pan, static_addr_t)
280 UAT_BUFFER_CB_DEF(addr_uat, eui64, static_addr_t, eui64, eui64_len)
283 * Decryption Keys UAT
286 /* UAT variables */
287 static uat_t *ieee802154_key_uat;
288 static ieee802154_key_t *ieee802154_keys;
289 static unsigned num_ieee802154_keys;
291 static void ieee802154_key_post_update_cb(void)
293 unsigned i;
294 GByteArray *bytes;
296 for (i = 0; i < num_ieee802154_keys; i++)
298 switch (ieee802154_keys[i].hash_type) {
299 case KEY_HASH_NONE:
300 case KEY_HASH_ZIP:
301 /* Get the IEEE 802.15.4 decryption key. */
302 bytes = g_byte_array_new();
303 if (hex_str_to_bytes(ieee802154_keys[i].pref_key, bytes, false))
305 if (ieee802154_keys[i].hash_type == KEY_HASH_ZIP) {
306 char digest[32];
308 if (!ws_hmac_buffer(GCRY_MD_SHA256, digest, "ZigBeeIP", 8, bytes->data, IEEE802154_CIPHER_SIZE)) {
309 /* Copy upper hashed bytes to the key */
310 memcpy(ieee802154_keys[i].key, &digest[IEEE802154_CIPHER_SIZE], IEEE802154_CIPHER_SIZE);
311 /* Copy lower hashed bytes to the MLE key */
312 memcpy(ieee802154_keys[i].mle_key, digest, IEEE802154_CIPHER_SIZE);
313 } else {
314 /* Just copy the keys verbatim */
315 memcpy(ieee802154_keys[i].key, bytes->data, IEEE802154_CIPHER_SIZE);
316 memcpy(ieee802154_keys[i].mle_key, bytes->data, IEEE802154_CIPHER_SIZE);
318 } else {
319 /* Just copy the keys verbatim */
320 memcpy(ieee802154_keys[i].key, bytes->data, IEEE802154_CIPHER_SIZE);
321 memcpy(ieee802154_keys[i].mle_key, bytes->data, IEEE802154_CIPHER_SIZE);
324 g_byte_array_free(bytes, true);
325 break;
326 case KEY_HASH_THREAD:
327 /* XXX - TODO? */
328 break;
333 static bool ieee802154_key_update_cb(void *r, char **err)
335 ieee802154_key_t* rec = (ieee802154_key_t*)r;
336 GByteArray *bytes;
338 switch (rec->hash_type) {
339 case KEY_HASH_NONE:
340 case KEY_HASH_ZIP:
341 bytes = g_byte_array_new();
342 if (hex_str_to_bytes(rec->pref_key, bytes, false) == false)
344 *err = g_strdup("Invalid key");
345 g_byte_array_free(bytes, true);
346 return false;
349 if (bytes->len < IEEE802154_CIPHER_SIZE)
351 *err = ws_strdup_printf("Key must be at least %d bytes", IEEE802154_CIPHER_SIZE);
352 g_byte_array_free(bytes, true);
353 return false;
355 g_byte_array_free(bytes, true);
356 break;
357 case KEY_HASH_THREAD:
358 /* XXX - TODO? */
359 break;
362 return true;
365 static void* ieee802154_key_copy_cb(void* n, const void* o, size_t siz _U_) {
366 ieee802154_key_t* new_record = (ieee802154_key_t*)n;
367 const ieee802154_key_t* old_record = (const ieee802154_key_t*)o;
369 new_record->pref_key = g_strdup(old_record->pref_key);
370 new_record->key_index = old_record->key_index;
371 new_record->hash_type = old_record->hash_type;
373 return new_record;
376 static void ieee802154_key_free_cb(void*r) {
377 ieee802154_key_t* rec = (ieee802154_key_t *)r;
379 g_free(rec->pref_key);
382 /* Field callbacks. */
383 UAT_CSTRING_CB_DEF(key_uat, pref_key, ieee802154_key_t)
384 UAT_DEC_CB_DEF(key_uat, key_index, ieee802154_key_t)
385 UAT_VS_DEF(key_uat, hash_type, ieee802154_key_t, ieee802154_key_hash, KEY_HASH_NONE, "No hash")
388 /*-------------------------------------
389 * Dissector Function Prototypes
390 *-------------------------------------
393 /* Dissection Routines. */
394 static int dissect_ieee802154_nonask_phy (tvbuff_t *, packet_info *, proto_tree *, void *);
395 static int dissect_ieee802154 (tvbuff_t *, packet_info *, proto_tree *, void *);
396 static int dissect_ieee802154_nofcs (tvbuff_t *, packet_info *, proto_tree *, void *);
397 static int dissect_ieee802154_cc24xx (tvbuff_t *, packet_info *, proto_tree *, void *);
398 static int dissect_ieee802154_tap (tvbuff_t *, packet_info *, proto_tree *, void *);
399 static tvbuff_t *dissect_zboss_specific (tvbuff_t *, packet_info *, proto_tree *);
400 static void dissect_ieee802154_common (tvbuff_t *, packet_info *, proto_tree *, unsigned, unsigned);
401 static void ieee802154_dissect_fcs(tvbuff_t *tvb, proto_tree *ieee802154_tree, unsigned fcs_len, bool fcs_ok);
402 static void ieee802154_dissect_cc24xx_metadata(tvbuff_t *tvb, proto_tree *ieee802154_tree, bool fcs_ok);
403 static ieee802154_fcs_type_t dissect_ieee802154_tap_tlvs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
405 /* Information Elements */
406 static int dissect_ieee802154_header_ie (tvbuff_t *, packet_info *, proto_tree *, unsigned, ieee802154_packet *);
407 static int dissect_ieee802154_payload_ie (tvbuff_t *, packet_info *, proto_tree *, unsigned, ieee802154_packet *);
408 static int dissect_802154_eb_filter (tvbuff_t *, packet_info *, proto_tree *, void *);
409 static int dissect_802154_tsch_time_sync (tvbuff_t *, packet_info *, proto_tree *, void *);
410 static int dissect_802154_tsch_timeslot (tvbuff_t *, packet_info *, proto_tree *, void *);
411 static int dissect_802154_tsch_slotframe_link (tvbuff_t *, packet_info *, proto_tree *, void *);
412 static int dissect_802154_channel_hopping (tvbuff_t *, packet_info *, proto_tree *, void *);
413 /* Sub-dissector helpers. */
414 static void dissect_ieee802154_fcf (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *, unsigned *);
415 static void dissect_ieee802154_command (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
416 static void dissect_ieee802154_assoc_req (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
417 static void dissect_ieee802154_assoc_rsp (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
418 static void dissect_ieee802154_disassoc (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
419 static void dissect_ieee802154_realign (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
420 static void dissect_ieee802154_gtsreq (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
422 /* Decryption helpers. */
423 static tvbuff_t *dissect_ieee802154_decrypt(tvbuff_t *, unsigned, packet_info *, ieee802154_packet *, ieee802154_decrypt_info_t*);
425 static unsigned ieee802154_set_mac_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t *uat_key);
426 static unsigned ieee802154_set_trel_key(ieee802154_packet* packet, unsigned char* key, unsigned char* alt_key, ieee802154_key_t* uat_key);
427 static void tsch_ccm_init_nonce(uint64_t addr, uint64_t asn, char* generic_nonce);
429 /* Initialize Protocol and Registered fields */
430 static int proto_ieee802154_nonask_phy;
431 static int hf_ieee802154_nonask_phy_preamble;
432 static int hf_ieee802154_nonask_phy_sfd;
433 static int hf_ieee802154_nonask_phy_length;
434 static int hf_ieee802154_nonask_phr;
436 static int proto_ieee802154;
437 static int proto_ieee802154_tap;
438 static int hf_ieee802154_frame_length;
439 static int hf_ieee802154_fcf;
440 static int hf_ieee802154_frame_type;
441 static int hf_ieee802154_security;
442 static int hf_ieee802154_pending;
443 static int hf_ieee802154_ack_request;
444 static int hf_ieee802154_pan_id_compression;
445 static int hf_ieee802154_fcf_reserved;
446 static int hf_ieee802154_seqno_suppression;
447 static int hf_ieee802154_ie_present;
448 static int hf_ieee802154_src_addr_mode;
449 static int hf_ieee802154_version;
450 static int hf_ieee802154_dst_addr_mode;
452 static int hf_ieee802154_mpf_long_frame_control;
453 static int hf_ieee802154_mpf_dst_addr_mode;
454 static int hf_ieee802154_mpf_src_addr_mode;
455 static int hf_ieee802154_mpf_pan_id_present;
456 static int hf_ieee802154_mpf_security;
457 static int hf_ieee802154_mpf_seqno_suppression;
458 static int hf_ieee802154_mpf_pending;
459 static int hf_ieee802154_mpf_version;
460 static int hf_ieee802154_mpf_ack_request;
461 static int hf_ieee802154_mpf_ie_present;
463 static int hf_ieee802154_header_ies;
464 static int hf_ieee802154_header_ie_tlv;
465 static int hf_ieee802154_header_ie_type;
466 static int hf_ieee802154_header_ie_id;
467 static int hf_ieee802154_header_ie_length;
468 static int hf_ieee802154_ie_unknown_content;
469 static int hf_ieee802154_ie_unknown_content_payload;
470 static int hf_ieee802154_hie_unsupported;
471 static int hf_ieee802154_hie_time_correction;
472 static int hf_ieee802154_hie_ht1;
473 static int hf_ieee802154_hie_ht2;
474 static int hf_ieee802154_hie_thread;
475 static int hf_ieee802154_nack;
476 static int hf_ieee802154_hie_time_correction_time_sync_info;
477 static int hf_ieee802154_hie_time_correction_value;
478 static int hf_ieee802154_hie_csl;
479 static int hf_ieee802154_hie_csl_phase;
480 static int hf_ieee802154_hie_csl_period;
481 static int hf_ieee802154_hie_csl_rendezvous_time;
482 static int hf_ieee802154_hie_rdv;
483 static int hf_ieee802154_hie_rdv_wakeup_interval;
484 static int hf_ieee802154_hie_global_time;
485 static int hf_ieee802154_hie_global_time_value;
486 static int hf_ieee802154_hie_vendor_specific;
487 static int hf_ieee802154_hie_vendor_specific_vendor_oui;
488 static int hf_ieee802154_hie_vendor_specific_content;
489 static int hf_ieee802154_payload_ies;
490 static int hf_ieee802154_payload_ie_tlv;
491 static int hf_ieee802154_payload_ie_type;
492 static int hf_ieee802154_payload_ie_id;
493 static int hf_ieee802154_payload_ie_length;
494 static int hf_ieee802154_pie_unsupported;
495 static int hf_ieee802154_pie_termination;
496 static int hf_ieee802154_pie_vendor;
497 static int hf_ieee802154_pie_vendor_oui;
498 static int hf_ieee802154_pie_vendor_variable;
499 static int hf_ieee802154_pie_ietf;
500 static int hf_ieee802154_mlme;
501 static int hf_ieee802154_mlme_ie_data;
502 static int hf_ieee802154_mlme_ie_unsupported;
503 static int hf_ieee802154_psie;
504 static int hf_ieee802154_psie_type;
505 static int hf_ieee802154_psie_id_short;
506 static int hf_ieee802154_psie_length_short;
507 static int hf_ieee802154_psie_id_long;
508 static int hf_ieee802154_psie_length_long;
510 static int hf_ieee802154_tsch_sync;
511 static int hf_ieee802154_tsch_asn;
512 static int hf_ieee802154_tsch_join_metric;
513 static int hf_ieee802154_tsch_slotframe;
514 static int hf_ieee802154_tsch_link_info;
515 static int hf_ieee802154_tsch_slotf_link_nb_slotf;
516 static int hf_ieee802154_tsch_slotf_link_slotf_handle;
517 static int hf_ieee802154_tsch_slotf_size;
518 static int hf_ieee802154_tsch_slotf_link_nb_links;
519 static int hf_ieee802154_tsch_slotf_link_timeslot;
520 static int hf_ieee802154_tsch_slotf_link_channel_offset;
521 static int hf_ieee802154_tsch_slotf_link_options;
522 static int hf_ieee802154_tsch_slotf_link_options_tx;
523 static int hf_ieee802154_tsch_slotf_link_options_rx;
524 static int hf_ieee802154_tsch_slotf_link_options_shared;
525 static int hf_ieee802154_tsch_slotf_link_options_timkeeping;
526 static int hf_ieee802154_tsch_slotf_link_options_priority;
527 static int hf_ieee802154_tsch_channel_hopping;
528 static int hf_ieee802154_tsch_hopping_sequence_id;
529 static int hf_ieee802154_tsch_timeslot;
530 static int hf_ieee802154_tsch_timeslot_id;
531 static int hf_ieee802154_tsch_timeslot_cca_offset;
532 static int hf_ieee802154_tsch_timeslot_cca;
533 static int hf_ieee802154_tsch_timeslot_tx_offset;
534 static int hf_ieee802154_tsch_timeslot_rx_offset;
535 static int hf_ieee802154_tsch_timeslot_rx_ack_delay;
536 static int hf_ieee802154_tsch_timeslot_tx_ack_delay;
537 static int hf_ieee802154_tsch_timeslot_rx_wait;
538 static int hf_ieee802154_tsch_timeslot_ack_wait;
539 static int hf_ieee802154_tsch_timeslot_turnaround;
540 static int hf_ieee802154_tsch_timeslot_max_ack;
541 static int hf_ieee802154_tsch_timeslot_max_tx;
542 static int hf_ieee802154_tsch_timeslot_length;
544 static int hf_ieee802154_psie_eb_filter;
545 static int hf_ieee802154_psie_eb_filter_pjoin;
546 static int hf_ieee802154_psie_eb_filter_lqi;
547 static int hf_ieee802154_psie_eb_filter_lqi_min;
548 static int hf_ieee802154_psie_eb_filter_percent;
549 static int hf_ieee802154_psie_eb_filter_percent_prob;
550 static int hf_ieee802154_psie_eb_filter_attr_id;
551 static int hf_ieee802154_psie_eb_filter_attr_id_bitmap;
552 static int hf_ieee802154_p_ie_ietf_sub_id;
554 static int hf_ieee802154_6top;
555 static int hf_ieee802154_6top_version;
556 static int hf_ieee802154_6top_type;
557 static int hf_ieee802154_6top_flags_reserved;
558 static int hf_ieee802154_6top_code;
559 static int hf_ieee802154_6top_sfid;
560 static int hf_ieee802154_6top_seqnum;
561 static int hf_ieee802154_6top_metadata;
562 static int hf_ieee802154_6top_cell_options;
563 static int hf_ieee802154_6top_cell_option_tx;
564 static int hf_ieee802154_6top_cell_option_rx;
565 static int hf_ieee802154_6top_cell_option_shared;
566 static int hf_ieee802154_6top_cell_option_reserved;
567 static int hf_ieee802154_6top_num_cells;
568 static int hf_ieee802154_6top_cell_list;
569 static int hf_ieee802154_6top_rel_cell_list;
570 static int hf_ieee802154_6top_cand_cell_list;
571 static int hf_ieee802154_6top_cell;
572 static int hf_ieee802154_6top_reserved;
573 static int hf_ieee802154_6top_offset;
574 static int hf_ieee802154_6top_max_num_cells;
575 static int hf_ieee802154_6top_slot_offset;
576 static int hf_ieee802154_6top_channel_offset;
577 static int hf_ieee802154_6top_total_num_cells;
578 static int hf_ieee802154_6top_payload;
580 static int hf_ieee802159_mpx;
581 static int hf_ieee802159_mpx_transaction_control;
582 static int hf_ieee802159_mpx_transfer_type;
583 static int hf_ieee802159_mpx_transaction_id;
584 static int hf_ieee802159_mpx_transaction_id_as_multiplex_id;
585 static int hf_ieee802159_mpx_fragment_number;
586 static int hf_ieee802159_mpx_total_frame_size;
587 static int hf_ieee802159_mpx_multiplex_id;
588 static int hf_ieee802159_mpx_kmp_id;
589 static int hf_ieee802159_mpx_kmp_vendor_oui;
590 static int hf_ieee802159_mpx_fragment;
591 static int hf_ieee802159_mpx_wisun_subid;
593 static int proto_zboss;
594 static int hf_zboss_direction;
595 static int hf_zboss_page;
596 static int hf_zboss_channel;
597 static int hf_zboss_trace_number;
599 static int hf_ieee802154_seqno;
600 static int hf_ieee802154_dst_panID;
601 static int hf_ieee802154_dst16;
602 static int hf_ieee802154_dst64;
603 static int hf_ieee802154_src_panID;
604 static int hf_ieee802154_src16;
605 static int hf_ieee802154_src64;
606 static int hf_ieee802154_src64_origin;
607 static int hf_ieee802154_addr16;
608 static int hf_ieee802154_addr64;
609 static int hf_ieee802154_fcs;
610 static int hf_ieee802154_fcs32;
611 static int hf_ieee802154_rssi;
612 static int hf_ieee802154_fcs_ok;
613 static int hf_ieee802154_correlation;
615 /* Registered fields for Command Packets */
616 static int hf_ieee802154_cmd_id;
617 static int hf_ieee802154_cinfo_alt_coord;
618 static int hf_ieee802154_cinfo_device_type;
619 static int hf_ieee802154_cinfo_power_src;
620 static int hf_ieee802154_cinfo_idle_rx;
621 static int hf_ieee802154_cinfo_sec_capable;
622 static int hf_ieee802154_cinfo_alloc_addr;
623 static int hf_ieee802154_assoc_addr;
624 static int hf_ieee802154_assoc_status;
625 static int hf_ieee802154_disassoc_reason;
626 static int hf_ieee802154_realign_pan;
627 static int hf_ieee802154_realign_caddr;
628 static int hf_ieee802154_realign_channel;
629 static int hf_ieee802154_realign_addr;
630 static int hf_ieee802154_realign_channel_page;
631 static int hf_ieee802154_gtsreq_len;
632 static int hf_ieee802154_gtsreq_dir;
633 static int hf_ieee802154_gtsreq_type;
634 static int hf_ieee802154_cmd_vendor_oui;
636 /* Registered fields for Beacon Packets */
637 static int hf_ieee802154_beacon_order;
638 static int hf_ieee802154_superframe_order;
639 static int hf_ieee802154_cap;
640 static int hf_ieee802154_superframe_battery_ext;
641 static int hf_ieee802154_superframe_coord;
642 static int hf_ieee802154_assoc_permit;
643 static int hf_ieee802154_gts_count;
644 static int hf_ieee802154_gts_permit;
645 static int hf_ieee802154_gts_direction;
646 static int hf_ieee802154_gts_address;
647 static int hf_ieee802154_pending16;
648 static int hf_ieee802154_pending64;
650 /* Registered fields for Auxiliary Security Header */
651 static int hf_ieee802154_aux_security_header;
652 static int hf_ieee802154_aux_sec_security_control;
653 static int hf_ieee802154_aux_sec_security_level;
654 static int hf_ieee802154_aux_sec_key_id_mode;
655 static int hf_ieee802154_aux_sec_frame_counter_suppression;
656 static int hf_ieee802154_aux_sec_asn_in_nonce;
657 static int hf_ieee802154_aux_sec_reserved;
658 static int hf_ieee802154_aux_sec_frame_counter;
659 static int hf_ieee802154_aux_sec_key_source;
660 static int hf_ieee802154_aux_sec_key_source_bytes;
661 static int hf_ieee802154_aux_sec_key_index;
662 static int hf_ieee802154_mic;
663 static int hf_ieee802154_key_number;
665 /* 802.15.4-2003 security */
666 static int hf_ieee802154_sec_frame_counter;
667 static int hf_ieee802154_sec_key_sequence_counter;
669 /* 802.15.4 ack */
670 static int hf_ieee802154_no_ack;
671 static int hf_ieee802154_no_ack_request;
672 static int hf_ieee802154_ack_in;
673 static int hf_ieee802154_ack_to;
674 static int hf_ieee802154_ack_time;
676 /* 802.15.4 TAP */
677 static int hf_ieee802154_tap_version;
678 static int hf_ieee802154_tap_reserved;
679 static int hf_ieee802154_tap_length;
680 static int hf_ieee802154_tap_data_length;
681 static int hf_ieee802154_tap_tlv_type;
682 static int hf_ieee802154_tap_tlv_length;
683 static int hf_ieee802154_tap_tlv_unknown;
684 static int hf_ieee802154_tap_tlv_padding;
685 static int hf_ieee802154_tap_fcs_type;
686 static int hf_ieee802154_tap_rss;
687 static int hf_ieee802154_ch_page;
688 static int hf_ieee802154_ch_num;
689 static int hf_ieee802154_bit_rate;
690 static int hf_ieee802154_sun_band;
691 static int hf_ieee802154_sun_type;
692 static int hf_ieee802154_sun_mode;
693 static int hf_ieee802154_mode_fsk_a;
694 static int hf_ieee802154_mode_fsk_b;
695 static int hf_ieee802154_mode_oqpsk_a;
696 static int hf_ieee802154_mode_oqpsk_b;
697 static int hf_ieee802154_mode_oqpsk_c;
698 static int hf_ieee802154_mode_ofdm;
699 static int hf_ieee802154_sof_ts;
700 static int hf_ieee802154_eof_ts;
701 static int hf_ieee802154_slot_start_ts;
702 static int hf_ieee802154_tap_timeslot_length;
703 static int hf_ieee802154_tap_lqi;
704 static int hf_ieee802154_chplan_start;
705 static int hf_ieee802154_chplan_spacing;
706 static int hf_ieee802154_chplan_channels;
707 static int hf_ieee802154_ch_freq;
708 static int hf_ieee802154_frame_start_offset;
709 static int hf_ieee802154_frame_duration;
710 static int hf_ieee802154_frame_end_offset;
711 static int hf_ieee802154_asn;
713 static int hf_ieee802154_tap_phr_type;
714 static int hf_ieee802154_tap_phr_bits;
715 static int hf_ieee802154_tap_phr_data;
717 static int hf_ieee802154_tap_phr_fsk;
718 static int hf_ieee802154_tap_fsk_ms_phr;
719 static int hf_ieee802154_tap_wisun_ms_phr;
721 static int hf_ieee802154_tap_phr_fsk_ms;
722 static int hf_ieee802154_tap_phr_fsk_fcs;
723 static int hf_ieee802154_tap_phr_fsk_dw;
724 static int hf_ieee802154_tap_phr_fsk_length;
726 static int hf_ieee802154_tap_phr_fsk_ms_param;
727 static int hf_ieee802154_tap_phr_fsk_ms_fec;
728 static int hf_ieee802154_tap_phr_fsk_ms_checksum;
729 static int hf_ieee802154_tap_phr_fsk_ms_parity;
731 static int hf_ieee802154_tap_phr_fsk_ms_mode_page;
732 static int hf_ieee802154_tap_phr_fsk_ms_mode_scheme;
733 static int hf_ieee802154_tap_phr_fsk_ms_mode_mode;
734 static int hf_ieee802154_tap_phr_fsk_ms_mode_addl_mode;
735 static int hf_ieee802154_tap_phr_wisun_fsk_ms_reserved;
736 static int hf_ieee802154_tap_phr_wisun_fsk_ms_phymodeid;
738 /* Bit-masks for SUN FSK PHR per IEEE 802.15.4-2020 19.2.4 */
739 #define IEEE802154_TAP_PHR_FSK_MS 0x8000
740 #define IEEE802154_TAP_PHR_FSK_FCS 0x0100
741 #define IEEE802154_TAP_PHR_FSK_DW 0x0080
742 #define IEEE802154_TAP_PHR_FSK_LENGTH 0x07ff
744 /* Bit-masks for SUN FSK Mode Switch PHR per IEEE 802.15.4-2020 19.2.5 */
745 #define IEEE802154_TAP_PHR_FSK_MS_PARAM 0x6000
746 #define IEEE802154_TAP_PHR_FSK_MS_FEC 0x1000
747 #define IEEE802154_TAP_PHR_FSK_MS_MODE 0x0FE0
748 #define IEEE802154_TAP_PHR_FSK_MS_MODE_PAGE 0x0800
749 #define IEEE802154_TAP_PHR_FSK_MS_MODE_SCHEME 0x0600
750 #define IEEE802154_TAP_PHR_FSK_MS_MODE_MODE 0x01E0
751 #define IEEE802154_TAP_PHR_FSK_MS_CHECKSUM 0x001E
752 #define IEEE802154_TAP_PHR_FSK_MS_PARITY 0x0001
754 #define IEEE802154_TAP_PHR_FSK_MS_SCHEME_FSK 0x0000
755 #define IEEE802154_TAP_PHR_FSK_MS_SCHEME_OFDM 0x0200
756 #define IEEE802154_TAP_PHR_FSK_MS_SCHEME_OQPSK 0x0400
757 #define IEEE802154_TAP_PHR_FSK_MS_SCHEME_ADDL 0x0600
759 /* Bit-masks for Wi-SUN FSK Mode Switch PHR */
760 #define IEEE802154_TAP_PHR_WISUN_FSK_MS_RESERVED 0x6000
761 #define IEEE802154_TAP_PHR_WISUN_FSK_MS_PHYMODEID 0x1FE0
763 typedef struct _ieee802154_transaction_t {
764 uint64_t dst64;
765 uint64_t src64;
766 int32_t dst_addr_mode;
767 int32_t src_addr_mode;
768 uint16_t dst16;
769 uint16_t src16;
770 uint32_t rqst_frame;
771 uint32_t ack_frame;
772 nstime_t rqst_time;
773 nstime_t ack_time;
774 bool dst_pan_present;
775 bool src_pan_present;
776 uint16_t dst_pan;
777 uint16_t src_pan;
778 } ieee802154_transaction_t;
780 static const nstime_t ieee802154_transaction_timeout = NSTIME_INIT_SECS_MSECS(1, 0); // ACKs usually arrive within milliseconds
782 static wmem_tree_t *transaction_unmatched_pdus;
783 static wmem_tree_t *transaction_matched_pdus;
785 static ieee802154_transaction_t *transaction_start(packet_info *pinfo, proto_tree *tree, const ieee802154_packet *packet, uint32_t *key);
786 static ieee802154_transaction_t *transaction_end(packet_info *pinfo, proto_tree *tree, const ieee802154_packet *packet, uint32_t *key);
788 /* Initialize Subtree Pointers */
789 static int ett_ieee802154_nonask_phy;
790 static int ett_ieee802154_nonask_phy_phr;
791 static int ett_ieee802154_tap;
792 static int ett_ieee802154_tap_header;
793 static int ett_ieee802154_tap_tlv;
794 static int ett_ieee802154;
795 static int ett_ieee802154_fcf;
796 static int ett_ieee802154_auxiliary_security;
797 static int ett_ieee802154_aux_sec_control;
798 static int ett_ieee802154_aux_sec_key_id;
799 static int ett_ieee802154_fcs;
800 static int ett_ieee802154_cmd;
801 static int ett_ieee802154_superframe;
802 static int ett_ieee802154_gts;
803 static int ett_ieee802154_gts_direction;
804 static int ett_ieee802154_gts_descriptors;
805 static int ett_ieee802154_pendaddr;
806 static int ett_ieee802154_header_ies;
807 static int ett_ieee802154_header_ie;
808 static int ett_ieee802154_header_ie_tlv;
809 static int ett_ieee802154_hie_unsupported;
810 static int ett_ieee802154_hie_time_correction;
811 static int ett_ieee802154_hie_ht;
812 static int ett_ieee802154_hie_thread;
813 static int ett_ieee802154_hie_csl;
814 static int ett_ieee802154_hie_rdv;
815 static int ett_ieee802154_hie_global_time;
816 static int ett_ieee802154_hie_vendor_specific;
817 static int ett_ieee802154_payload_ie;
818 static int ett_ieee802154_payload_ie_tlv;
819 static int ett_ieee802154_pie_termination;
820 static int ett_ieee802154_pie_vendor;
821 static int ett_ieee802154_pie_ietf;
822 static int ett_ieee802154_pie_unsupported;
823 static int ett_ieee802154_mlme;
824 static int ett_ieee802154_mlme_payload;
825 static int ett_ieee802154_mlme_payload_data;
826 static int ett_ieee802154_mlme_unsupported;
827 static int ett_ieee802154_tsch_slotframe;
828 static int ett_ieee802154_tsch_slotframe_list;
829 static int ett_ieee802154_tsch_slotframe_link;
830 static int ett_ieee802154_tsch_slotframe_link_options;
831 static int ett_ieee802154_tsch_timeslot;
832 static int ett_ieee802154_tsch_synch;
833 static int ett_ieee802154_channel_hopping;
834 static int ett_ieee802154_psie;
835 static int ett_ieee802154_eb_filter;
836 static int ett_ieee802154_eb_filter_bitmap;
837 static int ett_ieee802154_zigbee;
838 static int ett_ieee802154_zboss;
839 static int ett_ieee802154_p_ie_6top;
840 static int ett_ieee802154_p_ie_6top_cell_options;
841 static int ett_ieee802154_p_ie_6top_cell_list;
842 static int ett_ieee802154_p_ie_6top_cand_cell_list;
843 static int ett_ieee802154_p_ie_6top_rel_cell_list;
844 static int ett_ieee802154_p_ie_6top_cell;
845 static int ett_ieee802159_mpx;
846 static int ett_ieee802159_mpx_transaction_control;
847 static int ett_ieee802154_tap_phr;
849 static expert_field ei_ieee802154_fcs_bitmask_len;
850 static expert_field ei_ieee802154_invalid_addressing;
851 static expert_field ei_ieee802154_invalid_panid_compression;
852 static expert_field ei_ieee802154_invalid_panid_compression2;
853 static expert_field ei_ieee802154_fcs;
854 static expert_field ei_ieee802154_decrypt_error;
855 static expert_field ei_ieee802154_dst;
856 static expert_field ei_ieee802154_src;
857 static expert_field ei_ieee802154_frame_ver;
858 /* static expert_field ei_ieee802154_frame_type; */
859 static expert_field ei_ieee802154_seqno_suppression;
860 static expert_field ei_ieee802154_ack_not_found;
861 static expert_field ei_ieee802154_ack_request_not_found;
862 static expert_field ei_ieee802154_time_correction_error;
863 static expert_field ei_ieee802154_6top_unsupported_type;
864 static expert_field ei_ieee802154_6top_unsupported_return_code;
865 static expert_field ei_ieee802154_6top_unsupported_command;
866 static expert_field ei_ieee802154_ie_unsupported_id;
867 static expert_field ei_ieee802154_ie_unknown_extra_content;
868 static expert_field ei_ieee802154_ie_unknown_extra_content_payload;
869 static expert_field ei_ieee802159_mpx_invalid_transfer_type;
870 static expert_field ei_ieee802159_mpx_unsupported_kmp;
871 static expert_field ei_ieee802159_mpx_unknown_kmp;
872 static expert_field ei_ieee802154_missing_payload_ie;
873 static expert_field ei_ieee802154_payload_ie_in_header;
874 static expert_field ei_ieee802154_unsupported_cmd;
875 static expert_field ei_ieee802154_unknown_cmd;
876 static expert_field ei_ieee802154_tap_tlv_invalid_type;
877 static expert_field ei_ieee802154_tap_tlv_invalid_length;
878 static expert_field ei_ieee802154_tap_tlv_padding_not_zeros;
879 static expert_field ei_ieee802154_tap_tlv_invalid_fcs_type;
880 static expert_field ei_ieee802154_tap_tlv_reserved_not_zero;
881 static expert_field ei_ieee802154_tap_no_payload;
883 static int ieee802_15_4_short_address_type = -1;
885 * Dissector handles
886 * - beacon dissection is always heuristic.
887 * - the PANID table is for stateful dissectors only (ie: Decode-As)
888 * - otherwise, data dissectors fall back to the heuristic dissectors.
890 static dissector_table_t panid_dissector_table;
891 static heur_dissector_list_t ieee802154_beacon_subdissector_list;
892 static heur_dissector_list_t ieee802154_heur_subdissector_list;
894 /* For the IEs and the vendor specific command */
895 static dissector_table_t header_ie_dissector_table;
896 static dissector_table_t payload_ie_dissector_table;
897 static dissector_table_t mlme_ie_dissector_table;
898 static dissector_table_t cmd_vendor_dissector_table;
900 static dissector_handle_t zigbee_ie_handle;
901 static dissector_handle_t zigbee_nwk_handle;
902 static dissector_handle_t ieee802154_handle;
903 static dissector_handle_t ieee802154_nonask_phy_handle;
904 static dissector_handle_t ieee802154_nofcs_handle;
905 static dissector_handle_t ieee802154_tap_handle;
907 /* Thread 802.15.4 - 2015 */
908 static dissector_handle_t thread_ie_handle;
910 static int ieee802154_tap;
912 /* Handles for MPX-IE the Multiplex ID */
913 static dissector_table_t ethertype_table;
914 static dissector_handle_t eapol_handle;
915 static dissector_handle_t lowpan_handle;
916 static dissector_handle_t wisun_sec_handle;
918 /* Versions */
919 static const value_string ieee802154_frame_versions[] = {
920 { IEEE802154_VERSION_2003, "IEEE Std 802.15.4-2003" },
921 { IEEE802154_VERSION_2006, "IEEE Std 802.15.4-2006" },
922 { IEEE802154_VERSION_2015, "IEEE Std 802.15.4-2015" },
923 { IEEE802154_VERSION_RESERVED, "Reserved" },
924 { 0, NULL }
927 /* Name Strings */
928 static const value_string ieee802154_frame_types[] = {
929 { IEEE802154_FCF_BEACON, "Beacon" },
930 { IEEE802154_FCF_DATA, "Data" },
931 { IEEE802154_FCF_ACK, "Ack" },
932 { IEEE802154_FCF_CMD, "Command" },
933 { IEEE802154_FCF_RESERVED, "Reserved" },
934 { IEEE802154_FCF_MULTIPURPOSE, "Multipurpose" },
935 { IEEE802154_FCF_FRAGMENT, "Fragment or Frak" },
936 { IEEE802154_FCF_EXTENDED, "Extended" },
937 { 0, NULL }
940 static const value_string ieee802154_addr_modes[] = {
941 { IEEE802154_FCF_ADDR_NONE, "None" },
942 { IEEE802154_FCF_ADDR_RESERVED, "Reserved" },
943 { IEEE802154_FCF_ADDR_SHORT, "Short/16-bit" },
944 { IEEE802154_FCF_ADDR_EXT, "Long/64-bit" },
945 { 0, NULL }
948 static const value_string ieee802154_cmd_names[] = {
949 { IEEE802154_CMD_ASSOC_REQ, "Association Request" },
950 { IEEE802154_CMD_ASSOC_RSP, "Association Response" },
951 { IEEE802154_CMD_DISASSOC_NOTIFY, "Disassociation Notification" },
952 { IEEE802154_CMD_DATA_RQ, "Data Request" },
953 { IEEE802154_CMD_PANID_CONFLICT, "PAN ID Conflict" },
954 { IEEE802154_CMD_ORPHAN_NOTIFY, "Orphan Notification" },
955 { IEEE802154_CMD_BEACON_REQ, "Beacon Request" },
956 { IEEE802154_CMD_COORD_REALIGN, "Coordinator Realignment" },
957 { IEEE802154_CMD_GTS_REQ, "GTS Request" },
958 { IEEE802154_CMD_TRLE_MGMT_REQ, "TRLE Management Request"},
959 { IEEE802154_CMD_TRLE_MGMT_RSP, "TRLE Management Response"},
960 { IEEE802154_CMD_DSME_ASSOC_REQ, "DSME Association Request"},
961 { IEEE802154_CMD_DSME_ASSOC_RSP, "DSME Association Response"},
962 { IEEE802154_CMD_DSME_GTS_REQ, "DSME GTS Request"},
963 { IEEE802154_CMD_DSME_GTS_RSP, "DSME GTS Response"},
964 { IEEE802154_CMD_DSME_GTS_NOTIFY, "DSME GTS Notify"},
965 { IEEE802154_CMD_DSME_INFO_REQ, "DSME Information Request"},
966 { IEEE802154_CMD_DSME_INFO_RSP, "DSME Information Response"},
967 { IEEE802154_CMD_DSME_BEACON_ALLOC_NOTIFY, "DSME Beacon Allocation Notification"},
968 { IEEE802154_CMD_DSME_BEACON_COLL_NOTIFY, "DSME Beacon Collision Notification"},
969 { IEEE802154_CMD_DSME_LINK_REPORT, "DSME Link Report"},
970 { IEEE802154_CMD_RIT_DATA_REQ, "RIT Data Request"},
971 { IEEE802154_CMD_DBS_REQ, "DBS Request"},
972 { IEEE802154_CMD_DBS_RSP, "DBS Response"},
973 { IEEE802154_CMD_RIT_DATA_RSP, "RIT Data Response"},
974 { IEEE802154_CMD_VENDOR_SPECIFIC, "Vendor Specific"},
975 { 0, NULL }
978 static const value_string ieee802154_sec_level_names[] = {
979 { SECURITY_LEVEL_NONE, "No Security" },
980 { SECURITY_LEVEL_MIC_32, "32-bit Message Integrity Code" },
981 { SECURITY_LEVEL_MIC_64, "64-bit Message Integrity Code" },
982 { SECURITY_LEVEL_MIC_128, "128-bit Message Integrity Code" },
983 { SECURITY_LEVEL_ENC, "Encryption" },
984 { SECURITY_LEVEL_ENC_MIC_32, "Encryption with 32-bit Message Integrity Code" },
985 { SECURITY_LEVEL_ENC_MIC_64, "Encryption with 64-bit Message Integrity Code" },
986 { SECURITY_LEVEL_ENC_MIC_128, "Encryption with 128-bit Message Integrity Code" },
987 { 0, NULL }
990 static const value_string ieee802154_key_id_mode_names[] = {
991 { KEY_ID_MODE_IMPLICIT, "Implicit Key" },
992 { KEY_ID_MODE_KEY_INDEX, "Indexed Key using the Default Key Source" },
993 { KEY_ID_MODE_KEY_EXPLICIT_4, "Explicit Key with 4-octet Key Source" },
994 { KEY_ID_MODE_KEY_EXPLICIT_8, "Explicit Key with 8-octet Key Source" },
995 { 0, NULL }
998 static const true_false_string ieee802154_gts_direction_tfs = {
999 "Receive Only",
1000 "Transmit Only"
1003 /* The 802.15.4-2003 security suites for the security preferences (only AES-CCM suites are supported). */
1004 /* NOTE: The equivalent 2006 security level identifier enumerations are used to simplify 2003 & 2006 integration! */
1005 static const enum_val_t ieee802154_2003_sec_suite_enums[] = {
1006 { "AES-CCM-128", "AES-128 Encryption, 128-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_128 },
1007 { "AES-CCM-64", "AES-128 Encryption, 64-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_64 },
1008 { "AES-CCM-32", "AES-128 Encryption, 32-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_32 },
1009 { NULL, NULL, 0 }
1012 /* Enumeration for key generation */
1013 static const value_string ieee802154_key_hash_vals[] = {
1014 { KEY_HASH_NONE, "No hash"},
1015 { KEY_HASH_ZIP, "ZigBee IP hash" },
1016 { KEY_HASH_THREAD, "Thread hash" },
1017 { 0, NULL }
1020 static const value_string ieee802154_ie_types[] = {
1021 { 0, "Header" },
1022 { 1, "Payload" },
1023 { 0, NULL }
1026 static const value_string ieee802154_psie_types[] = {
1027 { 0, "Short" },
1028 { 1, "Long" },
1029 { 0, NULL }
1032 static const value_string ieee802154_header_ie_names[] = {
1033 { IEEE802154_HEADER_IE_VENDOR_SPECIFIC, "Vendor Specific IE" },
1034 { IEEE802154_HEADER_IE_CSL, "CSL IE" },
1035 { IEEE802154_HEADER_IE_RIT, "RIT IE" },
1036 { IEEE802154_HEADER_IE_DSME_PAN, "DSME PAN descriptor IE" },
1037 { IEEE802154_HEADER_IE_RENDEZVOUS, "Rendezvous Time IE" },
1038 { IEEE802154_HEADER_IE_TIME_CORR, "Time Correction IE" },
1039 { IEEE802154_HEADER_IE_EXT_DSME_PAN, "Extended DSME PAN descriptor IE" },
1040 { IEEE802154_HEADER_IE_FSCD, "Fragment Sequence Context Description (FSCD) IE" },
1041 { IEEE802154_HEADER_IE_SMPL_SUPER_FRM, "Simplified Superframe Specification IE" },
1042 { IEEE802154_HEADER_IE_SMPL_GTS, "Simplified GTS Specification IE" },
1043 { IEEE802154_HEADER_IE_LECIM, "LECIM Capabilities IE" },
1044 { IEEE802154_HEADER_IE_TRLE, "TRLE Descriptor" },
1045 { IEEE802154_HEADER_IE_RCC_CAP, "RCC Capabilities IE" },
1046 { IEEE802154_HEADER_IE_RCCN, "RCCN Descriptor IE" },
1047 { IEEE802154_HEADER_IE_GLOBAL_TIME, "Global Time IE" },
1048 { IEEE802154_HEADER_IE_WISUN, "Wi-SUN IE" },
1049 { IEEE802154_HEADER_IE_DA_IE, "DA IE" },
1050 { IEEE802154_HEADER_IE_HT1, "Header Termination 1 IE" },
1051 { IEEE802154_HEADER_IE_HT2, "Header Termination 2 IE" },
1052 { 0, NULL }
1055 static const true_false_string hf_ieee802154_nack_tfs = {
1056 "Negative Acknowledgement",
1057 "Acknowledgement"
1060 static const value_string ieee802154_payload_ie_names[] = {
1061 { IEEE802154_PAYLOAD_IE_ESDU, "ESDU IE" },
1062 { IEEE802154_PAYLOAD_IE_MLME, "MLME IE" },
1063 { IEEE802154_PAYLOAD_IE_VENDOR, "Vendor Specific IE" },
1064 { IEEE802154_PAYLOAD_IE_MPX, "MPX IE" },
1065 { IEEE802154_PAYLOAD_IE_WISUN, "Wi-SUN IE" },
1066 { IEEE802154_PAYLOAD_IE_IETF, "IETF IE" },
1067 { IEEE802154_PAYLOAD_IE_TERMINATION, "Payload Termination IE" },
1068 { 0, NULL }
1071 static const value_string ieee802154_psie_names[] = {
1072 { IEEE802154_MLME_SUBIE_CHANNEL_HOPPING, "Channel Hopping IE" },
1073 { IEEE802154_MLME_SUBIE_TSCH_SYNCH, "TSCH Synchronization IE" },
1074 { IEEE802154_MLME_SUBIE_TSCH_SLOTFR_LINK, "TSCH Slotframe and Link IE" },
1075 { IEEE802154_MLME_SUBIE_TSCH_TIMESLOT, "TSCH Timeslot IE" },
1076 { IEEE802154_MLME_SUBIE_HOPPING_TIMING, "Hopping Timing IE" },
1077 { IEEE802154_MLME_SUBIE_ENHANCED_BEACON_FILTER, "Enhanced Beacon Filter IE" },
1078 { IEEE802154_MLME_SUBIE_MAC_METRICS, "MAC Metrics IE" },
1079 { IEEE802154_MLME_SUBIE_ALL_MAC_METRICS, "All MAC Metrics IE" },
1080 { IEEE802154_MLME_SUBIE_COEXISTENCE_SPEC, "Coexistence Specification IE" },
1081 { IEEE802154_MLME_SUBIE_SUN_DEVICE_CAPABILITIES, "SUN Device Capabilities IE" },
1082 { IEEE802154_MLME_SUBIE_SUN_FSK_GEN_PHY, "SUN FSK Generic PHY IE" },
1083 { IEEE802154_MLME_SUBIE_MODE_SWITCH_PARAMETER, "Mode Switch Parameter IE" },
1084 { IEEE802154_MLME_SUBIE_PHY_PARAMETER_CHANGE, "PHY Parameter Change IE" },
1085 { IEEE802154_MLME_SUBIE_O_QPSK_PHY_MODE, "O-QPSY PHY Mode IE" },
1086 { IEEE802154_MLME_SUBIE_PCA_ALLOCATION, "PCA Allocation IE" },
1087 { IEEE802154_MLME_SUBIE_DSSS_OPER_MODE, "LECIM DSSS Operating Mode IE"},
1088 { IEEE802154_MLME_SUBIE_FSK_OPER_MODE, "LECIM FSK Operating Mode IE" },
1089 { IEEE802154_MLME_SUBIE_TVWS_PHY_OPE_MODE, "TVWS PHY Operating Mode Description IE" },
1090 { IEEE802154_MLME_SUBIE_TVWS_DEVICE_CAPAB, "TVWS Device Capabilities IE" },
1091 { IEEE802154_MLME_SUBIE_TVWS_DEVICE_CATEG, "TVWS Device Category IE" },
1092 { IEEE802154_MLME_SUBIE_TVWS_DEVICE_IDENTIF, "TVWS Device Identification IE" },
1093 { IEEE802154_MLME_SUBIE_TVWS_DEVICE_LOCATION, "TVWS Device Location IE" },
1094 { IEEE802154_MLME_SUBIE_TVWS_CH_INFOR_QUERY, "TVWS Channel Information Query IE" },
1095 { IEEE802154_MLME_SUBIE_TVWS_CH_INFOR_SOURCE, "TVWS Channel Information Source IE" },
1096 { IEEE802154_MLME_SUBIE_CTM, "CTM IE" },
1097 { IEEE802154_MLME_SUBIE_TIMESTAMP, "Timestamp IE" },
1098 { IEEE802154_MLME_SUBIE_TIMESTAMP_DIFF, "Timestamp Difference IE"},
1099 { IEEE802154_MLME_SUBIE_TMCP_SPECIFICATION, "TMCTP Specification IE" },
1100 { IEEE802154_MLME_SUBIE_RCC_PHY_OPER_MODE, "RCC PHY Operating Mode IE" },
1101 { IEEE802154_IETF_SUBIE_6TOP, "6top IE" },
1102 { IEEE802154_IETF_SUBIE_6TOP_DRAFT, "6top IE (draft)" },
1103 { 0, NULL }
1106 const value_string zboss_page_names[] = {
1107 { 0, "2.4 GHz" },
1108 { 28, "863-868 MHz band"},
1109 { 29, "868-870, 870-876 MHz band" },
1110 { 30, "870-876 MHz band" },
1111 { 31, "915-921 MHz band" },
1112 { 0, NULL }
1115 static const value_string zboss_direction_names[] = {
1116 { 0, "IN" },
1117 { 1, "OUT" },
1118 { 0, NULL }
1121 static const value_string tap_tlv_types[] = {
1122 { IEEE802154_TAP_FCS_TYPE, "FCS type"},
1123 { IEEE802154_TAP_RSS, "RSS"},
1124 { IEEE802154_TAP_BIT_RATE, "Bit rate"},
1125 { IEEE802154_TAP_CHANNEL_ASSIGNMENT, "Channel assignment"},
1126 { IEEE802154_TAP_SUN_PHY_INFO, "SUN PHY Information"},
1127 { IEEE802154_TAP_START_OF_FRAME_TS, "Start of frame timestamp"},
1128 { IEEE802154_TAP_END_OF_FRAME_TS, "End of frame timestamp"},
1129 { IEEE802154_TAP_ASN, "Absolute Slot Number (ASN)"},
1130 { IEEE802154_TAP_SLOT_START_TS, "Start of slot timestamp"},
1131 { IEEE802154_TAP_TIMESLOT_LENGTH, "Slot length"},
1132 { IEEE802154_TAP_LQI, "Link Quality Indicator"},
1133 { IEEE802154_TAP_CHANNEL_FREQUENCY, "Channel center frequency"},
1134 { IEEE802154_TAP_CHANNEL_PLAN, "Channel plan"},
1135 { IEEE802154_TAP_PHY_HEADER, "PHY Header"},
1136 { 0, NULL }
1139 static const value_string tap_fcs_type_names[] = {
1140 { IEEE802154_FCS_TYPE_NONE, "None" },
1141 { IEEE802154_FCS_TYPE_16_BIT, "ITU-T CRC16" },
1142 { IEEE802154_FCS_TYPE_32_BIT, "ITU-T CRC32" },
1143 { 0, NULL }
1146 /* IEEE 802.15.4 Table 7-19 */
1147 static const value_string sun_bands[] = {
1148 { 0, "169 MHz [169.400-169.475]" },
1149 { 1, "450 MHz [450-470]" },
1150 { 2, "470 MHz [470-510]" },
1151 { 3, "780 MHz [779-787]" },
1152 { 4, "863 MHz [863-870]" },
1153 { 5, "896 MHz [896-901]" },
1154 { 6, "901 MHz [901-902]" },
1155 { 7, "915 MHz [902-928]" },
1156 { 8, "917 MHz [917-923.5]" },
1157 { 9, "920 MHz [920-928]" },
1158 { 10, "928 MHz [928-960]" },
1159 { 11, "920 MHz [920-960]" },
1160 { 12, "1427 MHz [1427-1518]" },
1161 { 13, "2450 MHz [2400-2483.5]" },
1162 { 14, "866 MHz [865-867]" },
1163 { 15, "870 MHz [870-876]" },
1164 { 16, "915 MHz-a [902-928 alternate]" },
1165 { 17, "915 MHz-b [902-907.5 & 915-928]" },
1166 { 18, "915 MHz-c [915-928]" },
1167 { 19, "915 MHz-d [915-921]" },
1168 { 20, "915 MHz-e [915-918]" },
1169 { 21, "919 MHz [919-923]" },
1170 { 22, "920 MHz-a [920.5-924.5]" },
1171 { 23, "920 MHz-b [920-925]" },
1172 { 24, "867 MHz [866-869]" },
1173 /* Exegin defined numbers for bands in Table 10-1 but not in Table 7-19 */
1174 { 32, "433 MHz [433.05-434.79]" },
1175 { 33, "868 MHz [868-868.6]" },
1176 { 34, "2380 MHz [2360-2400]" },
1177 { 0, NULL }
1180 /* IEEE 802.15.4 Table 7-20 */
1181 static const value_string sun_types[] = {
1182 { IEEE802154_SUN_TYPE_FSK_A, "FSK-A" },
1183 { IEEE802154_SUN_TYPE_FSK_B, "FSK-B" },
1184 { IEEE802154_SUN_TYPE_OQPSK_A, "O-QPSK-A" },
1185 { IEEE802154_SUN_TYPE_OQPSK_B, "O-QPSK-B" },
1186 { IEEE802154_SUN_TYPE_OQPSK_C, "O-QPSK-C" },
1187 { IEEE802154_SUN_TYPE_OFDM_OPT1, "OFDM Option 1" },
1188 { IEEE802154_SUN_TYPE_OFDM_OPT2, "OFDM Option 2" },
1189 { IEEE802154_SUN_TYPE_OFDM_OPT3, "OFDM Option 3" },
1190 { IEEE802154_SUN_TYPE_OFDM_OPT4, "OFDM Option 4" },
1191 { 0, NULL }
1194 static const value_string fsk_a_modes[] = {
1195 { 0, "4.8 kb/s; 2-FSK; mod index = 1.0; channel spacing = 12.5 kHz" },
1196 { 1, "9.6 kb/s; 4-FSK; mod index = 0.33; channel spacing = 12.5 kHz" },
1197 { 2, "10 kb/s; 2-FSK; mod index = 0.5; channel spacing = 12.5 kHz" },
1198 { 3, "20 kb/s; 2-FSK; mod index = 0.5; channel spacing = 12.5 kHz" },
1199 { 4, "40 kb/s; 2-FSK; mod index = 0.5; channel spacing = 12.5 kHz" },
1200 { 5, "4.8 kb/s; 2-FSK; mod index = 0.5; channel spacing = 12.5 kHz" },
1201 { 6, "2.4 kb/s; 2-FSK; mod index = 2.0; channel spacing = 12.5 kHz" },
1202 { 7, "9.6 kb/s; 4-FSK; mod index = 0.33; channel spacing = 12.5 kHz" },
1203 { 0, NULL }
1206 static const value_string fsk_b_modes[] = {
1207 { 0, "50 kb/s; 2-FSK; mod index = 1.0; channel spacing = 200 kHz" },
1208 { 1, "100 kb/s; 2-FSK; mod index = 1.0; channel spacing = 400 kHz" },
1209 { 2, "150 kb/s; 2-FSK; mod index = 0.5; channel spacing = 400 kHz" },
1210 { 3, "200 kb/s; 2-FSK; mod index = 0.5; channel spacing = 400 kHz" },
1211 { 4, "200 kb/s; 4-FSK; mod index = 0.33; channel spacing = 400 kHz" },
1212 { 5, "200 kb/s; 2-FSK; mod index = 1.0; channel spacing = 600 kHz" },
1213 { 6, "400 kb/s; 4-FSK; mod index = 0.33; channel spacing = 600 kHz" },
1214 { 7, "100 kb/s; 2-FSK; mod index = 0.5; channel spacing = 200 kHz"},
1215 { 8, "50 kb/s; 2-FSK; mod index = 0.5; channel spacing = 100 kHz"},
1216 { 9, "150 kb/s; 2-FSK; mod index = 0.5; channel spacing = 200 kHz"},
1217 { 10, "300 kb/s; 2-FSK; mod index = 0.5; channel spacing = 400 kHz" },
1218 { 0, NULL }
1221 static const value_string oqpsk_a_modes[] = {
1222 { 0, "chip rate = 100 kchip/s; SpreadingMode = DSSS; RateMode = 0; data rate = 6.25 kb/s"},
1223 { 1, "chip rate = 100 kchip/s; SpreadingMode = DSSS; RateMode = 1; data rate = 12.5 kb/s"},
1224 { 2, "chip rate = 100 kchip/s; SpreadingMode = DSSS; RateMode = 2; data rate = 25 kb/s"},
1225 { 3, "chip rate = 100 kchip/s; SpreadingMode = DSSS; RateMode = 3; data rate = 50 kb/s"},
1226 { 0, NULL }
1229 static const value_string oqpsk_b_modes[] = {
1230 { 0, "chip rate = 1000 kchip/s; SpreadingMode = DSSS; RateMode = 0; data rate = 31.25 kb/s"},
1231 { 1, "chip rate = 1000 kchip/s; SpreadingMode = DSSS; RateMode = 1; data rate = 125 kb/s"},
1232 { 2, "chip rate = 1000 kchip/s; SpreadingMode = DSSS; RateMode = 2; data rate = 250 kb/s"},
1233 { 3, "chip rate = 1000 kchip/s; SpreadingMode = DSSS; RateMode = 3; data rate = 500 kb/s"},
1234 { 4, "chip rate = 1000 kchip/s; SpreadingMode = MDSSS; RateMode = 0; data rate = 62.5 kb/s"},
1235 { 5, "chip rate = 1000 kchip/s; SpreadingMode = MDSSS; RateMode = 1; data rate = 125 kb/s"},
1236 { 6, "chip rate = 1000 kchip/s; SpreadingMode = MDSSS; RateMode = 2; data rate = 250 kb/s"},
1237 { 7, "chip rate = 1000 kchip/s; SpreadingMode = MDSSS; RateMode = 3; data rate = 500 kb/s"},
1238 { 0, NULL }
1241 static const value_string oqpsk_c_modes[] = {
1242 { 0, "chip rate = 2000 kchip/s; SpreadingMode = DSSS; RateMode = 0; data rate = 31.25 kb/s"},
1243 { 1, "chip rate = 2000 kchip/s; SpreadingMode = DSSS; RateMode = 1; data rate = 125 kb/s"},
1244 { 2, "chip rate = 2000 kchip/s; SpreadingMode = DSSS; RateMode = 2; data rate = 250 kb/s"},
1245 { 3, "chip rate = 2000 kchip/s; SpreadingMode = DSSS; RateMode = 3; data rate = 500 kb/s"},
1246 { 4, "chip rate = 2000 kchip/s; SpreadingMode = MDSSS; RateMode = 0; data rate = 62.5 kb/s"},
1247 { 5, "chip rate = 2000 kchip/s; SpreadingMode = MDSSS; RateMode = 1; data rate = 125 kb/s"},
1248 { 6, "chip rate = 2000 kchip/s; SpreadingMode = MDSSS; RateMode = 2; data rate = 250 kb/s"},
1249 { 7, "chip rate = 2000 kchip/s; SpreadingMode = MDSSS; RateMode = 3; data rate = 500 kb/s"},
1250 { 0, NULL }
1253 static const value_string ofdm_modes[] = {
1254 { 0, "MCS0" },
1255 { 1, "MCS1" },
1256 { 2, "MCS2" },
1257 { 3, "MCS3" },
1258 { 4, "MCS4" },
1259 { 5, "MCS5" },
1260 { 6, "MCS6" },
1261 { 0, NULL },
1264 static const value_string channel_page_names[] = {
1265 { 0, "Default" },
1266 { 1, "ASK" },
1267 { 2, "O-QPSK" },
1268 { 3, "CSS" },
1269 { 4, "HRP UWB" },
1270 { 5, "780 MHz" },
1271 { 6, "GFSK" },
1272 { 7, "MSK" },
1273 { 8, "LRP_UWB" },
1274 { 9, "SUN" },
1275 { 10, "SUN FSK" },
1276 { 11, "2380 MHz" },
1277 { 12, "LECIM" },
1278 { 13, "RCC" },
1279 { 0, NULL }
1282 static const value_string ietf_6top_types[] = {
1283 { IETF_6TOP_TYPE_REQUEST, "Request" },
1284 { IETF_6TOP_TYPE_RESPONSE, "Response" },
1285 { IETF_6TOP_TYPE_CONFIRMATION, "Confirmation" },
1286 { 0, NULL }
1289 static const value_string ietf_6top_command_identifiers[] = {
1290 { IETF_6TOP_CMD_ADD, "ADD" },
1291 { IETF_6TOP_CMD_DELETE, "DELETE" },
1292 { IETF_6TOP_CMD_RELOCATE, "RELOCATE" },
1293 { IETF_6TOP_CMD_COUNT, "COUNT" },
1294 { IETF_6TOP_CMD_LIST, "LIST" },
1295 { IETF_6TOP_CMD_SIGNAL, "SIGNAL" },
1296 { IETF_6TOP_CMD_CLEAR, "CLEAR" },
1297 { 0, NULL }
1300 static const value_string ietf_6top_return_codes[] = {
1301 { IETF_6TOP_RC_SUCCESS, "SUCCESS" },
1302 { IETF_6TOP_RC_EOL, "RC_EOL" },
1303 { IETF_6TOP_RC_ERR, "RC_ERR" },
1304 { IETF_6TOP_RC_RESET, "RC_RESET" },
1305 { IETF_6TOP_RC_ERR_VERSION, "RC_ERR_VERSION" },
1306 { IETF_6TOP_RC_ERR_SFID, "RC_ERR_SFID" },
1307 { IETF_6TOP_RC_ERR_SEQNUM, "RC_ERR_SEQNUM" },
1308 { IETF_6TOP_RC_ERR_CELLLIST, "RC_ERR_CELLLIST" },
1309 { IETF_6TOP_RC_ERR_BUSY, "RC_ERR_BUSY" },
1310 { IETF_6TOP_RC_ERR_LOCKED, "RC_ERR_LOCKED" },
1311 { 0, NULL }
1314 static const value_string ietf_6top_cell_options[] = {
1315 { 0, "ALL" },
1316 { 1, "TX" },
1317 { 2, "RX" },
1318 { 3, "TX|RX" },
1319 { 4, "SHARED" },
1320 { 5, "TX|SHARED" },
1321 { 6, "RX|SHARED" },
1322 { 7, "TX|RX|SHARED" },
1323 { 0, NULL}
1326 static const value_string mpx_transfer_type_vals[] = {
1327 { IEEE802159_MPX_FULL_FRAME, "Full Frame" },
1328 { IEEE802159_MPX_FULL_FRAME_NO_MUXID, "Full frame with compressed Multiplex ID" },
1329 { IEEE802159_MPX_NON_LAST_FRAGMENT, "Non-last Fragment" },
1330 { IEEE802159_MPX_LAST_FRAGMENT, "Last Fragment" },
1331 { IEEE802159_MPX_ABORT, "Abort" },
1332 { 0, NULL }
1335 static const value_string mpx_multiplex_id_vals[] = {
1336 { IEEE802159_MPX_MULTIPLEX_ID_KMP, "KMP" },
1337 { IEEE802159_MPX_MULTIPLEX_ID_WISUN, "Wi-SUN" },
1338 { 0, NULL }
1341 // used by the Wi-SUN dissector
1342 const value_string ieee802154_mpx_kmp_id_vals[] = {
1343 { IEEE802159_MPX_KMP_ID_IEEE8021X, "IEEE 802.1X/MKA" },
1344 { IEEE802159_MPX_KMP_ID_HIP, "HIP" },
1345 { IEEE802159_MPX_KMP_ID_IKEV2, "IKEv2" },
1346 { IEEE802159_MPX_KMP_ID_PANA, "PANA" },
1347 { IEEE802159_MPX_KMP_ID_DRAGONFLY, "Dragonfly" },
1348 { IEEE802159_MPX_KMP_ID_IEEE80211_4WH, "IEEE 802.11/4WH" },
1349 { IEEE802159_MPX_KMP_ID_IEEE80211_GKH, "IEEE 802.11/GKH" },
1350 { IEEE802159_MPX_KMP_ID_ETSI_TS_102_887_2, "ETSI TS 102 887-2" },
1351 { IEEE802159_MPX_KMP_ID_VENDOR_SPECIFIC, "Vendor-specific" },
1352 { 0, NULL }
1355 static const value_string mpx_wisun_subid_vals[] = {
1356 { IEEE802159_MPX_WISUN_SUBID_MHDS, "WM-MHDS" },
1357 { IEEE802159_MPX_WISUN_SUBID_6LOWPAN, "WM-6LO" },
1358 { IEEE802159_MPX_WISUN_SUBID_SECURITY, "WM-SEC" },
1359 { 0, NULL }
1362 static const value_string ieee802154_phr_type_vals[] = {
1363 { PHR_RAW , "RAW" },
1364 { PHR_O_QPSK , "O-QPSK" },
1365 { PHR_CSS , "CSS" },
1366 { PHR_HRP_UWB , "HRP UWB" },
1367 { PHR_MSK , "MSK" },
1368 { PHR_LRP_UWB , "LRP UWB" },
1369 { PHR_SUN_FSK , "SUN FSK" },
1370 { PHR_SUN_OFDM , "SUN OFDM" },
1371 { PHR_SUN_O_QPSK , "SUN O-QPSK" },
1372 { PHR_LECIM_FSK , "LECIM FSK" },
1373 { PHR_TVWS_FSK , "TVWS FSK" },
1374 { PHR_TVWS_OFDM , "TVWS OFDM" },
1375 { PHR_TVWS_NB_OFDM , "TVWS-NB OFDM" },
1376 { PHR_RCC_LMR , "RCC LMR" },
1377 { PHR_CMB_O_QPSK , "CMB O-QPSK" },
1378 { PHR_CMB_GFSK , "CMB GFSK" },
1379 { PHR_TASK , "TASK" },
1380 { PHR_RS_GFSK , "RS GFSK" },
1381 { PHR_WISUN_FSK_MS , "Wi-SUN FSK MS" },
1382 { 0, NULL }
1385 /* SUN FSK PHR fields - IEEE 802.15.4-2020 19.2.4 */
1386 static const true_false_string tfs_fcs_type = { "2-octet FCS", "4-octet FCS" };
1387 static const value_string vals_fsk_ms_page[] = {
1388 {0, "9"},
1389 {1, "10"},
1390 {0, NULL}
1393 static const value_string ieee802154_phr_fsk_ms_scheme[] = {
1394 { 0, "SUN FSK" },
1395 { 1, "SUN OFDM" },
1396 { 2, "SUN O-QPSK" },
1397 { 3, "Additional" },
1398 { 0, NULL }
1401 static const value_string ieee802154_phr_fsk_ms_mode[] = {
1402 { 1, "SUN FSK operating mode #1" },
1403 { 2, "SUN FSK operating mode #2" },
1404 { 4, "SUN FSK operating mode #3" },
1405 { 8, "SUN FSK operating mode #4" },
1406 { 0, NULL }
1409 static const value_string ieee802154_phr_fsk_ms_additional_modes[] = {
1410 { 0, "SUN FSK operating mode #5" },
1411 { 1, "SUN FSK operating mode #1a" },
1412 { 2, "SUN FSK operating mode #1b" },
1413 { 0, NULL }
1416 /* Wi-SUN phyModeID - Wi-SUN PHY Specification Revision 1v09 Annex F PHY Operating Mode */
1417 static const value_string ieee802154_phr_wisun_phymodeid[] = {
1418 { 1, "FSK #1a 50ksym/s mod-index 0.5" },
1419 { 2, "FSK #1b 50ksym/s mod-index 1.0" },
1420 { 3, "FSK #2a 100ksym/s mod-index 0.5" },
1421 { 4, "FSK #2b 100ksym/s mod-index 1.0" },
1422 { 5, "FSK #3 150ksym/s mod-index 0.5" },
1423 { 6, "FSK #4a 200ksym/s mod-index 0.5" },
1424 { 7, "FSK #4b 200ksym/s mod-index 1.0" },
1425 { 8, "FSK #5 300ksym/s mod-index 0.5" },
1426 { 17, "FSK with FEC #1a 50ksym/s mod-index 0.5" },
1427 { 18, "FSK with FEC #1b 50ksym/s mod-index 1.0" },
1428 { 19, "FSK with FEC #2a 100ksym/s mod-index 0.5" },
1429 { 20, "FSK with FEC #2b 100ksym/s mod-index 1.0" },
1430 { 21, "FSK with FEC #3 150ksym/s mod-index 0.5" },
1431 { 22, "FSK with FEC #4a 200ksym/s mod-index 0.5" },
1432 { 23, "FSK with FEC #4b 200ksym/s mod-index 1.0" },
1433 { 24, "FSK with FEC #5 300ksym/s mod-index 0.5" },
1434 { 34, "OFDM Option 1 MCS 2 400kbps" },
1435 { 35, "OFDM Option 1 MCS 3 800kbps" },
1436 { 36, "OFDM Option 1 MCS 4 1200kbps" },
1437 { 37, "OFDM Option 1 MCS 5 1600kbps" },
1438 { 38, "OFDM Option 1 MCS 6 2400kbps" },
1439 { 51, "OFDM Option 2 MCS 3 400kbps" },
1440 { 52, "OFDM Option 2 MCS 4 600kbps" },
1441 { 53, "OFDM Option 2 MCS 5 800kbps" },
1442 { 54, "OFDM Option 2 MCS 6 1200kbps" },
1443 { 68, "OFDM Option 3 MCS 4 300kbps" },
1444 { 69, "OFDM Option 3 MCS 5 400kbps" },
1445 { 70, "OFDM Option 3 MCS 6 600kbps" },
1446 { 84, "OFDM Option 4 MCS 4 150kbps" },
1447 { 85, "OFDM Option 4 MCS 5 200kbps" },
1448 { 86, "OFDM Option 4 MCS 6 300kbps" },
1449 { 0, NULL }
1452 /* Preferences for 2003 security */
1453 static int ieee802154_sec_suite = SECURITY_LEVEL_ENC_MIC_64;
1454 static bool ieee802154_extend_auth = true;
1456 /* Macro to check addressing, and throw a warning flag if incorrect. */
1457 #define IEEE802154_CMD_ADDR_CHECK(_pinfo_, _item_, _cmdid_, _x_) \
1458 if (!(_x_)) \
1459 expert_add_info_format(_pinfo_, _item_, &ei_ieee802154_invalid_addressing, \
1460 "Invalid Addressing for %s", \
1461 val_to_str_const(_cmdid_, ieee802154_cmd_names, "Unknown Command"))
1463 /* CRC definitions. IEEE 802.15.4 CRCs vary from ITU-T by using an initial value of
1464 * 0x0000, and no XOR out. IEEE802154_CRC_XOR is defined as 0xFFFF in order to un-XOR
1465 * the output from the ITU-T (CCITT) CRC routines in Wireshark.
1467 #define IEEE802154_CRC_SEED 0x0000
1468 #define IEEE802154_CRC_XOROUT 0xFFFF
1469 #define ieee802154_crc_tvb(tvb, offset) (crc16_ccitt_tvb_seed(tvb, offset, IEEE802154_CRC_SEED) ^ IEEE802154_CRC_XOROUT)
1471 /* For the 32-bit CRC, IEEE 802.15.4 uses ITU-T (CCITT) CRC-32. */
1472 #define ieee802154_crc32_tvb(tvb, offset) (crc32_ccitt_tvb(tvb, offset))
1474 static int ieee802_15_4_short_address_to_str(const address* addr, char *buf, int buf_len)
1476 uint16_t ieee_802_15_4_short_addr = pletoh16(addr->data);
1478 if (ieee_802_15_4_short_addr == 0xffff)
1480 (void) g_strlcpy(buf, "Broadcast", buf_len);
1481 return 10;
1484 *buf++ = '0';
1485 *buf++ = 'x';
1486 buf = word_to_hex(buf, ieee_802_15_4_short_addr);
1487 *buf = '\0'; /* NULL terminate */
1489 return 7;
1492 static int ieee802_15_4_short_address_str_len(const address* addr _U_)
1494 return 11;
1497 static int ieee802_15_4_short_address_len(void)
1499 return 2;
1502 /* ======================================================================= */
1503 static conversation_t *_find_or_create_conversation(packet_info *pinfo, const address *src_addr, const address *dst_addr)
1505 conversation_t *conv = NULL;
1507 /* Have we seen this conversation before? */
1508 conv = find_conversation(pinfo->num, src_addr, dst_addr, CONVERSATION_NONE, 0, 0, 0);
1509 if (conv == NULL) {
1510 /* No, this is a new conversation. */
1511 conv = conversation_new(pinfo->num, src_addr, dst_addr, CONVERSATION_NONE, 0, 0, 0);
1513 return conv;
1516 /* ======================================================================= */
1517 static ieee802154_transaction_t *transaction_start(packet_info *pinfo, proto_tree *tree, const ieee802154_packet *packet, uint32_t *key)
1519 ieee802154_transaction_t *ieee802154_trans;
1520 wmem_tree_key_t ieee802154_key[3];
1521 proto_item *it;
1523 if (!PINFO_FD_VISITED(pinfo)) {
1525 * This is a new request, create a new transaction structure and map it
1526 * to the unmatched table.
1528 ieee802154_key[0].length = 2;
1529 ieee802154_key[0].key = key;
1530 ieee802154_key[1].length = 0;
1531 ieee802154_key[1].key = NULL;
1533 ieee802154_trans = wmem_new0(wmem_file_scope(), ieee802154_transaction_t);
1535 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT)
1536 ieee802154_trans->dst16 = packet->dst16;
1537 else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)
1538 ieee802154_trans->dst64 = packet->dst64;
1539 ieee802154_trans->dst_addr_mode = packet->dst_addr_mode;
1541 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT)
1542 ieee802154_trans->src16 = packet->src16;
1543 else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT)
1544 ieee802154_trans->src64 = packet->src64;
1545 ieee802154_trans->src_addr_mode = packet->src_addr_mode;
1547 if (packet->dst_pan_present) {
1548 ieee802154_trans->dst_pan_present = true;
1549 ieee802154_trans->dst_pan = packet->dst_pan;
1551 if (packet->src_pan_present) {
1552 ieee802154_trans->src_pan_present = true;
1553 ieee802154_trans->src_pan = packet->src_pan;
1555 ieee802154_trans->rqst_frame = pinfo->num;
1556 ieee802154_trans->ack_frame = 0;
1557 ieee802154_trans->rqst_time = pinfo->abs_ts;
1558 nstime_set_unset(&ieee802154_trans->ack_time);
1559 wmem_tree_insert32_array(transaction_unmatched_pdus, ieee802154_key, (void *)ieee802154_trans);
1560 } else {
1561 /* Already visited this frame */
1562 uint32_t frame_num = pinfo->num;
1564 ieee802154_key[0].length = 2;
1565 ieee802154_key[0].key = key;
1566 ieee802154_key[1].length = 1;
1567 ieee802154_key[1].key = &frame_num;
1568 ieee802154_key[2].length = 0;
1569 ieee802154_key[2].key = NULL;
1571 ieee802154_trans = (ieee802154_transaction_t *)wmem_tree_lookup32_array(transaction_matched_pdus, ieee802154_key);
1573 if (!ieee802154_trans) {
1574 /* No ACK found - add field and expert info */
1575 it = proto_tree_add_item(tree, hf_ieee802154_no_ack, NULL, 0, 0, ENC_NA);
1576 proto_item_set_generated(it);
1578 expert_add_info_format(pinfo, it, &ei_ieee802154_ack_not_found, "No ack found to request in frame %u", pinfo->num);
1580 return NULL;
1584 /* Print state tracking in the tree */
1585 if (ieee802154_trans->ack_frame) {
1586 it = proto_tree_add_uint(tree, hf_ieee802154_ack_in, NULL, 0, 0, ieee802154_trans->ack_frame);
1587 proto_item_set_generated(it);
1590 return ieee802154_trans;
1591 } /* transaction_start() */
1593 static ieee802154_transaction_t *transaction_end(packet_info *pinfo, proto_tree *tree, const ieee802154_packet *packet, uint32_t *key)
1595 ieee802154_transaction_t *ieee802154_trans = NULL;
1596 wmem_tree_key_t ieee802154_key[3];
1597 proto_item *it;
1599 if (!PINFO_FD_VISITED(pinfo)) {
1600 uint32_t frame_num;
1601 nstime_t ns;
1603 ieee802154_key[0].length = 2;
1604 ieee802154_key[0].key = key;
1605 ieee802154_key[1].length = 0;
1606 ieee802154_key[1].key = NULL;
1608 ieee802154_trans = (ieee802154_transaction_t *)wmem_tree_lookup32_array(transaction_unmatched_pdus, ieee802154_key);
1609 if (ieee802154_trans == NULL)
1610 return NULL;
1612 /* we have already seen this response, or an identical one */
1613 if (ieee802154_trans->ack_frame != 0)
1614 return NULL;
1616 /* If addresses are present they must match */
1617 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1618 if (packet->src16 != ieee802154_trans->dst16)
1619 return NULL;
1621 else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1622 if (packet->src64 != ieee802154_trans->dst64)
1623 return NULL;
1625 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1626 if (packet->dst16 != ieee802154_trans->src16)
1627 return NULL;
1629 else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1630 if (packet->dst64 != ieee802154_trans->src64)
1631 return NULL;
1634 nstime_delta(&ns, &pinfo->abs_ts, &ieee802154_trans->rqst_time);
1635 if (nstime_cmp(&ns, &ieee802154_transaction_timeout) > 0)
1636 return NULL;
1638 ieee802154_trans->ack_time = ns;
1639 ieee802154_trans->ack_frame = pinfo->num;
1642 * We found a match. Add entries to the matched table for both
1643 * request and ack frames
1645 ieee802154_key[0].length = 2;
1646 ieee802154_key[0].key = key;
1647 ieee802154_key[1].length = 1;
1648 ieee802154_key[1].key = &frame_num;
1649 ieee802154_key[2].length = 0;
1650 ieee802154_key[2].key = NULL;
1652 frame_num = ieee802154_trans->rqst_frame;
1653 wmem_tree_insert32_array(transaction_matched_pdus, ieee802154_key, (void *)ieee802154_trans);
1655 frame_num = ieee802154_trans->ack_frame;
1656 wmem_tree_insert32_array(transaction_matched_pdus, ieee802154_key, (void *)ieee802154_trans);
1657 } else {
1658 /* Already visited this frame */
1659 uint32_t frame_num = pinfo->num;
1661 ieee802154_key[0].length = 2;
1662 ieee802154_key[0].key = key;
1663 ieee802154_key[1].length = 1;
1664 ieee802154_key[1].key = &frame_num;
1665 ieee802154_key[2].length = 0;
1666 ieee802154_key[2].key = NULL;
1668 ieee802154_trans = (ieee802154_transaction_t *)wmem_tree_lookup32_array(transaction_matched_pdus, ieee802154_key);
1670 if (!ieee802154_trans) {
1671 /* No ack request found - add field and expert info */
1672 it = proto_tree_add_item(tree, hf_ieee802154_no_ack_request, NULL, 0, 0, ENC_NA);
1673 proto_item_set_generated(it);
1675 expert_add_info_format(pinfo, it, &ei_ieee802154_ack_request_not_found, "No request found to ack in frame %u", pinfo->num);
1676 return NULL;
1680 if (packet->dst_pan_present == false) {
1681 if (ieee802154_trans->src_pan_present) {
1682 it = proto_tree_add_uint(tree, hf_ieee802154_dst_panID, NULL, 0, 0, ieee802154_trans->src_pan);
1683 proto_item_set_generated(it);
1685 else if (ieee802154_trans->dst_pan_present) {
1686 it = proto_tree_add_uint(tree, hf_ieee802154_dst_panID, NULL, 0, 0, ieee802154_trans->dst_pan);
1687 proto_item_set_generated(it);
1690 if ((packet->src_pan_present == false) && (ieee802154_trans->src_pan_present) && (ieee802154_trans->dst_pan_present)) {
1691 it = proto_tree_add_uint(tree, hf_ieee802154_src_panID, NULL, 0, 0, ieee802154_trans->dst_pan);
1692 proto_item_set_generated(it);
1695 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) {
1696 if (ieee802154_trans->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1697 it = proto_tree_add_uint(tree, hf_ieee802154_dst16, NULL, 0, 0, ieee802154_trans->src16);
1698 proto_item_set_generated(it);
1700 it = proto_tree_add_uint(tree, hf_ieee802154_addr16, NULL, 0, 0, ieee802154_trans->src16);
1701 proto_item_set_hidden(it);
1702 proto_item_set_generated(it);
1704 else if (ieee802154_trans->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1705 it = proto_tree_add_eui64(tree, hf_ieee802154_dst64, NULL, 0, 0, ieee802154_trans->src64);
1706 proto_item_set_generated(it);
1708 it = proto_tree_add_eui64(tree, hf_ieee802154_addr64, NULL, 0, 0, ieee802154_trans->src64);
1709 proto_item_set_hidden(it);
1710 proto_item_set_generated(it);
1714 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) {
1715 if (ieee802154_trans->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1716 it = proto_tree_add_uint(tree, hf_ieee802154_src16, NULL, 0, 0, ieee802154_trans->dst16);
1717 proto_item_set_generated(it);
1719 it = proto_tree_add_uint(tree, hf_ieee802154_addr16, NULL, 0, 0, ieee802154_trans->dst16);
1720 proto_item_set_hidden(it);
1721 proto_item_set_generated(it);
1723 else if (ieee802154_trans->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1724 it = proto_tree_add_eui64(tree, hf_ieee802154_src64, NULL, 0, 0, ieee802154_trans->dst64);
1725 proto_item_set_generated(it);
1727 it = proto_tree_add_eui64(tree, hf_ieee802154_addr64, NULL, 0, 0, ieee802154_trans->dst64);
1728 proto_item_set_hidden(it);
1729 proto_item_set_generated(it);
1733 /* Print state tracking in the tree */
1734 it = proto_tree_add_uint(tree, hf_ieee802154_ack_to, NULL, 0, 0, ieee802154_trans->rqst_frame);
1735 proto_item_set_generated(it);
1737 it = proto_tree_add_time(tree, hf_ieee802154_ack_time, NULL, 0, 0, &ieee802154_trans->ack_time);
1738 proto_item_set_generated(it);
1740 return ieee802154_trans;
1742 } /* transaction_end() */
1745 * Dissector helper, parses and displays the frame control field.
1747 * @param tvb pointer to buffer containing raw packet.
1748 * @param pinfo pointer to packet information fields
1749 * @param tree pointer to data tree wireshark uses to display packet.
1750 * @param packet IEEE 802.15.4 packet information.
1751 * @param offset offset into the tvb to find the FCF.
1754 static void
1755 dissect_ieee802154_fcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet, unsigned *offset)
1757 uint16_t fcf;
1758 static int * const ieee802154_fields[] = {
1759 &hf_ieee802154_frame_type,
1760 &hf_ieee802154_security,
1761 &hf_ieee802154_pending,
1762 &hf_ieee802154_ack_request,
1763 &hf_ieee802154_pan_id_compression,
1764 &hf_ieee802154_fcf_reserved,
1765 &hf_ieee802154_seqno_suppression,
1766 &hf_ieee802154_ie_present,
1767 &hf_ieee802154_dst_addr_mode,
1768 &hf_ieee802154_version,
1769 &hf_ieee802154_src_addr_mode,
1770 NULL
1773 static int* const ieee802154_mpf_short_fields[] = {
1774 &hf_ieee802154_frame_type,
1775 &hf_ieee802154_mpf_long_frame_control,
1776 &hf_ieee802154_mpf_dst_addr_mode,
1777 &hf_ieee802154_mpf_src_addr_mode,
1778 NULL
1781 static int* const ieee802154_mpf_long_fields[] = {
1782 &hf_ieee802154_frame_type,
1783 &hf_ieee802154_mpf_long_frame_control,
1784 &hf_ieee802154_mpf_dst_addr_mode,
1785 &hf_ieee802154_mpf_src_addr_mode,
1786 &hf_ieee802154_mpf_pan_id_present,
1787 &hf_ieee802154_mpf_security,
1788 &hf_ieee802154_mpf_seqno_suppression,
1789 &hf_ieee802154_mpf_pending,
1790 &hf_ieee802154_mpf_version,
1791 &hf_ieee802154_mpf_ack_request,
1792 &hf_ieee802154_mpf_ie_present,
1793 NULL
1796 /* Get the FCF field. */
1797 fcf = tvb_get_letohs(tvb, *offset);
1799 /* Parse FCF Flags. */
1800 packet->frame_type = (fcf & IEEE802154_FCF_TYPE_MASK);
1802 if (packet->frame_type == IEEE802154_FCF_MULTIPURPOSE) {
1803 /* Multipurpose frames use a different 1 or 2 byte FCF */
1804 packet->long_frame_control = (fcf & IEEE802154_MPF_FCF_LONG_FC) >> 3;
1805 packet->dst_addr_mode = (fcf & IEEE802154_MPF_FCF_DADDR_MASK) >> 4;
1806 packet->src_addr_mode = (fcf & IEEE802154_MPF_FCF_SADDR_MASK) >> 6;
1808 /* The second octet of the FCF is only present if the long frame control bit is set */
1809 if (packet->long_frame_control) {
1810 packet->pan_id_present = (fcf & IEEE802154_MPF_FCF_PAN_ID_PRESENT) >> 8;
1811 packet->security_enable = (fcf & IEEE802154_MPF_FCF_SEC_EN) >> 9;
1812 packet->seqno_suppression = (fcf & IEEE802154_MPF_FCF_SEQNO_SUPPRESSION) >> 10;
1813 packet->frame_pending = (fcf & IEEE802154_MPF_FCF_FRAME_PND) >> 11;
1814 packet->version = (fcf & IEEE802154_MPF_FCF_VERSION) >> 12;
1815 packet->ack_request = (fcf & IEEE802154_MPF_FCF_ACK_REQ) >> 14;
1816 packet->ie_present = (fcf & IEEE802154_MPF_FCF_IE_PRESENT) >> 15;
1818 else {
1819 packet->security_enable = false;
1820 packet->seqno_suppression = false;
1821 packet->frame_pending = false;
1822 packet->version = 0;
1823 packet->ack_request = false;
1824 packet->ie_present = false;
1827 if (ieee802154e_compatibility) {
1828 if (((tvb_reported_length(tvb) == IEEE802154E_LE_WUF_LEN)) && !packet->long_frame_control) {
1829 /* Check if this is an IEEE 802.15.4e LE-multipurpose Wake-up Frame, which has a single-octet FCF
1830 * and a static layout that cannot be inferred from the FCF alone. */
1831 uint16_t ie_header = tvb_get_letohs(tvb, (*offset) + 6);
1832 uint16_t id = (uint16_t)((ie_header & IEEE802154_HEADER_IE_ID_MASK) >> 7);
1833 uint16_t length = (uint16_t)(ie_header & IEEE802154_HEADER_IE_LENGTH_MASK);
1834 if ((id == IEEE802154_HEADER_IE_RENDEZVOUS) && (length == 2)) {
1835 /* This appears to be a WUF, as identified by containing a single
1836 * Rendezvous Time Header IE with only a rendezvous time. */
1837 packet->ie_present = true;
1838 packet->pan_id_present = true;
1843 else {
1844 /* Standard 802.15.4 FCF */
1845 packet->security_enable = (fcf & IEEE802154_FCF_SEC_EN) >> 3;
1846 packet->frame_pending = (fcf & IEEE802154_FCF_FRAME_PND) >> 4;
1847 packet->ack_request = (fcf & IEEE802154_FCF_ACK_REQ) >> 5;
1848 packet->pan_id_compression = (fcf & IEEE802154_FCF_PAN_ID_COMPRESSION) >> 6;
1849 /* bit 7 reserved */
1850 packet->seqno_suppression = (fcf & IEEE802154_FCF_SEQNO_SUPPRESSION) >> 8;
1851 packet->ie_present = (fcf & IEEE802154_FCF_IE_PRESENT) >> 9;
1852 packet->dst_addr_mode = (fcf & IEEE802154_FCF_DADDR_MASK) >> 10;
1853 packet->version = (fcf & IEEE802154_FCF_VERSION) >> 12;
1854 packet->src_addr_mode = (fcf & IEEE802154_FCF_SADDR_MASK) >> 14;
1857 if ((packet->version == IEEE802154_VERSION_2015) && (packet->frame_type == IEEE802154_FCF_BEACON)) {
1858 proto_item_append_text(tree, " Enhanced Beacon");
1859 col_set_str(pinfo->cinfo, COL_INFO, "Enhanced Beacon");
1861 else {
1862 proto_item_append_text(tree, " %s", val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
1863 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
1866 if (packet->frame_type == IEEE802154_FCF_MULTIPURPOSE) {
1867 if (packet->long_frame_control) {
1868 proto_tree_add_bitmask(tree, tvb, *offset, hf_ieee802154_fcf,
1869 ett_ieee802154_fcf, ieee802154_mpf_long_fields, ENC_LITTLE_ENDIAN);
1870 *offset += 2;
1872 else {
1873 proto_tree_add_bitmask_len(tree, tvb, *offset, 1, hf_ieee802154_fcf,
1874 ett_ieee802154_fcf, ieee802154_mpf_short_fields,
1875 &ei_ieee802154_fcs_bitmask_len, ENC_LITTLE_ENDIAN);
1876 *offset += 1;
1879 else {
1880 proto_tree_add_bitmask(tree, tvb, *offset, hf_ieee802154_fcf,
1881 ett_ieee802154_fcf, ieee802154_fields, ENC_LITTLE_ENDIAN);
1882 *offset += 2;
1885 } /* dissect_ieee802154_fcf */
1887 void register_ieee802154_mac_key_hash_handler(unsigned hash_identifier, ieee802154_set_key_func key_func)
1889 /* Ensure no duplication */
1890 DISSECTOR_ASSERT(wmem_tree_lookup32(mac_key_hash_handlers, hash_identifier) == NULL);
1892 wmem_tree_insert32(mac_key_hash_handlers, hash_identifier, (void*)key_func);
1895 void dissect_ieee802154_aux_sec_header_and_key(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, ieee802154_packet *packet, unsigned *offset)
1897 proto_tree *field_tree, *header_tree;
1898 proto_item *ti, *hidden_item;
1899 uint8_t security_control;
1900 unsigned aux_length = 1; /* Minimum length of the auxiliary header. */
1901 static int * const security_fields[] = {
1902 &hf_ieee802154_aux_sec_security_level,
1903 &hf_ieee802154_aux_sec_key_id_mode,
1904 &hf_ieee802154_aux_sec_frame_counter_suppression,
1905 &hf_ieee802154_aux_sec_asn_in_nonce,
1906 &hf_ieee802154_aux_sec_reserved,
1907 NULL
1910 /* Parse the security control field. */
1911 security_control = tvb_get_uint8(tvb, *offset);
1912 packet->security_level = (ieee802154_security_level)(security_control & IEEE802154_AUX_SEC_LEVEL_MASK);
1913 packet->key_id_mode = (ieee802154_key_id_mode)((security_control & IEEE802154_AUX_KEY_ID_MODE_MASK) >> IEEE802154_AUX_KEY_ID_MODE_SHIFT);
1914 if (packet->version == IEEE802154_VERSION_2015) {
1915 packet->frame_counter_suppression = security_control & IEEE802154_AUX_FRAME_COUNTER_SUPPRESSION_MASK ? true : false;
1918 /* Compute the length of the auxiliary header and create a subtree. */
1919 if (!packet->frame_counter_suppression) aux_length += 4;
1920 if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) aux_length++;
1921 if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) aux_length += 4;
1922 if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) aux_length += 8;
1924 ti = proto_tree_add_item(tree, hf_ieee802154_aux_security_header, tvb, *offset, aux_length, ENC_NA);
1925 header_tree = proto_item_add_subtree(ti, ett_ieee802154_auxiliary_security);
1927 /* Security Control Field */
1928 proto_tree_add_bitmask(header_tree, tvb, *offset, hf_ieee802154_aux_sec_security_control, ett_ieee802154_aux_sec_control, security_fields, ENC_NA);
1929 (*offset)++;
1931 /* Frame Counter Field */
1932 if (!packet->frame_counter_suppression) {
1933 proto_tree_add_item_ret_uint(header_tree, hf_ieee802154_aux_sec_frame_counter, tvb, *offset, 4, ENC_LITTLE_ENDIAN, &packet->frame_counter);
1934 (*offset) += 4;
1936 else {
1937 packet->asn = ieee802154_tsch_asn;
1940 /* Key identifier field(s). */
1941 if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) {
1942 /* Create a subtree. */
1943 field_tree = proto_tree_add_subtree(header_tree, tvb, *offset, 1,
1944 ett_ieee802154_aux_sec_key_id, &ti, "Key Identifier Field"); /* Will fix length later. */
1945 /* Add key source, if it exists. */
1946 if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) {
1947 packet->key_source.addr32 = tvb_get_ntohl(tvb, *offset);
1948 proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, *offset, 4, packet->key_source.addr32);
1949 hidden_item = proto_tree_add_item(field_tree, hf_ieee802154_aux_sec_key_source_bytes, tvb, *offset, 4, ENC_NA);
1950 proto_item_set_hidden(hidden_item);
1951 proto_item_set_len(ti, 1 + 4);
1952 (*offset) += 4;
1954 if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) {
1955 packet->key_source.addr64 = tvb_get_ntoh64(tvb, *offset);
1956 proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, *offset, 8, packet->key_source.addr64);
1957 hidden_item = proto_tree_add_item(field_tree, hf_ieee802154_aux_sec_key_source_bytes, tvb, *offset, 8, ENC_NA);
1958 proto_item_set_hidden(hidden_item);
1959 proto_item_set_len(ti, 1 + 8);
1960 (*offset) += 8;
1962 /* Add key identifier. */
1963 packet->key_index = tvb_get_uint8(tvb, *offset);
1964 proto_tree_add_uint(field_tree, hf_ieee802154_aux_sec_key_index, tvb, *offset, 1, packet->key_index);
1965 (*offset)++;
1969 tvbuff_t *decrypt_ieee802154_payload(tvbuff_t * tvb, unsigned offset, packet_info * pinfo, proto_tree* key_tree,
1970 ieee802154_packet * packet, ieee802154_decrypt_info_t* decrypt_info,
1971 ieee802154_set_key_func set_key_func, ieee802154_decrypt_func decrypt_func)
1973 proto_item* ti;
1974 unsigned char key[IEEE802154_CIPHER_SIZE];
1975 unsigned char alt_key[IEEE802154_CIPHER_SIZE];
1976 tvbuff_t * payload_tvb = NULL;
1978 /* Lookup the key. */
1979 for (decrypt_info->key_number = 0; decrypt_info->key_number < num_ieee802154_keys; decrypt_info->key_number++) {
1980 unsigned nkeys = set_key_func(packet, key, alt_key, &ieee802154_keys[decrypt_info->key_number]);
1981 if (nkeys >= 1) {
1982 /* Try with the initial key */
1983 decrypt_info->key = key;
1984 payload_tvb = decrypt_func(tvb, offset, pinfo, packet, decrypt_info);
1985 if (!((*decrypt_info->status == DECRYPT_PACKET_MIC_CHECK_FAILED) || (*decrypt_info->status == DECRYPT_PACKET_DECRYPT_FAILED))) {
1986 break;
1989 if (nkeys >= 2) {
1990 /* Try also with the alternate key */
1991 decrypt_info->key = alt_key;
1992 payload_tvb = decrypt_func(tvb, offset, pinfo, packet, decrypt_info);
1993 if (!((*decrypt_info->status == DECRYPT_PACKET_MIC_CHECK_FAILED) || (*decrypt_info->status == DECRYPT_PACKET_DECRYPT_FAILED))) {
1994 break;
1998 decrypt_info->key = NULL;
1999 if (decrypt_info->key_number == num_ieee802154_keys) {
2000 /* None of the stored keys seemed to work */
2001 *decrypt_info->status = DECRYPT_PACKET_NO_KEY;
2004 /* Store the key number used for retrieval */
2005 ti = proto_tree_add_uint(key_tree, hf_ieee802154_key_number, tvb, 0, 0, decrypt_info->key_number);
2006 proto_item_set_hidden(ti);
2007 return payload_tvb;
2012 * Check if the CRC-OK flag in the CC24xx metadata trailer is true
2013 * @param tvb the IEEE 802.15.4 frame
2014 * @return if the flag is true
2016 static bool
2017 is_cc24xx_crc_ok(tvbuff_t *tvb)
2019 return tvb_get_letohs(tvb, tvb_reported_length(tvb)-2) & IEEE802154_CC24xx_CRC_OK ? true : false;
2023 * Verify the 16/32 bit IEEE 802.15.4 FCS
2024 * @param tvb the IEEE 802.15.4 frame from the FCF up to and including the FCS
2025 * @return if the computed FCS matches the transmitted FCS
2027 static bool
2028 is_fcs_ok(tvbuff_t *tvb, unsigned fcs_len)
2030 if (fcs_len == 2) {
2031 /* The FCS is in the last two bytes of the packet. */
2032 uint16_t fcs = tvb_get_letohs(tvb, tvb_reported_length(tvb)-2);
2033 uint16_t fcs_calc = (uint16_t) ieee802154_crc_tvb(tvb, tvb_reported_length(tvb)-2);
2034 return fcs == fcs_calc;
2036 else {
2037 /* The FCS is in the last four bytes of the packet. */
2038 uint32_t fcs = tvb_get_letohl(tvb, tvb_reported_length(tvb)-4);
2039 uint32_t fcs_calc = ieee802154_crc32_tvb(tvb, tvb_reported_length(tvb)-4);
2040 return fcs == fcs_calc;
2045 * Dissector for IEEE 802.15.4 packets with a PHY for which there's a
2046 * 4-octet preamble, a 1-octet SFD, and a 1-octet PHY header
2047 * with the uppermost bit reserved and the remaining 7 bits being
2048 * the frame length, and a 16-bit CRC value at the end.
2050 * Currently, those are the following PHYs:
2052 * O-QPSK
2053 * Binary phase-shift keying (BPSK)
2054 * GFSK
2055 * MSK
2056 * RCC DSSS BPSK
2058 * @param tvb pointer to buffer containing raw packet.
2059 * @param pinfo pointer to packet information fields
2060 * @param tree pointer to data tree wireshark uses to display packet.
2062 static int
2063 dissect_ieee802154_nonask_phy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2065 proto_tree *ieee802154_tree = NULL;
2066 proto_item *proto_root = NULL;
2068 unsigned offset = 0;
2069 uint8_t phr;
2070 tvbuff_t* mac;
2072 /* Create the protocol tree. */
2073 if (tree) {
2074 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");
2075 ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154_nonask_phy);
2078 /* Add the protocol name. */
2079 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4 non-ASK PHY");
2081 phr = tvb_get_uint8(tvb,offset+4+1);
2083 if (tree) {
2084 unsigned loffset = offset;
2085 static int * const phr_fields[] = {
2086 &hf_ieee802154_nonask_phy_length,
2087 NULL
2090 proto_tree_add_item(ieee802154_tree, hf_ieee802154_nonask_phy_preamble, tvb, loffset, 4, ENC_LITTLE_ENDIAN);
2091 loffset +=4 ;
2092 proto_tree_add_item(ieee802154_tree, hf_ieee802154_nonask_phy_sfd, tvb, loffset, 1, ENC_LITTLE_ENDIAN);
2093 loffset +=1 ;
2095 proto_tree_add_bitmask(ieee802154_tree, tvb, loffset, hf_ieee802154_nonask_phr, ett_ieee802154_nonask_phy_phr,
2096 phr_fields, ENC_NA);
2099 offset += 4+2*1;
2100 mac = tvb_new_subset_length_caplen(tvb,offset,-1, phr & IEEE802154_PHY_LENGTH_MASK);
2102 /* These always have the FCS at the end. */
2105 * Call the common dissector; FCS length is 2, and no flags.
2107 dissect_ieee802154_common(mac, pinfo, ieee802154_tree, 2, 0);
2108 return tvb_captured_length(tvb);
2109 } /* dissect_ieee802154_nonask_phy */
2111 /* Return the length in octets for the user configured
2112 * FCS/metadata following the PHY Payload */
2113 static unsigned
2114 ieee802154_fcs_type_len(unsigned i)
2116 unsigned fcs_type_lengths[] = { 2, 2, 4 };
2117 if (i < array_length(fcs_type_lengths)) {
2118 return fcs_type_lengths[i];
2120 return 0;
2124 * Dissector for IEEE 802.15.4 packet with an FCS containing a 16/32-bit
2125 * CRC value, or TI CC24xx metadata, at the end.
2127 * @param tvb pointer to buffer containing raw packet.
2128 * @param pinfo pointer to packet information fields.
2129 * @param tree pointer to data tree wireshark uses to display packet.
2131 static int
2132 dissect_ieee802154(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2134 tvbuff_t *new_tvb = dissect_zboss_specific(tvb, pinfo, tree);
2135 unsigned options = 0;
2136 unsigned fcs_len;
2138 /* Set the default FCS length based on the FCS type in the configuration */
2139 fcs_len = ieee802154_fcs_type_len(ieee802154_fcs_type);
2141 if (ieee802154_fcs_type == IEEE802154_CC24XX_METADATA) {
2142 options = DISSECT_IEEE802154_OPTION_CC24xx;
2145 if (new_tvb != tvb) {
2146 /* ZBOSS traffic dump: always TI metadata trailer, always ZigBee */
2147 options = DISSECT_IEEE802154_OPTION_CC24xx|DISSECT_IEEE802154_OPTION_ZBOSS;
2148 fcs_len = 2;
2151 /* Call the common dissector. */
2152 dissect_ieee802154_common(new_tvb, pinfo, tree, fcs_len, options);
2153 return tvb_captured_length(tvb);
2154 } /* dissect_ieee802154 */
2157 * Dissector for IEEE 802.15.4 packet with no FCS present.
2159 * @param tvb pointer to buffer containing raw packet.
2160 * @param pinfo pointer to packet information fields
2161 * @param tree pointer to data tree wireshark uses to display packet.
2162 * @return captured length.
2164 static int
2165 dissect_ieee802154_nofcs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
2168 * Call the common dissector; FCS length is 0, and no flags.
2170 dissect_ieee802154_common(tvb, pinfo, tree, 0, 0);
2171 return tvb_captured_length(tvb);
2172 } /* dissect_ieee802154_nofcs */
2175 * Dissector for IEEE 802.15.4 packet dump produced by ZBOSS
2177 * @param tvb pointer to buffer containing raw packet.
2178 * @param pinfo pointer to packet information fields
2179 * @param tree pointer to data tree wireshark uses to display packet.
2180 * @return new tvb subset if this is really ZBOSS dump, else oririnal tvb.
2182 static tvbuff_t *
2183 dissect_zboss_specific(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
2185 proto_tree *zboss_tree;
2186 proto_item *proto_root;
2187 unsigned off = 0;
2188 uint32_t direction_byte, page_byte, channel;
2190 if (tvb_captured_length(tvb) > 5)
2192 if (tvb_get_uint8(tvb, off++) == 'Z'
2193 && tvb_get_uint8(tvb, off++) == 'B'
2194 && tvb_get_uint8(tvb, off++) == 'O'
2195 && tvb_get_uint8(tvb, off++) == 'S'
2196 && tvb_get_uint8(tvb, off++) == 'S')
2198 /* Create the protocol tree. */
2199 proto_root = proto_tree_add_protocol_format(tree, proto_zboss, tvb, 0, tvb_captured_length(tvb), "ZBOSS dump");
2200 zboss_tree = proto_item_add_subtree(proto_root, ett_ieee802154_zboss);
2202 proto_tree_add_item_ret_uint(zboss_tree, hf_zboss_direction, tvb, off, 1, ENC_NA, &direction_byte);
2203 proto_item_append_text(proto_root, ", %s", direction_byte ? "OUT" : "IN");
2205 proto_tree_add_item_ret_uint(zboss_tree, hf_zboss_page, tvb, off, 1, ENC_NA, &page_byte);
2206 proto_item_append_text(proto_root, ", page %u", page_byte);
2207 off++;
2209 proto_tree_add_item_ret_uint(zboss_tree, hf_zboss_channel, tvb, off, 1, ENC_NA, &channel);
2210 proto_item_append_text(proto_root, ", channel %u", channel);
2211 off++;
2213 proto_tree_add_item(zboss_tree, hf_zboss_trace_number, tvb, off, 4, ENC_LITTLE_ENDIAN);
2214 off += 4;
2216 return tvb_new_subset_remaining(tvb, off);
2219 return tvb;
2220 } /* dissect_zboss_specific */
2223 * Dissector for IEEE 802.15.4 packet with 2 bytes of ChipCon/Texas
2224 * Instruments compatible metadata at the end of the frame, and no FCS.
2225 * This is typically called by layers encapsulating an IEEE 802.15.4 packet.
2227 * @param tvb pointer to buffer containing raw packet.
2228 * @param pinfo pointer to packet information fields
2229 * @param tree pointer to data tree wireshark uses to display packet.
2231 static int
2232 dissect_ieee802154_cc24xx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
2235 * Call the common dissector.
2236 * 2 bytes of metadata at the end of the packet data.
2238 dissect_ieee802154_common(tvb, pinfo, tree, 2, DISSECT_IEEE802154_OPTION_CC24xx);
2239 return tvb_captured_length(tvb);
2240 } /* dissect_ieee802154_cc24xx */
2243 * Dissector for IEEE 802.15.4 TAP packet
2245 * Contains optional TLVs and encapsulates an IEEE 802.15.4 packet.
2247 * @param tvb pointer to buffer containing raw packet.
2248 * @param pinfo pointer to packet information fields
2249 * @param tree pointer to data tree wireshark uses to display packet.
2251 static int
2252 dissect_ieee802154_tap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
2254 proto_tree *info_tree = NULL;
2255 proto_tree *header_tree = NULL;
2256 proto_item *proto_root = NULL;
2257 proto_item *ti = NULL;
2258 uint32_t version = 0;
2259 uint32_t length = 0;
2260 uint32_t data_length = 0;
2261 tvbuff_t* tlv_tvb;
2262 tvbuff_t* payload_tvb;
2263 ieee802154_fcs_type_t tap_fcs_type;
2264 unsigned fcs_len;
2266 /* Check the version in the TAP header */
2267 version = tvb_get_uint8(tvb, 0);
2268 if (version != 0) {
2269 /* Malformed packet. We do not understand any other version at this time */
2270 return 0;
2273 /* Get the total length of the header and TLVs */
2274 length = tvb_get_letohs(tvb, 2);
2276 if (length > tvb_captured_length(tvb)) {
2277 /* Malformed packet. The TLVs exceeds our captured packet. */
2278 return 0;
2281 /* Create the protocol tree */
2282 proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154_tap, tvb, 0, length, "IEEE 802.15.4 TAP");
2283 info_tree = proto_item_add_subtree(proto_root, ett_ieee802154_tap);
2285 header_tree = proto_tree_add_subtree(info_tree, tvb, 0, 4, ett_ieee802154_tap_header, &proto_root, "Header");
2286 proto_tree_add_item(header_tree, hf_ieee802154_tap_version, tvb, 0, 1, ENC_LITTLE_ENDIAN);
2287 proto_tree_add_item(header_tree, hf_ieee802154_tap_reserved, tvb, 1, 1, ENC_LITTLE_ENDIAN);
2288 proto_tree_add_item(header_tree, hf_ieee802154_tap_length, tvb, 2, 2, ENC_LITTLE_ENDIAN);
2290 /* Add the protocol name. */
2291 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4 TAP");
2293 /* Create a new tvb subset with only the TLVs to dissect */
2294 tlv_tvb = tvb_new_subset_length(tvb, 4, length - 4);
2295 tap_fcs_type = dissect_ieee802154_tap_tlvs(tlv_tvb, pinfo, info_tree);
2297 /* Set the FCS length based on the FCS type */
2298 switch (tap_fcs_type) {
2300 case IEEE802154_FCS_TYPE_NONE:
2301 fcs_len = 0;
2302 break;
2304 case IEEE802154_FCS_TYPE_16_BIT:
2305 fcs_len = 2;
2306 break;
2308 case IEEE802154_FCS_TYPE_32_BIT:
2309 fcs_len = 4;
2310 break;
2312 default:
2313 /* Not valid */
2314 return tvb_captured_length(tvb);
2317 /* Report the remaining bytes as the IEEE 802.15.4 Data Length */
2318 data_length = tvb_reported_length_remaining(tvb, length);
2319 ti = proto_tree_add_uint(info_tree, hf_ieee802154_tap_data_length, NULL, 0, 0, data_length);
2320 proto_item_set_generated(ti);
2322 if (data_length > 0) {
2324 * Call the common dissector with the real 802.15.4 data which follows the TLV header.
2325 * Create a separate packet bytes pane for the real data.
2326 * Specified FCS length, no flags.
2328 payload_tvb = tvb_new_child_real_data(tvb, tvb_get_ptr(tvb, length, data_length), data_length, data_length);
2329 add_new_data_source(pinfo, payload_tvb, "IEEE 802.15.4 Data");
2330 dissect_ieee802154_common(payload_tvb, pinfo, tree, fcs_len, 0);
2332 else {
2333 expert_add_info(pinfo, ti, &ei_ieee802154_tap_no_payload);
2336 return tvb_captured_length(tvb);
2337 } /* dissect_ieee802154_tap */
2340 * IEEE 802.15.4 packet dissection routine for Wireshark.
2342 * This function extracts all the information first before displaying.
2343 * If payload exists, that portion will be passed into another dissector
2344 * for further processing.
2346 * This is called after the individual dissect_ieee802154* functions
2347 * have been called to determine what sort of FCS is present, if any.
2349 * @param tvb pointer to buffer containing raw packet.
2350 * @param pinfo pointer to packet information fields
2351 * @param tree pointer to data tree Wireshark uses to display packet.
2352 * @param options bitwise or of dissector options (see DISSECT_IEEE802154_OPTION_xxx).
2354 static void
2355 dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned fcs_len, unsigned options)
2357 proto_tree *ieee802154_tree;
2358 ieee802154_packet *packet;
2359 bool fcs_present;
2360 bool fcs_ok;
2361 tvbuff_t* no_fcs_tvb;
2363 if (fcs_len != 0) {
2365 * Well, this packet should, in theory, have an FCS or CC24xx
2366 * metadata.
2367 * Do we have the entire packet, and does it have enough data for
2368 * the FCS/metadata?
2370 unsigned reported_len = tvb_reported_length(tvb);
2372 if (reported_len < fcs_len) {
2374 * The packet is claimed not to even have enough data
2375 * for the FCS/metadata. Pretend it doesn't have one.
2377 no_fcs_tvb = tvb;
2378 fcs_present = false;
2379 fcs_ok = true; // assume OK if not present
2380 } else {
2382 * The packet is claimed to have enough data for the
2383 * FCS/metadata.
2384 * Slice it off from the reported length.
2386 reported_len -= fcs_len;
2387 no_fcs_tvb = tvb_new_subset_length(tvb, 0, reported_len);
2390 * Is the FCS/metadata present in the captured data?
2391 * reported_len is now the length of the packet without the
2392 * FCS/metadata, so the FCS/metadata begins at an offset of
2393 * reported_len.
2395 if (tvb_bytes_exist(tvb, reported_len, fcs_len)) {
2397 * Yes. Check whether the FCS was OK.
2399 * If we have an FCS, check it.
2400 * If we have metadata, check its "FCS OK" flag.
2402 fcs_present = true;
2403 fcs_ok = options & DISSECT_IEEE802154_OPTION_CC24xx ? is_cc24xx_crc_ok(tvb) : is_fcs_ok(tvb, fcs_len);
2404 } else {
2406 * No.
2408 * Either 1) this means that there was a snapshot length
2409 * in effect when the capture was done, and that sliced
2410 * some or all of the FCS/metadata off or 2) this is a
2411 * capture with no FCS/metadata, using the same link-layer
2412 * header type value as captures with the FCS/metadata,
2413 * and indicating the lack of the FCS/metadata by having
2414 * the captured length be the length of the packet minus
2415 * the length of the FCS/metadata and the actual length
2416 * being the length of the packet including the FCS/metadata,
2417 * rather than by using the "no FCS" link-layer header type.
2419 * We could try to distinguish between them by checking
2420 * for a captured length that's exactly fcs_len bytes
2421 * less than the actual length. That would allow us to
2422 * report packets that are cut short just before, or in
2423 * the middle of, the FCS as having been cut short by the
2424 * snapshot length.
2426 * However, we can't distinguish between a packet that
2427 * happened to be cut fcs_len bytes short due to a
2428 * snapshot length being in effect when the capture was
2429 * done and a packet that *wasn't* cut short by a snapshot
2430 * length but that doesn't include the FCS/metadata.
2431 * Let's hope that rarely happens.
2433 fcs_present = false;
2434 fcs_ok = true; // assume OK if not present
2437 } else {
2438 no_fcs_tvb = tvb;
2439 fcs_present = false;
2440 fcs_ok = true; // assume OK if not present
2443 unsigned mhr_len = ieee802154_dissect_header(no_fcs_tvb, pinfo, tree, 0, &ieee802154_tree, &packet);
2444 if (!mhr_len || tvb_reported_length_remaining(no_fcs_tvb, mhr_len) < 0 ) {
2445 return;
2448 if ((packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) && (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE)) {
2449 _find_or_create_conversation(pinfo, &pinfo->dl_src, &pinfo->dl_dst);
2452 if (ieee802154_ack_tracking && (packet->ack_request || packet->frame_type == IEEE802154_FCF_ACK)) {
2453 uint32_t key[2] = {0};
2455 key[0] = packet->seqno;
2456 if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) {
2457 key[1] = pinfo->rec->rec_header.packet_header.interface_id;
2460 if (packet->ack_request) {
2461 transaction_start(pinfo, ieee802154_tree, packet, key);
2463 else {
2464 transaction_end(pinfo, ieee802154_tree, packet, key);
2468 tvbuff_t* payload = ieee802154_decrypt_payload(no_fcs_tvb, mhr_len, pinfo, ieee802154_tree, packet);
2469 if (payload) {
2470 unsigned pie_size = ieee802154_dissect_payload_ies(payload, pinfo, ieee802154_tree, packet);
2471 payload = tvb_new_subset_remaining(payload, pie_size);
2472 if (options & DISSECT_IEEE802154_OPTION_ZBOSS && packet->frame_type == IEEE802154_FCF_DATA) {
2473 if ((!fcs_ok && ieee802154_fcs_ok) || !tvb_reported_length(payload)) {
2474 call_data_dissector(payload, pinfo, tree);
2475 } else {
2476 call_dissector_with_data(zigbee_nwk_handle, payload, pinfo, tree, packet);
2478 } else {
2479 ieee802154_dissect_frame_payload(payload, pinfo, ieee802154_tree, packet, fcs_ok);
2483 if (fcs_present) {
2484 if (options & DISSECT_IEEE802154_OPTION_CC24xx)
2485 ieee802154_dissect_cc24xx_metadata(tvb, ieee802154_tree, fcs_ok);
2486 else
2487 ieee802154_dissect_fcs(tvb, ieee802154_tree, fcs_len, fcs_ok);
2489 /* If the CRC is invalid, make a note of it in the info column. */
2490 if (!fcs_ok) {
2491 col_append_str(pinfo->cinfo, COL_INFO, ", Bad FCS");
2492 proto_item_append_text(proto_tree_get_parent(ieee802154_tree), ", Bad FCS");
2494 /* Flag packet as having a bad crc. */
2495 expert_add_info(pinfo, proto_tree_get_parent(ieee802154_tree), &ei_ieee802154_fcs);
2497 } else {
2498 if (ieee802154_tree) {
2499 /* Even if the FCS isn't present, add the fcs_ok field to the tree to
2500 * help with filter. Be sure not to make it visible though.
2502 proto_item *ti = proto_tree_add_boolean_format_value(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, 0, 0, fcs_ok, "Unknown");
2503 proto_item_set_hidden(ti);
2507 tap_queue_packet(ieee802154_tap, pinfo, NULL);
2510 unsigned
2511 ieee802154_dissect_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned options, proto_tree **created_header_tree, ieee802154_packet **parsed_info)
2513 proto_tree *ieee802154_tree = NULL;
2514 proto_item *proto_root = NULL;
2515 proto_item *hidden_item;
2516 proto_item *ti;
2517 unsigned offset = 0;
2518 ieee802154_packet *packet = wmem_new0(pinfo->pool, ieee802154_packet);
2519 ieee802154_short_addr addr16;
2520 ieee802154_hints_t *ieee_hints;
2522 packet->short_table = ieee802154_map.short_table;
2524 /* Allocate frame data with hints for upper layers */
2525 if (!PINFO_FD_VISITED(pinfo) ||
2526 (ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0)) == NULL) {
2527 ieee_hints = wmem_new0(wmem_file_scope(), ieee802154_hints_t);
2528 p_add_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0, ieee_hints);
2531 /* Save a pointer to the whole packet */
2532 ieee_hints->packet = packet;
2534 /* Create the protocol tree. */
2535 if (tree) {
2536 proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154, tvb, 0, tvb_captured_length(tvb), "IEEE 802.15.4");
2537 ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154);
2539 /* Add the protocol name. */
2540 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4");
2542 /* Set out parameters */
2543 *created_header_tree = ieee802154_tree;
2544 *parsed_info = packet;
2546 /* Add the packet length to the filter field */
2547 hidden_item = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_frame_length, NULL, 0, 0, tvb_reported_length(tvb));
2548 proto_item_set_hidden(hidden_item);
2550 /* Frame Control Field */
2551 dissect_ieee802154_fcf(tvb, pinfo, ieee802154_tree, packet, &offset);
2553 /* Sequence Number */
2554 if (packet->seqno_suppression) {
2555 if (packet->version != IEEE802154_VERSION_2015 && packet->frame_type != IEEE802154_FCF_MULTIPURPOSE) {
2556 expert_add_info(pinfo, proto_root, &ei_ieee802154_seqno_suppression);
2558 } else { /* IEEE 802.15.4 Sequence Number Suppression */
2559 packet->seqno = tvb_get_uint8(tvb, offset);
2560 if (tree) {
2561 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_seqno, tvb, offset, 1, packet->seqno);
2562 /* For Ack packets display this in the root. */
2563 if (packet->frame_type == IEEE802154_FCF_ACK) {
2564 proto_item_append_text(proto_root, ", Sequence Number: %u", packet->seqno);
2567 offset += 1;
2571 * ADDRESSING FIELDS
2573 /* Clear out the addressing strings. */
2574 clear_address(&pinfo->net_dst);
2575 clear_address(&pinfo->dl_dst);
2576 clear_address(&pinfo->dst);
2577 clear_address(&pinfo->net_src);
2578 clear_address(&pinfo->dl_src);
2579 clear_address(&pinfo->src);
2581 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_RESERVED) {
2582 /* Invalid Destination Address Mode. Abort Dissection. */
2583 expert_add_info(pinfo, proto_root, &ei_ieee802154_dst);
2584 return 0;
2587 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_RESERVED) {
2588 /* Invalid Source Address Mode. Abort Dissection. */
2589 expert_add_info(pinfo, proto_root, &ei_ieee802154_src);
2590 return 0;
2593 if (packet->frame_type == IEEE802154_FCF_MULTIPURPOSE) {
2594 /* Multipurpose frames have a different set of frame versions, with 0 as the only valid version */
2595 if (packet->version != 0) {
2596 /* Unknown Frame Version for Multipurpose frames. Abort Dissection */
2597 expert_add_info(pinfo, proto_root, &ei_ieee802154_frame_ver);
2598 return 0;
2601 /* The source PAN ID is always omitted in multipurpose frames */
2602 packet->src_pan_present = false;
2604 if (packet->pan_id_present) {
2605 packet->dst_pan_present = true;
2608 else if (packet->version == IEEE802154_VERSION_RESERVED) {
2609 /* Unknown Frame Version. Abort Dissection. */
2610 expert_add_info(pinfo, proto_root, &ei_ieee802154_frame_ver);
2611 return 0;
2613 else if ((packet->version == IEEE802154_VERSION_2003) || /* For Frame Version 0b00 and */
2614 (packet->version == IEEE802154_VERSION_2006)) { /* 0b01 effect defined in section 7.2.1.5 */
2616 if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* if both destination and source */
2617 (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE)) { /* addressing information is present */
2618 if (packet->pan_id_compression == 1) { /* PAN IDs are identical */
2619 packet->dst_pan_present = true;
2620 packet->src_pan_present = false; /* source PAN ID is omitted */
2622 else { /* PAN IDs are different, both shall be included in the frame */
2623 packet->dst_pan_present = true;
2624 packet->src_pan_present = true;
2627 else {
2628 if (packet->pan_id_compression == 1) { /* all remaining cases pan_id_compression must be zero */
2629 expert_add_info(pinfo, proto_root, &ei_ieee802154_invalid_panid_compression);
2630 return 0;
2632 else {
2633 /* only either the destination or the source addressing information is present */
2634 if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
2635 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE)) { /* Not Present */
2636 packet->dst_pan_present = true;
2637 packet->src_pan_present = false;
2639 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2640 (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE)) { /* Present */
2641 packet->dst_pan_present = false;
2642 packet->src_pan_present = true;
2644 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2645 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE)) { /* Not Present */
2646 packet->dst_pan_present = false;
2647 packet->src_pan_present = false;
2649 else {
2650 expert_add_info(pinfo, proto_root, &ei_ieee802154_invalid_addressing);
2651 return 0;
2656 else if (packet->version == IEEE802154_VERSION_2015) {
2657 /* for Frame Version 0b10 PAN Id Compression only applies to these frame types */
2658 if ((packet->frame_type == IEEE802154_FCF_BEACON) ||
2659 (packet->frame_type == IEEE802154_FCF_DATA) ||
2660 (packet->frame_type == IEEE802154_FCF_ACK) ||
2661 (packet->frame_type == IEEE802154_FCF_CMD) ) {
2663 /* Implements Table 7-6 of IEEE 802.15.4-2015
2665 * Destination Address Source Address Destination PAN ID Source PAN ID PAN ID Compression
2666 *-------------------------------------------------------------------------------------------------
2667 * 1. Not Present Not Present Not Present Not Present 0
2668 * 2. Not Present Not Present Present Not Present 1
2669 * 3. Present Not Present Present Not Present 0
2670 * 4. Present Not Present Not Present Not Present 1
2672 * 5. Not Present Present Not Present Present 0
2673 * 6. Not Present Present Not Present Not Present 1
2675 * 7. Extended Extended Present Not Present 0
2676 * 8. Extended Extended Not Present Not Present 1
2678 * 9. Short Short Present Present 0
2679 * 10. Short Extended Present Present 0
2680 * 11. Extended Short Present Present 0
2682 * 12. Short Extended Present Not Present 1
2683 * 13. Extended Short Present Not Present 1
2684 * 14. Short Short Present Not Present 1
2687 /* Row 1 */
2688 if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2689 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2690 (packet->pan_id_compression == 0)) {
2691 packet->dst_pan_present = false;
2692 packet->src_pan_present = false;
2694 /* Row 2 */
2695 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2696 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2697 (packet->pan_id_compression == 1)) {
2698 packet->dst_pan_present = true;
2699 packet->src_pan_present = false;
2701 /* Row 3 */
2702 else if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
2703 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2704 (packet->pan_id_compression == 0)) {
2705 packet->dst_pan_present = true;
2706 packet->src_pan_present = false;
2708 /* Row 4 */
2709 else if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
2710 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2711 (packet->pan_id_compression == 1)) {
2712 packet->dst_pan_present = false;
2713 packet->src_pan_present = false;
2715 /* Row 5 */
2716 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2717 (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
2718 (packet->pan_id_compression == 0)) {
2719 packet->dst_pan_present = false;
2720 packet->src_pan_present = true;
2722 /* Row 6 */
2723 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2724 (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* Present */
2725 (packet->pan_id_compression == 1)) {
2726 packet->dst_pan_present = false;
2727 packet->src_pan_present = false;
2729 /* Row 7 */
2730 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2731 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2732 (packet->pan_id_compression == 0)) {
2733 packet->dst_pan_present = true;
2734 packet->src_pan_present = false;
2736 /* Row 8 */
2737 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2738 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2739 (packet->pan_id_compression == 1)) {
2740 packet->dst_pan_present = false;
2741 packet->src_pan_present = false;
2743 /* Row 9 */
2744 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2745 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2746 (packet->pan_id_compression == 0)) {
2747 packet->dst_pan_present = true;
2748 packet->src_pan_present = (ieee802154e_compatibility ? false : true);
2750 /* Row 10 */
2751 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2752 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2753 (packet->pan_id_compression == 0)) {
2754 packet->dst_pan_present = true;
2755 packet->src_pan_present = (ieee802154e_compatibility ? false : true);
2757 /* Row 11 */
2758 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2759 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2760 (packet->pan_id_compression == 0)) {
2761 packet->dst_pan_present = true;
2762 packet->src_pan_present = (ieee802154e_compatibility ? false : true);
2764 /* Row 12 */
2765 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2766 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2767 (packet->pan_id_compression == 1)) {
2768 packet->dst_pan_present = true;
2769 packet->src_pan_present = false;
2771 /* Row 13 */
2772 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /* Extended */
2773 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2774 (packet->pan_id_compression == 1)) {
2775 packet->dst_pan_present = true;
2776 packet->src_pan_present = false;
2778 /* Row 14 */
2779 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2780 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /* Short */
2781 (packet->pan_id_compression == 1)) {
2782 packet->dst_pan_present = true;
2783 packet->src_pan_present = false;
2785 else {
2786 expert_add_info(pinfo, proto_root, &ei_ieee802154_invalid_panid_compression2);
2787 return 0;
2790 else { /* Frame Type is neither Beacon, Data, Ack, nor Command: PAN ID Compression is not used */
2791 packet->dst_pan_present = false; /* no PAN ID will */
2792 packet->src_pan_present = false; /* be present */
2795 else {
2796 /* Unknown Frame Version. Abort Dissection. */
2797 expert_add_info(pinfo, proto_root, &ei_ieee802154_frame_ver);
2798 return 0;
2802 * Addressing Fields
2805 /* Destination PAN Id */
2806 if (packet->dst_pan_present) {
2807 packet->dst_pan = tvb_get_letohs(tvb, offset);
2808 if (ieee802154_tree) {
2809 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst_panID, tvb, offset, 2, packet->dst_pan);
2811 offset += 2;
2814 /* Destination Address */
2815 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
2816 /* Get the address. */
2817 packet->dst16 = tvb_get_letohs(tvb, offset);
2819 /* Provide address hints to higher layers that need it. */
2820 if (ieee_hints) {
2821 ieee_hints->dst16 = packet->dst16;
2824 set_address_tvb(&pinfo->dl_dst, ieee802_15_4_short_address_type, 2, tvb, offset);
2825 copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
2827 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst16, tvb, offset, 2, packet->dst16);
2828 ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_addr16, tvb, offset, 2, packet->dst16);
2829 proto_item_set_generated(ti);
2830 proto_item_set_hidden(ti);
2832 offset += 2;
2834 else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
2835 uint64_t *p_addr = (uint64_t *)wmem_new(pinfo->pool, uint64_t);
2837 /* Get the address */
2838 packet->dst64 = tvb_get_letoh64(tvb, offset);
2840 /* Copy and convert the address to network byte order. */
2841 *p_addr = pntoh64(&(packet->dst64));
2843 /* Display the destination address. */
2844 /* XXX - OUI resolution doesn't happen when displaying resolved
2845 * EUI64 addresses; that should probably be fixed in
2846 * epan/addr_resolv.c.
2848 set_address(&pinfo->dl_dst, AT_EUI64, 8, p_addr);
2849 copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
2850 if (tree) {
2851 proto_tree_add_item(ieee802154_tree, hf_ieee802154_dst64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2852 ti = proto_tree_add_item(ieee802154_tree, hf_ieee802154_addr64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2853 proto_item_set_generated(ti);
2854 proto_item_set_hidden(ti);
2857 offset += 8;
2860 /* Source PAN Id */
2861 if (packet->src_pan_present) {
2862 packet->src_pan = tvb_get_letohs(tvb, offset);
2863 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src_panID, tvb, offset, 2, packet->src_pan);
2864 offset += 2;
2866 else {
2867 if (packet->dst_pan_present) {
2868 packet->src_pan = packet->dst_pan;
2870 else {
2871 packet->src_pan = IEEE802154_BCAST_PAN;
2874 if (ieee_hints) {
2875 ieee_hints->src_pan = packet->src_pan;
2878 /* Source Address */
2879 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
2880 /* Get the address. */
2881 packet->src16 = tvb_get_letohs(tvb, offset);
2883 if (!PINFO_FD_VISITED(pinfo)) {
2884 /* If we know our extended source address from previous packets,
2885 * provide a pointer to it in a hint for upper layers */
2886 addr16.addr = packet->src16;
2887 addr16.pan = packet->src_pan;
2889 if (ieee_hints) {
2890 ieee_hints->src16 = packet->src16;
2891 ieee_hints->map_rec = (ieee802154_map_rec *)
2892 g_hash_table_lookup(ieee802154_map.short_table, &addr16);
2896 set_address_tvb(&pinfo->dl_src, ieee802_15_4_short_address_type, 2, tvb, offset);
2897 copy_address_shallow(&pinfo->src, &pinfo->dl_src);
2899 /* Add the addressing info to the tree. */
2900 if (tree) {
2901 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src16, tvb, offset, 2, packet->src16);
2902 ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_addr16, tvb, offset, 2, packet->src16);
2903 proto_item_set_generated(ti);
2904 proto_item_set_hidden(ti);
2906 if (ieee_hints && ieee_hints->map_rec) {
2907 /* Display inferred source address info */
2908 ti = proto_tree_add_eui64(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 0,
2909 ieee_hints->map_rec->addr64);
2910 proto_item_set_generated(ti);
2911 ti = proto_tree_add_eui64(ieee802154_tree, hf_ieee802154_addr64, tvb, offset, 0, ieee_hints->map_rec->addr64);
2912 proto_item_set_generated(ti);
2913 proto_item_set_hidden(ti);
2915 if ( ieee_hints->map_rec->start_fnum ) {
2916 ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src64_origin, tvb, 0, 0,
2917 ieee_hints->map_rec->start_fnum);
2919 else {
2920 ti = proto_tree_add_uint_format_value(ieee802154_tree, hf_ieee802154_src64_origin, tvb, 0, 0,
2921 ieee_hints->map_rec->start_fnum, "Pre-configured");
2923 proto_item_set_generated(ti);
2927 offset += 2;
2929 else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
2930 uint64_t *p_addr = (uint64_t *)wmem_new(pinfo->pool, uint64_t);
2932 /* Get the address. */
2933 packet->src64 = tvb_get_letoh64(tvb, offset);
2935 /* Copy and convert the address to network byte order. */
2936 *p_addr = pntoh64(&(packet->src64));
2938 /* Display the source address. */
2939 /* XXX - OUI resolution doesn't happen when displaying resolved
2940 * EUI64 addresses; that should probably be fixed in
2941 * epan/addr_resolv.c.
2943 set_address(&pinfo->dl_src, AT_EUI64, 8, p_addr);
2944 copy_address_shallow(&pinfo->src, &pinfo->dl_src);
2945 if (tree) {
2946 proto_tree_add_item(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2947 ti = proto_tree_add_item(ieee802154_tree, hf_ieee802154_addr64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2948 proto_item_set_generated(ti);
2949 proto_item_set_hidden(ti);
2952 offset += 8;
2955 /* Add the addressing info to the root of the tree. */
2956 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
2957 proto_item_append_text(proto_root, ", Src: %s", address_to_str(pinfo->pool, &pinfo->src));
2958 col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", address_to_str(pinfo->pool, &pinfo->src));
2960 else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
2961 proto_item_append_text(proto_root, ", Src: %s", eui64_to_display(pinfo->pool, packet->src64));
2962 col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", eui64_to_display(pinfo->pool, packet->src64));
2965 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
2966 proto_item_append_text(proto_root, ", Dst: %s", address_to_str(pinfo->pool, &pinfo->dst));
2967 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", address_to_str(pinfo->pool, &pinfo->dst));
2969 else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
2970 proto_item_append_text(proto_root, ", Dst: %s", eui64_to_display(pinfo->pool, packet->dst64));
2971 col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", eui64_to_display(pinfo->pool, packet->dst64));
2974 /* Existence of the Auxiliary Security Header is controlled by the Security Enabled Field */
2975 if (packet->security_enable &&
2976 ((packet->frame_type == IEEE802154_FCF_MULTIPURPOSE) || (packet->version != IEEE802154_VERSION_2003)) &&
2977 !(options & IEEE802154_DISSECT_HEADER_OPTION_NO_AUX_SEC_HDR))
2979 dissect_ieee802154_aux_sec_header_and_key(tvb, pinfo, ieee802154_tree, packet, &offset);
2983 * NONPAYLOAD FIELDS
2986 /* All of the beacon fields, except the beacon payload are considered nonpayload. */
2987 if ((packet->frame_type != IEEE802154_FCF_MULTIPURPOSE) && ((packet->version == IEEE802154_VERSION_2003) || (packet->version == IEEE802154_VERSION_2006))) {
2988 if (packet->frame_type == IEEE802154_FCF_BEACON) { /* Regular Beacon. Some are not present in frame version (Enhanced) Beacons */
2989 dissect_ieee802154_superframe(tvb, pinfo, ieee802154_tree, &offset); /* superframe spec */
2990 dissect_ieee802154_gtsinfo(tvb, pinfo, ieee802154_tree, &offset); /* GTS information fields */
2991 dissect_ieee802154_pendaddr(tvb, pinfo, ieee802154_tree, &offset); /* Pending address list */
2994 if (packet->frame_type == IEEE802154_FCF_CMD) {
2996 * In IEEE802.15.4-2003 and 2006 the command identifier is considered to be part of the header
2997 * and is thus not encrypted. For IEEE802.15.4-2012e and later the command id is considered to be
2998 * part of the payload, is encrypted, and follows the payload IEs. Thus we only parse the command id
2999 * here for 2006 and earlier frames. */
3000 packet->command_id = tvb_get_uint8(tvb, offset);
3001 if (tree) {
3002 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_cmd_id, tvb, offset, 1, packet->command_id);
3004 offset++;
3006 /* Display the command identifier in the info column. */
3007 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
3010 else {
3011 if (packet->ie_present) {
3012 offset += dissect_ieee802154_header_ie(tvb, pinfo, ieee802154_tree, offset, packet);
3016 /* IEEE 802.15.4-2003 may have security information pre-pended to payload */
3017 if (packet->security_enable && (packet->frame_type != IEEE802154_FCF_MULTIPURPOSE) && (packet->version == IEEE802154_VERSION_2003))
3019 /* Store security suite preference in the 2006 security level identifier to simplify 2003 integration! */
3020 packet->security_level = (ieee802154_security_level)ieee802154_sec_suite;
3022 /* Frame Counter and Key Sequence Counter prepended to the payload of an encrypted frame */
3023 if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
3024 packet->frame_counter = tvb_get_letohl (tvb, offset);
3025 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_frame_counter, tvb, offset, (int)sizeof(uint32_t), packet->frame_counter);
3026 offset += (int)sizeof(uint32_t);
3028 packet->key_sequence_counter = tvb_get_uint8 (tvb, offset);
3029 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_key_sequence_counter, tvb, offset, (int)sizeof(uint8_t), packet->key_sequence_counter);
3030 offset += (int)sizeof(uint8_t);
3034 return offset;
3038 * XXX - "mhr_len" is really a general offset; this is used elsewhere.
3040 tvbuff_t*
3041 ieee802154_decrypt_payload(tvbuff_t *tvb, unsigned mhr_len, packet_info *pinfo, proto_tree *ieee802154_tree, ieee802154_packet *packet)
3043 proto_item *proto_root = proto_tree_get_parent(ieee802154_tree);
3044 proto_tree *tree = proto_tree_get_parent_tree(ieee802154_tree);
3045 unsigned char rx_mic[IEEE802154_CIPHER_SIZE];
3046 unsigned rx_mic_len = IEEE802154_MIC_LENGTH(packet->security_level);
3047 ieee802154_decrypt_status status = DECRYPT_NOT_ENCRYPTED;
3048 tvbuff_t *payload_tvb;
3050 unsigned id2 = proto_get_id_by_short_name("TREL");
3051 wmem_list_frame_t* ptr2 = wmem_list_find(pinfo->layers, GUINT_TO_POINTER(id2));
3053 /* Encrypted Payload. */
3054 if (packet->security_enable || ptr2) {
3055 ieee802154_decrypt_info_t decrypt_info;
3057 decrypt_info.rx_mic = rx_mic;
3058 decrypt_info.rx_mic_length = &rx_mic_len;
3059 decrypt_info.status = &status;
3060 decrypt_info.key = NULL; /* payload function will fill that in */
3062 if (ptr2) // if this pointer is not null that mean we found trel
3063 payload_tvb = decrypt_ieee802154_payload(tvb, mhr_len, pinfo, NULL, packet, &decrypt_info,
3064 ieee802154_set_trel_key, dissect_ieee802154_decrypt);
3065 else
3066 /* call with NULL tree since we add the key_number below without hiding it */
3067 payload_tvb = decrypt_ieee802154_payload(tvb, mhr_len, pinfo, NULL, packet, &decrypt_info,
3068 ieee802154_set_mac_key, dissect_ieee802154_decrypt);
3070 /* Get the unencrypted data if decryption failed. */
3071 if (!payload_tvb) {
3072 /* Deal with possible truncation and the MIC field at the end. */
3073 int reported_len = tvb_reported_length(tvb)-mhr_len-rx_mic_len;
3074 payload_tvb = tvb_new_subset_length(tvb, mhr_len, reported_len);
3077 /* Display the MIC. */
3078 if (rx_mic_len) {
3079 if (tvb_bytes_exist(tvb, tvb_reported_length(tvb) - rx_mic_len, rx_mic_len)) {
3080 proto_tree_add_item(ieee802154_tree, hf_ieee802154_mic, tvb, tvb_reported_length(tvb)-rx_mic_len, rx_mic_len, ENC_NA);
3084 /* Display the reason for failure, and abort if the error was fatal. */
3085 switch (status) {
3086 case DECRYPT_PACKET_SUCCEEDED:
3088 proto_item *pi = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_key_number, tvb, 0, 0, decrypt_info.key_number);
3089 proto_item_set_generated(pi);
3090 break;
3092 case DECRYPT_NOT_ENCRYPTED:
3093 break; // nothing to do
3095 case DECRYPT_FRAME_COUNTER_SUPPRESSION_UNSUPPORTED:
3096 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "Decryption of 802.15.4-2015 with frame counter suppression is not supported");
3097 call_data_dissector(payload_tvb, pinfo, tree);
3098 return NULL;
3100 case DECRYPT_PACKET_TOO_SMALL:
3101 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "Packet was too small to include the CRC and MIC");
3102 call_data_dissector(payload_tvb, pinfo, tree);
3103 return NULL;
3105 case DECRYPT_PACKET_NO_EXT_SRC_ADDR:
3106 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "No extended source address - can't decrypt");
3107 call_data_dissector(payload_tvb, pinfo, tree);
3108 return NULL;
3110 case DECRYPT_PACKET_NO_KEY:
3111 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "No encryption key set - can't decrypt");
3112 call_data_dissector(payload_tvb, pinfo, tree);
3113 return NULL;
3115 case DECRYPT_PACKET_DECRYPT_FAILED:
3116 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "Decrypt failed");
3117 call_data_dissector(payload_tvb, pinfo, tree);
3118 return NULL;
3120 case DECRYPT_PACKET_MIC_CHECK_FAILED:
3121 expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "MIC check failed");
3123 * Abort only if the payload was encrypted, in which case we
3124 * probably didn't decrypt the packet right (eg: wrong key).
3126 if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
3127 call_data_dissector(payload_tvb, pinfo, tree);
3128 return NULL;
3130 break;
3133 /* Plaintext Payload. */
3134 else {
3135 /* Deal with possible truncation. */
3136 int reported_len = tvb_reported_length(tvb)-mhr_len;
3137 payload_tvb = tvb_new_subset_length(tvb, mhr_len, reported_len);
3140 return payload_tvb;
3144 unsigned ieee802154_dissect_payload_ies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ieee802154_tree, ieee802154_packet *packet)
3146 /* Presence of Payload IEs is defined by the termination of the Header IEs */
3147 if (packet->payload_ie_present) {
3148 if (tvb_reported_length(tvb) > 2) {
3149 return (unsigned) dissect_ieee802154_payload_ie(tvb, pinfo, ieee802154_tree, 0, packet);
3150 } else {
3151 expert_add_info(pinfo, proto_tree_get_parent(ieee802154_tree), &ei_ieee802154_missing_payload_ie);
3154 return 0;
3158 unsigned ieee802154_dissect_frame_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ieee802154_tree, ieee802154_packet *packet, bool fcs_ok)
3160 tvbuff_t *payload_tvb = tvb;
3161 proto_tree *tree = proto_tree_get_parent_tree(ieee802154_tree);
3162 heur_dtbl_entry_t *hdtbl_entry;
3164 /* There are commands without payload */
3165 if (tvb_captured_length(payload_tvb) > 0 || packet->frame_type == IEEE802154_FCF_CMD) {
3167 * Wrap the sub-dissection in a try/catch block in case the payload is
3168 * broken. First we store the current protocol so we can fix it if an
3169 * exception is thrown by the subdissectors.
3171 const char* saved_proto = pinfo->current_proto;
3172 /* Try to dissect the payload. */
3173 TRY {
3174 switch (packet->frame_type) {
3175 case IEEE802154_FCF_BEACON:
3176 if (!dissector_try_heuristic(ieee802154_beacon_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, packet)) {
3177 unsigned offset;
3178 offset = dissect_zbee_tlvs(payload_tvb, pinfo, tree, 0, NULL, ZBEE_TLV_SRC_TYPE_DEFAULT, 0);
3179 if (tvb_captured_length_remaining(payload_tvb, offset) > 0)
3181 tvbuff_t *payload_tvb_remaining;
3182 payload_tvb_remaining = tvb_new_subset_remaining(payload_tvb, offset);
3183 /* Could not subdissect, call the data dissector instead. */
3184 call_data_dissector(payload_tvb_remaining, pinfo, tree);
3187 break;
3189 case IEEE802154_FCF_CMD:
3190 dissect_ieee802154_command(payload_tvb, pinfo, ieee802154_tree, packet);
3191 break;
3193 case IEEE802154_FCF_DATA:
3194 /* Sanity-check. */
3195 if ((!fcs_ok && ieee802154_fcs_ok) || !tvb_reported_length(payload_tvb)) {
3196 call_data_dissector(payload_tvb, pinfo, tree);
3197 break;
3199 /* Try the PANID dissector table for stateful dissection. */
3200 if (dissector_try_uint_with_data(panid_dissector_table, packet->src_pan, payload_tvb, pinfo, tree, true, packet)) {
3201 break;
3203 /* Try again with the destination PANID (if different) */
3204 if (((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) ||
3205 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)) &&
3206 (packet->dst_pan != packet->src_pan) &&
3207 dissector_try_uint_with_data(panid_dissector_table, packet->src_pan, payload_tvb, pinfo, tree, true, packet)) {
3208 break;
3210 /* Try heuristic dissection. */
3211 if (dissector_try_heuristic(ieee802154_heur_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, packet)) break;
3212 /* Fall-through to dump undissectable payloads. */
3213 /* FALL THROUGH */
3214 default:
3215 /* Could not subdissect, call the data dissector instead. */
3216 call_data_dissector(payload_tvb, pinfo, tree);
3217 } /* switch */
3219 CATCH_ALL {
3221 * Someone encountered an error while dissecting the payload. But
3222 * we haven't yet finished processing all of our layer. Catch and
3223 * display the exception, then fall-through to finish displaying
3224 * the FCS (which we display last so the frame is ordered correctly
3225 * in the tree).
3227 show_exception(payload_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
3228 pinfo->current_proto = saved_proto;
3230 ENDTRY;
3232 return tvb_captured_length(tvb);
3236 * Dissect the FCS at the end of the frame.
3237 * That is only displayed if the included length of the tvb encompasses it.
3239 * @param tvb the 802.15.4 frame tvb
3240 * @param ieee802154_tree the 802.15.4 protocol tree
3241 * @param fcs_len length of the FCS field
3242 * @param fcs_ok set to false to indicate FCS verification failed
3244 static void
3245 ieee802154_dissect_fcs(tvbuff_t *tvb, proto_tree *ieee802154_tree, unsigned fcs_len, bool fcs_ok)
3247 proto_item *ti;
3248 /* The FCS should be the last bytes of the reported packet. */
3249 unsigned offset = tvb_reported_length(tvb)-fcs_len;
3250 /* Dissect the FCS only if it exists (captures which don't or can't get the
3251 * FCS will simply truncate the packet to omit it, but should still set the
3252 * reported length to cover the original packet length), so if the snapshot
3253 * is too short for an FCS don't make a fuss.
3255 if (ieee802154_tree) {
3256 if (fcs_len == 2) {
3257 uint16_t fcs = tvb_get_letohs(tvb, offset);
3259 ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_fcs, tvb, offset, 2, fcs);
3260 if (fcs_ok) {
3261 proto_item_append_text(ti, " (Correct)");
3263 else {
3264 proto_item_append_text(ti, " (Incorrect, expected FCS=0x%04x)", ieee802154_crc_tvb(tvb, offset));
3266 /* To Help with filtering, add the fcs_ok field to the tree. */
3267 ti = proto_tree_add_boolean(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, offset, 2, (uint64_t) fcs_ok);
3268 proto_item_set_hidden(ti);
3270 else {
3271 uint32_t fcs = tvb_get_letohl(tvb, offset);
3273 ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_fcs32, tvb, offset, 4, fcs);
3274 if (fcs_ok) {
3275 proto_item_append_text(ti, " (Correct)");
3277 else {
3278 proto_item_append_text(ti, " (Incorrect, expected FCS=0x%08x)", ieee802154_crc32_tvb(tvb, offset));
3280 /* To Help with filtering, add the fcs_ok field to the tree. */
3281 ti = proto_tree_add_boolean(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, offset, 2, (uint64_t) fcs_ok);
3282 proto_item_set_hidden(ti);
3285 } /* ieee802154_dissect_fcs */
3288 * Dissect the TI CC24xx metadata at the end of the frame.
3289 * That is only displayed if the included length of the tvb encompasses it.
3291 * @param tvb the 802.15.4 frame tvb
3292 * @param ieee802154_tree the 802.15.4 protocol tree
3293 * @param fcs_ok set to false to indicate FCS verification failed
3295 static void
3296 ieee802154_dissect_cc24xx_metadata(tvbuff_t *tvb, proto_tree *ieee802154_tree, bool fcs_ok)
3298 /* The metadata should be the last 2 bytes of the reported packet. */
3299 unsigned offset = tvb_reported_length(tvb)-2;
3300 /* Dissect the metadata only if it exists (captures which don't or can't get the
3301 * metadata will simply truncate the packet to omit it, but should still set the
3302 * reported length to cover the original packet length), so if the snapshot
3303 * is too short for the metadata don't make a fuss.
3305 if (ieee802154_tree) {
3306 proto_tree *field_tree;
3307 uint16_t metadata = tvb_get_letohs(tvb, offset);
3309 /* Create a subtree for the metadata. */
3310 field_tree = proto_tree_add_subtree_format(ieee802154_tree, tvb, offset, 2, ett_ieee802154_fcs, NULL,
3311 "TI CC24xx-format metadata: FCS %s", (fcs_ok) ? "OK" : "Bad");
3312 /* Display metadata contents. */
3313 proto_tree_add_boolean(field_tree, hf_ieee802154_fcs_ok, tvb, offset, 1, (uint64_t) (metadata & IEEE802154_CC24xx_CRC_OK));
3314 proto_tree_add_int(field_tree, hf_ieee802154_rssi, tvb, offset++, 1, (int8_t) (metadata & IEEE802154_CC24xx_RSSI));
3315 proto_tree_add_uint(field_tree, hf_ieee802154_correlation, tvb, offset, 1, (uint8_t) ((metadata & IEEE802154_CC24xx_CORRELATION) >> 8));
3317 } /* ieee802154_dissect_cc24xx_metadata */
3319 static void
3320 dissect_ieee802154_tap_sun_phy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, unsigned length)
3322 (void) pinfo;
3323 if (length == 3) {
3324 uint32_t band;
3325 uint32_t sun_type;
3326 uint32_t mode;
3327 proto_tree_add_item_ret_uint(tree, hf_ieee802154_sun_band, tvb, offset, 1, ENC_LITTLE_ENDIAN, &band);
3328 proto_item_append_text(proto_tree_get_parent(tree), ": Band: %s (%u)", val_to_str_const(band, sun_bands, "Unknown"), band);
3329 proto_tree_add_item_ret_uint(tree, hf_ieee802154_sun_type, tvb, offset+1, 1, ENC_LITTLE_ENDIAN, &sun_type);
3330 if (sun_type < array_length(sun_types)) {
3331 proto_item_append_text(proto_tree_get_parent(tree), ", Type: %s (%u)", val_to_str_const(sun_type, sun_types, "Unknown"), sun_type);
3334 switch (sun_type) {
3335 case IEEE802154_SUN_TYPE_FSK_A:
3336 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_fsk_a, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3337 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3338 break;
3339 case IEEE802154_SUN_TYPE_FSK_B:
3340 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_fsk_b, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3341 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3342 break;
3343 case IEEE802154_SUN_TYPE_OQPSK_A:
3344 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_oqpsk_a, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3345 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3346 break;
3347 case IEEE802154_SUN_TYPE_OQPSK_B:
3348 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_oqpsk_b, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3349 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3350 break;
3351 case IEEE802154_SUN_TYPE_OQPSK_C:
3352 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_oqpsk_c, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3353 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3354 break;
3355 case IEEE802154_SUN_TYPE_OFDM_OPT1:
3356 case IEEE802154_SUN_TYPE_OFDM_OPT2:
3357 case IEEE802154_SUN_TYPE_OFDM_OPT3:
3358 case IEEE802154_SUN_TYPE_OFDM_OPT4:
3359 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_ofdm, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3360 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3361 break;
3362 default:
3363 proto_tree_add_item(tree, hf_ieee802154_sun_mode, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
3364 break;
3365 } /* switch (sun_type) */
3367 } /* dissect_ieee802154_tap_sun_phy */
3369 static void
3370 dissect_ieee802154_tap_phy_header(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned offset, unsigned length)
3372 uint32_t phr_type;
3373 uint32_t phr_bits;
3375 proto_tree_add_item_ret_uint(tree, hf_ieee802154_tap_phr_type, tvb, offset, 2, ENC_LITTLE_ENDIAN, &phr_type);
3376 proto_tree_add_item_ret_uint(tree, hf_ieee802154_tap_phr_bits, tvb, offset+2, 2, ENC_LITTLE_ENDIAN, &phr_bits);
3378 switch (phr_type) {
3379 case PHR_WISUN_FSK_MS: {
3380 uint32_t phr_data = tvb_get_letohs(tvb, offset+4);
3381 if (phr_data & IEEE802154_TAP_PHR_FSK_MS) {
3382 static int* const ieee802154_tap_phr_fsk_wisun_ms_fields[] = {
3383 &hf_ieee802154_tap_phr_fsk_ms,
3384 &hf_ieee802154_tap_phr_wisun_fsk_ms_reserved,
3385 &hf_ieee802154_tap_phr_wisun_fsk_ms_phymodeid,
3386 &hf_ieee802154_tap_phr_fsk_ms_checksum,
3387 &hf_ieee802154_tap_phr_fsk_ms_parity,
3388 NULL
3390 proto_item *pi = proto_tree_add_bitmask_with_flags(tree, tvb, offset+4, hf_ieee802154_tap_wisun_ms_phr,
3391 ett_ieee802154_tap_phr, ieee802154_tap_phr_fsk_wisun_ms_fields, ENC_LITTLE_ENDIAN, BMT_NO_TFS);
3392 if (phr_data & IEEE802154_TAP_PHR_WISUN_FSK_MS_RESERVED) {
3393 expert_add_info(NULL, pi, &ei_ieee802154_tap_tlv_reserved_not_zero);
3395 /* TODO: expert info BCH(15,11) checksum check */
3396 /* TODO: expert info parity check */
3398 break;
3400 case PHR_SUN_FSK: {
3401 uint32_t phr_data = tvb_get_letohs(tvb, offset+4);
3402 if (phr_data & IEEE802154_TAP_PHR_FSK_MS) {
3403 int *const *fields;
3404 if ((phr_data & IEEE802154_TAP_PHR_FSK_MS_MODE_SCHEME) == IEEE802154_TAP_PHR_FSK_MS_SCHEME_FSK) {
3405 /* SUN FSK */
3406 static int* const ieee802154_tap_phr_fsk_ms_fields[] = {
3407 &hf_ieee802154_tap_phr_fsk_ms,
3408 &hf_ieee802154_tap_phr_fsk_ms_param,
3409 &hf_ieee802154_tap_phr_fsk_ms_fec,
3410 &hf_ieee802154_tap_phr_fsk_ms_mode_page,
3411 &hf_ieee802154_tap_phr_fsk_ms_mode_scheme,
3412 &hf_ieee802154_tap_phr_fsk_ms_mode_mode,
3413 &hf_ieee802154_tap_phr_fsk_ms_checksum,
3414 &hf_ieee802154_tap_phr_fsk_ms_parity,
3415 NULL
3417 fields = ieee802154_tap_phr_fsk_ms_fields;
3419 else if ((phr_data & IEEE802154_TAP_PHR_FSK_MS_MODE_SCHEME) == IEEE802154_TAP_PHR_FSK_MS_SCHEME_OFDM ||
3420 (phr_data & IEEE802154_TAP_PHR_FSK_MS_MODE_SCHEME) == IEEE802154_TAP_PHR_FSK_MS_SCHEME_OQPSK) {
3421 /* SUN OFDM or SUN O-QPSK */
3422 static int* const ieee802154_tap_phr_fsk_ms_ofdm_fields[] = {
3423 &hf_ieee802154_tap_phr_fsk_ms,
3424 &hf_ieee802154_tap_phr_fsk_ms_param,
3425 &hf_ieee802154_tap_phr_fsk_ms_fec,
3426 &hf_ieee802154_tap_phr_fsk_ms_mode_page,
3427 &hf_ieee802154_tap_phr_fsk_ms_mode_scheme,
3428 &hf_ieee802154_tap_phr_fsk_ms_checksum,
3429 &hf_ieee802154_tap_phr_fsk_ms_parity,
3430 NULL
3432 fields = ieee802154_tap_phr_fsk_ms_ofdm_fields;
3434 else /* if ((phr_data & IEEE802154_TAP_PHR_FSK_MS_MODE_SCHEME) == IEEE802154_TAP_PHR_FSK_MS_SCHEME_ADDL) */ {
3435 /* Additional Modes */
3436 static int* const ieee802154_tap_phr_fsk_ms_addl_fields[] = {
3437 &hf_ieee802154_tap_phr_fsk_ms,
3438 &hf_ieee802154_tap_phr_fsk_ms_param,
3439 &hf_ieee802154_tap_phr_fsk_ms_fec,
3440 &hf_ieee802154_tap_phr_fsk_ms_mode_page,
3441 &hf_ieee802154_tap_phr_fsk_ms_mode_scheme,
3442 &hf_ieee802154_tap_phr_fsk_ms_mode_addl_mode,
3443 &hf_ieee802154_tap_phr_fsk_ms_checksum,
3444 &hf_ieee802154_tap_phr_fsk_ms_parity,
3445 NULL
3447 fields = ieee802154_tap_phr_fsk_ms_addl_fields;
3449 proto_tree_add_bitmask_with_flags(tree, tvb, offset+4, hf_ieee802154_tap_fsk_ms_phr,
3450 ett_ieee802154_tap_phr, fields, ENC_LITTLE_ENDIAN, BMT_NO_TFS);
3451 /* TODO: expert info BCH(15,11) checksum check */
3452 /* TODO: expert info parity check */
3454 else {
3455 static int* const ieee802154_tap_phr_fsk_fields[] = {
3456 &hf_ieee802154_tap_phr_fsk_ms,
3457 &hf_ieee802154_tap_phr_fsk_fcs,
3458 &hf_ieee802154_tap_phr_fsk_dw,
3459 &hf_ieee802154_tap_phr_fsk_length,
3460 NULL
3462 proto_tree_add_bitmask_with_flags(tree, tvb, offset+4, hf_ieee802154_tap_phr_fsk,
3463 ett_ieee802154_tap_phr, ieee802154_tap_phr_fsk_fields, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
3465 break;
3468 case PHR_O_QPSK:
3469 case PHR_CSS:
3470 case PHR_HRP_UWB:
3471 case PHR_MSK:
3472 case PHR_LRP_UWB:
3473 case PHR_SUN_OFDM:
3474 case PHR_SUN_O_QPSK:
3475 case PHR_LECIM_FSK:
3476 case PHR_TVWS_FSK:
3477 case PHR_TVWS_OFDM:
3478 case PHR_TVWS_NB_OFDM:
3479 case PHR_RCC_LMR:
3480 case PHR_CMB_O_QPSK:
3481 case PHR_CMB_GFSK:
3482 case PHR_TASK:
3483 case PHR_RS_GFSK:
3484 /* TODO: write specific dissectors for these PHR types */
3485 /* fall-through with RAW dissection */
3486 case PHR_RAW:
3487 default: {
3488 proto_tree_add_item(tree, hf_ieee802154_tap_phr_data, tvb, offset+4, length-4, ENC_NA);
3489 break;
3495 * Create a tree for a TAP TLV
3497 * @param tree the tree to append this item to
3498 * @param tvb the tv buffer
3499 * @param offset offset into the tvbuff to begin dissection
3500 * @param type TLV type
3501 * @param length TLV length
3502 * @returns the tree created for the Payload IE
3504 static proto_tree*
3505 ieee802154_create_tap_tlv_tree(proto_tree *tree, tvbuff_t *tvb, int offset, uint32_t *type, uint32_t *length)
3507 proto_tree *subtree = NULL;
3508 proto_item *ti = NULL;
3509 uint32_t subtree_length;
3511 *length = tvb_get_letohs(tvb, offset+2);
3513 subtree_length = 4 + *length;
3514 if (*length % 4) {
3515 subtree_length += (4 - *length % 4);
3518 subtree = proto_tree_add_subtree(tree, tvb, offset, subtree_length, ett_ieee802154_tap_tlv, &ti, "");
3520 /* Check if we have a valid TLV */
3521 proto_tree_add_item_ret_uint(subtree, hf_ieee802154_tap_tlv_type, tvb, offset, 2, ENC_LITTLE_ENDIAN, type);
3522 if (*type < array_length(tap_tlv_types)) {
3523 proto_item_append_text(ti, "%s", val_to_str_const(*type, tap_tlv_types, "Unknown"));
3525 else {
3526 expert_add_info(NULL, ti, &ei_ieee802154_tap_tlv_invalid_type);
3529 proto_tree_add_item(subtree, hf_ieee802154_tap_tlv_length, tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
3530 if (!tvb_bytes_exist(tvb, offset+4, *length)) {
3531 expert_add_info(NULL, ti, &ei_ieee802154_tap_tlv_invalid_length);
3533 return subtree;
3534 } /* ieee802154_create_tap_tlv_tree */
3536 static ieee802154_fcs_type_t
3537 dissect_ieee802154_tap_tlvs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3539 uint32_t type;
3540 uint32_t length;
3541 int offset = 0;
3542 proto_item *ti;
3543 proto_tree *tlvtree;
3544 uint32_t tap_fcs_type;
3545 const char *type_str;
3546 nstime_t nstime;
3547 uint64_t frame_start_ts = 0;
3548 uint64_t frame_end_ts = 0;
3549 uint64_t slot_start_ts = 0;
3550 double delta_us = 0;
3551 uint32_t timeslot_length = 0;
3553 /* Default the FCS type to NONE when parsing TAP packets */
3554 tap_fcs_type = IEEE802154_FCS_TYPE_NONE;
3556 while (tvb_bytes_exist(tvb, offset, 4)) {
3557 tlvtree = ieee802154_create_tap_tlv_tree(tree, tvb, offset, &type, &length);
3558 offset += 4;
3560 switch (type) {
3561 case IEEE802154_TAP_FCS_TYPE:
3562 ti = proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_tap_fcs_type, tvb, offset, 1,
3563 ENC_LITTLE_ENDIAN, &tap_fcs_type);
3564 type_str = try_val_to_str(tap_fcs_type, tap_fcs_type_names);
3565 if (type_str == NULL) {
3566 /* Invalid - flag it as such */
3567 expert_add_info(NULL, ti, &ei_ieee802154_tap_tlv_invalid_fcs_type);
3569 /* Use "Unknown" for the parent */
3570 type_str = "Unknown";
3572 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %s (%u)",
3573 type_str, tap_fcs_type);
3574 break;
3575 case IEEE802154_TAP_RSS: {
3576 float rss = tvb_get_ieee_float(tvb, offset, ENC_LITTLE_ENDIAN);
3577 proto_tree_add_float_format_value(tlvtree, hf_ieee802154_tap_rss, tvb, offset, 4, rss, "%.2f dBm", rss);
3578 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %.2f dBm", rss);
3579 break;
3581 case IEEE802154_TAP_BIT_RATE: {
3582 uint32_t bitrate;
3583 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_bit_rate, tvb, offset, 4, ENC_LITTLE_ENDIAN, &bitrate);
3584 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %.3f kbps", bitrate/1000.0);
3585 break;
3587 case IEEE802154_TAP_CHANNEL_ASSIGNMENT: {
3588 uint32_t channel;
3589 uint32_t page;
3590 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_ch_num, tvb, offset, 2, ENC_LITTLE_ENDIAN, &channel);
3591 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_ch_page, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &page);
3592 proto_item_append_text(proto_tree_get_parent(tlvtree), ": Page: %s (%u), Number: %u", val_to_str_const(page, channel_page_names, "Unknown"), page, channel);
3593 break;
3595 case IEEE802154_TAP_SUN_PHY_INFO:
3596 dissect_ieee802154_tap_sun_phy(tvb, pinfo, tlvtree, offset, length);
3597 break;
3598 case IEEE802154_TAP_START_OF_FRAME_TS:
3599 proto_tree_add_item_ret_uint64(tlvtree, hf_ieee802154_sof_ts, tvb, offset, 8,
3600 ENC_LITTLE_ENDIAN, &frame_start_ts);
3601 nstime.secs = (time_t)frame_start_ts / 1000000000L;
3602 nstime.nsecs = frame_start_ts % 1000000000UL;
3603 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %s s", rel_time_to_secs_str(pinfo->pool, &nstime));
3604 break;
3605 case IEEE802154_TAP_END_OF_FRAME_TS:
3606 proto_tree_add_item_ret_uint64(tlvtree, hf_ieee802154_eof_ts, tvb, offset, 8,
3607 ENC_LITTLE_ENDIAN, &frame_end_ts);
3608 nstime.secs = (time_t)frame_end_ts / 1000000000L;
3609 nstime.nsecs = frame_end_ts % 1000000000UL;
3610 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %s s", rel_time_to_secs_str(pinfo->pool, &nstime));
3611 break;
3612 case IEEE802154_TAP_ASN:
3613 proto_tree_add_item_ret_uint64(tlvtree, hf_ieee802154_asn, tvb, offset, 8, ENC_LITTLE_ENDIAN, &ieee802154_tsch_asn);
3614 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %"PRIu64, ieee802154_tsch_asn);
3615 break;
3616 case IEEE802154_TAP_SLOT_START_TS:
3617 proto_tree_add_item_ret_uint64(tlvtree, hf_ieee802154_slot_start_ts, tvb, offset, 8,
3618 ENC_LITTLE_ENDIAN, &slot_start_ts);
3619 nstime.secs = (time_t)slot_start_ts / 1000000000L;
3620 nstime.nsecs = slot_start_ts % 1000000000UL;
3621 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %s s", rel_time_to_secs_str(pinfo->pool, &nstime));
3622 break;
3623 case IEEE802154_TAP_TIMESLOT_LENGTH:
3624 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_tap_timeslot_length, tvb, offset, 4,
3625 ENC_LITTLE_ENDIAN, &timeslot_length);
3626 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %"PRIu32" %s", timeslot_length, units_microseconds.singular);
3627 break;
3628 case IEEE802154_TAP_LQI: {
3629 uint32_t lqi;
3630 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_tap_lqi, tvb, offset, 1, ENC_LITTLE_ENDIAN, &lqi);
3631 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %u", lqi);
3632 break;
3634 case IEEE802154_TAP_CHANNEL_FREQUENCY: {
3635 float freq = tvb_get_ieee_float(tvb, offset, ENC_LITTLE_ENDIAN);
3636 proto_tree_add_float_format_value(tlvtree, hf_ieee802154_ch_freq, tvb, offset, 4, freq, "%.3f kHz", freq);
3637 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %.3f kHz", freq);
3638 break;
3640 case IEEE802154_TAP_CHANNEL_PLAN: {
3641 uint32_t count;
3642 float ch0_freq = tvb_get_ieee_float(tvb, offset, ENC_LITTLE_ENDIAN);
3643 float spacing = tvb_get_ieee_float(tvb, offset+4, ENC_LITTLE_ENDIAN);
3644 proto_tree_add_float_format_value(tlvtree, hf_ieee802154_chplan_start, tvb, offset, 4, ch0_freq, "%.3f kHz", ch0_freq);
3645 proto_item_append_text(proto_tree_get_parent(tlvtree), ": Start %.3f kHz", ch0_freq);
3646 proto_tree_add_float_format_value(tlvtree, hf_ieee802154_chplan_spacing, tvb, offset+4, 4, spacing, "%.3f kHz", spacing);
3647 proto_item_append_text(proto_tree_get_parent(tlvtree), ", Spacing %.3f kHz", spacing);
3648 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_chplan_channels, tvb, offset+8, 2, ENC_LITTLE_ENDIAN, &count);
3649 proto_item_append_text(proto_tree_get_parent(tlvtree), ", Channels %u", count);
3650 break;
3652 case IEEE802154_TAP_PHY_HEADER:
3653 dissect_ieee802154_tap_phy_header(tvb, pinfo, tlvtree, offset, length);
3654 break;
3655 default:
3656 proto_tree_add_item(tlvtree, hf_ieee802154_tap_tlv_unknown, tvb, offset, length, ENC_NA);
3657 proto_item_append_text(proto_tree_get_parent(tlvtree), "Unknown TLV");
3658 break;
3659 } /* switch (tlv_type) */
3661 if (length%4) {
3662 uint32_t zero = 0;
3663 GByteArray *padding = g_byte_array_sized_new(4);
3664 ti = proto_tree_add_bytes_item(tlvtree, hf_ieee802154_tap_tlv_padding, tvb, offset+length, 4-length%4, ENC_NA, padding, NULL, NULL);
3665 if (memcmp(&zero, padding->data, 4-length%4)) {
3666 expert_add_info(NULL, ti, &ei_ieee802154_tap_tlv_padding_not_zeros);
3668 g_byte_array_free(padding, true);
3670 offset += ROUND_UP(length, 4);
3671 } /* while */
3673 /* if we have both slot start and frame start timestamp, show frame start offset */
3674 if (slot_start_ts && frame_start_ts) {
3675 delta_us = (double)(frame_start_ts - slot_start_ts) / 1000;
3676 ti = proto_tree_add_double_format_value(tree, hf_ieee802154_frame_start_offset, NULL, 0, 0, delta_us, "%.3f %s", delta_us, units_microseconds.singular);
3677 proto_item_set_generated(ti);
3680 /* if we have both start and end frame timestamp, show frame duration */
3681 if (frame_start_ts && frame_end_ts) {
3682 delta_us = (double)(frame_end_ts - frame_start_ts) / 1000;
3683 ti = proto_tree_add_double_format_value(tree, hf_ieee802154_frame_duration, NULL, 0, 0, delta_us, "%.3f %s", delta_us, units_microseconds.singular);
3684 proto_item_set_generated(ti);
3687 /* if we have start of slot, timeslot length, and end of frame timestamp, show frame overflow (+ve) or underflow (-ve) */
3688 if (timeslot_length && frame_end_ts && slot_start_ts) {
3689 /* overflow = frame_end_ts - slot_start_ts - timeslot_length */
3690 delta_us = (double)(frame_end_ts - slot_start_ts) / 1000;
3691 delta_us -= timeslot_length;
3692 ti = proto_tree_add_double_format_value(tree, hf_ieee802154_frame_end_offset, NULL, 0, 0, delta_us, "%.3f %s", delta_us, units_microseconds.singular);
3693 proto_item_set_generated(ti);
3696 return (ieee802154_fcs_type_t)tap_fcs_type;
3697 } /* dissect_ieee802154_tap_tlvs */
3700 * Information Elements Processing (IEs)
3704 * Create a tree for a Payload IE incl. the TLV header and append the IE name to the parent item
3706 * @param tvb the tv buffer
3707 * @param tree the tree to append this item to
3708 * @param hf field index
3709 * @param ett tree index
3710 * @returns the tree created for the Payload IE
3712 proto_tree*
3713 ieee802154_create_pie_tree(tvbuff_t *tvb, proto_tree *tree, int hf, int ett)
3715 proto_item *subitem;
3716 proto_tree *subtree;
3717 header_field_info *hfinfo;
3718 static int * const tlv_fields[] = {
3719 &hf_ieee802154_payload_ie_type,
3720 &hf_ieee802154_payload_ie_id,
3721 &hf_ieee802154_payload_ie_length,
3722 NULL
3725 subitem = proto_tree_add_item(tree, hf, tvb, 0, tvb_reported_length(tvb), ENC_NA);
3726 subtree = proto_item_add_subtree(subitem, ett);
3727 proto_tree_add_bitmask_with_flags(subtree, tvb, 0, hf_ieee802154_payload_ie_tlv, ett_ieee802154_payload_ie_tlv,
3728 tlv_fields, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
3730 hfinfo = proto_registrar_get_nth(hf);
3731 if (hfinfo && hfinfo->name) {
3732 proto_item_append_text(proto_tree_get_parent(tree), ", %s", hfinfo->name);
3734 return subtree;
3738 * Create a tree for a Payload Sub-IE incl. the TLV header and append the IE name to the parent item
3740 * @param tvb the tv buffer
3741 * @param tree the tree to append this item to
3742 * @param hf field index
3743 * @param ett tree index
3744 * @returns the tree created for the Payload IE
3746 static proto_tree*
3747 ieee802154_create_psie_tree(tvbuff_t *tvb, proto_tree *tree, int hf, int ett)
3749 proto_item *subitem;
3750 proto_tree *subtree;
3751 header_field_info *hfinfo;
3753 subitem = proto_tree_add_item(tree, hf, tvb, 0, tvb_reported_length(tvb), ENC_NA);
3754 subtree = proto_item_add_subtree(subitem, ett);
3755 if (tvb_get_letohs(tvb, 0) & IEEE802154_PSIE_TYPE_MASK) {
3756 static int * const fields_long[] = {
3757 &hf_ieee802154_psie_type,
3758 &hf_ieee802154_psie_id_long,
3759 &hf_ieee802154_psie_length_long,
3760 NULL
3762 proto_tree_add_bitmask(subtree, tvb, 0, hf_ieee802154_psie, ett_ieee802154_psie, fields_long, ENC_LITTLE_ENDIAN);
3764 else {
3765 static int * const fields_short[] = {
3766 &hf_ieee802154_psie_type,
3767 &hf_ieee802154_psie_id_short,
3768 &hf_ieee802154_psie_length_short,
3769 NULL
3771 proto_tree_add_bitmask(subtree, tvb, 0, hf_ieee802154_psie, ett_ieee802154_psie, fields_short, ENC_LITTLE_ENDIAN);
3774 hfinfo = proto_registrar_get_nth(hf);
3775 if (hfinfo && hfinfo->name) {
3776 proto_item_append_text(proto_tree_get_parent(tree), ", %s", hfinfo->name);
3778 return subtree;
3782 * Subdissector for the MLME Channel Hopping Payload IE
3784 static int
3785 dissect_802154_channel_hopping(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3787 proto_tree *subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_tsch_channel_hopping, ett_ieee802154_mlme_payload);
3789 proto_tree_add_item(subtree, hf_ieee802154_tsch_hopping_sequence_id, tvb, 2, 1, ENC_LITTLE_ENDIAN);
3791 if (tvb_reported_length_remaining(tvb, 3) > 1) {
3792 /* TODO: There's still a huge amount of optional stuff that could follow */
3793 proto_tree_add_item(subtree, hf_ieee802154_mlme_ie_data, tvb, 3, tvb_reported_length_remaining(tvb, 3), ENC_NA);
3795 return tvb_reported_length(tvb);
3796 } /* dissect_802154_channel_hopping */
3799 * Subdissector for the Nested MLME IE for TSCH Synchronization
3801 static int
3802 dissect_802154_tsch_time_sync(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3804 proto_tree *subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_tsch_sync, ett_ieee802154_tsch_synch);
3806 proto_tree_add_item(subtree, hf_ieee802154_tsch_asn, tvb, 2, 5, ENC_LITTLE_ENDIAN);
3807 proto_tree_add_item(subtree, hf_ieee802154_tsch_join_metric, tvb, 7, 1, ENC_LITTLE_ENDIAN);
3808 return 8;
3809 }/* dissect_802154_tsch_time_sync*/
3812 * Subdissector for the Nested MLME IE for TSCH Slotframe and Link
3814 static int
3815 dissect_802154_tsch_slotframe_link(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3817 uint8_t nb_slotframes;
3818 uint8_t slotframe_index;
3819 proto_tree *subtree;
3820 unsigned offset = 0;
3822 subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_tsch_slotframe, ett_ieee802154_tsch_slotframe);
3823 offset += 2;
3825 nb_slotframes = tvb_get_uint8(tvb, offset);
3826 proto_tree_add_item(subtree, hf_ieee802154_tsch_slotf_link_nb_slotf, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3827 offset += 1;
3829 for (slotframe_index = 1; slotframe_index <= nb_slotframes; slotframe_index++) {
3830 /* Create a tree for the slotframe. */
3831 uint8_t nb_links = tvb_get_uint8(tvb, offset + 3);
3832 proto_item *sf_item = proto_tree_add_subtree_format(subtree, tvb, offset, 4 + (5 * nb_links),
3833 ett_ieee802154_tsch_slotframe, NULL,
3834 "Slotframes [%u]", slotframe_index);
3835 proto_tree *sf_tree = proto_item_add_subtree(sf_item, ett_ieee802154_tsch_slotframe_list);
3836 proto_tree_add_item(sf_tree, hf_ieee802154_tsch_slotf_link_slotf_handle, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3837 proto_tree_add_item(sf_tree, hf_ieee802154_tsch_slotf_size, tvb, offset + 1, 2, ENC_LITTLE_ENDIAN);
3838 proto_tree_add_item(sf_tree, hf_ieee802154_tsch_slotf_link_nb_links, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
3840 /* Create a tree for each link in the slotframe. */
3841 offset += 4;
3842 while (nb_links > 0) {
3843 static int * const fields_options[] = {
3844 &hf_ieee802154_tsch_slotf_link_options_tx,
3845 &hf_ieee802154_tsch_slotf_link_options_rx,
3846 &hf_ieee802154_tsch_slotf_link_options_shared,
3847 &hf_ieee802154_tsch_slotf_link_options_timkeeping,
3848 &hf_ieee802154_tsch_slotf_link_options_priority,
3849 NULL
3852 proto_item *link_item = proto_tree_add_item(sf_tree, hf_ieee802154_tsch_link_info, tvb, offset, 5, ENC_NA);
3853 proto_tree *link_tree = proto_item_add_subtree(link_item, ett_ieee802154_tsch_slotframe_link);
3854 proto_tree_add_item(link_tree, hf_ieee802154_tsch_slotf_link_timeslot, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3855 proto_tree_add_item(link_tree, hf_ieee802154_tsch_slotf_link_channel_offset, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
3856 proto_tree_add_bitmask(link_tree, tvb, offset + 4, hf_ieee802154_tsch_slotf_link_options, ett_ieee802154_tsch_slotframe_link_options, fields_options, ENC_LITTLE_ENDIAN);
3857 nb_links -= 1;
3858 offset += 5;
3862 return offset;
3863 }/* dissect_802154_tsch_slotframe_link */
3866 * Subdissector for the Nested MLME IE for TSCH Timeslot Description
3868 static int
3869 dissect_802154_tsch_timeslot(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3871 proto_tree *subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_tsch_timeslot, ett_ieee802154_tsch_timeslot);
3872 unsigned offset = 2;
3874 proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_id, tvb, 2, 1, ENC_LITTLE_ENDIAN);
3875 offset++;
3877 if (tvb_reported_length(tvb) > offset) {
3878 const int timeslot_fields[] = {
3879 hf_ieee802154_tsch_timeslot_cca_offset,
3880 hf_ieee802154_tsch_timeslot_cca,
3881 hf_ieee802154_tsch_timeslot_tx_offset,
3882 hf_ieee802154_tsch_timeslot_rx_offset,
3883 hf_ieee802154_tsch_timeslot_rx_ack_delay,
3884 hf_ieee802154_tsch_timeslot_tx_ack_delay,
3885 hf_ieee802154_tsch_timeslot_rx_wait,
3886 hf_ieee802154_tsch_timeslot_ack_wait,
3887 hf_ieee802154_tsch_timeslot_turnaround,
3888 hf_ieee802154_tsch_timeslot_max_ack,
3890 unsigned int i;
3891 for (i = 0; i < array_length(timeslot_fields); i++) {
3892 proto_tree_add_item(subtree, timeslot_fields[i], tvb, offset, 2, ENC_LITTLE_ENDIAN);
3893 offset += 2;
3896 /* The last two fields are may have different encodings depending on the length of the IE. */
3897 if (tvb_reported_length_remaining(tvb, offset) > 4) {
3898 proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_max_tx, tvb, offset, 3, ENC_LITTLE_ENDIAN);
3899 offset += 3;
3900 proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_length, tvb, offset, 3, ENC_LITTLE_ENDIAN);
3901 offset += 3;
3903 else {
3904 proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_max_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3905 offset += 2;
3906 proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3907 offset += 2;
3910 return offset;
3911 } /* dissect_802154_tsch_timeslot */
3914 * Subdissector for the 6TOP Protocol contained within the Payload Information Elements.
3916 static int
3917 dissect_ietf_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ies_tree, void *data _U_)
3919 const uint8_t supported_6p_version = 0x00;
3921 proto_tree *p_inf_elem_tree = ieee802154_create_pie_tree(tvb, ies_tree, hf_ieee802154_pie_ietf, ett_ieee802154_pie_ietf);
3922 unsigned offset = 2;
3923 unsigned pie_length = tvb_reported_length(tvb) - 2;
3924 uint8_t version;
3925 uint8_t type;
3926 uint8_t code;
3927 uint8_t num_cells = 0;
3928 bool have_cell_list = false;
3929 int i;
3930 proto_item *sixtop_item = NULL;
3931 proto_tree *sixtop_tree = NULL;
3932 proto_item *cell_list_item = NULL;
3933 proto_tree *cell_list_tree = NULL;
3934 proto_item *cell_item = NULL;
3935 proto_tree *cell_tree = NULL;
3936 proto_item *type_item = NULL;
3937 proto_item *code_item = NULL;
3938 const char *code_str = NULL;
3939 static int * const cell_options[] = {
3940 &hf_ieee802154_6top_cell_option_tx,
3941 &hf_ieee802154_6top_cell_option_rx,
3942 &hf_ieee802154_6top_cell_option_shared,
3943 &hf_ieee802154_6top_cell_option_reserved,
3944 NULL
3947 if (pie_length < 5) {
3948 return pie_length + 2;
3951 version = tvb_get_uint8(tvb, offset + 1) & IETF_6TOP_VERSION;
3953 if (version != supported_6p_version) {
3954 return pie_length + 2;
3957 type = (tvb_get_uint8(tvb, offset + 1) & IETF_6TOP_TYPE) >> 4;
3958 code = tvb_get_uint8(tvb, offset + 2);
3960 proto_tree_add_item(p_inf_elem_tree, hf_ieee802154_p_ie_ietf_sub_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3962 sixtop_item = proto_tree_add_item(p_inf_elem_tree, hf_ieee802154_6top, tvb, offset, pie_length, ENC_NA);
3963 sixtop_tree = proto_item_add_subtree(sixtop_item, ett_ieee802154_p_ie_6top);
3965 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_version, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
3966 type_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_type, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
3967 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_flags_reserved, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
3968 code_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_code, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
3969 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_sfid, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
3970 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_seqnum, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
3972 col_set_str(pinfo->cinfo, COL_PROTOCOL, "6top");
3973 if (type == IETF_6TOP_TYPE_REQUEST) {
3974 code_str = val_to_str_const(code, ietf_6top_command_identifiers,"Unknown");
3975 col_add_fstr(pinfo->cinfo, COL_INFO, "6P %s Request", code_str);
3976 } else {
3977 code_str = val_to_str_const(code, ietf_6top_return_codes,"Unknown");
3978 col_add_fstr(pinfo->cinfo, COL_INFO, "6P %s (%s)",
3979 val_to_str_const(type, ietf_6top_types,"Unknown"), code_str);
3981 proto_item_append_text(code_item, " (%s)", code_str);
3983 offset += 5;
3984 pie_length -= 5;
3986 if (type == IETF_6TOP_TYPE_REQUEST) {
3987 switch (code) {
3988 case IETF_6TOP_CMD_ADD:
3989 case IETF_6TOP_CMD_DELETE:
3990 case IETF_6TOP_CMD_RELOCATE:
3991 if (pie_length < 4) {
3992 break;
3994 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3995 proto_tree_add_bitmask(sixtop_tree, tvb, offset + 2, hf_ieee802154_6top_cell_options, ett_ieee802154_p_ie_6top_cell_options, cell_options, ENC_LITTLE_ENDIAN);
3996 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_num_cells, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
3997 num_cells = tvb_get_uint8(tvb, offset + 3);
3998 pie_length -= 4;
3999 offset += 4;
4000 if (pie_length > 0 && (pie_length % 4) == 0) {
4001 have_cell_list = true;
4003 break;
4004 case IETF_6TOP_CMD_COUNT:
4005 if (pie_length < 3) {
4006 break;
4008 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4009 proto_tree_add_bitmask(sixtop_tree, tvb, offset + 2, hf_ieee802154_6top_cell_options, ett_ieee802154_p_ie_6top_cell_options, cell_options, ENC_LITTLE_ENDIAN);
4010 pie_length -= 3;
4011 offset += 3;
4012 break;
4013 case IETF_6TOP_CMD_LIST:
4014 if (pie_length != 8) {
4015 break;
4017 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4018 proto_tree_add_bitmask(sixtop_tree, tvb, offset + 2, hf_ieee802154_6top_cell_options, ett_ieee802154_p_ie_6top_cell_options, cell_options, ENC_LITTLE_ENDIAN);
4019 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_reserved, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
4020 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_offset, tvb, offset + 4, 2, ENC_LITTLE_ENDIAN);
4021 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_max_num_cells, tvb, offset + 6, 2, ENC_LITTLE_ENDIAN);
4022 pie_length -= 8;
4023 offset += 8;
4024 break;
4025 case IETF_6TOP_CMD_SIGNAL:
4026 if (pie_length < 2) {
4027 break;
4029 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4030 if (pie_length > 2) {
4031 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_payload, tvb, offset + 2, pie_length - 2, ENC_NA);
4033 offset += pie_length;
4034 pie_length = 0;
4035 break;
4036 case IETF_6TOP_CMD_CLEAR:
4037 if (pie_length < 2) {
4038 break;
4040 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4041 pie_length -= 2;
4042 offset += 2;
4043 break;
4044 default:
4045 /* unsupported command */
4046 expert_add_info(pinfo, code_item, &ei_ieee802154_6top_unsupported_command);
4047 break;
4049 } else if (type == IETF_6TOP_TYPE_RESPONSE || type == IETF_6TOP_TYPE_CONFIRMATION) {
4050 switch(code) {
4051 case IETF_6TOP_RC_SUCCESS:
4052 if (pie_length > 0) {
4053 if (pie_length == 2) {
4054 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_total_num_cells, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4055 pie_length -= 2;
4056 offset += 2;
4057 } else if ((pie_length % 4) == 0) {
4058 have_cell_list = true;
4059 } else {
4060 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_payload, tvb, offset, pie_length, ENC_NA);
4061 offset += pie_length;
4062 pie_length = 0;
4065 break;
4066 case IETF_6TOP_RC_EOL:
4067 if(pie_length > 0 && (pie_length % 4) == 0) {
4068 have_cell_list = true;
4070 break;
4071 case IETF_6TOP_RC_ERR:
4072 case IETF_6TOP_RC_RESET:
4073 case IETF_6TOP_RC_ERR_VERSION:
4074 case IETF_6TOP_RC_ERR_SFID:
4075 case IETF_6TOP_RC_ERR_SEQNUM:
4076 case IETF_6TOP_RC_ERR_CELLLIST:
4077 case IETF_6TOP_RC_ERR_BUSY:
4078 case IETF_6TOP_RC_ERR_LOCKED:
4079 /* They have no other field */
4080 break;
4081 default:
4082 /* unsupported return code */
4083 expert_add_info(pinfo, code_item, &ei_ieee802154_6top_unsupported_return_code);
4084 break;
4086 } else {
4087 /* unsupported type */
4088 expert_add_info(pinfo, type_item, &ei_ieee802154_6top_unsupported_type);
4091 if (have_cell_list) {
4092 if (type == IETF_6TOP_TYPE_REQUEST && code == IETF_6TOP_CMD_RELOCATE) {
4093 cell_list_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_rel_cell_list, tvb, offset, pie_length, ENC_NA);
4094 cell_list_tree = proto_item_add_subtree(cell_list_item, ett_ieee802154_p_ie_6top_rel_cell_list);
4095 /* num_cells is expected to be set properly */
4096 for (i = 0; i < num_cells; offset += 4, i++) {
4097 cell_item = proto_tree_add_item(cell_list_tree, hf_ieee802154_6top_cell, tvb, offset, 4, ENC_NA);
4098 cell_tree = proto_item_add_subtree(cell_item, ett_ieee802154_p_ie_6top_cell);
4099 proto_tree_add_item(cell_tree, hf_ieee802154_6top_slot_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4100 proto_tree_add_item(cell_tree, hf_ieee802154_6top_channel_offset, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
4102 pie_length -= num_cells * 4;
4103 cell_list_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_cand_cell_list, tvb, offset, pie_length, ENC_NA);
4104 cell_list_tree = proto_item_add_subtree(cell_list_item, ett_ieee802154_p_ie_6top_cand_cell_list);
4105 for (i = 0; pie_length > 0; pie_length -= 4, offset += 4, i++) {
4106 cell_item = proto_tree_add_item(cell_list_tree, hf_ieee802154_6top_cell, tvb, offset, 4, ENC_NA);
4107 cell_tree = proto_item_add_subtree(cell_item, ett_ieee802154_p_ie_6top_cell);
4108 proto_tree_add_item(cell_tree, hf_ieee802154_6top_slot_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4109 proto_tree_add_item(cell_tree, hf_ieee802154_6top_channel_offset, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
4111 } else {
4112 cell_list_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_cell_list, tvb, offset, pie_length, ENC_NA);
4113 cell_list_tree = proto_item_add_subtree(cell_list_item, ett_ieee802154_p_ie_6top_cell_list);
4114 for (i = 0; pie_length > 0; pie_length -= 4, offset += 4, i++) {
4115 cell_item = proto_tree_add_item(cell_list_tree, hf_ieee802154_6top_cell, tvb, offset, 4, ENC_NA);
4116 cell_tree = proto_item_add_subtree(cell_item, ett_ieee802154_p_ie_6top_cell);
4117 proto_tree_add_item(cell_tree, hf_ieee802154_6top_slot_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4118 proto_tree_add_item(cell_tree, hf_ieee802154_6top_channel_offset, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
4123 return offset;
4124 } /* dissect_ieee802154_6top */
4127 * Subdissector for the Superframe specification sub-field within the beacon frame.
4129 * @param tvb pointer to buffer containing raw packet.
4130 * @param pinfo pointer to packet information fields (unused).
4131 * @param tree pointer to command subtree.
4132 * @param offset offset into the tvbuff to begin dissection.
4134 void
4135 dissect_ieee802154_superframe(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned *offset)
4137 static int * const superframe[] = {
4138 &hf_ieee802154_beacon_order,
4139 &hf_ieee802154_superframe_order,
4140 &hf_ieee802154_cap,
4141 &hf_ieee802154_superframe_battery_ext,
4142 &hf_ieee802154_superframe_coord,
4143 &hf_ieee802154_assoc_permit,
4144 NULL
4147 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);
4148 (*offset) += 2;
4149 } /* dissect_ieee802154_superframe */
4152 * Subdissector for the GTS information fields within the beacon frame.
4154 * @param tvb pointer to buffer containing raw packet.
4155 * @param pinfo pointer to packet information fields (unused).
4156 * @param tree pointer to command subtree.
4157 * @param offset offset into the tvbuff to begin dissection.
4159 void
4160 dissect_ieee802154_gtsinfo(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned *offset)
4162 proto_tree *field_tree = NULL;
4163 proto_tree *subtree = NULL;
4164 proto_item *ti;
4165 uint8_t gts_spec;
4166 uint8_t gts_count;
4168 /* Get and display the GTS specification field */
4169 gts_spec = tvb_get_uint8(tvb, *offset);
4170 gts_count = gts_spec & IEEE802154_GTS_COUNT_MASK;
4171 if (tree) {
4172 /* Add Subtree for GTS information. */
4173 if (gts_count) {
4174 field_tree = proto_tree_add_subtree(tree, tvb, *offset, 2 + (gts_count * 3), ett_ieee802154_gts, NULL, "GTS");
4176 else {
4177 field_tree = proto_tree_add_subtree(tree, tvb, *offset, 1, ett_ieee802154_gts, NULL, "GTS");
4180 proto_tree_add_uint(field_tree, hf_ieee802154_gts_count, tvb, *offset, 1, gts_count);
4181 proto_tree_add_boolean(field_tree, hf_ieee802154_gts_permit, tvb, *offset, 1, gts_spec & IEEE802154_GTS_PERMIT_MASK);
4183 (*offset) += 1;
4185 /* If the GTS descriptor count is nonzero, then the GTS directions mask and descriptor list are present. */
4186 if (gts_count) {
4187 uint8_t gts_directions = tvb_get_uint8(tvb, *offset);
4188 unsigned gts_rx = 0;
4189 int i;
4191 /* Display the directions mask. */
4192 if (tree) {
4193 proto_tree *dir_tree;
4195 /* Create a subtree. */
4196 dir_tree = proto_tree_add_subtree(field_tree, tvb, *offset, 1, ett_ieee802154_gts_direction, &ti, "GTS Directions");
4198 /* Add the directions to the subtree. */
4199 for (i=0; i<gts_count; i++) {
4200 bool dir = gts_directions & IEEE802154_GTS_DIRECTION_SLOT(i);
4201 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");
4202 if (dir) gts_rx++;
4203 } /* for */
4204 proto_item_append_text(ti, ": %i Receive & %i Transmit", gts_rx, gts_count - gts_rx);
4206 (*offset) += 1;
4208 /* Create a subtree for the GTS descriptors. */
4209 subtree = proto_tree_add_subtree(field_tree, tvb, *offset, gts_count * 3, ett_ieee802154_gts_descriptors, NULL, "GTS Descriptors");
4211 /* Get and display the GTS descriptors. */
4212 for (i=0; i<gts_count; i++) {
4213 uint16_t gts_addr = tvb_get_letohs(tvb, (*offset));
4214 uint8_t gts_slot = tvb_get_uint8(tvb, (*offset)+2);
4215 uint8_t gts_length = (gts_slot & IEEE802154_GTS_LENGTH_MASK) >> IEEE802154_GTS_LENGTH_SHIFT;
4217 gts_slot = (gts_slot & IEEE802154_GTS_SLOT_MASK);
4219 if (tree) {
4220 /* Add address, slot, and time length fields. */
4221 ti = proto_tree_add_uint(subtree, hf_ieee802154_gts_address, tvb, (*offset), 3, gts_addr);
4222 proto_item_append_text(ti, ", Slot: %i", gts_slot);
4223 proto_item_append_text(ti, ", Length: %i", gts_length);
4225 (*offset) += 3;
4226 } /* for */
4228 } /* dissect_ieee802154_gtsinfo */
4231 * Subdissector for the pending address list fields within the beacon frame.
4233 * @param tvb pointer to buffer containing raw packet.
4234 * @param pinfo pointer to packet information fields (unused).
4235 * @param tree pointer to command subtree.
4236 * @param offset into the tvbuff to begin dissection.
4238 void
4239 dissect_ieee802154_pendaddr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned *offset)
4241 proto_tree *subtree;
4242 uint8_t pend_spec;
4243 uint8_t pend_num16;
4244 uint8_t pend_num64;
4245 int i;
4247 /* Get the Pending Addresses specification fields */
4248 pend_spec = tvb_get_uint8(tvb, *offset);
4249 pend_num16 = pend_spec & IEEE802154_PENDADDR_SHORT_MASK;
4250 pend_num64 = (pend_spec & IEEE802154_PENDADDR_LONG_MASK) >> IEEE802154_PENDADDR_LONG_SHIFT;
4252 /* Add Subtree for the addresses */
4253 subtree = proto_tree_add_subtree_format(tree, tvb, *offset, 1 + 2*pend_num16 + 8*pend_num64,
4254 ett_ieee802154_pendaddr, NULL, "Pending Addresses: %i Short and %i Long", pend_num16, pend_num64);
4255 (*offset) += 1;
4257 for (i=0; i<pend_num16; i++) {
4258 uint16_t addr = tvb_get_letohs(tvb, *offset);
4259 proto_tree_add_uint(subtree, hf_ieee802154_pending16, tvb, *offset, 2, addr);
4260 (*offset) += 2;
4261 } /* for */
4262 for (i=0; i<pend_num64; i++) {
4263 proto_tree_add_item(subtree, hf_ieee802154_pending64, tvb, *offset, 8, ENC_LITTLE_ENDIAN);
4264 (*offset) += 8;
4265 } /* for */
4266 } /* dissect_ieee802154_pendaddr */
4269 * Header IEs
4273 * Create a tree for a Header IE incl. the TLV header and append the IE name to the parent item
4275 * @param tvb the tv buffer
4276 * @param tree the tree to append this item to
4277 * @param hf field index
4278 * @param ett tree index
4279 * @returns the tree created for the Header IE
4281 proto_tree*
4282 ieee802154_create_hie_tree(tvbuff_t *tvb, proto_tree *tree, int hf, int ett)
4284 proto_item *subitem;
4285 proto_tree *subtree;
4286 header_field_info *hfinfo;
4287 static int * const tlv_fields[] = {
4288 &hf_ieee802154_header_ie_type,
4289 &hf_ieee802154_header_ie_id,
4290 &hf_ieee802154_header_ie_length,
4291 NULL
4294 subitem = proto_tree_add_item(tree, hf, tvb, 0, tvb_reported_length(tvb), ENC_NA);
4295 subtree = proto_item_add_subtree(subitem, ett);
4296 proto_tree_add_bitmask_with_flags(subtree, tvb, 0, hf_ieee802154_header_ie_tlv, ett_ieee802154_header_ie_tlv,
4297 tlv_fields, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
4299 hfinfo = proto_registrar_get_nth(hf);
4300 if (hfinfo && hfinfo->name) {
4301 proto_item_append_text(proto_tree_get_parent(tree), ", %s", hfinfo->name);
4303 return subtree;
4307 * The dissectors for the individual Header IEs
4308 * They are called via call_dissector with the tvb including the IE header and data as ieee802154_packet
4312 * Dissect the CSL IE (7.4.2.3)
4314 static int
4315 dissect_hie_csl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
4317 proto_tree *subtree = ieee802154_create_hie_tree(tvb, tree, hf_ieee802154_hie_csl, ett_ieee802154_hie_csl);
4318 proto_tree_add_item(subtree, hf_ieee802154_hie_csl_phase, tvb, 2, 2, ENC_LITTLE_ENDIAN);
4319 proto_tree_add_item(subtree, hf_ieee802154_hie_csl_period, tvb, 4, 2, ENC_LITTLE_ENDIAN);
4320 if (tvb_reported_length(tvb) >= 8) {
4321 proto_tree_add_item(subtree, hf_ieee802154_hie_csl_rendezvous_time, tvb, 6, 2, ENC_LITTLE_ENDIAN);
4322 return 2 + 6;
4324 return 2 + 4;
4328 * Dissect the Rendez-Vous Time IE (7.4.2.6)
4329 * The IE is made of 2 fields:
4330 * - RendezVous Time: in 802.15.4-2015, this is exactly the same field as in the CSL IE
4331 * - Wake-Up Interval: the spec text is unclear about the field being optional or not. This dissector assumes it is
4333 static int
4334 dissect_hie_rendezvous_time(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
4336 proto_tree *subtree = ieee802154_create_hie_tree(tvb, tree, hf_ieee802154_hie_rdv, ett_ieee802154_hie_rdv);
4338 // reuse field from CSL IE
4339 proto_tree_add_item(subtree, hf_ieee802154_hie_csl_rendezvous_time, tvb, 2, 2, ENC_LITTLE_ENDIAN);
4341 // In 802.15.4-2015, Rendez-Vous Time IE is only present in CSL Wake-Up Frames
4342 // Update the packet information
4343 col_set_str(pinfo->cinfo, COL_INFO, "CSL Wake-up Frame");
4344 col_append_fstr(pinfo->cinfo, COL_INFO, ", Rendez-Vous Time: %d", tvb_get_uint16(tvb, 2, ENC_LITTLE_ENDIAN));
4346 // Assume Wake-Up Interval is optional. Spec says "only present [...] when macCslInterval is nonzero"
4347 if (tvb_reported_length(tvb) >= 6) {
4348 proto_tree_add_item(subtree, hf_ieee802154_hie_rdv_wakeup_interval, tvb, 4, 2, ENC_LITTLE_ENDIAN);
4349 return 2 + 4;
4352 return 2 + 2;
4356 * Dissect the Time Correction Header IE (7.4.2.7)
4358 * This field is constructed by taking a signed 16-bit 2's compliment time
4359 * correction in the range of -2048 us to 2047 us, AND'ing it with 0xfff, and
4360 * OR'ing again with 0x8000 to indicate a negative acknowledgment.
4362 static int
4363 dissect_hie_time_correction(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ies_tree, void *data _U_)
4365 static int * const fields[] = {
4366 &hf_ieee802154_hie_time_correction_value,
4367 &hf_ieee802154_nack,
4368 NULL
4370 proto_tree *tree = ieee802154_create_hie_tree(tvb, ies_tree, hf_ieee802154_hie_time_correction, ett_ieee802154_hie_time_correction);
4371 uint16_t time_sync_value = tvb_get_letohs(tvb, 2);
4372 proto_tree_add_bitmask_with_flags(tree, tvb, 2, hf_ieee802154_hie_time_correction_time_sync_info, ett_ieee802154_header_ie,
4373 fields, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
4375 if (time_sync_value & ~(0x8fff)) {
4376 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802154_time_correction_error);
4378 if (time_sync_value & 0x8000) {
4379 proto_item_append_text(proto_tree_get_parent(ies_tree), ": NACK");
4381 return 2 + 2;
4384 static int
4385 dissect_hie_global_time(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
4387 proto_tree *subtree = ieee802154_create_hie_tree(tvb, tree, hf_ieee802154_hie_global_time, ett_ieee802154_hie_global_time);
4388 proto_tree_add_item(subtree, hf_ieee802154_hie_global_time_value, tvb, 2, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
4389 return 2 + 4;
4393 * Dissect the Vendor Specific IE (7.4.2.2)
4395 static int
4396 dissect_hie_vendor_specific(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
4398 proto_tree *subtree = ieee802154_create_hie_tree(tvb, tree, hf_ieee802154_hie_vendor_specific,
4399 ett_ieee802154_hie_vendor_specific);
4401 unsigned hie_length = tvb_reported_length(tvb) - 2;
4402 unsigned offset = 2;
4404 tvb_get_letoh24(tvb, offset);
4405 proto_tree_add_item(subtree, hf_ieee802154_hie_vendor_specific_vendor_oui, tvb, offset, 3, ENC_LITTLE_ENDIAN);
4406 offset += 3; /* adjust for vendor OUI */
4407 hie_length -= 3;
4409 proto_tree_add_item(subtree, hf_ieee802154_hie_vendor_specific_content, tvb, offset, hie_length, ENC_NA);
4411 return tvb_reported_length(tvb);
4415 Subdissector for Vendor Specific Header IEs (Information Elements)
4417 static int
4418 dissect_ie_vendor(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ies_tree, void *data _U_)
4420 proto_tree *tree = ieee802154_create_pie_tree(tvb, ies_tree, hf_ieee802154_pie_vendor, ett_ieee802154_pie_vendor);
4422 unsigned offset = 2;
4423 unsigned pie_length = tvb_reported_length(tvb) - 2;
4424 tvbuff_t *next_tvb;
4425 uint32_t vendor_oui;
4427 vendor_oui = tvb_get_letoh24(tvb, offset);
4428 proto_tree_add_item(tree, hf_ieee802154_pie_vendor_oui, tvb, offset, 3, ENC_LITTLE_ENDIAN);
4429 offset += 3; /* adjust for vendor OUI */
4430 pie_length -= 3;
4431 next_tvb = tvb_new_subset_length(tvb, offset, pie_length);
4433 switch (vendor_oui) {
4434 case OUI_THREAD:
4435 /*Decoding vendor variable data */
4436 proto_tree_add_item(tree, hf_ieee802154_pie_vendor_variable, tvb, offset, pie_length, ENC_NA);
4437 break;
4439 default:
4440 call_data_dissector(next_tvb, pinfo, tree);
4441 break;
4444 return tvb_reported_length(tvb);
4448 * Subdissector for Header IEs (Information Elements)
4450 * Since the header is never encrypted and the payload may be encrypted,
4451 * we dissect header and payload IEs separately.
4452 * The termination of the Header IE tells us whether there are any
4453 * payload IEs to follow.
4455 * @param tvb the tv buffer
4456 * @param pinfo pointer to packet information fields.
4457 * @param tree the tree to append this item to
4458 * @param orig_offset offset into the tvbuff to begin dissection.
4459 * @param packet IEEE 802.15.4 packet information.
4461 static int
4462 dissect_ieee802154_header_ie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned orig_offset, ieee802154_packet *packet)
4464 // GCC emits a spurious -Wclobbered if offset is used as function parameter (even with volatile)
4465 volatile unsigned offset = orig_offset;
4466 proto_item *ies_item = proto_tree_add_item(tree, hf_ieee802154_header_ies, tvb, offset, -1, ENC_NA);
4467 proto_tree *ies_tree = proto_item_add_subtree(ies_item, ett_ieee802154_header_ie);
4468 volatile int remaining = tvb_reported_length_remaining(tvb, offset) - IEEE802154_MIC_LENGTH(packet->security_level);
4470 // Loop as long as we don't:
4472 // 1) run out of data;
4473 // 2) get a header termination IE.
4475 // See Table 9-6 "Termination IE inclusion rules" of IEEE Std 802.15.4-2015;
4476 // unless we have no payload IEs and no payload data, we *have* to have
4477 // a header termination IE to end the list of header IEs, so the "run out
4478 // of data" check needs only to check whether there's any data
4479 // left in the tvbuff (which has already had the FCS removed from
4480 // it), other than a MIC if present - if we have no payload IEs or
4481 // payload data, there might still be a MIC to Check the Message
4482 // Integrity.
4484 // XXX - we should make sure we have enough data left for an IE header,
4485 // and report a malformed frame if not, and if we do have enough data,
4486 // make sure we have enough data for the full IE, and report a malformed
4487 // frame if not.
4488 do {
4489 volatile int consumed = 0;
4490 uint16_t ie_header = tvb_get_letohs(tvb, offset);
4491 uint16_t id = (uint16_t) ((ie_header & IEEE802154_HEADER_IE_ID_MASK) >> 7);
4492 uint16_t length = (uint16_t) (ie_header & IEEE802154_HEADER_IE_LENGTH_MASK);
4493 tvbuff_t * volatile ie_tvb = tvb_new_subset_length(tvb, offset, 2 + length);
4495 if (id == IEEE802154_HEADER_IE_HT1 || id == IEEE802154_HEADER_IE_HT2) {
4496 int hf_term_ie = (id == IEEE802154_HEADER_IE_HT1) ? hf_ieee802154_hie_ht1 : hf_ieee802154_hie_ht2;
4497 ieee802154_create_hie_tree(ie_tvb, ies_tree, hf_term_ie, ett_ieee802154_hie_ht);
4498 consumed = 2;
4499 } else if (id == IEEE802154_HEADER_IE_VENDOR_SPECIFIC) {
4500 ieee802154_create_hie_tree(ie_tvb, ies_tree, hf_ieee802154_hie_thread, ett_ieee802154_hie_thread);
4501 dissect_ie_vendor(ie_tvb, pinfo, ies_tree, packet);
4502 consumed = 2 + length;
4503 } else {
4504 TRY {
4505 consumed = dissector_try_uint_with_data(header_ie_dissector_table, id, ie_tvb, pinfo, ies_tree, false, packet);
4506 if (consumed == 0) {
4507 proto_tree *subtree = ieee802154_create_hie_tree(ie_tvb, ies_tree, hf_ieee802154_hie_unsupported,
4508 ett_ieee802154_hie_unsupported);
4509 proto_tree_add_item(subtree, hf_ieee802154_ie_unknown_content, ie_tvb, 2, length, ENC_NA);
4510 consumed = 2 + length;
4511 if (ie_header & IEEE802154_PAYLOAD_IE_TYPE_MASK) {
4512 expert_add_info(pinfo, ies_tree, &ei_ieee802154_payload_ie_in_header);
4513 } else {
4514 expert_add_info(pinfo, ies_tree, &ei_ieee802154_ie_unsupported_id);
4518 CATCH_ALL {
4519 show_exception(tvb, pinfo, ies_tree, EXCEPT_CODE, GET_MESSAGE);
4520 consumed = 2 + length;
4522 ENDTRY;
4525 if (consumed < 2 + length) {
4526 proto_tree_add_item(ies_tree, hf_ieee802154_ie_unknown_content, ie_tvb, consumed, 2 + length - consumed, ENC_NA);
4527 expert_add_info(pinfo, ies_item, &ei_ieee802154_ie_unknown_extra_content);
4530 offset += 2 + length;
4531 remaining -= 2 + length;
4533 if (id == IEEE802154_HEADER_IE_HT1 || id == IEEE802154_HEADER_IE_HT2) {
4534 packet->payload_ie_present = (id == IEEE802154_HEADER_IE_HT1);
4535 break;
4537 } while (remaining > 0);
4539 proto_item_set_len(ies_item, offset - orig_offset);
4540 return offset - orig_offset;
4543 static int
4544 dissect_802154_eb_filter(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
4546 uint8_t filter;
4547 uint8_t attr_len;
4548 proto_tree *subtree;
4549 unsigned offset = 0;
4551 static int * const fields_eb_filter[] = {
4552 &hf_ieee802154_psie_eb_filter_pjoin,
4553 &hf_ieee802154_psie_eb_filter_lqi,
4554 &hf_ieee802154_psie_eb_filter_percent,
4555 &hf_ieee802154_psie_eb_filter_attr_id,
4556 /* reserved 5-7 */
4557 NULL
4560 subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_psie_eb_filter, ett_ieee802154_eb_filter);
4561 offset += 2;
4563 filter = tvb_get_uint8(tvb, offset);
4564 proto_tree_add_bitmask(subtree, tvb, offset, hf_ieee802154_psie_eb_filter,
4565 ett_ieee802154_eb_filter_bitmap, fields_eb_filter, ENC_NA);
4566 offset++;
4568 if (filter & IEEE802154_MLME_PSIE_EB_FLT_LQI) {
4569 proto_tree_add_item(subtree, hf_ieee802154_psie_eb_filter_lqi_min, tvb, offset, 1, ENC_NA);
4570 offset++;
4573 if (filter & IEEE802154_MLME_PSIE_EB_FLT_PERCENT) {
4574 proto_tree_add_item(subtree, hf_ieee802154_psie_eb_filter_percent_prob, tvb, offset, 1, ENC_NA);
4575 offset++;
4578 attr_len = (uint8_t) ((filter & IEEE802154_MLME_PSIE_EB_FLT_ATTR_LEN) >> 3);
4579 if (attr_len) {
4580 /* just display in hex until we know how to decode */
4581 proto_tree_add_item(subtree, hf_ieee802154_psie_eb_filter_attr_id_bitmap, tvb, offset, attr_len, ENC_LITTLE_ENDIAN);
4582 offset += attr_len;
4585 return offset;
4589 * Subdissector for MLME IEs
4591 static int
4592 dissect_pie_mlme(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ies_tree, void *data)
4594 proto_tree *tree = ieee802154_create_pie_tree(tvb, ies_tree, hf_ieee802154_mlme, ett_ieee802154_mlme);
4595 volatile unsigned offset = 2;
4597 while (tvb_reported_length_remaining(tvb, offset) > 1) {
4598 uint16_t psie_ie = tvb_get_letohs(tvb, offset);
4599 volatile uint16_t psie_id;
4600 tvbuff_t *volatile psie_tvb;
4602 if (psie_ie & IEEE802154_PSIE_TYPE_MASK) {
4603 /* long format: Table 7-17-Sub-ID allocation for long format */
4604 psie_id = (uint16_t) ((psie_ie & IEEE802154_PSIE_ID_MASK_LONG) >> 11);
4605 psie_tvb = tvb_new_subset_length(tvb, offset, (psie_ie & IEEE802154_PSIE_LENGTH_MASK_LONG) + 2);
4607 else {
4608 /* short format: Table 7-16-Sub-ID allocation for short format */
4609 psie_id = (uint16_t) ((psie_ie & IEEE802154_PSIE_ID_MASK_SHORT) >> 8);
4610 psie_tvb = tvb_new_subset_length(tvb, offset, (psie_ie & IEEE802154_PSIE_LENGTH_MASK_SHORT) + 2);
4612 offset += tvb_reported_length(psie_tvb);
4614 /* Pass the tvb off to a subdissector. */
4615 TRY {
4616 unsigned consumed = dissector_try_uint_with_data(mlme_ie_dissector_table, psie_id, psie_tvb, pinfo, tree, false, data);
4617 if (consumed == 0) {
4618 proto_tree *subtree = ieee802154_create_psie_tree(psie_tvb, tree, hf_ieee802154_mlme_ie_unsupported, ett_ieee802154_mlme_unsupported);
4619 if (tvb_reported_length(psie_tvb) > 2) {
4620 proto_tree_add_item(subtree, hf_ieee802154_mlme_ie_data, psie_tvb, 2, -1, ENC_NA);
4622 expert_add_info(pinfo, subtree, &ei_ieee802154_ie_unsupported_id);
4625 CATCH_ALL {
4626 show_exception(tvb, pinfo, ies_tree, EXCEPT_CODE, GET_MESSAGE);
4628 ENDTRY;
4630 return offset;
4634 * Subdissector for MPX IEs (IEEE 802.15.9)
4636 static int
4637 dissect_mpx_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ies_tree, void *data _U_)
4639 static int * const fields[] = {
4640 &hf_ieee802159_mpx_transaction_id,
4641 &hf_ieee802159_mpx_transfer_type,
4642 NULL
4644 static int * const fields_compressed_multiplex_id[] = {
4645 &hf_ieee802159_mpx_transaction_id_as_multiplex_id,
4646 &hf_ieee802159_mpx_transfer_type,
4647 NULL
4650 proto_tree *tree = ieee802154_create_pie_tree(tvb, ies_tree, hf_ieee802159_mpx, ett_ieee802159_mpx);
4651 unsigned offset = 2;
4652 uint8_t transaction_control = tvb_get_uint8(tvb, offset);
4653 uint8_t transfer_type = (uint8_t) (transaction_control & IEEE802159_MPX_TRANSFER_TYPE_MASK);
4654 uint8_t transaction_id = (uint8_t) ((transaction_control & IEEE802159_MPX_TRANSACTION_ID_MASK) >> IEEE802159_MPX_TRANSACTION_ID_SHIFT);
4655 int32_t multiplex_id = -1;
4656 uint8_t fragment_number;
4658 if (transfer_type == IEEE802159_MPX_FULL_FRAME_NO_MUXID) {
4659 proto_tree_add_bitmask_with_flags(tree, tvb, offset, hf_ieee802159_mpx_transaction_control, ett_ieee802159_mpx_transaction_control,
4660 fields_compressed_multiplex_id, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
4661 multiplex_id = transaction_id;
4662 } else {
4663 proto_tree_add_bitmask_with_flags(tree, tvb, offset, hf_ieee802159_mpx_transaction_control, ett_ieee802159_mpx_transaction_control,
4664 fields, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
4666 offset += 1;
4668 switch (transfer_type) { // cf. IEEE 802.15.9 Table 18 - Summary of different MPX IE formats
4669 case IEEE802159_MPX_FULL_FRAME:
4670 multiplex_id = tvb_get_letohs(tvb, offset);
4671 proto_tree_add_uint_format_value(tree, hf_ieee802159_mpx_multiplex_id, tvb, offset, 2, multiplex_id, "%s (0x%04x)",
4672 val_to_str_const(multiplex_id, (multiplex_id > 1500) ? etype_vals : mpx_multiplex_id_vals, "Unknown"), multiplex_id);
4673 offset += 2;
4674 break;
4675 case IEEE802159_MPX_FULL_FRAME_NO_MUXID:
4676 break; // nothing to do
4677 case IEEE802159_MPX_NON_LAST_FRAGMENT:
4678 fragment_number = tvb_get_uint8(tvb, offset);
4679 proto_tree_add_item(tree, hf_ieee802159_mpx_fragment_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4680 offset += 1;
4681 if (fragment_number == 0) {
4682 proto_tree_add_item(tree, hf_ieee802159_mpx_total_frame_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4683 offset += 2;
4684 multiplex_id = tvb_get_letohs(tvb, offset);
4685 proto_tree_add_item(tree, hf_ieee802159_mpx_multiplex_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4686 offset += 2;
4688 break;
4689 case IEEE802159_MPX_LAST_FRAGMENT:
4690 proto_tree_add_item(tree, hf_ieee802159_mpx_fragment_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4691 offset += 1;
4692 break;
4693 case IEEE802159_MPX_ABORT:
4694 if (tvb_reported_length_remaining(tvb, offset) == 2) {
4695 proto_tree_add_item(tree, hf_ieee802159_mpx_total_frame_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4696 offset += 2;
4698 return offset;
4699 default: // reserved values -> warning and return
4700 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_invalid_transfer_type);
4701 return offset;
4704 // TODO: reassembly
4706 dissector_handle_t dissector = NULL;
4708 if (multiplex_id == IEEE802159_MPX_MULTIPLEX_ID_KMP) {
4709 uint8_t kmp_id = tvb_get_uint8(tvb, offset);
4710 proto_tree_add_item(tree, hf_ieee802159_mpx_kmp_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4711 offset += 1;
4712 switch (kmp_id) {
4713 case IEEE802159_MPX_KMP_ID_IEEE8021X:
4714 case IEEE802159_MPX_KMP_ID_IEEE80211_4WH:
4715 case IEEE802159_MPX_KMP_ID_IEEE80211_GKH:
4716 dissector = eapol_handle;
4717 break;
4719 // TODO
4720 case IEEE802159_MPX_KMP_ID_HIP:
4721 case IEEE802159_MPX_KMP_ID_IKEV2:
4722 case IEEE802159_MPX_KMP_ID_PANA:
4723 case IEEE802159_MPX_KMP_ID_DRAGONFLY:
4724 case IEEE802159_MPX_KMP_ID_ETSI_TS_102_887_2:
4725 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_unsupported_kmp);
4726 break;
4728 case IEEE802159_MPX_KMP_ID_VENDOR_SPECIFIC:
4729 proto_tree_add_item(tree, hf_ieee802159_mpx_kmp_vendor_oui, tvb, offset, 3, ENC_BIG_ENDIAN);
4730 offset += 3;
4731 break;
4733 // Unknown
4734 default:
4735 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_unknown_kmp);
4738 else if (multiplex_id == IEEE802159_MPX_MULTIPLEX_ID_WISUN) {
4739 uint8_t subid = tvb_get_uint8(tvb, offset);
4740 proto_tree_add_item(tree, hf_ieee802159_mpx_wisun_subid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4741 offset += 1;
4742 switch (subid) {
4743 case IEEE802159_MPX_WISUN_SUBID_6LOWPAN:
4744 dissector = lowpan_handle;
4745 break;
4747 case IEEE802159_MPX_WISUN_SUBID_SECURITY:
4748 dissector = wisun_sec_handle;
4749 break;
4751 case IEEE802159_MPX_WISUN_SUBID_MHDS:
4752 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_unsupported_kmp);
4753 break;
4755 default:
4756 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_unknown_kmp);
4757 break;
4760 else if (multiplex_id > 1500) {
4761 dissector = dissector_get_uint_handle(ethertype_table, (unsigned)multiplex_id);
4764 if (transfer_type == IEEE802159_MPX_FULL_FRAME || transfer_type == IEEE802159_MPX_FULL_FRAME_NO_MUXID) {
4765 tvbuff_t * payload = tvb_new_subset_remaining(tvb, offset);
4766 if (dissector) {
4767 call_dissector(dissector, payload, pinfo, proto_tree_get_root(tree)); // exceptions are caught in our caller
4768 } else {
4769 call_data_dissector(payload, pinfo, proto_tree_get_root(tree));
4771 } else {
4772 proto_tree_add_item(tree, hf_ieee802159_mpx_fragment, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA);
4774 offset = tvb_reported_length(tvb);
4776 return offset;
4780 * Subdissector for Vendor Specific Payload IEs (Information Elements)
4782 static int
4783 dissect_pie_vendor(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ies_tree, void *data _U_)
4785 proto_tree *tree = ieee802154_create_pie_tree(tvb, ies_tree, hf_ieee802154_pie_vendor, ett_ieee802154_pie_vendor);
4787 unsigned offset = 2;
4788 unsigned pie_length = tvb_reported_length(tvb) - 2;
4789 tvbuff_t *next_tvb;
4790 uint32_t vendor_oui;
4792 vendor_oui = tvb_get_letoh24(tvb, offset);
4793 proto_tree_add_item(tree, hf_ieee802154_pie_vendor_oui, tvb, offset, 3, ENC_LITTLE_ENDIAN);
4794 offset += 3; /* adjust for vendor OUI */
4795 pie_length -= 3;
4796 next_tvb = tvb_new_subset_length(tvb, offset, pie_length);
4798 switch (vendor_oui) {
4799 case OUI_ZIGBEE:
4800 call_dissector_with_data(zigbee_ie_handle, next_tvb, pinfo, tree, &pie_length);
4801 break;
4803 default:
4804 call_data_dissector(next_tvb, pinfo, tree);
4805 break;
4808 return tvb_reported_length(tvb);
4812 * Subdissector for Payload IEs (Information Elements)
4814 * @param tvb the tv buffer
4815 * @param pinfo pointer to packet information fields.
4816 * @param tree the tree to append this item to
4817 * @param orig_offset offset into the tvbuff to begin dissection.
4818 * @param packet IEEE 802.15.4 packet information.
4820 static int
4821 dissect_ieee802154_payload_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned orig_offset, ieee802154_packet *packet)
4823 // GCC emits a spurious -Wclobbered if offset is used as function parameter (even with volatile)
4824 volatile unsigned offset = orig_offset;
4825 proto_item *ies_item = proto_tree_add_item(tree, hf_ieee802154_payload_ies, tvb, offset, -1, ENC_NA);
4826 proto_tree *ies_tree = proto_item_add_subtree(ies_item, ett_ieee802154_payload_ie);
4828 do {
4829 volatile int consumed = 0;
4830 uint16_t ie_header = tvb_get_letohs(tvb, offset);
4831 uint16_t id = (uint16_t) ((ie_header & IEEE802154_PAYLOAD_IE_ID_MASK) >> 11);
4832 volatile uint16_t length = (uint16_t) (ie_header & IEEE802154_PAYLOAD_IE_LENGTH_MASK);
4833 tvbuff_t * volatile ie_tvb = tvb_new_subset_length(tvb, offset, 2 + length);
4835 if (id == IEEE802154_PAYLOAD_IE_TERMINATION) {
4836 ieee802154_create_pie_tree(ie_tvb, ies_tree, hf_ieee802154_pie_termination, ett_ieee802154_pie_termination);
4837 consumed = 2;
4838 } else {
4839 TRY {
4840 consumed = dissector_try_uint_with_data(payload_ie_dissector_table, id, ie_tvb, pinfo, ies_tree, false, packet);
4841 if (consumed == 0) {
4842 proto_tree *subtree = ieee802154_create_pie_tree(ie_tvb, ies_tree, hf_ieee802154_pie_unsupported, ett_ieee802154_pie_unsupported);
4843 proto_tree_add_item(subtree, hf_ieee802154_ie_unknown_content_payload, ie_tvb, 2, length, ENC_NA);
4844 consumed = 2 + length;
4845 expert_add_info(pinfo, proto_tree_get_parent(subtree), &ei_ieee802154_ie_unsupported_id);
4848 CATCH_ALL {
4849 show_exception(tvb, pinfo, ies_tree, EXCEPT_CODE, GET_MESSAGE);
4850 consumed = 2 + length;
4852 ENDTRY;
4855 if (consumed < 2 + length) {
4856 proto_tree_add_item(ies_tree, hf_ieee802154_ie_unknown_content_payload, ie_tvb, consumed, 2 + length - consumed, ENC_NA);
4857 expert_add_info(pinfo, ies_item, &ei_ieee802154_ie_unknown_extra_content_payload);
4860 offset += 2 + length;
4862 if (id == IEEE802154_PAYLOAD_IE_TERMINATION) {
4863 break;
4865 } while (tvb_reported_length_remaining(tvb, offset) > 1);
4867 proto_item_set_len(ies_item, offset - orig_offset);
4868 return offset - orig_offset;
4871 static const true_false_string tfs_cinfo_device_type = { "FFD", "RFD" };
4872 static const true_false_string tfs_cinfo_power_src = { "AC/Mains Power", "Battery" };
4875 * Command subdissector routine for the Association request command.
4877 * @param tvb pointer to buffer containing raw packet.
4878 * @param pinfo pointer to packet information fields.
4879 * @param tree pointer to protocol tree.
4880 * @param packet IEEE 802.15.4 packet information.
4883 static void
4884 dissect_ieee802154_assoc_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4886 uint8_t cap;
4887 proto_tree *subtree;
4888 static int * const capability[] = {
4889 &hf_ieee802154_cinfo_alt_coord,
4890 &hf_ieee802154_cinfo_device_type,
4891 &hf_ieee802154_cinfo_power_src,
4892 &hf_ieee802154_cinfo_idle_rx,
4893 &hf_ieee802154_cinfo_sec_capable,
4894 &hf_ieee802154_cinfo_alloc_addr,
4895 NULL
4898 cap = tvb_get_uint8(tvb, 0);
4899 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", tfs_get_string(cap & IEEE802154_CMD_CINFO_DEVICE_TYPE, &tfs_cinfo_device_type));
4901 /* Create a subtree for this command frame. */
4902 subtree = proto_tree_add_subtree(tree, tvb, 0, 1, ett_ieee802154_cmd, NULL,
4903 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4905 /* Get and display capability info. */
4906 proto_tree_add_bitmask_list(subtree, tvb, 0, 1, capability, ENC_NA);
4908 /* Call the data dissector for any leftover bytes. */
4909 if (tvb_reported_length(tvb) > 1) {
4910 call_data_dissector(tvb_new_subset_remaining(tvb, 1), pinfo, tree);
4912 } /* dissect_ieee802154_assoc_req */
4915 * Command subdissector routine for the Association response command.
4917 * @param tvb pointer to buffer containing raw packet.
4918 * @param pinfo pointer to packet information fields.
4919 * @param tree pointer to protocol tree.
4920 * @param packet IEEE 802.15.4 packet information.
4922 static void
4923 dissect_ieee802154_assoc_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4925 proto_tree *subtree;
4926 proto_item *ti;
4927 uint16_t short_addr;
4928 uint8_t status;
4929 unsigned offset = 0;
4931 /* Create a subtree for this command frame. */
4932 subtree = proto_tree_add_subtree(tree, tvb, offset, 3, ett_ieee802154_cmd, NULL,
4933 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4935 /* Get and display the short address. */
4936 short_addr = tvb_get_letohs(tvb, offset);
4937 proto_tree_add_uint(subtree, hf_ieee802154_assoc_addr, tvb, offset, 2, short_addr);
4938 offset += 2;
4940 /* Get and display the status. */
4941 status = tvb_get_uint8(tvb, offset);
4942 if (tree) {
4943 ti = proto_tree_add_uint(subtree, hf_ieee802154_assoc_status, tvb, offset, 1, status);
4944 if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) proto_item_append_text(ti, " (Association Successful)");
4945 else if (status == IEEE802154_CMD_ASRSP_PAN_FULL) proto_item_append_text(ti, " (PAN Full)");
4946 else if (status == IEEE802154_CMD_ASRSP_PAN_DENIED) proto_item_append_text(ti, " (Association Denied)");
4947 else proto_item_append_text(ti, " (Reserved)");
4949 offset += 1;
4951 /* Update the info column. */
4952 if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) {
4953 /* Association was successful. */
4954 if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {
4955 col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", packet->dst_pan);
4957 if (short_addr != IEEE802154_NO_ADDR16) {
4958 col_append_fstr(pinfo->cinfo, COL_INFO, " Addr: 0x%04x", short_addr);
4961 else {
4962 /* Association was unsuccessful. */
4963 col_append_str(pinfo->cinfo, COL_INFO, ", Unsuccessful");
4966 /* Update the address table. */
4967 if ((status == IEEE802154_CMD_ASRSP_AS_SUCCESS) && (short_addr != IEEE802154_NO_ADDR16)) {
4968 ieee802154_addr_update(&ieee802154_map, short_addr, packet->dst_pan, packet->dst64,
4969 pinfo->current_proto, pinfo->num);
4972 /* Call the data dissector for any leftover bytes. */
4973 if (tvb_captured_length(tvb) > offset) {
4974 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
4976 } /* dissect_ieee802154_assoc_rsp */
4979 * Command subdissector routine for the Disassociate command.
4981 * @param tvb pointer to buffer containing raw packet.
4982 * @param pinfo pointer to packet information fields.
4983 * @param tree pointer to protocol tree.
4984 * @param packet IEEE 802.15.4 packet information.
4986 static void
4987 dissect_ieee802154_disassoc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4989 proto_tree *subtree;
4990 proto_item *ti;
4991 uint8_t reason;
4993 /* Create a subtree for this command frame. */
4994 subtree = proto_tree_add_subtree(tree, tvb, 0, 1, ett_ieee802154_cmd, NULL,
4995 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4997 /* Get and display the disassociation reason. */
4998 reason = tvb_get_uint8(tvb, 0);
4999 if (tree) {
5000 ti = proto_tree_add_uint(subtree, hf_ieee802154_disassoc_reason, tvb, 0, 1, reason);
5001 switch (reason) {
5002 case 0x01:
5003 proto_item_append_text(ti, " (Coordinator requests device to leave)");
5004 break;
5006 case 0x02:
5007 proto_item_append_text(ti, " (Device wishes to leave)");
5008 break;
5010 default:
5011 proto_item_append_text(ti, " (Reserved)");
5012 break;
5013 } /* switch */
5016 if (!PINFO_FD_VISITED(pinfo)) {
5017 /* Update the address tables */
5018 if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT ) {
5019 ieee802154_long_addr_invalidate(packet->dst64, pinfo->num);
5020 } else if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT ) {
5021 ieee802154_short_addr_invalidate(packet->dst16, packet->dst_pan, pinfo->num);
5025 /* Call the data dissector for any leftover bytes. */
5026 if (tvb_captured_length(tvb) > 1) {
5027 call_data_dissector(tvb_new_subset_remaining(tvb, 1), pinfo, tree);
5029 } /* dissect_ieee802154_disassoc */
5032 * Command subdissector routine for the Coordinator Realignment command.
5034 * @param tvb pointer to buffer containing raw packet.
5035 * @param pinfo pointer to packet information fields.
5036 * @param tree pointer to protocol tree.
5037 * @param packet IEEE 802.15.4 packet information.
5039 static void
5040 dissect_ieee802154_realign(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
5042 proto_tree *subtree;
5043 proto_item *subitem;
5044 uint16_t pan_id;
5045 uint16_t coord_addr;
5046 uint8_t channel;
5047 uint16_t short_addr;
5048 unsigned offset = 0;
5050 /* Create a subtree for this command frame. */
5051 subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_ieee802154_cmd, &subitem,
5052 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
5054 /* Get and display the command PAN ID. */
5055 pan_id = tvb_get_letohs(tvb, offset);
5056 proto_tree_add_uint(subtree, hf_ieee802154_realign_pan, tvb, offset, 2, pan_id);
5057 col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", pan_id);
5058 offset += 2;
5060 /* Get and display the coordinator address. */
5061 coord_addr = tvb_get_letohs(tvb, offset);
5062 proto_tree_add_uint(subtree, hf_ieee802154_realign_caddr, tvb, offset, 2, coord_addr);
5063 col_append_fstr(pinfo->cinfo, COL_INFO, ", Coordinator: 0x%04x", coord_addr);
5064 offset += 2;
5066 /* Get and display the channel. */
5067 channel = tvb_get_uint8(tvb, offset);
5068 proto_tree_add_uint(subtree, hf_ieee802154_realign_channel, tvb, offset, 1, channel);
5069 col_append_fstr(pinfo->cinfo, COL_INFO, ", Channel: %u", channel);
5070 offset += 1;
5072 /* Get and display the short address. */
5073 short_addr = tvb_get_letohs(tvb, offset);
5074 if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_addr, tvb, offset, 2, short_addr);
5075 if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)
5076 && (short_addr != IEEE802154_NO_ADDR16)) {
5077 col_append_fstr(pinfo->cinfo, COL_INFO, ", Addr: 0x%04x", short_addr);
5079 offset += 2;
5080 /* Update the address table. */
5081 if ((short_addr != IEEE802154_NO_ADDR16) && (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)) {
5082 ieee802154_addr_update(&ieee802154_map, short_addr, packet->dst_pan, packet->dst64,
5083 pinfo->current_proto, pinfo->num);
5086 /* Get and display the channel page, if it exists. Added in IEEE802.15.4-2006 */
5087 if (tvb_bytes_exist(tvb, offset, 1)) {
5088 uint8_t channel_page = tvb_get_uint8(tvb, offset);
5089 if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_channel_page, tvb, offset, 1, channel_page);
5090 offset += 1;
5093 /* Fix the length of the command subtree. */
5094 if (tree) {
5095 proto_item_set_len(subitem, offset);
5098 /* Call the data dissector for any leftover bytes. */
5099 if (tvb_captured_length(tvb) > offset) {
5100 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
5102 } /* dissect_ieee802154_realign */
5104 static const true_false_string tfs_gtsreq_dir = { "Receive", "Transmit" };
5105 static const true_false_string tfs_gtsreq_type= { "Allocate GTS", "Deallocate GTS" };
5108 * Command subdissector routine for the GTS request command.
5110 * Assumes that COL_INFO will be set to the command name,
5111 * command name will already be appended to the command subtree
5112 * and protocol root. In addition, assumes that the command ID
5113 * has already been parsed.
5115 * @param tvb pointer to buffer containing raw packet.
5116 * @param pinfo pointer to packet information fields (unused).
5117 * @param tree pointer to protocol tree.
5118 * @param packet IEEE 802.15.4 packet information (unused).
5121 static void
5122 dissect_ieee802154_gtsreq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
5124 proto_tree *subtree;
5125 static int * const characteristics[] = {
5126 &hf_ieee802154_gtsreq_len,
5127 &hf_ieee802154_gtsreq_dir,
5128 &hf_ieee802154_gtsreq_type,
5129 NULL
5132 /* Create a subtree for this command frame. */
5133 subtree = proto_tree_add_subtree(tree, tvb, 0, 1, ett_ieee802154_cmd, NULL,
5134 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
5136 proto_tree_add_bitmask_list(subtree, tvb, 0, 1, characteristics, ENC_NA);
5138 /* Call the data dissector for any leftover bytes. */
5139 if (tvb_reported_length(tvb) > 1) {
5140 call_data_dissector(tvb_new_subset_remaining(tvb, 1), pinfo, tree);
5142 } /* dissect_ieee802154_gtsreq */
5145 * Subdissector routine for IEEE 802.15.4 commands
5147 * @param tvb pointer to buffer containing the command payload
5148 * @param pinfo pointer to packet information fields
5149 * @param tree pointer to the protocol tree
5150 * @param packet IEEE 802.15.4 packet information
5152 static void
5153 dissect_ieee802154_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
5155 if ((packet->version == IEEE802154_VERSION_2015) && (packet->frame_type == IEEE802154_FCF_CMD)) {
5156 /* In 802.15.4e and later the Command Id follows the Payload IEs. */
5157 packet->command_id = tvb_get_uint8(tvb, 0);
5158 proto_tree_add_uint(tree, hf_ieee802154_cmd_id, tvb, 0, 1, packet->command_id);
5159 tvb = tvb_new_subset_remaining(tvb, 1);
5161 /* Display the command identifier in the info column. */
5162 if ((packet->version == IEEE802154_VERSION_2015) && (packet->command_id == IEEE802154_CMD_BEACON_REQ)) {
5163 col_set_str(pinfo->cinfo, COL_INFO, "Enhanced Beacon Request");
5165 else {
5166 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
5170 switch (packet->command_id) {
5171 case IEEE802154_CMD_ASSOC_REQ:
5172 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
5173 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
5174 (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
5175 dissect_ieee802154_assoc_req(tvb, pinfo, tree, packet);
5176 break;
5178 case IEEE802154_CMD_ASSOC_RSP:
5179 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
5180 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
5181 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
5182 dissect_ieee802154_assoc_rsp(tvb, pinfo, tree, packet);
5183 break;
5185 case IEEE802154_CMD_DISASSOC_NOTIFY:
5186 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
5187 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
5188 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
5189 dissect_ieee802154_disassoc(tvb, pinfo, tree, packet);
5190 break;
5192 case IEEE802154_CMD_DATA_RQ:
5193 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id, packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE);
5194 /* No payload expected. */
5195 break;
5197 case IEEE802154_CMD_PANID_CONFLICT:
5198 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
5199 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
5200 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
5201 /* No payload expected. */
5202 break;
5204 case IEEE802154_CMD_ORPHAN_NOTIFY:
5205 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
5206 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
5207 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
5208 (packet->dst16 == IEEE802154_BCAST_ADDR) &&
5209 (packet->src_pan == IEEE802154_BCAST_PAN) &&
5210 (packet->dst_pan == IEEE802154_BCAST_PAN));
5211 /* No payload expected. */
5212 break;
5214 case IEEE802154_CMD_BEACON_REQ:
5215 if ((packet->version == IEEE802154_VERSION_2003) || (packet->version == IEEE802154_VERSION_2006)) {
5216 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
5217 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
5218 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
5219 (packet->dst16 == IEEE802154_BCAST_ADDR) &&
5220 (packet->dst_pan == IEEE802154_BCAST_PAN));
5222 /* No payload expected. */
5223 break;
5225 case IEEE802154_CMD_COORD_REALIGN:
5226 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
5227 (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
5228 (packet->dst_pan == IEEE802154_BCAST_PAN) &&
5229 (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
5230 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
5231 /* If directed to a 16-bit address, check that it is being broadcast. */
5232 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id, packet->dst16 == IEEE802154_BCAST_ADDR);
5234 dissect_ieee802154_realign(tvb, pinfo, tree, packet);
5235 break;
5237 case IEEE802154_CMD_GTS_REQ:
5238 /* Check that the addressing is correct for this command type. */
5239 IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
5240 (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
5241 (packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
5242 (packet->src16 != IEEE802154_BCAST_ADDR) &&
5243 (packet->src16 != IEEE802154_NO_ADDR16));
5244 dissect_ieee802154_gtsreq(tvb, pinfo, tree, packet);
5245 break;
5247 case IEEE802154_CMD_VENDOR_SPECIFIC:
5249 uint32_t oui = tvb_get_letoh24(tvb, 0);
5250 proto_tree_add_item(tree, hf_ieee802154_cmd_vendor_oui, tvb, 0, 3, ENC_LITTLE_ENDIAN);
5251 if (!dissector_try_uint_with_data(cmd_vendor_dissector_table, oui, tvb_new_subset_remaining(tvb, 3), pinfo, tree, false, packet)) {
5252 call_data_dissector(tvb_new_subset_remaining(tvb, 3), pinfo, tree);
5254 break;
5257 case IEEE802154_CMD_TRLE_MGMT_REQ:
5258 case IEEE802154_CMD_TRLE_MGMT_RSP:
5259 case IEEE802154_CMD_DSME_ASSOC_REQ:
5260 case IEEE802154_CMD_DSME_ASSOC_RSP:
5261 case IEEE802154_CMD_DSME_GTS_REQ:
5262 case IEEE802154_CMD_DSME_GTS_RSP:
5263 case IEEE802154_CMD_DSME_GTS_NOTIFY:
5264 case IEEE802154_CMD_DSME_INFO_REQ:
5265 case IEEE802154_CMD_DSME_INFO_RSP:
5266 case IEEE802154_CMD_DSME_BEACON_ALLOC_NOTIFY:
5267 case IEEE802154_CMD_DSME_BEACON_COLL_NOTIFY:
5268 case IEEE802154_CMD_DSME_LINK_REPORT:
5269 case IEEE802154_CMD_RIT_DATA_REQ:
5270 case IEEE802154_CMD_DBS_REQ:
5271 case IEEE802154_CMD_DBS_RSP:
5272 case IEEE802154_CMD_RIT_DATA_RSP:
5273 /* TODO add support for these commands, for now if anything remains, dump it */
5274 expert_add_info(pinfo, tree, &ei_ieee802154_unsupported_cmd);
5275 if (tvb_captured_length_remaining(tvb, 0) > 0) {
5276 call_data_dissector(tvb, pinfo, tree);
5278 break;
5279 default:
5280 expert_add_info(pinfo, tree, &ei_ieee802154_unknown_cmd);
5281 if (tvb_captured_length_remaining(tvb, 0) > 0) {
5282 call_data_dissector(tvb, pinfo, tree);
5284 } /* switch */
5285 } /* dissect_ieee802154_command */
5288 * IEEE 802.15.4 decryption algorithm
5289 * @param tvb IEEE 802.15.4 packet, not including the FCS or metadata trailer.
5290 * @param pinfo Packet info structure.
5291 * @param offset Offset where the ciphertext 'c' starts.
5292 * @param packet IEEE 802.15.4 packet information.
5293 * @return decrypted payload.
5295 static tvbuff_t *
5296 dissect_ieee802154_decrypt(tvbuff_t *tvb,
5297 unsigned offset,
5298 packet_info *pinfo,
5299 ieee802154_packet *packet,
5300 ieee802154_decrypt_info_t* decrypt_info)
5302 tvbuff_t *ptext_tvb;
5303 bool have_mic = false;
5304 uint64_t srcAddr = 0;
5305 unsigned char tmp[IEEE802154_CIPHER_SIZE];
5306 unsigned M;
5307 int captured_len;
5308 int reported_len;
5309 ieee802154_hints_t *ieee_hints;
5310 char *generic_nonce_ptr = NULL;
5311 char generic_nonce[13];
5313 ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
5315 /* Get the captured and on-the-air length of the payload. */
5316 M = IEEE802154_MIC_LENGTH(packet->security_level);
5317 *decrypt_info->rx_mic_length = M;
5319 /* Is the MIC larger than the total amount of data? */
5320 reported_len = tvb_reported_length_remaining(tvb, offset) - M;
5321 if (reported_len < 0) {
5322 /* Yes. Give up. */
5323 *decrypt_info->status = DECRYPT_PACKET_TOO_SMALL;
5324 return NULL;
5326 /* Check whether the payload is truncated by a snapshot length. */
5327 if (tvb_bytes_exist(tvb, offset, reported_len)) {
5328 /* It's not, so we have all of the payload. */
5329 captured_len = reported_len;
5331 else {
5333 * It is, so we don't have all of the payload - and we don't
5334 * have the MIC, either, as that comes after the payload.
5335 * As the MIC isn't part of the captured data - the captured
5336 * data was cut short before the first byte of the MIC - we
5337 * don't subtract the length of the MIC from the amount of
5338 * captured data.
5340 captured_len = tvb_captured_length_remaining(tvb, offset);
5343 /* Check if the MIC is present in the captured data. */
5344 have_mic = tvb_bytes_exist(tvb, offset + reported_len, M);
5345 if (have_mic) {
5346 /* It is - save a copy of it. */
5347 tvb_memcpy(tvb, decrypt_info->rx_mic, offset + reported_len, M);
5350 /* We need the extended source address. */
5351 if ((packet->key_index == IEEE802154_THR_WELL_KNOWN_KEY_INDEX) &&
5352 (packet->key_source.addr32 == IEEE802154_THR_WELL_KNOWN_KEY_SRC))
5354 /* Use the well-known extended address */
5355 srcAddr = IEEE802154_THR_WELL_KNOWN_EXT_ADDR;
5356 } else {
5357 if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
5358 /* The source EUI-64 is included in the headers. */
5359 srcAddr = packet->src64;
5361 else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT && packet->frame_counter_suppression) {
5362 /* In TSCH mode, the source address is a combination of 802.15 CID, PAN ID and Short Address */
5363 srcAddr = IEEE80215_CID << 40;
5364 srcAddr |= ((uint64_t)packet->src_pan & 0xffff) << 16;
5365 srcAddr |= packet->src16;
5367 else if (ieee_hints && ieee_hints->map_rec && ieee_hints->map_rec->addr64) {
5368 /* Use the hint */
5369 srcAddr = ieee_hints->map_rec->addr64;
5371 else {
5372 /* Lookup failed. */
5373 *decrypt_info->status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
5374 return NULL;
5379 * CCM* - CTR mode payload encryption
5382 /* 802.15.4-2015 TSCH mode */
5383 if (packet->frame_counter_suppression) {
5384 tsch_ccm_init_nonce(srcAddr, packet->asn, generic_nonce);
5385 generic_nonce_ptr = generic_nonce;
5388 /* Create the CCM* initial block for decryption (Adata=0, M=0, counter=0). */
5389 if ((packet->frame_type != IEEE802154_FCF_MULTIPURPOSE) && (packet->version == IEEE802154_VERSION_2003))
5390 ccm_init_block(tmp, false, 0, srcAddr, packet->frame_counter, packet->key_sequence_counter, 0, NULL);
5391 else
5392 ccm_init_block(tmp, false, 0, srcAddr, packet->frame_counter, packet->security_level, 0, generic_nonce_ptr);
5395 * If the payload is encrypted, so that it's the ciphertext, and we
5396 * have at least one byte of it in the captured data, decrypt the
5397 * ciphertext, and place the plaintext in a new tvb.
5399 if (IEEE802154_IS_ENCRYPTED(packet->security_level) && captured_len) {
5400 uint8_t *text;
5402 * Make a copy of the ciphertext in heap memory.
5404 * We will decrypt the message in-place and then use the buffer as the
5405 * real data for the new tvb.
5407 text = (uint8_t *)tvb_memdup(pinfo->pool, tvb, offset, captured_len);
5409 /* Perform CTR-mode transformation. */
5410 if (!ccm_ctr_encrypt(decrypt_info->key, tmp, decrypt_info->rx_mic, text, captured_len)) {
5411 wmem_free(pinfo->pool, text);
5412 *decrypt_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
5413 return NULL;
5416 /* Create a tvbuff for the plaintext. */
5417 ptext_tvb = tvb_new_child_real_data(tvb, text, captured_len, reported_len);
5418 add_new_data_source(pinfo, ptext_tvb, "Decrypted IEEE 802.15.4 payload");
5419 *decrypt_info->status = DECRYPT_PACKET_SUCCEEDED;
5421 else {
5423 * Either the payload isn't encrypted or we don't have any of it
5424 * in the captured data.
5426 /* Decrypt the MIC (if present). */
5427 if ((have_mic) && (!ccm_ctr_encrypt(decrypt_info->key, tmp, decrypt_info->rx_mic, NULL, 0))) {
5428 *decrypt_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
5429 return NULL;
5432 /* Create a tvbuff for the plaintext. This might result in a zero-length tvbuff. */
5433 ptext_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
5434 *decrypt_info->status = DECRYPT_PACKET_SUCCEEDED;
5438 * CCM* - CBC-mode message authentication
5441 /* We can only verify the message if the MIC wasn't truncated. */
5442 if (have_mic) {
5443 unsigned char dec_mic[16];
5444 unsigned l_m = captured_len;
5445 unsigned l_a = offset;
5447 /* Adjust the lengths of the plaintext and additional data if unencrypted. */
5448 if (!IEEE802154_IS_ENCRYPTED(packet->security_level)) {
5449 l_a += l_m;
5450 l_m = 0;
5452 else if ((packet->frame_type != IEEE802154_FCF_MULTIPURPOSE) && (packet->version == IEEE802154_VERSION_2003) && !ieee802154_extend_auth)
5453 l_a -= 5; /* Exclude Frame Counter (4 bytes) and Key Sequence Counter (1 byte) from authentication data */
5456 /* Create the CCM* initial block for authentication (Adata!=0, M!=0, counter=l(m)). */
5457 if ((packet->frame_type != IEEE802154_FCF_MULTIPURPOSE) && (packet->version == IEEE802154_VERSION_2003))
5458 ccm_init_block(tmp, true, M, srcAddr, packet->frame_counter, packet->key_sequence_counter, l_m, NULL);
5459 else
5460 ccm_init_block(tmp, true, M, srcAddr, packet->frame_counter, packet->security_level, l_m, generic_nonce_ptr);
5462 /* Compute CBC-MAC authentication tag. */
5464 * And yes, despite the warning in tvbuff.h, I think tvb_get_ptr is the
5465 * right function here since either A) the payload wasn't encrypted, in
5466 * which case l_m is zero, or B) the payload was encrypted, and the tvb
5467 * already points to contiguous memory, since we just allocated it in
5468 * decryption phase.
5470 memset(dec_mic, 0, sizeof(dec_mic));
5471 if (!ccm_cbc_mac(decrypt_info->key, tmp, (const char *)tvb_memdup(pinfo->pool, tvb, 0, l_a), l_a, tvb_get_ptr(ptext_tvb, 0, l_m), l_m, dec_mic)) {
5472 *decrypt_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
5474 /* Compare the received MIC with the one we generated. */
5475 else if (memcmp(decrypt_info->rx_mic, dec_mic, M) != 0) {
5476 *decrypt_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
5480 /* Done! */
5481 return ptext_tvb;
5482 } /* dissect_ieee802154_decrypt */
5485 * Creates the CCM* initial block value for IEEE 802.15.4.
5487 * @param block Output pointer for the initial block.
5488 * @param adata true if additional auth data is present
5489 * @param M CCM* parameter M.
5490 * @param addr Source extended address.
5491 * @param frame_counter Packet frame counter
5492 * @param level Security level or key_sequence_counter for 802.15.4-2003
5493 * @param ctr_val Value in the last L bytes of the block.
5494 * @param generic_nonce 13-byte nonce to be set by non 802.15.4 calls. If set addr, frame_counter and level are ignored.
5496 void
5497 ccm_init_block(char *block, bool adata, int M, uint64_t addr, uint32_t frame_counter, uint8_t level, int ctr_val, const char *generic_nonce)
5499 int i = 0;
5501 /* Flags: Reserved(0) || Adata || (M-2)/2 || (L-1) */
5502 block[i] = (0x2 - 1); /* (L-1) */
5503 if (M > 0) block[i] |= (((M-2)/2) << 3); /* (M-2)/2 */
5504 if (adata) block[i] |= (1 << 6); /* Adata */
5505 i++;
5506 if (generic_nonce == NULL) {
5507 /* 2003 CCM Nonce: Source Address || Frame Counter || Key Sequence Counter */
5508 /* 2006 CCM* Nonce: Source Address || Frame Counter || Security Level */
5509 block[i++] = (uint8_t)((addr >> 56) & 0xff);
5510 block[i++] = (uint8_t)((addr >> 48) & 0xff);
5511 block[i++] = (uint8_t)((addr >> 40) & 0xff);
5512 block[i++] = (uint8_t)((addr >> 32) & 0xff);
5513 block[i++] = (uint8_t)((addr >> 24) & 0xff);
5514 block[i++] = (uint8_t)((addr >> 16) & 0xff);
5515 block[i++] = (uint8_t)((addr >> 8) & 0xff);
5516 block[i++] = (uint8_t)((addr >> 0) & 0xff);
5517 block[i++] = (uint8_t)((frame_counter >> 24) & 0xff);
5518 block[i++] = (uint8_t)((frame_counter >> 16) & 0xff);
5519 block[i++] = (uint8_t)((frame_counter >> 8) & 0xff);
5520 block[i++] = (uint8_t)((frame_counter >> 0) & 0xff);
5521 block[i++] = level;
5522 } else {
5523 memcpy(&block[i], generic_nonce, 13);
5524 i += 13;
5526 /* Plaintext length. */
5527 block[i++] = (uint8_t)((ctr_val >> 8) & 0xff);
5528 block[i] = (uint8_t)((ctr_val >> 0) & 0xff);
5529 } /* ccm_init_block */
5532 * Creates the IEEE 802.15.4 TSCH nonce.
5534 * @param addr Source extended address.
5535 * @param asn TSCH Absolute Slot Number
5536 * @param generic_nonce 13-byte nonce to returned by this function.
5538 static void
5539 tsch_ccm_init_nonce(uint64_t addr, uint64_t asn, char* generic_nonce)
5541 int i = 0;
5543 /* 2015 CCM* Nonce: Source Address || ASN */
5544 generic_nonce[i++] = (uint8_t)((addr >> 56) & 0xff);
5545 generic_nonce[i++] = (uint8_t)((addr >> 48) & 0xff);
5546 generic_nonce[i++] = (uint8_t)((addr >> 40) & 0xff);
5547 generic_nonce[i++] = (uint8_t)((addr >> 32) & 0xff);
5548 generic_nonce[i++] = (uint8_t)((addr >> 24) & 0xff);
5549 generic_nonce[i++] = (uint8_t)((addr >> 16) & 0xff);
5550 generic_nonce[i++] = (uint8_t)((addr >> 8) & 0xff);
5551 generic_nonce[i++] = (uint8_t)((addr >> 0) & 0xff);
5552 generic_nonce[i++] = (uint8_t)((asn >> 32) & 0xff);
5553 generic_nonce[i++] = (uint8_t)((asn >> 24) & 0xff);
5554 generic_nonce[i++] = (uint8_t)((asn >> 16) & 0xff);
5555 generic_nonce[i++] = (uint8_t)((asn >> 8) & 0xff);
5556 generic_nonce[i++] = (uint8_t)((asn >> 0) & 0xff);
5557 } /* tsch_ccm_init_nonce */
5560 * Perform an in-place CTR-mode encryption/decryption.
5562 * @param key Encryption Key.
5563 * @param iv Counter initial value.
5564 * @param mic MIC to encrypt/decrypt.
5565 * @param data Buffer to encrypt/decrypt.
5566 * @param length Length of the buffer.
5567 * @return true on SUCCESS, false on error.
5569 bool
5570 ccm_ctr_encrypt(const char *key, const char *iv, char *mic, char *data, int length)
5572 gcry_cipher_hd_t cipher_hd;
5574 /* Open the cipher. */
5575 if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0)) {
5576 return false;
5579 /* Set the key and initial value. */
5580 if (gcry_cipher_setkey(cipher_hd, key, 16)) {
5581 gcry_cipher_close(cipher_hd);
5582 return false;
5584 if (gcry_cipher_setctr(cipher_hd, iv, 16)) {
5585 gcry_cipher_close(cipher_hd);
5586 return false;
5589 /* Decrypt the MIC. */
5590 if (gcry_cipher_encrypt(cipher_hd, mic, 16, NULL, 0)) {
5591 gcry_cipher_close(cipher_hd);
5592 return false;
5594 /* Decrypt the payload. */
5595 if (gcry_cipher_encrypt(cipher_hd, data, length, NULL, 0)) {
5596 gcry_cipher_close(cipher_hd);
5597 return false;
5600 /* Done with the cipher. */
5601 gcry_cipher_close(cipher_hd);
5602 return true;
5603 } /* ccm_ctr_encrypt */
5606 * Generate a CBC-MAC of the decrypted payload and additional authentication headers.
5607 * @param key Encryption Key.
5608 * @param iv Counter initial value.
5609 * @param a Additional auth headers.
5610 * @param a_len Length of the additional headers.
5611 * @param m Plaintext message.
5612 * @param m_len Length of plaintext message.
5613 * @param mic Output for CBC-MAC.
5614 * @return true on SUCCESS, false on error.
5616 bool
5617 ccm_cbc_mac(const char *key, const char *iv, const char *a, int a_len, const char *m, int m_len, char *mic)
5619 gcry_cipher_hd_t cipher_hd;
5620 unsigned i = 0;
5621 unsigned char block[IEEE802154_CIPHER_SIZE];
5623 /* Open the cipher. */
5624 if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_MAC)) return false;
5626 /* Set the key. */
5627 if (gcry_cipher_setkey(cipher_hd, key, IEEE802154_CIPHER_SIZE)) {
5628 gcry_cipher_close(cipher_hd);
5629 return false;
5632 /* Process the initial value. */
5633 if (gcry_cipher_encrypt(cipher_hd, mic, 16, iv, 16)) {
5634 gcry_cipher_close(cipher_hd);
5635 return false;
5638 /* Encode L(a) */
5639 i = 0;
5641 /* XXX: GINT_MAX is not defined so #if ... will always be false */
5642 #if (GINT_MAX >= (1LL << 32))
5643 if (a_len >= (1LL << 32)) {
5644 block[i++] = 0xff;
5645 block[i++] = 0xff;
5646 block[i++] = (a_len >> 56) & 0xff;
5647 block[i++] = (a_len >> 48) & 0xff;
5648 block[i++] = (a_len >> 40) & 0xff;
5649 block[i++] = (a_len >> 32) & 0xff;
5650 block[i++] = (a_len >> 24) & 0xff;
5651 block[i++] = (a_len >> 16) & 0xff;
5652 block[i++] = (a_len >> 8) & 0xff;
5653 block[i++] = (a_len >> 0) & 0xff;
5655 else
5656 #endif
5657 if (a_len >= ((1 << 16) - (1 << 8))) {
5658 block[i++] = 0xff;
5659 block[i++] = 0xfe;
5660 block[i++] = (a_len >> 24) & 0xff;
5661 block[i++] = (a_len >> 16) & 0xff;
5662 block[i++] = (a_len >> 8) & 0xff;
5663 block[i++] = (a_len >> 0) & 0xff;
5665 else {
5666 block[i++] = (a_len >> 8) & 0xff;
5667 block[i++] = (a_len >> 0) & 0xff;
5669 /* Append a to get the first block of input (pad if we encounter the end of a). */
5670 while ((i < sizeof(block)) && (a_len > 0)) {
5671 block[i++] = *a++;
5672 a_len--;
5674 while (i < sizeof(block)) {
5675 block[i++] = 0;
5678 /* Process the first block of AuthData. */
5679 if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, 16)) {
5680 gcry_cipher_close(cipher_hd);
5681 return false;
5684 /* Transform and process the remainder of a. */
5685 while (a_len > 0) {
5686 /* Copy and pad. */
5687 if ((unsigned)a_len >= sizeof(block)) {
5688 memcpy(block, a, sizeof(block));
5690 else {
5691 memcpy(block, a, a_len);
5692 memset(block+a_len, 0, sizeof(block)-a_len);
5694 /* Adjust pointers. */
5695 a += sizeof(block);
5696 a_len -= (int)sizeof(block);
5697 /* Execute the CBC-MAC algorithm. */
5698 if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, sizeof(block))) {
5699 gcry_cipher_close(cipher_hd);
5700 return false;
5702 } /* while */
5704 /* Process the message, m. */
5705 while (m_len > 0) {
5706 /* Copy and pad. */
5707 if ((unsigned)m_len >= sizeof(block)) {
5708 memcpy(block, m, sizeof(block));
5710 else {
5711 memcpy(block, m, m_len);
5712 memset(block+m_len, 0, sizeof(block)-m_len);
5714 /* Adjust pointers. */
5715 m += sizeof(block);
5716 m_len -= (int)sizeof(block);
5717 /* Execute the CBC-MAC algorithm. */
5718 if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, sizeof(block))) {
5719 gcry_cipher_close(cipher_hd);
5720 return false;
5724 /* Done with the cipher. */
5725 gcry_cipher_close(cipher_hd);
5726 return true;
5727 } /* ccm_cbc_mac */
5729 /* Key hash function. */
5730 unsigned ieee802154_short_addr_hash(const void *key)
5732 return (((const ieee802154_short_addr *)key)->addr) | (((const ieee802154_short_addr *)key)->pan << 16);
5735 /* Key equal function. */
5736 gboolean ieee802154_short_addr_equal(const void *a, const void *b)
5738 return (((const ieee802154_short_addr *)a)->pan == ((const ieee802154_short_addr *)b)->pan) &&
5739 (((const ieee802154_short_addr *)a)->addr == ((const ieee802154_short_addr *)b)->addr);
5742 /* Key hash function. */
5743 unsigned ieee802154_long_addr_hash(const void *key)
5745 return (unsigned)(((const ieee802154_long_addr *)key)->addr) & 0xFFFFFFFF;
5748 /* Key equal function. */
5749 gboolean ieee802154_long_addr_equal(const void *a, const void *b)
5751 return (((const ieee802154_long_addr *)a)->addr == ((const ieee802154_long_addr *)b)->addr);
5754 /* Set MAC key function. */
5755 static unsigned ieee802154_set_mac_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t *uat_key)
5757 ieee802154_set_key_func func = (ieee802154_set_key_func)wmem_tree_lookup32(mac_key_hash_handlers, uat_key->hash_type);
5759 if (func != NULL)
5760 return func(packet, key, alt_key, uat_key);
5762 /* Right now, KEY_HASH_NONE and KEY_HASH_ZIP are not registered because they
5763 work with this "default" behavior */
5764 if (packet->key_index == uat_key->key_index)
5766 memcpy(key, uat_key->key, IEEE802154_CIPHER_SIZE);
5767 return 1;
5770 return 0;
5773 static bool trel_key_derivation_func(/*ieee802154_packet* packet*/ unsigned char* key, uint32_t seq, ieee802154_key_t* uat_key)
5775 uint8_t prk[32]; /* GCRY_MD_SHA256 hash output. */
5776 gcry_error_t err;
5777 uint32_t Key_sequence = seq;
5778 unsigned char ikm[16];
5779 GByteArray* bytes;
5780 bytes = g_byte_array_new();
5781 bool res = hex_str_to_bytes(uat_key->pref_key, bytes, false);
5782 if (!res) return false;
5784 uint8_t saltstring[] = { 'T', 'h', 'r', 'e', 'a', 'd', 'S', 'e', 'q', 'u', 'e', 'n', 'c', 'e', 'M', 'a', 's', 't', 'e', 'r', 'K', 'e', 'y' };
5785 uint8_t info_str[] = { 'T', 'h', 'r', 'e', 'a', 'd', 'O', 'v', 'e','r', 'I', 'n', 'f', 'r', 'a', 'K', 'e', 'y' };
5786 uint8_t salt[sizeof(uint32_t) + sizeof(saltstring)];
5788 salt[0] = (Key_sequence >> 24) & 0xff;
5789 salt[1] = (Key_sequence >> 16) & 0xff;
5790 salt[2] = (Key_sequence >> 8) & 0xff;
5791 salt[3] = (Key_sequence >> 0) & 0xff;
5793 memcpy(ikm, bytes->data, 16);
5794 memcpy(salt + sizeof(uint32_t), saltstring, sizeof(saltstring));
5796 err = hkdf_extract(GCRY_MD_SHA256, salt, sizeof(salt), ikm, sizeof(ikm), prk);
5797 DISSECTOR_ASSERT(err == 0);
5798 err = hkdf_expand(GCRY_MD_SHA256, prk, sizeof(prk), info_str, sizeof(info_str), key, 16);
5799 DISSECTOR_ASSERT(err == 0);
5801 return true;
5803 static unsigned ieee802154_set_trel_key(ieee802154_packet* packet, unsigned char* key, unsigned char* alt_key, ieee802154_key_t* uat_key)
5805 if (packet->key_index == uat_key->key_index && alt_key)
5807 memcpy(key, uat_key->key, IEEE802154_CIPHER_SIZE);
5810 if(trel_key_derivation_func(key, 0, uat_key) == 1)
5811 return 1;
5813 return 0;
5817 * Creates a record that maps the given short address and pan to a long (extended) address.
5818 * @param short_addr 16-bit short address
5819 * @param pan 16-bit PAN id
5820 * @param long_addr 64-bit long (extended) address
5821 * @param proto pointer to name of current protocol
5822 * @param fnum Frame number this mapping became valid
5823 * @return true Record was updated, false Couldn't find it
5825 ieee802154_map_rec *ieee802154_addr_update(ieee802154_map_tab_t *au_ieee802154_map,
5826 uint16_t short_addr, uint16_t pan, uint64_t long_addr, const char *proto, unsigned fnum)
5828 ieee802154_short_addr addr16;
5829 ieee802154_map_rec *p_map_rec;
5830 void * old_key;
5832 /* Look up short address hash */
5833 addr16.pan = pan;
5834 addr16.addr = short_addr;
5835 p_map_rec = (ieee802154_map_rec *)g_hash_table_lookup(au_ieee802154_map->short_table, &addr16);
5837 /* Update mapping record */
5838 if (p_map_rec) {
5839 /* record already exists */
5840 if ( p_map_rec->addr64 == long_addr ) {
5841 /* no change */
5842 return p_map_rec;
5844 else {
5845 /* mark current mapping record invalid */
5846 p_map_rec->end_fnum = fnum;
5850 /* create a new mapping record */
5851 p_map_rec = wmem_new(wmem_file_scope(), ieee802154_map_rec);
5852 p_map_rec->proto = proto;
5853 p_map_rec->start_fnum = fnum;
5854 p_map_rec->end_fnum = 0;
5855 p_map_rec->addr64 = long_addr;
5857 /* link new mapping record to addr hash tables */
5858 if ( g_hash_table_lookup_extended(au_ieee802154_map->short_table, &addr16, &old_key, NULL) ) {
5859 /* update short addr hash table, reusing pointer to old key */
5860 g_hash_table_insert(au_ieee802154_map->short_table, old_key, p_map_rec);
5861 } else {
5862 /* create new hash entry */
5863 g_hash_table_insert(au_ieee802154_map->short_table, wmem_memdup(wmem_file_scope(), &addr16, sizeof(addr16)), p_map_rec);
5866 if ( g_hash_table_lookup_extended(au_ieee802154_map->long_table, &long_addr, &old_key, NULL) ) {
5867 /* update long addr hash table, reusing pointer to old key */
5868 g_hash_table_insert(au_ieee802154_map->long_table, old_key, p_map_rec);
5869 } else {
5870 /* create new hash entry */
5871 g_hash_table_insert(au_ieee802154_map->long_table, wmem_memdup(wmem_file_scope(), &long_addr, sizeof(long_addr)), p_map_rec);
5874 return p_map_rec;
5875 } /* ieee802154_addr_update */
5878 * Marks a mapping record associated with device with short_addr
5879 * as invalid at a certain frame number, typically when a
5880 * disassociation occurs.
5882 * @param short_addr 16-bit short address
5883 * @param pan 16-bit PAN id
5884 * @param fnum Frame number when mapping became invalid
5885 * @return true Record was updated, false Couldn't find it
5887 bool ieee802154_short_addr_invalidate(uint16_t short_addr, uint16_t pan, unsigned fnum)
5889 ieee802154_short_addr addr16;
5890 ieee802154_map_rec *map_rec;
5892 addr16.pan = pan;
5893 addr16.addr = short_addr;
5895 map_rec = (ieee802154_map_rec *)g_hash_table_lookup(ieee802154_map.short_table, &addr16);
5896 if ( map_rec ) {
5897 /* indicates this mapping is invalid at frame fnum */
5898 map_rec->end_fnum = fnum;
5899 return true;
5902 return false;
5903 } /* ieee802154_short_addr_invalidate */
5906 * Mark a mapping record associated with device with long_addr
5907 * as invalid at a certain frame number, typically when a
5908 * disassociation occurs.
5910 * @param long_addr 16-bit short address
5911 * @param fnum Frame number when mapping became invalid
5912 * @return true If record was updated, false otherwise
5914 bool ieee802154_long_addr_invalidate(uint64_t long_addr, unsigned fnum)
5916 ieee802154_map_rec *map_rec;
5918 map_rec = (ieee802154_map_rec *)g_hash_table_lookup(ieee802154_map.long_table, &long_addr);
5919 if ( map_rec ) {
5920 /* indicates this mapping is invalid at frame fnum */
5921 map_rec->end_fnum = fnum;
5922 return true;
5925 return false;
5926 } /* ieee802154_long_addr_invalidate */
5929 * Init routine for the IEEE 802.15.4 dissector. Creates hash
5930 * tables for mapping between 16-bit to 64-bit addresses and
5931 * populates them with static address pairs from a UAT
5932 * preference table.
5934 static void
5935 proto_init_ieee802154(void)
5937 unsigned i;
5939 ieee802154_map.short_table = g_hash_table_new(ieee802154_short_addr_hash, ieee802154_short_addr_equal);
5940 ieee802154_map.long_table = g_hash_table_new(ieee802154_long_addr_hash, ieee802154_long_addr_equal);
5941 /* Reload the hash table from the static address UAT. */
5942 for (i=0; (i<num_static_addrs) && (static_addrs); i++) {
5943 ieee802154_addr_update(&ieee802154_map,(uint16_t)static_addrs[i].addr16, (uint16_t)static_addrs[i].pan,
5944 pntoh64(static_addrs[i].eui64), ieee802154_user, IEEE802154_USER_MAPPING);
5945 } /* for */
5946 } /* proto_init_ieee802154 */
5949 * Cleanup for the IEEE 802.15.4 dissector.
5951 static void
5952 proto_cleanup_ieee802154(void)
5954 g_hash_table_destroy(ieee802154_map.short_table);
5955 g_hash_table_destroy(ieee802154_map.long_table);
5958 /* Returns the prompt string for the Decode-As dialog. */
5959 static void ieee802154_da_prompt(packet_info *pinfo _U_, char* result)
5961 ieee802154_hints_t *hints;
5962 hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
5963 if (hints)
5964 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IEEE 802.15.4 PAN 0x%04x as", hints->src_pan);
5965 else
5966 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IEEE 802.15.4 PAN Unknown");
5967 } /* iee802154_da_prompt */
5969 /* Returns the value to index the panid decode table with (source PAN)*/
5970 static void *ieee802154_da_value(packet_info *pinfo _U_)
5972 ieee802154_hints_t *hints;
5973 hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
5974 if (hints)
5975 return GUINT_TO_POINTER((unsigned)(hints->src_pan));
5976 else
5977 return NULL;
5978 } /* iee802154_da_value */
5980 static const char* ieee802154_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter)
5982 if (filter == CONV_FT_SRC_ADDRESS) {
5983 if (conv->src_address.type == ieee802_15_4_short_address_type)
5984 return "wpan.src16";
5985 else if (conv->src_address.type == AT_EUI64)
5986 return "wpan.src64";
5989 if (filter == CONV_FT_DST_ADDRESS) {
5990 if (conv->dst_address.type == ieee802_15_4_short_address_type)
5991 return "wpan.dst16";
5992 else if (conv->dst_address.type == AT_EUI64)
5993 return "wpan.dst64";
5996 if (filter == CONV_FT_ANY_ADDRESS) {
5997 if (conv->src_address.type == ieee802_15_4_short_address_type)
5998 return "wpan.addr16";
5999 else if (conv->src_address.type == AT_EUI64)
6000 return "wpan.addr64";
6003 return CONV_FILTER_INVALID;
6006 static ct_dissector_info_t ieee802154_ct_dissector_info = {&ieee802154_conv_get_filter_type };
6008 static tap_packet_status ieee802154_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_, tap_flags_t flags)
6010 conv_hash_t *hash = (conv_hash_t*)pct;
6011 hash->flags = flags;
6013 add_conversation_table_data(hash, &pinfo->dl_src, &pinfo->dl_dst, 0, 0, 1,
6014 pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts,
6015 &ieee802154_ct_dissector_info, CONVERSATION_NONE);
6017 return TAP_PACKET_REDRAW;
6020 static const char* ieee802154_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter)
6022 if (filter == CONV_FT_ANY_ADDRESS) {
6023 if (endpoint->myaddress.type == ieee802_15_4_short_address_type)
6024 return "wpan.addr16";
6025 else if (endpoint->myaddress.type == AT_EUI64)
6026 return "wpan.addr64";
6029 return CONV_FILTER_INVALID;
6032 static et_dissector_info_t ieee802154_endpoint_dissector_info = {&ieee802154_endpoint_get_filter_type };
6034 static tap_packet_status ieee802154_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_, tap_flags_t flags)
6036 conv_hash_t *hash = (conv_hash_t*)pit;
6037 hash->flags = flags;
6039 /* Take two "add" passes per packet, adding for each direction, ensures that all
6040 packets are counted properly (even if address is sending to itself)
6041 XXX - this could probably be done more efficiently inside endpoint_table */
6042 add_endpoint_table_data(hash, &pinfo->dl_src, 0, true, 1,
6043 pinfo->fd->pkt_len, &ieee802154_endpoint_dissector_info, ENDPOINT_NONE);
6044 add_endpoint_table_data(hash, &pinfo->dl_dst, 0, false, 1,
6045 pinfo->fd->pkt_len, &ieee802154_endpoint_dissector_info, ENDPOINT_NONE);
6047 return TAP_PACKET_REDRAW;
6050 static bool ieee802154_filter_valid(packet_info *pinfo, void *user_data _U_)
6052 return proto_is_frame_protocol(pinfo->layers, "wpan")
6053 && ((pinfo->dl_src.type == ieee802_15_4_short_address_type) || (pinfo->dl_src.type == AT_EUI64))
6054 && ((pinfo->dl_dst.type == ieee802_15_4_short_address_type) || (pinfo->dl_dst.type == AT_EUI64));
6057 static char* ieee802154_build_filter(packet_info *pinfo, void *user_data _U_)
6059 return ws_strdup_printf("wpan.%s eq %s and wpan.%s eq %s",
6060 (pinfo->dl_src.type == ieee802_15_4_short_address_type) ? "addr16" : "addr64",
6061 address_to_str(pinfo->pool, &pinfo->dl_src),
6062 (pinfo->dl_dst.type == ieee802_15_4_short_address_type) ? "addr16" : "addr64",
6063 address_to_str(pinfo->pool, &pinfo->dl_dst));
6067 * IEEE 802.15.4 protocol registration routine.
6069 void proto_register_ieee802154(void)
6071 /* Protocol fields */
6072 static hf_register_info hf_phy[] = {
6073 /* PHY level */
6075 { &hf_ieee802154_nonask_phy_preamble,
6076 { "Preamble", "wpan-nonask-phy.preamble", FT_UINT32, BASE_HEX, NULL, 0x0,
6077 NULL, HFILL }},
6079 { &hf_ieee802154_nonask_phy_sfd,
6080 { "Start of Frame Delimiter", "wpan-nonask-phy.sfd", FT_UINT8, BASE_HEX, NULL, 0x0,
6081 NULL, HFILL }},
6083 { &hf_ieee802154_nonask_phy_length,
6084 { "Frame Length", "wpan-nonask-phy.frame_length", FT_UINT8, BASE_HEX, NULL,
6085 IEEE802154_PHY_LENGTH_MASK, NULL, HFILL }},
6087 { &hf_ieee802154_nonask_phr,
6088 { "PHR", "wpan-nonask-phy.phr", FT_UINT8, BASE_HEX, NULL,
6089 0x0, NULL, HFILL }},
6092 static hf_register_info hf[] = {
6094 { &hf_ieee802154_frame_length,
6095 { "Frame Length", "wpan.frame_length", FT_UINT8, BASE_DEC, NULL, 0x0,
6096 "Frame Length as reported from lower layer", HFILL }},
6098 { &hf_ieee802154_fcf,
6099 { "Frame Control Field", "wpan.fcf", FT_UINT16, BASE_HEX, NULL,
6100 0x0, NULL, HFILL }},
6102 { &hf_ieee802154_frame_type,
6103 { "Frame Type", "wpan.frame_type", FT_UINT16, BASE_HEX, VALS(ieee802154_frame_types),
6104 IEEE802154_FCF_TYPE_MASK, NULL, HFILL }},
6106 { &hf_ieee802154_security,
6107 { "Security Enabled", "wpan.security", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_SEC_EN,
6108 "Whether security operations are performed at the MAC layer or not.", HFILL }},
6110 { &hf_ieee802154_pending,
6111 { "Frame Pending", "wpan.pending", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_FRAME_PND,
6112 "Indication of additional packets waiting to be transferred from the source device.", HFILL }},
6114 { &hf_ieee802154_ack_request,
6115 { "Acknowledge Request", "wpan.ack_request", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_ACK_REQ,
6116 "Whether the sender of this packet requests acknowledgment or not.", HFILL }},
6118 { &hf_ieee802154_pan_id_compression,
6119 { "PAN ID Compression", "wpan.pan_id_compression", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_PAN_ID_COMPRESSION,
6120 "Whether this packet contains the PAN ID or not.", HFILL }},
6122 { &hf_ieee802154_fcf_reserved,
6123 { "Reserved", "wpan.fcf.reserved", FT_BOOLEAN, 16, NULL, 0x0080,
6124 NULL, HFILL }},
6126 { &hf_ieee802154_seqno_suppression,
6127 { "Sequence Number Suppression", "wpan.seqno_suppression", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_SEQNO_SUPPRESSION,
6128 "Whether this packet contains the Sequence Number or not.", HFILL }},
6130 { &hf_ieee802154_ie_present,
6131 { "Information Elements Present", "wpan.ie_present", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_IE_PRESENT,
6132 "Whether this packet contains the Information Elements or not.", HFILL }},
6134 { &hf_ieee802154_dst_addr_mode,
6135 { "Destination Addressing Mode", "wpan.dst_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
6136 IEEE802154_FCF_DADDR_MASK, NULL, HFILL }},
6138 { &hf_ieee802154_version,
6139 { "Frame Version", "wpan.version", FT_UINT16, BASE_DEC, VALS(ieee802154_frame_versions),
6140 IEEE802154_FCF_VERSION, NULL, HFILL }},
6142 { &hf_ieee802154_src_addr_mode,
6143 { "Source Addressing Mode", "wpan.src_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
6144 IEEE802154_FCF_SADDR_MASK, NULL, HFILL }},
6146 /* 802.15.4-2015 Multipurpose frame control fields */
6147 { &hf_ieee802154_mpf_long_frame_control,
6148 { "Long Frame Control", "wpan.long_frame_control", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_LONG_FC,
6149 "Whether this frame control field uses one or two octets.", HFILL }},
6151 { &hf_ieee802154_mpf_dst_addr_mode,
6152 { "Destination Addressing Mode", "wpan.dst_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
6153 IEEE802154_MPF_FCF_DADDR_MASK, NULL, HFILL }},
6155 { &hf_ieee802154_mpf_src_addr_mode,
6156 { "Source Addressing Mode", "wpan.src_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
6157 IEEE802154_MPF_FCF_SADDR_MASK, NULL, HFILL }},
6159 { &hf_ieee802154_mpf_pan_id_present,
6160 { "PAN ID Present", "wpan.pan_id_present", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_PAN_ID_PRESENT,
6161 "Whether this packet contains the destination PAN ID or not", HFILL }},
6163 { &hf_ieee802154_mpf_security,
6164 { "Security Enabled", "wpan.security", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_SEC_EN,
6165 "Whether security operations are performed at the MAC layer or not.", HFILL }},
6167 { &hf_ieee802154_mpf_seqno_suppression,
6168 { "Sequence Number Suppression", "wpan.seqno_suppression", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_SEQNO_SUPPRESSION,
6169 "Whether this packet contains the Sequence Number or not.", HFILL }},
6171 { &hf_ieee802154_mpf_pending,
6172 { "Frame Pending", "wpan.pending", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_FRAME_PND,
6173 "Indication of additional packets waiting to be transferred from the source device.", HFILL }},
6175 { &hf_ieee802154_mpf_version,
6176 { "Multipurpose Frame Version", "wpan.mpf_version", FT_UINT16, BASE_DEC, NULL,
6177 IEEE802154_MPF_FCF_VERSION, NULL, HFILL }},
6179 { &hf_ieee802154_mpf_ack_request,
6180 { "Acknowledge Request", "wpan.ack_request", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_ACK_REQ,
6181 "Whether the sender of this packet requests acknowledgment or not.", HFILL }},
6183 { &hf_ieee802154_mpf_ie_present,
6184 { "Information Elements Present", "wpan.ie_present", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_IE_PRESENT,
6185 "Whether this packet contains the Information Elements or not.", HFILL }},
6187 { &hf_ieee802154_seqno,
6188 { "Sequence Number", "wpan.seq_no", FT_UINT8, BASE_DEC, NULL, 0x0,
6189 NULL, HFILL }},
6191 { &hf_ieee802154_dst_panID,
6192 { "Destination PAN", "wpan.dst_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
6193 NULL, HFILL }},
6195 { &hf_ieee802154_dst16,
6196 { "Destination", "wpan.dst16", FT_UINT16, BASE_HEX, NULL, 0x0,
6197 NULL, HFILL }},
6199 { &hf_ieee802154_dst64,
6200 { "Destination", "wpan.dst64", FT_EUI64, BASE_NONE, NULL, 0x0,
6201 NULL, HFILL }},
6203 { &hf_ieee802154_src_panID,
6204 { "Source PAN", "wpan.src_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
6205 NULL, HFILL }},
6207 { &hf_ieee802154_src16,
6208 { "Source", "wpan.src16", FT_UINT16, BASE_HEX, NULL, 0x0,
6209 NULL, HFILL }},
6211 { &hf_ieee802154_src64,
6212 { "Extended Source", "wpan.src64", FT_EUI64, BASE_NONE, NULL, 0x0,
6213 NULL, HFILL }},
6215 { &hf_ieee802154_addr16,
6216 { "Address", "wpan.addr16", FT_UINT16, BASE_HEX, NULL, 0x0,
6217 NULL, HFILL }},
6219 { &hf_ieee802154_addr64,
6220 { "Extended Address", "wpan.addr64", FT_EUI64, BASE_NONE, NULL, 0x0,
6221 NULL, HFILL }},
6223 { &hf_ieee802154_src64_origin,
6224 { "Origin", "wpan.src64.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
6225 NULL, HFILL }},
6227 { &hf_ieee802154_fcs,
6228 { "FCS", "wpan.fcs", FT_UINT16, BASE_HEX, NULL, 0x0,
6229 NULL, HFILL }},
6231 { &hf_ieee802154_fcs32,
6232 { "FCS", "wpan.fcs32", FT_UINT32, BASE_HEX, NULL, 0x0,
6233 NULL, HFILL }},
6235 { &hf_ieee802154_rssi,
6236 { "RSSI", "wpan.rssi", FT_INT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_decibels), 0x0,
6237 "Received Signal Strength", HFILL }},
6239 { &hf_ieee802154_fcs_ok,
6240 { "FCS Valid", "wpan.fcs_ok", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
6241 NULL, HFILL }},
6243 { &hf_ieee802154_correlation,
6244 { "LQI Correlation Value", "wpan.correlation", FT_UINT8, BASE_DEC, NULL, 0x0,
6245 NULL, HFILL }},
6247 /* Information Elements */
6249 { &hf_ieee802154_ie_unknown_content,
6250 { "Unknown Content", "wpan.ie.unknown_content", FT_BYTES, SEP_SPACE, NULL, 0x0,
6251 NULL, HFILL }},
6253 { &hf_ieee802154_ie_unknown_content_payload,
6254 { "Unknown Content Payload", "wpan.ie.unknown_content_payload", FT_BYTES, SEP_SPACE, NULL, 0x0,
6255 NULL, HFILL }},
6257 /* Header IE */
6259 { &hf_ieee802154_header_ies,
6260 { "Header IEs", "wpan.header_ie", FT_NONE, BASE_NONE, NULL,
6261 0x0, NULL, HFILL }},
6263 { &hf_ieee802154_header_ie_tlv,
6264 { "IE Header", "wpan.header_ie_tlv", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
6266 { &hf_ieee802154_header_ie_type,
6267 { "Type", "wpan.header_ie.type", FT_UINT16, BASE_DEC, VALS(ieee802154_ie_types),
6268 IEEE802154_HEADER_IE_TYPE_MASK, NULL, HFILL }},
6270 { &hf_ieee802154_header_ie_id,
6271 { "Id", "wpan.header_ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_header_ie_names),
6272 IEEE802154_HEADER_IE_ID_MASK, NULL, HFILL }},
6274 { &hf_ieee802154_header_ie_length,
6275 { "Length", "wpan.header_ie.length", FT_UINT16, BASE_DEC, NULL,
6276 IEEE802154_HEADER_IE_LENGTH_MASK, NULL, HFILL }},
6279 /* Individual Header IEs */
6281 { &hf_ieee802154_hie_unsupported,
6282 { "Unsupported Header IE", "wpan.header_ie.unsupported", FT_NONE, BASE_NONE, NULL, 0x0,
6283 NULL, HFILL }},
6285 { &hf_ieee802154_hie_ht1,
6286 { "Header Termination 1 IE (Payload IEs follow)", "wpan.header_ie.ht1", FT_NONE, BASE_NONE, NULL, 0x0,
6287 NULL, HFILL }},
6289 { &hf_ieee802154_hie_ht2,
6290 { "Header Termination 2 IE (Payload follows)", "wpan.header_ie.ht2", FT_NONE, BASE_NONE, NULL, 0x0,
6291 NULL, HFILL }},
6293 { &hf_ieee802154_hie_thread,
6294 { "Thread IE (Payload follows)", "wpan.header_ie.thread", FT_NONE, BASE_NONE, NULL, 0x0,
6295 NULL, HFILL }},
6298 /* Time correction IE */
6299 { &hf_ieee802154_hie_time_correction,
6300 { "Time Correction IE", "wpan.header_ie.time_correction", FT_NONE, BASE_NONE, NULL, 0x0,
6301 NULL, HFILL }},
6303 { &hf_ieee802154_hie_time_correction_time_sync_info,
6304 { "Time Sync Info", "wpan.header_ie.time_correction.time_sync_info", FT_UINT16, BASE_HEX, NULL, 0x0,
6305 NULL, HFILL }},
6307 { &hf_ieee802154_nack,
6308 { "Nack", "wpan.nack", FT_BOOLEAN, 16, TFS(&hf_ieee802154_nack_tfs), 0x8000,
6309 NULL, HFILL }},
6311 { &hf_ieee802154_hie_time_correction_value,
6312 { "Time Correction", "wpan.header_ie.time_correction.value", FT_INT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microseconds), 0x0FFF,
6313 "Time correction in microseconds", HFILL }},
6315 /* CSL IE */
6316 { &hf_ieee802154_hie_csl,
6317 { "CSL IE", "wpan.header_ie.csl", FT_NONE, BASE_NONE, NULL, 0x0,
6318 NULL, HFILL }},
6320 { &hf_ieee802154_hie_csl_phase,
6321 { "Phase", "wpan.header_ie.csl.phase", FT_INT16, BASE_DEC, NULL, 0x0,
6322 "CSL Phase in units of 10 symbols", HFILL }},
6324 { &hf_ieee802154_hie_csl_period,
6325 { "Period", "wpan.header_ie.csl.period", FT_INT16, BASE_DEC, NULL, 0x0,
6326 "CSL Period in units of 10 symbols", HFILL }},
6328 { &hf_ieee802154_hie_csl_rendezvous_time,
6329 { "Rendezvous Time", "wpan.header_ie.csl.rendezvous_time", FT_INT16, BASE_DEC, NULL, 0x0,
6330 "CSL Rendezvous Time in units of 10 symbols", HFILL }},
6332 /* RendezVous Time IE */
6333 { &hf_ieee802154_hie_rdv,
6334 { "Rendezvous Time IE", "wpan.header_ie.rdv", FT_NONE, BASE_NONE, NULL, 0x0,
6335 NULL, HFILL }},
6337 { &hf_ieee802154_hie_rdv_wakeup_interval,
6338 { "Wake-up Interval", "wpan.header_ie.csl.wakeup_interval", FT_INT16, BASE_DEC, NULL, 0x0,
6339 "Interval between two successive Wake-Up frames, in units of 10 symbols", HFILL }},
6341 /* Global Time IE */
6342 { &hf_ieee802154_hie_global_time,
6343 { "Global Time IE", "wpan.header_ie.global_time", FT_NONE, BASE_NONE, NULL, 0x0,
6344 NULL, HFILL }},
6346 { &hf_ieee802154_hie_global_time_value,
6347 { "Global Time", "wpan.header_ie.global_time.value", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0,
6348 NULL, HFILL }},
6350 /* Vendor Specific IE */
6351 { &hf_ieee802154_hie_vendor_specific,
6352 { "Vendor Specific IE", "wpan.header_ie.vendor_specific", FT_NONE, BASE_NONE, NULL, 0x0,
6353 NULL, HFILL }},
6355 { &hf_ieee802154_hie_vendor_specific_vendor_oui,
6356 { "Vendor OUI", "wpan.header_ie.vendor_specific.vendor_oui", FT_UINT24, BASE_OUI, NULL, 0x0,
6357 NULL, HFILL }},
6359 { &hf_ieee802154_hie_vendor_specific_content,
6360 { "Vendor Content", "wpan.header_ie.vendor_specific.content", FT_BYTES, SEP_SPACE, NULL, 0x0,
6361 NULL, HFILL }},
6363 /* Payload IEs */
6365 { &hf_ieee802154_payload_ies,
6366 { "Payload IEs", "wpan.payload_ie", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6368 { &hf_ieee802154_payload_ie_tlv,
6369 { "IE Header", "wpan.payload_ie_tlv", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
6371 { &hf_ieee802154_payload_ie_type,
6372 { "Type", "wpan.payload_ie.type", FT_UINT16, BASE_DEC, VALS(ieee802154_ie_types),
6373 IEEE802154_PAYLOAD_IE_TYPE_MASK, NULL, HFILL }},
6375 { &hf_ieee802154_payload_ie_id,
6376 { "Id", "wpan.payload_ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_payload_ie_names),
6377 IEEE802154_PAYLOAD_IE_ID_MASK, NULL, HFILL }},
6379 { &hf_ieee802154_payload_ie_length,
6380 { "Length", "wpan.payload_ie.length", FT_UINT16, BASE_DEC, NULL,
6381 IEEE802154_PAYLOAD_IE_LENGTH_MASK, NULL, HFILL }},
6384 /* Individual Payload IEs */
6386 { &hf_ieee802154_pie_unsupported,
6387 { "Unknown Payload IE", "wpan.payload_ie.unknown", FT_NONE, BASE_NONE, NULL, 0x0,
6388 NULL, HFILL }},
6390 { &hf_ieee802154_pie_termination,
6391 { "Payload Termination IE", "wpan.payload_ie.termination", FT_NONE, BASE_NONE, NULL, 0x0,
6392 NULL, HFILL }},
6394 { &hf_ieee802154_pie_vendor,
6395 { "Vendor Specific IE", "wpan.payload_ie.vendor", FT_NONE, BASE_NONE, NULL, 0x0,
6396 NULL, HFILL }},
6398 { &hf_ieee802154_pie_vendor_oui,
6399 { "Vendor OUI", "wpan.payload_ie.vendor.oui", FT_UINT24, BASE_OUI, NULL, 0x0,
6400 NULL, HFILL }},
6402 { &hf_ieee802154_pie_vendor_variable,
6403 { "Vendor variable", "wpan.payload_ie.vendor.variable", FT_BYTES, BASE_NONE, NULL, 0x0,
6404 NULL, HFILL }},
6406 { &hf_ieee802154_mlme,
6407 { "MLME IE", "wpan.mlme", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6409 { &hf_ieee802154_psie_type,
6410 { "Type", "wpan.mlme.ie.type", FT_UINT16, BASE_DEC, VALS(ieee802154_psie_types),
6411 IEEE802154_PSIE_TYPE_MASK, NULL, HFILL }},
6413 { &hf_ieee802154_psie,
6414 { "MLME Sub IE", "wpan.mlme.ie", FT_UINT16, BASE_HEX, NULL,
6415 0x0, NULL, HFILL }},
6417 { &hf_ieee802154_psie_id_short,
6418 { "Sub ID", "wpan.mlme.ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_psie_names),
6419 IEEE802154_PSIE_ID_MASK_SHORT, NULL, HFILL }},
6421 { &hf_ieee802154_psie_length_short,
6422 { "Length", "wpan.mlme.ie.length", FT_UINT16, BASE_DEC, NULL,
6423 IEEE802154_PSIE_LENGTH_MASK_SHORT, NULL, HFILL }},
6425 { &hf_ieee802154_psie_id_long,
6426 { "Sub ID", "wpan.mlme.ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_psie_names),
6427 IEEE802154_PSIE_ID_MASK_LONG, NULL, HFILL }},
6429 { &hf_ieee802154_psie_length_long,
6430 { "Length", "wpan.mlme.ie.length", FT_UINT16, BASE_DEC, NULL,
6431 IEEE802154_PSIE_LENGTH_MASK_LONG, NULL, HFILL }},
6433 { &hf_ieee802154_mlme_ie_unsupported,
6434 { "Unsupported Sub IE", "wpan.mlme.unsupported", FT_NONE, BASE_NONE, NULL,
6435 0, NULL, HFILL }},
6437 { &hf_ieee802154_mlme_ie_data,
6438 { "Data", "wpan.mlme.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6440 { &hf_ieee802154_psie_eb_filter,
6441 { "Enhanced Beacon Filter", "wpan.eb_filter", FT_UINT8, BASE_HEX, NULL,
6442 0, NULL, HFILL }},
6444 { &hf_ieee802154_psie_eb_filter_pjoin,
6445 { "Permit Join Filter", "wpan.eb_filter.pjoin", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
6446 IEEE802154_MLME_PSIE_EB_FLT_PJOIN, NULL, HFILL }},
6448 { &hf_ieee802154_psie_eb_filter_lqi,
6449 { "LQI Filter", "wpan.eb_filter.lqi", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
6450 IEEE802154_MLME_PSIE_EB_FLT_LQI, NULL, HFILL }},
6452 { &hf_ieee802154_psie_eb_filter_lqi_min,
6453 { "Minimum LQI", "wpan.eb_filter.lqi_minimum", FT_UINT8, BASE_DEC, NULL,
6454 0x0, NULL, HFILL }},
6456 { &hf_ieee802154_psie_eb_filter_percent,
6457 { "Probability to Respond", "wpan.eb_filter.contains_prob", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
6458 IEEE802154_MLME_PSIE_EB_FLT_PERCENT, NULL, HFILL }},
6460 { &hf_ieee802154_psie_eb_filter_percent_prob,
6461 { "Response Probability Percentage", "wpan.eb_filter.prob", FT_UINT8, BASE_DEC, NULL,
6462 0x0, NULL, HFILL }},
6464 { &hf_ieee802154_psie_eb_filter_attr_id,
6465 { "Requested Attribute Length", "wpan.eb_filter.attr_id", FT_UINT8, BASE_DEC, NULL,
6466 IEEE802154_MLME_PSIE_EB_FLT_ATTR_LEN, NULL, HFILL }},
6468 { &hf_ieee802154_psie_eb_filter_attr_id_bitmap,
6469 { "Attribute ID Bitmap", "wpan.eb_filter.attr_id_bits", FT_UINT24, BASE_HEX, NULL,
6470 0x0, NULL, HFILL }},
6472 { &hf_ieee802154_tsch_sync,
6473 { "TSCH Synchronization IE", "wpan.tsch.time_sync", FT_NONE, BASE_NONE, NULL, 0x0,
6474 NULL, HFILL }},
6476 { &hf_ieee802154_tsch_asn,
6477 { "Absolute Slot Number", "wpan.tsch.asn", FT_UINT40, BASE_DEC, NULL, 0x0,
6478 NULL, HFILL }},
6480 { &hf_ieee802154_tsch_join_metric,
6481 { "Join Metric", "wpan.tsch.join_metric", FT_UINT8, BASE_DEC, NULL, 0x0,
6482 NULL, HFILL }},
6484 { &hf_ieee802154_tsch_timeslot,
6485 { "TSCH Timeslot IE", "wpan.tsch.timeslot", FT_NONE, BASE_NONE, NULL, 0x0,
6486 NULL, HFILL }},
6488 { &hf_ieee802154_tsch_timeslot_id,
6489 { "Timeslot ID", "wpan.tsch.timeslot.id", FT_UINT8, BASE_HEX, NULL, 0x0,
6490 "Identifier of the Timeslot Template", HFILL }},
6492 { &hf_ieee802154_tsch_timeslot_cca_offset,
6493 { "CCA Offset", "wpan.tsch.timeslot.cca_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6494 "Time between the beginning of the timeslot and the start of CCA", HFILL }},
6496 { &hf_ieee802154_tsch_timeslot_cca,
6497 { "CCA", "wpan.tsch.timeslot.cca", FT_UINT16, BASE_DEC, NULL, 0x0,
6498 "Duration of CCA", HFILL }},
6500 { &hf_ieee802154_tsch_timeslot_tx_offset,
6501 { "TX Offset", "wpan.tsch.timeslot.tx_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6502 "Time between the beginning of the timeslot and the start of frame transmission", HFILL }},
6504 { &hf_ieee802154_tsch_timeslot_rx_offset,
6505 { "RX Offset", "wpan.tsch.timeslot.rx_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6506 "Time between the beginning of the timeslot to when the receiver shall be listening", HFILL }},
6508 { &hf_ieee802154_tsch_timeslot_rx_ack_delay,
6509 { "RX Ack Delay", "wpan.tsch.timeslot.rx_ack_delay", FT_UINT16, BASE_DEC, NULL, 0x0,
6510 "Time between the end of frame to when the transmitter shall listen for acknowledgment", HFILL }},
6512 { &hf_ieee802154_tsch_timeslot_tx_ack_delay,
6513 { "TX Ack Delay", "wpan.tsch.timeslot.tx_ack_delay", FT_UINT16, BASE_DEC, NULL, 0x0,
6514 "Time between the end of frame to start of acknowledgment", HFILL }},
6516 { &hf_ieee802154_tsch_timeslot_rx_wait,
6517 { "RX Wait", "wpan.tsch.timeslot.rx_wait", FT_UINT16, BASE_DEC, NULL, 0x0,
6518 "Time to wait for the start of frame", HFILL }},
6520 { &hf_ieee802154_tsch_timeslot_ack_wait,
6521 { "Ack Wait", "wpan.tsch.timeslot.ack_wait", FT_UINT16, BASE_DEC, NULL, 0x0,
6522 "Minimum time to wait for the start of an acknowledgment", HFILL }},
6524 { &hf_ieee802154_tsch_timeslot_turnaround,
6525 { "Turn Around", "wpan.tsch.timeslot.turnaround", FT_UINT16, BASE_DEC, NULL, 0x0,
6526 "Transmit to receive turnaround time", HFILL }},
6528 { &hf_ieee802154_tsch_timeslot_max_ack,
6529 { "Max Ack", "wpan.tsch.timeslot.max_ack", FT_UINT16, BASE_DEC, NULL, 0x0,
6530 "Transmission time to send an acknowledgment", HFILL }},
6532 { &hf_ieee802154_tsch_timeslot_max_tx,
6533 { "Max TX", "wpan.tsch.timeslot.max_tx", FT_UINT24, BASE_DEC, NULL, 0x0,
6534 "Transmission time to send the maximum length frame", HFILL }},
6536 { &hf_ieee802154_tsch_timeslot_length,
6537 { "Timeslot Length", "wpan.tsch.timeslot.length", FT_UINT24, BASE_DEC, NULL, 0x0,
6538 "Total length of the timeslot, including any unused time after frame transmission", HFILL }},
6540 { &hf_ieee802154_tsch_channel_hopping,
6541 { "Channel Hopping IE", "wpan.channel_hopping", FT_NONE, BASE_NONE, NULL, 0x0,
6542 NULL, HFILL }},
6544 { &hf_ieee802154_tsch_slotframe,
6545 { "Slotframe IE", "wpan.tsch.slotframe", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6547 { &hf_ieee802154_tsch_link_info,
6548 { "Link Information", "wpan.tsch.link_info", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6550 { &hf_ieee802154_tsch_slotf_link_nb_slotf,
6551 { "Number of Slotframes", "wpan.tsch.slotframe_num", FT_UINT8, BASE_DEC, NULL, 0x0,
6552 NULL, HFILL }},
6554 { &hf_ieee802154_tsch_slotf_link_slotf_handle,
6555 { "Slotframe handle", "wpan.tsch.slotframe_handle", FT_UINT8, BASE_DEC, NULL, 0x0,
6556 NULL, HFILL }},
6558 { &hf_ieee802154_tsch_slotf_size,
6559 { "Slotframe size", "wpan.tsch.slotframe_size", FT_UINT16, BASE_DEC, NULL, 0x0,
6560 NULL, HFILL }},
6562 { &hf_ieee802154_tsch_slotf_link_nb_links,
6563 { "Number of Links", "wpan.tsch.nb_links", FT_UINT8, BASE_DEC, NULL, 0x0,
6564 NULL, HFILL }},
6566 { &hf_ieee802154_tsch_slotf_link_timeslot,
6567 { "Timeslot", "wpan.tsch.link_timeslot", FT_UINT16, BASE_DEC, NULL, 0x0,
6568 NULL, HFILL }},
6570 { &hf_ieee802154_tsch_slotf_link_channel_offset,
6571 { "Channel Offset", "wpan.tsch.channel_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6572 NULL, HFILL }},
6574 { &hf_ieee802154_tsch_slotf_link_options,
6575 { "Link Options", "wpan.tsch.link_options", FT_UINT8, BASE_HEX, NULL, 0x0,
6576 NULL, HFILL }},
6578 { &hf_ieee802154_tsch_slotf_link_options_tx,
6579 { "TX Link", "wpan.tsch.link_options.tx", FT_BOOLEAN, 8, NULL, (1 << 0),
6580 NULL, HFILL }},
6582 { &hf_ieee802154_tsch_slotf_link_options_rx,
6583 { "RX Link", "wpan.tsch.link_options.rx", FT_BOOLEAN, 8, NULL, (1 << 1),
6584 NULL, HFILL }},
6586 { &hf_ieee802154_tsch_slotf_link_options_shared,
6587 { "Shared Link", "wpan.tsch.link_options.shared", FT_BOOLEAN, 8, NULL, (1 << 2),
6588 NULL, HFILL }},
6590 { &hf_ieee802154_tsch_slotf_link_options_timkeeping,
6591 { "Timekeeping", "wpan.tsch.link_options.timekeeping", FT_BOOLEAN, 8, NULL, (1 << 3),
6592 NULL, HFILL }},
6594 { &hf_ieee802154_tsch_slotf_link_options_priority,
6595 { "Priority", "wpan.tsch.link_options.priority", FT_BOOLEAN, 8, NULL, (1 << 4),
6596 NULL, HFILL }},
6598 { &hf_ieee802154_tsch_hopping_sequence_id,
6599 { "Hopping Sequence ID", "wpan.tsch.hopping_sequence_id", FT_UINT8, BASE_HEX, NULL, 0x0,
6600 NULL, HFILL }},
6602 /* IETF IE */
6603 { &hf_ieee802154_pie_ietf,
6604 { "IETF Payload IE", "wpan.payload_ie.ietf", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6606 { &hf_ieee802154_p_ie_ietf_sub_id,
6607 { "Sub-ID", "wpan.ietf_ie.sub_id", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
6609 /* IETF IE - 6top IE */
6610 { &hf_ieee802154_6top,
6611 { "6top IE", "wpan.6top", FT_NONE, BASE_NONE, NULL, 0x0,
6612 NULL, HFILL }},
6614 { &hf_ieee802154_6top_version,
6615 { "6P Version", "wpan.6top_version", FT_UINT8, BASE_DEC, NULL, IETF_6TOP_VERSION,
6616 NULL, HFILL }},
6618 { &hf_ieee802154_6top_type,
6619 { "Type", "wpan.6top_type", FT_UINT8, BASE_HEX, VALS(ietf_6top_types), IETF_6TOP_TYPE,
6620 NULL, HFILL }},
6622 { &hf_ieee802154_6top_flags_reserved,
6623 { "Reserved", "wpan.6top_flags_reserved", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_FLAGS_RESERVED,
6624 NULL, HFILL }},
6626 { &hf_ieee802154_6top_code,
6627 { "Code", "wpan.6top_code", FT_UINT8, BASE_HEX, NULL, 0x0,
6628 NULL, HFILL }},
6630 { &hf_ieee802154_6top_sfid,
6631 { "SFID (6top Scheduling Function ID)", "wpan.6top_sfid", FT_UINT8, BASE_HEX, NULL, 0x0,
6632 NULL, HFILL }},
6634 { &hf_ieee802154_6top_seqnum,
6635 { "SeqNum", "wpan.6top_seqnum", FT_UINT8, BASE_DEC, NULL, IETF_6TOP_SEQNUM,
6636 NULL, HFILL }},
6638 { &hf_ieee802154_6top_metadata,
6639 { "Metadata", "wpan.6top_metadata", FT_UINT16, BASE_HEX, NULL, 0x0,
6640 NULL, HFILL }},
6642 { &hf_ieee802154_6top_cell_options,
6643 { "Cell Options", "wpan.6top_cell_options", FT_UINT8, BASE_HEX, VALS(ietf_6top_cell_options), 0x0,
6644 NULL, HFILL }},
6646 { &hf_ieee802154_6top_cell_option_tx,
6647 { "Transmit (TX) Cell", "wpan.6top_cell_option_tx", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_TX,
6648 NULL, HFILL }},
6650 { &hf_ieee802154_6top_cell_option_rx,
6651 { "Receive (RX) Cell", "wpan.6top_cell_option_rx", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_RX,
6652 NULL, HFILL }},
6654 { &hf_ieee802154_6top_cell_option_shared,
6655 { "SHARED Cell", "wpan.6top_cell_option_shared", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_SHARED,
6656 NULL, HFILL }},
6658 { &hf_ieee802154_6top_cell_option_reserved,
6659 { "Reserved", "wpan.6top_cell_option_reserved", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_RESERVED,
6660 NULL, HFILL }},
6662 { &hf_ieee802154_6top_num_cells,
6663 { "Number of Cells", "wpan.6top_num_cells", FT_UINT8, BASE_DEC, NULL, 0x0,
6664 NULL, HFILL }},
6666 { &hf_ieee802154_6top_cell_list,
6667 { "CellList", "wpan.6top_cell_list", FT_NONE, BASE_NONE, NULL, 0x0,
6668 NULL, HFILL }},
6670 { &hf_ieee802154_6top_rel_cell_list,
6671 { "Rel. CellList", "wpan.6top_rel_cell_list", FT_NONE, BASE_NONE, NULL, 0x0,
6672 NULL, HFILL }},
6674 { &hf_ieee802154_6top_cand_cell_list,
6675 { "Cand. CellList", "wpan.6top_cand_cell_list", FT_NONE, BASE_NONE, NULL, 0x0,
6676 NULL, HFILL }},
6678 { &hf_ieee802154_6top_cell,
6679 { "Cell", "wpan.6top_cell", FT_BYTES, BASE_NONE, NULL, 0x0,
6680 NULL, HFILL }},
6682 { &hf_ieee802154_6top_reserved,
6683 { "Reserved", "wpan.6top_reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
6684 NULL, HFILL }},
6686 { &hf_ieee802154_6top_offset,
6687 { "Offset", "wpan.6top_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6688 NULL, HFILL }},
6690 { &hf_ieee802154_6top_max_num_cells,
6691 { "Maximum Number of Requested Cells", "wpan.6top_max_num_cells", FT_UINT16, BASE_DEC, NULL, 0x0,
6692 NULL, HFILL }},
6694 { &hf_ieee802154_6top_slot_offset,
6695 { "Slot Offset", "wpan.6top_cell_slot_offset", FT_UINT16, BASE_HEX, NULL, 0x0,
6696 NULL, HFILL }},
6698 { &hf_ieee802154_6top_channel_offset,
6699 { "Channel Offset", "wpan.6top_channel_offset", FT_UINT16, BASE_HEX, NULL, 0x0,
6700 NULL, HFILL }},
6702 { &hf_ieee802154_6top_total_num_cells,
6703 { "Total Number of Cells", "wpan.6top_total_num_cells", FT_UINT16, BASE_DEC, NULL, 0x0,
6704 NULL, HFILL }},
6706 { &hf_ieee802154_6top_payload,
6707 { "Payload", "wpan.6top_payload", FT_BYTES, BASE_NONE, NULL, 0x0,
6708 NULL, HFILL }},
6710 /* MPX IE (IEEE 802.15.9) */
6711 { &hf_ieee802159_mpx,
6712 { "MPX IE", "wpan.mpx", FT_NONE, BASE_NONE, NULL, 0x0,
6713 NULL, HFILL }
6716 { &hf_ieee802159_mpx_transaction_control,
6717 { "Transaction Control", "wpan.mpx.transaction_control", FT_UINT8, BASE_HEX, NULL, 0x0,
6718 NULL, HFILL }
6721 { &hf_ieee802159_mpx_transfer_type,
6722 { "Transfer Type", "wpan.mpx.transfer_type", FT_UINT8, BASE_HEX, VALS(mpx_transfer_type_vals), IEEE802159_MPX_TRANSFER_TYPE_MASK,
6723 NULL, HFILL }
6726 { &hf_ieee802159_mpx_transaction_id,
6727 { "Transaction ID", "wpan.mpx.transaction_id", FT_UINT8, BASE_HEX, NULL, IEEE802159_MPX_TRANSACTION_ID_MASK,
6728 NULL, HFILL }
6731 { &hf_ieee802159_mpx_transaction_id_as_multiplex_id,
6732 { "Multiplex ID", "wpan.mpx.multiplex_id", FT_UINT8, BASE_HEX, VALS(mpx_multiplex_id_vals), IEEE802159_MPX_TRANSACTION_ID_MASK,
6733 "Transaction ID used as Multiplex ID", HFILL }
6736 { &hf_ieee802159_mpx_fragment_number,
6737 { "Fragment Number", "wpan.mpx.fragment_number", FT_UINT8, BASE_DEC, NULL, 0x0,
6738 NULL, HFILL }
6741 { &hf_ieee802159_mpx_total_frame_size,
6742 { "Total Frame Size", "wpan.mpx.total_frame_size", FT_UINT16, BASE_DEC, NULL, 0x0,
6743 "Total Upper-Layer Frame Size", HFILL }
6746 { &hf_ieee802159_mpx_multiplex_id,
6747 { "Multiplex ID", "wpan.mpx.multiplex_id", FT_UINT16, BASE_HEX, NULL, 0x0,
6748 NULL, HFILL }
6751 { &hf_ieee802159_mpx_kmp_id,
6752 { "KMP ID", "wpan.mpx.kmp.id", FT_UINT8, BASE_DEC, VALS(ieee802154_mpx_kmp_id_vals), 0x0,
6753 NULL, HFILL }
6756 { &hf_ieee802159_mpx_kmp_vendor_oui,
6757 { "Vendor OUI", "wpan.mpx.kmp.vendor_oui", FT_UINT24, BASE_OUI, NULL, 0x0,
6758 NULL, HFILL }
6761 { &hf_ieee802159_mpx_fragment,
6762 { "Upper-Layer Frame Fragment", "wpan.mpx.fragment", FT_BYTES, SEP_SPACE, NULL, 0x0,
6763 NULL, HFILL }
6766 { &hf_ieee802159_mpx_wisun_subid,
6767 { "Wi-SUN Multiplex Sub ID", "wpan.mpx.wisun", FT_UINT8, BASE_HEX, VALS(mpx_wisun_subid_vals), 0x0,
6768 NULL, HFILL }
6771 /* Command Frame Specific Fields */
6773 { &hf_ieee802154_cmd_id,
6774 { "Command Identifier", "wpan.cmd", FT_UINT8, BASE_HEX, VALS(ieee802154_cmd_names), 0x0,
6775 NULL, HFILL }},
6777 { &hf_ieee802154_cmd_vendor_oui,
6778 { "Vendor OUI", "wpan.cmd.vendor_oui", FT_UINT24, BASE_OUI, NULL, 0x0,
6779 NULL, HFILL }},
6781 /* Capability Information Fields */
6783 { &hf_ieee802154_cinfo_alt_coord,
6784 { "Alternate PAN Coordinator", "wpan.cinfo.alt_coord", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALT_PAN_COORD,
6785 "Whether this device can act as a PAN coordinator or not.", HFILL }},
6787 { &hf_ieee802154_cinfo_device_type,
6788 { "Device Type", "wpan.cinfo.device_type", FT_BOOLEAN, 8, TFS(&tfs_cinfo_device_type), IEEE802154_CMD_CINFO_DEVICE_TYPE,
6789 "Whether this device is RFD (reduced-function device) or FFD (full-function device).", HFILL }},
6791 { &hf_ieee802154_cinfo_power_src,
6792 { "Power Source", "wpan.cinfo.power_src", FT_BOOLEAN, 8, TFS(&tfs_cinfo_power_src), IEEE802154_CMD_CINFO_POWER_SRC,
6793 "Whether this device is operating on AC/mains or battery power.", HFILL }},
6795 { &hf_ieee802154_cinfo_idle_rx,
6796 { "Receive On When Idle", "wpan.cinfo.idle_rx", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_IDLE_RX,
6797 "Whether this device can receive packets while idle or not.", HFILL }},
6799 { &hf_ieee802154_cinfo_sec_capable,
6800 { "Security Capability", "wpan.cinfo.sec_capable", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_SEC_CAPABLE,
6801 "Whether this device is capable of receiving encrypted packets.", HFILL }},
6803 { &hf_ieee802154_cinfo_alloc_addr,
6804 { "Allocate Address", "wpan.cinfo.alloc_addr", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALLOC_ADDR,
6805 "Whether this device wishes to use a 16-bit short address instead of its IEEE 802.15.4 64-bit long address.", HFILL }},
6807 /* Association response fields */
6809 { &hf_ieee802154_assoc_addr,
6810 { "Short Address", "wpan.asoc.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
6811 "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 }},
6813 { &hf_ieee802154_assoc_status,
6814 { "Association Status", "wpan.assoc.status", FT_UINT8, BASE_HEX, NULL, 0x0,
6815 NULL, HFILL }},
6817 { &hf_ieee802154_disassoc_reason,
6818 { "Disassociation Reason", "wpan.disassoc.reason", FT_UINT8, BASE_HEX, NULL, 0x0,
6819 NULL, HFILL }},
6821 /* Coordinator Realignment fields */
6823 { &hf_ieee802154_realign_pan,
6824 { "PAN ID", "wpan.realign.pan", FT_UINT16, BASE_HEX, NULL, 0x0,
6825 "The PAN identifier the coordinator wishes to use for future communication.", HFILL }},
6827 { &hf_ieee802154_realign_caddr,
6828 { "Coordinator Short Address", "wpan.realign.caddr", FT_UINT16, BASE_HEX, NULL, 0x0,
6829 "The 16-bit address the coordinator wishes to use for future communication.", HFILL }},
6831 { &hf_ieee802154_realign_channel,
6832 { "Logical Channel", "wpan.realign.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
6833 "The logical channel the coordinator wishes to use for future communication.", HFILL }},
6835 { &hf_ieee802154_realign_addr,
6836 { "Short Address", "wpan.realign.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
6837 "A short-address that the orphaned device shall assume if applicable.", HFILL }},
6839 { &hf_ieee802154_realign_channel_page,
6840 { "Channel Page", "wpan.realign.channel_page", FT_UINT8, BASE_DEC, NULL, 0x0,
6841 "The logical channel page the coordinator wishes to use for future communication.", HFILL }},
6843 { &hf_ieee802154_gtsreq_len,
6844 { "GTS Length", "wpan.gtsreq.length", FT_UINT8, BASE_DEC, NULL, IEEE802154_CMD_GTS_REQ_LEN,
6845 "Number of superframe slots the device is requesting.", HFILL }},
6847 { &hf_ieee802154_gtsreq_dir,
6848 { "GTS Direction", "wpan.gtsreq.direction", FT_BOOLEAN, 8, TFS(&tfs_gtsreq_dir), IEEE802154_CMD_GTS_REQ_DIR,
6849 "The direction of traffic in the guaranteed timeslot.", HFILL }},
6851 { &hf_ieee802154_gtsreq_type,
6852 { "Characteristic Type", "wpan.gtsreq.type", FT_BOOLEAN, 8, TFS(&tfs_gtsreq_type), IEEE802154_CMD_GTS_REQ_TYPE,
6853 "Whether this request is to allocate or deallocate a timeslot.", HFILL }},
6855 /* Beacon Frame Specific Fields */
6857 { &hf_ieee802154_beacon_order,
6858 { "Beacon Interval", "wpan.beacon_order", FT_UINT16, BASE_DEC, NULL, IEEE802154_BEACON_ORDER_MASK,
6859 "Specifies the transmission interval of the beacons.", HFILL }},
6861 { &hf_ieee802154_superframe_order,
6862 { "Superframe Interval", "wpan.superframe_order", FT_UINT16, BASE_DEC, NULL,
6863 IEEE802154_SUPERFRAME_ORDER_MASK,
6864 "Specifies the length of time the coordinator will interact with the PAN.", HFILL }},
6866 { &hf_ieee802154_cap,
6867 { "Final CAP Slot", "wpan.cap", FT_UINT16, BASE_DEC, NULL, IEEE802154_SUPERFRAME_CAP_MASK,
6868 "Specifies the final superframe slot used by the CAP.", HFILL }},
6870 { &hf_ieee802154_superframe_battery_ext,
6871 { "Battery Extension", "wpan.battery_ext", FT_BOOLEAN, 16, NULL, IEEE802154_BATT_EXTENSION_MASK,
6872 "Whether transmissions may not extend past the length of the beacon frame.", HFILL }},
6874 { &hf_ieee802154_superframe_coord,
6875 { "PAN Coordinator", "wpan.bcn_coord", FT_BOOLEAN, 16, NULL, IEEE802154_SUPERFRAME_COORD_MASK,
6876 "Whether this beacon frame is being transmitted by the PAN coordinator or not.", HFILL }},
6878 { &hf_ieee802154_assoc_permit,
6879 { "Association Permit", "wpan.assoc_permit", FT_BOOLEAN, 16, NULL, IEEE802154_ASSOC_PERMIT_MASK,
6880 "Whether this PAN is accepting association requests or not.", HFILL }},
6882 { &hf_ieee802154_gts_count,
6883 { "GTS Descriptor Count", "wpan.gts.count", FT_UINT8, BASE_DEC, NULL, 0x0,
6884 "The number of GTS descriptors present in this beacon frame.", HFILL }},
6886 { &hf_ieee802154_gts_permit,
6887 { "GTS Permit", "wpan.gts.permit", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
6888 "Whether the PAN coordinator is accepting GTS requests or not.", HFILL }},
6890 { &hf_ieee802154_gts_direction,
6891 { "Direction", "wpan.gts.direction", FT_BOOLEAN, BASE_NONE, TFS(&ieee802154_gts_direction_tfs), 0x0,
6892 "A flag defining the direction of the GTS Slot.", HFILL }},
6894 { &hf_ieee802154_gts_address,
6895 { "Address", "wpan.gts.address", FT_UINT16, BASE_HEX, NULL, 0x0,
6896 NULL, HFILL }},
6898 { &hf_ieee802154_pending16,
6899 { "Address", "wpan.pending16", FT_UINT16, BASE_HEX, NULL, 0x0,
6900 "Device with pending data to receive.", HFILL }},
6902 { &hf_ieee802154_pending64,
6903 { "Address", "wpan.pending64", FT_EUI64, BASE_NONE, NULL, 0x0,
6904 "Device with pending data to receive.", HFILL }},
6906 /* Auxiliary Security Header Fields */
6907 { &hf_ieee802154_aux_security_header,
6908 { "Auxiliary Security Header", "wpan.aux_sec.hdr", FT_NONE, BASE_NONE, NULL,
6909 0x0, "The Auxiliary Security Header of the frame", HFILL }},
6911 { &hf_ieee802154_aux_sec_security_level,
6912 { "Security Level", "wpan.aux_sec.sec_level", FT_UINT8, BASE_HEX, VALS(ieee802154_sec_level_names),
6913 IEEE802154_AUX_SEC_LEVEL_MASK, "The Security Level of the frame", HFILL }},
6915 { &hf_ieee802154_aux_sec_security_control,
6916 { "Security Control Field", "wpan.aux_sec.security_control_field", FT_UINT8, BASE_HEX, NULL,
6917 0x0, NULL, HFILL }},
6919 { &hf_ieee802154_aux_sec_key_id_mode,
6920 { "Key Identifier Mode", "wpan.aux_sec.key_id_mode", FT_UINT8, BASE_HEX, VALS(ieee802154_key_id_mode_names),
6921 IEEE802154_AUX_KEY_ID_MODE_MASK,
6922 "The scheme to use by the recipient to lookup the key in its key table", HFILL }},
6924 { &hf_ieee802154_aux_sec_frame_counter_suppression,
6925 { "Frame Counter Suppression", "wpan.aux_sec.frame_counter_suppression", FT_BOOLEAN, 8, NULL,
6926 IEEE802154_AUX_FRAME_COUNTER_SUPPRESSION_MASK,
6927 "Whether the frame counter is omitted from the Auxiliary Security Header", HFILL }},
6929 { &hf_ieee802154_aux_sec_asn_in_nonce,
6930 { "ASN in Nonce", "wpan.aux_sec.asn_in_nonce", FT_BOOLEAN, 8, NULL,
6931 IEEE802154_AUX_ASN_IN_NONCE_MASK,
6932 "Whether the ASN is used to generate the nonce instead of the frame counter", HFILL }},
6934 { &hf_ieee802154_aux_sec_reserved,
6935 { "Reserved", "wpan.aux_sec.reserved", FT_UINT8, BASE_HEX, NULL, IEEE802154_AUX_CTRL_RESERVED_MASK,
6936 NULL, HFILL }},
6938 { &hf_ieee802154_aux_sec_frame_counter,
6939 { "Frame Counter", "wpan.aux_sec.frame_counter", FT_UINT32, BASE_DEC, NULL, 0x0,
6940 "Frame counter of the originator of the protected frame", HFILL }},
6942 { &hf_ieee802154_aux_sec_key_source,
6943 { "Key Source", "wpan.aux_sec.key_source", FT_UINT64, BASE_HEX, NULL, 0x0,
6944 "Key Source for processing of the protected frame", HFILL }},
6946 { &hf_ieee802154_aux_sec_key_source_bytes,
6947 { "Key Source", "wpan.aux_sec.key_source.bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
6948 "Key Source for processing of the protected frame", HFILL }},
6950 { &hf_ieee802154_aux_sec_key_index,
6951 { "Key Index", "wpan.aux_sec.key_index", FT_UINT8, BASE_HEX, NULL, 0x0,
6952 "Key Index for processing of the protected frame", HFILL }},
6954 { &hf_ieee802154_mic,
6955 { "MIC", "wpan.mic", FT_BYTES, BASE_NONE, NULL, 0x0,
6956 NULL, HFILL }},
6958 { &hf_ieee802154_key_number,
6959 { "Key Number", "wpan.key_number", FT_UINT8, BASE_DEC, NULL, 0x0,
6960 "Key number used to decode", HFILL }},
6962 /* IEEE 802.15.4-2003 Security Header Fields */
6963 { &hf_ieee802154_sec_frame_counter,
6964 { "Frame Counter", "wpan.sec_frame_counter", FT_UINT32, BASE_HEX, NULL, 0x0,
6965 "Frame counter of the originator of the protected frame (802.15.4-2003)", HFILL }},
6967 { &hf_ieee802154_sec_key_sequence_counter,
6968 { "Key Sequence Counter", "wpan.sec_key_sequence_counter", FT_UINT8, BASE_HEX, NULL, 0x0,
6969 "Key Sequence counter of the originator of the protected frame (802.15.4-2003)", HFILL }},
6971 { &hf_ieee802154_no_ack,
6972 { "No ack found", "wpan.no_ack", FT_NONE, BASE_NONE, NULL, 0x0,
6973 "No corresponding ack frame was found", HFILL }},
6975 { &hf_ieee802154_no_ack_request,
6976 { "No request found", "wpan.no_ack_request", FT_NONE, BASE_NONE, NULL, 0x0,
6977 "No corresponding request frame was found", HFILL }},
6979 { &hf_ieee802154_ack_in,
6980 { "Ack In", "wpan.ack_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
6981 "The ack to this request is in this frame", HFILL }},
6983 { &hf_ieee802154_ack_to,
6984 { "Ack To", "wpan.ack_to", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_ACK), 0x0,
6985 "This is the ack to the request in this frame", HFILL }},
6987 { &hf_ieee802154_ack_time,
6988 { "Ack Time", "wpan.ack_time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
6989 "The time between the request and the ack", HFILL }},
6991 /* ZBOSS dump */
6993 { &hf_zboss_page,
6994 { "Page", "wpan-zboss.page", FT_UINT8, BASE_DEC_HEX, VALS(zboss_page_names), 0xFE,
6995 "IEEE802.15.4 page number", HFILL } },
6997 { &hf_zboss_channel,
6998 { "Channel", "wpan-zboss.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
6999 "Channel number", HFILL }},
7001 { &hf_zboss_direction,
7002 { "ZBOSS Direction", "wpan-zboss.direction", FT_UINT8, BASE_HEX, VALS(zboss_direction_names), 0x01,
7003 "ZBOSS Packet Direction", HFILL }},
7005 { &hf_zboss_trace_number,
7006 { "Trace number", "wpan-zboss.trace", FT_UINT32, BASE_DEC, NULL, 0x0,
7007 "Trace item number", HFILL }},
7009 /* TAP Packet Fields */
7010 { &hf_ieee802154_tap_version,
7011 { "Version", "wpan-tap.version", FT_UINT8, BASE_DEC, NULL, 0x0,
7012 "TAP Packet Version", HFILL }},
7014 { &hf_ieee802154_tap_reserved,
7015 { "Reserved", "wpan-tap.reserved", FT_UINT8, BASE_DEC, NULL, 0x0,
7016 "TAP Packet Reserved", HFILL }},
7018 { &hf_ieee802154_tap_length,
7019 { "Length", "wpan-tap.length", FT_UINT16, BASE_DEC, NULL, 0x0,
7020 "TAP Packet Length", HFILL }},
7022 { &hf_ieee802154_tap_data_length,
7023 { "Data Length", "wpan-tap.data_length", FT_UINT16, BASE_DEC, NULL, 0x0,
7024 "IEEE 802.15.4 Data Length", HFILL }},
7026 { &hf_ieee802154_tap_tlv_type,
7027 { "TLV Type", "wpan-tap.tlv.type", FT_UINT16, BASE_DEC, VALS(tap_tlv_types), 0x0,
7028 NULL, HFILL }},
7030 { &hf_ieee802154_tap_tlv_length,
7031 { "TLV Length", "wpan-tap.tlv.length", FT_UINT16, BASE_DEC, NULL, 0x0,
7032 NULL, HFILL }},
7034 { &hf_ieee802154_tap_tlv_unknown,
7035 { "Unknown", "wpan-tap.tlv.unknown", FT_BYTES, BASE_NONE, NULL, 0x0,
7036 NULL, HFILL }},
7038 { &hf_ieee802154_tap_tlv_padding,
7039 { "Padding", "wpan-tap.tlv.padding", FT_BYTES, BASE_NONE, NULL, 0x0,
7040 NULL, HFILL }},
7042 { &hf_ieee802154_tap_fcs_type,
7043 { "FCS Type", "wpan-tap.fcs_type", FT_UINT8, BASE_DEC, VALS(tap_fcs_type_names), 0x0,
7044 NULL, HFILL }},
7046 { &hf_ieee802154_tap_rss,
7047 { "RSS", "wpan-tap.rss", FT_FLOAT, BASE_NONE|BASE_UNIT_STRING, UNS(&units_dbm), 0x0,
7048 NULL, HFILL }},
7050 { &hf_ieee802154_ch_num,
7051 { "Channel", "wpan-tap.ch_num", FT_UINT16, BASE_DEC, NULL, 0x0,
7052 "Channel number", HFILL }},
7054 { &hf_ieee802154_ch_page,
7055 { "Page", "wpan-tap.ch_page", FT_UINT8, BASE_DEC, VALS(channel_page_names), 0x0,
7056 "Channel page", HFILL }},
7058 { &hf_ieee802154_bit_rate,
7059 { "Bit Rate", "wpan-tap.bit_rate", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_bit_sec), 0x0,
7060 NULL, HFILL }},
7062 { &hf_ieee802154_sun_band,
7063 { "Band", "wpan-tap.sun_band", FT_UINT8, BASE_DEC, VALS(sun_bands), 0x0,
7064 NULL, HFILL }},
7066 { &hf_ieee802154_sun_type,
7067 { "Type", "wpan-tap.sun_type", FT_UINT8, BASE_DEC, VALS(sun_types), 0x0,
7068 NULL, HFILL }},
7070 { &hf_ieee802154_sun_mode,
7071 { "Mode", "wpan-tap.sun_mode", FT_UINT8, BASE_DEC, NULL, 0x0,
7072 NULL, HFILL }},
7074 { &hf_ieee802154_mode_fsk_a,
7075 { "FSK-A mode", "wpan-tap.mode.fsk_a", FT_UINT8, BASE_DEC, VALS(fsk_a_modes), 0x0,
7076 NULL, HFILL }},
7078 { &hf_ieee802154_mode_fsk_b,
7079 { "FSK-B mode", "wpan-tap.mode.fsk_b", FT_UINT8, BASE_DEC, VALS(fsk_b_modes), 0x0,
7080 NULL, HFILL }},
7082 { &hf_ieee802154_mode_oqpsk_a,
7083 { "O-QPSK-A mode", "wpan-tap.mode.oqpsk_a", FT_UINT8, BASE_DEC, VALS(oqpsk_a_modes), 0x0,
7084 NULL, HFILL }},
7086 { &hf_ieee802154_mode_oqpsk_b,
7087 { "O-QPSK-B mode", "wpan-tap.mode.oqpsk_b", FT_UINT8, BASE_DEC, VALS(oqpsk_b_modes), 0x0,
7088 NULL, HFILL }},
7090 { &hf_ieee802154_mode_oqpsk_c,
7091 { "O-QPSK-C mode", "wpan-tap.mode.oqpsk_c", FT_UINT8, BASE_DEC, VALS(oqpsk_c_modes), 0x0,
7092 NULL, HFILL }},
7094 { &hf_ieee802154_mode_ofdm,
7095 { "OFDM mode", "wpan-tap.mode.ofdm", FT_UINT8, BASE_DEC, VALS(ofdm_modes), 0x0,
7096 NULL, HFILL }},
7098 { &hf_ieee802154_sof_ts,
7099 { "Start of frame timestamp", "wpan-tap.sof_ts", FT_UINT64, BASE_DEC|BASE_UNIT_STRING, UNS(&units_nanoseconds), 0x0,
7100 NULL, HFILL }},
7102 { &hf_ieee802154_eof_ts,
7103 { "End of frame timestamp", "wpan-tap.eof_ts", FT_UINT64, BASE_DEC|BASE_UNIT_STRING, UNS(&units_nanoseconds), 0x0,
7104 NULL, HFILL }},
7106 { &hf_ieee802154_slot_start_ts,
7107 { "Start of slot timestamp", "wpan-tap.slot_start_ts", FT_UINT64, BASE_DEC|BASE_UNIT_STRING, UNS(&units_nanoseconds), 0x0,
7108 NULL, HFILL }},
7110 { &hf_ieee802154_tap_timeslot_length,
7111 { "Timeslot length", "wpan-tap.timeslot_length", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microseconds), 0x0,
7112 NULL, HFILL }},
7114 { &hf_ieee802154_tap_lqi,
7115 { "Link Quality Indicator", "wpan-tap.lqi", FT_UINT8, BASE_DEC, NULL, 0x0,
7116 NULL, HFILL }},
7118 { &hf_ieee802154_chplan_start,
7119 { "Channel0 freq", "wpan-tap.chplan.start", FT_FLOAT, BASE_NONE|BASE_UNIT_STRING, UNS(&units_khz), 0x0,
7120 "Channel 0 center frequency", HFILL }},
7122 { &hf_ieee802154_chplan_spacing,
7123 { "Spacing", "wpan-tap.chplan.spacing", FT_FLOAT, BASE_NONE|BASE_UNIT_STRING, UNS(&units_khz), 0x0,
7124 "Channel spacing", HFILL }},
7126 { &hf_ieee802154_chplan_channels,
7127 { "Channels", "wpan-tap.chplan.channels", FT_UINT16, BASE_DEC, NULL, 0x0,
7128 "Number of channels", HFILL }},
7130 { &hf_ieee802154_ch_freq,
7131 { "Frequency", "wpan-tap.ch_freq", FT_FLOAT, BASE_NONE|BASE_UNIT_STRING, UNS(&units_khz), 0x0,
7132 "Channel center frequency", HFILL }},
7134 { &hf_ieee802154_frame_start_offset,
7135 { "Frame start offset", "wpan.tsch.frame_start_offset", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_microseconds), 0x0,
7136 "Start of frame timestamp - start of slot timestamp", HFILL }},
7138 { &hf_ieee802154_frame_duration,
7139 { "Frame duration", "wpan.tsch.frame_duration", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_microseconds), 0x0,
7140 "End of frame timestamp - start of frame timestamp", HFILL }},
7142 { &hf_ieee802154_frame_end_offset,
7143 { "Frame end offset", "wpan.tsch.frame_end_offset", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_microseconds), 0x0,
7144 "End of frame timestamp - (start of slot timestamp + timeslot length)", HFILL }},
7146 { &hf_ieee802154_asn,
7147 { "ASN", "wpan-tap.asn", FT_UINT64, BASE_DEC, NULL, 0x0,
7148 "Absolute Slot Number", HFILL }},
7150 { &hf_ieee802154_tap_phr_type,
7151 { "PHR Type", "wpan-tap.phr.type", FT_UINT16, BASE_DEC, VALS(ieee802154_phr_type_vals), 0x0,
7152 NULL, HFILL }},
7154 { &hf_ieee802154_tap_phr_bits,
7155 { "PHR Bits", "wpan-tap.phr.bits", FT_UINT16, BASE_DEC, NULL, 0x0,
7156 NULL, HFILL }},
7158 { &hf_ieee802154_tap_phr_data,
7159 { "PHR Data", "wpan-tap.phr.data", FT_BYTES, BASE_NONE, NULL, 0x0,
7160 NULL, HFILL }},
7162 { &hf_ieee802154_tap_phr_fsk,
7163 { "FSK PHR", "wpan-tap.phr.fsk", FT_UINT16, BASE_HEX, NULL, 0x0,
7164 NULL, HFILL }},
7166 { &hf_ieee802154_tap_fsk_ms_phr,
7167 { "FSK Mode Switch PHR", "wpan-tap.phr.fsk_ms", FT_UINT16, BASE_HEX, NULL, 0x0,
7168 NULL, HFILL }},
7170 { &hf_ieee802154_tap_wisun_ms_phr,
7171 { "Wi-SUN Mode Switch PHR", "wpan-tap.phr.wisun_ms", FT_UINT16, BASE_HEX, NULL, 0x0,
7172 NULL, HFILL }},
7174 { &hf_ieee802154_tap_phr_fsk_ms,
7175 { "MS", "wpan-tap.phr.fsk.ms", FT_BOOLEAN, 16, TFS(&tfs_enabled_disabled), IEEE802154_TAP_PHR_FSK_MS,
7176 "Mode Switch", HFILL }},
7178 { &hf_ieee802154_tap_phr_fsk_fcs,
7179 { "FCS Type", "wpan-tap.phr.fsk.fcs", FT_BOOLEAN, 16, TFS(&tfs_fcs_type), IEEE802154_TAP_PHR_FSK_FCS,
7180 NULL, HFILL }},
7182 { &hf_ieee802154_tap_phr_fsk_dw,
7183 { "DW", "wpan-tap.phr.fsk.dw", FT_BOOLEAN, 16, TFS(&tfs_enabled_disabled), IEEE802154_TAP_PHR_FSK_DW,
7184 "Data Whitening", HFILL }},
7186 { &hf_ieee802154_tap_phr_fsk_length,
7187 { "Frame Length", "wpan-tap.phr.fsk.length", FT_UINT16, BASE_HEX, NULL, IEEE802154_TAP_PHR_FSK_LENGTH,
7188 NULL, HFILL }},
7190 { &hf_ieee802154_tap_phr_fsk_ms_param,
7191 { "Parameter", "wpan-tap.phr.fsk_ms.length", FT_UINT16, BASE_HEX, NULL, IEEE802154_TAP_PHR_FSK_MS_PARAM,
7192 "Mode Switch Parameter", HFILL }},
7194 { &hf_ieee802154_tap_phr_fsk_ms_fec,
7195 { "FEC", "wpan-tap.phr.fsk_ms.fec", FT_BOOLEAN, 16, TFS(&tfs_enabled_disabled), IEEE802154_TAP_PHR_FSK_MS_FEC,
7196 "New Mode FEC", HFILL }},
7198 { &hf_ieee802154_tap_phr_fsk_ms_checksum,
7199 { "Checksum", "wpan-tap.phr.fsk_ms.checksum", FT_UINT16, BASE_HEX, NULL, IEEE802154_TAP_PHR_FSK_MS_CHECKSUM,
7200 "BCH(15,11) checksum", HFILL }},
7202 { &hf_ieee802154_tap_phr_fsk_ms_parity,
7203 { "Parity", "wpan-tap.phr.fsk_ms.parity", FT_UINT16, BASE_HEX, NULL, IEEE802154_TAP_PHR_FSK_MS_PARITY,
7204 "Parity Check bit", HFILL }},
7206 { &hf_ieee802154_tap_phr_fsk_ms_mode_page,
7207 { "Page", "wpan-tap.phr.fsk_ms.page", FT_UINT16, BASE_HEX, VALS(vals_fsk_ms_page), IEEE802154_TAP_PHR_FSK_MS_MODE_PAGE,
7208 "New Mode Page", HFILL }},
7210 { &hf_ieee802154_tap_phr_fsk_ms_mode_scheme,
7211 { "Scheme", "wpan-tap.phr.fsk_ms.scheme", FT_UINT16, BASE_HEX, VALS(ieee802154_phr_fsk_ms_scheme), IEEE802154_TAP_PHR_FSK_MS_MODE_SCHEME,
7212 "New Mode Modulation Scheme", HFILL }},
7214 { &hf_ieee802154_tap_phr_fsk_ms_mode_mode,
7215 { "Mode", "wpan-tap.phr.fsk_ms.mode", FT_UINT16, BASE_HEX, VALS(ieee802154_phr_fsk_ms_mode), IEEE802154_TAP_PHR_FSK_MS_MODE_MODE,
7216 "New Mode Mode", HFILL }},
7218 { &hf_ieee802154_tap_phr_fsk_ms_mode_addl_mode,
7219 { "Additional Mode", "wpan-tap.phr.fsk_ms.mode", FT_UINT16, BASE_HEX, VALS(ieee802154_phr_fsk_ms_additional_modes), IEEE802154_TAP_PHR_FSK_MS_MODE_MODE,
7220 "New Mode Additional Mode", HFILL }},
7222 { &hf_ieee802154_tap_phr_wisun_fsk_ms_reserved,
7223 { "Reserved", "wpan-tap.phr.wisun_ms.reserved", FT_UINT16, BASE_HEX, NULL, IEEE802154_TAP_PHR_WISUN_FSK_MS_RESERVED,
7224 NULL, HFILL }},
7226 { &hf_ieee802154_tap_phr_wisun_fsk_ms_phymodeid,
7227 { "PhyModeId", "wpan-tap.phr.wisun_ms.phymodeid", FT_UINT16, BASE_HEX, VALS(ieee802154_phr_wisun_phymodeid), IEEE802154_TAP_PHR_WISUN_FSK_MS_PHYMODEID,
7228 "New Wi-SUN PhyModeId", HFILL }},
7231 /* Subtrees */
7232 static int *ett[] = {
7233 &ett_ieee802154_nonask_phy,
7234 &ett_ieee802154_nonask_phy_phr,
7235 &ett_ieee802154_tap,
7236 &ett_ieee802154_tap_header,
7237 &ett_ieee802154_tap_tlv,
7238 &ett_ieee802154,
7239 &ett_ieee802154_fcf,
7240 &ett_ieee802154_auxiliary_security,
7241 &ett_ieee802154_aux_sec_control,
7242 &ett_ieee802154_aux_sec_key_id,
7243 &ett_ieee802154_fcs,
7244 &ett_ieee802154_cmd,
7245 &ett_ieee802154_superframe,
7246 &ett_ieee802154_gts,
7247 &ett_ieee802154_gts_direction,
7248 &ett_ieee802154_gts_descriptors,
7249 &ett_ieee802154_pendaddr,
7250 &ett_ieee802154_header_ies,
7251 &ett_ieee802154_header_ie,
7252 &ett_ieee802154_header_ie_tlv,
7253 &ett_ieee802154_hie_unsupported,
7254 &ett_ieee802154_hie_time_correction,
7255 &ett_ieee802154_hie_ht,
7256 &ett_ieee802154_hie_thread,
7257 &ett_ieee802154_hie_csl,
7258 &ett_ieee802154_hie_rdv,
7259 &ett_ieee802154_hie_global_time,
7260 &ett_ieee802154_hie_vendor_specific,
7261 &ett_ieee802154_payload_ie,
7262 &ett_ieee802154_payload_ie_tlv,
7263 &ett_ieee802154_pie_termination,
7264 &ett_ieee802154_pie_vendor,
7265 &ett_ieee802159_mpx,
7266 &ett_ieee802159_mpx_transaction_control,
7267 &ett_ieee802154_pie_ietf,
7268 &ett_ieee802154_pie_unsupported,
7269 &ett_ieee802154_tsch_slotframe,
7270 &ett_ieee802154_tsch_slotframe_list,
7271 &ett_ieee802154_tsch_slotframe_link,
7272 &ett_ieee802154_tsch_slotframe_link_options,
7273 &ett_ieee802154_tsch_timeslot,
7274 &ett_ieee802154_tsch_synch,
7275 &ett_ieee802154_channel_hopping,
7276 &ett_ieee802154_mlme,
7277 &ett_ieee802154_mlme_payload,
7278 &ett_ieee802154_mlme_payload_data,
7279 &ett_ieee802154_mlme_unsupported,
7280 &ett_ieee802154_psie,
7281 &ett_ieee802154_eb_filter,
7282 &ett_ieee802154_eb_filter_bitmap,
7283 &ett_ieee802154_zigbee,
7284 &ett_ieee802154_zboss,
7285 &ett_ieee802154_p_ie_6top,
7286 &ett_ieee802154_p_ie_6top_cell_options,
7287 &ett_ieee802154_p_ie_6top_cell_list,
7288 &ett_ieee802154_p_ie_6top_rel_cell_list,
7289 &ett_ieee802154_p_ie_6top_cand_cell_list,
7290 &ett_ieee802154_p_ie_6top_cell,
7291 &ett_ieee802154_tap_phr,
7294 static ei_register_info ei[] = {
7295 { &ei_ieee802154_fcs_bitmask_len, { "wpan.bitmask_len_error", PI_UNDECODED, PI_WARN,
7296 "Only least-significant bytes decoded", EXPFILL }},
7297 { &ei_ieee802154_invalid_addressing, { "wpan.invalid_addressing", PI_MALFORMED, PI_WARN,
7298 "Invalid Addressing", EXPFILL }},
7299 { &ei_ieee802154_invalid_panid_compression, { "wpan.invalid_panid_compression", PI_MALFORMED, PI_ERROR,
7300 "Invalid Setting for PAN ID Compression", EXPFILL }},
7301 { &ei_ieee802154_invalid_panid_compression2, { "wpan.invalid_panid_compression", PI_MALFORMED, PI_ERROR,
7302 "Invalid Pan ID Compression and addressing combination for Frame Version 2", EXPFILL }},
7303 { &ei_ieee802154_dst, { "wpan.dst_invalid", PI_MALFORMED, PI_ERROR,
7304 "Invalid Destination Address Mode", EXPFILL }},
7305 { &ei_ieee802154_src, { "wpan.src_invalid", PI_MALFORMED, PI_ERROR,
7306 "Invalid Source Address Mode", EXPFILL }},
7307 { &ei_ieee802154_frame_ver, { "wpan.frame_version_unknown", PI_MALFORMED, PI_ERROR,
7308 "Frame Version Unknown Cannot Dissect", EXPFILL }},
7309 #if 0
7310 { &ei_ieee802154_frame_type, { "wpan.frame_type_unknown", PI_MALFORMED, PI_ERROR,
7311 "Frame Type Unknown Cannot Dissect", EXPFILL }},
7312 #endif
7313 { &ei_ieee802154_decrypt_error, { "wpan.decrypt_error", PI_UNDECODED, PI_WARN,
7314 "Decryption error", EXPFILL }},
7315 { &ei_ieee802154_fcs, { "wpan.fcs.bad", PI_CHECKSUM, PI_WARN,
7316 "Bad FCS", EXPFILL }},
7317 { &ei_ieee802154_ack_not_found, { "wpan.ack_not_found", PI_SEQUENCE, PI_NOTE,
7318 "Ack not found", EXPFILL }},
7319 { &ei_ieee802154_ack_request_not_found, { "wpan.ack_request_not_found", PI_SEQUENCE, PI_NOTE,
7320 "Request not found", EXPFILL }},
7321 { &ei_ieee802154_seqno_suppression, { "wpan.seqno_suppression_invalid", PI_MALFORMED, PI_WARN,
7322 "Sequence Number Suppression invalid for 802.15.4-2003 and 2006", EXPFILL }},
7323 { &ei_ieee802154_6top_unsupported_type, { "wpan.6top_unsupported_type", PI_PROTOCOL, PI_WARN,
7324 "Unsupported Type of Message", EXPFILL }},
7325 { &ei_ieee802154_6top_unsupported_command, { "wpan.6top_unsupported_command", PI_PROTOCOL, PI_WARN,
7326 "Unsupported 6top command", EXPFILL }},
7327 { &ei_ieee802154_time_correction_error, { "wpan.time_correction.error", PI_PROTOCOL, PI_WARN,
7328 "Incorrect value. Reference: IEEE-802.15.4-2015. Table 7-8: Values of the Time Sync Info field for ACK with timing information", EXPFILL}},
7329 { &ei_ieee802154_6top_unsupported_return_code, { "wpan.6top_unsupported_code", PI_PROTOCOL, PI_WARN,
7330 "Unsupported 6top return code", EXPFILL }},
7331 { &ei_ieee802154_ie_unsupported_id, { "wpan.ie_unsupported_id", PI_PROTOCOL, PI_WARN,
7332 "Unsupported IE ID", EXPFILL }},
7333 { &ei_ieee802154_ie_unknown_extra_content, { "wpan.ie_unknown_extra_content", PI_PROTOCOL, PI_WARN,
7334 "Unexpected extra content for IE", EXPFILL }},
7335 { &ei_ieee802154_ie_unknown_extra_content_payload, { "wpan.ie_unknown_extra_content_payload", PI_PROTOCOL, PI_WARN,
7336 "Unexpected extra content for IE payload", EXPFILL }},
7337 { &ei_ieee802159_mpx_invalid_transfer_type, { "wpan.payload_ie.mpx.invalid_transfer_type", PI_PROTOCOL, PI_WARN,
7338 "Invalid transfer type (cf. IEEE 802.15.9 Table 19)", EXPFILL }},
7339 { &ei_ieee802159_mpx_unsupported_kmp, { "wpan.mpx.unsupported_kmp", PI_PROTOCOL, PI_WARN,
7340 "Unsupported KMP ID", EXPFILL }},
7341 { &ei_ieee802159_mpx_unknown_kmp, { "wpan.mpx.unknown_kmp", PI_PROTOCOL, PI_WARN,
7342 "Unknown KMP ID (cf. IEEE 802.15.9 Table 21)", EXPFILL }},
7343 { &ei_ieee802154_missing_payload_ie, { "wpan.payload_ie.missing", PI_MALFORMED, PI_WARN,
7344 "Payload IE indicated by Header Termination, but no Payload IE present", EXPFILL }},
7345 { &ei_ieee802154_payload_ie_in_header, { "wpan.payload_ie.in_header", PI_MALFORMED, PI_WARN,
7346 "Payload IE in header", EXPFILL }},
7347 { &ei_ieee802154_unsupported_cmd, { "wpan.cmd.unsupported_cmd", PI_PROTOCOL, PI_WARN,
7348 "Unsupported Command ID", EXPFILL }},
7349 { &ei_ieee802154_unknown_cmd, { "wpan.cmd.unknown_cmd", PI_PROTOCOL, PI_WARN,
7350 "Unknown Command Id (cf. IEEE 802.15.4-2015 Table 7-49)", EXPFILL }},
7351 { &ei_ieee802154_tap_tlv_invalid_type, { "wpan-tap.tlv.invalid_type", PI_MALFORMED, PI_WARN,
7352 "Invalid TLV type", EXPFILL }},
7353 { &ei_ieee802154_tap_tlv_invalid_length, { "wpan-tap.tlv.invalid_length", PI_MALFORMED, PI_WARN,
7354 "Invalid TLV length", EXPFILL }},
7355 { &ei_ieee802154_tap_tlv_padding_not_zeros, { "wpan-tap.tlv.padding_not_zeros", PI_MALFORMED, PI_WARN,
7356 "TLV padding not zero", EXPFILL }},
7357 { &ei_ieee802154_tap_tlv_invalid_fcs_type, { "wpan-tap.tlv.invalid_fcs_type", PI_MALFORMED, PI_ERROR,
7358 "Invalid FCS type", EXPFILL }},
7359 { &ei_ieee802154_tap_tlv_reserved_not_zero, { "wpan-tap.tlv.reserved_not_zero", PI_PROTOCOL, PI_WARN,
7360 "Reserved bits not zero", EXPFILL }},
7361 { &ei_ieee802154_tap_no_payload, { "wpan-tap.tlv.no_payload", PI_COMMENTS_GROUP, PI_COMMENT,
7362 "No payload", EXPFILL }},
7365 /* Preferences. */
7366 module_t *ieee802154_module;
7367 expert_module_t* expert_ieee802154;
7369 static uat_field_t addr_uat_flds[] = {
7370 UAT_FLD_HEX(addr_uat,addr16,"Short Address",
7371 "16-bit short address in hexadecimal."),
7372 UAT_FLD_HEX(addr_uat,pan,"PAN Identifier",
7373 "16-bit PAN identifier in hexadecimal."),
7374 UAT_FLD_BUFFER(addr_uat,eui64,"EUI-64",
7375 "64-bit extended unique identifier."),
7376 UAT_END_FIELDS
7379 static uat_field_t key_uat_flds[] = {
7380 UAT_FLD_CSTRING(key_uat,pref_key,"Decryption key",
7381 "128-bit decryption key in hexadecimal format"),
7382 UAT_FLD_DEC(key_uat,key_index,"Decryption key index",
7383 "Key index in decimal format"),
7384 UAT_FLD_VS(key_uat, hash_type, "Key hash", ieee802154_key_hash_vals, "Specifies which hash scheme is used to derived the key"),
7385 UAT_END_FIELDS
7388 static const enum_val_t fcs_type_vals[] = {
7389 {"cc24xx", "TI CC24xx metadata", IEEE802154_CC24XX_METADATA},
7390 {"16", "ITU-T CRC-16", IEEE802154_FCS_16_BIT},
7391 {"32", "ITU-T CRC-32", IEEE802154_FCS_32_BIT},
7392 {NULL, NULL, -1}
7395 static build_valid_func ieee802154_da_build_value[1] = {ieee802154_da_value};
7396 static decode_as_value_t ieee802154_da_values = {ieee802154_da_prompt, 1, ieee802154_da_build_value};
7397 static decode_as_t ieee802154_da = {
7398 IEEE802154_PROTOABBREV_WPAN, IEEE802154_PROTOABBREV_WPAN_PANID,
7399 1, 0, &ieee802154_da_values, NULL, NULL,
7400 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL
7403 /* Register the init routine. */
7404 register_init_routine(proto_init_ieee802154);
7405 register_cleanup_routine(proto_cleanup_ieee802154);
7407 /* Register Protocol name and description. */
7408 proto_ieee802154 = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN", "IEEE 802.15.4",
7409 IEEE802154_PROTOABBREV_WPAN);
7410 proto_ieee802154_nonask_phy = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN non-ASK PHY",
7411 "IEEE 802.15.4 non-ASK PHY", "wpan-nonask-phy");
7412 proto_zboss = proto_register_protocol("ZBOSS IEEE 802.15.4 dump",
7413 "ZBOSS dump", "wpan-zboss");
7414 proto_ieee802154_tap = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN TAP",
7415 "IEEE 802.15.4 TAP", "wpan-tap");
7417 /* Register header fields and subtrees. */
7418 proto_register_field_array(proto_ieee802154, hf, array_length(hf));
7419 proto_register_field_array(proto_ieee802154, hf_phy, array_length(hf_phy));
7421 proto_register_subtree_array(ett, array_length(ett));
7423 expert_ieee802154 = expert_register_protocol(proto_ieee802154);
7424 expert_register_field_array(expert_ieee802154, ei, array_length(ei));
7426 ieee802_15_4_short_address_type = address_type_dissector_register("AT_IEEE_802_15_4_SHORT", "IEEE 802.15.4 16-bit short address",
7427 ieee802_15_4_short_address_to_str, ieee802_15_4_short_address_str_len, NULL, NULL, ieee802_15_4_short_address_len, NULL, NULL);
7429 /* add a user preference to set the 802.15.4 ethertype */
7430 ieee802154_module = prefs_register_protocol(proto_ieee802154,
7431 proto_reg_handoff_ieee802154);
7432 prefs_register_uint_preference(ieee802154_module, "802154_ethertype",
7433 "802.15.4 Ethertype (in hex)",
7434 "(Hexadecimal) Ethertype used to indicate IEEE 802.15.4 frame.",
7435 16, &ieee802154_ethertype);
7436 prefs_register_obsolete_preference(ieee802154_module, "802154_cc24xx");
7437 prefs_register_enum_preference(ieee802154_module, "fcs_format",
7438 "FCS format",
7439 "The FCS format in the captured payload",
7440 &ieee802154_fcs_type, fcs_type_vals, false);
7441 prefs_register_bool_preference(ieee802154_module, "802154_fcs_ok",
7442 "Dissect only good FCS",
7443 "Dissect payload only if FCS is valid.",
7444 &ieee802154_fcs_ok);
7445 prefs_register_bool_preference(ieee802154_module, "802154_ack_tracking",
7446 "Enable ACK tracking",
7447 "Match frames with ACK request to ACK packets",
7448 &ieee802154_ack_tracking);
7449 prefs_register_bool_preference(ieee802154_module, "802154e_compatibility",
7450 "Assume 802.15.4e-2012 for compatibility",
7451 "Parse assuming 802.15.4e quirks for compatibility",
7452 &ieee802154e_compatibility);
7454 /* Create a UAT for static address mappings. */
7455 static_addr_uat = uat_new("Static Addresses",
7456 sizeof(static_addr_t), /* record size */
7457 "802154_addresses", /* filename */
7458 true, /* from_profile */
7459 &static_addrs, /* data_ptr */
7460 &num_static_addrs, /* numitems_ptr */
7461 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
7462 NULL, /* help */
7463 addr_uat_copy_cb, /* copy callback */
7464 addr_uat_update_cb, /* update callback */
7465 addr_uat_free_cb, /* free callback */
7466 NULL, /* post update callback */
7467 NULL, /* reset callback */
7468 addr_uat_flds); /* UAT field definitions */
7469 prefs_register_uat_preference(ieee802154_module, "static_addr",
7470 "Static Addresses",
7471 "A table of static address mappings between 16-bit short addressing and EUI-64 addresses",
7472 static_addr_uat);
7474 /* Create a UAT for key management. */
7475 ieee802154_key_uat = uat_new("Keys",
7476 sizeof(ieee802154_key_t), /* record size */
7477 "ieee802154_keys", /* filename */
7478 true, /* from_profile */
7479 &ieee802154_keys, /* data_ptr */
7480 &num_ieee802154_keys, /* numitems_ptr */
7481 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
7482 NULL, /* help */
7483 ieee802154_key_copy_cb, /* copy callback */
7484 ieee802154_key_update_cb, /* update callback */
7485 ieee802154_key_free_cb, /* free callback */
7486 ieee802154_key_post_update_cb, /* post update callback */
7487 NULL, /* reset callback */
7488 key_uat_flds); /* UAT field definitions */
7489 prefs_register_uat_preference(ieee802154_module, "ieee802154_keys",
7490 "Decryption Keys",
7491 "Decryption key configuration data",
7492 ieee802154_key_uat);
7494 /* Register preferences for a decryption key */
7495 prefs_register_obsolete_preference(ieee802154_module, "802154_key");
7497 prefs_register_enum_preference(ieee802154_module, "802154_sec_suite",
7498 "Security Suite (802.15.4-2003)",
7499 "Specifies the security suite to use for 802.15.4-2003 secured frames"
7500 " (only supported suites are listed). Option ignored for 802.15.4-2006"
7501 " and unsecured frames.",
7502 &ieee802154_sec_suite, ieee802154_2003_sec_suite_enums, false);
7504 prefs_register_bool_preference(ieee802154_module, "802154_extend_auth",
7505 "Extend authentication data (802.15.4-2003)",
7506 "Set if the manufacturer extends the authentication data with the"
7507 " security header. Option ignored for 802.15.4-2006 and unsecured frames.",
7508 &ieee802154_extend_auth);
7510 /* Register the subdissector list */
7511 panid_dissector_table = register_dissector_table(IEEE802154_PROTOABBREV_WPAN_PANID, "IEEE 802.15.4 PANID", proto_ieee802154, FT_UINT16, BASE_HEX);
7512 ieee802154_heur_subdissector_list = register_heur_dissector_list_with_description(IEEE802154_PROTOABBREV_WPAN, "IEEE 802.15.4 PANID", proto_ieee802154);
7513 ieee802154_beacon_subdissector_list = register_heur_dissector_list_with_description(IEEE802154_PROTOABBREV_WPAN_BEACON, "IEEE 802.15.4 FCF beacon", proto_ieee802154);
7515 /* Register dissector tables */
7516 header_ie_dissector_table = register_dissector_table(IEEE802154_HEADER_IE_DTABLE, "IEEE 802.15.4 Header IEs", proto_ieee802154, FT_UINT8, BASE_HEX);
7517 payload_ie_dissector_table = register_dissector_table(IEEE802154_PAYLOAD_IE_DTABLE, "IEEE 802.15.4 Payload IEs", proto_ieee802154, FT_UINT8, BASE_HEX);
7518 mlme_ie_dissector_table = register_dissector_table(IEEE802154_MLME_IE_DTABLE, "IEEE 802.15.4 Nested IEs", proto_ieee802154, FT_UINT8, BASE_HEX);
7519 cmd_vendor_dissector_table = register_dissector_table(IEEE802154_CMD_VENDOR_DTABLE, "IEEE 802.15.4 Vendor Specific Commands", proto_ieee802154, FT_UINT24, BASE_HEX );
7521 /* Register dissectors with Wireshark */
7522 ieee802154_handle = register_dissector(IEEE802154_PROTOABBREV_WPAN, dissect_ieee802154, proto_ieee802154);
7523 ieee802154_nofcs_handle = register_dissector("wpan_nofcs", dissect_ieee802154_nofcs, proto_ieee802154);
7524 register_dissector("wpan_cc24xx", dissect_ieee802154_cc24xx, proto_ieee802154);
7525 ieee802154_nonask_phy_handle = register_dissector("wpan-nonask-phy", dissect_ieee802154_nonask_phy, proto_ieee802154_nonask_phy);
7526 ieee802154_tap_handle = register_dissector("wpan-tap", dissect_ieee802154_tap, proto_ieee802154_tap);
7528 /* Setup registration for other dissectors to provide mac key hash algorithms */
7529 mac_key_hash_handlers = wmem_tree_new(wmem_epan_scope());
7531 /* Register a Decode-As handler */
7532 register_decode_as(&ieee802154_da);
7534 /* Create trees for transactions */
7535 transaction_unmatched_pdus = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
7536 transaction_matched_pdus = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
7538 ieee802154_tap = register_tap(IEEE802154_PROTOABBREV_WPAN);
7540 register_conversation_table(proto_ieee802154, true, ieee802154_conversation_packet, ieee802154_endpoint_packet);
7541 register_conversation_filter(IEEE802154_PROTOABBREV_WPAN, "IEEE 802.15.4", ieee802154_filter_valid, ieee802154_build_filter, NULL);
7542 } /* proto_register_ieee802154 */
7546 * Registers the IEEE 802.15.4 dissector with Wireshark.
7547 * Will be called every time 'apply' is pressed in the preferences menu.
7548 * as well as during Wireshark initialization
7550 void proto_reg_handoff_ieee802154(void)
7552 static bool prefs_initialized = false;
7553 static unsigned int old_ieee802154_ethertype;
7555 if (!prefs_initialized) {
7556 /* Get the dissector handles. */
7557 zigbee_ie_handle = find_dissector_add_dependency("zbee_ie", proto_ieee802154);
7558 zigbee_nwk_handle = find_dissector("zbee_nwk");
7560 thread_ie_handle = find_dissector_add_dependency("thread_ie",proto_ieee802154);
7561 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4, ieee802154_handle);
7562 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_NONASK_PHY, ieee802154_nonask_phy_handle);
7563 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_NOFCS, ieee802154_nofcs_handle);
7564 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_TAP, ieee802154_tap_handle);
7565 dissector_add_uint("sll.ltype", LINUX_SLL_P_IEEE802154, ieee802154_handle);
7567 /* Register internal IE handlers */
7568 dissector_add_uint(IEEE802154_HEADER_IE_DTABLE, IEEE802154_HEADER_IE_TIME_CORR, create_dissector_handle(dissect_hie_time_correction, -1));
7569 dissector_add_uint(IEEE802154_HEADER_IE_DTABLE, IEEE802154_HEADER_IE_CSL, create_dissector_handle(dissect_hie_csl, -1));
7570 dissector_add_uint(IEEE802154_HEADER_IE_DTABLE, IEEE802154_HEADER_IE_RENDEZVOUS, create_dissector_handle(dissect_hie_rendezvous_time, -1));
7571 dissector_add_uint(IEEE802154_HEADER_IE_DTABLE, IEEE802154_HEADER_IE_GLOBAL_TIME, create_dissector_handle(dissect_hie_global_time, -1));
7572 dissector_add_uint(IEEE802154_HEADER_IE_DTABLE, IEEE802154_HEADER_IE_VENDOR_SPECIFIC, create_dissector_handle(dissect_hie_vendor_specific, -1));
7574 dissector_add_uint(IEEE802154_PAYLOAD_IE_DTABLE, IEEE802154_PAYLOAD_IE_MLME, create_dissector_handle(dissect_pie_mlme, -1));
7575 dissector_add_uint(IEEE802154_PAYLOAD_IE_DTABLE, IEEE802154_PAYLOAD_IE_VENDOR, create_dissector_handle(dissect_pie_vendor, -1));
7576 dissector_add_uint(IEEE802154_PAYLOAD_IE_DTABLE, IEEE802154_PAYLOAD_IE_MPX, create_dissector_handle(dissect_mpx_ie, -1));
7577 dissector_add_uint(IEEE802154_PAYLOAD_IE_DTABLE, IEEE802154_PAYLOAD_IE_IETF, create_dissector_handle(dissect_ietf_ie, -1));
7579 dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_CHANNEL_HOPPING, create_dissector_handle(dissect_802154_channel_hopping, -1));
7580 dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_TSCH_SYNCH, create_dissector_handle(dissect_802154_tsch_time_sync, -1));
7581 dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_TSCH_SLOTFR_LINK, create_dissector_handle(dissect_802154_tsch_slotframe_link, -1));
7582 dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_TSCH_TIMESLOT, create_dissector_handle(dissect_802154_tsch_timeslot, -1));
7583 dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_ENHANCED_BEACON_FILTER, create_dissector_handle(dissect_802154_eb_filter, -1));
7585 /* For the MPX-IE */
7586 ethertype_table = find_dissector_table("ethertype");
7587 eapol_handle = find_dissector("eapol");
7588 lowpan_handle = find_dissector("6lowpan");
7589 wisun_sec_handle = find_dissector("wisun.sec");
7590 prefs_initialized = true;
7591 } else {
7592 dissector_delete_uint("ethertype", old_ieee802154_ethertype, ieee802154_handle);
7595 old_ieee802154_ethertype = ieee802154_ethertype;
7597 /* Register dissector handles. */
7598 dissector_add_uint("ethertype", ieee802154_ethertype, ieee802154_handle);
7600 } /* proto_reg_handoff_ieee802154 */
7603 * Editor modelines - https://www.wireshark.org/tools/modelines.html
7605 * Local variables:
7606 * c-basic-offset: 4
7607 * tab-width: 8
7608 * indent-tabs-mode: nil
7609 * End:
7611 * vi: set shiftwidth=4 tabstop=8 expandtab:
7612 * :indentSize=4:tabSize=8:noTabs=true: