1 /* packet-ieee802154.c
2  *
3  * Multipurpose frame support
4  * By Devan Lai <devanl@davisinstruments.com>
5  * Copyright 2019 Davis Instruments
6  *
7  * IEEE 802.15.4-2015 CCM* nonce for TSCH mode
8  * By Maxime Brunelle <Maxime.Brunelle@trilliant.com>
9  * Copyright 2019 Trilliant Inc.
10  *
11  * IEEE802154 TAP link type
12  * By James Ko <jck@exegin.com>
13  * Copyright 2019 Exegin Technologies Limited
14  *
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
21  *
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
26  *
27  * IEEE 802.15.4 Dissectors for Wireshark
28  * By Owen Kirby <osk@exegin.com>
29  * Copyright 2007 Exegin Technologies Limited
30  *
31  * Wireshark - Network traffic analyzer
32  * By Gerald Combs <gerald@wireshark.org>
33  * Copyright 1998 Gerald Combs
34  *
35  * SPDX-License-Identifier: GPL-2.0-or-later
36  *------------------------------------------------------------
37  *
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  *------------------------------------------------------------
42  *
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  *------------------------------------------------------------
47  *
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  *------------------------------------------------------------
52  *
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).
60  *
61  *  For a 4-byte FCS, CRC32 is calculated using the ITU-T CRC32.
62  *
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  *------------------------------------------------------------
73  *
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  *------------------------------------------------------------
80  */
81 
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 <wsutil/pint.h>
105 
106 /* Use libgcrypt for cipher libraries. */
107 #include <wsutil/wsgcrypt.h>
108 
109 #include "packet-ieee802154.h"
110 #include "packet-sll.h"
111 
112 void proto_register_ieee802154(void);
113 void proto_reg_handoff_ieee802154(void);
114 
115 /* Dissection Options for dissect_ieee802154_common */
116 #define DISSECT_IEEE802154_OPTION_CC24xx    0x00000001 /* Frame has TI CC24xx metadata, not an FCS, at the end */
117 #define DISSECT_IEEE802154_OPTION_ZBOSS     0x00000002 /* ZBOSS traffic dump */
118 
119 /* ethertype for 802.15.4 tag - encapsulating an Ethernet packet */
120 static unsigned int ieee802154_ethertype = 0x809A;
121 
122 /* FCS Types used by user configuration */
123 #define IEEE802154_CC24XX_METADATA 0 /* Not an FCS, but TI CC24xx metadata */
124 #define IEEE802154_FCS_16_BIT      1 /* ITU-T CRC16 */
125 #define IEEE802154_FCS_32_BIT      2 /* ITU-T CRC32 */
126 
127 static gint ieee802154_fcs_type = IEEE802154_FCS_16_BIT;
128 
129 /* 802.15.4 TAP Fields */
130 typedef enum {
131     IEEE802154_TAP_FCS_TYPE             = 0x0000,
132     IEEE802154_TAP_RSS                  = 0x0001,
133     IEEE802154_TAP_BIT_RATE             = 0x0002,
134     IEEE802154_TAP_CHANNEL_ASSIGNMENT   = 0x0003,
135     IEEE802154_TAP_SUN_PHY_INFO         = 0x0004,
136     IEEE802154_TAP_START_OF_FRAME_TS    = 0x0005,
137     IEEE802154_TAP_END_OF_FRAME_TS      = 0x0006,
138     IEEE802154_TAP_ASN                  = 0x0007,
139     IEEE802154_TAP_SLOT_START_TS        = 0x0008,
140     IEEE802154_TAP_TIMESLOT_LENGTH      = 0x0009,
141     IEEE802154_TAP_LQI                  = 0x000A,
142     IEEE802154_TAP_CHANNEL_FREQUENCY    = 0x000B,
143     IEEE802154_TAP_CHANNEL_PLAN         = 0x000C,
144 } ieee802154_info_type_t;
145 
146 typedef enum {
147     IEEE802154_FCS_TYPE_NONE        = 0,
148     IEEE802154_FCS_TYPE_16_BIT      = 1, /* ITU-T CRC16 */
149     IEEE802154_FCS_TYPE_32_BIT      = 2, /* ITU-T CRC32 */
150 } ieee802154_fcs_type_t;
151 
152 typedef enum {
153     IEEE802154_SUN_TYPE_FSK_A       = 0x00,
154     IEEE802154_SUN_TYPE_FSK_B       = 0x01,
155     IEEE802154_SUN_TYPE_OQPSK_A     = 0x02,
156     IEEE802154_SUN_TYPE_OQPSK_B     = 0x03,
157     IEEE802154_SUN_TYPE_OQPSK_C     = 0x04,
158     IEEE802154_SUN_TYPE_OFDM_OPT1   = 0x05,
159     IEEE802154_SUN_TYPE_OFDM_OPT2   = 0x06,
160     IEEE802154_SUN_TYPE_OFDM_OPT3   = 0x07,
161     IEEE802154_SUN_TYPE_OFDM_OPT4   = 0x08,
162 } ieee802154_sun_type_t;
163 
164 /* boolean value set if the FCS must be ok before payload is dissected */
165 static gboolean ieee802154_fcs_ok = TRUE;
166 
167 /* boolean value set to enable ack tracking */
168 static gboolean ieee802154_ack_tracking = FALSE;
169 
170 /* boolean value set to enable 802.15.4e dissection compatibility */
171 static gboolean ieee802154e_compatibility = FALSE;
172 
173 /* TSCH ASN for nonce in decryption */
174 static guint64 ieee802154_tsch_asn = 0;
175 
176 static const char  *ieee802154_user    = "User";
177 
178 static wmem_tree_t* mac_key_hash_handlers;
179 
180 #ifndef ROUND_UP
181 #define ROUND_UP(_offset_, _align_) (((_offset_) + (_align_) - 1) / (_align_) * (_align_))
182 #endif
183 
184 /*
185  * Address Hash Tables
186  *
187  */
188 ieee802154_map_tab_t ieee802154_map = { NULL, NULL };
189 
190 /*
191  * Static Address Mapping UAT
192  *
193  */
194 /* UAT entry structure. */
195 typedef struct {
196     guchar *eui64;
197     guint   eui64_len;
198     guint   addr16;
199     guint   pan;
200 } static_addr_t;
201 
202 /* UAT variables */
203 static uat_t         *static_addr_uat  = NULL;
204 static static_addr_t *static_addrs     = NULL;
205 static guint          num_static_addrs = 0;
206 
207 static void*
addr_uat_copy_cb(void * dest,const void * source,size_t len _U_)208 addr_uat_copy_cb(void *dest, const void *source, size_t len _U_)
209 {
210     const static_addr_t* o = (const static_addr_t*)source;
211     static_addr_t* d = (static_addr_t*)dest;
212 
213     d->eui64 = (guchar *)g_memdup2(o->eui64, o->eui64_len);
214     d->eui64_len = o->eui64_len;
215     d->addr16 = o->addr16;
216     d->pan = o->pan;
217 
218     return dest;
219 }
220 
221 /* Sanity-checks a UAT record. */
222 static gboolean
addr_uat_update_cb(void * r,char ** err)223 addr_uat_update_cb(void *r, char **err)
224 {
225     static_addr_t *map = (static_addr_t *)r;
226     /* Ensure a valid short address */
227     if (map->addr16 >= IEEE802154_NO_ADDR16) {
228         *err = g_strdup("Invalid short address");
229         return FALSE;
230     }
231     /* Ensure a valid PAN identifier. */
232     if (map->pan >= IEEE802154_BCAST_PAN) {
233         *err = g_strdup("Invalid PAN identifier");
234         return FALSE;
235     }
236     /* Ensure a valid EUI-64 length */
237     if (map->eui64_len != sizeof(guint64)) {
238         *err = g_strdup("Invalid EUI-64 length");
239         return FALSE;
240     }
241     return TRUE;
242 } /* ieee802154_addr_uat_update_cb */
243 
244 static void
addr_uat_free_cb(void * r)245 addr_uat_free_cb(void *r)
246 {
247     static_addr_t *rec = (static_addr_t *)r;
248     g_free(rec->eui64);
249 }
250 
251 /* Field callbacks. */
252 UAT_HEX_CB_DEF(addr_uat, addr16, static_addr_t)
253 UAT_HEX_CB_DEF(addr_uat, pan, static_addr_t)
254 UAT_BUFFER_CB_DEF(addr_uat, eui64, static_addr_t, eui64, eui64_len)
255 
256 /*
257  * Decryption Keys UAT
258  */
259 
260 /* UAT variables */
261 static uat_t            *ieee802154_key_uat = NULL;
262 static ieee802154_key_t *ieee802154_keys = NULL;
263 static guint             num_ieee802154_keys = 0;
264 
ieee802154_key_post_update_cb(void)265 static void ieee802154_key_post_update_cb(void)
266 {
267     guint i;
268     GByteArray *bytes;
269 
270     for (i = 0; i < num_ieee802154_keys; i++)
271     {
272         switch (ieee802154_keys[i].hash_type) {
273         case KEY_HASH_NONE:
274         case KEY_HASH_ZIP:
275             /* Get the IEEE 802.15.4 decryption key. */
276             bytes = g_byte_array_new();
277             if (hex_str_to_bytes(ieee802154_keys[i].pref_key, bytes, FALSE))
278             {
279                 if (ieee802154_keys[i].hash_type == KEY_HASH_ZIP) {
280                     char digest[32];
281 
282                     if (!ws_hmac_buffer(GCRY_MD_SHA256, digest, "ZigBeeIP", 8, bytes->data, IEEE802154_CIPHER_SIZE)) {
283                         /* Copy upper hashed bytes to the key */
284                         memcpy(ieee802154_keys[i].key, &digest[IEEE802154_CIPHER_SIZE], IEEE802154_CIPHER_SIZE);
285                         /* Copy lower hashed bytes to the MLE key */
286                         memcpy(ieee802154_keys[i].mle_key, digest, IEEE802154_CIPHER_SIZE);
287                     } else {
288                         /* Just copy the keys verbatim */
289                         memcpy(ieee802154_keys[i].key, bytes->data, IEEE802154_CIPHER_SIZE);
290                         memcpy(ieee802154_keys[i].mle_key, bytes->data, IEEE802154_CIPHER_SIZE);
291                     }
292                 } else {
293                     /* Just copy the keys verbatim */
294                     memcpy(ieee802154_keys[i].key, bytes->data, IEEE802154_CIPHER_SIZE);
295                     memcpy(ieee802154_keys[i].mle_key, bytes->data, IEEE802154_CIPHER_SIZE);
296                 }
297             }
298             g_byte_array_free(bytes, TRUE);
299             break;
300         case KEY_HASH_THREAD:
301             /* XXX - TODO? */
302             break;
303         }
304     }
305 }
306 
ieee802154_key_update_cb(void * r,char ** err)307 static gboolean ieee802154_key_update_cb(void *r, char **err)
308 {
309     ieee802154_key_t* rec = (ieee802154_key_t*)r;
310     GByteArray *bytes;
311 
312     switch (rec->hash_type) {
313     case KEY_HASH_NONE:
314     case KEY_HASH_ZIP:
315         bytes = g_byte_array_new();
316         if (hex_str_to_bytes(rec->pref_key, bytes, FALSE) == FALSE)
317         {
318             *err = g_strdup("Invalid key");
319             g_byte_array_free(bytes, TRUE);
320             return FALSE;
321         }
322 
323         if (bytes->len < IEEE802154_CIPHER_SIZE)
324         {
325             *err = g_strdup_printf("Key must be at least %d bytes", IEEE802154_CIPHER_SIZE);
326             g_byte_array_free(bytes, TRUE);
327             return FALSE;
328         }
329         g_byte_array_free(bytes, TRUE);
330         break;
331     case KEY_HASH_THREAD:
332         /* XXX - TODO? */
333         break;
334     }
335 
336     return TRUE;
337 }
338 
ieee802154_key_copy_cb(void * n,const void * o,size_t siz _U_)339 static void* ieee802154_key_copy_cb(void* n, const void* o, size_t siz _U_) {
340     ieee802154_key_t* new_record = (ieee802154_key_t*)n;
341     const ieee802154_key_t* old_record = (const ieee802154_key_t*)o;
342 
343     new_record->pref_key = g_strdup(old_record->pref_key);
344     new_record->key_index = old_record->key_index;
345     new_record->hash_type = old_record->hash_type;
346 
347     return new_record;
348 }
349 
ieee802154_key_free_cb(void * r)350 static void ieee802154_key_free_cb(void*r) {
351     ieee802154_key_t* rec = (ieee802154_key_t *)r;
352 
353     g_free(rec->pref_key);
354 }
355 
356 /* Field callbacks. */
357 UAT_CSTRING_CB_DEF(key_uat, pref_key, ieee802154_key_t)
358 UAT_DEC_CB_DEF(key_uat, key_index, ieee802154_key_t)
359 UAT_VS_DEF(key_uat, hash_type, ieee802154_key_t, ieee802154_key_hash, KEY_HASH_NONE, "No hash")
360 
361 
362 /*-------------------------------------
363  * Dissector Function Prototypes
364  *-------------------------------------
365  */
366 
367 /* Dissection Routines. */
368 static int dissect_ieee802154_nonask_phy   (tvbuff_t *, packet_info *, proto_tree *, void *);
369 static int dissect_ieee802154              (tvbuff_t *, packet_info *, proto_tree *, void *);
370 static int dissect_ieee802154_nofcs        (tvbuff_t *, packet_info *, proto_tree *, void *);
371 static int dissect_ieee802154_cc24xx       (tvbuff_t *, packet_info *, proto_tree *, void *);
372 static int dissect_ieee802154_tap          (tvbuff_t *, packet_info *, proto_tree *, void *);
373 static tvbuff_t *dissect_zboss_specific    (tvbuff_t *, packet_info *, proto_tree *);
374 static void dissect_ieee802154_common      (tvbuff_t *, packet_info *, proto_tree *, guint, guint);
375 static void ieee802154_dissect_fcs(tvbuff_t *tvb, proto_tree *ieee802154_tree, guint fcs_len, gboolean fcs_ok);
376 static void ieee802154_dissect_cc24xx_metadata(tvbuff_t *tvb, proto_tree *ieee802154_tree, gboolean fcs_ok);
377 static ieee802154_fcs_type_t dissect_ieee802154_tap_tlvs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
378 
379 /* Information Elements */
380 static int dissect_ieee802154_header_ie        (tvbuff_t *, packet_info *, proto_tree *, guint, ieee802154_packet *);
381 static int dissect_ieee802154_payload_ie       (tvbuff_t *, packet_info *, proto_tree *, guint, ieee802154_packet *);
382 static int dissect_802154_eb_filter            (tvbuff_t *, packet_info *, proto_tree *, void *);
383 static int dissect_802154_tsch_time_sync       (tvbuff_t *, packet_info *, proto_tree *, void *);
384 static int dissect_802154_tsch_timeslot        (tvbuff_t *, packet_info *, proto_tree *, void *);
385 static int dissect_802154_tsch_slotframe_link  (tvbuff_t *, packet_info *, proto_tree *, void *);
386 static int dissect_802154_channel_hopping      (tvbuff_t *, packet_info *, proto_tree *, void *);
387 /* Sub-dissector helpers. */
388 static void dissect_ieee802154_fcf             (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *, guint *);
389 static void dissect_ieee802154_command         (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
390 static void dissect_ieee802154_assoc_req       (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
391 static void dissect_ieee802154_assoc_rsp       (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
392 static void dissect_ieee802154_disassoc        (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
393 static void dissect_ieee802154_realign         (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
394 static void dissect_ieee802154_gtsreq          (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
395 
396 /* Decryption helpers. */
397 static tvbuff_t *dissect_ieee802154_decrypt(tvbuff_t *, guint, packet_info *, ieee802154_packet *, ieee802154_decrypt_info_t*);
398 
399 static guint ieee802154_set_mac_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t *uat_key);
400 static void tsch_ccm_init_nonce(guint64 addr, guint64 asn, gchar* generic_nonce);
401 
402 /* Initialize Protocol and Registered fields */
403 static int proto_ieee802154_nonask_phy = -1;
404 static int hf_ieee802154_nonask_phy_preamble = -1;
405 static int hf_ieee802154_nonask_phy_sfd = -1;
406 static int hf_ieee802154_nonask_phy_length = -1;
407 static int hf_ieee802154_nonask_phr = -1;
408 
409 static int proto_ieee802154 = -1;
410 static int proto_ieee802154_tap = -1;
411 static int hf_ieee802154_frame_length = -1;
412 static int hf_ieee802154_fcf = -1;
413 static int hf_ieee802154_frame_type = -1;
414 static int hf_ieee802154_security = -1;
415 static int hf_ieee802154_pending = -1;
416 static int hf_ieee802154_ack_request = -1;
417 static int hf_ieee802154_pan_id_compression = -1;
418 static int hf_ieee802154_fcf_reserved = -1;
419 static int hf_ieee802154_seqno_suppression = -1;
420 static int hf_ieee802154_ie_present = -1;
421 static int hf_ieee802154_src_addr_mode = -1;
422 static int hf_ieee802154_version = -1;
423 static int hf_ieee802154_dst_addr_mode = -1;
424 
425 static int hf_ieee802154_mpf_long_frame_control = -1;
426 static int hf_ieee802154_mpf_dst_addr_mode = -1;
427 static int hf_ieee802154_mpf_src_addr_mode = -1;
428 static int hf_ieee802154_mpf_pan_id_present = -1;
429 static int hf_ieee802154_mpf_security = -1;
430 static int hf_ieee802154_mpf_seqno_suppression = -1;
431 static int hf_ieee802154_mpf_pending = -1;
432 static int hf_ieee802154_mpf_version = -1;
433 static int hf_ieee802154_mpf_ack_request = -1;
434 static int hf_ieee802154_mpf_ie_present = -1;
435 
436 static int hf_ieee802154_header_ies = -1;
437 static int hf_ieee802154_header_ie_tlv = -1;
438 static int hf_ieee802154_header_ie_type = -1;
439 static int hf_ieee802154_header_ie_id = -1;
440 static int hf_ieee802154_header_ie_length = -1;
441 static int hf_ieee802154_ie_unknown_content = -1;
442 static int hf_ieee802154_hie_unsupported = -1;
443 static int hf_ieee802154_hie_time_correction = -1;
444 static int hf_ieee802154_hie_ht1 = -1;
445 static int hf_ieee802154_hie_ht2 = -1;
446 static int hf_ieee802154_nack = -1;
447 static int hf_ieee802154_hie_time_correction_time_sync_info = -1;
448 static int hf_ieee802154_hie_time_correction_value = -1;
449 static int hf_ieee802154_hie_csl = -1;
450 static int hf_ieee802154_hie_csl_phase = -1;
451 static int hf_ieee802154_hie_csl_period = -1;
452 static int hf_ieee802154_hie_csl_rendezvous_time = -1;
453 static int hf_ieee802154_hie_global_time = -1;
454 static int hf_ieee802154_hie_global_time_value = -1;
455 static int hf_ieee802154_hie_vendor_specific = -1;
456 static int hf_ieee802154_hie_vendor_specific_vendor_oui = -1;
457 static int hf_ieee802154_hie_vendor_specific_content = -1;
458 static int hf_ieee802154_payload_ies = -1;
459 static int hf_ieee802154_payload_ie_tlv = -1;
460 static int hf_ieee802154_payload_ie_type = -1;
461 static int hf_ieee802154_payload_ie_id = -1;
462 static int hf_ieee802154_payload_ie_length = -1;
463 static int hf_ieee802154_pie_unsupported = -1;
464 static int hf_ieee802154_pie_termination = -1;
465 static int hf_ieee802154_pie_vendor = -1;
466 static int hf_ieee802154_pie_vendor_oui = -1;
467 static int hf_ieee802154_pie_ietf = -1;
468 static int hf_ieee802154_mlme = -1;
469 static int hf_ieee802154_mlme_ie_data = -1;
470 static int hf_ieee802154_mlme_ie_unsupported = -1;
471 static int hf_ieee802154_psie = -1;
472 static int hf_ieee802154_psie_type = -1;
473 static int hf_ieee802154_psie_id_short = -1;
474 static int hf_ieee802154_psie_length_short = -1;
475 static int hf_ieee802154_psie_id_long = -1;
476 static int hf_ieee802154_psie_length_long = -1;
477 
478 static int hf_ieee802154_tsch_sync = -1;
479 static int hf_ieee802154_tsch_asn = -1;
480 static int hf_ieee802154_tsch_join_metric = -1;
481 static int hf_ieee802154_tsch_slotframe = -1;
482 static int hf_ieee802154_tsch_link_info = -1;
483 static int hf_ieee802154_tsch_slotf_link_nb_slotf = -1;
484 static int hf_ieee802154_tsch_slotf_link_slotf_handle= -1;
485 static int hf_ieee802154_tsch_slotf_size = -1;
486 static int hf_ieee802154_tsch_slotf_link_nb_links = -1;
487 static int hf_ieee802154_tsch_slotf_link_timeslot = -1;
488 static int hf_ieee802154_tsch_slotf_link_channel_offset = -1;
489 static int hf_ieee802154_tsch_slotf_link_options = -1;
490 static int hf_ieee802154_tsch_slotf_link_options_tx = -1;
491 static int hf_ieee802154_tsch_slotf_link_options_rx = -1;
492 static int hf_ieee802154_tsch_slotf_link_options_shared = -1;
493 static int hf_ieee802154_tsch_slotf_link_options_timkeeping = -1;
494 static int hf_ieee802154_tsch_slotf_link_options_priority = -1;
495 static int hf_ieee802154_tsch_channel_hopping = -1;
496 static int hf_ieee802154_tsch_hopping_sequence_id = -1;
497 static int hf_ieee802154_tsch_timeslot = -1;
498 static int hf_ieee802154_tsch_timeslot_id = -1;
499 static int hf_ieee802154_tsch_timeslot_cca_offset = -1;
500 static int hf_ieee802154_tsch_timeslot_cca = -1;
501 static int hf_ieee802154_tsch_timeslot_tx_offset = -1;
502 static int hf_ieee802154_tsch_timeslot_rx_offset = -1;
503 static int hf_ieee802154_tsch_timeslot_rx_ack_delay = -1;
504 static int hf_ieee802154_tsch_timeslot_tx_ack_delay = -1;
505 static int hf_ieee802154_tsch_timeslot_rx_wait = -1;
506 static int hf_ieee802154_tsch_timeslot_ack_wait = -1;
507 static int hf_ieee802154_tsch_timeslot_turnaround = -1;
508 static int hf_ieee802154_tsch_timeslot_max_ack = -1;
509 static int hf_ieee802154_tsch_timeslot_max_tx = -1;
510 static int hf_ieee802154_tsch_timeslot_length = -1;
511 
512 static int hf_ieee802154_psie_eb_filter = -1;
513 static int hf_ieee802154_psie_eb_filter_pjoin = -1;
514 static int hf_ieee802154_psie_eb_filter_lqi = -1;
515 static int hf_ieee802154_psie_eb_filter_lqi_min = -1;
516 static int hf_ieee802154_psie_eb_filter_percent = -1;
517 static int hf_ieee802154_psie_eb_filter_percent_prob = -1;
518 static int hf_ieee802154_psie_eb_filter_attr_id = -1;
519 static int hf_ieee802154_psie_eb_filter_attr_id_bitmap = -1;
520 static int hf_ieee802154_p_ie_ietf_sub_id = -1;
521 
522 static int hf_ieee802154_6top = -1;
523 static int hf_ieee802154_6top_version = -1;
524 static int hf_ieee802154_6top_type = -1;
525 static int hf_ieee802154_6top_flags_reserved = -1;
526 static int hf_ieee802154_6top_code = -1;
527 static int hf_ieee802154_6top_sfid = -1;
528 static int hf_ieee802154_6top_seqnum = -1;
529 static int hf_ieee802154_6top_metadata = -1;
530 static int hf_ieee802154_6top_cell_options = -1;
531 static int hf_ieee802154_6top_cell_option_tx = -1;
532 static int hf_ieee802154_6top_cell_option_rx = -1;
533 static int hf_ieee802154_6top_cell_option_shared = -1;
534 static int hf_ieee802154_6top_cell_option_reserved = -1;
535 static int hf_ieee802154_6top_num_cells = -1;
536 static int hf_ieee802154_6top_cell_list = -1;
537 static int hf_ieee802154_6top_rel_cell_list = -1;
538 static int hf_ieee802154_6top_cand_cell_list = -1;
539 static int hf_ieee802154_6top_cell = -1;
540 static int hf_ieee802154_6top_reserved = -1;
541 static int hf_ieee802154_6top_offset = -1;
542 static int hf_ieee802154_6top_max_num_cells = -1;
543 static int hf_ieee802154_6top_slot_offset = -1;
544 static int hf_ieee802154_6top_channel_offset = -1;
545 static int hf_ieee802154_6top_total_num_cells = -1;
546 static int hf_ieee802154_6top_payload = -1;
547 
548 static int hf_ieee802159_mpx = -1;
549 static int hf_ieee802159_mpx_transaction_control = -1;
550 static int hf_ieee802159_mpx_transfer_type = -1;
551 static int hf_ieee802159_mpx_transaction_id = -1;
552 static int hf_ieee802159_mpx_transaction_id_as_multiplex_id = -1;
553 static int hf_ieee802159_mpx_fragment_number = -1;
554 static int hf_ieee802159_mpx_total_frame_size = -1;
555 static int hf_ieee802159_mpx_multiplex_id = -1;
556 static int hf_ieee802159_mpx_kmp_id = -1;
557 static int hf_ieee802159_mpx_kmp_vendor_oui = -1;
558 static int hf_ieee802159_mpx_fragment = -1;
559 static int hf_ieee802159_mpx_wisun_subid = -1;
560 
561 static int proto_zboss = -1;
562 static int hf_zboss_direction = -1;
563 static int hf_zboss_page = -1;
564 static int hf_zboss_channel = -1;
565 static int hf_zboss_trace_number = -1;
566 
567 static int hf_ieee802154_seqno = -1;
568 static int hf_ieee802154_dst_panID = -1;
569 static int hf_ieee802154_dst16 = -1;
570 static int hf_ieee802154_dst64 = -1;
571 static int hf_ieee802154_src_panID = -1;
572 static int hf_ieee802154_src16 = -1;
573 static int hf_ieee802154_src64 = -1;
574 static int hf_ieee802154_src64_origin = -1;
575 static int hf_ieee802154_addr16 = -1;
576 static int hf_ieee802154_addr64 = -1;
577 static int hf_ieee802154_fcs = -1;
578 static int hf_ieee802154_fcs32 = -1;
579 static int hf_ieee802154_rssi = -1;
580 static int hf_ieee802154_fcs_ok = -1;
581 static int hf_ieee802154_correlation = -1;
582 
583 /* Registered fields for Command Packets */
584 static int hf_ieee802154_cmd_id = -1;
585 static int hf_ieee802154_cinfo_alt_coord = -1;
586 static int hf_ieee802154_cinfo_device_type = -1;
587 static int hf_ieee802154_cinfo_power_src = -1;
588 static int hf_ieee802154_cinfo_idle_rx = -1;
589 static int hf_ieee802154_cinfo_sec_capable = -1;
590 static int hf_ieee802154_cinfo_alloc_addr = -1;
591 static int hf_ieee802154_assoc_addr = -1;
592 static int hf_ieee802154_assoc_status = -1;
593 static int hf_ieee802154_disassoc_reason = -1;
594 static int hf_ieee802154_realign_pan = -1;
595 static int hf_ieee802154_realign_caddr = -1;
596 static int hf_ieee802154_realign_channel = -1;
597 static int hf_ieee802154_realign_addr = -1;
598 static int hf_ieee802154_realign_channel_page = -1;
599 static int hf_ieee802154_gtsreq_len = -1;
600 static int hf_ieee802154_gtsreq_dir = -1;
601 static int hf_ieee802154_gtsreq_type = -1;
602 static int hf_ieee802154_cmd_vendor_oui = -1;
603 
604 /* Registered fields for Beacon Packets */
605 static int hf_ieee802154_beacon_order = -1;
606 static int hf_ieee802154_superframe_order = -1;
607 static int hf_ieee802154_cap = -1;
608 static int hf_ieee802154_superframe_battery_ext = -1;
609 static int hf_ieee802154_superframe_coord = -1;
610 static int hf_ieee802154_assoc_permit = -1;
611 static int hf_ieee802154_gts_count = -1;
612 static int hf_ieee802154_gts_permit = -1;
613 static int hf_ieee802154_gts_direction = -1;
614 static int hf_ieee802154_gts_address = -1;
615 static int hf_ieee802154_pending16 = -1;
616 static int hf_ieee802154_pending64 = -1;
617 
618 /* Registered fields for Auxiliary Security Header */
619 static int hf_ieee802154_aux_security_header = -1;
620 static int hf_ieee802154_aux_sec_security_control = -1;
621 static int hf_ieee802154_aux_sec_security_level = -1;
622 static int hf_ieee802154_aux_sec_key_id_mode = -1;
623 static int hf_ieee802154_aux_sec_frame_counter_suppression = -1;
624 static int hf_ieee802154_aux_sec_asn_in_nonce = -1;
625 static int hf_ieee802154_aux_sec_reserved = -1;
626 static int hf_ieee802154_aux_sec_frame_counter = -1;
627 static int hf_ieee802154_aux_sec_key_source = -1;
628 static int hf_ieee802154_aux_sec_key_source_bytes = -1;
629 static int hf_ieee802154_aux_sec_key_index = -1;
630 static int hf_ieee802154_mic = -1;
631 static int hf_ieee802154_key_number = -1;
632 
633 /* 802.15.4-2003 security */
634 static int hf_ieee802154_sec_frame_counter = -1;
635 static int hf_ieee802154_sec_key_sequence_counter = -1;
636 
637 /* 802.15.4 ack */
638 static int hf_ieee802154_no_ack = -1;
639 static int hf_ieee802154_no_ack_request = -1;
640 static int hf_ieee802154_ack_in = -1;
641 static int hf_ieee802154_ack_to = -1;
642 static int hf_ieee802154_ack_time = -1;
643 
644 /* 802.15.4 TAP */
645 static int hf_ieee802154_tap_version = -1;
646 static int hf_ieee802154_tap_reserved = -1;
647 static int hf_ieee802154_tap_length = -1;
648 static int hf_ieee802154_tap_data_length = -1;
649 static int hf_ieee802154_tap_tlv_type = -1;
650 static int hf_ieee802154_tap_tlv_length = -1;
651 static int hf_ieee802154_tap_tlv_unknown = -1;
652 static int hf_ieee802154_tap_tlv_padding = -1;
653 static int hf_ieee802154_tap_fcs_type = -1;
654 static int hf_ieee802154_tap_rss = -1;
655 static int hf_ieee802154_ch_page = -1;
656 static int hf_ieee802154_ch_num = -1;
657 static int hf_ieee802154_bit_rate = -1;
658 static int hf_ieee802154_sun_band = -1;
659 static int hf_ieee802154_sun_type = -1;
660 static int hf_ieee802154_sun_mode = -1;
661 static int hf_ieee802154_mode_fsk_a = -1;
662 static int hf_ieee802154_mode_fsk_b = -1;
663 static int hf_ieee802154_mode_oqpsk_a = -1;
664 static int hf_ieee802154_mode_oqpsk_b = -1;
665 static int hf_ieee802154_mode_oqpsk_c = -1;
666 static int hf_ieee802154_mode_ofdm = -1;
667 static int hf_ieee802154_sof_ts = -1;
668 static int hf_ieee802154_eof_ts = -1;
669 static int hf_ieee802154_slot_start_ts = -1;
670 static int hf_ieee802154_tap_timeslot_length = -1;
671 static int hf_ieee802154_tap_lqi = -1;
672 static int hf_ieee802154_chplan_start = -1;
673 static int hf_ieee802154_chplan_spacing = -1;
674 static int hf_ieee802154_chplan_channels = -1;
675 static int hf_ieee802154_ch_freq = -1;
676 static int hf_ieee802154_frame_start_offset = -1;
677 static int hf_ieee802154_frame_duration = -1;
678 static int hf_ieee802154_frame_end_offset = -1;
679 static int hf_ieee802154_asn = -1;
680 
681 typedef struct _ieee802154_transaction_t {
682     guint64 dst64;
683     guint64 src64;
684     gint32 dst_addr_mode;
685     gint32 src_addr_mode;
686     guint16 dst16;
687     guint16 src16;
688     guint32 rqst_frame;
689     guint32 ack_frame;
690     nstime_t rqst_time;
691     nstime_t ack_time;
692     gboolean dst_pan_present;
693     gboolean src_pan_present;
694     guint16 dst_pan;
695     guint16 src_pan;
696 } ieee802154_transaction_t;
697 
698 static const nstime_t ieee802154_transaction_timeout = NSTIME_INIT_SECS_MSECS(1, 0); // ACKs usually arrive within milliseconds
699 
700 static wmem_tree_t *transaction_unmatched_pdus;
701 static wmem_tree_t *transaction_matched_pdus;
702 
703 static ieee802154_transaction_t *transaction_start(packet_info *pinfo, proto_tree *tree, const ieee802154_packet *packet, guint32 *key);
704 static ieee802154_transaction_t *transaction_end(packet_info *pinfo, proto_tree *tree, const ieee802154_packet *packet, guint32 *key);
705 
706 /* Initialize Subtree Pointers */
707 static gint ett_ieee802154_nonask_phy = -1;
708 static gint ett_ieee802154_nonask_phy_phr = -1;
709 static gint ett_ieee802154_tap = -1;
710 static gint ett_ieee802154_tap_header = -1;
711 static gint ett_ieee802154_tap_tlv = -1;
712 static gint ett_ieee802154 = -1;
713 static gint ett_ieee802154_fcf = -1;
714 static gint ett_ieee802154_auxiliary_security = -1;
715 static gint ett_ieee802154_aux_sec_control = -1;
716 static gint ett_ieee802154_aux_sec_key_id = -1;
717 static gint ett_ieee802154_fcs = -1;
718 static gint ett_ieee802154_cmd = -1;
719 static gint ett_ieee802154_superframe = -1;
720 static gint ett_ieee802154_gts = -1;
721 static gint ett_ieee802154_gts_direction = -1;
722 static gint ett_ieee802154_gts_descriptors = -1;
723 static gint ett_ieee802154_pendaddr = -1;
724 static gint ett_ieee802154_header_ies = -1;
725 static gint ett_ieee802154_header_ie = -1;
726 static gint ett_ieee802154_header_ie_tlv = -1;
727 static gint ett_ieee802154_hie_unsupported = -1;
728 static gint ett_ieee802154_hie_time_correction = -1;
729 static gint ett_ieee802154_hie_ht = -1;
730 static gint ett_ieee802154_hie_csl = -1;
731 static gint ett_ieee802154_hie_global_time = -1;
732 static gint ett_ieee802154_hie_vendor_specific = -1;
733 static gint ett_ieee802154_payload_ie = -1;
734 static gint ett_ieee802154_payload_ie_tlv = -1;
735 static gint ett_ieee802154_pie_termination = -1;
736 static gint ett_ieee802154_pie_vendor = -1;
737 static gint ett_ieee802154_pie_ietf = -1;
738 static gint ett_ieee802154_pie_unsupported = -1;
739 static gint ett_ieee802154_mlme = -1;
740 static gint ett_ieee802154_mlme_payload = -1;
741 static gint ett_ieee802154_mlme_payload_data = -1;
742 static gint ett_ieee802154_mlme_unsupported = -1;
743 static gint ett_ieee802154_tsch_slotframe = -1;
744 static gint ett_ieee802154_tsch_slotframe_list = -1;
745 static gint ett_ieee802154_tsch_slotframe_link = -1;
746 static gint ett_ieee802154_tsch_slotframe_link_options = -1;
747 static gint ett_ieee802154_tsch_timeslot = -1;
748 static gint ett_ieee802154_tsch_synch = -1;
749 static gint ett_ieee802154_channel_hopping = -1;
750 static gint ett_ieee802154_psie = -1;
751 static gint ett_ieee802154_eb_filter = -1;
752 static gint ett_ieee802154_eb_filter_bitmap = -1;
753 static gint ett_ieee802154_zigbee = -1;
754 static gint ett_ieee802154_zboss = -1;
755 static gint ett_ieee802154_p_ie_6top = -1;
756 static gint ett_ieee802154_p_ie_6top_cell_options = -1;
757 static gint ett_ieee802154_p_ie_6top_cell_list = -1;
758 static gint ett_ieee802154_p_ie_6top_cand_cell_list = -1;
759 static gint ett_ieee802154_p_ie_6top_rel_cell_list = -1;
760 static gint ett_ieee802154_p_ie_6top_cell = -1;
761 static gint ett_ieee802159_mpx = -1;
762 static gint ett_ieee802159_mpx_transaction_control = -1;
763 
764 static expert_field ei_ieee802154_fcs_bitmask_len = EI_INIT;
765 static expert_field ei_ieee802154_invalid_addressing = EI_INIT;
766 static expert_field ei_ieee802154_invalid_panid_compression = EI_INIT;
767 static expert_field ei_ieee802154_invalid_panid_compression2 = EI_INIT;
768 static expert_field ei_ieee802154_fcs = EI_INIT;
769 static expert_field ei_ieee802154_decrypt_error = EI_INIT;
770 static expert_field ei_ieee802154_dst = EI_INIT;
771 static expert_field ei_ieee802154_src = EI_INIT;
772 static expert_field ei_ieee802154_frame_ver = EI_INIT;
773 /* static expert_field ei_ieee802154_frame_type = EI_INIT; */
774 static expert_field ei_ieee802154_seqno_suppression = EI_INIT;
775 static expert_field ei_ieee802154_ack_not_found = EI_INIT;
776 static expert_field ei_ieee802154_ack_request_not_found = EI_INIT;
777 static expert_field ei_ieee802154_time_correction_error = EI_INIT;
778 static expert_field ei_ieee802154_6top_unsupported_type = EI_INIT;
779 static expert_field ei_ieee802154_6top_unsupported_return_code = EI_INIT;
780 static expert_field ei_ieee802154_6top_unsupported_command = EI_INIT;
781 static expert_field ei_ieee802154_ie_unsupported_id = EI_INIT;
782 static expert_field ei_ieee802154_ie_unknown_extra_content = EI_INIT;
783 static expert_field ei_ieee802159_mpx_invalid_transfer_type = EI_INIT;
784 static expert_field ei_ieee802159_mpx_unsupported_kmp = EI_INIT;
785 static expert_field ei_ieee802159_mpx_unknown_kmp = EI_INIT;
786 static expert_field ei_ieee802154_missing_payload_ie = EI_INIT;
787 static expert_field ei_ieee802154_payload_ie_in_header = EI_INIT;
788 static expert_field ei_ieee802154_unsupported_cmd = EI_INIT;
789 static expert_field ei_ieee802154_unknown_cmd = EI_INIT;
790 static expert_field ei_ieee802154_tap_tlv_invalid_type = EI_INIT;
791 static expert_field ei_ieee802154_tap_tlv_invalid_length = EI_INIT;
792 static expert_field ei_ieee802154_tap_tlv_padding_not_zeros = EI_INIT;
793 static expert_field ei_ieee802154_tap_tlv_invalid_fcs_type = EI_INIT;
794 
795 static int ieee802_15_4_short_address_type = -1;
796 /*
797  * Dissector handles
798  *  - beacon dissection is always heuristic.
799  *  - the PANID table is for stateful dissectors only (ie: Decode-As)
800  *  - otherwise, data dissectors fall back to the heuristic dissectors.
801  */
802 static dissector_table_t        panid_dissector_table;
803 static heur_dissector_list_t    ieee802154_beacon_subdissector_list;
804 static heur_dissector_list_t    ieee802154_heur_subdissector_list;
805 
806 /* For the IEs and the vendor specific command */
807 static dissector_table_t header_ie_dissector_table;
808 static dissector_table_t payload_ie_dissector_table;
809 static dissector_table_t mlme_ie_dissector_table;
810 static dissector_table_t cmd_vendor_dissector_table;
811 
812 static dissector_handle_t  zigbee_ie_handle;
813 static dissector_handle_t  zigbee_nwk_handle;
814 static dissector_handle_t  ieee802154_handle;
815 static dissector_handle_t  ieee802154_nonask_phy_handle;
816 static dissector_handle_t  ieee802154_nofcs_handle;
817 static dissector_handle_t  ieee802154_tap_handle;
818 
819 static int ieee802154_tap = -1;
820 
821 /* Handles for MPX-IE the Multiplex ID */
822 static dissector_table_t ethertype_table;
823 static dissector_handle_t eapol_handle;
824 static dissector_handle_t lowpan_handle;
825 static dissector_handle_t wisun_sec_handle;
826 
827 /* Versions */
828 static const value_string ieee802154_frame_versions[] = {
829     { IEEE802154_VERSION_2003,     "IEEE Std 802.15.4-2003" },
830     { IEEE802154_VERSION_2006,     "IEEE Std 802.15.4-2006" },
831     { IEEE802154_VERSION_2015,     "IEEE Std 802.15.4-2015" },
832     { IEEE802154_VERSION_RESERVED, "Reserved" },
833     { 0, NULL }
834 };
835 
836 /* Name Strings */
837 static const value_string ieee802154_frame_types[] = {
838     { IEEE802154_FCF_BEACON,       "Beacon" },
839     { IEEE802154_FCF_DATA,         "Data" },
840     { IEEE802154_FCF_ACK,          "Ack" },
841     { IEEE802154_FCF_CMD,          "Command" },
842     { IEEE802154_FCF_RESERVED,     "Reserved" },
843     { IEEE802154_FCF_MULTIPURPOSE, "Multipurpose" },
844     { IEEE802154_FCF_FRAGMENT,     "Fragment or Frak" },
845     { IEEE802154_FCF_EXTENDED,     "Extended" },
846     { 0, NULL }
847 };
848 
849 static const value_string ieee802154_addr_modes[] = {
850     { IEEE802154_FCF_ADDR_NONE,     "None" },
851     { IEEE802154_FCF_ADDR_RESERVED, "Reserved" },
852     { IEEE802154_FCF_ADDR_SHORT,    "Short/16-bit" },
853     { IEEE802154_FCF_ADDR_EXT,      "Long/64-bit" },
854     { 0, NULL }
855 };
856 
857 static const value_string ieee802154_cmd_names[] = {
858     { IEEE802154_CMD_ASSOC_REQ,                 "Association Request" },
859     { IEEE802154_CMD_ASSOC_RSP,                 "Association Response" },
860     { IEEE802154_CMD_DISASSOC_NOTIFY,           "Disassociation Notification" },
861     { IEEE802154_CMD_DATA_RQ,                   "Data Request" },
862     { IEEE802154_CMD_PANID_CONFLICT,            "PAN ID Conflict" },
863     { IEEE802154_CMD_ORPHAN_NOTIFY,             "Orphan Notification" },
864     { IEEE802154_CMD_BEACON_REQ,                "Beacon Request" },
865     { IEEE802154_CMD_COORD_REALIGN,             "Coordinator Realignment" },
866     { IEEE802154_CMD_GTS_REQ,                   "GTS Request" },
867     { IEEE802154_CMD_TRLE_MGMT_REQ,             "TRLE Management Request"},
868     { IEEE802154_CMD_TRLE_MGMT_RSP,             "TRLE Management Response"},
869     { IEEE802154_CMD_DSME_ASSOC_REQ,            "DSME Association Request"},
870     { IEEE802154_CMD_DSME_ASSOC_RSP,            "DSME Association Response"},
871     { IEEE802154_CMD_DSME_GTS_REQ,              "DSME GTS Request"},
872     { IEEE802154_CMD_DSME_GTS_RSP,              "DSME GTS Response"},
873     { IEEE802154_CMD_DSME_GTS_NOTIFY,           "DSME GTS Notify"},
874     { IEEE802154_CMD_DSME_INFO_REQ,             "DSME Information Request"},
875     { IEEE802154_CMD_DSME_INFO_RSP,             "DSME Information Response"},
876     { IEEE802154_CMD_DSME_BEACON_ALLOC_NOTIFY,  "DSME Beacon Allocation Notification"},
877     { IEEE802154_CMD_DSME_BEACON_COLL_NOTIFY,   "DSME Beacon Collision Notification"},
878     { IEEE802154_CMD_DSME_LINK_REPORT,          "DSME Link Report"},
879     { IEEE802154_CMD_RIT_DATA_REQ,              "RIT Data Request"},
880     { IEEE802154_CMD_DBS_REQ,                   "DBS Request"},
881     { IEEE802154_CMD_DBS_RSP,                   "DBS Response"},
882     { IEEE802154_CMD_RIT_DATA_RSP,              "RIT Data Response"},
883     { IEEE802154_CMD_VENDOR_SPECIFIC,           "Vendor Specific"},
884     { 0, NULL }
885 };
886 
887 static const value_string ieee802154_sec_level_names[] = {
888     { SECURITY_LEVEL_NONE,        "No Security" },
889     { SECURITY_LEVEL_MIC_32,      "32-bit Message Integrity Code" },
890     { SECURITY_LEVEL_MIC_64,      "64-bit Message Integrity Code" },
891     { SECURITY_LEVEL_MIC_128,     "128-bit Message Integrity Code" },
892     { SECURITY_LEVEL_ENC,         "Encryption" },
893     { SECURITY_LEVEL_ENC_MIC_32,  "Encryption with 32-bit Message Integrity Code" },
894     { SECURITY_LEVEL_ENC_MIC_64,  "Encryption with 64-bit Message Integrity Code" },
895     { SECURITY_LEVEL_ENC_MIC_128, "Encryption with 128-bit Message Integrity Code" },
896     { 0, NULL }
897 };
898 
899 static const value_string ieee802154_key_id_mode_names[] = {
900     { KEY_ID_MODE_IMPLICIT,       "Implicit Key" },
901     { KEY_ID_MODE_KEY_INDEX,      "Indexed Key using the Default Key Source" },
902     { KEY_ID_MODE_KEY_EXPLICIT_4, "Explicit Key with 4-octet Key Source" },
903     { KEY_ID_MODE_KEY_EXPLICIT_8, "Explicit Key with 8-octet Key Source" },
904     { 0, NULL }
905 };
906 
907 static const true_false_string ieee802154_gts_direction_tfs = {
908     "Receive Only",
909     "Transmit Only"
910 };
911 
912 /* The 802.15.4-2003 security suites for the security preferences (only AES-CCM suites are supported). */
913 /* NOTE: The equivalent 2006 security level identifier enumerations are used to simplify 2003 & 2006 integration! */
914 static const enum_val_t ieee802154_2003_sec_suite_enums[] = {
915     { "AES-CCM-128", "AES-128 Encryption, 128-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_128 },
916     { "AES-CCM-64",  "AES-128 Encryption, 64-bit Integrity Protection",  SECURITY_LEVEL_ENC_MIC_64 },
917     { "AES-CCM-32",  "AES-128 Encryption, 32-bit Integrity Protection",  SECURITY_LEVEL_ENC_MIC_32 },
918     { NULL, NULL, 0 }
919 };
920 
921 /* Enumeration for key generation */
922 static const value_string ieee802154_key_hash_vals[] = {
923     { KEY_HASH_NONE, "No hash"},
924     { KEY_HASH_ZIP, "ZigBee IP hash" },
925     { KEY_HASH_THREAD, "Thread hash" },
926     { 0, NULL }
927 };
928 
929 static const value_string ieee802154_ie_types[] = {
930     { 0, "Header" },
931     { 1, "Payload" },
932     { 0, NULL }
933 };
934 
935 static const value_string ieee802154_psie_types[] = {
936     { 0, "Short" },
937     { 1, "Long" },
938     { 0, NULL }
939 };
940 
941 static const value_string ieee802154_header_ie_names[] = {
942     { IEEE802154_HEADER_IE_VENDOR_SPECIFIC, "Vendor Specific IE" },
943     { IEEE802154_HEADER_IE_CSL,             "CSL IE" },
944     { IEEE802154_HEADER_IE_RIT,             "RIT IE" },
945     { IEEE802154_HEADER_IE_DSME_PAN,        "DSME PAN descriptor IE" },
946     { IEEE802154_HEADER_IE_RENDEZVOUS,      "Rendezvous Time IE" },
947     { IEEE802154_HEADER_IE_TIME_CORR,       "Time Correction IE" },
948     { IEEE802154_HEADER_IE_EXT_DSME_PAN,    "Extended DSME PAN descriptor IE" },
949     { IEEE802154_HEADER_IE_FSCD,            "Fragment Sequence Context Description (FSCD) IE" },
950     { IEEE802154_HEADER_IE_SMPL_SUPER_FRM,  "Simplified Superframe Specification IE" },
951     { IEEE802154_HEADER_IE_SMPL_GTS,        "Simplified GTS Specification IE" },
952     { IEEE802154_HEADER_IE_LECIM,           "LECIM Capabilities IE" },
953     { IEEE802154_HEADER_IE_TRLE,            "TRLE Descriptor" },
954     { IEEE802154_HEADER_IE_RCC_CAP,         "RCC Capabilities IE" },
955     { IEEE802154_HEADER_IE_RCCN,            "RCCN Descriptor IE" },
956     { IEEE802154_HEADER_IE_GLOBAL_TIME,     "Global Time IE" },
957     { IEEE802154_HEADER_IE_WISUN,           "Wi-SUN IE" },
958     { IEEE802154_HEADER_IE_DA_IE,           "DA IE" },
959     { IEEE802154_HEADER_IE_HT1,             "Header Termination 1 IE" },
960     { IEEE802154_HEADER_IE_HT2,             "Header Termination 2 IE" },
961     { 0, NULL }
962 };
963 
964 static const true_false_string hf_ieee802154_nack_tfs = {
965     "Negative Acknowledgement",
966     "Acknowledgement"
967 };
968 
969 static const value_string ieee802154_payload_ie_names[] = {
970     { IEEE802154_PAYLOAD_IE_ESDU,                     "ESDU IE" },
971     { IEEE802154_PAYLOAD_IE_MLME,                     "MLME IE" },
972     { IEEE802154_PAYLOAD_IE_VENDOR,                   "Vendor Specific IE" },
973     { IEEE802154_PAYLOAD_IE_MPX,                      "MPX IE" },
974     { IEEE802154_PAYLOAD_IE_WISUN,                    "Wi-SUN IE" },
975     { IEEE802154_PAYLOAD_IE_IETF,                     "IETF IE" },
976     { IEEE802154_PAYLOAD_IE_TERMINATION,              "Payload Termination IE" },
977     { 0, NULL }
978 };
979 
980 static const value_string ieee802154_psie_names[] = {
981     { IEEE802154_MLME_SUBIE_CHANNEL_HOPPING,          "Channel Hopping IE" },
982     { IEEE802154_MLME_SUBIE_TSCH_SYNCH,               "TSCH Synchronization IE" },
983     { IEEE802154_MLME_SUBIE_TSCH_SLOTFR_LINK,         "TSCH Slotframe and Link IE" },
984     { IEEE802154_MLME_SUBIE_TSCH_TIMESLOT,            "TSCH Timeslot IE" },
985     { IEEE802154_MLME_SUBIE_HOPPING_TIMING,           "Hopping Timing IE" },
986     { IEEE802154_MLME_SUBIE_ENHANCED_BEACON_FILTER,   "Enhanced Beacon Filter IE" },
987     { IEEE802154_MLME_SUBIE_MAC_METRICS,              "MAC Metrics IE" },
988     { IEEE802154_MLME_SUBIE_ALL_MAC_METRICS,          "All MAC Metrics IE" },
989     { IEEE802154_MLME_SUBIE_COEXISTENCE_SPEC,         "Coexistence Specification IE" },
990     { IEEE802154_MLME_SUBIE_SUN_DEVICE_CAPABILITIES,  "SUN Device Capabilities IE" },
991     { IEEE802154_MLME_SUBIE_SUN_FSK_GEN_PHY,          "SUN FSK Generic PHY IE" },
992     { IEEE802154_MLME_SUBIE_MODE_SWITCH_PARAMETER,    "Mode Switch Parameter IE" },
993     { IEEE802154_MLME_SUBIE_PHY_PARAMETER_CHANGE,     "PHY Parameter Change IE" },
994     { IEEE802154_MLME_SUBIE_O_QPSK_PHY_MODE,          "O-QPSY PHY Mode IE" },
995     { IEEE802154_MLME_SUBIE_PCA_ALLOCATION,           "PCA Allocation IE" },
996     { IEEE802154_MLME_SUBIE_DSSS_OPER_MODE,           "LECIM DSSS Operating Mode IE"},
997     { IEEE802154_MLME_SUBIE_FSK_OPER_MODE,            "LECIM FSK Operating Mode IE" },
998     { IEEE802154_MLME_SUBIE_TVWS_PHY_OPE_MODE,        "TVWS PHY Operating Mode Description IE" },
999     { IEEE802154_MLME_SUBIE_TVWS_DEVICE_CAPAB,        "TVWS Device Capabilities IE" },
1000     { IEEE802154_MLME_SUBIE_TVWS_DEVICE_CATEG,        "TVWS Device Category IE" },
1001     { IEEE802154_MLME_SUBIE_TVWS_DEVICE_IDENTIF,      "TVWS Device Identification IE" },
1002     { IEEE802154_MLME_SUBIE_TVWS_DEVICE_LOCATION,     "TVWS Device Location IE" },
1003     { IEEE802154_MLME_SUBIE_TVWS_CH_INFOR_QUERY,      "TVWS Channel Information Query IE" },
1004     { IEEE802154_MLME_SUBIE_TVWS_CH_INFOR_SOURCE,     "TVWS Channel Information Source IE" },
1005     { IEEE802154_MLME_SUBIE_CTM,                      "CTM IE" },
1006     { IEEE802154_MLME_SUBIE_TIMESTAMP,                "Timestamp IE" },
1007     { IEEE802154_MLME_SUBIE_TIMESTAMP_DIFF,           "Timestamp Difference IE"},
1008     { IEEE802154_MLME_SUBIE_TMCP_SPECIFICATION,       "TMCTP Specification IE" },
1009     { IEEE802154_MLME_SUBIE_RCC_PHY_OPER_MODE,        "RCC PHY Operating Mode IE" },
1010     { IEEE802154_IETF_SUBIE_6TOP,                     "6top IE" },
1011     { 0, NULL }
1012 };
1013 
1014 static const value_string zboss_page_names[] = {
1015     { 0, "2.4 GHz" },
1016     { 28, "863-868 MHz band"},
1017     { 29, "868-870, 870-876 MHz band" },
1018     { 30, "870-876 MHz band" },
1019     { 31, "915-921 MHz band" },
1020     { 0, NULL }
1021 };
1022 
1023 static const value_string zboss_direction_names[] = {
1024     { 0, "IN" },
1025     { 1, "OUT" },
1026     { 0, NULL }
1027 };
1028 
1029 static const value_string tap_tlv_types[] = {
1030     { IEEE802154_TAP_FCS_TYPE,  "FCS type"},
1031     { IEEE802154_TAP_RSS, "RSS"},
1032     { IEEE802154_TAP_BIT_RATE, "Bit rate"},
1033     { IEEE802154_TAP_CHANNEL_ASSIGNMENT, "Channel assignment"},
1034     { IEEE802154_TAP_SUN_PHY_INFO, "SUN PHY Information"},
1035     { IEEE802154_TAP_START_OF_FRAME_TS, "Start of frame timestamp"},
1036     { IEEE802154_TAP_END_OF_FRAME_TS, "End of frame timestamp"},
1037     { IEEE802154_TAP_ASN, "Absolute Slot Number (ASN)"},
1038     { IEEE802154_TAP_SLOT_START_TS, "Start of slot timestamp"},
1039     { IEEE802154_TAP_TIMESLOT_LENGTH, "Slot length"},
1040     { IEEE802154_TAP_LQI, "Link Quality Indicator"},
1041     { IEEE802154_TAP_CHANNEL_FREQUENCY, "Channel center frequency"},
1042     { IEEE802154_TAP_CHANNEL_PLAN, "Channel plan"},
1043     { 0, NULL }
1044 };
1045 
1046 static const value_string tap_fcs_type_names[] = {
1047     { IEEE802154_FCS_TYPE_NONE, "None" },
1048     { IEEE802154_FCS_TYPE_16_BIT, "ITU-T CRC16" },
1049     { IEEE802154_FCS_TYPE_32_BIT, "ITU-T CRC32" },
1050     { 0, NULL }
1051 };
1052 
1053 /* IEEE 802.15.4 Table 7-19 */
1054 static const value_string sun_bands[] = {
1055     { 0, "169 MHz [169.400-169.475]" },
1056     { 1, "450 MHz [450-470]" },
1057     { 2, "470 MHz [470-510]" },
1058     { 3, "780 MHz [779-787]" },
1059     { 4, "863 MHz [863-870]" },
1060     { 5, "896 MHz [896-901]" },
1061     { 6, "901 MHz [901-902]" },
1062     { 7, "915 MHz [902-928]" },
1063     { 8, "917 MHz [917-923.5]" },
1064     { 9, "920 MHz [920-928]" },
1065     { 10, "928 MHz [928-960]" },
1066     { 11, "920 MHz [920-960]" },
1067     { 12, "1427 MHz [1427-1518]" },
1068     { 13, "2450 MHz [2400-2483.5]" },
1069     { 14, "866 MHz [865-867]" },
1070     { 15, "870 MHz [870-876]" },
1071     { 16, "915 MHz-a [902-928 alternate]" },
1072     { 17, "915 MHz-b [902-907.5 & 915-928]" },
1073     { 18, "915 MHz-c [915-928]" },
1074     { 19, "915 MHz-d [915-921]" },
1075     { 20, "915 MHz-e [915-918]" },
1076     { 21, "919 MHz [919-923]" },
1077     { 22, "920 MHz-a [920.5-924.5]" },
1078     { 23, "920 MHz-b [920-925]" },
1079     { 24, "867 MHz [866-869]" },
1080     /* Exegin defined numbers for bands in Table 10-1 but not in Table 7-19 */
1081     { 32, "433 MHz [433.05-434.79]" },
1082     { 33, "868 MHz [868-868.6]" },
1083     { 34, "2380 MHz [2360-2400]" },
1084     { 0, NULL }
1085 };
1086 
1087 /* IEEE 802.15.4 Table 7-20 */
1088 static const value_string sun_types[] = {
1089     { IEEE802154_SUN_TYPE_FSK_A, "FSK-A" },
1090     { IEEE802154_SUN_TYPE_FSK_B, "FSK-B" },
1091     { IEEE802154_SUN_TYPE_OQPSK_A, "O-QPSK-A" },
1092     { IEEE802154_SUN_TYPE_OQPSK_B, "O-QPSK-B" },
1093     { IEEE802154_SUN_TYPE_OQPSK_C, "O-QPSK-C" },
1094     { IEEE802154_SUN_TYPE_OFDM_OPT1, "OFDM Option 1" },
1095     { IEEE802154_SUN_TYPE_OFDM_OPT2, "OFDM Option 2" },
1096     { IEEE802154_SUN_TYPE_OFDM_OPT3, "OFDM Option 3" },
1097     { IEEE802154_SUN_TYPE_OFDM_OPT4, "OFDM Option 4" },
1098     { 0, NULL }
1099 };
1100 
1101 static const value_string fsk_a_modes[] = {
1102     { 0, "4.8 kb/s; 2-FSK; mod index = 1.0; channel spacing = 12.5 kHz" },
1103     { 1, "9.6 kb/s; 4-FSK; mod index = 0.33; channel spacing = 12.5 kHz" },
1104     { 2, "10 kb/s; 2-FSK; mod index = 0.5; channel spacing = 12.5 kHz" },
1105     { 3, "20 kb/s; 2-FSK; mod index = 0.5; channel spacing = 12.5 kHz" },
1106     { 4, "40 kb/s; 2-FSK; mod index = 0.5; channel spacing = 12.5 kHz" },
1107     { 5, "4.8 kb/s; 2-FSK; mod index = 0.5; channel spacing = 12.5 kHz" },
1108     { 6, "2.4 kb/s; 2-FSK; mod index = 2.0; channel spacing = 12.5 kHz" },
1109     { 7, "9.6 kb/s; 4-FSK; mod index = 0.33; channel spacing = 12.5 kHz" },
1110     { 0, NULL }
1111 };
1112 
1113 static const value_string fsk_b_modes[] = {
1114     { 0, "50 kb/s; 2-FSK; mod index = 1.0; channel spacing = 200 kHz" },
1115     { 1, "100 kb/s; 2-FSK; mod index = 1.0; channel spacing = 400 kHz" },
1116     { 2, "150 kb/s; 2-FSK; mod index = 0.5; channel spacing = 400 kHz" },
1117     { 3, "200 kb/s; 2-FSK; mod index = 0.5; channel spacing = 400 kHz" },
1118     { 4, "200 kb/s; 4-FSK; mod index = 0.33; channel spacing = 400 kHz" },
1119     { 5, "200 kb/s; 2-FSK; mod index = 1.0; channel spacing = 600 kHz" },
1120     { 6, "400 kb/s; 4-FSK; mod index = 0.33; channel spacing = 600 kHz" },
1121     { 7, "100 kb/s; 2-FSK; mod index = 0.5; channel spacing = 200 kHz"},
1122     { 8, "50 kb/s; 2-FSK; mod index = 0.5; channel spacing = 100 kHz"},
1123     { 9, "150 kb/s; 2-FSK; mod index = 0.5; channel spacing = 200 kHz"},
1124     { 10, "300 kb/s; 2-FSK; mod index = 0.5; channel spacing = 400 kHz" },
1125     { 0, NULL }
1126 };
1127 
1128 static const value_string oqpsk_a_modes[] = {
1129     { 0, "chip rate = 100 kchip/s; SpreadingMode = DSSS; RateMode = 0; data rate = 6.25 kb/s"},
1130     { 1, "chip rate = 100 kchip/s; SpreadingMode = DSSS; RateMode = 1; data rate = 12.5 kb/s"},
1131     { 2, "chip rate = 100 kchip/s; SpreadingMode = DSSS; RateMode = 2; data rate = 25 kb/s"},
1132     { 3, "chip rate = 100 kchip/s; SpreadingMode = DSSS; RateMode = 3; data rate = 50 kb/s"},
1133     { 0, NULL }
1134 };
1135 
1136 static const value_string oqpsk_b_modes[] = {
1137     { 0, "chip rate = 1000 kchip/s; SpreadingMode = DSSS; RateMode = 0; data rate = 31.25 kb/s"},
1138     { 1, "chip rate = 1000 kchip/s; SpreadingMode = DSSS; RateMode = 1; data rate = 125 kb/s"},
1139     { 2, "chip rate = 1000 kchip/s; SpreadingMode = DSSS; RateMode = 2; data rate = 250 kb/s"},
1140     { 3, "chip rate = 1000 kchip/s; SpreadingMode = DSSS; RateMode = 3; data rate = 500 kb/s"},
1141     { 4, "chip rate = 1000 kchip/s; SpreadingMode = MDSSS; RateMode = 0; data rate = 62.5 kb/s"},
1142     { 5, "chip rate = 1000 kchip/s; SpreadingMode = MDSSS; RateMode = 1; data rate = 125 kb/s"},
1143     { 6, "chip rate = 1000 kchip/s; SpreadingMode = MDSSS; RateMode = 2; data rate = 250 kb/s"},
1144     { 7, "chip rate = 1000 kchip/s; SpreadingMode = MDSSS; RateMode = 3; data rate = 500 kb/s"},
1145     { 0, NULL }
1146 };
1147 
1148 static const value_string oqpsk_c_modes[] = {
1149     { 0, "chip rate = 2000 kchip/s; SpreadingMode = DSSS; RateMode = 0; data rate = 31.25 kb/s"},
1150     { 1, "chip rate = 2000 kchip/s; SpreadingMode = DSSS; RateMode = 1; data rate = 125 kb/s"},
1151     { 2, "chip rate = 2000 kchip/s; SpreadingMode = DSSS; RateMode = 2; data rate = 250 kb/s"},
1152     { 3, "chip rate = 2000 kchip/s; SpreadingMode = DSSS; RateMode = 3; data rate = 500 kb/s"},
1153     { 4, "chip rate = 2000 kchip/s; SpreadingMode = MDSSS; RateMode = 0; data rate = 62.5 kb/s"},
1154     { 5, "chip rate = 2000 kchip/s; SpreadingMode = MDSSS; RateMode = 1; data rate = 125 kb/s"},
1155     { 6, "chip rate = 2000 kchip/s; SpreadingMode = MDSSS; RateMode = 2; data rate = 250 kb/s"},
1156     { 7, "chip rate = 2000 kchip/s; SpreadingMode = MDSSS; RateMode = 3; data rate = 500 kb/s"},
1157     { 0, NULL }
1158 };
1159 
1160 static const value_string ofdm_modes[] = {
1161     { 0, "MCS0" },
1162     { 1, "MCS1" },
1163     { 2, "MCS2" },
1164     { 3, "MCS3" },
1165     { 4, "MCS4" },
1166     { 5, "MCS5" },
1167     { 6, "MCS6" },
1168     { 0, NULL },
1169 };
1170 
1171 static const value_string channel_page_names[] = {
1172     { 0, "Default" },
1173     { 1, "ASK" },
1174     { 2, "O-QPSK" },
1175     { 3, "CSS" },
1176     { 4, "HRP UWB" },
1177     { 5, "780 MHz" },
1178     { 6, "GFSK" },
1179     { 7, "MSK" },
1180     { 8, "LRP_UWB" },
1181     { 9, "SUN" },
1182     { 10, "SUN FSK" },
1183     { 11, "2380 MHz" },
1184     { 12, "LECIM" },
1185     { 13, "RCC" },
1186     { 0, NULL }
1187 };
1188 
1189 static const value_string ietf_6top_types[] = {
1190     { IETF_6TOP_TYPE_REQUEST, "Request" },
1191     { IETF_6TOP_TYPE_RESPONSE, "Response" },
1192     { IETF_6TOP_TYPE_CONFIRMATION, "Confirmation" },
1193     { 0, NULL }
1194 };
1195 
1196 static const value_string ietf_6top_command_identifiers[] = {
1197     { IETF_6TOP_CMD_ADD, "ADD" },
1198     { IETF_6TOP_CMD_DELETE, "DELETE" },
1199     { IETF_6TOP_CMD_RELOCATE, "RELOCATE" },
1200     { IETF_6TOP_CMD_COUNT, "COUNT" },
1201     { IETF_6TOP_CMD_LIST, "LIST" },
1202     { IETF_6TOP_CMD_SIGNAL, "SIGNAL" },
1203     { IETF_6TOP_CMD_CLEAR, "CLEAR" },
1204     { 0, NULL }
1205 };
1206 
1207 static const value_string ietf_6top_return_codes[] = {
1208     { IETF_6TOP_RC_SUCCESS, "SUCCESS" },
1209     { IETF_6TOP_RC_EOL, "RC_EOL" },
1210     { IETF_6TOP_RC_ERR, "RC_ERR" },
1211     { IETF_6TOP_RC_RESET, "RC_RESET" },
1212     { IETF_6TOP_RC_ERR_VERSION, "RC_ERR_VERSION" },
1213     { IETF_6TOP_RC_ERR_SFID, "RC_ERR_SFID" },
1214     { IETF_6TOP_RC_ERR_SEQNUM, "RC_ERR_SEQNUM" },
1215     { IETF_6TOP_RC_ERR_CELLLIST, "RC_ERR_CELLLIST" },
1216     { IETF_6TOP_RC_ERR_BUSY, "RC_ERR_BUSY" },
1217     { IETF_6TOP_RC_ERR_LOCKED, "RC_ERR_LOCKED" },
1218     { 0, NULL }
1219 };
1220 
1221 static const value_string ietf_6top_cell_options[] = {
1222     { 0, "ALL" },
1223     { 1, "TX" },
1224     { 2, "RX" },
1225     { 3, "TX|RX" },
1226     { 4, "SHARED" },
1227     { 5, "TX|SHARED" },
1228     { 6, "RX|SHARED" },
1229     { 7, "TX|RX|SHARED" },
1230     { 0, NULL}
1231 };
1232 
1233 static const value_string mpx_transfer_type_vals[] = {
1234     { IEEE802159_MPX_FULL_FRAME, "Full Frame" },
1235     { IEEE802159_MPX_FULL_FRAME_NO_MUXID, "Full frame with compressed Multiplex ID" },
1236     { IEEE802159_MPX_NON_LAST_FRAGMENT, "Non-last Fragment" },
1237     { IEEE802159_MPX_LAST_FRAGMENT, "Last Fragment" },
1238     { IEEE802159_MPX_ABORT, "Abort" },
1239     { 0, NULL }
1240 };
1241 
1242 static const value_string mpx_multiplex_id_vals[] = {
1243     { IEEE802159_MPX_MULTIPLEX_ID_KMP, "KMP" },
1244     { IEEE802159_MPX_MULTIPLEX_ID_WISUN, "Wi-SUN" },
1245     { 0, NULL }
1246 };
1247 
1248 // used by the Wi-SUN dissector
1249 const value_string ieee802154_mpx_kmp_id_vals[] = {
1250     { IEEE802159_MPX_KMP_ID_IEEE8021X, "IEEE 802.1X/MKA" },
1251     { IEEE802159_MPX_KMP_ID_HIP, "HIP" },
1252     { IEEE802159_MPX_KMP_ID_IKEV2, "IKEv2" },
1253     { IEEE802159_MPX_KMP_ID_PANA, "PANA" },
1254     { IEEE802159_MPX_KMP_ID_DRAGONFLY, "Dragonfly" },
1255     { IEEE802159_MPX_KMP_ID_IEEE80211_4WH, "IEEE 802.11/4WH" },
1256     { IEEE802159_MPX_KMP_ID_IEEE80211_GKH, "IEEE 802.11/GKH" },
1257     { IEEE802159_MPX_KMP_ID_ETSI_TS_102_887_2, "ETSI TS 102 887-2" },
1258     { IEEE802159_MPX_KMP_ID_VENDOR_SPECIFIC, "Vendor-specific" },
1259     { 0, NULL }
1260 };
1261 
1262 static const value_string mpx_wisun_subid_vals[] = {
1263     { IEEE802159_MPX_WISUN_SUBID_MHDS, "WM-MHDS" },
1264     { IEEE802159_MPX_WISUN_SUBID_6LOWPAN, "WM-6LO" },
1265     { IEEE802159_MPX_WISUN_SUBID_SECURITY, "WM-SEC" },
1266     { 0, NULL }
1267 };
1268 
1269 /* Preferences for 2003 security */
1270 static gint ieee802154_sec_suite = SECURITY_LEVEL_ENC_MIC_64;
1271 static gboolean ieee802154_extend_auth = TRUE;
1272 
1273 /* Macro to check addressing, and throw a warning flag if incorrect. */
1274 #define IEEE802154_CMD_ADDR_CHECK(_pinfo_, _item_, _cmdid_, _x_)     \
1275    if (!(_x_))                                                       \
1276      expert_add_info_format(_pinfo_, _item_, &ei_ieee802154_invalid_addressing, \
1277                             "Invalid Addressing for %s",             \
1278                             val_to_str_const(_cmdid_, ieee802154_cmd_names, "Unknown Command"))
1279 
1280 /* CRC definitions. IEEE 802.15.4 CRCs vary from ITU-T by using an initial value of
1281  * 0x0000, and no XOR out. IEEE802154_CRC_XOR is defined as 0xFFFF in order to un-XOR
1282  * the output from the ITU-T (CCITT) CRC routines in Wireshark.
1283  */
1284 #define IEEE802154_CRC_SEED     0x0000
1285 #define IEEE802154_CRC_XOROUT   0xFFFF
1286 #define ieee802154_crc_tvb(tvb, offset)   (crc16_ccitt_tvb_seed(tvb, offset, IEEE802154_CRC_SEED) ^ IEEE802154_CRC_XOROUT)
1287 
1288 /* For the 32-bit CRC, IEEE 802.15.4 uses ITU-T (CCITT) CRC-32. */
1289 #define ieee802154_crc32_tvb(tvb, offset) (crc32_ccitt_tvb(tvb, offset))
1290 
ieee802_15_4_short_address_to_str(const address * addr,gchar * buf,int buf_len)1291 static int ieee802_15_4_short_address_to_str(const address* addr, gchar *buf, int buf_len)
1292 {
1293     guint16 ieee_802_15_4_short_addr = pletoh16(addr->data);
1294 
1295     if (ieee_802_15_4_short_addr == 0xffff)
1296     {
1297         (void) g_strlcpy(buf, "Broadcast", buf_len);
1298         return 10;
1299     }
1300 
1301     *buf++ = '0';
1302     *buf++ = 'x';
1303     buf = word_to_hex(buf, ieee_802_15_4_short_addr);
1304     *buf = '\0'; /* NULL terminate */
1305 
1306     return 7;
1307 }
1308 
ieee802_15_4_short_address_str_len(const address * addr _U_)1309 static int ieee802_15_4_short_address_str_len(const address* addr _U_)
1310 {
1311     return 11;
1312 }
1313 
ieee802_15_4_short_address_len(void)1314 static int ieee802_15_4_short_address_len(void)
1315 {
1316     return 2;
1317 }
1318 
1319 /* ======================================================================= */
_find_or_create_conversation(packet_info * pinfo,const address * src_addr,const address * dst_addr)1320 static conversation_t *_find_or_create_conversation(packet_info *pinfo, const address *src_addr, const address *dst_addr)
1321 {
1322     conversation_t *conv = NULL;
1323 
1324     /* Have we seen this conversation before? */
1325     conv = find_conversation(pinfo->num, src_addr, dst_addr, ENDPOINT_NONE, 0, 0, 0);
1326     if (conv == NULL) {
1327         /* No, this is a new conversation. */
1328         conv = conversation_new(pinfo->num, src_addr, dst_addr, ENDPOINT_NONE, 0, 0, 0);
1329     }
1330     return conv;
1331 }
1332 
1333 /* ======================================================================= */
transaction_start(packet_info * pinfo,proto_tree * tree,const ieee802154_packet * packet,guint32 * key)1334 static ieee802154_transaction_t *transaction_start(packet_info *pinfo, proto_tree *tree, const ieee802154_packet *packet, guint32 *key)
1335 {
1336     ieee802154_transaction_t    *ieee802154_trans;
1337     wmem_tree_key_t             ieee802154_key[3];
1338     proto_item                  *it;
1339 
1340     if (!PINFO_FD_VISITED(pinfo)) {
1341         /*
1342          * This is a new request, create a new transaction structure and map it
1343          * to the unmatched table.
1344          */
1345         ieee802154_key[0].length = 2;
1346         ieee802154_key[0].key = key;
1347         ieee802154_key[1].length = 0;
1348         ieee802154_key[1].key = NULL;
1349 
1350         ieee802154_trans = wmem_new0(wmem_file_scope(), ieee802154_transaction_t);
1351 
1352         if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT)
1353             ieee802154_trans->dst16 = packet->dst16;
1354         else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)
1355             ieee802154_trans->dst64 = packet->dst64;
1356         ieee802154_trans->dst_addr_mode = packet->dst_addr_mode;
1357 
1358         if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT)
1359             ieee802154_trans->src16 = packet->src16;
1360         else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT)
1361             ieee802154_trans->src64 = packet->src64;
1362         ieee802154_trans->src_addr_mode = packet->src_addr_mode;
1363 
1364         if (packet->dst_pan_present) {
1365             ieee802154_trans->dst_pan_present = TRUE;
1366             ieee802154_trans->dst_pan = packet->dst_pan;
1367         }
1368         if (packet->src_pan_present) {
1369             ieee802154_trans->src_pan_present = TRUE;
1370             ieee802154_trans->src_pan = packet->src_pan;
1371         }
1372         ieee802154_trans->rqst_frame = pinfo->num;
1373         ieee802154_trans->ack_frame = 0;
1374         ieee802154_trans->rqst_time = pinfo->abs_ts;
1375         nstime_set_unset(&ieee802154_trans->ack_time);
1376         wmem_tree_insert32_array(transaction_unmatched_pdus, ieee802154_key, (void *)ieee802154_trans);
1377     } else {
1378         /* Already visited this frame */
1379         guint32 frame_num = pinfo->num;
1380 
1381         ieee802154_key[0].length = 2;
1382         ieee802154_key[0].key = key;
1383         ieee802154_key[1].length = 1;
1384         ieee802154_key[1].key = &frame_num;
1385         ieee802154_key[2].length = 0;
1386         ieee802154_key[2].key = NULL;
1387 
1388         ieee802154_trans = (ieee802154_transaction_t *)wmem_tree_lookup32_array(transaction_matched_pdus, ieee802154_key);
1389 
1390         if (!ieee802154_trans) {
1391             /* No ACK found - add field and expert info */
1392             it = proto_tree_add_item(tree, hf_ieee802154_no_ack, NULL, 0, 0, ENC_NA);
1393             proto_item_set_generated(it);
1394 
1395             expert_add_info_format(pinfo, it, &ei_ieee802154_ack_not_found, "No ack found to request in frame %u", pinfo->num);
1396 
1397             return NULL;
1398         }
1399     }
1400 
1401     /* Print state tracking in the tree */
1402     if (ieee802154_trans->ack_frame) {
1403         it = proto_tree_add_uint(tree, hf_ieee802154_ack_in, NULL, 0, 0, ieee802154_trans->ack_frame);
1404         proto_item_set_generated(it);
1405     }
1406 
1407     return ieee802154_trans;
1408 } /* transaction_start() */
1409 
transaction_end(packet_info * pinfo,proto_tree * tree,const ieee802154_packet * packet,guint32 * key)1410 static ieee802154_transaction_t *transaction_end(packet_info *pinfo, proto_tree *tree, const ieee802154_packet *packet, guint32 *key)
1411 {
1412     ieee802154_transaction_t    *ieee802154_trans = NULL;
1413     wmem_tree_key_t             ieee802154_key[3];
1414     proto_item                  *it;
1415 
1416     if (!PINFO_FD_VISITED(pinfo)) {
1417         guint32 frame_num;
1418         nstime_t ns;
1419 
1420         ieee802154_key[0].length = 2;
1421         ieee802154_key[0].key = key;
1422         ieee802154_key[1].length = 0;
1423         ieee802154_key[1].key = NULL;
1424 
1425         ieee802154_trans = (ieee802154_transaction_t *)wmem_tree_lookup32_array(transaction_unmatched_pdus, ieee802154_key);
1426         if (ieee802154_trans == NULL)
1427             return NULL;
1428 
1429         /* we have already seen this response, or an identical one */
1430         if (ieee802154_trans->ack_frame != 0)
1431             return NULL;
1432 
1433         /* If addresses are present they must match */
1434         if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1435             if (packet->src16 != ieee802154_trans->dst16)
1436                 return NULL;
1437         }
1438         else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1439             if (packet->src64 != ieee802154_trans->dst64)
1440                 return NULL;
1441         }
1442         if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1443             if (packet->dst16 != ieee802154_trans->src16)
1444                 return NULL;
1445         }
1446         else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1447             if (packet->dst64 != ieee802154_trans->src64)
1448                 return NULL;
1449         }
1450 
1451         nstime_delta(&ns, &pinfo->abs_ts, &ieee802154_trans->rqst_time);
1452         if (nstime_cmp(&ns, &ieee802154_transaction_timeout) > 0)
1453             return NULL;
1454 
1455         ieee802154_trans->ack_time = ns;
1456         ieee802154_trans->ack_frame = pinfo->num;
1457 
1458         /*
1459          * We found a match.  Add entries to the matched table for both
1460          * request and ack frames
1461          */
1462         ieee802154_key[0].length = 2;
1463         ieee802154_key[0].key = key;
1464         ieee802154_key[1].length = 1;
1465         ieee802154_key[1].key = &frame_num;
1466         ieee802154_key[2].length = 0;
1467         ieee802154_key[2].key = NULL;
1468 
1469         frame_num = ieee802154_trans->rqst_frame;
1470         wmem_tree_insert32_array(transaction_matched_pdus, ieee802154_key, (void *)ieee802154_trans);
1471 
1472         frame_num = ieee802154_trans->ack_frame;
1473         wmem_tree_insert32_array(transaction_matched_pdus, ieee802154_key, (void *)ieee802154_trans);
1474     } else {
1475         /* Already visited this frame */
1476         guint32 frame_num = pinfo->num;
1477 
1478         ieee802154_key[0].length = 2;
1479         ieee802154_key[0].key = key;
1480         ieee802154_key[1].length = 1;
1481         ieee802154_key[1].key = &frame_num;
1482         ieee802154_key[2].length = 0;
1483         ieee802154_key[2].key = NULL;
1484 
1485         ieee802154_trans = (ieee802154_transaction_t *)wmem_tree_lookup32_array(transaction_matched_pdus, ieee802154_key);
1486 
1487         if (!ieee802154_trans) {
1488             /* No ack request found - add field and expert info */
1489             it = proto_tree_add_item(tree, hf_ieee802154_no_ack_request, NULL, 0, 0, ENC_NA);
1490             proto_item_set_generated(it);
1491 
1492             expert_add_info_format(pinfo, it, &ei_ieee802154_ack_request_not_found, "No request found to ack in frame %u", pinfo->num);
1493             return NULL;
1494         }
1495     }
1496 
1497     if (packet->dst_pan_present == FALSE) {
1498         if (ieee802154_trans->src_pan_present) {
1499             it = proto_tree_add_uint(tree, hf_ieee802154_dst_panID, NULL, 0, 0, ieee802154_trans->src_pan);
1500             proto_item_set_generated(it);
1501         }
1502         else if (ieee802154_trans->dst_pan_present) {
1503             it = proto_tree_add_uint(tree, hf_ieee802154_dst_panID, NULL, 0, 0, ieee802154_trans->dst_pan);
1504             proto_item_set_generated(it);
1505         }
1506     }
1507     if ((packet->src_pan_present == FALSE) && (ieee802154_trans->src_pan_present) && (ieee802154_trans->dst_pan_present)) {
1508         it = proto_tree_add_uint(tree, hf_ieee802154_src_panID, NULL, 0, 0, ieee802154_trans->dst_pan);
1509         proto_item_set_generated(it);
1510     }
1511 
1512     if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) {
1513         if (ieee802154_trans->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1514             it = proto_tree_add_uint(tree, hf_ieee802154_dst16, NULL, 0, 0, ieee802154_trans->src16);
1515             proto_item_set_generated(it);
1516 
1517             it = proto_tree_add_uint(tree, hf_ieee802154_addr16, NULL, 0, 0, ieee802154_trans->src16);
1518             proto_item_set_hidden(it);
1519             proto_item_set_generated(it);
1520         }
1521         else if (ieee802154_trans->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1522             it = proto_tree_add_eui64(tree, hf_ieee802154_dst64, NULL, 0, 0, ieee802154_trans->src64);
1523             proto_item_set_generated(it);
1524 
1525             it = proto_tree_add_eui64(tree, hf_ieee802154_addr64, NULL, 0, 0, ieee802154_trans->src64);
1526             proto_item_set_hidden(it);
1527             proto_item_set_generated(it);
1528         }
1529     }
1530 
1531     if (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) {
1532         if (ieee802154_trans->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1533             it = proto_tree_add_uint(tree, hf_ieee802154_src16, NULL, 0, 0, ieee802154_trans->dst16);
1534             proto_item_set_generated(it);
1535 
1536             it = proto_tree_add_uint(tree, hf_ieee802154_addr16, NULL, 0, 0, ieee802154_trans->dst16);
1537             proto_item_set_hidden(it);
1538             proto_item_set_generated(it);
1539         }
1540         else if (ieee802154_trans->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1541             it = proto_tree_add_eui64(tree, hf_ieee802154_src64, NULL, 0, 0, ieee802154_trans->dst64);
1542             proto_item_set_generated(it);
1543 
1544             it = proto_tree_add_eui64(tree, hf_ieee802154_addr64, NULL, 0, 0, ieee802154_trans->dst64);
1545             proto_item_set_hidden(it);
1546             proto_item_set_generated(it);
1547         }
1548     }
1549 
1550     /* Print state tracking in the tree */
1551     it = proto_tree_add_uint(tree, hf_ieee802154_ack_to, NULL, 0, 0, ieee802154_trans->rqst_frame);
1552     proto_item_set_generated(it);
1553 
1554     it = proto_tree_add_time(tree, hf_ieee802154_ack_time, NULL, 0, 0, &ieee802154_trans->ack_time);
1555     proto_item_set_generated(it);
1556 
1557     return ieee802154_trans;
1558 
1559 } /* transaction_end() */
1560 
1561 /**
1562  * Dissector helper, parses and displays the frame control field.
1563  *
1564  * @param tvb pointer to buffer containing raw packet.
1565  * @param pinfo pointer to packet information fields
1566  * @param tree pointer to data tree wireshark uses to display packet.
1567  * @param packet IEEE 802.15.4 packet information.
1568  * @param offset offset into the tvb to find the FCF.
1569  *
1570  */
1571 static void
dissect_ieee802154_fcf(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet,guint * offset)1572 dissect_ieee802154_fcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet, guint *offset)
1573 {
1574     guint16     fcf;
1575     static int * const ieee802154_fields[] = {
1576         &hf_ieee802154_frame_type,
1577         &hf_ieee802154_security,
1578         &hf_ieee802154_pending,
1579         &hf_ieee802154_ack_request,
1580         &hf_ieee802154_pan_id_compression,
1581         &hf_ieee802154_fcf_reserved,
1582         &hf_ieee802154_seqno_suppression,
1583         &hf_ieee802154_ie_present,
1584         &hf_ieee802154_dst_addr_mode,
1585         &hf_ieee802154_version,
1586         &hf_ieee802154_src_addr_mode,
1587         NULL
1588     };
1589 
1590     static int* const ieee802154_mpf_short_fields[] = {
1591         &hf_ieee802154_frame_type,
1592         &hf_ieee802154_mpf_long_frame_control,
1593         &hf_ieee802154_mpf_dst_addr_mode,
1594         &hf_ieee802154_mpf_src_addr_mode,
1595         NULL
1596     };
1597 
1598     static int* const ieee802154_mpf_long_fields[] = {
1599         &hf_ieee802154_frame_type,
1600         &hf_ieee802154_mpf_long_frame_control,
1601         &hf_ieee802154_mpf_dst_addr_mode,
1602         &hf_ieee802154_mpf_src_addr_mode,
1603         &hf_ieee802154_mpf_pan_id_present,
1604         &hf_ieee802154_mpf_security,
1605         &hf_ieee802154_mpf_seqno_suppression,
1606         &hf_ieee802154_mpf_pending,
1607         &hf_ieee802154_mpf_version,
1608         &hf_ieee802154_mpf_ack_request,
1609         &hf_ieee802154_mpf_ie_present,
1610         NULL
1611     };
1612 
1613     /* Get the FCF field. */
1614     fcf = tvb_get_letohs(tvb, *offset);
1615 
1616      /* Parse FCF Flags. */
1617     packet->frame_type          = (fcf & IEEE802154_FCF_TYPE_MASK);
1618 
1619     if (packet->frame_type == IEEE802154_FCF_MULTIPURPOSE) {
1620         /* Multipurpose frames use a different 1 or 2 byte FCF */
1621         packet->long_frame_control  = (fcf & IEEE802154_MPF_FCF_LONG_FC) >> 3;
1622         packet->dst_addr_mode       = (fcf & IEEE802154_MPF_FCF_DADDR_MASK) >> 4;
1623         packet->src_addr_mode       = (fcf & IEEE802154_MPF_FCF_SADDR_MASK) >> 6;
1624 
1625         /* The second octet of the FCF is only present if the long frame control bit is set */
1626         if (packet->long_frame_control) {
1627             packet->pan_id_present = (fcf & IEEE802154_MPF_FCF_PAN_ID_PRESENT) >> 8;
1628             packet->security_enable = (fcf & IEEE802154_MPF_FCF_SEC_EN) >> 9;
1629             packet->seqno_suppression = (fcf & IEEE802154_MPF_FCF_SEQNO_SUPPRESSION) >> 10;
1630             packet->frame_pending   = (fcf & IEEE802154_MPF_FCF_FRAME_PND) >> 11;
1631             packet->version         = (fcf & IEEE802154_MPF_FCF_VERSION) >> 12;
1632             packet->ack_request     = (fcf & IEEE802154_MPF_FCF_ACK_REQ) >> 14;
1633             packet->ie_present      = (fcf & IEEE802154_MPF_FCF_IE_PRESENT) >> 15;
1634         }
1635         else {
1636             packet->security_enable = FALSE;
1637             packet->seqno_suppression = FALSE;
1638             packet->frame_pending   = FALSE;
1639             packet->version         = 0;
1640             packet->ack_request     = FALSE;
1641             packet->ie_present      = FALSE;
1642         }
1643 
1644         if (ieee802154e_compatibility) {
1645             if (((tvb_reported_length(tvb) == IEEE802154E_LE_WUF_LEN)) && !packet->long_frame_control) {
1646                 /* Check if this is an IEEE 802.15.4e LE-multipurpose Wake-up Frame, which has a single-octet FCF
1647                  * and a static layout that cannot be inferred from the FCF alone. */
1648                 guint16 ie_header = tvb_get_letohs(tvb, (*offset) + 6);
1649                 guint16 id = (guint16)((ie_header & IEEE802154_HEADER_IE_ID_MASK) >> 7);
1650                 guint16 length = (guint16)(ie_header & IEEE802154_HEADER_IE_LENGTH_MASK);
1651                 if ((id == IEEE802154_HEADER_IE_RENDEZVOUS) && (length == 2)) {
1652                     /* This appears to be a WUF, as identified by containing a single
1653                      * Rendezvous Time Header IE with only a rendezvous time. */
1654                     packet->ie_present = TRUE;
1655                     packet->pan_id_present = TRUE;
1656                 }
1657             }
1658         }
1659     }
1660     else {
1661         /* Standard 802.15.4 FCF */
1662         packet->security_enable     = (fcf & IEEE802154_FCF_SEC_EN) >> 3;
1663         packet->frame_pending       = (fcf & IEEE802154_FCF_FRAME_PND) >> 4;
1664         packet->ack_request         = (fcf & IEEE802154_FCF_ACK_REQ) >> 5;
1665         packet->pan_id_compression  = (fcf & IEEE802154_FCF_PAN_ID_COMPRESSION) >> 6;
1666         /* bit 7 reserved */
1667         packet->seqno_suppression   = (fcf & IEEE802154_FCF_SEQNO_SUPPRESSION) >> 8;
1668         packet->ie_present          = (fcf & IEEE802154_FCF_IE_PRESENT) >> 9;
1669         packet->dst_addr_mode       = (fcf & IEEE802154_FCF_DADDR_MASK) >> 10;
1670         packet->version             = (fcf & IEEE802154_FCF_VERSION) >> 12;
1671         packet->src_addr_mode       = (fcf & IEEE802154_FCF_SADDR_MASK) >> 14;
1672     }
1673 
1674     if ((packet->version == IEEE802154_VERSION_2015) && (packet->frame_type == IEEE802154_FCF_BEACON)) {
1675         proto_item_append_text(tree, " Enhanced Beacon");
1676         col_set_str(pinfo->cinfo, COL_INFO, "Enhanced Beacon");
1677     }
1678     else {
1679         proto_item_append_text(tree, " %s", val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
1680         col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
1681     }
1682 
1683     if (packet->frame_type == IEEE802154_FCF_MULTIPURPOSE) {
1684         if (packet->long_frame_control) {
1685             proto_tree_add_bitmask(tree, tvb, *offset, hf_ieee802154_fcf,
1686                                    ett_ieee802154_fcf, ieee802154_mpf_long_fields, ENC_LITTLE_ENDIAN);
1687             *offset += 2;
1688         }
1689         else {
1690             proto_tree_add_bitmask_len(tree, tvb, *offset, 1, hf_ieee802154_fcf,
1691                                        ett_ieee802154_fcf, ieee802154_mpf_short_fields,
1692                                        &ei_ieee802154_fcs_bitmask_len, ENC_LITTLE_ENDIAN);
1693             *offset += 1;
1694         }
1695     }
1696     else {
1697         proto_tree_add_bitmask(tree, tvb, *offset, hf_ieee802154_fcf,
1698                                ett_ieee802154_fcf, ieee802154_fields, ENC_LITTLE_ENDIAN);
1699         *offset += 2;
1700     }
1701 
1702 } /* dissect_ieee802154_fcf */
1703 
register_ieee802154_mac_key_hash_handler(guint hash_identifier,ieee802154_set_key_func key_func)1704 void register_ieee802154_mac_key_hash_handler(guint hash_identifier, ieee802154_set_key_func key_func)
1705 {
1706     /* Ensure no duplication */
1707     DISSECTOR_ASSERT(wmem_tree_lookup32(mac_key_hash_handlers, hash_identifier) == NULL);
1708 
1709     wmem_tree_insert32(mac_key_hash_handlers, hash_identifier, (void*)key_func);
1710 }
1711 
dissect_ieee802154_aux_sec_header_and_key(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,ieee802154_packet * packet,guint * offset)1712 void dissect_ieee802154_aux_sec_header_and_key(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, ieee802154_packet *packet, guint *offset)
1713 {
1714     proto_tree *field_tree, *header_tree;
1715     proto_item *ti, *hidden_item;
1716     guint8     security_control;
1717     guint      aux_length = 1; /* Minimum length of the auxiliary header. */
1718     static int * const security_fields[] = {
1719             &hf_ieee802154_aux_sec_security_level,
1720             &hf_ieee802154_aux_sec_key_id_mode,
1721             &hf_ieee802154_aux_sec_frame_counter_suppression,
1722             &hf_ieee802154_aux_sec_asn_in_nonce,
1723             &hf_ieee802154_aux_sec_reserved,
1724             NULL
1725     };
1726 
1727     /* Parse the security control field. */
1728     security_control = tvb_get_guint8(tvb, *offset);
1729     packet->security_level = (ieee802154_security_level)(security_control & IEEE802154_AUX_SEC_LEVEL_MASK);
1730     packet->key_id_mode = (ieee802154_key_id_mode)((security_control & IEEE802154_AUX_KEY_ID_MODE_MASK) >> IEEE802154_AUX_KEY_ID_MODE_SHIFT);
1731     if (packet->version == IEEE802154_VERSION_2015) {
1732         packet->frame_counter_suppression = security_control & IEEE802154_AUX_FRAME_COUNTER_SUPPRESSION_MASK ? TRUE : FALSE;
1733     }
1734 
1735     /* Compute the length of the auxiliary header and create a subtree.  */
1736     if (!packet->frame_counter_suppression) aux_length += 4;
1737     if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) aux_length++;
1738     if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) aux_length += 4;
1739     if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) aux_length += 8;
1740 
1741     ti = proto_tree_add_item(tree, hf_ieee802154_aux_security_header, tvb, *offset, aux_length, ENC_NA);
1742     header_tree = proto_item_add_subtree(ti, ett_ieee802154_auxiliary_security);
1743 
1744     /* Security Control Field */
1745     proto_tree_add_bitmask(header_tree, tvb, *offset, hf_ieee802154_aux_sec_security_control, ett_ieee802154_aux_sec_control, security_fields, ENC_NA);
1746     (*offset)++;
1747 
1748     /* Frame Counter Field */
1749     if (!packet->frame_counter_suppression) {
1750         proto_tree_add_item_ret_uint(header_tree, hf_ieee802154_aux_sec_frame_counter, tvb, *offset, 4, ENC_LITTLE_ENDIAN, &packet->frame_counter);
1751         (*offset) += 4;
1752     }
1753     else {
1754         packet->asn = ieee802154_tsch_asn;
1755     }
1756 
1757     /* Key identifier field(s). */
1758     if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) {
1759         /* Create a subtree. */
1760         field_tree = proto_tree_add_subtree(header_tree, tvb, *offset, 1,
1761                 ett_ieee802154_aux_sec_key_id, &ti, "Key Identifier Field"); /* Will fix length later. */
1762         /* Add key source, if it exists. */
1763         if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) {
1764             packet->key_source.addr32 = tvb_get_ntohl(tvb, *offset);
1765             proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, *offset, 4, packet->key_source.addr32);
1766             hidden_item = proto_tree_add_item(field_tree, hf_ieee802154_aux_sec_key_source_bytes, tvb, *offset, 4, ENC_NA);
1767             proto_item_set_hidden(hidden_item);
1768             proto_item_set_len(ti, 1 + 4);
1769             (*offset) += 4;
1770         }
1771         if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) {
1772             packet->key_source.addr64 = tvb_get_ntoh64(tvb, *offset);
1773             proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, *offset, 8, packet->key_source.addr64);
1774             hidden_item = proto_tree_add_item(field_tree, hf_ieee802154_aux_sec_key_source_bytes, tvb, *offset, 8, ENC_NA);
1775             proto_item_set_hidden(hidden_item);
1776             proto_item_set_len(ti, 1 + 8);
1777             (*offset) += 8;
1778         }
1779         /* Add key identifier. */
1780         packet->key_index = tvb_get_guint8(tvb, *offset);
1781         proto_tree_add_uint(field_tree, hf_ieee802154_aux_sec_key_index, tvb, *offset, 1, packet->key_index);
1782         (*offset)++;
1783     }
1784 }
1785 
decrypt_ieee802154_payload(tvbuff_t * tvb,guint offset,packet_info * pinfo,proto_tree * key_tree,ieee802154_packet * packet,ieee802154_decrypt_info_t * decrypt_info,ieee802154_set_key_func set_key_func,ieee802154_decrypt_func decrypt_func)1786 tvbuff_t *decrypt_ieee802154_payload(tvbuff_t * tvb, guint offset, packet_info * pinfo, proto_tree* key_tree,
1787                                      ieee802154_packet * packet, ieee802154_decrypt_info_t* decrypt_info,
1788                                      ieee802154_set_key_func set_key_func, ieee802154_decrypt_func decrypt_func)
1789 {
1790     proto_item* ti;
1791     unsigned char key[IEEE802154_CIPHER_SIZE];
1792     unsigned char alt_key[IEEE802154_CIPHER_SIZE];
1793     tvbuff_t * payload_tvb = NULL;
1794 
1795     /* Lookup the key. */
1796     for (decrypt_info->key_number = 0; decrypt_info->key_number < num_ieee802154_keys; decrypt_info->key_number++) {
1797         guint nkeys = set_key_func(packet, key, alt_key, &ieee802154_keys[decrypt_info->key_number]);
1798         if (nkeys >= 1) {
1799             /* Try with the initial key */
1800             decrypt_info->key = key;
1801             payload_tvb = decrypt_func(tvb, offset, pinfo, packet, decrypt_info);
1802             if (!((*decrypt_info->status == DECRYPT_PACKET_MIC_CHECK_FAILED) || (*decrypt_info->status == DECRYPT_PACKET_DECRYPT_FAILED))) {
1803                 break;
1804             }
1805         }
1806         if (nkeys >= 2) {
1807             /* Try also with the alternate key */
1808             decrypt_info->key = alt_key;
1809             payload_tvb = decrypt_func(tvb, offset, pinfo, packet, decrypt_info);
1810             if (!((*decrypt_info->status == DECRYPT_PACKET_MIC_CHECK_FAILED) || (*decrypt_info->status == DECRYPT_PACKET_DECRYPT_FAILED))) {
1811                 break;
1812             }
1813         }
1814     }
1815     if (decrypt_info->key_number == num_ieee802154_keys) {
1816         /* None of the stored keys seemed to work */
1817         *decrypt_info->status = DECRYPT_PACKET_NO_KEY;
1818     }
1819 
1820     /* Store the key number used for retrieval */
1821     ti = proto_tree_add_uint(key_tree, hf_ieee802154_key_number, tvb, 0, 0, decrypt_info->key_number);
1822     proto_item_set_hidden(ti);
1823     return payload_tvb;
1824 }
1825 
1826 
1827 /**
1828  * Check if the CRC-OK flag in the CC24xx metadata trailer is true
1829  * @param tvb the IEEE 802.15.4 frame
1830  * @return if the flag is true
1831  */
1832 static gboolean
is_cc24xx_crc_ok(tvbuff_t * tvb)1833 is_cc24xx_crc_ok(tvbuff_t *tvb)
1834 {
1835     return tvb_get_letohs(tvb, tvb_reported_length(tvb)-2) & IEEE802154_CC24xx_CRC_OK ? TRUE : FALSE;
1836 }
1837 
1838 /**
1839  * Verify the 16/32 bit IEEE 802.15.4 FCS
1840  * @param tvb the IEEE 802.15.4 frame from the FCF up to and including the FCS
1841  * @return if the computed FCS matches the transmitted FCS
1842  */
1843 static gboolean
is_fcs_ok(tvbuff_t * tvb,guint fcs_len)1844 is_fcs_ok(tvbuff_t *tvb, guint fcs_len)
1845 {
1846     if (fcs_len == 2) {
1847         /* The FCS is in the last two bytes of the packet. */
1848         guint16 fcs = tvb_get_letohs(tvb, tvb_reported_length(tvb)-2);
1849         guint16 fcs_calc = (guint16) ieee802154_crc_tvb(tvb, tvb_reported_length(tvb)-2);
1850         return fcs == fcs_calc;
1851     }
1852     else {
1853         /* The FCS is in the last four bytes of the packet. */
1854         guint32 fcs = tvb_get_letohl(tvb, tvb_reported_length(tvb)-4);
1855         guint32 fcs_calc = ieee802154_crc32_tvb(tvb, tvb_reported_length(tvb)-4);
1856         return fcs == fcs_calc;
1857     }
1858 }
1859 
1860 /**
1861  * Dissector for IEEE 802.15.4 packets with a PHY for which there's a
1862  * 4-octet preamble, a 1-octet SFD, and a 1-octet PHY header
1863  * with the uppermost bit reserved and the remaining 7 bits being
1864  * the frame length, and a 16-bit CRC value at the end.
1865  *
1866  * Currently, those are the following PHYs:
1867  *
1868  *    O-QPSK
1869  *    Binary phase-shift keying (BPSK)
1870  *    GFSK
1871  *    MSK
1872  *    RCC DSSS BPSK
1873  *
1874  * @param tvb pointer to buffer containing raw packet.
1875  * @param pinfo pointer to packet information fields
1876  * @param tree pointer to data tree wireshark uses to display packet.
1877  */
1878 static int
dissect_ieee802154_nonask_phy(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1879 dissect_ieee802154_nonask_phy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1880 {
1881     proto_tree *ieee802154_tree = NULL;
1882     proto_item *proto_root      = NULL;
1883 
1884     guint       offset          = 0;
1885     guint8      phr;
1886     tvbuff_t*   mac;
1887 
1888     /* Create the protocol tree. */
1889     if (tree) {
1890         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");
1891         ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154_nonask_phy);
1892     }
1893 
1894     /* Add the protocol name. */
1895     col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4 non-ASK PHY");
1896 
1897     phr = tvb_get_guint8(tvb,offset+4+1);
1898 
1899     if (tree) {
1900         guint loffset = offset;
1901         static int * const phr_fields[] = {
1902                     &hf_ieee802154_nonask_phy_length,
1903                     NULL
1904                 };
1905 
1906         proto_tree_add_item(ieee802154_tree, hf_ieee802154_nonask_phy_preamble, tvb, loffset, 4, ENC_LITTLE_ENDIAN);
1907         loffset +=4 ;
1908         proto_tree_add_item(ieee802154_tree, hf_ieee802154_nonask_phy_sfd, tvb, loffset, 1, ENC_LITTLE_ENDIAN);
1909         loffset +=1 ;
1910 
1911         proto_tree_add_bitmask(ieee802154_tree, tvb, loffset, hf_ieee802154_nonask_phr, ett_ieee802154_nonask_phy_phr,
1912             phr_fields, ENC_NA);
1913     }
1914 
1915     offset += 4+2*1;
1916     mac = tvb_new_subset_length_caplen(tvb,offset,-1, phr & IEEE802154_PHY_LENGTH_MASK);
1917 
1918     /* These always have the FCS at the end. */
1919 
1920     /*
1921      * Call the common dissector; FCS length is 2, and no flags.
1922      */
1923     dissect_ieee802154_common(mac, pinfo, ieee802154_tree, 2, 0);
1924     return tvb_captured_length(tvb);
1925 } /* dissect_ieee802154_nonask_phy */
1926 
1927 /* Return the length in octets for the user configured
1928  * FCS/metadata following the PHY Payload */
1929 static guint
ieee802154_fcs_type_len(guint i)1930 ieee802154_fcs_type_len(guint i)
1931 {
1932     guint fcs_type_lengths[] = { 2, 2, 4 };
1933     if (i < array_length(fcs_type_lengths)) {
1934         return fcs_type_lengths[i];
1935     }
1936     return 0;
1937 }
1938 
1939 /**
1940  * Dissector for IEEE 802.15.4 packet with an FCS containing a 16/32-bit
1941  * CRC value, or TI CC24xx metadata, at the end.
1942  *
1943  * @param tvb pointer to buffer containing raw packet.
1944  * @param pinfo pointer to packet information fields.
1945  * @param tree pointer to data tree wireshark uses to display packet.
1946  */
1947 static int
dissect_ieee802154(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1948 dissect_ieee802154(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1949 {
1950     tvbuff_t *new_tvb = dissect_zboss_specific(tvb, pinfo, tree);
1951     guint options = 0;
1952     guint fcs_len;
1953 
1954     /* Set the default FCS length based on the FCS type in the configuration */
1955     fcs_len = ieee802154_fcs_type_len(ieee802154_fcs_type);
1956 
1957     if (ieee802154_fcs_type == IEEE802154_CC24XX_METADATA) {
1958         options = DISSECT_IEEE802154_OPTION_CC24xx;
1959     }
1960 
1961     if (new_tvb != tvb) {
1962         /* ZBOSS traffic dump: always TI metadata trailer, always ZigBee */
1963         options = DISSECT_IEEE802154_OPTION_CC24xx|DISSECT_IEEE802154_OPTION_ZBOSS;
1964         fcs_len = 2;
1965     }
1966 
1967     /* Call the common dissector. */
1968     dissect_ieee802154_common(new_tvb, pinfo, tree, fcs_len, options);
1969     return tvb_captured_length(tvb);
1970 } /* dissect_ieee802154 */
1971 
1972 /**
1973  * Dissector for IEEE 802.15.4 packet with no FCS present.
1974  *
1975  * @param tvb pointer to buffer containing raw packet.
1976  * @param pinfo pointer to packet information fields
1977  * @param tree pointer to data tree wireshark uses to display packet.
1978  * @return captured length.
1979  */
1980 static int
dissect_ieee802154_nofcs(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1981 dissect_ieee802154_nofcs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
1982 {
1983     /*
1984      * Call the common dissector; FCS length is 0, and no flags.
1985      */
1986     dissect_ieee802154_common(tvb, pinfo, tree, 0, 0);
1987     return tvb_captured_length(tvb);
1988 } /* dissect_ieee802154_nofcs */
1989 
1990 /**
1991  * Dissector for IEEE 802.15.4 packet dump produced by ZBOSS
1992  *
1993  * @param tvb pointer to buffer containing raw packet.
1994  * @param pinfo pointer to packet information fields
1995  * @param tree pointer to data tree wireshark uses to display packet.
1996  * @return new tvb subset if this is really ZBOSS dump, else oririnal tvb.
1997  */
1998 static tvbuff_t *
dissect_zboss_specific(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree)1999 dissect_zboss_specific(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
2000 {
2001     proto_tree *zboss_tree;
2002     proto_item *proto_root;
2003     guint off = 0;
2004     guint32 direction_byte, page_byte, channel;
2005 
2006     if (tvb_captured_length(tvb) > 5)
2007     {
2008         if (tvb_get_guint8(tvb, off++) == 'Z'
2009             && tvb_get_guint8(tvb, off++) == 'B'
2010             && tvb_get_guint8(tvb, off++) == 'O'
2011             && tvb_get_guint8(tvb, off++) == 'S'
2012             && tvb_get_guint8(tvb, off++) == 'S')
2013         {
2014             /* Create the protocol tree. */
2015             proto_root = proto_tree_add_protocol_format(tree, proto_zboss, tvb, 0, tvb_captured_length(tvb), "ZBOSS dump");
2016             zboss_tree = proto_item_add_subtree(proto_root, ett_ieee802154_zboss);
2017 
2018             proto_tree_add_item_ret_uint(zboss_tree, hf_zboss_direction, tvb, off, 1, ENC_NA, &direction_byte);
2019             proto_item_append_text(proto_root, ", %s", direction_byte ? "OUT" : "IN");
2020 
2021             proto_tree_add_item_ret_uint(zboss_tree, hf_zboss_page, tvb, off, 1, ENC_NA, &page_byte);
2022             proto_item_append_text(proto_root, ", page %u", page_byte);
2023             off++;
2024 
2025             proto_tree_add_item_ret_uint(zboss_tree, hf_zboss_channel, tvb, off, 1, ENC_NA, &channel);
2026             proto_item_append_text(proto_root, ", channel %u", channel);
2027             off++;
2028 
2029             proto_tree_add_item(zboss_tree, hf_zboss_trace_number, tvb, off, 4, ENC_LITTLE_ENDIAN);
2030             off += 4;
2031 
2032             return tvb_new_subset_remaining(tvb, off);
2033         }
2034     }
2035     return tvb;
2036 } /* dissect_zboss_specific */
2037 
2038 /**
2039  * Dissector for IEEE 802.15.4 packet with 2 bytes of ChipCon/Texas
2040  * Instruments compatible metadata at the end of the frame, and no FCS.
2041  * This is typically called by layers encapsulating an IEEE 802.15.4 packet.
2042  *
2043  * @param tvb pointer to buffer containing raw packet.
2044  * @param pinfo pointer to packet information fields
2045  * @param tree pointer to data tree wireshark uses to display packet.
2046  */
2047 static int
dissect_ieee802154_cc24xx(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2048 dissect_ieee802154_cc24xx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
2049 {
2050     /*
2051      * Call the common dissector.
2052      * 2 bytes of metadata at the end of the packet data.
2053      */
2054     dissect_ieee802154_common(tvb, pinfo, tree, 2, DISSECT_IEEE802154_OPTION_CC24xx);
2055     return tvb_captured_length(tvb);
2056 } /* dissect_ieee802154_cc24xx */
2057 
2058 /**
2059  * Dissector for IEEE 802.15.4 TAP packet
2060  *
2061  * Contains optional TLVs and encapsulates an IEEE 802.15.4 packet.
2062  *
2063  * @param tvb pointer to buffer containing raw packet.
2064  * @param pinfo pointer to packet information fields
2065  * @param tree pointer to data tree wireshark uses to display packet.
2066  */
2067 static int
dissect_ieee802154_tap(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2068 dissect_ieee802154_tap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * data _U_)
2069 {
2070     proto_tree *info_tree = NULL;
2071     proto_tree *header_tree = NULL;
2072     proto_item *proto_root = NULL;
2073     proto_item *ti = NULL;
2074     guint32     version = 0;
2075     guint32     length = 0;
2076     guint32     data_length = 0;
2077     tvbuff_t*   tlv_tvb;
2078     tvbuff_t*   payload_tvb;
2079     ieee802154_fcs_type_t tap_fcs_type;
2080     guint       fcs_len;
2081 
2082     /* Check the version in the TAP header */
2083     version = tvb_get_guint8(tvb, 0);
2084     if (version != 0) {
2085         /* Malformed packet. We do not understand any other version at this time */
2086         return 0;
2087     }
2088 
2089     /* Get the total length of the header and TLVs */
2090     length = tvb_get_letohs(tvb, 2);
2091 
2092     if (length > tvb_captured_length(tvb)) {
2093         /* Malformed packet. The TLVs exceeds our captured packet. */
2094         return 0;
2095     }
2096 
2097     /* Create the protocol tree */
2098     proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154_tap, tvb, 0, length, "IEEE 802.15.4 TAP");
2099     info_tree = proto_item_add_subtree(proto_root, ett_ieee802154_tap);
2100 
2101     header_tree = proto_tree_add_subtree(info_tree, tvb, 0, 4, ett_ieee802154_tap_header, &proto_root, "Header");
2102     proto_tree_add_item(header_tree, hf_ieee802154_tap_version, tvb, 0, 1, ENC_LITTLE_ENDIAN);
2103     proto_tree_add_item(header_tree, hf_ieee802154_tap_reserved, tvb, 1, 1, ENC_LITTLE_ENDIAN);
2104     proto_tree_add_item(header_tree, hf_ieee802154_tap_length, tvb, 2, 2, ENC_LITTLE_ENDIAN);
2105 
2106     /* Add the protocol name. */
2107     col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4 TAP");
2108 
2109     /* Create a new tvb subset with only the TLVs to dissect */
2110     tlv_tvb = tvb_new_subset_length(tvb, 4, length - 4);
2111     tap_fcs_type = dissect_ieee802154_tap_tlvs(tlv_tvb, pinfo, info_tree);
2112 
2113     /* Set the FCS length based on the FCS type */
2114     switch (tap_fcs_type) {
2115 
2116     case IEEE802154_FCS_TYPE_NONE:
2117         fcs_len = 0;
2118         break;
2119 
2120     case IEEE802154_FCS_TYPE_16_BIT:
2121         fcs_len = 2;
2122         break;
2123 
2124     case IEEE802154_FCS_TYPE_32_BIT:
2125         fcs_len = 4;
2126         break;
2127 
2128     default:
2129         /* Not valid */
2130         return tvb_captured_length(tvb);
2131     }
2132 
2133     /* Report the remaining bytes as the IEEE 802.15.4 Data Length */
2134     data_length = tvb_reported_length_remaining(tvb, length);
2135     ti = proto_tree_add_uint(info_tree, hf_ieee802154_tap_data_length, NULL, 0, 0, data_length);
2136     proto_item_set_generated(ti);
2137 
2138     /*
2139      * Call the common dissector with the real 802.15.4 data which follows the TLV header.
2140      * Create a separate packet bytes pane for the real data.
2141      * Specified FCS length, no flags.
2142      */
2143     payload_tvb = tvb_new_child_real_data(tvb, tvb_get_ptr(tvb, length, data_length), data_length, data_length);
2144     add_new_data_source(pinfo, payload_tvb, "IEEE 802.15.4 Data");
2145     dissect_ieee802154_common(payload_tvb, pinfo, tree, fcs_len, 0);
2146 
2147     return tvb_captured_length(tvb);
2148 } /* dissect_ieee802154_tap */
2149 
2150 /**
2151  * IEEE 802.15.4 packet dissection routine for Wireshark.
2152  *
2153  * This function extracts all the information first before displaying.
2154  * If payload exists, that portion will be passed into another dissector
2155  * for further processing.
2156  *
2157  * This is called after the individual dissect_ieee802154* functions
2158  * have been called to determine what sort of FCS is present, if any.
2159  *
2160  * @param tvb pointer to buffer containing raw packet.
2161  * @param pinfo pointer to packet information fields
2162  * @param tree pointer to data tree Wireshark uses to display packet.
2163  * @param options bitwise or of dissector options (see DISSECT_IEEE802154_OPTION_xxx).
2164  */
2165 static void
dissect_ieee802154_common(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint fcs_len,guint options)2166 dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint fcs_len, guint options)
2167 {
2168     proto_tree *ieee802154_tree;
2169     ieee802154_packet *packet;
2170     gboolean fcs_present;
2171     gboolean fcs_ok;
2172     tvbuff_t* no_fcs_tvb;
2173 
2174     if (fcs_len != 0) {
2175         /*
2176          * Well, this packet should, in theory, have an FCS or CC24xx
2177          * metadata.
2178          * Do we have the entire packet, and does it have enough data for
2179          * the FCS/metadata?
2180          */
2181         guint reported_len = tvb_reported_length(tvb);
2182 
2183         if (reported_len < fcs_len) {
2184             /*
2185              * The packet is claimed not to even have enough data
2186              * for the FCS/metadata.  Pretend it doesn't have one.
2187              */
2188             no_fcs_tvb = tvb;
2189             fcs_present = FALSE;
2190             fcs_ok = TRUE;  // assume OK if not present
2191         } else {
2192             /*
2193              * The packet is claimed to have enough data for the
2194              * FCS/metadata.
2195              * Slice it off from the reported length.
2196              */
2197             reported_len -= fcs_len;
2198             no_fcs_tvb = tvb_new_subset_length(tvb, 0, reported_len);
2199 
2200             /*
2201              * Is the FCS/metadata present in the captured data?
2202              * reported_len is now the length of the packet without the
2203              * FCS/metadata, so the FCS/metadata begins at an offset of
2204              * reported_len.
2205              */
2206             if (tvb_bytes_exist(tvb, reported_len, fcs_len)) {
2207                 /*
2208                  * Yes.  Check whether the FCS was OK.
2209                  *
2210                  * If we have an FCS, check it.
2211                  * If we have metadata, check its "FCS OK" flag.
2212                  */
2213                 fcs_present = TRUE;
2214                 fcs_ok = options & DISSECT_IEEE802154_OPTION_CC24xx ? is_cc24xx_crc_ok(tvb) : is_fcs_ok(tvb, fcs_len);
2215             } else {
2216                 /*
2217                  * No.
2218                  *
2219                  * Either 1) this means that there was a snapshot length
2220                  * in effect when the capture was done, and that sliced
2221                  * some or all of the FCS/metadata off or 2) this is a
2222                  * capture with no FCS/metadata, using the same link-layer
2223                  * header type value as captures with the FCS/metadata,
2224                  * and indicating the lack of the FCS/metadata by having
2225                  * the captured length be the length of the packet minus
2226                  * the length of the FCS/metadata and the actual length
2227                  * being the length of the packet including the FCS/metadata,
2228                  * rather than by using the "no FCS" link-layer header type.
2229                  *
2230                  * We could try to distinguish between them by checking
2231                  * for a captured length that's exactly fcs_len bytes
2232                  * less than the actual length.  That would allow us to
2233                  * report packets that are cut short just before, or in
2234                  * the middle of, the FCS as having been cut short by the
2235                  * snapshot length.
2236                  *
2237                  * However, we can't distinguish between a packet that
2238                  * happened to be cut fcs_len bytes short due to a
2239                  * snapshot length being in effect when the capture was
2240                  * done and a packet that *wasn't* cut short by a snapshot
2241                  * length but that doesn't include the FCS/metadata.
2242                  * Let's hope that rarely happens.
2243                  */
2244                 fcs_present = FALSE;
2245                 fcs_ok = TRUE;  // assume OK if not present
2246             }
2247         }
2248     } else {
2249         no_fcs_tvb = tvb;
2250         fcs_present = FALSE;
2251         fcs_ok = TRUE;  // assume OK if not present
2252     }
2253 
2254     guint mhr_len = ieee802154_dissect_header(no_fcs_tvb, pinfo, tree, 0, &ieee802154_tree, &packet);
2255     if (!mhr_len || tvb_reported_length_remaining(no_fcs_tvb, mhr_len) < 0 ) {
2256         return;
2257     }
2258 
2259     if ((packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) && (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE)) {
2260         _find_or_create_conversation(pinfo, &pinfo->dl_src, &pinfo->dl_dst);
2261     }
2262 
2263     if (ieee802154_ack_tracking && (packet->ack_request || packet->frame_type == IEEE802154_FCF_ACK)) {
2264         guint32 key[2] = {0};
2265 
2266         key[0] = packet->seqno;
2267         if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) {
2268             key[1] = pinfo->rec->rec_header.packet_header.interface_id;
2269         }
2270 
2271         if (packet->ack_request) {
2272             transaction_start(pinfo, ieee802154_tree, packet, key);
2273         }
2274         else {
2275             transaction_end(pinfo, ieee802154_tree, packet, key);
2276         }
2277     }
2278 
2279     tvbuff_t* payload = ieee802154_decrypt_payload(no_fcs_tvb, mhr_len, pinfo, ieee802154_tree, packet);
2280     if (payload) {
2281         guint pie_size = ieee802154_dissect_payload_ies(payload, pinfo, ieee802154_tree, packet);
2282         payload = tvb_new_subset_remaining(payload, pie_size);
2283         if (options & DISSECT_IEEE802154_OPTION_ZBOSS && packet->frame_type == IEEE802154_FCF_DATA) {
2284             if ((!fcs_ok && ieee802154_fcs_ok) || !tvb_reported_length(payload)) {
2285                 call_data_dissector(payload, pinfo, tree);
2286             } else {
2287                 call_dissector_with_data(zigbee_nwk_handle, payload, pinfo, tree, packet);
2288             }
2289         } else {
2290             ieee802154_dissect_frame_payload(payload, pinfo, ieee802154_tree, packet, fcs_ok);
2291         }
2292     }
2293 
2294     if (fcs_present) {
2295         if (options & DISSECT_IEEE802154_OPTION_CC24xx)
2296             ieee802154_dissect_cc24xx_metadata(tvb, ieee802154_tree, fcs_ok);
2297         else
2298             ieee802154_dissect_fcs(tvb, ieee802154_tree, fcs_len, fcs_ok);
2299 
2300         /* If the CRC is invalid, make a note of it in the info column. */
2301         if (!fcs_ok) {
2302             col_append_str(pinfo->cinfo, COL_INFO, ", Bad FCS");
2303             proto_item_append_text(proto_tree_get_parent(ieee802154_tree), ", Bad FCS");
2304 
2305             /* Flag packet as having a bad crc. */
2306             expert_add_info(pinfo, proto_tree_get_parent(ieee802154_tree), &ei_ieee802154_fcs);
2307         }
2308     } else {
2309         if (ieee802154_tree) {
2310             /* Even if the FCS isn't present, add the fcs_ok field to the tree to
2311              * help with filter. Be sure not to make it visible though.
2312              */
2313             proto_item *ti = proto_tree_add_boolean_format_value(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, 0, 0, fcs_ok, "Unknown");
2314             proto_item_set_hidden(ti);
2315         }
2316     }
2317 
2318     tap_queue_packet(ieee802154_tap, pinfo, NULL);
2319 }
2320 
2321 guint
ieee802154_dissect_header(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint options,proto_tree ** created_header_tree,ieee802154_packet ** parsed_info)2322 ieee802154_dissect_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint options, proto_tree **created_header_tree, ieee802154_packet **parsed_info)
2323 {
2324     proto_tree              *ieee802154_tree = NULL;
2325     proto_item              *proto_root = NULL;
2326     proto_item              *hidden_item;
2327     proto_item              *ti;
2328     guint                   offset = 0;
2329     ieee802154_packet      *packet = wmem_new0(pinfo->pool, ieee802154_packet);
2330     ieee802154_short_addr   addr16;
2331     ieee802154_hints_t     *ieee_hints;
2332 
2333     packet->short_table = ieee802154_map.short_table;
2334 
2335     /* Allocate frame data with hints for upper layers */
2336     if (!PINFO_FD_VISITED(pinfo) ||
2337         (ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0)) == NULL) {
2338         ieee_hints = wmem_new0(wmem_file_scope(), ieee802154_hints_t);
2339         p_add_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0, ieee_hints);
2340     }
2341 
2342     /* Save a pointer to the whole packet */
2343     ieee_hints->packet = packet;
2344 
2345     /* Create the protocol tree. */
2346     if (tree) {
2347         proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154, tvb, 0, tvb_captured_length(tvb), "IEEE 802.15.4");
2348         ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154);
2349     }
2350     /* Add the protocol name. */
2351     col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4");
2352 
2353     /* Set out parameters */
2354     *created_header_tree = ieee802154_tree;
2355     *parsed_info = packet;
2356 
2357     /* Add the packet length to the filter field */
2358     hidden_item = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_frame_length, NULL, 0, 0, tvb_reported_length(tvb));
2359     proto_item_set_hidden(hidden_item);
2360 
2361     /* Frame Control Field */
2362     dissect_ieee802154_fcf(tvb, pinfo, ieee802154_tree, packet, &offset);
2363 
2364     /* Sequence Number */
2365     if (packet->seqno_suppression) {
2366         if (packet->version != IEEE802154_VERSION_2015 && packet->frame_type != IEEE802154_FCF_MULTIPURPOSE) {
2367             expert_add_info(pinfo, proto_root, &ei_ieee802154_seqno_suppression);
2368         }
2369     } else { /* IEEE 802.15.4 Sequence Number Suppression */
2370         packet->seqno = tvb_get_guint8(tvb, offset);
2371         if (tree) {
2372             proto_tree_add_uint(ieee802154_tree, hf_ieee802154_seqno, tvb, offset, 1, packet->seqno);
2373             /* For Ack packets display this in the root. */
2374             if (packet->frame_type == IEEE802154_FCF_ACK) {
2375                 proto_item_append_text(proto_root, ", Sequence Number: %u", packet->seqno);
2376             }
2377         }
2378         offset += 1;
2379     }
2380 
2381     /*
2382      * ADDRESSING FIELDS
2383      */
2384     /* Clear out the addressing strings. */
2385     clear_address(&pinfo->net_dst);
2386     clear_address(&pinfo->dl_dst);
2387     clear_address(&pinfo->dst);
2388     clear_address(&pinfo->net_src);
2389     clear_address(&pinfo->dl_src);
2390     clear_address(&pinfo->src);
2391 
2392     if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_RESERVED) {
2393         /* Invalid Destination Address Mode. Abort Dissection. */
2394         expert_add_info(pinfo, proto_root, &ei_ieee802154_dst);
2395         return 0;
2396     }
2397 
2398     if (packet->src_addr_mode == IEEE802154_FCF_ADDR_RESERVED) {
2399         /* Invalid Source Address Mode. Abort Dissection. */
2400         expert_add_info(pinfo, proto_root, &ei_ieee802154_src);
2401         return 0;
2402     }
2403 
2404     if (packet->frame_type == IEEE802154_FCF_MULTIPURPOSE) {
2405         /* Multipurpose frames have a different set of frame versions, with 0 as the only valid version */
2406         if (packet->version != 0) {
2407             /* Unknown Frame Version for Multipurpose frames. Abort Dissection */
2408             expert_add_info(pinfo, proto_root, &ei_ieee802154_frame_ver);
2409             return 0;
2410         }
2411 
2412         /* The source PAN ID is always omitted in multipurpose frames */
2413         packet->src_pan_present = FALSE;
2414 
2415         if (packet->pan_id_present) {
2416             packet->dst_pan_present = TRUE;
2417         }
2418     }
2419     else if (packet->version == IEEE802154_VERSION_RESERVED) {
2420         /* Unknown Frame Version. Abort Dissection. */
2421         expert_add_info(pinfo, proto_root, &ei_ieee802154_frame_ver);
2422         return 0;
2423     }
2424     else if ((packet->version == IEEE802154_VERSION_2003) ||  /* For Frame Version 0b00 and */
2425              (packet->version == IEEE802154_VERSION_2006))  { /* 0b01 effect defined in section 7.2.1.5 */
2426 
2427         if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /* if both destination and source */
2428             (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE)) { /* addressing information is present */
2429             if (packet->pan_id_compression == 1) { /* PAN IDs are identical */
2430                 packet->dst_pan_present = TRUE;
2431                 packet->src_pan_present = FALSE; /* source PAN ID is omitted */
2432             }
2433             else { /* PAN IDs are different, both shall be included in the frame */
2434                 packet->dst_pan_present = TRUE;
2435                 packet->src_pan_present = TRUE;
2436             }
2437         }
2438         else {
2439             if (packet->pan_id_compression == 1) { /* all remaining cases pan_id_compression must be zero */
2440                 expert_add_info(pinfo, proto_root, &ei_ieee802154_invalid_panid_compression);
2441                 return 0;
2442             }
2443             else {
2444                 /* only either the destination or the source addressing information is present */
2445                 if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) &&        /*   Present   */
2446                     (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE)) {        /* Not Present */
2447                     packet->dst_pan_present = TRUE;
2448                     packet->src_pan_present = FALSE;
2449                 }
2450                 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) &&   /* Not Present */
2451                          (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE)) {   /*   Present   */
2452                     packet->dst_pan_present = FALSE;
2453                     packet->src_pan_present = TRUE;
2454                 }
2455                 else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) &&   /* Not Present */
2456                          (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE)) {   /* Not Present */
2457                     packet->dst_pan_present = FALSE;
2458                     packet->src_pan_present = FALSE;
2459                 }
2460                 else {
2461                     expert_add_info(pinfo, proto_root, &ei_ieee802154_invalid_addressing);
2462                     return 0;
2463                 }
2464             }
2465         }
2466     }
2467     else if (packet->version == IEEE802154_VERSION_2015) {
2468         /* for Frame Version 0b10 PAN Id Compression only applies to these frame types */
2469         if ((packet->frame_type == IEEE802154_FCF_BEACON) ||
2470             (packet->frame_type == IEEE802154_FCF_DATA)   ||
2471             (packet->frame_type == IEEE802154_FCF_ACK)    ||
2472             (packet->frame_type == IEEE802154_FCF_CMD)       ) {
2473 
2474             /* Implements Table 7-6 of IEEE 802.15.4-2015
2475              *
2476              *      Destination Address  Source Address  Destination PAN ID  Source PAN ID   PAN ID Compression
2477              *-------------------------------------------------------------------------------------------------
2478              *  1.  Not Present          Not Present     Not Present         Not Present     0
2479              *  2.  Not Present          Not Present     Present             Not Present     1
2480              *  3.  Present              Not Present     Present             Not Present     0
2481              *  4.  Present              Not Present     Not Present         Not Present     1
2482              *
2483              *  5.  Not Present          Present         Not Present         Present         0
2484              *  6.  Not Present          Present         Not Present         Not Present     1
2485              *
2486              *  7.  Extended             Extended        Present             Not Present     0
2487              *  8.  Extended             Extended        Not Present         Not Present     1
2488              *
2489              *  9.  Short                Short           Present             Present         0
2490              * 10.  Short                Extended        Present             Present         0
2491              * 11.  Extended             Short           Present             Present         0
2492              *
2493              * 12.  Short                Extended        Present             Not Present     1
2494              * 13.  Extended             Short           Present             Not Present     1
2495              * 14.  Short                Short           Present             Not Present     1
2496              */
2497 
2498             /* Row 1 */
2499             if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) &&      /* Not Present */
2500                 (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) &&      /* Not Present */
2501                 (packet->pan_id_compression == 0)) {
2502                         packet->dst_pan_present = FALSE;
2503                         packet->src_pan_present = FALSE;
2504             }
2505             /* Row 2 */
2506             else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2507                      (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2508                      (packet->pan_id_compression == 1)) {
2509                         packet->dst_pan_present = TRUE;
2510                         packet->src_pan_present = FALSE;
2511             }
2512             /* Row 3 */
2513             else if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /*  Present    */
2514                      (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2515                      (packet->pan_id_compression == 0)) {
2516                         packet->dst_pan_present = TRUE;
2517                         packet->src_pan_present = FALSE;
2518             }
2519             /* Row 4 */
2520             else if ((packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) && /*  Present    */
2521                      (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2522                      (packet->pan_id_compression == 1)) {
2523                         packet->dst_pan_present = FALSE;
2524                         packet->src_pan_present = FALSE;
2525             }
2526             /* Row 5 */
2527             else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2528                      (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) && /*  Present    */
2529                      (packet->pan_id_compression == 0)) {
2530                         packet->dst_pan_present = FALSE;
2531                         packet->src_pan_present = TRUE;
2532             }
2533             /* Row 6 */
2534             else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) && /* Not Present */
2535                      (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) && /*  Present    */
2536                      (packet->pan_id_compression == 1)) {
2537                         packet->dst_pan_present = FALSE;
2538                         packet->src_pan_present = FALSE;
2539             }
2540             /* Row 7 */
2541             else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /*  Extended    */
2542                      (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /*  Extended    */
2543                      (packet->pan_id_compression == 0)) {
2544                         packet->dst_pan_present = TRUE;
2545                         packet->src_pan_present = FALSE;
2546             }
2547             /* Row 8 */
2548             else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) && /*  Extended    */
2549                      (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) && /*  Extended    */
2550                      (packet->pan_id_compression == 1)) {
2551                         packet->dst_pan_present = FALSE;
2552                         packet->src_pan_present = FALSE;
2553             }
2554             /* Row 9 */
2555             else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /*  Short     */
2556                      (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /*  Short     */
2557                      (packet->pan_id_compression == 0)) {
2558                         packet->dst_pan_present = TRUE;
2559                         packet->src_pan_present = (ieee802154e_compatibility ? FALSE : TRUE);
2560             }
2561             /* Row 10 */
2562             else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) && /*  Short    */
2563                      (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&   /*  Extended */
2564                      (packet->pan_id_compression == 0)) {
2565                         packet->dst_pan_present = TRUE;
2566                         packet->src_pan_present = (ieee802154e_compatibility ? FALSE : TRUE);
2567             }
2568             /* Row 11 */
2569             else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)   &&   /*  Extended */
2570                      (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&   /*  Short    */
2571                      (packet->pan_id_compression == 0)) {
2572                         packet->dst_pan_present = TRUE;
2573                         packet->src_pan_present = (ieee802154e_compatibility ? FALSE : TRUE);
2574             }
2575             /* Row 12 */
2576             else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&   /*  Short    */
2577                      (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT)   &&   /*  Extended */
2578                      (packet->pan_id_compression == 1)) {
2579                         packet->dst_pan_present = TRUE;
2580                         packet->src_pan_present = FALSE;
2581             }
2582             /* Row 13 */
2583             else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)   &&   /*  Extended */
2584                      (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&   /*  Short    */
2585                      (packet->pan_id_compression == 1)) {
2586                         packet->dst_pan_present = TRUE;
2587                         packet->src_pan_present = FALSE;
2588             }
2589             /* Row 14 */
2590             else if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&   /*  Short    */
2591                      (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&   /*  Short    */
2592                      (packet->pan_id_compression == 1)) {
2593                         packet->dst_pan_present = TRUE;
2594                         packet->src_pan_present = FALSE;
2595             }
2596             else {
2597                 expert_add_info(pinfo, proto_root, &ei_ieee802154_invalid_panid_compression2);
2598                 return 0;
2599             }
2600         }
2601         else { /* Frame Type is neither Beacon, Data, Ack, nor Command: PAN ID Compression is not used */
2602             packet->dst_pan_present = FALSE; /* no PAN ID will */
2603             packet->src_pan_present = FALSE; /* be present     */
2604         }
2605     }
2606     else {
2607         /* Unknown Frame Version. Abort Dissection. */
2608         expert_add_info(pinfo, proto_root, &ei_ieee802154_frame_ver);
2609         return 0;
2610     }
2611 
2612     /*
2613      * Addressing Fields
2614      */
2615 
2616     /* Destination PAN Id */
2617     if (packet->dst_pan_present) {
2618         packet->dst_pan = tvb_get_letohs(tvb, offset);
2619         if (ieee802154_tree) {
2620             proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst_panID, tvb, offset, 2, packet->dst_pan);
2621         }
2622         offset += 2;
2623     }
2624 
2625     /* Destination Address  */
2626     if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
2627         gchar* dst_addr;
2628 
2629         /* Get the address. */
2630         packet->dst16 = tvb_get_letohs(tvb, offset);
2631 
2632         /* Provide address hints to higher layers that need it. */
2633         if (ieee_hints) {
2634             ieee_hints->dst16 = packet->dst16;
2635         }
2636 
2637         set_address_tvb(&pinfo->dl_dst, ieee802_15_4_short_address_type, 2, tvb, offset);
2638         copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
2639         dst_addr = address_to_str(pinfo->pool, &pinfo->dst);
2640 
2641         proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst16, tvb, offset, 2, packet->dst16);
2642         proto_item_append_text(proto_root, ", Dst: %s", dst_addr);
2643         ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_addr16, tvb, offset, 2, packet->dst16);
2644         proto_item_set_generated(ti);
2645         proto_item_set_hidden(ti);
2646 
2647         col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_addr);
2648         offset += 2;
2649     }
2650     else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
2651         guint64 *p_addr = (guint64 *)wmem_new(pinfo->pool, guint64);
2652 
2653         /* Get the address */
2654         packet->dst64 = tvb_get_letoh64(tvb, offset);
2655 
2656         /* Copy and convert the address to network byte order. */
2657         *p_addr = pntoh64(&(packet->dst64));
2658 
2659         /* Display the destination address. */
2660         /* XXX - OUI resolution doesn't happen when displaying resolved
2661          * EUI64 addresses; that should probably be fixed in
2662          * epan/addr_resolv.c.
2663          */
2664         set_address(&pinfo->dl_dst, AT_EUI64, 8, p_addr);
2665         copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
2666         if (tree) {
2667             proto_tree_add_item(ieee802154_tree, hf_ieee802154_dst64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2668             proto_item_append_text(proto_root, ", Dst: %s", eui64_to_display(pinfo->pool, packet->dst64));
2669             ti = proto_tree_add_item(ieee802154_tree, hf_ieee802154_addr64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2670             proto_item_set_generated(ti);
2671             proto_item_set_hidden(ti);
2672         }
2673         col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", eui64_to_display(pinfo->pool, packet->dst64));
2674         offset += 8;
2675     }
2676 
2677     /* Source PAN Id */
2678     if (packet->src_pan_present) {
2679         packet->src_pan = tvb_get_letohs(tvb, offset);
2680         proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src_panID, tvb, offset, 2, packet->src_pan);
2681         offset += 2;
2682     }
2683     else {
2684         if (packet->dst_pan_present) {
2685             packet->src_pan = packet->dst_pan;
2686         }
2687         else {
2688             packet->src_pan = IEEE802154_BCAST_PAN;
2689         }
2690     }
2691     if (ieee_hints) {
2692         ieee_hints->src_pan = packet->src_pan;
2693     }
2694 
2695     /* Source Address */
2696     if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
2697         gchar* src_addr;
2698 
2699         /* Get the address. */
2700         packet->src16 = tvb_get_letohs(tvb, offset);
2701 
2702         if (!PINFO_FD_VISITED(pinfo)) {
2703             /* If we know our extended source address from previous packets,
2704                 * provide a pointer to it in a hint for upper layers */
2705             addr16.addr = packet->src16;
2706             addr16.pan = packet->src_pan;
2707 
2708             if (ieee_hints) {
2709                 ieee_hints->src16 = packet->src16;
2710                 ieee_hints->map_rec = (ieee802154_map_rec *)
2711                     g_hash_table_lookup(ieee802154_map.short_table, &addr16);
2712             }
2713         }
2714 
2715         set_address_tvb(&pinfo->dl_src, ieee802_15_4_short_address_type, 2, tvb, offset);
2716         copy_address_shallow(&pinfo->src, &pinfo->dl_src);
2717         src_addr = address_to_str(pinfo->pool, &pinfo->src);
2718 
2719         /* Add the addressing info to the tree. */
2720         if (tree) {
2721             proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src16, tvb, offset, 2, packet->src16);
2722             proto_item_append_text(proto_root, ", Src: %s", src_addr);
2723             ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_addr16, tvb, offset, 2, packet->src16);
2724             proto_item_set_generated(ti);
2725             proto_item_set_hidden(ti);
2726 
2727             if (ieee_hints && ieee_hints->map_rec) {
2728                 /* Display inferred source address info */
2729                 ti = proto_tree_add_eui64(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 0,
2730                         ieee_hints->map_rec->addr64);
2731                 proto_item_set_generated(ti);
2732                 ti = proto_tree_add_eui64(ieee802154_tree, hf_ieee802154_addr64, tvb, offset, 0, ieee_hints->map_rec->addr64);
2733                 proto_item_set_generated(ti);
2734                 proto_item_set_hidden(ti);
2735 
2736                 if ( ieee_hints->map_rec->start_fnum ) {
2737                     ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src64_origin, tvb, 0, 0,
2738                         ieee_hints->map_rec->start_fnum);
2739                 }
2740                 else {
2741                     ti = proto_tree_add_uint_format_value(ieee802154_tree, hf_ieee802154_src64_origin, tvb, 0, 0,
2742                         ieee_hints->map_rec->start_fnum, "Pre-configured");
2743                 }
2744                 proto_item_set_generated(ti);
2745             }
2746         }
2747 
2748         col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_addr);
2749 
2750         offset += 2;
2751     }
2752     else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
2753         guint64 *p_addr = (guint64 *)wmem_new(pinfo->pool, guint64);
2754 
2755         /* Get the address. */
2756         packet->src64 = tvb_get_letoh64(tvb, offset);
2757 
2758         /* Copy and convert the address to network byte order. */
2759         *p_addr = pntoh64(&(packet->src64));
2760 
2761         /* Display the source address. */
2762         /* XXX - OUI resolution doesn't happen when displaying resolved
2763          * EUI64 addresses; that should probably be fixed in
2764          * epan/addr_resolv.c.
2765          */
2766         set_address(&pinfo->dl_src, AT_EUI64, 8, p_addr);
2767         copy_address_shallow(&pinfo->src, &pinfo->dl_src);
2768         if (tree) {
2769             proto_tree_add_item(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2770             proto_item_append_text(proto_root, ", Src: %s", eui64_to_display(pinfo->pool, packet->src64));
2771             ti = proto_tree_add_item(ieee802154_tree, hf_ieee802154_addr64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2772             proto_item_set_generated(ti);
2773             proto_item_set_hidden(ti);
2774         }
2775 
2776         col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", eui64_to_display(pinfo->pool, packet->src64));
2777         offset += 8;
2778     }
2779 
2780     /* Existence of the Auxiliary Security Header is controlled by the Security Enabled Field */
2781     if ((packet->security_enable) && (packet->version != IEEE802154_VERSION_2003) && !(options & IEEE802154_DISSECT_HEADER_OPTION_NO_AUX_SEC_HDR)) {
2782         dissect_ieee802154_aux_sec_header_and_key(tvb, pinfo, ieee802154_tree, packet, &offset);
2783     }
2784 
2785     /*
2786      * NONPAYLOAD FIELDS
2787      *
2788      */
2789     /* All of the beacon fields, except the beacon payload are considered nonpayload. */
2790     if (((packet->version == IEEE802154_VERSION_2003) || (packet->version == IEEE802154_VERSION_2006)) && (packet->frame_type != IEEE802154_FCF_MULTIPURPOSE)) {
2791         if (packet->frame_type == IEEE802154_FCF_BEACON) { /* Regular Beacon. Some are not present in frame version (Enhanced) Beacons */
2792             dissect_ieee802154_superframe(tvb, pinfo, ieee802154_tree, &offset); /* superframe spec */
2793             dissect_ieee802154_gtsinfo(tvb, pinfo, ieee802154_tree, &offset);    /* GTS information fields */
2794             dissect_ieee802154_pendaddr(tvb, pinfo, ieee802154_tree, &offset);   /* Pending address list */
2795         }
2796 
2797         if (packet->frame_type == IEEE802154_FCF_CMD) {
2798             /**
2799              * In IEEE802.15.4-2003 and 2006 the command identifier is considered to be part of the header
2800              * and is thus not encrypted. For IEEE802.15.4-2012e and later the command id is considered to be
2801              * part of the payload, is encrypted, and follows the payload IEs. Thus we only parse the command id
2802              * here for 2006 and earlier frames. */
2803             packet->command_id = tvb_get_guint8(tvb, offset);
2804             if (tree) {
2805                 proto_tree_add_uint(ieee802154_tree, hf_ieee802154_cmd_id, tvb, offset, 1, packet->command_id);
2806             }
2807             offset++;
2808 
2809             /* Display the command identifier in the info column. */
2810             col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
2811         }
2812     }
2813     else {
2814         if (packet->ie_present) {
2815             offset += dissect_ieee802154_header_ie(tvb, pinfo, ieee802154_tree, offset, packet);
2816         }
2817     }
2818 
2819     /* IEEE 802.15.4-2003 may have security information pre-pended to payload */
2820     if (packet->security_enable && (packet->version == IEEE802154_VERSION_2003)) {
2821         /* Store security suite preference in the 2006 security level identifier to simplify 2003 integration! */
2822         packet->security_level = (ieee802154_security_level)ieee802154_sec_suite;
2823 
2824         /* Frame Counter and Key Sequence Counter prepended to the payload of an encrypted frame */
2825         if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
2826             packet->frame_counter = tvb_get_letohl (tvb, offset);
2827             proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_frame_counter, tvb, offset, (int)sizeof(guint32), packet->frame_counter);
2828             offset += (int)sizeof(guint32);
2829 
2830             packet->key_sequence_counter = tvb_get_guint8 (tvb, offset);
2831             proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_key_sequence_counter, tvb, offset, (int)sizeof(guint8), packet->key_sequence_counter);
2832             offset += (int)sizeof(guint8);
2833         }
2834     }
2835 
2836     return offset;
2837 }
2838 
2839 /*
2840  * XXX - "mhr_len" is really a general offset; this is used elsewhere.
2841  */
2842 tvbuff_t*
ieee802154_decrypt_payload(tvbuff_t * tvb,guint mhr_len,packet_info * pinfo,proto_tree * ieee802154_tree,ieee802154_packet * packet)2843 ieee802154_decrypt_payload(tvbuff_t *tvb, guint mhr_len, packet_info *pinfo, proto_tree *ieee802154_tree, ieee802154_packet *packet)
2844 {
2845     proto_item *proto_root = proto_tree_get_parent(ieee802154_tree);
2846     proto_tree *tree = proto_tree_get_parent_tree(ieee802154_tree);
2847     unsigned char rx_mic[IEEE802154_CIPHER_SIZE];
2848     guint rx_mic_len = IEEE802154_MIC_LENGTH(packet->security_level);
2849     ieee802154_decrypt_status status = DECRYPT_NOT_ENCRYPTED;
2850     tvbuff_t *payload_tvb;
2851 
2852     /* Encrypted Payload. */
2853     if (packet->security_enable) {
2854         ieee802154_decrypt_info_t decrypt_info;
2855 
2856         decrypt_info.rx_mic = rx_mic;
2857         decrypt_info.rx_mic_length = &rx_mic_len;
2858         decrypt_info.status = &status;
2859         decrypt_info.key = NULL; /* payload function will fill that in */
2860 
2861         /* call with NULL tree since we add the key_number below without hiding it */
2862         payload_tvb = decrypt_ieee802154_payload(tvb, mhr_len, pinfo, NULL, packet, &decrypt_info,
2863                                      ieee802154_set_mac_key, dissect_ieee802154_decrypt);
2864 
2865         /* Get the unencrypted data if decryption failed.  */
2866         if (!payload_tvb) {
2867             /* Deal with possible truncation and the MIC field at the end. */
2868             gint reported_len = tvb_reported_length(tvb)-mhr_len-rx_mic_len;
2869             payload_tvb = tvb_new_subset_length(tvb, mhr_len, reported_len);
2870         }
2871 
2872         /* Display the MIC. */
2873         if (rx_mic_len) {
2874             if (tvb_bytes_exist(tvb, tvb_reported_length(tvb) - rx_mic_len, rx_mic_len)) {
2875                 proto_tree_add_item(ieee802154_tree, hf_ieee802154_mic, tvb, tvb_reported_length(tvb)-rx_mic_len, rx_mic_len, ENC_NA);
2876             }
2877         }
2878 
2879         /* Display the reason for failure, and abort if the error was fatal. */
2880         switch (status) {
2881         case DECRYPT_PACKET_SUCCEEDED:
2882         {
2883             proto_item *pi = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_key_number, tvb, 0, 0, decrypt_info.key_number);
2884             proto_item_set_generated(pi);
2885             break;
2886         }
2887         case DECRYPT_NOT_ENCRYPTED:
2888             break;  // nothing to do
2889 
2890         case DECRYPT_FRAME_COUNTER_SUPPRESSION_UNSUPPORTED:
2891             expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "Decryption of 802.15.4-2015 with frame counter suppression is not supported");
2892             call_data_dissector(payload_tvb, pinfo, tree);
2893             return NULL;
2894 
2895         case DECRYPT_PACKET_TOO_SMALL:
2896             expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "Packet was too small to include the CRC and MIC");
2897             call_data_dissector(payload_tvb, pinfo, tree);
2898             return NULL;
2899 
2900         case DECRYPT_PACKET_NO_EXT_SRC_ADDR:
2901             expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "No extended source address - can't decrypt");
2902             call_data_dissector(payload_tvb, pinfo, tree);
2903             return NULL;
2904 
2905         case DECRYPT_PACKET_NO_KEY:
2906             expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "No encryption key set - can't decrypt");
2907             call_data_dissector(payload_tvb, pinfo, tree);
2908             return NULL;
2909 
2910         case DECRYPT_PACKET_DECRYPT_FAILED:
2911             expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "Decrypt failed");
2912             call_data_dissector(payload_tvb, pinfo, tree);
2913             return NULL;
2914 
2915         case DECRYPT_PACKET_MIC_CHECK_FAILED:
2916             expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "MIC check failed");
2917             /*
2918              * Abort only if the payload was encrypted, in which case we
2919              * probably didn't decrypt the packet right (eg: wrong key).
2920              */
2921             if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
2922                 call_data_dissector(payload_tvb, pinfo, tree);
2923                 return NULL;
2924             }
2925             break;
2926         }
2927     }
2928     /* Plaintext Payload. */
2929     else {
2930         /* Deal with possible truncation. */
2931         gint reported_len = tvb_reported_length(tvb)-mhr_len;
2932         payload_tvb = tvb_new_subset_length(tvb, mhr_len, reported_len);
2933     }
2934 
2935     return payload_tvb;
2936 }
2937 
2938 
ieee802154_dissect_payload_ies(tvbuff_t * tvb,packet_info * pinfo,proto_tree * ieee802154_tree,ieee802154_packet * packet)2939 guint ieee802154_dissect_payload_ies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ieee802154_tree, ieee802154_packet *packet)
2940 {
2941     /* Presence of Payload IEs is defined by the termination of the Header IEs */
2942     if (packet->payload_ie_present) {
2943         if (tvb_reported_length(tvb) > 2) {
2944             return (guint) dissect_ieee802154_payload_ie(tvb, pinfo, ieee802154_tree, 0, packet);
2945         } else {
2946             expert_add_info(pinfo, proto_tree_get_parent(ieee802154_tree), &ei_ieee802154_missing_payload_ie);
2947         }
2948     }
2949     return 0;
2950 }
2951 
2952 
ieee802154_dissect_frame_payload(tvbuff_t * tvb,packet_info * pinfo,proto_tree * ieee802154_tree,ieee802154_packet * packet,gboolean fcs_ok)2953 guint ieee802154_dissect_frame_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ieee802154_tree, ieee802154_packet *packet, gboolean fcs_ok)
2954 {
2955     tvbuff_t *payload_tvb = tvb;
2956     proto_tree *tree = proto_tree_get_parent_tree(ieee802154_tree);
2957     heur_dtbl_entry_t *hdtbl_entry;
2958 
2959     /* There are commands without payload */
2960     if (tvb_captured_length(payload_tvb) > 0 || packet->frame_type == IEEE802154_FCF_CMD) {
2961         /*
2962          * Wrap the sub-dissection in a try/catch block in case the payload is
2963          * broken. First we store the current protocol so we can fix it if an
2964          * exception is thrown by the subdissectors.
2965          */
2966         const char* saved_proto = pinfo->current_proto;
2967         /* Try to dissect the payload. */
2968         TRY {
2969             switch (packet->frame_type) {
2970             case IEEE802154_FCF_BEACON:
2971                 if (!dissector_try_heuristic(ieee802154_beacon_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, packet)) {
2972                     /* Could not subdissect, call the data dissector instead. */
2973                     call_data_dissector(payload_tvb, pinfo, tree);
2974                 }
2975                 break;
2976 
2977             case IEEE802154_FCF_CMD:
2978                 dissect_ieee802154_command(payload_tvb, pinfo, ieee802154_tree, packet);
2979                 break;
2980 
2981             case IEEE802154_FCF_DATA:
2982                 /* Sanity-check. */
2983                 if ((!fcs_ok && ieee802154_fcs_ok) || !tvb_reported_length(payload_tvb)) {
2984                     call_data_dissector(payload_tvb, pinfo, tree);
2985                     break;
2986                 }
2987                 /* Try the PANID dissector table for stateful dissection. */
2988                 if (dissector_try_uint_new(panid_dissector_table, packet->src_pan, payload_tvb, pinfo, tree, TRUE, packet)) {
2989                     break;
2990                 }
2991                 /* Try again with the destination PANID (if different) */
2992                 if (((packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) ||
2993                      (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)) &&
2994                         (packet->dst_pan != packet->src_pan) &&
2995                         dissector_try_uint_new(panid_dissector_table, packet->src_pan, payload_tvb, pinfo, tree, TRUE, packet)) {
2996                     break;
2997                 }
2998                 /* Try heuristic dissection. */
2999                 if (dissector_try_heuristic(ieee802154_heur_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, packet)) break;
3000                 /* Fall-through to dump undissectable payloads. */
3001                 /* FALL THROUGH */
3002             default:
3003                 /* Could not subdissect, call the data dissector instead. */
3004                 call_data_dissector(payload_tvb, pinfo, tree);
3005             } /* switch */
3006         }
3007         CATCH_ALL {
3008             /*
3009              * Someone encountered an error while dissecting the payload. But
3010              * we haven't yet finished processing all of our layer. Catch and
3011              * display the exception, then fall-through to finish displaying
3012              * the FCS (which we display last so the frame is ordered correctly
3013              * in the tree).
3014              */
3015             show_exception(payload_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
3016             pinfo->current_proto = saved_proto;
3017         }
3018         ENDTRY;
3019     }
3020     return tvb_captured_length(tvb);
3021 }
3022 
3023 /**
3024  * Dissect the FCS at the end of the frame.
3025  * That is only displayed if the included length of the tvb encompasses it.
3026  *
3027  * @param tvb the 802.15.4 frame tvb
3028  * @param ieee802154_tree the 802.15.4 protocol tree
3029  * @param fcs_len length of the FCS field
3030  * @param fcs_ok set to FALSE to indicate FCS verification failed
3031  */
3032 static void
ieee802154_dissect_fcs(tvbuff_t * tvb,proto_tree * ieee802154_tree,guint fcs_len,gboolean fcs_ok)3033 ieee802154_dissect_fcs(tvbuff_t *tvb, proto_tree *ieee802154_tree, guint fcs_len, gboolean fcs_ok)
3034 {
3035     proto_item *ti;
3036     /* The FCS should be the last bytes of the reported packet. */
3037     guint offset = tvb_reported_length(tvb)-fcs_len;
3038     /* Dissect the FCS only if it exists (captures which don't or can't get the
3039      * FCS will simply truncate the packet to omit it, but should still set the
3040      * reported length to cover the original packet length), so if the snapshot
3041      * is too short for an FCS don't make a fuss.
3042      */
3043     if (ieee802154_tree) {
3044         if (fcs_len == 2) {
3045             guint16     fcs = tvb_get_letohs(tvb, offset);
3046 
3047             ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_fcs, tvb, offset, 2, fcs);
3048             if (fcs_ok) {
3049                 proto_item_append_text(ti, " (Correct)");
3050             }
3051             else {
3052                 proto_item_append_text(ti, " (Incorrect, expected FCS=0x%04x)", ieee802154_crc_tvb(tvb, offset));
3053             }
3054             /* To Help with filtering, add the fcs_ok field to the tree.  */
3055             ti = proto_tree_add_boolean(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, offset, 2, (guint32) fcs_ok);
3056             proto_item_set_hidden(ti);
3057         }
3058         else {
3059             guint32 fcs = tvb_get_letohl(tvb, offset);
3060 
3061             ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_fcs32, tvb, offset, 4, fcs);
3062             if (fcs_ok) {
3063                 proto_item_append_text(ti, " (Correct)");
3064             }
3065             else {
3066                 proto_item_append_text(ti, " (Incorrect, expected FCS=0x%08x)", ieee802154_crc32_tvb(tvb, offset));
3067             }
3068             /* To Help with filtering, add the fcs_ok field to the tree.  */
3069             ti = proto_tree_add_boolean(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, offset, 2, (guint32) fcs_ok);
3070             proto_item_set_hidden(ti);
3071         }
3072     }
3073 } /* ieee802154_dissect_fcs */
3074 
3075 /**
3076  * Dissect the TI CC24xx metadata at the end of the frame.
3077  * That is only displayed if the included length of the tvb encompasses it.
3078  *
3079  * @param tvb the 802.15.4 frame tvb
3080  * @param ieee802154_tree the 802.15.4 protocol tree
3081  * @param fcs_ok set to FALSE to indicate FCS verification failed
3082  */
3083 static void
ieee802154_dissect_cc24xx_metadata(tvbuff_t * tvb,proto_tree * ieee802154_tree,gboolean fcs_ok)3084 ieee802154_dissect_cc24xx_metadata(tvbuff_t *tvb, proto_tree *ieee802154_tree, gboolean fcs_ok)
3085 {
3086     /* The metadata should be the last 2 bytes of the reported packet. */
3087     guint offset = tvb_reported_length(tvb)-2;
3088     /* Dissect the metadata only if it exists (captures which don't or can't get the
3089      * metadata will simply truncate the packet to omit it, but should still set the
3090      * reported length to cover the original packet length), so if the snapshot
3091      * is too short for the metadata don't make a fuss.
3092      */
3093     if (ieee802154_tree) {
3094         proto_tree  *field_tree;
3095         guint16     metadata = tvb_get_letohs(tvb, offset);
3096 
3097         /* Create a subtree for the metadata. */
3098         field_tree = proto_tree_add_subtree_format(ieee802154_tree, tvb, offset, 2, ett_ieee802154_fcs, NULL,
3099                      "TI CC24xx-format metadata: FCS %s", (fcs_ok) ? "OK" : "Bad");
3100         /* Display metadata contents.  */
3101         proto_tree_add_boolean(field_tree, hf_ieee802154_fcs_ok, tvb, offset, 1, (guint32) (metadata & IEEE802154_CC24xx_CRC_OK));
3102         proto_tree_add_int(field_tree, hf_ieee802154_rssi, tvb, offset++, 1, (gint8) (metadata & IEEE802154_CC24xx_RSSI));
3103         proto_tree_add_uint(field_tree, hf_ieee802154_correlation, tvb, offset, 1, (guint8) ((metadata & IEEE802154_CC24xx_CORRELATION) >> 8));
3104     }
3105 } /* ieee802154_dissect_cc24xx_metadata */
3106 
3107 static void
dissect_ieee802154_tap_sun_phy(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint offset,guint length)3108 dissect_ieee802154_tap_sun_phy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint length)
3109 {
3110     (void) pinfo;
3111     if (length == 3) {
3112         guint32 band;
3113         guint32 sun_type;
3114         guint32 mode;
3115         proto_tree_add_item_ret_uint(tree, hf_ieee802154_sun_band, tvb, offset, 1, ENC_LITTLE_ENDIAN, &band);
3116         proto_item_append_text(proto_tree_get_parent(tree), ": Band: %s (%u)", val_to_str_const(band, sun_bands, "Unknown"), band);
3117         proto_tree_add_item_ret_uint(tree, hf_ieee802154_sun_type, tvb, offset+1, 1, ENC_LITTLE_ENDIAN, &sun_type);
3118         if (sun_type < array_length(sun_types)) {
3119             proto_item_append_text(proto_tree_get_parent(tree), ", Type: %s (%u)", val_to_str_const(sun_type, sun_types, "Unknown"), sun_type);
3120         }
3121 
3122         switch (sun_type) {
3123             case IEEE802154_SUN_TYPE_FSK_A:
3124                 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_fsk_a, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3125                 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3126                 break;
3127             case IEEE802154_SUN_TYPE_FSK_B:
3128                 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_fsk_b, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3129                 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3130                 break;
3131             case IEEE802154_SUN_TYPE_OQPSK_A:
3132                 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_oqpsk_a, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3133                 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3134                 break;
3135             case IEEE802154_SUN_TYPE_OQPSK_B:
3136                 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_oqpsk_b, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3137                 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3138                 break;
3139             case IEEE802154_SUN_TYPE_OQPSK_C:
3140                 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_oqpsk_c, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3141                 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3142                 break;
3143             case IEEE802154_SUN_TYPE_OFDM_OPT1:
3144             case IEEE802154_SUN_TYPE_OFDM_OPT2:
3145             case IEEE802154_SUN_TYPE_OFDM_OPT3:
3146             case IEEE802154_SUN_TYPE_OFDM_OPT4:
3147                 proto_tree_add_item_ret_uint(tree, hf_ieee802154_mode_ofdm, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &mode);
3148                 proto_item_append_text(proto_tree_get_parent(tree), ", Mode: %u", mode);
3149                 break;
3150             default:
3151                 proto_tree_add_item(tree, hf_ieee802154_sun_mode, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
3152                 break;
3153         } /* switch (sun_type) */
3154     }
3155 } /* dissect_ieee802154_tap_sun_phy */
3156 
3157 /**
3158  * Create a tree for a TAP TLV
3159  *
3160  * @param tree the tree to append this item to
3161  * @param tvb the tv buffer
3162  * @param offset offset into the tvbuff to begin dissection
3163  * @param type TLV type
3164  * @param length TLV length
3165  * @returns the tree created for the Payload IE
3166  */
3167 static proto_tree*
ieee802154_create_tap_tlv_tree(proto_tree * tree,tvbuff_t * tvb,gint offset,guint32 * type,guint32 * length)3168 ieee802154_create_tap_tlv_tree(proto_tree *tree, tvbuff_t *tvb, gint offset, guint32 *type, guint32 *length)
3169 {
3170     proto_tree *subtree = NULL;
3171     proto_item *ti = NULL;
3172     guint32 subtree_length;
3173 
3174     *length = tvb_get_letohs(tvb, offset+2);
3175 
3176     subtree_length = 4 + *length;
3177     if (*length % 4) {
3178         subtree_length += (4 - *length % 4);
3179     }
3180 
3181     subtree = proto_tree_add_subtree(tree, tvb, offset, subtree_length, ett_ieee802154_tap_tlv, &ti, "");
3182 
3183     /* Check if we have a valid TLV */
3184     proto_tree_add_item_ret_uint(subtree, hf_ieee802154_tap_tlv_type, tvb, offset, 2, ENC_LITTLE_ENDIAN, type);
3185     if (*type < array_length(tap_tlv_types)) {
3186         proto_item_append_text(ti, "%s", val_to_str_const(*type, tap_tlv_types, "Unknown"));
3187     }
3188     else {
3189         expert_add_info(NULL, ti, &ei_ieee802154_tap_tlv_invalid_type);
3190     }
3191 
3192     proto_tree_add_item(subtree, hf_ieee802154_tap_tlv_length, tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
3193     if (!tvb_bytes_exist(tvb, offset+4, *length)) {
3194         expert_add_info(NULL, ti, &ei_ieee802154_tap_tlv_invalid_length);
3195     }
3196     return subtree;
3197 } /* ieee802154_create_tap_tlv_tree */
3198 
3199 static ieee802154_fcs_type_t
dissect_ieee802154_tap_tlvs(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree)3200 dissect_ieee802154_tap_tlvs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3201 {
3202     guint32 type;
3203     guint32 length;
3204     gint offset = 0;
3205     proto_item *ti;
3206     proto_tree *tlvtree;
3207     guint32 tap_fcs_type;
3208     const char *type_str;
3209     nstime_t nstime;
3210     guint64 frame_start_ts = 0;
3211     guint64 frame_end_ts = 0;
3212     guint64 slot_start_ts = 0;
3213     double delta_us = 0;
3214     guint32 timeslot_length = 0;
3215 
3216     /* Default the FCS type to NONE when parsing TAP packets */
3217     tap_fcs_type = IEEE802154_FCS_TYPE_NONE;
3218 
3219     while (tvb_bytes_exist(tvb, offset, 4)) {
3220         tlvtree = ieee802154_create_tap_tlv_tree(tree, tvb, offset, &type, &length);
3221         offset += 4;
3222 
3223         switch (type) {
3224             case IEEE802154_TAP_FCS_TYPE:
3225                 ti = proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_tap_fcs_type, tvb, offset, 1,
3226                                                   ENC_LITTLE_ENDIAN, &tap_fcs_type);
3227                 type_str = try_val_to_str(tap_fcs_type, tap_fcs_type_names);
3228                 if (type_str == NULL) {
3229                     /* Invalid - flag it as such */
3230                     expert_add_info(NULL, ti, &ei_ieee802154_tap_tlv_invalid_fcs_type);
3231 
3232                     /* Use "Unknown" for the parent */
3233                     type_str = "Unknown";
3234                 }
3235                 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %s (%u)",
3236                                        type_str, tap_fcs_type);
3237                 break;
3238             case IEEE802154_TAP_RSS: {
3239                 gfloat rss = tvb_get_ieee_float(tvb, offset, ENC_LITTLE_ENDIAN);
3240                 proto_tree_add_float_format_value(tlvtree, hf_ieee802154_tap_rss, tvb, offset, 4, rss, "%.2f dBm", rss);
3241                 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %.2f dBm", rss);
3242                 break;
3243             }
3244             case IEEE802154_TAP_BIT_RATE: {
3245                 guint32 bitrate;
3246                 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_bit_rate, tvb, offset, 4, ENC_LITTLE_ENDIAN, &bitrate);
3247                 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %.3f kbps", bitrate/1000.0);
3248                 break;
3249             }
3250             case IEEE802154_TAP_CHANNEL_ASSIGNMENT: {
3251                 guint32 channel;
3252                 guint32 page;
3253                 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_ch_num, tvb, offset, 2, ENC_LITTLE_ENDIAN, &channel);
3254                 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_ch_page, tvb, offset+2, 1, ENC_LITTLE_ENDIAN, &page);
3255                 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);
3256                 break;
3257             }
3258             case IEEE802154_TAP_SUN_PHY_INFO:
3259                 dissect_ieee802154_tap_sun_phy(tvb, pinfo, tlvtree, offset, length);
3260                 break;
3261             case IEEE802154_TAP_START_OF_FRAME_TS:
3262                 proto_tree_add_item_ret_uint64(tlvtree, hf_ieee802154_sof_ts, tvb, offset, 8,
3263                                                ENC_LITTLE_ENDIAN, &frame_start_ts);
3264                 nstime.secs = (time_t)frame_start_ts / 1000000000L;
3265                 nstime.nsecs = frame_start_ts % 1000000000UL;
3266                 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %s s", rel_time_to_secs_str(pinfo->pool, &nstime));
3267                 break;
3268             case IEEE802154_TAP_END_OF_FRAME_TS:
3269                 proto_tree_add_item_ret_uint64(tlvtree, hf_ieee802154_eof_ts, tvb, offset, 8,
3270                                     ENC_LITTLE_ENDIAN, &frame_end_ts);
3271                 nstime.secs = (time_t)frame_end_ts / 1000000000L;
3272                 nstime.nsecs = frame_end_ts % 1000000000UL;
3273                 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %s s", rel_time_to_secs_str(pinfo->pool, &nstime));
3274                 break;
3275             case IEEE802154_TAP_ASN:
3276                 proto_tree_add_item_ret_uint64(tlvtree, hf_ieee802154_asn, tvb, offset, 8, ENC_LITTLE_ENDIAN, &ieee802154_tsch_asn);
3277                 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %"G_GUINT64_FORMAT, ieee802154_tsch_asn);
3278                 break;
3279             case IEEE802154_TAP_SLOT_START_TS:
3280                 proto_tree_add_item_ret_uint64(tlvtree, hf_ieee802154_slot_start_ts, tvb, offset, 8,
3281                                     ENC_LITTLE_ENDIAN, &slot_start_ts);
3282                 nstime.secs = (time_t)slot_start_ts / 1000000000L;
3283                 nstime.nsecs = slot_start_ts % 1000000000UL;
3284                 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %s s", rel_time_to_secs_str(pinfo->pool, &nstime));
3285                 break;
3286             case IEEE802154_TAP_TIMESLOT_LENGTH:
3287                 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_tap_timeslot_length, tvb, offset, 4,
3288                                              ENC_LITTLE_ENDIAN, &timeslot_length);
3289                 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %"G_GUINT32_FORMAT" %s", timeslot_length, units_microseconds.singular);
3290                 break;
3291             case IEEE802154_TAP_LQI: {
3292                 guint32 lqi;
3293                 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_tap_lqi, tvb, offset, 1, ENC_LITTLE_ENDIAN, &lqi);
3294                 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %u", lqi);
3295                 break;
3296             }
3297             case IEEE802154_TAP_CHANNEL_FREQUENCY: {
3298                 gfloat freq = tvb_get_ieee_float(tvb, offset, ENC_LITTLE_ENDIAN);
3299                 proto_tree_add_float_format_value(tlvtree, hf_ieee802154_ch_freq, tvb, offset, 4, freq, "%.3f kHz", freq);
3300                 proto_item_append_text(proto_tree_get_parent(tlvtree), ": %.3f kHz", freq);
3301                 break;
3302             }
3303             case IEEE802154_TAP_CHANNEL_PLAN: {
3304                 guint32 count;
3305                 gfloat ch0_freq = tvb_get_ieee_float(tvb, offset, ENC_LITTLE_ENDIAN);
3306                 gfloat spacing = tvb_get_ieee_float(tvb, offset+4, ENC_LITTLE_ENDIAN);
3307                 proto_tree_add_float_format_value(tlvtree, hf_ieee802154_chplan_start, tvb, offset, 4, ch0_freq, "%.3f kHz", ch0_freq);
3308                 proto_item_append_text(proto_tree_get_parent(tlvtree), ": Start %.3f kHz", ch0_freq);
3309                 proto_tree_add_float_format_value(tlvtree, hf_ieee802154_chplan_spacing, tvb, offset+4, 4, spacing, "%.3f kHz", spacing);
3310                 proto_item_append_text(proto_tree_get_parent(tlvtree), ", Spacing %.3f kHz", spacing);
3311                 proto_tree_add_item_ret_uint(tlvtree, hf_ieee802154_chplan_channels, tvb, offset+8, 2, ENC_LITTLE_ENDIAN, &count);
3312                 proto_item_append_text(proto_tree_get_parent(tlvtree), ", Channels %u", count);
3313                 break;
3314             }
3315             default:
3316                 proto_tree_add_item(tlvtree, hf_ieee802154_tap_tlv_unknown, tvb, offset, length, ENC_NA);
3317                 proto_item_append_text(proto_tree_get_parent(tlvtree), "Unknown TLV");
3318                 break;
3319         } /* switch (tlv_type) */
3320 
3321         if (length%4) {
3322             guint32 zero = 0;
3323             GByteArray *padding = g_byte_array_sized_new(4);
3324             ti = proto_tree_add_bytes_item(tlvtree, hf_ieee802154_tap_tlv_padding, tvb, offset+length, 4-length%4, ENC_NA, padding, NULL, NULL);
3325             if (memcmp(&zero, padding->data, 4-length%4)) {
3326                 expert_add_info(NULL, ti, &ei_ieee802154_tap_tlv_padding_not_zeros);
3327             }
3328             g_byte_array_free(padding, TRUE);
3329         }
3330         offset += ROUND_UP(length, 4);
3331     } /* while */
3332 
3333     /* if we have both slot start and frame start timestamp, show frame start offset */
3334     if (slot_start_ts && frame_start_ts) {
3335         delta_us = (double)(frame_start_ts - slot_start_ts) / 1000;
3336         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);
3337         proto_item_set_generated(ti);
3338     }
3339 
3340     /* if we have both start and end frame timestamp, show frame duration */
3341     if (frame_start_ts && frame_end_ts) {
3342         delta_us = (double)(frame_end_ts - frame_start_ts) / 1000;
3343         ti = proto_tree_add_double_format_value(tree, hf_ieee802154_frame_duration, NULL, 0, 0, delta_us, "%.3f %s", delta_us, units_microseconds.singular);
3344         proto_item_set_generated(ti);
3345     }
3346 
3347     /* if we have start of slot, timeslot length, and end of frame timestamp, show frame overflow (+ve) or underflow (-ve) */
3348     if (timeslot_length && frame_end_ts && slot_start_ts) {
3349         /* overflow = frame_end_ts - slot_start_ts - timeslot_length */
3350         delta_us = (double)(frame_end_ts - slot_start_ts) / 1000;
3351         delta_us -= timeslot_length;
3352         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);
3353         proto_item_set_generated(ti);
3354     }
3355 
3356     return (ieee802154_fcs_type_t)tap_fcs_type;
3357 } /* dissect_ieee802154_tap_tlvs */
3358 
3359 /*
3360  * Information Elements Processing (IEs)
3361  */
3362 
3363 /**
3364  * Create a tree for a Payload IE incl. the TLV header and append the IE name to the parent item
3365  *
3366  * @param tvb the tv buffer
3367  * @param tree the tree to append this item to
3368  * @param hf field index
3369  * @param ett tree index
3370  * @returns the tree created for the Payload IE
3371  */
3372 proto_tree*
ieee802154_create_pie_tree(tvbuff_t * tvb,proto_tree * tree,int hf,gint ett)3373 ieee802154_create_pie_tree(tvbuff_t *tvb, proto_tree *tree, int hf, gint ett)
3374 {
3375     proto_item *subitem;
3376     proto_tree *subtree;
3377     header_field_info *hfinfo;
3378     static int * const tlv_fields[] = {
3379             &hf_ieee802154_payload_ie_type,
3380             &hf_ieee802154_payload_ie_id,
3381             &hf_ieee802154_payload_ie_length,
3382             NULL
3383     };
3384 
3385     subitem = proto_tree_add_item(tree, hf, tvb, 0, tvb_reported_length(tvb), ENC_NA);
3386     subtree = proto_item_add_subtree(subitem, ett);
3387     proto_tree_add_bitmask_with_flags(subtree, tvb, 0, hf_ieee802154_payload_ie_tlv, ett_ieee802154_payload_ie_tlv,
3388                                       tlv_fields, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
3389 
3390     hfinfo = proto_registrar_get_nth(hf);
3391     if (hfinfo && hfinfo->name) {
3392         proto_item_append_text(proto_tree_get_parent(tree), ", %s", hfinfo->name);
3393     }
3394     return subtree;
3395 }
3396 
3397 /**
3398  * Create a tree for a Payload Sub-IE incl. the TLV header and append the IE name to the parent item
3399  *
3400  * @param tvb the tv buffer
3401  * @param tree the tree to append this item to
3402  * @param hf field index
3403  * @param ett tree index
3404  * @returns the tree created for the Payload IE
3405  */
3406 static proto_tree*
ieee802154_create_psie_tree(tvbuff_t * tvb,proto_tree * tree,int hf,gint ett)3407 ieee802154_create_psie_tree(tvbuff_t *tvb, proto_tree *tree, int hf, gint ett)
3408 {
3409     proto_item *subitem;
3410     proto_tree *subtree;
3411     header_field_info *hfinfo;
3412 
3413     subitem  = proto_tree_add_item(tree, hf, tvb, 0, tvb_reported_length(tvb), ENC_NA);
3414     subtree = proto_item_add_subtree(subitem, ett);
3415     if (tvb_get_letohs(tvb, 0) & IEEE802154_PSIE_TYPE_MASK) {
3416         static int * const fields_long[] = {
3417             &hf_ieee802154_psie_type,
3418             &hf_ieee802154_psie_id_long,
3419             &hf_ieee802154_psie_length_long,
3420             NULL
3421         };
3422         proto_tree_add_bitmask(subtree, tvb, 0, hf_ieee802154_psie, ett_ieee802154_psie, fields_long, ENC_LITTLE_ENDIAN);
3423     }
3424     else {
3425         static int * const fields_short[] = {
3426             &hf_ieee802154_psie_type,
3427             &hf_ieee802154_psie_id_short,
3428             &hf_ieee802154_psie_length_short,
3429             NULL
3430         };
3431         proto_tree_add_bitmask(subtree, tvb, 0, hf_ieee802154_psie, ett_ieee802154_psie, fields_short, ENC_LITTLE_ENDIAN);
3432     }
3433 
3434     hfinfo = proto_registrar_get_nth(hf);
3435     if (hfinfo && hfinfo->name) {
3436         proto_item_append_text(proto_tree_get_parent(tree), ", %s", hfinfo->name);
3437     }
3438     return subtree;
3439 }
3440 
3441 /**
3442  * Subdissector for the MLME Channel Hopping Payload IE
3443  */
3444 static int
dissect_802154_channel_hopping(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3445 dissect_802154_channel_hopping(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3446 {
3447     proto_tree *subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_tsch_channel_hopping, ett_ieee802154_mlme_payload);
3448 
3449     proto_tree_add_item(subtree, hf_ieee802154_tsch_hopping_sequence_id, tvb, 2, 1, ENC_LITTLE_ENDIAN);
3450 
3451     if (tvb_reported_length_remaining(tvb, 3) > 1) {
3452         /* TODO: There's still a huge amount of optional stuff that could follow */
3453         proto_tree_add_item(subtree, hf_ieee802154_mlme_ie_data, tvb, 3, tvb_reported_length_remaining(tvb, 3), ENC_NA);
3454     }
3455     return tvb_reported_length(tvb);
3456 } /* dissect_802154_channel_hopping */
3457 
3458 /**
3459  * Subdissector for the Nested MLME IE for TSCH Synchronization
3460  */
3461 static int
dissect_802154_tsch_time_sync(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3462 dissect_802154_tsch_time_sync(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3463 {
3464     proto_tree *subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_tsch_sync, ett_ieee802154_tsch_synch);
3465 
3466     proto_tree_add_item(subtree, hf_ieee802154_tsch_asn, tvb, 2, 5, ENC_LITTLE_ENDIAN);
3467     proto_tree_add_item(subtree, hf_ieee802154_tsch_join_metric, tvb, 7, 1, ENC_LITTLE_ENDIAN);
3468     return 8;
3469 }/* dissect_802154_tsch_time_sync*/
3470 
3471 /**
3472  * Subdissector for the Nested MLME IE for TSCH Slotframe and Link
3473  */
3474 static int
dissect_802154_tsch_slotframe_link(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3475 dissect_802154_tsch_slotframe_link(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3476 {
3477     guint8 nb_slotframes;
3478     guint8 slotframe_index;
3479     proto_tree *subtree;
3480     guint offset = 0;
3481 
3482     subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_tsch_slotframe, ett_ieee802154_tsch_slotframe);
3483     offset += 2;
3484 
3485     nb_slotframes = tvb_get_guint8(tvb, offset);
3486     proto_tree_add_item(subtree, hf_ieee802154_tsch_slotf_link_nb_slotf, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3487     offset += 1;
3488 
3489     for (slotframe_index = 1; slotframe_index <= nb_slotframes; slotframe_index++) {
3490         /* Create a tree for the slotframe. */
3491         guint8 nb_links = tvb_get_guint8(tvb, offset + 3);
3492         proto_item *sf_item = proto_tree_add_subtree_format(subtree, tvb, offset, 4 + (5 * nb_links),
3493                                                             ett_ieee802154_tsch_slotframe, NULL,
3494                                                             "Slotframes [%u]", slotframe_index);
3495         proto_tree *sf_tree = proto_item_add_subtree(sf_item, ett_ieee802154_tsch_slotframe_list);
3496         proto_tree_add_item(sf_tree, hf_ieee802154_tsch_slotf_link_slotf_handle, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3497         proto_tree_add_item(sf_tree, hf_ieee802154_tsch_slotf_size, tvb, offset + 1, 2, ENC_LITTLE_ENDIAN);
3498         proto_tree_add_item(sf_tree, hf_ieee802154_tsch_slotf_link_nb_links, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
3499 
3500         /* Create a tree for each link in the slotframe. */
3501         offset += 4;
3502         while (nb_links > 0) {
3503             static int * const fields_options[] = {
3504                 &hf_ieee802154_tsch_slotf_link_options_tx,
3505                 &hf_ieee802154_tsch_slotf_link_options_rx,
3506                 &hf_ieee802154_tsch_slotf_link_options_shared,
3507                 &hf_ieee802154_tsch_slotf_link_options_timkeeping,
3508                 &hf_ieee802154_tsch_slotf_link_options_priority,
3509                 NULL
3510             };
3511 
3512             proto_item  *link_item = proto_tree_add_item(sf_tree, hf_ieee802154_tsch_link_info, tvb, offset, 5, ENC_NA);
3513             proto_tree  *link_tree = proto_item_add_subtree(link_item, ett_ieee802154_tsch_slotframe_link);
3514             proto_tree_add_item(link_tree, hf_ieee802154_tsch_slotf_link_timeslot, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3515             proto_tree_add_item(link_tree, hf_ieee802154_tsch_slotf_link_channel_offset, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
3516             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);
3517             nb_links -= 1;
3518             offset += 5;
3519         }
3520     }
3521 
3522     return offset;
3523 }/* dissect_802154_tsch_slotframe_link */
3524 
3525 /**
3526  * Subdissector for the Nested MLME IE for TSCH Timeslot Description
3527  */
3528 static int
dissect_802154_tsch_timeslot(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3529 dissect_802154_tsch_timeslot(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3530 {
3531     proto_tree *subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_tsch_timeslot, ett_ieee802154_tsch_timeslot);
3532     guint offset = 2;
3533 
3534     proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_id, tvb, 2, 1, ENC_LITTLE_ENDIAN);
3535     offset++;
3536 
3537     if (tvb_reported_length(tvb) > offset) {
3538         const int timeslot_fields[] = {
3539             hf_ieee802154_tsch_timeslot_cca_offset,
3540             hf_ieee802154_tsch_timeslot_cca,
3541             hf_ieee802154_tsch_timeslot_tx_offset,
3542             hf_ieee802154_tsch_timeslot_rx_offset,
3543             hf_ieee802154_tsch_timeslot_rx_ack_delay,
3544             hf_ieee802154_tsch_timeslot_tx_ack_delay,
3545             hf_ieee802154_tsch_timeslot_rx_wait,
3546             hf_ieee802154_tsch_timeslot_ack_wait,
3547             hf_ieee802154_tsch_timeslot_turnaround,
3548             hf_ieee802154_tsch_timeslot_max_ack,
3549         };
3550         unsigned int i;
3551         for (i = 0; i < sizeof(timeslot_fields)/sizeof(timeslot_fields[1]); i++) {
3552             proto_tree_add_item(subtree, timeslot_fields[i], tvb, offset, 2, ENC_LITTLE_ENDIAN);
3553             offset += 2;
3554         }
3555 
3556         /* The last two fields are may have different encodings depending on the length of the IE. */
3557         if (tvb_reported_length_remaining(tvb, offset) > 4) {
3558             proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_max_tx, tvb, offset, 3, ENC_LITTLE_ENDIAN);
3559             offset += 3;
3560             proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_length, tvb, offset, 3, ENC_LITTLE_ENDIAN);
3561             offset += 3;
3562         }
3563         else {
3564             proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_max_tx, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3565             offset += 2;
3566             proto_tree_add_item(subtree, hf_ieee802154_tsch_timeslot_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3567             offset += 2;
3568         }
3569     }
3570     return offset;
3571 } /* dissect_802154_tsch_timeslot */
3572 
3573 /**
3574  * Subdissector for the 6TOP Protocol contained within the Payload Information Elements.
3575  */
3576 static int
dissect_ietf_ie(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * ies_tree,void * data _U_)3577 dissect_ietf_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ies_tree, void *data _U_)
3578 {
3579     const guint8 supported_6p_version = 0x00;
3580 
3581     proto_tree *p_inf_elem_tree = ieee802154_create_pie_tree(tvb, ies_tree, hf_ieee802154_pie_ietf, ett_ieee802154_pie_ietf);
3582     guint      offset = 2;
3583     guint      pie_length = tvb_reported_length(tvb) - 2;
3584     guint8     subie;
3585     guint8     version;
3586     guint8     type;
3587     guint8     code;
3588     guint8     num_cells = 0;
3589     gboolean   have_cell_list = FALSE;
3590     int        i;
3591     proto_item *sixtop_item = NULL;
3592     proto_tree *sixtop_tree = NULL;
3593     proto_item *cell_list_item = NULL;
3594     proto_tree *cell_list_tree = NULL;
3595     proto_item *cell_item = NULL;
3596     proto_tree *cell_tree = NULL;
3597     proto_item *type_item = NULL;
3598     proto_item *code_item = NULL;
3599     const gchar *code_str = NULL;
3600     static int * const cell_options[] = {
3601         &hf_ieee802154_6top_cell_option_tx,
3602         &hf_ieee802154_6top_cell_option_rx,
3603         &hf_ieee802154_6top_cell_option_shared,
3604         &hf_ieee802154_6top_cell_option_reserved,
3605         NULL
3606     };
3607 
3608     if (pie_length < 5) {
3609         return pie_length + 2;
3610     }
3611 
3612     subie = tvb_get_guint8(tvb, offset);
3613     version =  tvb_get_guint8(tvb, offset + 1) & IETF_6TOP_VERSION;
3614 
3615     if (subie != IEEE802154_IETF_SUBIE_6TOP || version != supported_6p_version) {
3616         return pie_length + 2;
3617     }
3618 
3619     type = (tvb_get_guint8(tvb, offset + 1) & IETF_6TOP_TYPE) >> 4;
3620     code = tvb_get_guint8(tvb, offset + 2);
3621 
3622     proto_tree_add_item(p_inf_elem_tree, hf_ieee802154_p_ie_ietf_sub_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3623 
3624     sixtop_item = proto_tree_add_item(p_inf_elem_tree, hf_ieee802154_6top, tvb, offset, pie_length, ENC_NA);
3625     sixtop_tree = proto_item_add_subtree(sixtop_item, ett_ieee802154_p_ie_6top);
3626 
3627     proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_version, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
3628     type_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_type, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
3629     proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_flags_reserved, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
3630     code_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_code, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
3631     proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_sfid, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
3632     proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_seqnum, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
3633 
3634     col_set_str(pinfo->cinfo, COL_PROTOCOL, "6top");
3635     if (type == IETF_6TOP_TYPE_REQUEST) {
3636       code_str = val_to_str_const(code, ietf_6top_command_identifiers,"Unknown");
3637       col_add_fstr(pinfo->cinfo, COL_INFO, "6P %s Request", code_str);
3638     } else {
3639       code_str = val_to_str_const(code, ietf_6top_return_codes,"Unknown");
3640       col_add_fstr(pinfo->cinfo, COL_INFO, "6P %s (%s)",
3641                    val_to_str_const(type, ietf_6top_types,"Unknown"), code_str);
3642     }
3643     proto_item_append_text(code_item, " (%s)", code_str);
3644 
3645     offset += 5;
3646     pie_length -= 5;
3647 
3648     if (type == IETF_6TOP_TYPE_REQUEST) {
3649         switch (code) {
3650         case IETF_6TOP_CMD_ADD:
3651         case IETF_6TOP_CMD_DELETE:
3652         case IETF_6TOP_CMD_RELOCATE:
3653             if (pie_length < 4) {
3654                 break;
3655             }
3656             proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3657             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);
3658             proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_num_cells, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
3659             num_cells = tvb_get_guint8(tvb, offset + 3);
3660             pie_length -= 4;
3661             offset += 4;
3662             if (pie_length > 0 && (pie_length % 4) == 0) {
3663                 have_cell_list = TRUE;
3664             }
3665             break;
3666         case IETF_6TOP_CMD_COUNT:
3667             if (pie_length < 3) {
3668                 break;
3669             }
3670             proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3671             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);
3672             pie_length -= 3;
3673             offset += 3;
3674             break;
3675         case IETF_6TOP_CMD_LIST:
3676             if (pie_length != 8) {
3677                 break;
3678             }
3679             proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3680             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);
3681             proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_reserved, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
3682             proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_offset, tvb, offset + 4, 2, ENC_LITTLE_ENDIAN);
3683             proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_max_num_cells, tvb, offset + 6, 2, ENC_LITTLE_ENDIAN);
3684             pie_length -= 8;
3685             offset += 8;
3686             break;
3687         case IETF_6TOP_CMD_SIGNAL:
3688             if (pie_length < 2) {
3689                 break;
3690             }
3691             proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3692             if (pie_length > 2) {
3693                 proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_payload, tvb, offset + 2, pie_length - 2, ENC_NA);
3694             }
3695             offset += pie_length;
3696             pie_length = 0;
3697             break;
3698         case IETF_6TOP_CMD_CLEAR:
3699             if (pie_length < 2) {
3700                 break;
3701             }
3702             proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3703             pie_length -= 2;
3704             offset += 2;
3705             break;
3706         default:
3707             /* unsupported command */
3708             expert_add_info(pinfo, code_item, &ei_ieee802154_6top_unsupported_command);
3709             break;
3710         }
3711     } else if (type == IETF_6TOP_TYPE_RESPONSE || type == IETF_6TOP_TYPE_CONFIRMATION) {
3712         switch(code) {
3713         case IETF_6TOP_RC_SUCCESS:
3714             if (pie_length > 0) {
3715                 if (pie_length == 2) {
3716                     proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_total_num_cells, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3717                     pie_length -= 2;
3718                     offset += 2;
3719                 } else if ((pie_length % 4) == 0) {
3720                     have_cell_list = TRUE;
3721                 } else {
3722                     proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_payload, tvb, offset, pie_length, ENC_NA);
3723                     offset += pie_length;
3724                     pie_length = 0;
3725                 }
3726             }
3727             break;
3728         case IETF_6TOP_RC_EOL:
3729             if(pie_length > 0 && (pie_length % 4) == 0) {
3730                 have_cell_list = TRUE;
3731             }
3732             break;
3733         case IETF_6TOP_RC_ERR:
3734         case IETF_6TOP_RC_RESET:
3735         case IETF_6TOP_RC_ERR_VERSION:
3736         case IETF_6TOP_RC_ERR_SFID:
3737         case IETF_6TOP_RC_ERR_SEQNUM:
3738         case IETF_6TOP_RC_ERR_CELLLIST:
3739         case IETF_6TOP_RC_ERR_BUSY:
3740         case IETF_6TOP_RC_ERR_LOCKED:
3741             /* They have no other field */
3742             break;
3743         default:
3744             /* unsupported return code */
3745             expert_add_info(pinfo, code_item, &ei_ieee802154_6top_unsupported_return_code);
3746             break;
3747         }
3748     } else {
3749         /* unsupported type */
3750         expert_add_info(pinfo, type_item, &ei_ieee802154_6top_unsupported_type);
3751     }
3752 
3753     if (have_cell_list) {
3754         if (type == IETF_6TOP_TYPE_REQUEST && code == IETF_6TOP_CMD_RELOCATE) {
3755             cell_list_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_rel_cell_list, tvb, offset, pie_length, ENC_NA);
3756             cell_list_tree = proto_item_add_subtree(cell_list_item, ett_ieee802154_p_ie_6top_rel_cell_list);
3757             /* num_cells is expected to be set properly */
3758             for (i = 0; i < num_cells; offset += 4, i++) {
3759                 cell_item = proto_tree_add_item(cell_list_tree, hf_ieee802154_6top_cell, tvb, offset, 4, ENC_NA);
3760                 cell_tree = proto_item_add_subtree(cell_item, ett_ieee802154_p_ie_6top_cell);
3761                 proto_tree_add_item(cell_tree, hf_ieee802154_6top_slot_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3762                 proto_tree_add_item(cell_tree, hf_ieee802154_6top_channel_offset, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
3763             }
3764             pie_length -= num_cells * 4;
3765             cell_list_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_cand_cell_list, tvb, offset, pie_length, ENC_NA);
3766             cell_list_tree = proto_item_add_subtree(cell_list_item, ett_ieee802154_p_ie_6top_cand_cell_list);
3767             for (i = 0; pie_length > 0; pie_length -= 4, offset += 4, i++) {
3768                 cell_item = proto_tree_add_item(cell_list_tree, hf_ieee802154_6top_cell, tvb, offset, 4, ENC_NA);
3769                 cell_tree = proto_item_add_subtree(cell_item, ett_ieee802154_p_ie_6top_cell);
3770                 proto_tree_add_item(cell_tree, hf_ieee802154_6top_slot_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3771                 proto_tree_add_item(cell_tree, hf_ieee802154_6top_channel_offset, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
3772             }
3773         } else {
3774             cell_list_item = proto_tree_add_item(sixtop_tree, hf_ieee802154_6top_cell_list, tvb, offset, pie_length, ENC_NA);
3775             cell_list_tree = proto_item_add_subtree(cell_list_item, ett_ieee802154_p_ie_6top_cell_list);
3776             for (i = 0; pie_length > 0; pie_length -= 4, offset += 4, i++) {
3777                 cell_item = proto_tree_add_item(cell_list_tree, hf_ieee802154_6top_cell, tvb, offset, 4, ENC_NA);
3778                 cell_tree = proto_item_add_subtree(cell_item, ett_ieee802154_p_ie_6top_cell);
3779                 proto_tree_add_item(cell_tree, hf_ieee802154_6top_slot_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3780                 proto_tree_add_item(cell_tree, hf_ieee802154_6top_channel_offset, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
3781             }
3782         }
3783     }
3784 
3785     return offset;
3786 } /* dissect_ieee802154_6top */
3787 
3788 /**
3789  * Subdissector for the Superframe specification sub-field within the beacon frame.
3790  *
3791  * @param tvb pointer to buffer containing raw packet.
3792  * @param pinfo pointer to packet information fields (unused).
3793  * @param tree pointer to command subtree.
3794  * @param offset offset into the tvbuff to begin dissection.
3795  */
3796 void
dissect_ieee802154_superframe(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,guint * offset)3797 dissect_ieee802154_superframe(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
3798 {
3799     static int * const superframe[] = {
3800         &hf_ieee802154_beacon_order,
3801         &hf_ieee802154_superframe_order,
3802         &hf_ieee802154_cap,
3803         &hf_ieee802154_superframe_battery_ext,
3804         &hf_ieee802154_superframe_coord,
3805         &hf_ieee802154_assoc_permit,
3806         NULL
3807     };
3808 
3809     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);
3810     (*offset) += 2;
3811 } /* dissect_ieee802154_superframe */
3812 
3813 /**
3814  * Subdissector for the GTS information fields within the beacon frame.
3815  *
3816  * @param tvb pointer to buffer containing raw packet.
3817  * @param pinfo pointer to packet information fields (unused).
3818  * @param tree pointer to command subtree.
3819  * @param offset offset into the tvbuff to begin dissection.
3820  */
3821 void
dissect_ieee802154_gtsinfo(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,guint * offset)3822 dissect_ieee802154_gtsinfo(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
3823 {
3824     proto_tree *field_tree = NULL;
3825     proto_tree *subtree    = NULL;
3826     proto_item *ti;
3827     guint8      gts_spec;
3828     guint8      gts_count;
3829 
3830     /*  Get and display the GTS specification field */
3831     gts_spec = tvb_get_guint8(tvb, *offset);
3832     gts_count = gts_spec & IEEE802154_GTS_COUNT_MASK;
3833     if (tree) {
3834         /*  Add Subtree for GTS information. */
3835         if (gts_count) {
3836             field_tree = proto_tree_add_subtree(tree, tvb, *offset, 2 + (gts_count * 3), ett_ieee802154_gts, NULL, "GTS");
3837         }
3838         else {
3839             field_tree = proto_tree_add_subtree(tree, tvb, *offset, 1, ett_ieee802154_gts, NULL, "GTS");
3840         }
3841 
3842         proto_tree_add_uint(field_tree, hf_ieee802154_gts_count, tvb, *offset, 1, gts_count);
3843         proto_tree_add_boolean(field_tree, hf_ieee802154_gts_permit, tvb, *offset, 1, gts_spec & IEEE802154_GTS_PERMIT_MASK);
3844     }
3845     (*offset) += 1;
3846 
3847     /* If the GTS descriptor count is nonzero, then the GTS directions mask and descriptor list are present. */
3848     if (gts_count) {
3849         guint8  gts_directions = tvb_get_guint8(tvb, *offset);
3850         guint   gts_rx = 0;
3851         int     i;
3852 
3853         /* Display the directions mask. */
3854         if (tree) {
3855             proto_tree  *dir_tree;
3856 
3857             /* Create a subtree. */
3858             dir_tree = proto_tree_add_subtree(field_tree, tvb, *offset, 1, ett_ieee802154_gts_direction, &ti, "GTS Directions");
3859 
3860             /* Add the directions to the subtree. */
3861             for (i=0; i<gts_count; i++) {
3862                 gboolean    dir = gts_directions & IEEE802154_GTS_DIRECTION_SLOT(i);
3863                 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");
3864                 if (dir) gts_rx++;
3865             } /* for */
3866             proto_item_append_text(ti, ": %i Receive & %i Transmit", gts_rx, gts_count - gts_rx);
3867         }
3868         (*offset) += 1;
3869 
3870         /* Create a subtree for the GTS descriptors. */
3871         subtree = proto_tree_add_subtree(field_tree, tvb, *offset, gts_count * 3, ett_ieee802154_gts_descriptors, NULL, "GTS Descriptors");
3872 
3873         /* Get and display the GTS descriptors. */
3874         for (i=0; i<gts_count; i++) {
3875             guint16 gts_addr        = tvb_get_letohs(tvb, (*offset));
3876             guint8  gts_slot        = tvb_get_guint8(tvb, (*offset)+2);
3877             guint8  gts_length      = (gts_slot & IEEE802154_GTS_LENGTH_MASK) >> IEEE802154_GTS_LENGTH_SHIFT;
3878 
3879             gts_slot = (gts_slot & IEEE802154_GTS_SLOT_MASK);
3880 
3881             if (tree) {
3882                 /* Add address, slot, and time length fields. */
3883                 ti = proto_tree_add_uint(subtree, hf_ieee802154_gts_address, tvb, (*offset), 3, gts_addr);
3884                 proto_item_append_text(ti, ", Slot: %i", gts_slot);
3885                 proto_item_append_text(ti, ", Length: %i", gts_length);
3886             }
3887             (*offset) += 3;
3888         } /* for */
3889     }
3890 } /* dissect_ieee802154_gtsinfo */
3891 
3892 /**
3893  * Subdissector for the pending address list fields within the beacon frame.
3894  *
3895  * @param tvb pointer to buffer containing raw packet.
3896  * @param pinfo pointer to packet information fields (unused).
3897  * @param tree pointer to command subtree.
3898  * @param offset into the tvbuff to begin dissection.
3899  */
3900 void
dissect_ieee802154_pendaddr(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,guint * offset)3901 dissect_ieee802154_pendaddr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
3902 {
3903     proto_tree *subtree;
3904     guint8      pend_spec;
3905     guint8      pend_num16;
3906     guint8      pend_num64;
3907     int         i;
3908 
3909     /*  Get the Pending Addresses specification fields */
3910     pend_spec = tvb_get_guint8(tvb, *offset);
3911     pend_num16 = pend_spec & IEEE802154_PENDADDR_SHORT_MASK;
3912     pend_num64 = (pend_spec & IEEE802154_PENDADDR_LONG_MASK) >> IEEE802154_PENDADDR_LONG_SHIFT;
3913 
3914     /*  Add Subtree for the addresses */
3915     subtree = proto_tree_add_subtree_format(tree, tvb, *offset, 1 + 2*pend_num16 + 8*pend_num64,
3916                         ett_ieee802154_pendaddr, NULL, "Pending Addresses: %i Short and %i Long", pend_num16, pend_num64);
3917     (*offset) += 1;
3918 
3919     for (i=0; i<pend_num16; i++) {
3920         guint16 addr = tvb_get_letohs(tvb, *offset);
3921         proto_tree_add_uint(subtree, hf_ieee802154_pending16, tvb, *offset, 2, addr);
3922         (*offset) += 2;
3923     } /* for */
3924     for (i=0; i<pend_num64; i++) {
3925         proto_tree_add_item(subtree, hf_ieee802154_pending64, tvb, *offset, 8, ENC_LITTLE_ENDIAN);
3926         (*offset) += 8;
3927     } /* for */
3928 } /* dissect_ieee802154_pendaddr */
3929 
3930 /*
3931  * Header IEs
3932  */
3933 
3934 /**
3935  * Create a tree for a Header IE incl. the TLV header and append the IE name to the parent item
3936  *
3937  * @param tvb the tv buffer
3938  * @param tree the tree to append this item to
3939  * @param hf field index
3940  * @param ett tree index
3941  * @returns the tree created for the Header IE
3942  */
3943 proto_tree*
ieee802154_create_hie_tree(tvbuff_t * tvb,proto_tree * tree,int hf,gint ett)3944 ieee802154_create_hie_tree(tvbuff_t *tvb, proto_tree *tree, int hf, gint ett)
3945 {
3946     proto_item *subitem;
3947     proto_tree *subtree;
3948     header_field_info *hfinfo;
3949     static int * const tlv_fields[] = {
3950             &hf_ieee802154_header_ie_type,
3951             &hf_ieee802154_header_ie_id,
3952             &hf_ieee802154_header_ie_length,
3953             NULL
3954     };
3955 
3956     subitem = proto_tree_add_item(tree, hf, tvb, 0, tvb_reported_length(tvb), ENC_NA);
3957     subtree = proto_item_add_subtree(subitem, ett);
3958     proto_tree_add_bitmask_with_flags(subtree, tvb, 0, hf_ieee802154_header_ie_tlv, ett_ieee802154_header_ie_tlv,
3959                                       tlv_fields, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
3960 
3961     hfinfo = proto_registrar_get_nth(hf);
3962     if (hfinfo && hfinfo->name) {
3963         proto_item_append_text(proto_tree_get_parent(tree), ", %s", hfinfo->name);
3964     }
3965     return subtree;
3966 }
3967 
3968 /*
3969  * The dissectors for the individual Header IEs
3970  * They are called via call_dissector with the tvb including the IE header and data as ieee802154_packet
3971  */
3972 
3973 /**
3974  * Dissect the CSL IE (7.4.2.3)
3975  */
3976 static int
dissect_hie_csl(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)3977 dissect_hie_csl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
3978 {
3979     proto_tree *subtree = ieee802154_create_hie_tree(tvb, tree, hf_ieee802154_hie_csl, ett_ieee802154_hie_csl);
3980     proto_tree_add_item(subtree, hf_ieee802154_hie_csl_phase, tvb, 2, 2, ENC_LITTLE_ENDIAN);
3981     proto_tree_add_item(subtree, hf_ieee802154_hie_csl_period, tvb, 4, 2, ENC_LITTLE_ENDIAN);
3982     if (tvb_reported_length(tvb) >= 8) {
3983         proto_tree_add_item(subtree, hf_ieee802154_hie_csl_rendezvous_time, tvb, 6, 2, ENC_LITTLE_ENDIAN);
3984         return 2 + 6;
3985     }
3986     return 2 + 4;
3987 }
3988 
3989 /**
3990  * Dissect the Time Correction Header IE (7.4.2.7)
3991  *
3992  * This field is constructed by taking a signed 16-bit 2's compliment time
3993  * correction in the range of -2048 us to 2047 us, AND'ing it with 0xfff, and
3994  * OR'ing again with 0x8000 to indicate a negative acknowledgment.
3995  */
3996 static int
dissect_hie_time_correction(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * ies_tree,void * data _U_)3997 dissect_hie_time_correction(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ies_tree, void *data _U_)
3998 {
3999     static int * const fields[] = {
4000             &hf_ieee802154_hie_time_correction_value,
4001             &hf_ieee802154_nack,
4002             NULL
4003     };
4004     proto_tree *tree = ieee802154_create_hie_tree(tvb, ies_tree, hf_ieee802154_hie_time_correction, ett_ieee802154_hie_time_correction);
4005     guint16 time_sync_value = tvb_get_letohs(tvb, 2);
4006     proto_tree_add_bitmask_with_flags(tree, tvb, 2, hf_ieee802154_hie_time_correction_time_sync_info, ett_ieee802154_header_ie,
4007                                       fields, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
4008 
4009     if (time_sync_value & ~(0x8fff)) {
4010         expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802154_time_correction_error);
4011     }
4012     if (time_sync_value & 0x8000) {
4013         proto_item_append_text(proto_tree_get_parent(ies_tree), ": NACK");
4014     }
4015     return 2 + 2;
4016 }
4017 
4018 static int
dissect_hie_global_time(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4019 dissect_hie_global_time(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
4020 {
4021     proto_tree *subtree = ieee802154_create_hie_tree(tvb, tree, hf_ieee802154_hie_global_time, ett_ieee802154_hie_global_time);
4022     proto_tree_add_item(subtree, hf_ieee802154_hie_global_time_value, tvb, 2, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
4023     return 2 + 4;
4024 }
4025 
4026 /**
4027  * Dissect the Vendor Specific IE (7.4.2.2)
4028  */
4029 static int
dissect_hie_vendor_specific(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4030 dissect_hie_vendor_specific(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
4031 {
4032     proto_tree *subtree = ieee802154_create_hie_tree(tvb, tree, hf_ieee802154_hie_vendor_specific,
4033                                                                 ett_ieee802154_hie_vendor_specific);
4034 
4035     guint hie_length = tvb_reported_length(tvb) - 2;
4036     guint      offset = 2;
4037 
4038     tvb_get_letoh24(tvb, offset);
4039     proto_tree_add_item(subtree, hf_ieee802154_hie_vendor_specific_vendor_oui, tvb, offset, 3, ENC_LITTLE_ENDIAN);
4040     offset += 3; /* adjust for vendor OUI */
4041     hie_length -= 3;
4042 
4043     proto_tree_add_item(subtree, hf_ieee802154_hie_vendor_specific_content, tvb, offset, hie_length, ENC_NA);
4044 
4045     return tvb_reported_length(tvb);
4046 }
4047 
4048 /**
4049  * Subdissector for Header IEs (Information Elements)
4050  *
4051  * Since the header is never encrypted and the payload may be encrypted,
4052  * we dissect header and payload IEs separately.
4053  * The termination of the Header IE tells us whether there are any
4054  * payload IEs to follow.
4055  *
4056  * @param tvb the tv buffer
4057  * @param pinfo pointer to packet information fields.
4058  * @param tree the tree to append this item to
4059  * @param orig_offset offset into the tvbuff to begin dissection.
4060  * @param packet IEEE 802.15.4 packet information.
4061  */
4062 static int
dissect_ieee802154_header_ie(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint orig_offset,ieee802154_packet * packet)4063 dissect_ieee802154_header_ie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint orig_offset, ieee802154_packet *packet)
4064 {
4065     // GCC emits a spurious -Wclobbered if offset is used as function parameter (even with volatile)
4066     volatile guint offset = orig_offset;
4067     proto_item *ies_item = proto_tree_add_item(tree, hf_ieee802154_header_ies, tvb, offset, -1, ENC_NA);
4068     proto_tree *ies_tree = proto_item_add_subtree(ies_item, ett_ieee802154_header_ie);
4069     volatile gint remaining = tvb_reported_length_remaining(tvb, offset) - IEEE802154_MIC_LENGTH(packet->security_level);
4070 
4071     // Loop as long as we don't:
4072     //
4073     // 1) run out of data;
4074     // 2) get a header termination IE.
4075     //
4076     // See Table 9-6 "Termination IE inclusion rules" of IEEE Std 802.15.4-2015;
4077     // unless we have no payload IEs and no payload data, we *have* to have
4078     // a header termination IE to end the list of header IEs, so the "run out
4079     // of data" check needs only to check whether there's any data
4080     // left in the tvbuff (which has already had the FCS removed from
4081     // it), other than a MIC if present - if we have no payload IEs or
4082     // payload data, there might still be a MIC to Check the Message
4083     // Integrity.
4084     //
4085     // XXX - we should make sure we have enough data left for an IE header,
4086     // and report a malformed frame if not, and if we do have enough data,
4087     // make sure we have enough data for the full IE, and report a malformed
4088     // frame if not.
4089     do {
4090         volatile int consumed = 0;
4091         guint16 ie_header = tvb_get_letohs(tvb, offset);
4092         guint16 id = (guint16) ((ie_header & IEEE802154_HEADER_IE_ID_MASK) >> 7);
4093         guint16 length = (guint16) (ie_header & IEEE802154_HEADER_IE_LENGTH_MASK);
4094         tvbuff_t *ie_tvb = tvb_new_subset_length(tvb, offset, 2 + length);
4095 
4096         if (id == IEEE802154_HEADER_IE_HT1 || id == IEEE802154_HEADER_IE_HT2) {
4097             int hf_term_ie = (id == IEEE802154_HEADER_IE_HT1) ? hf_ieee802154_hie_ht1 : hf_ieee802154_hie_ht2;
4098             ieee802154_create_hie_tree(ie_tvb, ies_tree, hf_term_ie, ett_ieee802154_hie_ht);
4099             consumed = 2;
4100         } else {
4101             TRY {
4102                 consumed = dissector_try_uint_new(header_ie_dissector_table, id, ie_tvb, pinfo, ies_tree, FALSE, packet);
4103                 if (consumed == 0) {
4104                     proto_tree *subtree = ieee802154_create_hie_tree(ie_tvb, ies_tree, hf_ieee802154_hie_unsupported,
4105                                                                 ett_ieee802154_hie_unsupported);
4106                     proto_tree_add_item(subtree, hf_ieee802154_ie_unknown_content, ie_tvb, 2, length, ENC_NA);
4107                     consumed = 2 + length;
4108                     if (ie_header & IEEE802154_PAYLOAD_IE_TYPE_MASK) {
4109                         expert_add_info(pinfo, ies_tree, &ei_ieee802154_payload_ie_in_header);
4110                     } else {
4111                         expert_add_info(pinfo, ies_tree, &ei_ieee802154_ie_unsupported_id);
4112                     }
4113                 }
4114             }
4115             CATCH_ALL {
4116                 show_exception(tvb, pinfo, ies_tree, EXCEPT_CODE, GET_MESSAGE);
4117                 consumed = 2 + length;
4118             }
4119             ENDTRY;
4120         }
4121 
4122         if (consumed < 2 + length) {
4123             proto_tree_add_item(ies_tree, hf_ieee802154_ie_unknown_content, ie_tvb, consumed, 2 + length - consumed, ENC_NA);
4124             expert_add_info(pinfo, ies_item, &ei_ieee802154_ie_unknown_extra_content);
4125         }
4126 
4127         offset += 2 + length;
4128         remaining -= 2 + length;
4129 
4130         if (id == IEEE802154_HEADER_IE_HT1 || id == IEEE802154_HEADER_IE_HT2) {
4131             packet->payload_ie_present = (id == IEEE802154_HEADER_IE_HT1);
4132             break;
4133         }
4134     } while (remaining > 0);
4135 
4136     proto_item_set_len(ies_item, offset - orig_offset);
4137     return offset - orig_offset;
4138 }
4139 
4140 static int
dissect_802154_eb_filter(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data _U_)4141 dissect_802154_eb_filter(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
4142 {
4143     guint8  filter;
4144     guint8  attr_len;
4145     proto_tree *subtree;
4146     guint offset = 0;
4147 
4148     static int * const fields_eb_filter[] = {
4149         &hf_ieee802154_psie_eb_filter_pjoin,
4150         &hf_ieee802154_psie_eb_filter_lqi,
4151         &hf_ieee802154_psie_eb_filter_percent,
4152         &hf_ieee802154_psie_eb_filter_attr_id,
4153         /* reserved 5-7 */
4154         NULL
4155     };
4156 
4157     subtree = ieee802154_create_psie_tree(tvb, tree, hf_ieee802154_psie_eb_filter, ett_ieee802154_eb_filter);
4158     offset += 2;
4159 
4160     filter = tvb_get_guint8(tvb, offset);
4161     proto_tree_add_bitmask(subtree, tvb, offset, hf_ieee802154_psie_eb_filter,
4162                            ett_ieee802154_eb_filter_bitmap, fields_eb_filter, ENC_NA);
4163     offset++;
4164 
4165     if (filter & IEEE802154_MLME_PSIE_EB_FLT_LQI) {
4166         proto_tree_add_item(subtree, hf_ieee802154_psie_eb_filter_lqi_min, tvb, offset, 1, ENC_NA);
4167         offset++;
4168     }
4169 
4170     if (filter & IEEE802154_MLME_PSIE_EB_FLT_PERCENT) {
4171         proto_tree_add_item(subtree, hf_ieee802154_psie_eb_filter_percent_prob, tvb, offset, 1, ENC_NA);
4172         offset++;
4173     }
4174 
4175     attr_len = (guint8) ((filter & IEEE802154_MLME_PSIE_EB_FLT_ATTR_LEN) >> 3);
4176     if (attr_len) {
4177         /* just display in hex until we know how to decode */
4178         proto_tree_add_item(subtree, hf_ieee802154_psie_eb_filter_attr_id_bitmap, tvb, offset, attr_len, ENC_LITTLE_ENDIAN);
4179         offset += attr_len;
4180     }
4181 
4182     return offset;
4183 }
4184 
4185 /**
4186  * Subdissector for MLME IEs
4187  */
4188 static int
dissect_pie_mlme(tvbuff_t * tvb,packet_info * pinfo,proto_tree * ies_tree,void * data)4189 dissect_pie_mlme(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ies_tree, void *data)
4190 {
4191     proto_tree *tree = ieee802154_create_pie_tree(tvb, ies_tree, hf_ieee802154_mlme, ett_ieee802154_mlme);
4192     volatile guint offset = 2;
4193 
4194     while (tvb_reported_length_remaining(tvb, offset) > 1) {
4195         guint16             psie_ie = tvb_get_letohs(tvb, offset);
4196         volatile guint16    psie_id;
4197         tvbuff_t *volatile  psie_tvb;
4198 
4199         if (psie_ie & IEEE802154_PSIE_TYPE_MASK) {
4200             /* long format: Table 7-17-Sub-ID allocation for long format */
4201             psie_id  = (guint16) ((psie_ie & IEEE802154_PSIE_ID_MASK_LONG) >> 11);
4202             psie_tvb = tvb_new_subset_length(tvb, offset, (psie_ie & IEEE802154_PSIE_LENGTH_MASK_LONG) + 2);
4203         }
4204         else {
4205             /* short format: Table 7-16-Sub-ID allocation for short format */
4206             psie_id  = (guint16) ((psie_ie & IEEE802154_PSIE_ID_MASK_SHORT) >> 8);
4207             psie_tvb = tvb_new_subset_length(tvb, offset, (psie_ie & IEEE802154_PSIE_LENGTH_MASK_SHORT) + 2);
4208         }
4209         offset += tvb_reported_length(psie_tvb);
4210 
4211         /* Pass the tvb off to a subdissector. */
4212         TRY {
4213             guint consumed = dissector_try_uint_new(mlme_ie_dissector_table, psie_id, psie_tvb, pinfo, tree, FALSE, data);
4214             if (consumed == 0) {
4215                 proto_tree *subtree = ieee802154_create_psie_tree(psie_tvb, tree, hf_ieee802154_mlme_ie_unsupported, ett_ieee802154_mlme_unsupported);
4216                 if (tvb_reported_length(psie_tvb) > 2) {
4217                     proto_tree_add_item(subtree, hf_ieee802154_mlme_ie_data, psie_tvb, 2, -1, ENC_NA);
4218                 }
4219                 expert_add_info(pinfo, subtree, &ei_ieee802154_ie_unsupported_id);
4220             }
4221         }
4222         CATCH_ALL {
4223             show_exception(tvb, pinfo, ies_tree, EXCEPT_CODE, GET_MESSAGE);
4224         }
4225         ENDTRY;
4226     }
4227     return offset;
4228 }
4229 
4230 /**
4231  * Subdissector for MPX IEs (IEEE 802.15.9)
4232  */
4233 static int
dissect_mpx_ie(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * ies_tree,void * data _U_)4234 dissect_mpx_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ies_tree, void *data _U_)
4235 {
4236     static int * const fields[] = {
4237             &hf_ieee802159_mpx_transaction_id,
4238             &hf_ieee802159_mpx_transfer_type,
4239             NULL
4240     };
4241     static int * const fields_compressed_multiplex_id[] = {
4242             &hf_ieee802159_mpx_transaction_id_as_multiplex_id,
4243             &hf_ieee802159_mpx_transfer_type,
4244             NULL
4245     };
4246 
4247     proto_tree *tree = ieee802154_create_pie_tree(tvb, ies_tree, hf_ieee802159_mpx, ett_ieee802159_mpx);
4248     guint offset = 2;
4249     guint8 transaction_control = tvb_get_guint8(tvb, offset);
4250     guint8 transfer_type = (guint8) (transaction_control & IEEE802159_MPX_TRANSFER_TYPE_MASK);
4251     guint8 transaction_id = (guint8) ((transaction_control & IEEE802159_MPX_TRANSACTION_ID_MASK) >> IEEE802159_MPX_TRANSACTION_ID_SHIFT);
4252     gint32 multiplex_id = -1;
4253     guint8 fragment_number;
4254 
4255     if (transfer_type == IEEE802159_MPX_FULL_FRAME_NO_MUXID) {
4256         proto_tree_add_bitmask_with_flags(tree, tvb, offset, hf_ieee802159_mpx_transaction_control, ett_ieee802159_mpx_transaction_control,
4257                                fields_compressed_multiplex_id, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
4258         multiplex_id = transaction_id;
4259     } else {
4260         proto_tree_add_bitmask_with_flags(tree, tvb, offset, hf_ieee802159_mpx_transaction_control, ett_ieee802159_mpx_transaction_control,
4261                                fields, ENC_LITTLE_ENDIAN, BMT_NO_FLAGS);
4262     }
4263     offset += 1;
4264 
4265     switch (transfer_type) {  // cf. IEEE 802.15.9 Table 18 - Summary of different MPX IE formats
4266         case IEEE802159_MPX_FULL_FRAME:
4267             multiplex_id = tvb_get_letohs(tvb, offset);
4268             proto_tree_add_uint_format_value(tree, hf_ieee802159_mpx_multiplex_id, tvb, offset, 2, multiplex_id, "%s (0x%04x)",
4269                 val_to_str_const(multiplex_id, (multiplex_id > 1500) ? etype_vals : mpx_multiplex_id_vals, "Unknown"), multiplex_id);
4270             offset += 2;
4271             break;
4272         case IEEE802159_MPX_FULL_FRAME_NO_MUXID:
4273             break;  // nothing to do
4274         case IEEE802159_MPX_NON_LAST_FRAGMENT:
4275             fragment_number = tvb_get_guint8(tvb, offset);
4276             proto_tree_add_item(tree, hf_ieee802159_mpx_fragment_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4277             offset += 1;
4278             if (fragment_number == 0) {
4279                 proto_tree_add_item(tree, hf_ieee802159_mpx_total_frame_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4280                 offset += 2;
4281                 multiplex_id = tvb_get_letohs(tvb, offset);
4282                 proto_tree_add_item(tree, hf_ieee802159_mpx_multiplex_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4283                 offset += 2;
4284             }
4285             break;
4286         case IEEE802159_MPX_LAST_FRAGMENT:
4287             proto_tree_add_item(tree, hf_ieee802159_mpx_fragment_number, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4288             offset += 1;
4289             break;
4290         case IEEE802159_MPX_ABORT:
4291             if (tvb_reported_length_remaining(tvb, offset) == 2) {
4292                 proto_tree_add_item(tree, hf_ieee802159_mpx_total_frame_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4293                 offset += 2;
4294             }
4295             return offset;
4296         default:  // reserved values -> warning and return
4297             expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_invalid_transfer_type);
4298             return offset;
4299     }
4300 
4301     // TODO: reassembly
4302 
4303     dissector_handle_t dissector = NULL;
4304 
4305     if (multiplex_id == IEEE802159_MPX_MULTIPLEX_ID_KMP) {
4306         guint8 kmp_id = tvb_get_guint8(tvb, offset);
4307         proto_tree_add_item(tree, hf_ieee802159_mpx_kmp_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4308         offset += 1;
4309         switch (kmp_id) {
4310             case IEEE802159_MPX_KMP_ID_IEEE8021X:
4311             case IEEE802159_MPX_KMP_ID_IEEE80211_4WH:
4312             case IEEE802159_MPX_KMP_ID_IEEE80211_GKH:
4313                 dissector = eapol_handle;
4314                 break;
4315 
4316             // TODO
4317             case IEEE802159_MPX_KMP_ID_HIP:
4318             case IEEE802159_MPX_KMP_ID_IKEV2:
4319             case IEEE802159_MPX_KMP_ID_PANA:
4320             case IEEE802159_MPX_KMP_ID_DRAGONFLY:
4321             case IEEE802159_MPX_KMP_ID_ETSI_TS_102_887_2:
4322                 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_unsupported_kmp);
4323                 break;
4324 
4325             case IEEE802159_MPX_KMP_ID_VENDOR_SPECIFIC:
4326                 proto_tree_add_item(tree, hf_ieee802159_mpx_kmp_vendor_oui, tvb, offset, 3, ENC_BIG_ENDIAN);
4327                 offset += 3;
4328                 break;
4329 
4330             // Unknown
4331             default:
4332                 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_unknown_kmp);
4333         }
4334     }
4335     else if (multiplex_id == IEEE802159_MPX_MULTIPLEX_ID_WISUN) {
4336         guint8 subid = tvb_get_guint8(tvb, offset);
4337         proto_tree_add_item(tree, hf_ieee802159_mpx_wisun_subid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4338         offset += 1;
4339         switch (subid) {
4340             case IEEE802159_MPX_WISUN_SUBID_6LOWPAN:
4341                 dissector = lowpan_handle;
4342                 break;
4343 
4344             case IEEE802159_MPX_WISUN_SUBID_SECURITY:
4345                 dissector = wisun_sec_handle;
4346                 break;
4347 
4348             case IEEE802159_MPX_WISUN_SUBID_MHDS:
4349                 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_unsupported_kmp);
4350                 break;
4351 
4352             default:
4353                 expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_ieee802159_mpx_unknown_kmp);
4354                 break;
4355         }
4356     }
4357     else if (multiplex_id > 1500) {
4358         dissector = dissector_get_uint_handle(ethertype_table, (guint)multiplex_id);
4359     }
4360 
4361     if (transfer_type == IEEE802159_MPX_FULL_FRAME || transfer_type == IEEE802159_MPX_FULL_FRAME_NO_MUXID) {
4362         tvbuff_t * payload = tvb_new_subset_remaining(tvb, offset);
4363         if (dissector) {
4364             call_dissector(dissector, payload, pinfo, proto_tree_get_root(tree));  // exceptions are caught in our caller
4365         } else {
4366             call_data_dissector(payload, pinfo, proto_tree_get_root(tree));
4367         }
4368     } else {
4369         proto_tree_add_item(tree, hf_ieee802159_mpx_fragment, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA);
4370     }
4371     offset = tvb_reported_length(tvb);
4372 
4373     return offset;
4374 }
4375 
4376 /**
4377  * Subdissector for Vendor Specific Payload IEs (Information Elements)
4378  */
4379 static int
dissect_pie_vendor(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * ies_tree,void * data _U_)4380 dissect_pie_vendor(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ies_tree, void *data _U_)
4381 {
4382     proto_tree *tree = ieee802154_create_pie_tree(tvb, ies_tree, hf_ieee802154_pie_vendor, ett_ieee802154_pie_vendor);
4383 
4384     guint      offset = 2;
4385     guint      pie_length = tvb_reported_length(tvb) - 2;
4386     tvbuff_t  *next_tvb;
4387     guint32    vendor_oui;
4388 
4389     vendor_oui = tvb_get_letoh24(tvb, offset);
4390     proto_tree_add_item(tree, hf_ieee802154_pie_vendor_oui, tvb, offset, 3, ENC_LITTLE_ENDIAN);
4391     offset += 3; /* adjust for vendor OUI */
4392     pie_length -= 3;
4393     next_tvb = tvb_new_subset_length(tvb, offset, pie_length);
4394 
4395     switch (vendor_oui) {
4396         case OUI_ZIGBEE:
4397             call_dissector_with_data(zigbee_ie_handle, next_tvb, pinfo, tree, &pie_length);
4398             break;
4399 
4400         default:
4401             call_data_dissector(next_tvb, pinfo, tree);
4402             break;
4403     }
4404 
4405     return tvb_reported_length(tvb);
4406 }
4407 
4408 /**
4409  * Subdissector for Payload IEs (Information Elements)
4410  *
4411  * @param tvb the tv buffer
4412  * @param pinfo pointer to packet information fields.
4413  * @param tree the tree to append this item to
4414  * @param orig_offset offset into the tvbuff to begin dissection.
4415  * @param packet IEEE 802.15.4 packet information.
4416 */
4417 static int
dissect_ieee802154_payload_ie(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,guint orig_offset,ieee802154_packet * packet)4418 dissect_ieee802154_payload_ie(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint orig_offset, ieee802154_packet *packet)
4419 {
4420     // GCC emits a spurious -Wclobbered if offset is used as function parameter (even with volatile)
4421     volatile guint offset = orig_offset;
4422     proto_item *ies_item = proto_tree_add_item(tree, hf_ieee802154_payload_ies, tvb, offset, -1, ENC_NA);
4423     proto_tree *ies_tree = proto_item_add_subtree(ies_item, ett_ieee802154_payload_ie);
4424 
4425     do {
4426         volatile int consumed = 0;
4427         guint16 ie_header = tvb_get_letohs(tvb, offset);
4428         guint16 id = (guint16) ((ie_header & IEEE802154_PAYLOAD_IE_ID_MASK) >> 11);
4429         volatile guint16 length = (guint16) (ie_header & IEEE802154_PAYLOAD_IE_LENGTH_MASK);
4430         tvbuff_t *ie_tvb = tvb_new_subset_length(tvb, offset, 2 + length);
4431 
4432         if (id == IEEE802154_PAYLOAD_IE_TERMINATION) {
4433             ieee802154_create_pie_tree(ie_tvb, ies_tree, hf_ieee802154_pie_termination, ett_ieee802154_pie_termination);
4434             consumed = 2;
4435         } else {
4436             TRY {
4437                 consumed = dissector_try_uint_new(payload_ie_dissector_table, id, ie_tvb, pinfo, ies_tree, FALSE, packet);
4438                 if (consumed == 0) {
4439                     proto_tree *subtree = ieee802154_create_pie_tree(ie_tvb, ies_tree, hf_ieee802154_pie_unsupported,
4440                                                                  ett_ieee802154_pie_unsupported);
4441                     proto_tree_add_item(subtree, hf_ieee802154_ie_unknown_content, ie_tvb, 2, length, ENC_NA);
4442                     consumed = 2 + length;
4443                     expert_add_info(pinfo, proto_tree_get_parent(subtree), &ei_ieee802154_ie_unsupported_id);
4444                 }
4445             }
4446             CATCH_ALL {
4447                 show_exception(tvb, pinfo, ies_tree, EXCEPT_CODE, GET_MESSAGE);
4448                 consumed = 2 + length;
4449             }
4450             ENDTRY;
4451         }
4452 
4453         if (consumed < 2 + length) {
4454             proto_tree_add_item(ies_tree, hf_ieee802154_ie_unknown_content, ie_tvb, consumed, 2 + length - consumed, ENC_NA);
4455             expert_add_info(pinfo, ies_item, &ei_ieee802154_ie_unknown_extra_content);
4456         }
4457 
4458         offset += 2 + length;
4459 
4460         if (id == IEEE802154_PAYLOAD_IE_TERMINATION) {
4461             break;
4462         }
4463     } while (tvb_reported_length_remaining(tvb, offset) > 1);
4464 
4465     proto_item_set_len(ies_item, offset - orig_offset);
4466     return offset - orig_offset;
4467 }
4468 
4469 static const true_false_string tfs_cinfo_device_type = { "FFD", "RFD" };
4470 static const true_false_string tfs_cinfo_power_src = { "AC/Mains Power", "Battery" };
4471 
4472 /**
4473  * Command subdissector routine for the Association request command.
4474  *
4475  * @param tvb pointer to buffer containing raw packet.
4476  * @param pinfo pointer to packet information fields.
4477  * @param tree pointer to protocol tree.
4478  * @param packet IEEE 802.15.4 packet information.
4479  */
4480 
4481 static void
dissect_ieee802154_assoc_req(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet)4482 dissect_ieee802154_assoc_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4483 {
4484     guint8 cap;
4485     proto_tree *subtree;
4486     static int * const capability[] = {
4487         &hf_ieee802154_cinfo_alt_coord,
4488         &hf_ieee802154_cinfo_device_type,
4489         &hf_ieee802154_cinfo_power_src,
4490         &hf_ieee802154_cinfo_idle_rx,
4491         &hf_ieee802154_cinfo_sec_capable,
4492         &hf_ieee802154_cinfo_alloc_addr,
4493         NULL
4494     };
4495 
4496     cap = tvb_get_guint8(tvb, 0);
4497     col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", tfs_get_string(cap & IEEE802154_CMD_CINFO_DEVICE_TYPE, &tfs_cinfo_device_type));
4498 
4499     /* Create a subtree for this command frame. */
4500     subtree = proto_tree_add_subtree(tree, tvb, 0, 1, ett_ieee802154_cmd, NULL,
4501                     val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4502 
4503     /* Get and display capability info. */
4504     proto_tree_add_bitmask_list(subtree, tvb, 0, 1, capability, ENC_NA);
4505 
4506     /* Call the data dissector for any leftover bytes. */
4507     if (tvb_reported_length(tvb) > 1) {
4508         call_data_dissector(tvb_new_subset_remaining(tvb, 1), pinfo, tree);
4509     }
4510 } /* dissect_ieee802154_assoc_req */
4511 
4512 /**
4513  * Command subdissector routine for the Association response command.
4514  *
4515  * @param tvb pointer to buffer containing raw packet.
4516  * @param pinfo pointer to packet information fields.
4517  * @param tree pointer to protocol tree.
4518  * @param packet IEEE 802.15.4 packet information.
4519  */
4520 static void
dissect_ieee802154_assoc_rsp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet)4521 dissect_ieee802154_assoc_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4522 {
4523     proto_tree *subtree;
4524     proto_item *ti;
4525     guint16     short_addr;
4526     guint8      status;
4527     guint       offset  = 0;
4528 
4529     /* Create a subtree for this command frame. */
4530     subtree = proto_tree_add_subtree(tree, tvb, offset, 3, ett_ieee802154_cmd, NULL,
4531                     val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4532 
4533     /* Get and display the short address. */
4534     short_addr = tvb_get_letohs(tvb, offset);
4535     proto_tree_add_uint(subtree, hf_ieee802154_assoc_addr, tvb, offset, 2, short_addr);
4536     offset += 2;
4537 
4538     /* Get and display the status. */
4539     status = tvb_get_guint8(tvb, offset);
4540     if (tree) {
4541         ti = proto_tree_add_uint(subtree, hf_ieee802154_assoc_status, tvb, offset, 1, status);
4542         if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) proto_item_append_text(ti, " (Association Successful)");
4543         else if (status == IEEE802154_CMD_ASRSP_PAN_FULL) proto_item_append_text(ti, " (PAN Full)");
4544         else if (status == IEEE802154_CMD_ASRSP_PAN_DENIED) proto_item_append_text(ti, " (Association Denied)");
4545         else proto_item_append_text(ti, " (Reserved)");
4546     }
4547     offset += 1;
4548 
4549     /* Update the info column. */
4550     if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) {
4551         /* Association was successful. */
4552         if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {
4553             col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", packet->dst_pan);
4554         }
4555         if (short_addr != IEEE802154_NO_ADDR16) {
4556             col_append_fstr(pinfo->cinfo, COL_INFO, " Addr: 0x%04x", short_addr);
4557         }
4558     }
4559     else {
4560         /* Association was unsuccessful. */
4561         col_append_str(pinfo->cinfo, COL_INFO, ", Unsuccessful");
4562     }
4563 
4564     /* Update the address table. */
4565     if ((status == IEEE802154_CMD_ASRSP_AS_SUCCESS) && (short_addr != IEEE802154_NO_ADDR16)) {
4566         ieee802154_addr_update(&ieee802154_map, short_addr, packet->dst_pan, packet->dst64,
4567                 pinfo->current_proto, pinfo->num);
4568     }
4569 
4570     /* Call the data dissector for any leftover bytes. */
4571     if (tvb_captured_length(tvb) > offset) {
4572         call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
4573     }
4574 } /* dissect_ieee802154_assoc_rsp */
4575 
4576 /**
4577  * Command subdissector routine for the Disassociate command.
4578  *
4579  * @param tvb pointer to buffer containing raw packet.
4580  * @param pinfo pointer to packet information fields.
4581  * @param tree pointer to protocol tree.
4582  * @param packet IEEE 802.15.4 packet information.
4583  */
4584 static void
dissect_ieee802154_disassoc(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet)4585 dissect_ieee802154_disassoc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4586 {
4587     proto_tree *subtree;
4588     proto_item *ti;
4589     guint8      reason;
4590 
4591     /* Create a subtree for this command frame. */
4592     subtree = proto_tree_add_subtree(tree, tvb, 0, 1, ett_ieee802154_cmd, NULL,
4593                     val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4594 
4595     /* Get and display the disassociation reason. */
4596     reason = tvb_get_guint8(tvb, 0);
4597     if (tree) {
4598         ti = proto_tree_add_uint(subtree, hf_ieee802154_disassoc_reason, tvb, 0, 1, reason);
4599         switch (reason) {
4600             case 0x01:
4601                 proto_item_append_text(ti, " (Coordinator requests device to leave)");
4602                 break;
4603 
4604             case 0x02:
4605                 proto_item_append_text(ti, " (Device wishes to leave)");
4606                 break;
4607 
4608             default:
4609                 proto_item_append_text(ti, " (Reserved)");
4610                 break;
4611         } /* switch */
4612     }
4613 
4614     if (!PINFO_FD_VISITED(pinfo)) {
4615         /* Update the address tables */
4616         if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT ) {
4617             ieee802154_long_addr_invalidate(packet->dst64, pinfo->num);
4618         } else if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT ) {
4619             ieee802154_short_addr_invalidate(packet->dst16, packet->dst_pan, pinfo->num);
4620         }
4621     }
4622 
4623     /* Call the data dissector for any leftover bytes. */
4624     if (tvb_captured_length(tvb) > 1) {
4625         call_data_dissector(tvb_new_subset_remaining(tvb, 1), pinfo, tree);
4626     }
4627 } /* dissect_ieee802154_disassoc */
4628 
4629 /**
4630  * Command subdissector routine for the Coordinator Realignment command.
4631  *
4632  * @param tvb pointer to buffer containing raw packet.
4633  * @param pinfo pointer to packet information fields.
4634  * @param tree pointer to protocol tree.
4635  * @param packet IEEE 802.15.4 packet information.
4636  */
4637 static void
dissect_ieee802154_realign(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet)4638 dissect_ieee802154_realign(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4639 {
4640     proto_tree *subtree;
4641     proto_item *subitem;
4642     guint16     pan_id;
4643     guint16     coord_addr;
4644     guint8      channel;
4645     guint16     short_addr;
4646     guint       offset  = 0;
4647 
4648     /* Create a subtree for this command frame. */
4649     subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_ieee802154_cmd, &subitem,
4650                 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4651 
4652     /* Get and display the command PAN ID. */
4653     pan_id = tvb_get_letohs(tvb, offset);
4654     proto_tree_add_uint(subtree, hf_ieee802154_realign_pan, tvb, offset, 2, pan_id);
4655     col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", pan_id);
4656     offset += 2;
4657 
4658     /* Get and display the coordinator address. */
4659     coord_addr = tvb_get_letohs(tvb, offset);
4660     proto_tree_add_uint(subtree, hf_ieee802154_realign_caddr, tvb, offset, 2, coord_addr);
4661     col_append_fstr(pinfo->cinfo, COL_INFO, ", Coordinator: 0x%04x", coord_addr);
4662     offset += 2;
4663 
4664     /* Get and display the channel. */
4665     channel = tvb_get_guint8(tvb, offset);
4666     proto_tree_add_uint(subtree, hf_ieee802154_realign_channel, tvb, offset, 1, channel);
4667     col_append_fstr(pinfo->cinfo, COL_INFO, ", Channel: %u", channel);
4668     offset += 1;
4669 
4670     /* Get and display the short address. */
4671     short_addr = tvb_get_letohs(tvb, offset);
4672     if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_addr, tvb, offset, 2, short_addr);
4673     if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)
4674         && (short_addr != IEEE802154_NO_ADDR16)) {
4675         col_append_fstr(pinfo->cinfo, COL_INFO, ", Addr: 0x%04x", short_addr);
4676     }
4677     offset += 2;
4678     /* Update the address table. */
4679     if ((short_addr != IEEE802154_NO_ADDR16) && (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)) {
4680         ieee802154_addr_update(&ieee802154_map, short_addr, packet->dst_pan, packet->dst64,
4681                 pinfo->current_proto, pinfo->num);
4682     }
4683 
4684     /* Get and display the channel page, if it exists. Added in IEEE802.15.4-2006 */
4685     if (tvb_bytes_exist(tvb, offset, 1)) {
4686         guint8  channel_page = tvb_get_guint8(tvb, offset);
4687         if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_channel_page, tvb, offset, 1, channel_page);
4688         offset += 1;
4689     }
4690 
4691     /* Fix the length of the command subtree. */
4692     if (tree) {
4693         proto_item_set_len(subitem, offset);
4694     }
4695 
4696     /* Call the data dissector for any leftover bytes. */
4697     if (tvb_captured_length(tvb) > offset) {
4698         call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
4699     }
4700 } /* dissect_ieee802154_realign */
4701 
4702 static const true_false_string tfs_gtsreq_dir = { "Receive", "Transmit" };
4703 static const true_false_string tfs_gtsreq_type= { "Allocate GTS", "Deallocate GTS" };
4704 
4705 /**
4706  * Command subdissector routine for the GTS request command.
4707  *
4708  * Assumes that COL_INFO will be set to the command name,
4709  * command name will already be appended to the command subtree
4710  * and protocol root. In addition, assumes that the command ID
4711  * has already been parsed.
4712  *
4713  * @param tvb pointer to buffer containing raw packet.
4714  * @param pinfo pointer to packet information fields (unused).
4715  * @param tree pointer to protocol tree.
4716  * @param packet IEEE 802.15.4 packet information (unused).
4717  */
4718 
4719 static void
dissect_ieee802154_gtsreq(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet)4720 dissect_ieee802154_gtsreq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4721 {
4722     proto_tree *subtree;
4723     static int * const characteristics[] = {
4724         &hf_ieee802154_gtsreq_len,
4725         &hf_ieee802154_gtsreq_dir,
4726         &hf_ieee802154_gtsreq_type,
4727         NULL
4728     };
4729 
4730     /* Create a subtree for this command frame. */
4731     subtree = proto_tree_add_subtree(tree, tvb, 0, 1, ett_ieee802154_cmd, NULL,
4732                 val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4733 
4734     proto_tree_add_bitmask_list(subtree, tvb, 0, 1, characteristics, ENC_NA);
4735 
4736     /* Call the data dissector for any leftover bytes. */
4737     if (tvb_reported_length(tvb) > 1) {
4738         call_data_dissector(tvb_new_subset_remaining(tvb, 1), pinfo, tree);
4739     }
4740 } /* dissect_ieee802154_gtsreq */
4741 
4742 /**
4743  * Subdissector routine for IEEE 802.15.4 commands
4744  *
4745  * @param tvb pointer to buffer containing the command payload
4746  * @param pinfo pointer to packet information fields
4747  * @param tree pointer to the protocol tree
4748  * @param packet IEEE 802.15.4 packet information
4749  */
4750 static void
dissect_ieee802154_command(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,ieee802154_packet * packet)4751 dissect_ieee802154_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
4752 {
4753     if ((packet->version == IEEE802154_VERSION_2015) && (packet->frame_type == IEEE802154_FCF_CMD)) {
4754         /* In 802.15.4e and later the Command Id follows the Payload IEs. */
4755         packet->command_id = tvb_get_guint8(tvb, 0);
4756         proto_tree_add_uint(tree, hf_ieee802154_cmd_id, tvb, 0, 1, packet->command_id);
4757         tvb = tvb_new_subset_remaining(tvb, 1);
4758 
4759         /* Display the command identifier in the info column. */
4760         if ((packet->version == IEEE802154_VERSION_2015) && (packet->command_id == IEEE802154_CMD_BEACON_REQ)) {
4761             col_set_str(pinfo->cinfo, COL_INFO, "Enhanced Beacon Request");
4762         }
4763         else {
4764             col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
4765         }
4766     }
4767 
4768     switch (packet->command_id) {
4769     case IEEE802154_CMD_ASSOC_REQ:
4770         IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4771             (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
4772             (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
4773         dissect_ieee802154_assoc_req(tvb, pinfo, tree, packet);
4774         break;
4775 
4776     case IEEE802154_CMD_ASSOC_RSP:
4777         IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4778             (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
4779             (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
4780         dissect_ieee802154_assoc_rsp(tvb, pinfo, tree, packet);
4781         break;
4782 
4783     case IEEE802154_CMD_DISASSOC_NOTIFY:
4784         IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4785             (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
4786             (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
4787         dissect_ieee802154_disassoc(tvb, pinfo, tree, packet);
4788         break;
4789 
4790     case IEEE802154_CMD_DATA_RQ:
4791         IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id, packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE);
4792         /* No payload expected. */
4793         break;
4794 
4795     case IEEE802154_CMD_PANID_CONFLICT:
4796         IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4797             (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
4798             (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
4799         /* No payload expected. */
4800         break;
4801 
4802     case IEEE802154_CMD_ORPHAN_NOTIFY:
4803         IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4804             (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
4805             (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
4806             (packet->dst16 == IEEE802154_BCAST_ADDR) &&
4807             (packet->src_pan == IEEE802154_BCAST_PAN) &&
4808             (packet->dst_pan == IEEE802154_BCAST_PAN));
4809         /* No payload expected. */
4810         break;
4811 
4812     case IEEE802154_CMD_BEACON_REQ:
4813         if ((packet->version == IEEE802154_VERSION_2003) || (packet->version == IEEE802154_VERSION_2006)) {
4814             IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4815                     (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
4816                     (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
4817                     (packet->dst16 == IEEE802154_BCAST_ADDR) &&
4818                     (packet->dst_pan == IEEE802154_BCAST_PAN));
4819         }
4820         /* No payload expected. */
4821         break;
4822 
4823     case IEEE802154_CMD_COORD_REALIGN:
4824         IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4825             (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
4826             (packet->dst_pan == IEEE802154_BCAST_PAN) &&
4827             (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
4828         if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
4829             /* If directed to a 16-bit address, check that it is being broadcast. */
4830             IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id, packet->dst16 == IEEE802154_BCAST_ADDR);
4831         }
4832         dissect_ieee802154_realign(tvb, pinfo, tree, packet);
4833         break;
4834 
4835     case IEEE802154_CMD_GTS_REQ:
4836         /* Check that the addressing is correct for this command type. */
4837         IEEE802154_CMD_ADDR_CHECK(pinfo, tree, packet->command_id,
4838             (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
4839             (packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
4840             (packet->src16 != IEEE802154_BCAST_ADDR) &&
4841             (packet->src16 != IEEE802154_NO_ADDR16));
4842         dissect_ieee802154_gtsreq(tvb, pinfo, tree, packet);
4843         break;
4844 
4845     case IEEE802154_CMD_VENDOR_SPECIFIC:
4846     {
4847         guint32 oui = tvb_get_ntoh24(tvb, 0);
4848         if (!dissector_try_uint_new(cmd_vendor_dissector_table, oui, tvb, pinfo, tree, FALSE, packet)) {
4849             proto_tree_add_item(tree, hf_ieee802154_cmd_vendor_oui, tvb, 0, 3, ENC_BIG_ENDIAN);
4850             call_data_dissector(tvb_new_subset_remaining(tvb, 3), pinfo, tree);
4851         }
4852         break;
4853     }
4854 
4855     case IEEE802154_CMD_TRLE_MGMT_REQ:
4856     case IEEE802154_CMD_TRLE_MGMT_RSP:
4857     case IEEE802154_CMD_DSME_ASSOC_REQ:
4858     case IEEE802154_CMD_DSME_ASSOC_RSP:
4859     case IEEE802154_CMD_DSME_GTS_REQ:
4860     case IEEE802154_CMD_DSME_GTS_RSP:
4861     case IEEE802154_CMD_DSME_GTS_NOTIFY:
4862     case IEEE802154_CMD_DSME_INFO_REQ:
4863     case IEEE802154_CMD_DSME_INFO_RSP:
4864     case IEEE802154_CMD_DSME_BEACON_ALLOC_NOTIFY:
4865     case IEEE802154_CMD_DSME_BEACON_COLL_NOTIFY:
4866     case IEEE802154_CMD_DSME_LINK_REPORT:
4867     case IEEE802154_CMD_RIT_DATA_REQ:
4868     case IEEE802154_CMD_DBS_REQ:
4869     case IEEE802154_CMD_DBS_RSP:
4870     case IEEE802154_CMD_RIT_DATA_RSP:
4871         /* TODO add support for these commands, for now if anything remains, dump it */
4872         expert_add_info(pinfo, tree, &ei_ieee802154_unsupported_cmd);
4873         if (tvb_captured_length_remaining(tvb, 0) > 0) {
4874             call_data_dissector(tvb, pinfo, tree);
4875         }
4876         break;
4877     default:
4878         expert_add_info(pinfo, tree, &ei_ieee802154_unknown_cmd);
4879         if (tvb_captured_length_remaining(tvb, 0) > 0) {
4880             call_data_dissector(tvb, pinfo, tree);
4881         }
4882     } /* switch */
4883 } /* dissect_ieee802154_command */
4884 
4885 /**
4886  * IEEE 802.15.4 decryption algorithm
4887  * @param tvb IEEE 802.15.4 packet, not including the FCS or metadata trailer.
4888  * @param pinfo Packet info structure.
4889  * @param offset Offset where the ciphertext 'c' starts.
4890  * @param packet IEEE 802.15.4 packet information.
4891  * @return decrypted payload.
4892  */
4893 static tvbuff_t *
dissect_ieee802154_decrypt(tvbuff_t * tvb,guint offset,packet_info * pinfo,ieee802154_packet * packet,ieee802154_decrypt_info_t * decrypt_info)4894 dissect_ieee802154_decrypt(tvbuff_t *tvb,
4895                            guint offset,
4896                            packet_info *pinfo,
4897                            ieee802154_packet *packet,
4898                            ieee802154_decrypt_info_t* decrypt_info)
4899 {
4900     tvbuff_t           *ptext_tvb;
4901     gboolean            have_mic = FALSE;
4902     guint64             srcAddr = 0;
4903     unsigned char       tmp[IEEE802154_CIPHER_SIZE];
4904     guint               M;
4905     gint                captured_len;
4906     gint                reported_len;
4907     ieee802154_hints_t *ieee_hints;
4908     gchar              *generic_nonce_ptr = NULL;
4909     gchar               generic_nonce[13];
4910 
4911     ieee_hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
4912 
4913     /* Get the captured and on-the-air length of the payload. */
4914     M = IEEE802154_MIC_LENGTH(packet->security_level);
4915     *decrypt_info->rx_mic_length = M;
4916 
4917     /* Is the MIC larger than the total amount of data? */
4918     reported_len = tvb_reported_length_remaining(tvb, offset) - M;
4919     if (reported_len < 0) {
4920         /* Yes.  Give up. */
4921         *decrypt_info->status = DECRYPT_PACKET_TOO_SMALL;
4922         return NULL;
4923     }
4924     /* Check whether the payload is truncated by a snapshot length. */
4925     if (tvb_bytes_exist(tvb, offset, reported_len)) {
4926         /* It's not, so we have all of the payload. */
4927         captured_len = reported_len;
4928     }
4929     else {
4930         /*
4931          * It is, so we don't have all of the payload - and we don't
4932          * have the MIC, either, as that comes after the payload.
4933          * As the MIC isn't part of the captured data - the captured
4934          * data was cut short before the first byte of the MIC - we
4935          * don't subtract the length of the MIC from the amount of
4936          * captured data.
4937          */
4938         captured_len = tvb_captured_length_remaining(tvb, offset);
4939     }
4940 
4941     /* Check if the MIC is present in the captured data. */
4942     have_mic = tvb_bytes_exist(tvb, offset + reported_len, M);
4943     if (have_mic) {
4944         /* It is - save a copy of it. */
4945         tvb_memcpy(tvb, decrypt_info->rx_mic, offset + reported_len, M);
4946     }
4947 
4948     /* We need the extended source address. */
4949     if ((packet->key_index == IEEE802154_THR_WELL_KNOWN_KEY_INDEX) &&
4950         (packet->key_source.addr32 == IEEE802154_THR_WELL_KNOWN_KEY_SRC))
4951     {
4952         /* Use the well-known extended address */
4953         srcAddr = IEEE802154_THR_WELL_KNOWN_EXT_ADDR;
4954     } else {
4955         if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
4956             /* The source EUI-64 is included in the headers. */
4957             srcAddr = packet->src64;
4958         }
4959         else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT && packet->frame_counter_suppression) {
4960             /* In TSCH mode, the source address is a combination of 802.15 CID, PAN ID and Short Address */
4961             srcAddr = IEEE80215_CID << 40;
4962             srcAddr |= ((guint64)packet->src_pan & 0xffff) << 16;
4963             srcAddr |= packet->src16;
4964         }
4965         else if (ieee_hints && ieee_hints->map_rec && ieee_hints->map_rec->addr64) {
4966             /* Use the hint */
4967             srcAddr = ieee_hints->map_rec->addr64;
4968         }
4969         else {
4970             /* Lookup failed.  */
4971             *decrypt_info->status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
4972             return NULL;
4973         }
4974     }
4975 
4976     /*
4977      * CCM* - CTR mode payload encryption
4978      *
4979      */
4980     /* 802.15.4-2015 TSCH mode */
4981     if (packet->frame_counter_suppression) {
4982         tsch_ccm_init_nonce(srcAddr, packet->asn, generic_nonce);
4983         generic_nonce_ptr = generic_nonce;
4984     }
4985 
4986     /* Create the CCM* initial block for decryption (Adata=0, M=0, counter=0). */
4987     if (packet->version == IEEE802154_VERSION_2003)
4988         ccm_init_block(tmp, FALSE, 0, srcAddr, packet->frame_counter, packet->key_sequence_counter, 0, NULL);
4989     else
4990         ccm_init_block(tmp, FALSE, 0, srcAddr, packet->frame_counter, packet->security_level, 0, generic_nonce_ptr);
4991 
4992     /*
4993      * If the payload is encrypted, so that it's the ciphertext, and we
4994      * have at least one byte of it in the captured data, decrypt the
4995      * ciphertext, and place the plaintext in a new tvb.
4996      */
4997     if (IEEE802154_IS_ENCRYPTED(packet->security_level) && captured_len) {
4998         guint8 *text;
4999         /*
5000          * Make a copy of the ciphertext in heap memory.
5001          *
5002          * We will decrypt the message in-place and then use the buffer as the
5003          * real data for the new tvb.
5004          */
5005         text = (guint8 *)tvb_memdup(pinfo->pool, tvb, offset, captured_len);
5006 
5007         /* Perform CTR-mode transformation. */
5008         if (!ccm_ctr_encrypt(decrypt_info->key, tmp, decrypt_info->rx_mic, text, captured_len)) {
5009             wmem_free(pinfo->pool, text);
5010             *decrypt_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
5011             return NULL;
5012         }
5013 
5014         /* Create a tvbuff for the plaintext. */
5015         ptext_tvb = tvb_new_child_real_data(tvb, text, captured_len, reported_len);
5016         add_new_data_source(pinfo, ptext_tvb, "Decrypted IEEE 802.15.4 payload");
5017         *decrypt_info->status = DECRYPT_PACKET_SUCCEEDED;
5018     }
5019     else {
5020         /*
5021          * Either the payload isn't encrypted or we don't have any of it
5022          * in the captured data.
5023          */
5024         /* Decrypt the MIC (if present). */
5025         if ((have_mic) && (!ccm_ctr_encrypt(decrypt_info->key, tmp, decrypt_info->rx_mic, NULL, 0))) {
5026             *decrypt_info->status = DECRYPT_PACKET_DECRYPT_FAILED;
5027             return NULL;
5028         }
5029 
5030         /* Create a tvbuff for the plaintext. This might result in a zero-length tvbuff. */
5031         ptext_tvb = tvb_new_subset_length_caplen(tvb, offset, captured_len, reported_len);
5032         *decrypt_info->status = DECRYPT_PACKET_SUCCEEDED;
5033     }
5034 
5035     /*
5036      * CCM* - CBC-mode message authentication
5037      *
5038      */
5039     /* We can only verify the message if the MIC wasn't truncated. */
5040     if (have_mic) {
5041         unsigned char           dec_mic[16];
5042         guint                   l_m = captured_len;
5043         guint                   l_a = offset;
5044 
5045         /* Adjust the lengths of the plaintext and additional data if unencrypted. */
5046         if (!IEEE802154_IS_ENCRYPTED(packet->security_level)) {
5047             l_a += l_m;
5048             l_m = 0;
5049         }
5050         else if ((packet->version == IEEE802154_VERSION_2003) && !ieee802154_extend_auth)
5051             l_a -= 5;   /* Exclude Frame Counter (4 bytes) and Key Sequence Counter (1 byte) from authentication data */
5052 
5053 
5054         /* Create the CCM* initial block for authentication (Adata!=0, M!=0, counter=l(m)). */
5055         if (packet->version == IEEE802154_VERSION_2003)
5056             ccm_init_block(tmp, TRUE, M, srcAddr, packet->frame_counter, packet->key_sequence_counter, l_m, NULL);
5057         else
5058             ccm_init_block(tmp, TRUE, M, srcAddr, packet->frame_counter, packet->security_level, l_m, generic_nonce_ptr);
5059 
5060         /* Compute CBC-MAC authentication tag. */
5061         /*
5062          * And yes, despite the warning in tvbuff.h, I think tvb_get_ptr is the
5063          * right function here since either A) the payload wasn't encrypted, in
5064          * which case l_m is zero, or B) the payload was encrypted, and the tvb
5065          * already points to contiguous memory, since we just allocated it in
5066          * decryption phase.
5067          */
5068         memset(dec_mic, 0, sizeof(dec_mic));
5069         if (!ccm_cbc_mac(decrypt_info->key, tmp, (const gchar *)tvb_memdup(pinfo->pool, tvb, 0, l_a), l_a, tvb_get_ptr(ptext_tvb, 0, l_m), l_m, dec_mic)) {
5070             *decrypt_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
5071         }
5072         /* Compare the received MIC with the one we generated. */
5073         else if (memcmp(decrypt_info->rx_mic, dec_mic, M) != 0) {
5074             *decrypt_info->status = DECRYPT_PACKET_MIC_CHECK_FAILED;
5075         }
5076     }
5077 
5078     /* Done! */
5079     return ptext_tvb;
5080 } /* dissect_ieee802154_decrypt */
5081 
5082 /**
5083  * Creates the CCM* initial block value for IEEE 802.15.4.
5084  *
5085  * @param block Output pointer for the initial block.
5086  * @param adata TRUE if additional auth data is present
5087  * @param M CCM* parameter M.
5088  * @param addr Source extended address.
5089  * @param frame_counter Packet frame counter
5090  * @param level Security level or key_sequence_counter for 802.15.4-2003
5091  * @param ctr_val Value in the last L bytes of the block.
5092  * @param generic_nonce 13-byte nonce to be set by non 802.15.4 calls. If set addr, frame_counter and level are ignored.
5093  */
5094 void
ccm_init_block(gchar * block,gboolean adata,gint M,guint64 addr,guint32 frame_counter,guint8 level,gint ctr_val,const gchar * generic_nonce)5095 ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, guint32 frame_counter, guint8 level, gint ctr_val, const gchar *generic_nonce)
5096 {
5097     gint                i = 0;
5098 
5099     /* Flags: Reserved(0) || Adata || (M-2)/2 || (L-1) */
5100     block[i] = (0x2 - 1); /* (L-1) */
5101     if (M > 0) block[i] |= (((M-2)/2) << 3); /* (M-2)/2 */
5102     if (adata) block[i] |= (1 << 6); /* Adata */
5103     i++;
5104     if (generic_nonce == NULL) {
5105         /* 2003 CCM Nonce:  Source Address || Frame Counter || Key Sequence Counter */
5106         /* 2006 CCM* Nonce: Source Address || Frame Counter || Security Level */
5107         block[i++] = (guint8)((addr >> 56) & 0xff);
5108         block[i++] = (guint8)((addr >> 48) & 0xff);
5109         block[i++] = (guint8)((addr >> 40) & 0xff);
5110         block[i++] = (guint8)((addr >> 32) & 0xff);
5111         block[i++] = (guint8)((addr >> 24) & 0xff);
5112         block[i++] = (guint8)((addr >> 16) & 0xff);
5113         block[i++] = (guint8)((addr >> 8) & 0xff);
5114         block[i++] = (guint8)((addr >> 0) & 0xff);
5115         block[i++] = (guint8)((frame_counter >> 24) & 0xff);
5116         block[i++] = (guint8)((frame_counter >> 16) & 0xff);
5117         block[i++] = (guint8)((frame_counter >> 8) & 0xff);
5118         block[i++] = (guint8)((frame_counter >> 0) & 0xff);
5119         block[i++] = level;
5120     } else {
5121         memcpy(&block[i], generic_nonce, 13);
5122         i += 13;
5123     }
5124     /* Plaintext length. */
5125     block[i++] = (guint8)((ctr_val >> 8) & 0xff);
5126     block[i] = (guint8)((ctr_val >> 0) & 0xff);
5127 } /* ccm_init_block */
5128 
5129 /**
5130  * Creates the IEEE 802.15.4 TSCH nonce.
5131  *
5132  * @param addr Source extended address.
5133  * @param asn TSCH Absolute Slot Number
5134  * @param generic_nonce 13-byte nonce to returned by this function.
5135  */
5136 static void
tsch_ccm_init_nonce(guint64 addr,guint64 asn,gchar * generic_nonce)5137 tsch_ccm_init_nonce(guint64 addr, guint64 asn, gchar* generic_nonce)
5138 {
5139     gint i = 0;
5140 
5141     /* 2015 CCM* Nonce: Source Address || ASN */
5142     generic_nonce[i++] = (guint8)((addr >> 56) & 0xff);
5143     generic_nonce[i++] = (guint8)((addr >> 48) & 0xff);
5144     generic_nonce[i++] = (guint8)((addr >> 40) & 0xff);
5145     generic_nonce[i++] = (guint8)((addr >> 32) & 0xff);
5146     generic_nonce[i++] = (guint8)((addr >> 24) & 0xff);
5147     generic_nonce[i++] = (guint8)((addr >> 16) & 0xff);
5148     generic_nonce[i++] = (guint8)((addr >> 8) & 0xff);
5149     generic_nonce[i++] = (guint8)((addr >> 0) & 0xff);
5150     generic_nonce[i++] = (guint8)((asn >> 32) & 0xff);
5151     generic_nonce[i++] = (guint8)((asn >> 24) & 0xff);
5152     generic_nonce[i++] = (guint8)((asn >> 16) & 0xff);
5153     generic_nonce[i++] = (guint8)((asn >> 8) & 0xff);
5154     generic_nonce[i++] = (guint8)((asn >> 0) & 0xff);
5155 } /* tsch_ccm_init_nonce */
5156 
5157 /**
5158  * Perform an in-place CTR-mode encryption/decryption.
5159  *
5160  * @param key Encryption Key.
5161  * @param iv Counter initial value.
5162  * @param mic MIC to encrypt/decrypt.
5163  * @param data Buffer to encrypt/decrypt.
5164  * @param length Length of the buffer.
5165  * @return TRUE on SUCCESS, FALSE on error.
5166  */
5167 gboolean
ccm_ctr_encrypt(const gchar * key,const gchar * iv,gchar * mic,gchar * data,gint length)5168 ccm_ctr_encrypt(const gchar *key, const gchar *iv, gchar *mic, gchar *data, gint length)
5169 {
5170     gcry_cipher_hd_t    cipher_hd;
5171 
5172     /* Open the cipher. */
5173     if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0)) {
5174         return FALSE;
5175     }
5176 
5177     /* Set the key and initial value. */
5178     if (gcry_cipher_setkey(cipher_hd, key, 16)) {
5179         gcry_cipher_close(cipher_hd);
5180         return FALSE;
5181     }
5182     if (gcry_cipher_setctr(cipher_hd, iv, 16)) {
5183         gcry_cipher_close(cipher_hd);
5184         return FALSE;
5185     }
5186 
5187     /* Decrypt the MIC. */
5188     if (gcry_cipher_encrypt(cipher_hd, mic, 16, NULL, 0)) {
5189         gcry_cipher_close(cipher_hd);
5190         return FALSE;
5191     }
5192     /* Decrypt the payload. */
5193     if (gcry_cipher_encrypt(cipher_hd, data, length, NULL, 0)) {
5194         gcry_cipher_close(cipher_hd);
5195         return FALSE;
5196     }
5197 
5198     /* Done with the cipher. */
5199     gcry_cipher_close(cipher_hd);
5200     return TRUE;
5201 } /* ccm_ctr_encrypt */
5202 
5203 /**
5204  * Generate a CBC-MAC of the decrypted payload and additional authentication headers.
5205  * @param key Encryption Key.
5206  * @param iv Counter initial value.
5207  * @param a Additional auth headers.
5208  * @param a_len Length of the additional headers.
5209  * @param m Plaintext message.
5210  * @param m_len Length of plaintext message.
5211  * @param mic Output for CBC-MAC.
5212  * @return  TRUE on SUCCESS, FALSE on error.
5213  */
5214 gboolean
ccm_cbc_mac(const gchar * key,const gchar * iv,const gchar * a,gint a_len,const gchar * m,gint m_len,gchar * mic)5215 ccm_cbc_mac(const gchar *key, const gchar *iv, const gchar *a, gint a_len, const gchar *m, gint m_len, gchar *mic)
5216 {
5217     gcry_cipher_hd_t cipher_hd;
5218     guint            i = 0;
5219     unsigned char    block[IEEE802154_CIPHER_SIZE];
5220 
5221     /* Open the cipher. */
5222     if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_MAC)) return FALSE;
5223 
5224     /* Set the key. */
5225     if (gcry_cipher_setkey(cipher_hd, key, IEEE802154_CIPHER_SIZE)) {
5226         gcry_cipher_close(cipher_hd);
5227         return FALSE;
5228     }
5229 
5230     /* Process the initial value. */
5231     if (gcry_cipher_encrypt(cipher_hd, mic, 16, iv, 16)) {
5232         gcry_cipher_close(cipher_hd);
5233         return FALSE;
5234     }
5235 
5236     /* Encode L(a) */
5237     i = 0;
5238 
5239 /* XXX: GINT_MAX is not defined so #if ... will always be false */
5240 #if (GINT_MAX >= (1LL << 32))
5241     if (a_len >= (1LL << 32)) {
5242         block[i++] = 0xff;
5243         block[i++] = 0xff;
5244         block[i++] = (a_len >> 56) & 0xff;
5245         block[i++] = (a_len >> 48) & 0xff;
5246         block[i++] = (a_len >> 40) & 0xff;
5247         block[i++] = (a_len >> 32) & 0xff;
5248         block[i++] = (a_len >> 24) & 0xff;
5249         block[i++] = (a_len >> 16) & 0xff;
5250         block[i++] = (a_len >> 8) & 0xff;
5251         block[i++] = (a_len >> 0) & 0xff;
5252     }
5253     else
5254 #endif
5255     if (a_len >= ((1 << 16) - (1 << 8))) {
5256         block[i++] = 0xff;
5257         block[i++] = 0xfe;
5258         block[i++] = (a_len >> 24) & 0xff;
5259         block[i++] = (a_len >> 16) & 0xff;
5260         block[i++] = (a_len >> 8) & 0xff;
5261         block[i++] = (a_len >> 0) & 0xff;
5262     }
5263     else {
5264         block[i++] = (a_len >> 8) & 0xff;
5265         block[i++] = (a_len >> 0) & 0xff;
5266     }
5267     /* Append a to get the first block of input (pad if we encounter the end of a). */
5268     while ((i < sizeof(block)) && (a_len > 0)) {
5269         block[i++] = *a++;
5270         a_len--;
5271     }
5272     while (i < sizeof(block)) {
5273         block[i++] = 0;
5274     }
5275 
5276     /* Process the first block of AuthData. */
5277     if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, 16)) {
5278         gcry_cipher_close(cipher_hd);
5279         return FALSE;
5280     }
5281 
5282     /* Transform and process the remainder of a. */
5283     while (a_len > 0) {
5284         /* Copy and pad. */
5285         if ((guint)a_len >= sizeof(block)) {
5286             memcpy(block, a, sizeof(block));
5287         }
5288         else {
5289             memcpy(block, a, a_len);
5290             memset(block+a_len, 0, sizeof(block)-a_len);
5291         }
5292         /* Adjust pointers. */
5293         a += sizeof(block);
5294         a_len -= (int)sizeof(block);
5295         /* Execute the CBC-MAC algorithm. */
5296         if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, sizeof(block))) {
5297             gcry_cipher_close(cipher_hd);
5298             return FALSE;
5299         }
5300     } /* while */
5301 
5302     /* Process the message, m. */
5303     while (m_len > 0) {
5304         /* Copy and pad. */
5305         if ((guint)m_len >= sizeof(block)) {
5306             memcpy(block, m, sizeof(block));
5307         }
5308         else {
5309             memcpy(block, m, m_len);
5310             memset(block+m_len, 0, sizeof(block)-m_len);
5311         }
5312         /* Adjust pointers. */
5313         m += sizeof(block);
5314         m_len -= (int)sizeof(block);
5315         /* Execute the CBC-MAC algorithm. */
5316         if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, sizeof(block))) {
5317             gcry_cipher_close(cipher_hd);
5318             return FALSE;
5319         }
5320     }
5321 
5322     /* Done with the cipher. */
5323     gcry_cipher_close(cipher_hd);
5324     return TRUE;
5325 } /* ccm_cbc_mac */
5326 
5327 /* Key hash function. */
ieee802154_short_addr_hash(gconstpointer key)5328 guint ieee802154_short_addr_hash(gconstpointer key)
5329 {
5330     return (((const ieee802154_short_addr *)key)->addr) | (((const ieee802154_short_addr *)key)->pan << 16);
5331 }
5332 
5333 /* Key equal function. */
ieee802154_short_addr_equal(gconstpointer a,gconstpointer b)5334 gboolean ieee802154_short_addr_equal(gconstpointer a, gconstpointer b)
5335 {
5336     return (((const ieee802154_short_addr *)a)->pan == ((const ieee802154_short_addr *)b)->pan) &&
5337            (((const ieee802154_short_addr *)a)->addr == ((const ieee802154_short_addr *)b)->addr);
5338 }
5339 
5340 /* Key hash function. */
ieee802154_long_addr_hash(gconstpointer key)5341 guint ieee802154_long_addr_hash(gconstpointer key)
5342 {
5343     return (guint)(((const ieee802154_long_addr *)key)->addr) & 0xFFFFFFFF;
5344 }
5345 
5346 /* Key equal function. */
ieee802154_long_addr_equal(gconstpointer a,gconstpointer b)5347 gboolean ieee802154_long_addr_equal(gconstpointer a, gconstpointer b)
5348 {
5349     return (((const ieee802154_long_addr *)a)->addr == ((const ieee802154_long_addr *)b)->addr);
5350 }
5351 
5352 /* Set MAC key function. */
ieee802154_set_mac_key(ieee802154_packet * packet,unsigned char * key,unsigned char * alt_key,ieee802154_key_t * uat_key)5353 static guint ieee802154_set_mac_key(ieee802154_packet *packet, unsigned char *key, unsigned char *alt_key, ieee802154_key_t *uat_key)
5354 {
5355     ieee802154_set_key_func func = (ieee802154_set_key_func)wmem_tree_lookup32(mac_key_hash_handlers, uat_key->hash_type);
5356 
5357     if (func != NULL)
5358         return func(packet, key, alt_key, uat_key);
5359 
5360     /* Right now, KEY_HASH_NONE and KEY_HASH_ZIP are not registered because they
5361         work with this "default" behavior */
5362     if (packet->key_index == uat_key->key_index)
5363     {
5364         memcpy(key, uat_key->key, IEEE802154_CIPHER_SIZE);
5365         return 1;
5366     }
5367 
5368     return 0;
5369 }
5370 
5371 /**
5372  * Creates a record that maps the given short address and pan to a long (extended) address.
5373  * @param short_addr 16-bit short address
5374  * @param pan 16-bit PAN id
5375  * @param long_addr 64-bit long (extended) address
5376  * @param proto pointer to name of current protocol
5377  * @param fnum Frame number this mapping became valid
5378  * @return TRUE Record was updated, FALSE Couldn't find it
5379  */
ieee802154_addr_update(ieee802154_map_tab_t * au_ieee802154_map,guint16 short_addr,guint16 pan,guint64 long_addr,const char * proto,guint fnum)5380 ieee802154_map_rec *ieee802154_addr_update(ieee802154_map_tab_t *au_ieee802154_map,
5381         guint16 short_addr, guint16 pan, guint64 long_addr, const char *proto, guint fnum)
5382 {
5383     ieee802154_short_addr  addr16;
5384     ieee802154_map_rec    *p_map_rec;
5385     gpointer               old_key;
5386 
5387     /* Look up short address hash */
5388     addr16.pan = pan;
5389     addr16.addr = short_addr;
5390     p_map_rec = (ieee802154_map_rec *)g_hash_table_lookup(au_ieee802154_map->short_table, &addr16);
5391 
5392     /* Update mapping record */
5393     if (p_map_rec) {
5394         /* record already exists */
5395         if ( p_map_rec->addr64 == long_addr ) {
5396             /* no change */
5397             return p_map_rec;
5398         }
5399         else {
5400             /* mark current mapping record invalid */
5401             p_map_rec->end_fnum = fnum;
5402         }
5403     }
5404 
5405     /* create a new mapping record */
5406     p_map_rec = wmem_new(wmem_file_scope(), ieee802154_map_rec);
5407     p_map_rec->proto = proto;
5408     p_map_rec->start_fnum = fnum;
5409     p_map_rec->end_fnum = 0;
5410     p_map_rec->addr64 = long_addr;
5411 
5412     /* link new mapping record to addr hash tables */
5413     if ( g_hash_table_lookup_extended(au_ieee802154_map->short_table, &addr16, &old_key, NULL) ) {
5414         /* update short addr hash table, reusing pointer to old key */
5415         g_hash_table_insert(au_ieee802154_map->short_table, old_key, p_map_rec);
5416     } else {
5417         /* create new hash entry */
5418         g_hash_table_insert(au_ieee802154_map->short_table, wmem_memdup(wmem_file_scope(), &addr16, sizeof(addr16)), p_map_rec);
5419     }
5420 
5421     if ( g_hash_table_lookup_extended(au_ieee802154_map->long_table, &long_addr, &old_key, NULL) ) {
5422         /* update long addr hash table, reusing pointer to old key */
5423         g_hash_table_insert(au_ieee802154_map->long_table, old_key, p_map_rec);
5424     } else {
5425         /* create new hash entry */
5426         g_hash_table_insert(au_ieee802154_map->long_table, wmem_memdup(wmem_file_scope(), &long_addr, sizeof(long_addr)), p_map_rec);
5427     }
5428 
5429     return p_map_rec;
5430 } /* ieee802154_addr_update */
5431 
5432 /**
5433  * Marks a mapping record associated with device with short_addr
5434  * as invalid at a certain frame number, typically when a
5435  * disassociation occurs.
5436  *
5437  * @param short_addr 16-bit short address
5438  * @param pan 16-bit PAN id
5439  * @param fnum Frame number when mapping became invalid
5440  * @return TRUE Record was updated, FALSE Couldn't find it
5441  */
ieee802154_short_addr_invalidate(guint16 short_addr,guint16 pan,guint fnum)5442 gboolean ieee802154_short_addr_invalidate(guint16 short_addr, guint16 pan, guint fnum)
5443 {
5444     ieee802154_short_addr  addr16;
5445     ieee802154_map_rec    *map_rec;
5446 
5447     addr16.pan = pan;
5448     addr16.addr = short_addr;
5449 
5450     map_rec = (ieee802154_map_rec *)g_hash_table_lookup(ieee802154_map.short_table, &addr16);
5451     if ( map_rec ) {
5452         /* indicates this mapping is invalid at frame fnum */
5453         map_rec->end_fnum = fnum;
5454         return TRUE;
5455     }
5456 
5457     return FALSE;
5458 } /* ieee802154_short_addr_invalidate */
5459 
5460 /**
5461  * Mark a mapping record associated with device with long_addr
5462  * as invalid at a certain frame number, typically when a
5463  * disassociation occurs.
5464  *
5465  * @param long_addr 16-bit short address
5466  * @param fnum Frame number when mapping became invalid
5467  * @return TRUE If record was updated, FALSE otherwise
5468  */
ieee802154_long_addr_invalidate(guint64 long_addr,guint fnum)5469 gboolean ieee802154_long_addr_invalidate(guint64 long_addr, guint fnum)
5470 {
5471     ieee802154_map_rec   *map_rec;
5472 
5473     map_rec = (ieee802154_map_rec *)g_hash_table_lookup(ieee802154_map.long_table, &long_addr);
5474     if ( map_rec ) {
5475         /* indicates this mapping is invalid at frame fnum */
5476         map_rec->end_fnum = fnum;
5477         return TRUE;
5478     }
5479 
5480     return FALSE;
5481 } /* ieee802154_long_addr_invalidate */
5482 
5483 /**
5484  * Init routine for the IEEE 802.15.4 dissector. Creates hash
5485  * tables for mapping between 16-bit to 64-bit addresses and
5486  * populates them with static address pairs from a UAT
5487  * preference table.
5488  */
5489 static void
proto_init_ieee802154(void)5490 proto_init_ieee802154(void)
5491 {
5492     guint       i;
5493 
5494     ieee802154_map.short_table = g_hash_table_new(ieee802154_short_addr_hash, ieee802154_short_addr_equal);
5495     ieee802154_map.long_table = g_hash_table_new(ieee802154_long_addr_hash, ieee802154_long_addr_equal);
5496     /* Reload the hash table from the static address UAT. */
5497     for (i=0; (i<num_static_addrs) && (static_addrs); i++) {
5498         ieee802154_addr_update(&ieee802154_map,(guint16)static_addrs[i].addr16, (guint16)static_addrs[i].pan,
5499                pntoh64(static_addrs[i].eui64), ieee802154_user, IEEE802154_USER_MAPPING);
5500     } /* for */
5501 } /* proto_init_ieee802154 */
5502 
5503 /**
5504  * Cleanup for the IEEE 802.15.4 dissector.
5505  */
5506 static void
proto_cleanup_ieee802154(void)5507 proto_cleanup_ieee802154(void)
5508 {
5509     g_hash_table_destroy(ieee802154_map.short_table);
5510     g_hash_table_destroy(ieee802154_map.long_table);
5511 }
5512 
5513 /* Returns the prompt string for the Decode-As dialog. */
ieee802154_da_prompt(packet_info * pinfo _U_,gchar * result)5514 static void ieee802154_da_prompt(packet_info *pinfo _U_, gchar* result)
5515 {
5516     ieee802154_hints_t *hints;
5517     hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
5518     if (hints)
5519         g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IEEE 802.15.4 PAN 0x%04x as", hints->src_pan);
5520     else
5521         g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "IEEE 802.15.4 PAN Unknown");
5522 } /* iee802154_da_prompt */
5523 
5524 /* Returns the value to index the panid decode table with (source PAN)*/
ieee802154_da_value(packet_info * pinfo _U_)5525 static gpointer ieee802154_da_value(packet_info *pinfo _U_)
5526 {
5527     ieee802154_hints_t *hints;
5528     hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ieee802154, 0);
5529     if (hints)
5530         return GUINT_TO_POINTER((guint)(hints->src_pan));
5531     else
5532         return NULL;
5533 } /* iee802154_da_value */
5534 
ieee802154_conv_get_filter_type(conv_item_t * conv,conv_filter_type_e filter)5535 static const char* ieee802154_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter)
5536 {
5537     if (filter == CONV_FT_SRC_ADDRESS) {
5538         if (conv->src_address.type == ieee802_15_4_short_address_type)
5539             return "wpan.src16";
5540         else if (conv->src_address.type == AT_EUI64)
5541             return "wpan.src64";
5542     }
5543 
5544     if (filter == CONV_FT_DST_ADDRESS) {
5545         if (conv->dst_address.type == ieee802_15_4_short_address_type)
5546             return "wpan.dst16";
5547         else if (conv->dst_address.type == AT_EUI64)
5548             return "wpan.dst64";
5549     }
5550 
5551     if (filter == CONV_FT_ANY_ADDRESS) {
5552         if (conv->src_address.type == ieee802_15_4_short_address_type)
5553             return "wpan.addr16";
5554         else if (conv->src_address.type == AT_EUI64)
5555             return "wpan.addr64";
5556     }
5557 
5558     return CONV_FILTER_INVALID;
5559 }
5560 
5561 static ct_dissector_info_t ieee802154_ct_dissector_info = {&ieee802154_conv_get_filter_type };
5562 
ieee802154_conversation_packet(void * pct,packet_info * pinfo,epan_dissect_t * edt _U_,const void * vip _U_)5563 static tap_packet_status ieee802154_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_)
5564 {
5565     conv_hash_t *hash = (conv_hash_t*)pct;
5566 
5567     add_conversation_table_data(hash, &pinfo->dl_src, &pinfo->dl_dst, 0, 0, 1,
5568             pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts,
5569             &ieee802154_ct_dissector_info, ENDPOINT_NONE);
5570 
5571     return TAP_PACKET_REDRAW;
5572 }
5573 
ieee802154_host_get_filter_type(hostlist_talker_t * host,conv_filter_type_e filter)5574 static const char* ieee802154_host_get_filter_type(hostlist_talker_t* host, conv_filter_type_e filter)
5575 {
5576     if (filter == CONV_FT_ANY_ADDRESS) {
5577         if (host->myaddress.type == ieee802_15_4_short_address_type)
5578             return "wpan.addr16";
5579         else if (host->myaddress.type == AT_EUI64)
5580             return "wpan.addr64";
5581     }
5582 
5583     return CONV_FILTER_INVALID;
5584 }
5585 
5586 static hostlist_dissector_info_t ieee802154_host_dissector_info = {&ieee802154_host_get_filter_type };
5587 
ieee802154_hostlist_packet(void * pit,packet_info * pinfo,epan_dissect_t * edt _U_,const void * vip _U_)5588 static tap_packet_status ieee802154_hostlist_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_)
5589 {
5590     conv_hash_t *hash = (conv_hash_t*)pit;
5591 
5592     /* Take two "add" passes per packet, adding for each direction, ensures that all
5593      packets are counted properly (even if address is sending to itself)
5594      XXX - this could probably be done more efficiently inside hostlist_table */
5595     add_hostlist_table_data(hash, &pinfo->dl_src, 0, TRUE, 1,
5596             pinfo->fd->pkt_len, &ieee802154_host_dissector_info, ENDPOINT_NONE);
5597     add_hostlist_table_data(hash, &pinfo->dl_dst, 0, FALSE, 1,
5598             pinfo->fd->pkt_len, &ieee802154_host_dissector_info, ENDPOINT_NONE);
5599 
5600     return TAP_PACKET_REDRAW;
5601 }
5602 
ieee802154_filter_valid(packet_info * pinfo)5603 static gboolean ieee802154_filter_valid(packet_info *pinfo)
5604 {
5605     return proto_is_frame_protocol(pinfo->layers, "wpan")
5606             && ((pinfo->dl_src.type == ieee802_15_4_short_address_type) || (pinfo->dl_src.type == AT_EUI64))
5607             && ((pinfo->dl_dst.type == ieee802_15_4_short_address_type) || (pinfo->dl_dst.type == AT_EUI64));
5608 }
5609 
ieee802154_build_filter(packet_info * pinfo)5610 static gchar* ieee802154_build_filter(packet_info *pinfo)
5611 {
5612     return g_strdup_printf("wpan.%s eq %s and wpan.%s eq %s",
5613             (pinfo->dl_src.type == ieee802_15_4_short_address_type) ? "addr16" : "addr64",
5614             address_to_str(pinfo->pool, &pinfo->dl_src),
5615             (pinfo->dl_dst.type == ieee802_15_4_short_address_type) ? "addr16" : "addr64",
5616             address_to_str(pinfo->pool, &pinfo->dl_dst));
5617 }
5618 
5619 /**
5620  * IEEE 802.15.4 protocol registration routine.
5621  */
proto_register_ieee802154(void)5622 void proto_register_ieee802154(void)
5623 {
5624     /* Protocol fields  */
5625     static hf_register_info hf_phy[] = {
5626         /* PHY level */
5627 
5628         { &hf_ieee802154_nonask_phy_preamble,
5629         { "Preamble",                       "wpan-nonask-phy.preamble", FT_UINT32, BASE_HEX, NULL, 0x0,
5630             NULL, HFILL }},
5631 
5632         { &hf_ieee802154_nonask_phy_sfd,
5633         { "Start of Frame Delimiter",       "wpan-nonask-phy.sfd", FT_UINT8, BASE_HEX, NULL, 0x0,
5634             NULL, HFILL }},
5635 
5636         { &hf_ieee802154_nonask_phy_length,
5637         { "Frame Length",                   "wpan-nonask-phy.frame_length", FT_UINT8, BASE_HEX, NULL,
5638             IEEE802154_PHY_LENGTH_MASK, NULL, HFILL }},
5639 
5640         { &hf_ieee802154_nonask_phr,
5641         { "PHR",                            "wpan-nonask-phy.phr", FT_UINT8, BASE_HEX, NULL,
5642             0x0, NULL, HFILL }},
5643     };
5644 
5645     static hf_register_info hf[] = {
5646 
5647         { &hf_ieee802154_frame_length,
5648         { "Frame Length",                   "wpan.frame_length", FT_UINT8, BASE_DEC, NULL, 0x0,
5649             "Frame Length as reported from lower layer", HFILL }},
5650 
5651         { &hf_ieee802154_fcf,
5652         { "Frame Control Field",            "wpan.fcf", FT_UINT16, BASE_HEX, NULL,
5653             0x0, NULL, HFILL }},
5654 
5655         { &hf_ieee802154_frame_type,
5656         { "Frame Type",                     "wpan.frame_type", FT_UINT16, BASE_HEX, VALS(ieee802154_frame_types),
5657             IEEE802154_FCF_TYPE_MASK, NULL, HFILL }},
5658 
5659         { &hf_ieee802154_security,
5660         { "Security Enabled",               "wpan.security", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_SEC_EN,
5661             "Whether security operations are performed at the MAC layer or not.", HFILL }},
5662 
5663         { &hf_ieee802154_pending,
5664         { "Frame Pending",                  "wpan.pending", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_FRAME_PND,
5665             "Indication of additional packets waiting to be transferred from the source device.", HFILL }},
5666 
5667         { &hf_ieee802154_ack_request,
5668         { "Acknowledge Request",            "wpan.ack_request", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_ACK_REQ,
5669             "Whether the sender of this packet requests acknowledgment or not.", HFILL }},
5670 
5671         { &hf_ieee802154_pan_id_compression,
5672         { "PAN ID Compression",             "wpan.pan_id_compression", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_PAN_ID_COMPRESSION,
5673             "Whether this packet contains the PAN ID or not.", HFILL }},
5674 
5675         { &hf_ieee802154_fcf_reserved,
5676         { "Reserved",                       "wpan.fcf.reserved", FT_BOOLEAN, 16, NULL, 0x0080,
5677             NULL, HFILL }},
5678 
5679         { &hf_ieee802154_seqno_suppression,
5680         { "Sequence Number Suppression",    "wpan.seqno_suppression", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_SEQNO_SUPPRESSION,
5681             "Whether this packet contains the Sequence Number or not.", HFILL }},
5682 
5683         { &hf_ieee802154_ie_present,
5684         { "Information Elements Present",   "wpan.ie_present", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_IE_PRESENT,
5685             "Whether this packet contains the Information Elements or not.", HFILL }},
5686 
5687         { &hf_ieee802154_dst_addr_mode,
5688         { "Destination Addressing Mode",    "wpan.dst_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
5689             IEEE802154_FCF_DADDR_MASK, NULL, HFILL }},
5690 
5691         { &hf_ieee802154_version,
5692         { "Frame Version",                  "wpan.version", FT_UINT16, BASE_DEC, VALS(ieee802154_frame_versions),
5693             IEEE802154_FCF_VERSION, NULL, HFILL }},
5694 
5695         { &hf_ieee802154_src_addr_mode,
5696         { "Source Addressing Mode",         "wpan.src_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
5697             IEEE802154_FCF_SADDR_MASK, NULL, HFILL }},
5698 
5699         /* 802.15.4-2015 Multipurpose frame control fields */
5700         { &hf_ieee802154_mpf_long_frame_control,
5701         { "Long Frame Control",             "wpan.long_frame_control", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_LONG_FC,
5702             "Whether this frame control field uses one or two octets.", HFILL }},
5703 
5704         { &hf_ieee802154_mpf_dst_addr_mode,
5705         { "Destination Addressing Mode",    "wpan.dst_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
5706             IEEE802154_MPF_FCF_DADDR_MASK, NULL, HFILL }},
5707 
5708         { &hf_ieee802154_mpf_src_addr_mode,
5709         { "Source Addressing Mode",         "wpan.src_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
5710             IEEE802154_MPF_FCF_SADDR_MASK, NULL, HFILL }},
5711 
5712         { &hf_ieee802154_mpf_pan_id_present,
5713         { "PAN ID Present",                 "wpan.pan_id_present", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_PAN_ID_PRESENT,
5714             "Whether this packet contains the destination PAN ID or not", HFILL }},
5715 
5716         { &hf_ieee802154_mpf_security,
5717         { "Security Enabled",               "wpan.security", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_SEC_EN,
5718             "Whether security operations are performed at the MAC layer or not.", HFILL }},
5719 
5720         { &hf_ieee802154_mpf_seqno_suppression,
5721         { "Sequence Number Suppression",    "wpan.seqno_suppression", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_SEQNO_SUPPRESSION,
5722             "Whether this packet contains the Sequence Number or not.", HFILL }},
5723 
5724         { &hf_ieee802154_mpf_pending,
5725         { "Frame Pending",                  "wpan.pending", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_FRAME_PND,
5726             "Indication of additional packets waiting to be transferred from the source device.", HFILL }},
5727 
5728         { &hf_ieee802154_mpf_version,
5729         { "Multipurpose Frame Version",     "wpan.mpf_version", FT_UINT16, BASE_DEC, NULL,
5730             IEEE802154_MPF_FCF_VERSION, NULL, HFILL }},
5731 
5732         { &hf_ieee802154_mpf_ack_request,
5733         { "Acknowledge Request",            "wpan.ack_request", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_ACK_REQ,
5734             "Whether the sender of this packet requests acknowledgment or not.", HFILL }},
5735 
5736         { &hf_ieee802154_mpf_ie_present,
5737         { "Information Elements Present",   "wpan.ie_present", FT_BOOLEAN, 16, NULL, IEEE802154_MPF_FCF_IE_PRESENT,
5738             "Whether this packet contains the Information Elements or not.", HFILL }},
5739 
5740         { &hf_ieee802154_seqno,
5741         { "Sequence Number",                "wpan.seq_no", FT_UINT8, BASE_DEC, NULL, 0x0,
5742             NULL, HFILL }},
5743 
5744         { &hf_ieee802154_dst_panID,
5745         { "Destination PAN",                "wpan.dst_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
5746             NULL, HFILL }},
5747 
5748         { &hf_ieee802154_dst16,
5749         { "Destination",                    "wpan.dst16", FT_UINT16, BASE_HEX, NULL, 0x0,
5750             NULL, HFILL }},
5751 
5752         { &hf_ieee802154_dst64,
5753         { "Destination",                    "wpan.dst64", FT_EUI64, BASE_NONE, NULL, 0x0,
5754             NULL, HFILL }},
5755 
5756         { &hf_ieee802154_src_panID,
5757         { "Source PAN",                     "wpan.src_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
5758             NULL, HFILL }},
5759 
5760         { &hf_ieee802154_src16,
5761         { "Source",                         "wpan.src16", FT_UINT16, BASE_HEX, NULL, 0x0,
5762             NULL, HFILL }},
5763 
5764         { &hf_ieee802154_src64,
5765         { "Extended Source",                "wpan.src64", FT_EUI64, BASE_NONE, NULL, 0x0,
5766             NULL, HFILL }},
5767 
5768         { &hf_ieee802154_addr16,
5769         { "Address",                        "wpan.addr16", FT_UINT16, BASE_HEX, NULL, 0x0,
5770             NULL, HFILL }},
5771 
5772         { &hf_ieee802154_addr64,
5773         { "Extended Address",               "wpan.addr64", FT_EUI64, BASE_NONE, NULL, 0x0,
5774             NULL, HFILL }},
5775 
5776         { &hf_ieee802154_src64_origin,
5777         { "Origin",                         "wpan.src64.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5778             NULL, HFILL }},
5779 
5780         { &hf_ieee802154_fcs,
5781         { "FCS",                            "wpan.fcs", FT_UINT16, BASE_HEX, NULL, 0x0,
5782             NULL, HFILL }},
5783 
5784         { &hf_ieee802154_fcs32,
5785         { "FCS",                            "wpan.fcs32", FT_UINT32, BASE_HEX, NULL, 0x0,
5786             NULL, HFILL }},
5787 
5788         { &hf_ieee802154_rssi,
5789         { "RSSI",                           "wpan.rssi", FT_INT8, BASE_DEC|BASE_UNIT_STRING, &units_decibels, 0x0,
5790             "Received Signal Strength", HFILL }},
5791 
5792         { &hf_ieee802154_fcs_ok,
5793         { "FCS Valid",                      "wpan.fcs_ok", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5794             NULL, HFILL }},
5795 
5796         { &hf_ieee802154_correlation,
5797         { "LQI Correlation Value",          "wpan.correlation", FT_UINT8, BASE_DEC, NULL, 0x0,
5798             NULL, HFILL }},
5799 
5800         /* Information Elements */
5801 
5802         { &hf_ieee802154_ie_unknown_content,
5803         { "Unknown Content",                "wpan.ie.unknown_content", FT_BYTES, SEP_SPACE, NULL, 0x0,
5804             NULL, HFILL }},
5805 
5806         /* Header IE */
5807 
5808         { &hf_ieee802154_header_ies,
5809         { "Header IEs",                     "wpan.header_ie", FT_NONE, BASE_NONE, NULL,
5810             0x0, NULL, HFILL }},
5811 
5812         { &hf_ieee802154_header_ie_tlv,
5813           { "IE Header",                    "wpan.header_ie_tlv", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}},
5814 
5815         { &hf_ieee802154_header_ie_type,
5816         { "Type",                           "wpan.header_ie.type", FT_UINT16, BASE_DEC, VALS(ieee802154_ie_types),
5817                 IEEE802154_HEADER_IE_TYPE_MASK, NULL, HFILL }},
5818 
5819         { &hf_ieee802154_header_ie_id,
5820         { "Id",                             "wpan.header_ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_header_ie_names),
5821                 IEEE802154_HEADER_IE_ID_MASK, NULL, HFILL }},
5822 
5823         { &hf_ieee802154_header_ie_length,
5824         { "Length",                         "wpan.header_ie.length", FT_UINT16, BASE_DEC, NULL,
5825                 IEEE802154_HEADER_IE_LENGTH_MASK, NULL, HFILL }},
5826 
5827 
5828         /* Individual Header IEs */
5829 
5830         { &hf_ieee802154_hie_unsupported,
5831         { "Unsupported Header IE",          "wpan.header_ie.unsupported", FT_NONE, BASE_NONE, NULL, 0x0,
5832             NULL, HFILL }},
5833 
5834         { &hf_ieee802154_hie_ht1,
5835         { "Header Termination 1 IE (Payload IEs follow)", "wpan.header_ie.ht1", FT_NONE, BASE_NONE, NULL, 0x0,
5836             NULL, HFILL }},
5837 
5838         { &hf_ieee802154_hie_ht2,
5839         { "Header Termination 2 IE (Payload follows)",    "wpan.header_ie.ht2", FT_NONE, BASE_NONE, NULL, 0x0,
5840             NULL, HFILL }},
5841 
5842 
5843         /* Time correction IE */
5844         { &hf_ieee802154_hie_time_correction,
5845         { "Time Correction IE",             "wpan.header_ie.time_correction", FT_NONE, BASE_NONE, NULL, 0x0,
5846             NULL, HFILL }},
5847 
5848         { &hf_ieee802154_hie_time_correction_time_sync_info,
5849         { "Time Sync Info",                 "wpan.header_ie.time_correction.time_sync_info", FT_UINT16, BASE_HEX, NULL, 0x0,
5850             NULL, HFILL }},
5851 
5852         { &hf_ieee802154_nack,
5853         { "Nack",                           "wpan.nack", FT_BOOLEAN, 16, TFS(&hf_ieee802154_nack_tfs), 0x8000,
5854             NULL, HFILL }},
5855 
5856         { &hf_ieee802154_hie_time_correction_value,
5857         { "Time Correction",                "wpan.header_ie.time_correction.value", FT_INT16, BASE_DEC|BASE_UNIT_STRING, &units_microseconds, 0x0FFF,
5858             "Time correction in microseconds", HFILL }},
5859 
5860         /* CSL IE */
5861         { &hf_ieee802154_hie_csl,
5862         { "CSL IE", "wpan.header_ie.csl", FT_NONE, BASE_NONE, NULL, 0x0,
5863             NULL, HFILL }},
5864 
5865         { &hf_ieee802154_hie_csl_phase,
5866         { "Phase", "wpan.header_ie.csl.phase", FT_INT16, BASE_DEC, NULL, 0x0,
5867             "CSL Phase in units of 10 symbols", HFILL }},
5868 
5869         { &hf_ieee802154_hie_csl_period,
5870         { "Period", "wpan.header_ie.csl.period", FT_INT16, BASE_DEC, NULL, 0x0,
5871             "CSL Period in units of 10 symbols", HFILL }},
5872 
5873         { &hf_ieee802154_hie_csl_rendezvous_time,
5874         { "Rendezvous Time", "wpan.header_ie.csl.rendezvous_time", FT_INT16, BASE_DEC, NULL, 0x0,
5875             "CSL Rendezvous Time in units of 10 symbols", HFILL }},
5876 
5877         /* Global Time IE */
5878         { &hf_ieee802154_hie_global_time,
5879         { "Global Time IE",                 "wpan.header_ie.global_time", FT_NONE, BASE_NONE, NULL, 0x0,
5880             NULL, HFILL }},
5881 
5882         { &hf_ieee802154_hie_global_time_value,
5883         { "Global Time",                    "wpan.header_ie.global_time.value", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0,
5884             NULL, HFILL }},
5885 
5886 		/* Vendor Specific IE */
5887         { &hf_ieee802154_hie_vendor_specific,
5888         { "Vendor Specific IE",             "wpan.header_ie.vendor_specific", FT_NONE, BASE_NONE, NULL, 0x0,
5889             NULL, HFILL }},
5890 
5891         { &hf_ieee802154_hie_vendor_specific_vendor_oui,
5892         { "Vendor OUI",                 "wpan.header_ie.vendor_specific.vendor_oui", FT_UINT24, BASE_OUI, NULL, 0x0,
5893             NULL, HFILL }},
5894 
5895 		{ &hf_ieee802154_hie_vendor_specific_content,
5896         { "Vendor Content",                "wpan.header_ie.vendor_specific.content", FT_BYTES, SEP_SPACE, NULL, 0x0,
5897             NULL, HFILL }},
5898 
5899         /* Payload IEs */
5900 
5901         { &hf_ieee802154_payload_ies,
5902         { "Payload IEs",                    "wpan.payload_ie", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5903 
5904         { &hf_ieee802154_payload_ie_tlv,
5905         { "IE Header",                      "wpan.payload_ie_tlv", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5906 
5907         { &hf_ieee802154_payload_ie_type,
5908         { "Type",                           "wpan.payload_ie.type", FT_UINT16, BASE_DEC, VALS(ieee802154_ie_types),
5909                 IEEE802154_PAYLOAD_IE_TYPE_MASK, NULL, HFILL }},
5910 
5911         { &hf_ieee802154_payload_ie_id,
5912         { "Id",                             "wpan.payload_ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_payload_ie_names),
5913                 IEEE802154_PAYLOAD_IE_ID_MASK, NULL, HFILL }},
5914 
5915         { &hf_ieee802154_payload_ie_length,
5916         { "Length",                         "wpan.payload_ie.length", FT_UINT16, BASE_DEC, NULL,
5917                 IEEE802154_PAYLOAD_IE_LENGTH_MASK, NULL, HFILL }},
5918 
5919 
5920         /* Individual Payload IEs */
5921 
5922         { &hf_ieee802154_pie_unsupported,
5923         { "Unknown Payload IE",             "wpan.payload_ie.unknown", FT_NONE, BASE_NONE, NULL, 0x0,
5924             NULL, HFILL }},
5925 
5926         { &hf_ieee802154_pie_termination,
5927         { "Payload Termination IE",         "wpan.payload_ie.termination", FT_NONE, BASE_NONE, NULL, 0x0,
5928             NULL, HFILL }},
5929 
5930         { &hf_ieee802154_pie_vendor,
5931         { "Vendor Specific IE",             "wpan.payload_ie.vendor", FT_NONE, BASE_NONE, NULL, 0x0,
5932             NULL, HFILL }},
5933 
5934         { &hf_ieee802154_pie_vendor_oui,
5935         { "Vendor OUI",                     "wpan.payload_ie.vendor.oui", FT_UINT24, BASE_OUI, NULL, 0x0,
5936             NULL, HFILL }},
5937 
5938         { &hf_ieee802154_mlme,
5939         { "MLME IE",                        "wpan.mlme", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5940 
5941         { &hf_ieee802154_psie_type,
5942         { "Type",                           "wpan.mlme.ie.type", FT_UINT16, BASE_DEC, VALS(ieee802154_psie_types),
5943                 IEEE802154_PSIE_TYPE_MASK, NULL, HFILL }},
5944 
5945         { &hf_ieee802154_psie,
5946         { "MLME Sub IE",                    "wpan.mlme.ie", FT_UINT16, BASE_HEX, NULL,
5947             0x0, NULL, HFILL }},
5948 
5949         { &hf_ieee802154_psie_id_short,
5950         { "Sub ID",                         "wpan.mlme.ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_psie_names),
5951                 IEEE802154_PSIE_ID_MASK_SHORT, NULL, HFILL }},
5952 
5953         { &hf_ieee802154_psie_length_short,
5954         { "Length",                         "wpan.mlme.ie.length", FT_UINT16, BASE_DEC, NULL,
5955                 IEEE802154_PSIE_LENGTH_MASK_SHORT, NULL, HFILL }},
5956 
5957         { &hf_ieee802154_psie_id_long,
5958         { "Sub ID",                         "wpan.mlme.ie.id", FT_UINT16, BASE_HEX, VALS(ieee802154_psie_names),
5959                 IEEE802154_PSIE_ID_MASK_LONG, NULL, HFILL }},
5960 
5961         { &hf_ieee802154_psie_length_long,
5962         { "Length",                         "wpan.mlme.ie.length", FT_UINT16, BASE_DEC, NULL,
5963                 IEEE802154_PSIE_LENGTH_MASK_LONG, NULL, HFILL }},
5964 
5965         { &hf_ieee802154_mlme_ie_unsupported,
5966         { "Unsupported Sub IE",             "wpan.mlme.unsupported", FT_NONE, BASE_NONE, NULL,
5967               0, NULL, HFILL }},
5968 
5969         { &hf_ieee802154_mlme_ie_data,
5970         { "Data",                            "wpan.mlme.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5971 
5972         { &hf_ieee802154_psie_eb_filter,
5973         { "Enhanced Beacon Filter",         "wpan.eb_filter", FT_UINT8, BASE_HEX, NULL,
5974               0, NULL, HFILL }},
5975 
5976         { &hf_ieee802154_psie_eb_filter_pjoin,
5977         { "Permit Join Filter",             "wpan.eb_filter.pjoin", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
5978               IEEE802154_MLME_PSIE_EB_FLT_PJOIN, NULL, HFILL }},
5979 
5980         { &hf_ieee802154_psie_eb_filter_lqi,
5981         { "LQI Filter",                     "wpan.eb_filter.lqi", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
5982             IEEE802154_MLME_PSIE_EB_FLT_LQI, NULL, HFILL }},
5983 
5984         { &hf_ieee802154_psie_eb_filter_lqi_min,
5985         { "Minimum LQI",                    "wpan.eb_filter.lqi_minimum", FT_UINT8, BASE_DEC, NULL,
5986              0x0, NULL, HFILL }},
5987 
5988         { &hf_ieee802154_psie_eb_filter_percent,
5989         { "Probability to Respond",         "wpan.eb_filter.contains_prob", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled),
5990             IEEE802154_MLME_PSIE_EB_FLT_PERCENT, NULL, HFILL }},
5991 
5992         { &hf_ieee802154_psie_eb_filter_percent_prob,
5993         { "Response Probability Percentage", "wpan.eb_filter.prob", FT_UINT8, BASE_DEC, NULL,
5994                  0x0, NULL, HFILL }},
5995 
5996         { &hf_ieee802154_psie_eb_filter_attr_id,
5997         { "Requested Attribute Length",      "wpan.eb_filter.attr_id", FT_UINT8, BASE_DEC, NULL,
5998             IEEE802154_MLME_PSIE_EB_FLT_ATTR_LEN, NULL, HFILL }},
5999 
6000         { &hf_ieee802154_psie_eb_filter_attr_id_bitmap,
6001         { "Attribute ID Bitmap",             "wpan.eb_filter.attr_id_bits", FT_UINT24, BASE_HEX, NULL,
6002                 0x0, NULL, HFILL }},
6003 
6004         { &hf_ieee802154_tsch_sync,
6005           { "TSCH Synchronization IE",      "wpan.tsch.time_sync", FT_NONE, BASE_NONE, NULL, 0x0,
6006             NULL, HFILL }},
6007 
6008         { &hf_ieee802154_tsch_asn,
6009         { "Absolute Slot Number",           "wpan.tsch.asn", FT_UINT40, BASE_DEC, NULL, 0x0,
6010             NULL, HFILL }},
6011 
6012         { &hf_ieee802154_tsch_join_metric,
6013         { "Join Metric",                    "wpan.tsch.join_metric", FT_UINT8, BASE_DEC, NULL, 0x0,
6014             NULL, HFILL }},
6015 
6016         { &hf_ieee802154_tsch_timeslot,
6017           { "TSCH Timeslot IE",             "wpan.tsch.timeslot", FT_NONE, BASE_NONE, NULL, 0x0,
6018             NULL, HFILL }},
6019 
6020         { &hf_ieee802154_tsch_timeslot_id,
6021           { "Timeslot ID",                  "wpan.tsch.timeslot.id", FT_UINT8, BASE_HEX, NULL, 0x0,
6022             "Identifier of the Timeslot Template", HFILL }},
6023 
6024         { &hf_ieee802154_tsch_timeslot_cca_offset,
6025           { "CCA Offset",                   "wpan.tsch.timeslot.cca_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6026             "Time between the beginning of the timeslot and the start of CCA", HFILL }},
6027 
6028         { &hf_ieee802154_tsch_timeslot_cca,
6029           { "CCA",                          "wpan.tsch.timeslot.cca", FT_UINT16, BASE_DEC, NULL, 0x0,
6030             "Duration of CCA", HFILL }},
6031 
6032         { &hf_ieee802154_tsch_timeslot_tx_offset,
6033           { "TX Offset",                    "wpan.tsch.timeslot.tx_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6034             "Time between the beginning of the timeslot and the start of frame transmission", HFILL }},
6035 
6036         { &hf_ieee802154_tsch_timeslot_rx_offset,
6037           { "RX Offset",                    "wpan.tsch.timeslot.rx_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6038             "Time between the beginning of the timeslot to when the receiver shall be listening", HFILL }},
6039 
6040         { &hf_ieee802154_tsch_timeslot_rx_ack_delay,
6041           { "RX Ack Delay",                "wpan.tsch.timeslot.rx_ack_delay", FT_UINT16, BASE_DEC, NULL, 0x0,
6042             "Time between the end of frame to when the transmitter shall listen for acknowledgment", HFILL }},
6043 
6044         { &hf_ieee802154_tsch_timeslot_tx_ack_delay,
6045           { "TX Ack Delay",                "wpan.tsch.timeslot.tx_ack_delay", FT_UINT16, BASE_DEC, NULL, 0x0,
6046             "Time between the end of frame to start of acknowledgment", HFILL }},
6047 
6048         { &hf_ieee802154_tsch_timeslot_rx_wait,
6049           { "RX Wait",                      "wpan.tsch.timeslot.rx_wait", FT_UINT16, BASE_DEC, NULL, 0x0,
6050             "Time to wait for the start of frame", HFILL }},
6051 
6052         { &hf_ieee802154_tsch_timeslot_ack_wait,
6053           { "Ack Wait",                     "wpan.tsch.timeslot.ack_wait", FT_UINT16, BASE_DEC, NULL, 0x0,
6054             "Minimum time to wait for the start of an acknowledgment", HFILL }},
6055 
6056         { &hf_ieee802154_tsch_timeslot_turnaround,
6057           { "Turn Around",                  "wpan.tsch.timeslot.turnaround", FT_UINT16, BASE_DEC, NULL, 0x0,
6058             "Transmit to receive turnaround time", HFILL }},
6059 
6060         { &hf_ieee802154_tsch_timeslot_max_ack,
6061           { "Max Ack",                      "wpan.tsch.timeslot.max_ack", FT_UINT16, BASE_DEC, NULL, 0x0,
6062             "Transmission time to send an acknowledgment", HFILL }},
6063 
6064         { &hf_ieee802154_tsch_timeslot_max_tx,
6065           { "Max TX",                      "wpan.tsch.timeslot.max_tx", FT_UINT24, BASE_DEC, NULL, 0x0,
6066             "Transmission time to send the maximum length frame", HFILL }},
6067 
6068         { &hf_ieee802154_tsch_timeslot_length,
6069           { "Timeslot Length",              "wpan.tsch.timeslot.length", FT_UINT24, BASE_DEC, NULL, 0x0,
6070             "Total length of the timeslot, including any unused time after frame transmission", HFILL }},
6071 
6072         { &hf_ieee802154_tsch_channel_hopping,
6073         { "Channel Hopping IE",             "wpan.channel_hopping", FT_NONE, BASE_NONE, NULL, 0x0,
6074             NULL, HFILL }},
6075 
6076         { &hf_ieee802154_tsch_slotframe,
6077         { "Slotframe IE", "wpan.tsch.slotframe", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6078 
6079         { &hf_ieee802154_tsch_link_info,
6080         { "Link Information", "wpan.tsch.link_info", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6081 
6082         { &hf_ieee802154_tsch_slotf_link_nb_slotf,
6083         { "Number of Slotframes",           "wpan.tsch.slotframe_num", FT_UINT8, BASE_DEC, NULL, 0x0,
6084             NULL, HFILL }},
6085 
6086         { &hf_ieee802154_tsch_slotf_link_slotf_handle,
6087         { "Slotframe handle",               "wpan.tsch.slotframe_handle", FT_UINT8, BASE_DEC, NULL, 0x0,
6088             NULL, HFILL }},
6089 
6090         { &hf_ieee802154_tsch_slotf_size,
6091         { "Slotframe size",                 "wpan.tsch.slotframe_size", FT_UINT16, BASE_DEC, NULL, 0x0,
6092             NULL, HFILL }},
6093 
6094         { &hf_ieee802154_tsch_slotf_link_nb_links,
6095         { "Number of Links",                "wpan.tsch.nb_links", FT_UINT8, BASE_DEC, NULL, 0x0,
6096             NULL, HFILL }},
6097 
6098         { &hf_ieee802154_tsch_slotf_link_timeslot,
6099         { "Timeslot",                       "wpan.tsch.link_timeslot", FT_UINT16, BASE_DEC, NULL, 0x0,
6100             NULL, HFILL }},
6101 
6102         { &hf_ieee802154_tsch_slotf_link_channel_offset,
6103         { "Channel Offset",                 "wpan.tsch.channel_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6104             NULL, HFILL }},
6105 
6106         { &hf_ieee802154_tsch_slotf_link_options,
6107         { "Link Options",                   "wpan.tsch.link_options", FT_UINT8, BASE_HEX, NULL, 0x0,
6108             NULL, HFILL }},
6109 
6110         { &hf_ieee802154_tsch_slotf_link_options_tx,
6111         { "TX Link",                        "wpan.tsch.link_options.tx", FT_BOOLEAN, 8, NULL, (1 << 0),
6112             NULL, HFILL }},
6113 
6114         { &hf_ieee802154_tsch_slotf_link_options_rx,
6115         { "RX Link",                        "wpan.tsch.link_options.rx", FT_BOOLEAN, 8, NULL, (1 << 1),
6116             NULL, HFILL }},
6117 
6118         { &hf_ieee802154_tsch_slotf_link_options_shared,
6119         { "Shared Link",                    "wpan.tsch.link_options.shared", FT_BOOLEAN, 8, NULL, (1 << 2),
6120             NULL, HFILL }},
6121 
6122         { &hf_ieee802154_tsch_slotf_link_options_timkeeping,
6123         { "Timekeeping",                    "wpan.tsch.link_options.timekeeping", FT_BOOLEAN, 8, NULL, (1 << 3),
6124             NULL, HFILL }},
6125 
6126         { &hf_ieee802154_tsch_slotf_link_options_priority,
6127         { "Priority",                       "wpan.tsch.link_options.priority", FT_BOOLEAN, 8, NULL, (1 << 4),
6128             NULL, HFILL }},
6129 
6130         { &hf_ieee802154_tsch_hopping_sequence_id,
6131         { "Hopping Sequence ID",            "wpan.tsch.hopping_sequence_id", FT_UINT8, BASE_HEX, NULL, 0x0,
6132             NULL, HFILL }},
6133 
6134         /* IETF IE */
6135         { &hf_ieee802154_pie_ietf,
6136         { "IETF Payload IE",                 "wpan.payload_ie.ietf", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
6137 
6138         { &hf_ieee802154_p_ie_ietf_sub_id,
6139         { "Sub-ID",                          "wpan.ietf_ie.sub_id", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
6140 
6141         /* IETF IE - 6top IE */
6142         { &hf_ieee802154_6top,
6143         { "6top IE", "wpan.6top", FT_NONE, BASE_NONE, NULL, 0x0,
6144           NULL, HFILL }},
6145 
6146         { &hf_ieee802154_6top_version,
6147         { "6P Version", "wpan.6top_version", FT_UINT8, BASE_DEC, NULL, IETF_6TOP_VERSION,
6148           NULL, HFILL }},
6149 
6150         { &hf_ieee802154_6top_type,
6151           { "Type", "wpan.6top_type", FT_UINT8, BASE_HEX, VALS(ietf_6top_types), IETF_6TOP_TYPE,
6152           NULL, HFILL }},
6153 
6154         { &hf_ieee802154_6top_flags_reserved,
6155         { "Reserved", "wpan.6top_flags_reserved", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_FLAGS_RESERVED,
6156           NULL, HFILL }},
6157 
6158         { &hf_ieee802154_6top_code,
6159         { "Code",  "wpan.6top_code", FT_UINT8, BASE_HEX, NULL, 0x0,
6160           NULL, HFILL }},
6161 
6162         { &hf_ieee802154_6top_sfid,
6163         { "SFID (6top Scheduling Function ID)", "wpan.6top_sfid", FT_UINT8, BASE_HEX, NULL, 0x0,
6164           NULL, HFILL }},
6165 
6166         { &hf_ieee802154_6top_seqnum,
6167         { "SeqNum", "wpan.6top_seqnum", FT_UINT8, BASE_DEC, NULL, IETF_6TOP_SEQNUM,
6168           NULL, HFILL }},
6169 
6170         { &hf_ieee802154_6top_metadata,
6171         { "Metadata", "wpan.6top_metadata", FT_UINT16, BASE_HEX, NULL, 0x0,
6172           NULL, HFILL }},
6173 
6174         { &hf_ieee802154_6top_cell_options,
6175           { "Cell Options", "wpan.6top_cell_options", FT_UINT8, BASE_HEX, VALS(ietf_6top_cell_options), 0x0,
6176           NULL, HFILL }},
6177 
6178         { &hf_ieee802154_6top_cell_option_tx,
6179         { "Transmit (TX) Cell", "wpan.6top_cell_option_tx", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_TX,
6180           NULL, HFILL }},
6181 
6182         { &hf_ieee802154_6top_cell_option_rx,
6183         { "Receive (RX) Cell", "wpan.6top_cell_option_rx", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_RX,
6184           NULL, HFILL }},
6185 
6186         { &hf_ieee802154_6top_cell_option_shared,
6187         { "SHARED Cell", "wpan.6top_cell_option_shared", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_SHARED,
6188           NULL, HFILL }},
6189 
6190         { &hf_ieee802154_6top_cell_option_reserved,
6191         { "Reserved", "wpan.6top_cell_option_reserved", FT_UINT8, BASE_HEX, NULL, IETF_6TOP_CELL_OPTION_RESERVED,
6192           NULL, HFILL }},
6193 
6194         { &hf_ieee802154_6top_num_cells,
6195         { "Number of Cells", "wpan.6top_num_cells", FT_UINT8, BASE_DEC, NULL, 0x0,
6196           NULL, HFILL }},
6197 
6198         { &hf_ieee802154_6top_cell_list,
6199         { "CellList", "wpan.6top_cell_list", FT_NONE, BASE_NONE, NULL, 0x0,
6200           NULL, HFILL }},
6201 
6202         { &hf_ieee802154_6top_rel_cell_list,
6203         { "Rel. CellList", "wpan.6top_rel_cell_list", FT_NONE, BASE_NONE, NULL, 0x0,
6204           NULL, HFILL }},
6205 
6206         { &hf_ieee802154_6top_cand_cell_list,
6207         { "Cand. CellList", "wpan.6top_cand_cell_list", FT_NONE, BASE_NONE, NULL, 0x0,
6208           NULL, HFILL }},
6209 
6210         { &hf_ieee802154_6top_cell,
6211         { "Cell", "wpan.6top_cell", FT_BYTES, BASE_NONE, NULL, 0x0,
6212           NULL, HFILL }},
6213 
6214         { &hf_ieee802154_6top_reserved,
6215         { "Reserved", "wpan.6top_reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
6216           NULL, HFILL }},
6217 
6218         { &hf_ieee802154_6top_offset,
6219         { "Offset", "wpan.6top_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
6220           NULL, HFILL }},
6221 
6222         { &hf_ieee802154_6top_max_num_cells,
6223         { "Maximum Number of Requested Cells", "wpan.6top_max_num_cells", FT_UINT16, BASE_DEC, NULL, 0x0,
6224           NULL, HFILL }},
6225 
6226         { &hf_ieee802154_6top_slot_offset,
6227         { "Slot Offset", "wpan.6top_cell_slot_offset", FT_UINT16, BASE_HEX, NULL, 0x0,
6228           NULL, HFILL }},
6229 
6230         { &hf_ieee802154_6top_channel_offset,
6231         { "Channel Offset", "wpan.6top_channel_offset", FT_UINT16, BASE_HEX, NULL, 0x0,
6232           NULL, HFILL }},
6233 
6234         { &hf_ieee802154_6top_total_num_cells,
6235         { "Total Number of Cells", "wpan.6top_total_num_cells", FT_UINT16, BASE_DEC, NULL, 0x0,
6236           NULL, HFILL }},
6237 
6238         { &hf_ieee802154_6top_payload,
6239         { "Payload", "wpan.6top_payload", FT_BYTES, BASE_NONE, NULL, 0x0,
6240           NULL, HFILL }},
6241 
6242         /* MPX IE (IEEE 802.15.9) */
6243         { &hf_ieee802159_mpx,
6244           { "MPX IE", "wpan.mpx", FT_NONE, BASE_NONE, NULL, 0x0,
6245             NULL, HFILL }
6246         },
6247 
6248         { &hf_ieee802159_mpx_transaction_control,
6249           { "Transaction Control", "wpan.mpx.transaction_control", FT_UINT8, BASE_HEX, NULL, 0x0,
6250             NULL, HFILL }
6251         },
6252 
6253         { &hf_ieee802159_mpx_transfer_type,
6254           { "Transfer Type", "wpan.mpx.transfer_type", FT_UINT8, BASE_HEX, VALS(mpx_transfer_type_vals), IEEE802159_MPX_TRANSFER_TYPE_MASK,
6255             NULL, HFILL }
6256         },
6257 
6258         { &hf_ieee802159_mpx_transaction_id,
6259           { "Transaction ID", "wpan.mpx.transaction_id", FT_UINT8, BASE_HEX, NULL, IEEE802159_MPX_TRANSACTION_ID_MASK,
6260             NULL, HFILL }
6261         },
6262 
6263         { &hf_ieee802159_mpx_transaction_id_as_multiplex_id,
6264           { "Multiplex ID", "wpan.mpx.multiplex_id", FT_UINT8, BASE_HEX, VALS(mpx_multiplex_id_vals), IEEE802159_MPX_TRANSACTION_ID_MASK,
6265             "Transaction ID used as Multiplex ID", HFILL }
6266         },
6267 
6268         { &hf_ieee802159_mpx_fragment_number,
6269           { "Fragment Number", "wpan.mpx.fragment_number", FT_UINT8, BASE_DEC, NULL, 0x0,
6270             NULL, HFILL }
6271         },
6272 
6273         { &hf_ieee802159_mpx_total_frame_size,
6274           { "Total Frame Size", "wpan.mpx.total_frame_size", FT_UINT16, BASE_DEC, NULL, 0x0,
6275             "Total Upper-Layer Frame Size", HFILL }
6276         },
6277 
6278         { &hf_ieee802159_mpx_multiplex_id,
6279           { "Multiplex ID", "wpan.mpx.multiplex_id", FT_UINT16, BASE_HEX, NULL, 0x0,
6280             NULL, HFILL }
6281         },
6282 
6283         { &hf_ieee802159_mpx_kmp_id,
6284           { "KMP ID", "wpan.mpx.kmp.id", FT_UINT8, BASE_DEC, VALS(ieee802154_mpx_kmp_id_vals), 0x0,
6285             NULL, HFILL }
6286         },
6287 
6288         { &hf_ieee802159_mpx_kmp_vendor_oui,
6289           { "Vendor OUI", "wpan.mpx.kmp.vendor_oui", FT_UINT24, BASE_OUI, NULL, 0x0,
6290             NULL, HFILL }
6291         },
6292 
6293         { &hf_ieee802159_mpx_fragment,
6294           { "Upper-Layer Frame Fragment", "wpan.mpx.fragment", FT_BYTES, SEP_SPACE, NULL, 0x0,
6295             NULL, HFILL }
6296         },
6297 
6298         { &hf_ieee802159_mpx_wisun_subid,
6299           { "Wi-SUN Multiplex Sub ID", "wpan.mpx.wisun", FT_UINT8, BASE_HEX, VALS(mpx_wisun_subid_vals), 0x0,
6300             NULL, HFILL }
6301         },
6302 
6303         /* Command Frame Specific Fields */
6304 
6305         { &hf_ieee802154_cmd_id,
6306         { "Command Identifier",         "wpan.cmd", FT_UINT8, BASE_HEX, VALS(ieee802154_cmd_names), 0x0,
6307             NULL, HFILL }},
6308 
6309         { &hf_ieee802154_cmd_vendor_oui,
6310         { "Vendor OUI",                 "wpan.cmd.vendor_oui", FT_UINT24, BASE_OUI, NULL, 0x0,
6311             NULL, HFILL }},
6312 
6313         /*  Capability Information Fields */
6314 
6315         { &hf_ieee802154_cinfo_alt_coord,
6316         { "Alternate PAN Coordinator",  "wpan.cinfo.alt_coord", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALT_PAN_COORD,
6317             "Whether this device can act as a PAN coordinator or not.", HFILL }},
6318 
6319         { &hf_ieee802154_cinfo_device_type,
6320         { "Device Type",                "wpan.cinfo.device_type", FT_BOOLEAN, 8, TFS(&tfs_cinfo_device_type), IEEE802154_CMD_CINFO_DEVICE_TYPE,
6321             "Whether this device is RFD (reduced-function device) or FFD (full-function device).", HFILL }},
6322 
6323         { &hf_ieee802154_cinfo_power_src,
6324         { "Power Source",               "wpan.cinfo.power_src", FT_BOOLEAN, 8, TFS(&tfs_cinfo_power_src), IEEE802154_CMD_CINFO_POWER_SRC,
6325             "Whether this device is operating on AC/mains or battery power.", HFILL }},
6326 
6327         { &hf_ieee802154_cinfo_idle_rx,
6328         { "Receive On When Idle",       "wpan.cinfo.idle_rx", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_IDLE_RX,
6329             "Whether this device can receive packets while idle or not.", HFILL }},
6330 
6331         { &hf_ieee802154_cinfo_sec_capable,
6332         { "Security Capability",        "wpan.cinfo.sec_capable", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_SEC_CAPABLE,
6333             "Whether this device is capable of receiving encrypted packets.", HFILL }},
6334 
6335         { &hf_ieee802154_cinfo_alloc_addr,
6336         { "Allocate Address",           "wpan.cinfo.alloc_addr", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALLOC_ADDR,
6337             "Whether this device wishes to use a 16-bit short address instead of its IEEE 802.15.4 64-bit long address.", HFILL }},
6338 
6339         /*  Association response fields */
6340 
6341         { &hf_ieee802154_assoc_addr,
6342         { "Short Address",              "wpan.asoc.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
6343             "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 }},
6344 
6345         { &hf_ieee802154_assoc_status,
6346         { "Association Status",         "wpan.assoc.status", FT_UINT8, BASE_HEX, NULL, 0x0,
6347             NULL, HFILL }},
6348 
6349         { &hf_ieee802154_disassoc_reason,
6350         { "Disassociation Reason",      "wpan.disassoc.reason", FT_UINT8, BASE_HEX, NULL, 0x0,
6351             NULL, HFILL }},
6352 
6353         /*  Coordinator Realignment fields */
6354 
6355         { &hf_ieee802154_realign_pan,
6356         { "PAN ID",                     "wpan.realign.pan", FT_UINT16, BASE_HEX, NULL, 0x0,
6357             "The PAN identifier the coordinator wishes to use for future communication.", HFILL }},
6358 
6359         { &hf_ieee802154_realign_caddr,
6360         { "Coordinator Short Address",  "wpan.realign.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
6361             "The 16-bit address the coordinator wishes to use for future communication.", HFILL }},
6362 
6363         { &hf_ieee802154_realign_channel,
6364         { "Logical Channel",            "wpan.realign.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
6365             "The logical channel the coordinator wishes to use for future communication.", HFILL }},
6366 
6367         { &hf_ieee802154_realign_addr,
6368         { "Short Address",              "wpan.realign.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
6369             "A short-address that the orphaned device shall assume if applicable.", HFILL }},
6370 
6371         { &hf_ieee802154_realign_channel_page,
6372         { "Channel Page",               "wpan.realign.channel_page", FT_UINT8, BASE_DEC, NULL, 0x0,
6373             "The logical channel page the coordinator wishes to use for future communication.", HFILL }},
6374 
6375         { &hf_ieee802154_gtsreq_len,
6376         { "GTS Length",                 "wpan.gtsreq.length", FT_UINT8, BASE_DEC, NULL, IEEE802154_CMD_GTS_REQ_LEN,
6377             "Number of superframe slots the device is requesting.", HFILL }},
6378 
6379         { &hf_ieee802154_gtsreq_dir,
6380         { "GTS Direction",              "wpan.gtsreq.direction", FT_BOOLEAN, 8, TFS(&tfs_gtsreq_dir), IEEE802154_CMD_GTS_REQ_DIR,
6381             "The direction of traffic in the guaranteed timeslot.", HFILL }},
6382 
6383         { &hf_ieee802154_gtsreq_type,
6384         { "Characteristic Type",        "wpan.gtsreq.type", FT_BOOLEAN, 8, TFS(&tfs_gtsreq_type), IEEE802154_CMD_GTS_REQ_TYPE,
6385             "Whether this request is to allocate or deallocate a timeslot.", HFILL }},
6386 
6387         /* Beacon Frame Specific Fields */
6388 
6389         { &hf_ieee802154_beacon_order,
6390         { "Beacon Interval",            "wpan.beacon_order", FT_UINT16, BASE_DEC, NULL, IEEE802154_BEACON_ORDER_MASK,
6391             "Specifies the transmission interval of the beacons.", HFILL }},
6392 
6393         { &hf_ieee802154_superframe_order,
6394         { "Superframe Interval",        "wpan.superframe_order", FT_UINT16, BASE_DEC, NULL,
6395             IEEE802154_SUPERFRAME_ORDER_MASK,
6396             "Specifies the length of time the coordinator will interact with the PAN.", HFILL }},
6397 
6398         { &hf_ieee802154_cap,
6399         { "Final CAP Slot",             "wpan.cap", FT_UINT16, BASE_DEC, NULL, IEEE802154_SUPERFRAME_CAP_MASK,
6400             "Specifies the final superframe slot used by the CAP.", HFILL }},
6401 
6402         { &hf_ieee802154_superframe_battery_ext,
6403         { "Battery Extension",          "wpan.battery_ext", FT_BOOLEAN, 16, NULL, IEEE802154_BATT_EXTENSION_MASK,
6404             "Whether transmissions may not extend past the length of the beacon frame.", HFILL }},
6405 
6406         { &hf_ieee802154_superframe_coord,
6407         { "PAN Coordinator",            "wpan.bcn_coord", FT_BOOLEAN, 16, NULL, IEEE802154_SUPERFRAME_COORD_MASK,
6408             "Whether this beacon frame is being transmitted by the PAN coordinator or not.", HFILL }},
6409 
6410         { &hf_ieee802154_assoc_permit,
6411         { "Association Permit",         "wpan.assoc_permit", FT_BOOLEAN, 16, NULL, IEEE802154_ASSOC_PERMIT_MASK,
6412             "Whether this PAN is accepting association requests or not.", HFILL }},
6413 
6414         { &hf_ieee802154_gts_count,
6415         { "GTS Descriptor Count",       "wpan.gts.count", FT_UINT8, BASE_DEC, NULL, 0x0,
6416             "The number of GTS descriptors present in this beacon frame.", HFILL }},
6417 
6418         { &hf_ieee802154_gts_permit,
6419         { "GTS Permit",                 "wpan.gts.permit", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
6420             "Whether the PAN coordinator is accepting GTS requests or not.", HFILL }},
6421 
6422         { &hf_ieee802154_gts_direction,
6423         { "Direction",                  "wpan.gts.direction", FT_BOOLEAN, BASE_NONE, TFS(&ieee802154_gts_direction_tfs), 0x0,
6424             "A flag defining the direction of the GTS Slot.", HFILL }},
6425 
6426         { &hf_ieee802154_gts_address,
6427         { "Address",                    "wpan.gts.address", FT_UINT16, BASE_HEX, NULL, 0x0,
6428             NULL, HFILL }},
6429 
6430         { &hf_ieee802154_pending16,
6431         { "Address",                    "wpan.pending16", FT_UINT16, BASE_HEX, NULL, 0x0,
6432             "Device with pending data to receive.", HFILL }},
6433 
6434         { &hf_ieee802154_pending64,
6435         { "Address",                    "wpan.pending64", FT_EUI64, BASE_NONE, NULL, 0x0,
6436             "Device with pending data to receive.", HFILL }},
6437 
6438         /* Auxiliary Security Header Fields */
6439         { &hf_ieee802154_aux_security_header,
6440         { "Auxiliary Security Header", "wpan.aux_sec.hdr", FT_NONE, BASE_NONE, NULL,
6441             0x0, "The Auxiliary Security Header of the frame", HFILL }},
6442 
6443         { &hf_ieee802154_aux_sec_security_level,
6444         { "Security Level", "wpan.aux_sec.sec_level", FT_UINT8, BASE_HEX, VALS(ieee802154_sec_level_names),
6445             IEEE802154_AUX_SEC_LEVEL_MASK, "The Security Level of the frame", HFILL }},
6446 
6447         { &hf_ieee802154_aux_sec_security_control,
6448         { "Security Control Field", "wpan.aux_sec.security_control_field", FT_UINT8, BASE_HEX, NULL,
6449             0x0, NULL, HFILL }},
6450 
6451         { &hf_ieee802154_aux_sec_key_id_mode,
6452         { "Key Identifier Mode", "wpan.aux_sec.key_id_mode", FT_UINT8, BASE_HEX, VALS(ieee802154_key_id_mode_names),
6453             IEEE802154_AUX_KEY_ID_MODE_MASK,
6454             "The scheme to use by the recipient to lookup the key in its key table", HFILL }},
6455 
6456         { &hf_ieee802154_aux_sec_frame_counter_suppression,
6457         { "Frame Counter Suppression", "wpan.aux_sec.frame_counter_suppression", FT_BOOLEAN, 8, NULL,
6458             IEEE802154_AUX_FRAME_COUNTER_SUPPRESSION_MASK,
6459             "Whether the frame counter is omitted from the Auxiliary Security Header", HFILL }},
6460 
6461         { &hf_ieee802154_aux_sec_asn_in_nonce,
6462         { "ASN in Nonce", "wpan.aux_sec.asn_in_nonce", FT_BOOLEAN, 8, NULL,
6463             IEEE802154_AUX_ASN_IN_NONCE_MASK,
6464             "Whether the ASN is used to generate the nonce instead of the frame counter", HFILL }},
6465 
6466         { &hf_ieee802154_aux_sec_reserved,
6467         { "Reserved", "wpan.aux_sec.reserved", FT_UINT8, BASE_HEX, NULL, IEEE802154_AUX_CTRL_RESERVED_MASK,
6468             NULL, HFILL }},
6469 
6470         { &hf_ieee802154_aux_sec_frame_counter,
6471         { "Frame Counter", "wpan.aux_sec.frame_counter", FT_UINT32, BASE_DEC, NULL, 0x0,
6472             "Frame counter of the originator of the protected frame", HFILL }},
6473 
6474         { &hf_ieee802154_aux_sec_key_source,
6475         { "Key Source", "wpan.aux_sec.key_source", FT_UINT64, BASE_HEX, NULL, 0x0,
6476             "Key Source for processing of the protected frame", HFILL }},
6477 
6478         { &hf_ieee802154_aux_sec_key_source_bytes,
6479         { "Key Source", "wpan.aux_sec.key_source.bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
6480             "Key Source for processing of the protected frame", HFILL }},
6481 
6482         { &hf_ieee802154_aux_sec_key_index,
6483         { "Key Index", "wpan.aux_sec.key_index", FT_UINT8, BASE_HEX, NULL, 0x0,
6484             "Key Index for processing of the protected frame", HFILL }},
6485 
6486         { &hf_ieee802154_mic,
6487         { "MIC", "wpan.mic", FT_BYTES, BASE_NONE, NULL, 0x0,
6488             NULL, HFILL }},
6489 
6490         { &hf_ieee802154_key_number,
6491         { "Key Number", "wpan.key_number", FT_UINT8, BASE_DEC, NULL, 0x0,
6492             "Key number used to decode", HFILL }},
6493 
6494         /* IEEE 802.15.4-2003 Security Header Fields */
6495         { &hf_ieee802154_sec_frame_counter,
6496         { "Frame Counter", "wpan.sec_frame_counter", FT_UINT32, BASE_HEX, NULL, 0x0,
6497             "Frame counter of the originator of the protected frame (802.15.4-2003)", HFILL }},
6498 
6499         { &hf_ieee802154_sec_key_sequence_counter,
6500         { "Key Sequence Counter", "wpan.sec_key_sequence_counter", FT_UINT8, BASE_HEX, NULL, 0x0,
6501             "Key Sequence counter of the originator of the protected frame (802.15.4-2003)", HFILL }},
6502 
6503         { &hf_ieee802154_no_ack,
6504         { "No ack found", "wpan.no_ack", FT_NONE, BASE_NONE, NULL, 0x0,
6505             "No corresponding ack frame was found", HFILL }},
6506 
6507         { &hf_ieee802154_no_ack_request,
6508         { "No request found", "wpan.no_ack_request", FT_NONE, BASE_NONE, NULL, 0x0,
6509             "No corresponding request frame was found", HFILL }},
6510 
6511         { &hf_ieee802154_ack_in,
6512         { "Ack In", "wpan.ack_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
6513             "The ack to this request is in this frame", HFILL }},
6514 
6515         { &hf_ieee802154_ack_to,
6516         { "Ack To", "wpan.ack_to", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_ACK), 0x0,
6517             "This is the ack to the request in this frame", HFILL }},
6518 
6519         { &hf_ieee802154_ack_time,
6520         { "Ack Time", "wpan.ack_time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
6521             "The time between the request and the ack", HFILL }},
6522 
6523         /* ZBOSS dump */
6524 
6525         { &hf_zboss_page,
6526         { "Page", "wpan-zboss.page", FT_UINT8, BASE_DEC_HEX, VALS(zboss_page_names), 0xFE,
6527             "IEEE802.15.4 page number", HFILL } },
6528 
6529         { &hf_zboss_channel,
6530         { "Channel", "wpan-zboss.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
6531             "Channel number", HFILL }},
6532 
6533         { &hf_zboss_direction,
6534         { "ZBOSS Direction", "wpan-zboss.direction", FT_UINT8, BASE_HEX, VALS(zboss_direction_names), 0x01,
6535             "ZBOSS Packet Direction", HFILL }},
6536 
6537         { &hf_zboss_trace_number,
6538         { "Trace number", "wpan-zboss.trace", FT_UINT32, BASE_DEC, NULL, 0x0,
6539             "Trace item number", HFILL }},
6540 
6541         /* TAP Packet Fields */
6542         { &hf_ieee802154_tap_version,
6543         { "Version",        "wpan-tap.version", FT_UINT8, BASE_DEC, NULL, 0x0,
6544             "TAP Packet Version", HFILL }},
6545 
6546         { &hf_ieee802154_tap_reserved,
6547         { "Reserved",        "wpan-tap.reserved", FT_UINT8, BASE_DEC, NULL, 0x0,
6548             "TAP Packet Reserved", HFILL }},
6549 
6550         { &hf_ieee802154_tap_length,
6551         { "Length",        "wpan-tap.length", FT_UINT16, BASE_DEC, NULL, 0x0,
6552             "TAP Packet Length", HFILL }},
6553 
6554         { &hf_ieee802154_tap_data_length,
6555         { "Data Length",   "wpan-tap.data_length", FT_UINT16, BASE_DEC, NULL, 0x0,
6556             "IEEE 802.15.4 Data Length", HFILL }},
6557 
6558         { &hf_ieee802154_tap_tlv_type,
6559         { "TLV Type",       "wpan-tap.tlv.type", FT_UINT16, BASE_DEC, VALS(tap_tlv_types), 0x0,
6560             NULL, HFILL }},
6561 
6562         { &hf_ieee802154_tap_tlv_length,
6563         { "TLV Length",       "wpan-tap.tlv.length", FT_UINT16, BASE_DEC, NULL, 0x0,
6564             NULL, HFILL }},
6565 
6566         { &hf_ieee802154_tap_tlv_unknown,
6567         { "Unknown",                "wpan-tap.tlv.unknown", FT_BYTES, BASE_NONE, NULL, 0x0,
6568             NULL, HFILL }},
6569 
6570         { &hf_ieee802154_tap_tlv_padding,
6571         { "Padding",                "wpan-tap.tlv.padding", FT_BYTES, BASE_NONE, NULL, 0x0,
6572             NULL, HFILL }},
6573 
6574         { &hf_ieee802154_tap_fcs_type,
6575         { "FCS Type",       "wpan-tap.fcs_type", FT_UINT8, BASE_DEC, VALS(tap_fcs_type_names), 0x0,
6576             NULL, HFILL }},
6577 
6578         { &hf_ieee802154_tap_rss,
6579         { "RSS",           "wpan-tap.rss", FT_FLOAT, BASE_FLOAT|BASE_UNIT_STRING, &units_dbm, 0x0,
6580             NULL, HFILL }},
6581 
6582         { &hf_ieee802154_ch_num,
6583         { "Channel",        "wpan-tap.ch_num", FT_UINT16, BASE_DEC, NULL, 0x0,
6584             "Channel number", HFILL }},
6585 
6586         { &hf_ieee802154_ch_page,
6587         { "Page",           "wpan-tap.ch_page", FT_UINT8, BASE_DEC, VALS(channel_page_names), 0x0,
6588             "Channel page", HFILL }},
6589 
6590         { &hf_ieee802154_bit_rate,
6591         { "Bit Rate",       "wpan-tap.bit_rate", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &units_bit_sec, 0x0,
6592             NULL, HFILL }},
6593 
6594         { &hf_ieee802154_sun_band,
6595         { "Band",           "wpan-tap.sun_band", FT_UINT8, BASE_DEC, VALS(sun_bands), 0x0,
6596             NULL, HFILL }},
6597 
6598         { &hf_ieee802154_sun_type,
6599         { "Type",           "wpan-tap.sun_type", FT_UINT8, BASE_DEC, VALS(sun_types), 0x0,
6600             NULL, HFILL }},
6601 
6602         { &hf_ieee802154_sun_mode,
6603         { "Mode",           "wpan-tap.sun_mode", FT_UINT8, BASE_DEC, NULL, 0x0,
6604             NULL, HFILL }},
6605 
6606         { &hf_ieee802154_mode_fsk_a,
6607         { "FSK-A mode",     "wpan-tap.mode.fsk_a", FT_UINT8, BASE_DEC, VALS(fsk_a_modes), 0x0,
6608             NULL, HFILL }},
6609 
6610         { &hf_ieee802154_mode_fsk_b,
6611         { "FSK-B mode",     "wpan-tap.mode.fsk_b", FT_UINT8, BASE_DEC, VALS(fsk_b_modes), 0x0,
6612             NULL, HFILL }},
6613 
6614         { &hf_ieee802154_mode_oqpsk_a,
6615         { "O-QPSK-A mode",   "wpan-tap.mode.oqpsk_a", FT_UINT8, BASE_DEC, VALS(oqpsk_a_modes), 0x0,
6616             NULL, HFILL }},
6617 
6618         { &hf_ieee802154_mode_oqpsk_b,
6619         { "O-QPSK-B mode",   "wpan-tap.mode.oqpsk_b", FT_UINT8, BASE_DEC, VALS(oqpsk_b_modes), 0x0,
6620             NULL, HFILL }},
6621 
6622         { &hf_ieee802154_mode_oqpsk_c,
6623         { "O-QPSK-C mode",   "wpan-tap.mode.oqpsk_c", FT_UINT8, BASE_DEC, VALS(oqpsk_c_modes), 0x0,
6624             NULL, HFILL }},
6625 
6626         { &hf_ieee802154_mode_ofdm,
6627         { "OFDM mode",       "wpan-tap.mode.ofdm", FT_UINT8, BASE_DEC, VALS(ofdm_modes), 0x0,
6628             NULL, HFILL }},
6629 
6630         { &hf_ieee802154_sof_ts,
6631         { "Start of frame timestamp",   "wpan-tap.sof_ts", FT_UINT64, BASE_DEC|BASE_UNIT_STRING, &units_nanoseconds, 0x0,
6632             NULL, HFILL }},
6633 
6634         { &hf_ieee802154_eof_ts,
6635         { "End of frame timestamp",     "wpan-tap.eof_ts", FT_UINT64, BASE_DEC|BASE_UNIT_STRING, &units_nanoseconds, 0x0,
6636             NULL, HFILL }},
6637 
6638         { &hf_ieee802154_slot_start_ts,
6639         { "Start of slot timestamp",    "wpan-tap.slot_start_ts", FT_UINT64, BASE_DEC|BASE_UNIT_STRING, &units_nanoseconds, 0x0,
6640             NULL, HFILL }},
6641 
6642         { &hf_ieee802154_tap_timeslot_length,
6643         { "Timeslot length",            "wpan-tap.timeslot_length", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &units_microseconds, 0x0,
6644             NULL, HFILL }},
6645 
6646         { &hf_ieee802154_tap_lqi,
6647         { "Link Quality Indicator",     "wpan-tap.lqi", FT_UINT8, BASE_DEC, NULL, 0x0,
6648             NULL, HFILL }},
6649 
6650         { &hf_ieee802154_chplan_start,
6651         { "Channel0 freq",              "wpan-tap.chplan.start", FT_FLOAT, BASE_FLOAT|BASE_UNIT_STRING, &units_khz, 0x0,
6652             "Channel 0 center frequency", HFILL }},
6653 
6654         { &hf_ieee802154_chplan_spacing,
6655         { "Spacing",                    "wpan-tap.chplan.spacing", FT_FLOAT, BASE_FLOAT|BASE_UNIT_STRING, &units_khz, 0x0,
6656             "Channel spacing", HFILL }},
6657 
6658         { &hf_ieee802154_chplan_channels,
6659         { "Channels",                   "wpan-tap.chplan.channels", FT_UINT16, BASE_DEC, NULL, 0x0,
6660             "Number of channels", HFILL }},
6661 
6662         { &hf_ieee802154_ch_freq,
6663         { "Frequency",                  "wpan-tap.ch_freq", FT_FLOAT, BASE_FLOAT|BASE_UNIT_STRING, &units_khz, 0x0,
6664             "Channel center frequency", HFILL }},
6665 
6666         { &hf_ieee802154_frame_start_offset,
6667         { "Frame start offset",       "wpan.tsch.frame_start_offset", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_microseconds, 0x0,
6668             "Start of frame timestamp - start of slot timestamp", HFILL }},
6669 
6670         { &hf_ieee802154_frame_duration,
6671         { "Frame duration",           "wpan.tsch.frame_duration", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_microseconds, 0x0,
6672             "End of frame timestamp - start of frame timestamp", HFILL }},
6673 
6674         { &hf_ieee802154_frame_end_offset,
6675         { "Frame end offset", "wpan.tsch.frame_end_offset", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, &units_microseconds, 0x0,
6676             "End of frame timestamp - (start of slot timestamp + timeslot length)", HFILL }},
6677 
6678         { &hf_ieee802154_asn,
6679         { "ASN", "wpan-tap.asn", FT_UINT64, BASE_DEC, NULL, 0x0,
6680             "Absolute Slot Number", HFILL }},
6681 
6682     };
6683 
6684     /* Subtrees */
6685     static gint *ett[] = {
6686         &ett_ieee802154_nonask_phy,
6687         &ett_ieee802154_nonask_phy_phr,
6688         &ett_ieee802154_tap,
6689         &ett_ieee802154_tap_header,
6690         &ett_ieee802154_tap_tlv,
6691         &ett_ieee802154,
6692         &ett_ieee802154_fcf,
6693         &ett_ieee802154_auxiliary_security,
6694         &ett_ieee802154_aux_sec_control,
6695         &ett_ieee802154_aux_sec_key_id,
6696         &ett_ieee802154_fcs,
6697         &ett_ieee802154_cmd,
6698         &ett_ieee802154_superframe,
6699         &ett_ieee802154_gts,
6700         &ett_ieee802154_gts_direction,
6701         &ett_ieee802154_gts_descriptors,
6702         &ett_ieee802154_pendaddr,
6703         &ett_ieee802154_header_ies,
6704         &ett_ieee802154_header_ie,
6705         &ett_ieee802154_header_ie_tlv,
6706         &ett_ieee802154_hie_unsupported,
6707         &ett_ieee802154_hie_time_correction,
6708         &ett_ieee802154_hie_ht,
6709         &ett_ieee802154_hie_csl,
6710         &ett_ieee802154_hie_global_time,
6711         &ett_ieee802154_hie_vendor_specific,
6712         &ett_ieee802154_payload_ie,
6713         &ett_ieee802154_payload_ie_tlv,
6714         &ett_ieee802154_pie_termination,
6715         &ett_ieee802154_pie_vendor,
6716         &ett_ieee802159_mpx,
6717         &ett_ieee802159_mpx_transaction_control,
6718         &ett_ieee802154_pie_ietf,
6719         &ett_ieee802154_pie_unsupported,
6720         &ett_ieee802154_tsch_slotframe,
6721         &ett_ieee802154_tsch_slotframe_list,
6722         &ett_ieee802154_tsch_slotframe_link,
6723         &ett_ieee802154_tsch_slotframe_link_options,
6724         &ett_ieee802154_tsch_timeslot,
6725         &ett_ieee802154_tsch_synch,
6726         &ett_ieee802154_channel_hopping,
6727         &ett_ieee802154_mlme,
6728         &ett_ieee802154_mlme_payload,
6729         &ett_ieee802154_mlme_payload_data,
6730         &ett_ieee802154_mlme_unsupported,
6731         &ett_ieee802154_psie,
6732         &ett_ieee802154_eb_filter,
6733         &ett_ieee802154_eb_filter_bitmap,
6734         &ett_ieee802154_zigbee,
6735         &ett_ieee802154_zboss,
6736         &ett_ieee802154_p_ie_6top,
6737         &ett_ieee802154_p_ie_6top_cell_options,
6738         &ett_ieee802154_p_ie_6top_cell_list,
6739         &ett_ieee802154_p_ie_6top_rel_cell_list,
6740         &ett_ieee802154_p_ie_6top_cand_cell_list,
6741         &ett_ieee802154_p_ie_6top_cell
6742     };
6743 
6744     static ei_register_info ei[] = {
6745         { &ei_ieee802154_fcs_bitmask_len, { "wpan.bitmask_len_error", PI_UNDECODED, PI_WARN,
6746                 "Only least-significant bytes decoded", EXPFILL }},
6747         { &ei_ieee802154_invalid_addressing, { "wpan.invalid_addressing", PI_MALFORMED, PI_WARN,
6748                 "Invalid Addressing", EXPFILL }},
6749         { &ei_ieee802154_invalid_panid_compression, { "wpan.invalid_panid_compression", PI_MALFORMED, PI_ERROR,
6750                 "Invalid Setting for PAN ID Compression", EXPFILL }},
6751         { &ei_ieee802154_invalid_panid_compression2, { "wpan.invalid_panid_compression", PI_MALFORMED, PI_ERROR,
6752                 "Invalid Pan ID Compression and addressing combination for Frame Version 2", EXPFILL }},
6753         { &ei_ieee802154_dst, { "wpan.dst_invalid", PI_MALFORMED, PI_ERROR,
6754                 "Invalid Destination Address Mode", EXPFILL }},
6755         { &ei_ieee802154_src, { "wpan.src_invalid", PI_MALFORMED, PI_ERROR,
6756                 "Invalid Source Address Mode", EXPFILL }},
6757         { &ei_ieee802154_frame_ver,  { "wpan.frame_version_unknown", PI_MALFORMED, PI_ERROR,
6758                 "Frame Version Unknown Cannot Dissect", EXPFILL }},
6759 #if 0
6760         { &ei_ieee802154_frame_type, { "wpan.frame_type_unknown", PI_MALFORMED, PI_ERROR,
6761                 "Frame Type Unknown Cannot Dissect", EXPFILL }},
6762 #endif
6763         { &ei_ieee802154_decrypt_error, { "wpan.decrypt_error", PI_UNDECODED, PI_WARN,
6764                 "Decryption error", EXPFILL }},
6765         { &ei_ieee802154_fcs, { "wpan.fcs.bad", PI_CHECKSUM, PI_WARN,
6766                 "Bad FCS", EXPFILL }},
6767         { &ei_ieee802154_ack_not_found, { "wpan.ack_not_found",  PI_SEQUENCE, PI_NOTE,
6768                 "Ack not found", EXPFILL }},
6769         { &ei_ieee802154_ack_request_not_found, { "wpan.ack_request_not_found",  PI_SEQUENCE, PI_NOTE,
6770                 "Request not found", EXPFILL }},
6771         { &ei_ieee802154_seqno_suppression, { "wpan.seqno_suppression_invalid",  PI_MALFORMED, PI_WARN,
6772                 "Sequence Number Suppression invalid for 802.15.4-2003 and 2006", EXPFILL }},
6773         { &ei_ieee802154_6top_unsupported_type, { "wpan.6top_unsupported_type", PI_PROTOCOL, PI_WARN,
6774                 "Unsupported Type of Message", EXPFILL }},
6775         { &ei_ieee802154_6top_unsupported_command, { "wpan.6top_unsupported_command", PI_PROTOCOL, PI_WARN,
6776                 "Unsupported 6top command", EXPFILL }},
6777         { &ei_ieee802154_time_correction_error, { "wpan.time_correction.error", PI_PROTOCOL, PI_WARN,
6778                 "Incorrect value. Reference: IEEE-802.15.4-2015. Table 7-8: Values of the Time Sync Info field for ACK with timing information", EXPFILL}},
6779         { &ei_ieee802154_6top_unsupported_return_code, { "wpan.6top_unsupported_code", PI_PROTOCOL, PI_WARN,
6780                 "Unsupported 6top return code", EXPFILL }},
6781         { &ei_ieee802154_ie_unsupported_id, { "wpan.ie_unsupported_id", PI_PROTOCOL, PI_WARN,
6782                 "Unsupported IE ID", EXPFILL }},
6783         { &ei_ieee802154_ie_unknown_extra_content, { "wpan.ie_unknown_extra_content", PI_PROTOCOL, PI_WARN,
6784                 "Unexpected extra content for IE", EXPFILL }},
6785         { &ei_ieee802159_mpx_invalid_transfer_type, { "wpan.payload_ie.mpx.invalid_transfer_type", PI_PROTOCOL, PI_WARN,
6786                 "Invalid transfer type (cf. IEEE 802.15.9 Table 19)", EXPFILL }},
6787         { &ei_ieee802159_mpx_unsupported_kmp, { "wpan.mpx.unsupported_kmp", PI_PROTOCOL, PI_WARN,
6788                 "Unsupported KMP ID", EXPFILL }},
6789         { &ei_ieee802159_mpx_unknown_kmp, { "wpan.mpx.unknown_kmp", PI_PROTOCOL, PI_WARN,
6790                 "Unknown KMP ID (cf. IEEE 802.15.9 Table 21)", EXPFILL }},
6791         { &ei_ieee802154_missing_payload_ie, { "wpan.payload_ie.missing",  PI_MALFORMED, PI_WARN,
6792                 "Payload IE indicated by Header Termination, but no Payload IE present", EXPFILL }},
6793         { &ei_ieee802154_payload_ie_in_header, { "wpan.payload_ie.in_header",  PI_MALFORMED, PI_WARN,
6794                 "Payload IE in header", EXPFILL }},
6795         { &ei_ieee802154_unsupported_cmd, { "wpan.cmd.unsupported_cmd", PI_PROTOCOL, PI_WARN,
6796                 "Unsupported Command ID", EXPFILL }},
6797         { &ei_ieee802154_unknown_cmd, { "wpan.cmd.unknown_cmd", PI_PROTOCOL, PI_WARN,
6798                 "Unknown Command Id (cf. IEEE 802.15.4-2015 Table 7-49)", EXPFILL }},
6799         { &ei_ieee802154_tap_tlv_invalid_type, { "wpan-tap.tlv.invalid_type", PI_MALFORMED, PI_WARN,
6800                 "Invalid TLV type", EXPFILL }},
6801         { &ei_ieee802154_tap_tlv_invalid_length, { "wpan-tap.tlv.invalid_length", PI_MALFORMED, PI_WARN,
6802                 "Invalid TLV length", EXPFILL }},
6803         { &ei_ieee802154_tap_tlv_padding_not_zeros, { "wpan-tap.tlv.padding_not_zeros", PI_MALFORMED, PI_WARN,
6804                 "TLV padding not zero", EXPFILL }},
6805         { &ei_ieee802154_tap_tlv_invalid_fcs_type, { "wpan-tap.tlv.invalid_fcs_type", PI_MALFORMED, PI_ERROR,
6806                 "Invalid FCS type", EXPFILL }},
6807     };
6808 
6809     /* Preferences. */
6810     module_t *ieee802154_module;
6811     expert_module_t* expert_ieee802154;
6812 
6813     static uat_field_t addr_uat_flds[] = {
6814         UAT_FLD_HEX(addr_uat,addr16,"Short Address",
6815                 "16-bit short address in hexadecimal."),
6816         UAT_FLD_HEX(addr_uat,pan,"PAN Identifier",
6817                 "16-bit PAN identifier in hexadecimal."),
6818         UAT_FLD_BUFFER(addr_uat,eui64,"EUI-64",
6819                 "64-bit extended unique identifier."),
6820         UAT_END_FIELDS
6821     };
6822 
6823     static uat_field_t key_uat_flds[] = {
6824         UAT_FLD_CSTRING(key_uat,pref_key,"Decryption key",
6825                 "128-bit decryption key in hexadecimal format"),
6826         UAT_FLD_DEC(key_uat,key_index,"Decryption key index",
6827                 "Key index in decimal format"),
6828         UAT_FLD_VS(key_uat, hash_type, "Key hash", ieee802154_key_hash_vals, "Specifies which hash scheme is used to derived the key"),
6829         UAT_END_FIELDS
6830     };
6831 
6832     static const enum_val_t fcs_type_vals[] = {
6833         {"cc24xx", "TI CC24xx metadata",    IEEE802154_CC24XX_METADATA},
6834         {"16",     "ITU-T CRC-16",          IEEE802154_FCS_16_BIT},
6835         {"32",     "ITU-T CRC-32",          IEEE802154_FCS_32_BIT},
6836         {NULL, NULL, -1}
6837     };
6838 
6839     static build_valid_func     ieee802154_da_build_value[1] = {ieee802154_da_value};
6840     static decode_as_value_t    ieee802154_da_values = {ieee802154_da_prompt, 1, ieee802154_da_build_value};
6841     static decode_as_t          ieee802154_da = {
6842         IEEE802154_PROTOABBREV_WPAN, IEEE802154_PROTOABBREV_WPAN_PANID,
6843         1, 0, &ieee802154_da_values, NULL, NULL,
6844         decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL
6845     };
6846 
6847     /* Register the init routine. */
6848     register_init_routine(proto_init_ieee802154);
6849     register_cleanup_routine(proto_cleanup_ieee802154);
6850 
6851     /*  Register Protocol name and description. */
6852     proto_ieee802154 = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN", "IEEE 802.15.4",
6853            IEEE802154_PROTOABBREV_WPAN);
6854     proto_ieee802154_nonask_phy = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN non-ASK PHY",
6855             "IEEE 802.15.4 non-ASK PHY", "wpan-nonask-phy");
6856     proto_zboss = proto_register_protocol("ZBOSS IEEE 802.15.4 dump",
6857                                           "ZBOSS dump", "wpan-zboss");
6858     proto_ieee802154_tap = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN TAP",
6859                                           "IEEE 802.15.4 TAP", "wpan-tap");
6860 
6861     /*  Register header fields and subtrees. */
6862     proto_register_field_array(proto_ieee802154, hf, array_length(hf));
6863     proto_register_field_array(proto_ieee802154, hf_phy, array_length(hf_phy));
6864 
6865     proto_register_subtree_array(ett, array_length(ett));
6866 
6867     expert_ieee802154 = expert_register_protocol(proto_ieee802154);
6868     expert_register_field_array(expert_ieee802154, ei, array_length(ei));
6869 
6870     ieee802_15_4_short_address_type = address_type_dissector_register("AT_IEEE_802_15_4_SHORT", "IEEE 802.15.4 16-bit short address",
6871                                         ieee802_15_4_short_address_to_str, ieee802_15_4_short_address_str_len, NULL, NULL, ieee802_15_4_short_address_len, NULL, NULL);
6872 
6873     /* add a user preference to set the 802.15.4 ethertype */
6874     ieee802154_module = prefs_register_protocol(proto_ieee802154,
6875                                    proto_reg_handoff_ieee802154);
6876     prefs_register_uint_preference(ieee802154_module, "802154_ethertype",
6877                                    "802.15.4 Ethertype (in hex)",
6878                                    "(Hexadecimal) Ethertype used to indicate IEEE 802.15.4 frame.",
6879                                    16, &ieee802154_ethertype);
6880     prefs_register_obsolete_preference(ieee802154_module, "802154_cc24xx");
6881     prefs_register_enum_preference(ieee802154_module, "fcs_format",
6882                                    "FCS format",
6883                                    "The FCS format in the captured payload",
6884                                    &ieee802154_fcs_type, fcs_type_vals, FALSE);
6885     prefs_register_bool_preference(ieee802154_module, "802154_fcs_ok",
6886                                    "Dissect only good FCS",
6887                                    "Dissect payload only if FCS is valid.",
6888                                    &ieee802154_fcs_ok);
6889     prefs_register_bool_preference(ieee802154_module, "802154_ack_tracking",
6890                                    "Enable ACK tracking",
6891                                    "Match frames with ACK request to ACK packets",
6892                                    &ieee802154_ack_tracking);
6893     prefs_register_bool_preference(ieee802154_module, "802154e_compatibility",
6894                                     "Assume 802.15.4e-2012 for compatibility",
6895                                     "Parse assuming 802.15.4e quirks for compatibility",
6896                                     &ieee802154e_compatibility);
6897 
6898     /* Create a UAT for static address mappings. */
6899     static_addr_uat = uat_new("Static Addresses",
6900             sizeof(static_addr_t),      /* record size */
6901             "802154_addresses",         /* filename */
6902             TRUE,                       /* from_profile */
6903             &static_addrs,              /* data_ptr */
6904             &num_static_addrs,          /* numitems_ptr */
6905             UAT_AFFECTS_DISSECTION,     /* affects dissection of packets, but not set of named fields */
6906             NULL,                       /* help */
6907             addr_uat_copy_cb,           /* copy callback */
6908             addr_uat_update_cb,         /* update callback */
6909             addr_uat_free_cb,           /* free callback */
6910             NULL,                       /* post update callback */
6911             NULL,                       /* reset callback */
6912             addr_uat_flds);             /* UAT field definitions */
6913     prefs_register_uat_preference(ieee802154_module, "static_addr",
6914                 "Static Addresses",
6915                 "A table of static address mappings between 16-bit short addressing and EUI-64 addresses",
6916                 static_addr_uat);
6917 
6918     /* Create a UAT for key management. */
6919     ieee802154_key_uat = uat_new("Keys",
6920             sizeof(ieee802154_key_t),   /* record size */
6921             "ieee802154_keys",          /* filename */
6922             TRUE,                       /* from_profile */
6923             &ieee802154_keys,           /* data_ptr */
6924             &num_ieee802154_keys,       /* numitems_ptr */
6925             UAT_AFFECTS_DISSECTION,     /* affects dissection of packets, but not set of named fields */
6926             NULL,                       /* help */
6927             ieee802154_key_copy_cb,     /* copy callback */
6928             ieee802154_key_update_cb,   /* update callback */
6929             ieee802154_key_free_cb,     /* free callback */
6930             ieee802154_key_post_update_cb, /* post update callback */
6931             NULL,                       /* reset callback */
6932             key_uat_flds);              /* UAT field definitions */
6933     prefs_register_uat_preference(ieee802154_module, "ieee802154_keys",
6934                 "Decryption Keys",
6935                 "Decryption key configuration data",
6936                 ieee802154_key_uat);
6937 
6938     /* Register preferences for a decryption key */
6939     prefs_register_obsolete_preference(ieee802154_module, "802154_key");
6940 
6941     prefs_register_enum_preference(ieee802154_module, "802154_sec_suite",
6942                                    "Security Suite (802.15.4-2003)",
6943                                    "Specifies the security suite to use for 802.15.4-2003 secured frames"
6944                                    " (only supported suites are listed). Option ignored for 802.15.4-2006"
6945                                    " and unsecured frames.",
6946                                    &ieee802154_sec_suite, ieee802154_2003_sec_suite_enums, FALSE);
6947 
6948     prefs_register_bool_preference(ieee802154_module, "802154_extend_auth",
6949                                    "Extend authentication data (802.15.4-2003)",
6950                                    "Set if the manufacturer extends the authentication data with the"
6951                                    " security header. Option ignored for 802.15.4-2006 and unsecured frames.",
6952                                    &ieee802154_extend_auth);
6953 
6954     /* Register the subdissector list */
6955     panid_dissector_table = register_dissector_table(IEEE802154_PROTOABBREV_WPAN_PANID, "IEEE 802.15.4 PANID", proto_ieee802154, FT_UINT16, BASE_HEX);
6956     ieee802154_heur_subdissector_list = register_heur_dissector_list(IEEE802154_PROTOABBREV_WPAN, proto_ieee802154);
6957     ieee802154_beacon_subdissector_list = register_heur_dissector_list(IEEE802154_PROTOABBREV_WPAN_BEACON, proto_ieee802154);
6958 
6959     /* Register dissector tables */
6960     header_ie_dissector_table = register_dissector_table(IEEE802154_HEADER_IE_DTABLE, "IEEE 802.15.4 Header IEs", proto_ieee802154, FT_UINT8, BASE_HEX);
6961     payload_ie_dissector_table = register_dissector_table(IEEE802154_PAYLOAD_IE_DTABLE, "IEEE 802.15.4 Payload IEs", proto_ieee802154, FT_UINT8, BASE_HEX);
6962     mlme_ie_dissector_table = register_dissector_table(IEEE802154_MLME_IE_DTABLE, "IEEE 802.15.4 Nested IEs", proto_ieee802154, FT_UINT8, BASE_HEX);
6963     cmd_vendor_dissector_table = register_dissector_table(IEEE802154_CMD_VENDOR_DTABLE, "IEEE 802.15.4 Vendor Specific Commands", proto_ieee802154, FT_UINT24, BASE_HEX );
6964 
6965     /* Register dissectors with Wireshark */
6966     ieee802154_handle = register_dissector(IEEE802154_PROTOABBREV_WPAN, dissect_ieee802154, proto_ieee802154);
6967     ieee802154_nofcs_handle = register_dissector("wpan_nofcs", dissect_ieee802154_nofcs, proto_ieee802154);
6968     register_dissector("wpan_cc24xx", dissect_ieee802154_cc24xx, proto_ieee802154);
6969     ieee802154_nonask_phy_handle = register_dissector("wpan-nonask-phy", dissect_ieee802154_nonask_phy, proto_ieee802154_nonask_phy);
6970     ieee802154_tap_handle = register_dissector("wpan-tap", dissect_ieee802154_tap, proto_ieee802154_tap);
6971 
6972     /* Setup registration for other dissectors to provide mac key hash algorithms */
6973     mac_key_hash_handlers = wmem_tree_new(wmem_epan_scope());
6974 
6975     /* Register a Decode-As handler */
6976     register_decode_as(&ieee802154_da);
6977 
6978     /* Create trees for transactions */
6979     transaction_unmatched_pdus = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
6980     transaction_matched_pdus = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
6981 
6982     ieee802154_tap = register_tap(IEEE802154_PROTOABBREV_WPAN);
6983 
6984     register_conversation_table(proto_ieee802154, TRUE, ieee802154_conversation_packet, ieee802154_hostlist_packet);
6985     register_conversation_filter(IEEE802154_PROTOABBREV_WPAN, "IEEE 802.15.4", ieee802154_filter_valid, ieee802154_build_filter);
6986 } /* proto_register_ieee802154 */
6987 
6988 
6989 /**
6990  * Registers the IEEE 802.15.4 dissector with Wireshark.
6991  * Will be called every time 'apply' is pressed in the preferences menu.
6992  * as well as during Wireshark initialization
6993  */
proto_reg_handoff_ieee802154(void)6994 void proto_reg_handoff_ieee802154(void)
6995 {
6996     static gboolean            prefs_initialized = FALSE;
6997     static unsigned int        old_ieee802154_ethertype;
6998 
6999     if (!prefs_initialized) {
7000         /* Get the dissector handles. */
7001         zigbee_ie_handle = find_dissector_add_dependency("zbee_ie", proto_ieee802154);
7002         zigbee_nwk_handle = find_dissector("zbee_nwk");
7003 
7004         dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4, ieee802154_handle);
7005         dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_NONASK_PHY, ieee802154_nonask_phy_handle);
7006         dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_NOFCS, ieee802154_nofcs_handle);
7007         dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_TAP, ieee802154_tap_handle);
7008         dissector_add_uint("sll.ltype", LINUX_SLL_P_IEEE802154, ieee802154_handle);
7009 
7010         prefs_initialized = TRUE;
7011     } else {
7012         dissector_delete_uint("ethertype", old_ieee802154_ethertype, ieee802154_handle);
7013     }
7014 
7015     old_ieee802154_ethertype = ieee802154_ethertype;
7016 
7017     /* Register dissector handles. */
7018     dissector_add_uint("ethertype", ieee802154_ethertype, ieee802154_handle);
7019 
7020     /* Register internal IE handlers */
7021     dissector_add_uint(IEEE802154_HEADER_IE_DTABLE, IEEE802154_HEADER_IE_TIME_CORR, create_dissector_handle(dissect_hie_time_correction, -1));
7022     dissector_add_uint(IEEE802154_HEADER_IE_DTABLE, IEEE802154_HEADER_IE_CSL, create_dissector_handle(dissect_hie_csl, -1));
7023     dissector_add_uint(IEEE802154_HEADER_IE_DTABLE, IEEE802154_HEADER_IE_GLOBAL_TIME, create_dissector_handle(dissect_hie_global_time, -1));
7024     dissector_add_uint(IEEE802154_HEADER_IE_DTABLE, IEEE802154_HEADER_IE_VENDOR_SPECIFIC, create_dissector_handle(dissect_hie_vendor_specific, -1));
7025 
7026     dissector_add_uint(IEEE802154_PAYLOAD_IE_DTABLE, IEEE802154_PAYLOAD_IE_MLME, create_dissector_handle(dissect_pie_mlme, -1));
7027     dissector_add_uint(IEEE802154_PAYLOAD_IE_DTABLE, IEEE802154_PAYLOAD_IE_VENDOR, create_dissector_handle(dissect_pie_vendor, -1));
7028     dissector_add_uint(IEEE802154_PAYLOAD_IE_DTABLE, IEEE802154_PAYLOAD_IE_MPX, create_dissector_handle(dissect_mpx_ie, -1));
7029     dissector_add_uint(IEEE802154_PAYLOAD_IE_DTABLE, IEEE802154_PAYLOAD_IE_IETF, create_dissector_handle(dissect_ietf_ie, -1));
7030 
7031     dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_CHANNEL_HOPPING, create_dissector_handle(dissect_802154_channel_hopping, -1));
7032     dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_TSCH_SYNCH, create_dissector_handle(dissect_802154_tsch_time_sync, -1));
7033     dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_TSCH_SLOTFR_LINK, create_dissector_handle(dissect_802154_tsch_slotframe_link, -1));
7034     dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_TSCH_TIMESLOT, create_dissector_handle(dissect_802154_tsch_timeslot, -1));
7035     dissector_add_uint(IEEE802154_MLME_IE_DTABLE, IEEE802154_MLME_SUBIE_ENHANCED_BEACON_FILTER, create_dissector_handle(dissect_802154_eb_filter, -1));
7036 
7037     /* For the MPX-IE */
7038     ethertype_table = find_dissector_table("ethertype");
7039     eapol_handle = find_dissector("eapol");
7040     lowpan_handle = find_dissector("6lowpan");
7041     wisun_sec_handle = find_dissector("wisun.sec");
7042 } /* proto_reg_handoff_ieee802154 */
7043 
7044 /*
7045  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
7046  *
7047  * Local variables:
7048  * c-basic-offset: 4
7049  * tab-width: 8
7050  * indent-tabs-mode: nil
7051  * End:
7052  *
7053  * vi: set shiftwidth=4 tabstop=8 expandtab:
7054  * :indentSize=4:tabSize=8:noTabs=true:
7055  */
7056