From Michal Labedzki via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9333 :
[metze/wireshark/wip.git] / epan / dissectors / packet-ieee802154.c
1 /* packet-ieee802154.c
2  *
3  * $Id$
4  *
5  * Auxiliary Security Header support and
6  * option to force TI CC24xx FCS format
7  * By Jean-Francois Wauthy <jfw@info.fundp.ac.be>
8  * Copyright 2009 The University of Namur, Belgium
9  *
10  * IEEE 802.15.4 Dissectors for Wireshark
11  * By Owen Kirby <osk@exegin.com>
12  * Copyright 2007 Exegin Technologies Limited
13  *
14  * Wireshark - Network traffic analyzer
15  * By Gerald Combs <gerald@wireshark.org>
16  * Copyright 1998 Gerald Combs
17  *
18  * This program is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU General Public License
20  * as published by the Free Software Foundation; either version 2
21  * of the License, or (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31  *------------------------------------------------------------
32  *
33  *  In IEEE 802.15.4 packets, all fields are little endian. And
34  *  Each byte is transmitted least significant bit first (reflected
35  *  bit ordering).
36  *------------------------------------------------------------
37  *
38  *  IEEE 802.15.4 Packets have the following format:
39  *  |  FCF  |Seq No|  Addressing |         Data          |  FCS  |
40  *  |2 bytes|1 byte|0 to 20 bytes|Length-(Overhead) bytes|2 Bytes|
41  *------------------------------------------------------------
42  *
43  *  CRC16 is calculated using the x^16 + x^12 + x^5 + 1 polynomial
44  *  as specified by ITU-T, and is calculated over the IEEE 802.15.4
45  *  packet (excluding the FCS) as transmitted over the air. Note,
46  *  that because the least significan bits are transmitted first, this
47  *  will require reversing the bit-order in each byte. Also, unlike
48  *  most CRC algorithms, IEEE 802.15.4 uses an initial and final value
49  *  of 0x0000, instead of 0xffff (which is used by the CCITT).
50  *------------------------------------------------------------
51  *
52  *  This dissector supports both link-layer IEEE 802.15.4 captures
53  *  and IEEE 802.15.4 packets encapsulated within other layers.
54  *  Additionally, support has been provided for various formats
55  *  of the frame check sequence:
56  *      - IEEE 802.15.4 compliant FCS.
57  *      - ChipCon/Texas Instruments CC24xx style FCS.
58  *------------------------------------------------------------
59  */
60
61 /*  Include files */
62 #include "config.h"
63
64 #include <string.h>
65
66 #include <sys/stat.h>
67
68 #include <glib.h>
69
70 #include <epan/wmem/wmem.h>
71 #include <epan/packet.h>
72 #include <epan/crc16-tvb.h>
73 #include <epan/expert.h>
74 #include <epan/addr_resolv.h>
75 #include <epan/prefs.h>
76 #include <epan/uat.h>
77 #include <epan/strutil.h>
78 #include <epan/show_exception.h>
79
80 /* Use libgcrypt for cipher libraries. */
81 #ifdef HAVE_LIBGCRYPT
82 #include <wsutil/wsgcrypt.h>
83 #endif /* HAVE_LIBGCRYPT */
84
85 #include "packet-ieee802154.h"
86 #include "packet-sll.h"
87
88 /* Dissection Options for dissect_ieee802154_common */
89 #define DISSECT_IEEE802154_OPTION_CC24xx    0x00000001  /* FCS field contains a TI CC24xx style FCS. */
90 #define DISSECT_IEEE802154_OPTION_LINUX     0x00000002  /* Addressing fields are padded DLT_IEEE802_15_4_LINUX, not implemented. */
91
92 /* ethertype for 802.15.4 tag - encapsulating an Ethernet packet */
93 static unsigned int ieee802154_ethertype = 0x809A;
94
95 /* boolean value set if the FCS field is using the TI CC24xx format */
96 static gboolean ieee802154_cc24xx = FALSE;
97
98 /* boolean value set if the FCS must be ok before payload is dissected */
99 static gboolean ieee802154_fcs_ok = TRUE;
100
101 /* User string with the decryption key. */
102 static const gchar *ieee802154_key_str = NULL;
103 static gboolean     ieee802154_key_valid;
104 static guint8       ieee802154_key[IEEE802154_CIPHER_SIZE];
105 static const char  *ieee802154_user    = "User";
106
107 /*-------------------------------------
108  * Address Hash Tables
109  *-------------------------------------
110  */
111 static ieee802154_map_tab_t ieee802154_map = { NULL, NULL };
112
113 /*-------------------------------------
114  * Static Address Mapping UAT
115  *-------------------------------------
116  */
117 /* UAT entry structure. */
118 typedef struct {
119     guchar *eui64;
120     guint   eui64_len;
121     guint   addr16;
122     guint   pan;
123 } static_addr_t;
124
125 /* UAT variables */
126 static uat_t         *static_addr_uat  = NULL;
127 static static_addr_t *static_addrs     = NULL;
128 static guint          num_static_addrs = 0;
129
130 /* Sanity-checks a UAT record. */
131 static void
132 addr_uat_update_cb(void *r, const char **err)
133 {
134     static_addr_t *map = (static_addr_t *)r;
135     /* Ensure a valid short address */
136     if (map->addr16 >= IEEE802154_NO_ADDR16) {
137         *err = g_strdup("Invalid short address");
138         return;
139     }
140     /* Ensure a valid PAN identifier. */
141     if (map->pan >= IEEE802154_BCAST_PAN) {
142         *err = g_strdup("Invalid PAN identifier");
143         return;
144     }
145     /* Ensure a valid EUI-64 length */
146     if (map->eui64_len != sizeof(guint64)) {
147         *err = g_strdup("Invalid EUI-64 length");
148         return;
149     }
150 } /* ieee802154_addr_uat_update_cb */
151
152 /* Field callbacks. */
153 UAT_HEX_CB_DEF(addr_uat, addr16, static_addr_t)
154 UAT_HEX_CB_DEF(addr_uat, pan, static_addr_t)
155 UAT_BUFFER_CB_DEF(addr_uat, eui64, static_addr_t, eui64, eui64_len)
156
157 /*-------------------------------------
158  * Dissector Function Prototypes
159  *-------------------------------------
160  */
161 /* Register Functions. Loads the dissector into Wireshark. */
162 void proto_reg_handoff_ieee802154   (void);
163
164 /* Dissection Routines. */
165 static void dissect_ieee802154_nonask_phy   (tvbuff_t *, packet_info *, proto_tree *);
166 static void dissect_ieee802154              (tvbuff_t *, packet_info *, proto_tree *);
167 static void dissect_ieee802154_nofcs        (tvbuff_t *, packet_info *, proto_tree *);
168 static void dissect_ieee802154_cc24xx       (tvbuff_t *, packet_info *, proto_tree *);
169 /*static void dissect_ieee802154_linux        (tvbuff_t *, packet_info *, proto_tree *);  TODO: Implement Me. */
170 static void dissect_ieee802154_common       (tvbuff_t *, packet_info *, proto_tree *, guint);
171
172 /* Sub-dissector helpers. */
173 static void dissect_ieee802154_fcf          (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *, guint *);
174 static void dissect_ieee802154_superframe   (tvbuff_t *, packet_info *, proto_tree *, guint *);
175 static void dissect_ieee802154_gtsinfo      (tvbuff_t *, packet_info *, proto_tree *, guint *);
176 static void dissect_ieee802154_pendaddr     (tvbuff_t *, packet_info *, proto_tree *, guint *);
177 static void dissect_ieee802154_assoc_req    (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
178 static void dissect_ieee802154_assoc_rsp    (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
179 static void dissect_ieee802154_disassoc     (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
180 static void dissect_ieee802154_realign      (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
181 static void dissect_ieee802154_gtsreq       (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
182
183 /* Decryption helpers. */
184 typedef enum {
185     DECRYPT_PACKET_SUCCEEDED,
186     DECRYPT_NOT_ENCRYPTED,
187     DECRYPT_VERSION_UNSUPPORTED,
188     DECRYPT_PACKET_TOO_SMALL,
189     DECRYPT_PACKET_NO_EXT_SRC_ADDR,
190     DECRYPT_PACKET_NO_KEY,
191     DECRYPT_PACKET_DECRYPT_FAILED,
192     DECRYPT_PACKET_MIC_CHECK_FAILED
193 } ws_decrypt_status;
194
195 static tvbuff_t * dissect_ieee802154_decrypt(tvbuff_t *, guint, packet_info *, ieee802154_packet *,
196         ws_decrypt_status *);
197 static void ccm_init_block          (gchar *, gboolean, gint, guint64, ieee802154_packet *, gint);
198 static gboolean ccm_ctr_encrypt     (const gchar *, const gchar *, gchar *, gchar *, gint);
199 static gboolean ccm_cbc_mac         (const gchar *, const gchar *, const gchar *, gint, const gchar *, gint, gchar *);
200
201 /*  Initialize Protocol and Registered fields */
202 static int proto_ieee802154_nonask_phy = -1;
203 static int hf_ieee802154_nonask_phy_preamble = -1;
204 static int hf_ieee802154_nonask_phy_sfd = -1;
205 static int hf_ieee802154_nonask_phy_length = -1;
206
207 static int proto_ieee802154 = -1;
208 static int hf_ieee802154_frame_length = -1;
209 static int hf_ieee802154_frame_type = -1;
210 static int hf_ieee802154_security = -1;
211 static int hf_ieee802154_pending = -1;
212 static int hf_ieee802154_ack_request = -1;
213 static int hf_ieee802154_intra_pan = -1;
214 static int hf_ieee802154_seqno = -1;
215 static int hf_ieee802154_src_addr_mode = -1;
216 static int hf_ieee802154_dst_addr_mode = -1;
217 static int hf_ieee802154_version = -1;
218 static int hf_ieee802154_dst_panID = -1;
219 static int hf_ieee802154_dst16 = -1;
220 static int hf_ieee802154_dst64 = -1;
221 static int hf_ieee802154_src_panID = -1;
222 static int hf_ieee802154_src16 = -1;
223 static int hf_ieee802154_src64 = -1;
224 static int hf_ieee802154_src64_origin = -1;
225 static int hf_ieee802154_fcs = -1;
226 static int hf_ieee802154_rssi = -1;
227 static int hf_ieee802154_fcs_ok = -1;
228 static int hf_ieee802154_correlation = -1;
229
230 /*  Registered fields for Command Packets */
231 static int hf_ieee802154_cmd_id = -1;
232 static int hf_ieee802154_cinfo_alt_coord = -1;
233 static int hf_ieee802154_cinfo_device_type = -1;
234 static int hf_ieee802154_cinfo_power_src = -1;
235 static int hf_ieee802154_cinfo_idle_rx = -1;
236 static int hf_ieee802154_cinfo_sec_capable = -1;
237 static int hf_ieee802154_cinfo_alloc_addr = -1;
238 static int hf_ieee802154_assoc_addr = -1;
239 static int hf_ieee802154_assoc_status = -1;
240 static int hf_ieee802154_disassoc_reason = -1;
241 static int hf_ieee802154_realign_pan = -1;
242 static int hf_ieee802154_realign_caddr = -1;
243 static int hf_ieee802154_realign_channel = -1;
244 static int hf_ieee802154_realign_addr = -1;
245 static int hf_ieee802154_realign_channel_page = -1;
246 static int hf_ieee802154_gtsreq_len = -1;
247 static int hf_ieee802154_gtsreq_dir = -1;
248 static int hf_ieee802154_gtsreq_type = -1;
249
250 /*  Registered fields for Beacon Packets */
251 static int hf_ieee802154_beacon_order = -1;
252 static int hf_ieee802154_superframe_order = -1;
253 static int hf_ieee802154_cap = -1;
254 static int hf_ieee802154_superframe_battery_ext = -1;
255 static int hf_ieee802154_superframe_coord = -1;
256 static int hf_ieee802154_assoc_permit = -1;
257 static int hf_ieee802154_gts_count = -1;
258 static int hf_ieee802154_gts_permit = -1;
259 static int hf_ieee802154_gts_direction = -1;
260 static int hf_ieee802154_pending16 = -1;
261 static int hf_ieee802154_pending64 = -1;
262
263 /*  Registered fields for Auxiliary Security Header */
264 static int hf_ieee802154_security_level = -1;
265 static int hf_ieee802154_key_id_mode = -1;
266 static int hf_ieee802154_aux_sec_reserved = -1;
267 static int hf_ieee802154_aux_sec_frame_counter = -1;
268 static int hf_ieee802154_aux_sec_key_source = -1;
269 static int hf_ieee802154_aux_sec_key_index = -1;
270
271 /* 802.15.4-2003 security */
272 static int hf_ieee802154_sec_frame_counter = -1;
273 static int hf_ieee802154_sec_key_sequence_counter = -1;
274
275 /*  Initialize Subtree Pointers */
276 static gint ett_ieee802154_nonask_phy = -1;
277 static gint ett_ieee802154_nonask_phy_phr = -1;
278 static gint ett_ieee802154 = -1;
279 static gint ett_ieee802154_fcf = -1;
280 static gint ett_ieee802154_auxiliary_security = -1;
281 static gint ett_ieee802154_aux_sec_control = -1;
282 static gint ett_ieee802154_aux_sec_key_id = -1;
283 static gint ett_ieee802154_fcs = -1;
284 static gint ett_ieee802154_cmd = -1;
285 static gint ett_ieee802154_superframe = -1;
286 static gint ett_ieee802154_gts = -1;
287 static gint ett_ieee802154_gts_direction = -1;
288 static gint ett_ieee802154_gts_descriptors = -1;
289 static gint ett_ieee802154_pendaddr = -1;
290
291 static expert_field ei_ieee802154_invalid_addressing = EI_INIT;
292 static expert_field ei_ieee802154_fcs = EI_INIT;
293 static expert_field ei_ieee802154_decrypt_error = EI_INIT;
294 static expert_field ei_ieee802154_dst = EI_INIT;
295 static expert_field ei_ieee802154_src = EI_INIT;
296
297 /*  Dissector handles */
298 static dissector_handle_t       data_handle;
299 static heur_dissector_list_t    ieee802154_heur_subdissector_list;
300
301 /* Name Strings */
302 static const value_string ieee802154_frame_types[] = {
303     { IEEE802154_FCF_BEACON,    "Beacon" },
304     { IEEE802154_FCF_DATA,      "Data" },
305     { IEEE802154_FCF_ACK,       "Ack" },
306     { IEEE802154_FCF_CMD,       "Command" },
307     { 0, NULL }
308 };
309
310 static const value_string ieee802154_addr_modes[] = {
311     { IEEE802154_FCF_ADDR_NONE, "None" },
312     { IEEE802154_FCF_ADDR_SHORT,"Short/16-bit" },
313     { IEEE802154_FCF_ADDR_EXT,  "Long/64-bit" },
314     { 0, NULL }
315 };
316
317 static const value_string ieee802154_cmd_names[] = {
318     { IEEE802154_CMD_ASRQ,      "Association Request" },
319     { IEEE802154_CMD_ASRSP,     "Association Response" },
320     { IEEE802154_CMD_DISAS,     "Disassociation Notification" },
321     { IEEE802154_CMD_DATA_RQ,   "Data Request" },
322     { IEEE802154_CMD_PANID_ERR, "PAN ID Conflict" },
323     { IEEE802154_CMD_ORPH_NOTIF,"Orphan Notification" },
324     { IEEE802154_CMD_BCN_RQ,    "Beacon Request" },
325     { IEEE802154_CMD_COORD_REAL,"Coordinator Realignment" },
326     { IEEE802154_CMD_GTS_REQ,   "GTS Request" },
327     { 0, NULL }
328 };
329
330 static const value_string ieee802154_sec_level_names[] = {
331     { SECURITY_LEVEL_NONE,        "No Security" },
332     { SECURITY_LEVEL_MIC_32,      "32-bit Message Integrity Code" },
333     { SECURITY_LEVEL_MIC_64,      "64-bit Message Integrity Code" },
334     { SECURITY_LEVEL_MIC_128,     "128-bit Message Integrity Code" },
335     { SECURITY_LEVEL_ENC,         "Encryption" },
336     { SECURITY_LEVEL_ENC_MIC_32,  "Encryption with 32-bit Message Integrity Code" },
337     { SECURITY_LEVEL_ENC_MIC_64,  "Encryption with 64-bit Message Integrity Code" },
338     { SECURITY_LEVEL_ENC_MIC_128, "Encryption with 128-bit Message Integrity Code" },
339     { 0, NULL }
340 };
341
342 static const value_string ieee802154_key_id_mode_names[] = {
343     { KEY_ID_MODE_IMPLICIT,       "Implicit Key" },
344     { KEY_ID_MODE_KEY_INDEX,      "Indexed Key using the Default Key Source" },
345     { KEY_ID_MODE_KEY_EXPLICIT_4, "Explicit Key with 4-octet Key Source" },
346     { KEY_ID_MODE_KEY_EXPLICIT_8, "Explicit Key with 8-octet Key Source" },
347     { 0, NULL }
348 };
349
350 static const true_false_string ieee802154_gts_direction_tfs = {
351     "Receive Only",
352     "Transmit Only"
353 };
354
355 /* The 802.15.4-2003 security suites for the security preferences (only AES-CCM suites are supported). */
356 /* NOTE: The equivalent 2006 security level identifer enumerations are used to simplify 2003 & 2006 integration! */
357 static const enum_val_t ieee802154_2003_sec_suite_enums[] = {
358     { "AES-CCM-128", "AES-128 Encryption, 128-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_128 },
359     { "AES-CCM-64",  "AES-128 Encryption, 64-bit Integrity Protection",  SECURITY_LEVEL_ENC_MIC_64 },
360     { "AES-CCM-32",  "AES-128 Encryption, 32-bit Integrity Protection",  SECURITY_LEVEL_ENC_MIC_32 },
361     { NULL, NULL, 0 }
362 };
363
364 /* Preferences for 2003 security */
365 static gint ieee802154_sec_suite = SECURITY_LEVEL_ENC_MIC_64;
366 static gboolean ieee802154_extend_auth = TRUE;
367
368 /* Macro to check addressing, and throw a warning flag if incorrect. */
369 #define IEEE802154_CMD_ADDR_CHECK(_pinfo_, _item_, _cmdid_, _x_)     \
370    if (!(_x_))                                                       \
371      expert_add_info_format(_pinfo_, _item_, &ei_ieee802154_invalid_addressing, \
372                             "Invalid Addressing for %s",             \
373                             val_to_str_const(_cmdid_, ieee802154_cmd_names, "Unknown Command"))
374
375 /* CRC definitions. IEEE 802.15.4 CRCs vary from CCITT by using an initial value of
376  * 0x0000, and no XOR out. IEEE802154_CRC_XOR is defined as 0xFFFF in order to un-XOR
377  * the output from the CCITT CRC routines in Wireshark.
378  */
379 #define IEEE802154_CRC_SEED     0x0000
380 #define IEEE802154_CRC_XOROUT   0xFFFF
381 #define ieee802154_crc_tvb(tvb, offset)   (crc16_ccitt_tvb_seed(tvb, offset, IEEE802154_CRC_SEED) ^ IEEE802154_CRC_XOROUT)
382
383
384 /*FUNCTION:------------------------------------------------------
385  *  NAME
386  *      dissect_ieee802154_fcf
387  *  DESCRIPTION
388  *      Dissector helper, parses and displays the frame control
389  *      field.
390  *
391  *  PARAMETERS
392  *      ieee802154_packet   *packet - Packet info structure.
393  *      tvbuff_t    *tvb    - pointer to buffer containing raw packet.
394  *      packet_info *pinfo  - pointer to packet information fields
395  *      proto_tree  *tree   - pointer to data tree wireshark uses to display packet.
396  *      ieee802154_packet *packet   - IEEE 802.15.4 packet information.
397  *      guint       offset  - offset into the tvb to find the FCF.
398  *  RETURNS
399  *      void
400  *---------------------------------------------------------------
401  */
402 static void
403 dissect_ieee802154_fcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet, guint *offset)
404 {
405     guint16     fcf;
406     proto_tree *field_tree;
407     proto_item *ti;
408
409     /* Get the FCF field. */
410     fcf = tvb_get_letohs(tvb, *offset);
411
412      /* Parse FCF Flags. */
413     packet->frame_type      = fcf & IEEE802154_FCF_TYPE_MASK;
414     packet->security_enable = fcf & IEEE802154_FCF_SEC_EN;
415     packet->frame_pending   = fcf & IEEE802154_FCF_FRAME_PND;
416     packet->ack_request     = fcf & IEEE802154_FCF_ACK_REQ;
417     packet->intra_pan       = fcf & IEEE802154_FCF_INTRA_PAN;
418     packet->version         = (fcf & IEEE802154_FCF_VERSION) >> 12;
419     packet->dst_addr_mode   = (fcf & IEEE802154_FCF_DADDR_MASK) >> 10;
420     packet->src_addr_mode   = (fcf & IEEE802154_FCF_SADDR_MASK) >> 14;
421
422     /* Display the frame type. */
423     proto_item_append_text(tree, " %s", val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
424     col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
425
426     /* Add the FCF to the protocol tree. */
427     if (tree) {
428         /*  Create the FCF subtree. */
429         ti = proto_tree_add_text(tree, tvb, *offset, 2, "Frame Control Field: %s (0x%04x)",
430                 val_to_str_const(packet->frame_type, ieee802154_frame_types, "Unknown"), fcf);
431         field_tree = proto_item_add_subtree(ti, ett_ieee802154_fcf);
432
433         /* FCF Fields. */
434         proto_tree_add_uint(field_tree, hf_ieee802154_frame_type, tvb, *offset, 1, fcf & IEEE802154_FCF_TYPE_MASK);
435         proto_tree_add_boolean(field_tree, hf_ieee802154_security, tvb, *offset, 1, fcf & IEEE802154_FCF_SEC_EN);
436         proto_tree_add_boolean(field_tree, hf_ieee802154_pending, tvb, *offset, 1, fcf & IEEE802154_FCF_FRAME_PND);
437         proto_tree_add_boolean(field_tree, hf_ieee802154_ack_request, tvb, *offset, 1, fcf & IEEE802154_FCF_ACK_REQ);
438         proto_tree_add_boolean(field_tree, hf_ieee802154_intra_pan, tvb, *offset, 1, fcf & IEEE802154_FCF_INTRA_PAN);
439         proto_tree_add_uint(field_tree, hf_ieee802154_dst_addr_mode, tvb, (*offset)+1, 1, fcf & IEEE802154_FCF_DADDR_MASK);
440         proto_tree_add_uint(field_tree, hf_ieee802154_version, tvb, (*offset)+1, 1, fcf & IEEE802154_FCF_VERSION);
441         proto_tree_add_uint(field_tree, hf_ieee802154_src_addr_mode, tvb, (*offset)+1, 1, fcf & IEEE802154_FCF_SADDR_MASK);
442     }
443
444     *offset += 2;
445 } /* dissect_ieee802154_fcf */
446
447 /*FUNCTION:------------------------------------------------------
448  *  NAME
449  *      dissect_ieee802154_nonask_phy
450  *  DESCRIPTION
451  *      Dissector for IEEE 802.15.4 non-ASK PHY packet with an FCS containing
452  *      a 16-bit CRC value.
453  *
454  *  PARAMETERS
455  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
456  *      packet_info *pinfo  - pointer to packet information fields
457  *      proto_tree *tree    - pointer to data tree wireshark uses to display packet.
458  *  RETURNS
459  *      void
460  *---------------------------------------------------------------
461  */
462 static void
463 dissect_ieee802154_nonask_phy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
464 {
465     proto_tree *ieee802154_tree = NULL;
466     proto_item *proto_root      = NULL;
467
468     guint       offset          = 0;
469     guint32     preamble;
470     guint8      sfd,phr;
471     tvbuff_t*   mac;
472
473     /* Create the protocol tree. */
474     if (tree) {
475         proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154_nonask_phy, tvb, 0, tvb_length(tvb), "IEEE 802.15.4 non-ASK PHY");
476         ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154_nonask_phy);
477     }
478
479     /* Add the protocol name. */
480     col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4 non-ASK PHY");
481     /* Add the packet length. */
482     col_clear(pinfo->cinfo, COL_PACKET_LENGTH);
483     col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, "%i", tvb_length(tvb));
484
485     preamble=tvb_get_letohl(tvb,offset);
486     sfd=tvb_get_guint8(tvb,offset+4);
487     phr=tvb_get_guint8(tvb,offset+4+1);
488
489     if(tree) {
490         proto_tree *phr_tree;
491         proto_item *pi;
492         guint loffset=offset;
493
494         proto_tree_add_uint(ieee802154_tree, hf_ieee802154_nonask_phy_preamble, tvb, loffset, 4, preamble);
495         loffset+=4;
496         proto_tree_add_uint(ieee802154_tree, hf_ieee802154_nonask_phy_sfd, tvb, loffset, 1, sfd);
497         loffset+=1;
498
499         pi = proto_tree_add_text(ieee802154_tree, tvb, loffset, 1, "PHR: 0x%02x", phr);
500         phr_tree = proto_item_add_subtree(pi, ett_ieee802154_nonask_phy_phr);
501
502         proto_tree_add_uint(phr_tree, hf_ieee802154_nonask_phy_length, tvb, loffset, 1, phr);
503     }
504
505     offset+=4+2*1;
506     mac=tvb_new_subset(tvb,offset,-1, phr & IEEE802154_PHY_LENGTH_MASK);
507
508     /* Call the common dissector. */
509     dissect_ieee802154(mac, pinfo, ieee802154_tree);
510 } /* dissect_ieee802154_nonask_phy */
511
512 /*FUNCTION:------------------------------------------------------
513  *  NAME
514  *      dissect_ieee802154
515  *  DESCRIPTION
516  *      Dissector for IEEE 802.15.4 packet with an FCS containing
517  *      a 16-bit CRC value.
518  *
519  *  PARAMETERS
520  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
521  *      packet_info *pinfo  - pointer to packet information fields
522  *      proto_tree *tree    - pointer to data tree wireshark uses to display packet.
523  *  RETURNS
524  *      void
525  *---------------------------------------------------------------
526  */
527 static void
528 dissect_ieee802154(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
529 {
530     /* Call the common dissector. */
531     dissect_ieee802154_common(tvb, pinfo, tree, (ieee802154_cc24xx ? DISSECT_IEEE802154_OPTION_CC24xx : 0));
532 } /* dissect_ieee802154 */
533
534 /*FUNCTION:------------------------------------------------------
535  *  NAME
536  *      dissect_ieee802154_nofcs
537  *  DESCRIPTION
538  *      Dissector for IEEE 802.15.4 packet with no FCS present.
539  *
540  *  PARAMETERS
541  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
542  *      packet_info *pinfo  - pointer to packet information fields
543  *      proto_tree *tree    - pointer to data tree wireshark uses to display packet.
544  *  RETURNS
545  *      void
546  *---------------------------------------------------------------
547  */
548 static void
549 dissect_ieee802154_nofcs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
550 {
551     tvbuff_t    *new_tvb;
552     /* If there is no FCS present in the reported packet, then the length of
553      * the true IEEE 802.15.4 packet is actually 2 bytes longer. Re-create
554      * the buffer with an extended reported length so that the packet will
555      * be handled as though the FCS were truncated.
556      *
557      * Note, we can't just call tvb_set_reported_length(), because it includes
558      * checks to ensure that the new reported length is not longer than the old
559      * reported length (why?), and will throw an exception.
560      */
561     new_tvb = tvb_new_subset(tvb, 0, -1, tvb_reported_length(tvb)+IEEE802154_FCS_LEN);
562     /* Call the common dissector. */
563     dissect_ieee802154_common(new_tvb, pinfo, tree, 0);
564 } /* dissect_ieee802154_nofcs */
565
566 /*FUNCTION:------------------------------------------------------
567  *  NAME
568  *      dissect_ieee802154_cc24xx
569  *  DESCRIPTION
570  *      Dissector for IEEE 802.15.4 packet with a ChipCon/Texas
571  *      Instruments compatible FCS. This is typically called by
572  *      layers encapsulating an IEEE 802.15.4 packet.
573  *
574  *  PARAMETERS
575  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
576  *      packet_info *pinfo  - pointer to packet information fields
577  *      proto_tree *tree    - pointer to data tree wireshark uses to display packet.
578  *  RETURNS
579  *      void
580  *---------------------------------------------------------------
581  */
582 static void
583 dissect_ieee802154_cc24xx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
584 {
585     /* Call the common dissector. */
586     dissect_ieee802154_common(tvb, pinfo, tree, DISSECT_IEEE802154_OPTION_CC24xx);
587 } /* dissect_ieee802154_cc24xx */
588
589 /*FUNCTION:------------------------------------------------------
590  *  NAME
591  *      dissect_ieee802154_common
592  *  DESCRIPTION
593  *      IEEE 802.15.4 packet dissection routine for Wireshark.
594  *      This function extracts all the information first before displaying.
595  *      If payload exists, that portion will be passed into another dissector
596  *      for further processing.
597  *
598  *      This is called after the individual dissect_ieee802154* functions
599  *      have been called to determine what sort of FCS is present.
600  *      The dissect_ieee802154* functions will set the parameters
601  *      in the ieee802154_packet structure, and pass it to this one
602  *      through the data parameter.
603  *
604  *  PARAMETERS
605  *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
606  *      packet_info *pinfo  - pointer to packet information fields
607  *      proto_tree *tree    - pointer to data tree wireshark uses to display packet.
608  *      guint options       - bitwise or of dissector options (see DISSECT_IEEE802154_OPTION_xxx).
609  *  RETURNS
610  *      void
611  *---------------------------------------------------------------
612  */
613 static void
614 dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint options)
615 {
616     tvbuff_t                *volatile payload_tvb;
617     proto_tree              *volatile ieee802154_tree = NULL;
618     proto_item              *volatile proto_root = NULL;
619     proto_item              *hidden_item;
620     proto_item              *ti;
621
622     guint                   offset = 0;
623     volatile gboolean       fcs_ok = TRUE;
624     const char              *saved_proto;
625     ws_decrypt_status       status;
626
627     ieee802154_packet      *packet = wmem_new(wmem_packet_scope(), ieee802154_packet);
628     ieee802154_short_addr   addr16;
629     ieee802154_hints_t     *ieee_hints;
630
631     packet->short_table = ieee802154_map.short_table;
632
633     /* Allocate frame data with hints for upper layers */
634     if(!pinfo->fd->flags.visited){
635         ieee_hints = wmem_new0(wmem_file_scope(), ieee802154_hints_t);
636         p_add_proto_data(pinfo->fd, proto_ieee802154, 0, ieee_hints);
637     } else {
638         ieee_hints = (ieee802154_hints_t *)p_get_proto_data(pinfo->fd, proto_ieee802154, 0);
639     }
640
641     /* Create the protocol tree. */
642     if (tree) {
643         proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154, tvb, 0, tvb_length(tvb), "IEEE 802.15.4");
644         ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154);
645     }
646     /* Add the protocol name. */
647     col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4");
648     /* Add the packet length. */
649     col_clear(pinfo->cinfo, COL_PACKET_LENGTH);
650     col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, "%i", tvb_length(tvb));
651
652     /* Add the packet length to the filter field */
653     hidden_item = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_frame_length, NULL, 0, 0, tvb_reported_length(tvb));
654     PROTO_ITEM_SET_HIDDEN(hidden_item);
655
656     /*=====================================================
657      * FRAME CONTROL FIELD
658      *=====================================================
659      */
660     dissect_ieee802154_fcf(tvb, pinfo, ieee802154_tree, packet, &offset);
661
662     /*=====================================================
663      * SEQUENCE NUMBER
664      *=====================================================
665      */
666     packet->seqno = tvb_get_guint8(tvb, offset);
667     if (tree) {
668         proto_tree_add_uint(ieee802154_tree, hf_ieee802154_seqno, tvb, offset, 1, packet->seqno);
669         /* For Ack packets display this in the root. */
670         if (packet->frame_type == IEEE802154_FCF_ACK) {
671             proto_item_append_text(proto_root, ", Sequence Number: %u", packet->seqno);
672         }
673     }
674     offset += 1;
675
676     /*=====================================================
677      * ADDRESSING FIELDS
678      *=====================================================
679      */
680     /* Clear out the addressing strings. */
681     SET_ADDRESS(&pinfo->dst, AT_NONE, 0, NULL);
682     SET_ADDRESS(&pinfo->src, AT_NONE, 0, NULL);
683     SET_ADDRESS(&pinfo->dl_dst, AT_NONE, 0, NULL);
684     SET_ADDRESS(&pinfo->dl_src, AT_NONE, 0, NULL);
685     SET_ADDRESS(&pinfo->net_dst, AT_NONE, 0, NULL);
686     SET_ADDRESS(&pinfo->net_src, AT_NONE, 0, NULL);
687
688     /* Get and display the destination PAN, if present. */
689     if ( (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) ||
690          (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) ) {
691         packet->dst_pan = tvb_get_letohs(tvb, offset);
692         if (tree) {
693             proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst_panID, tvb, offset, 2, packet->dst_pan);
694         }
695         offset += 2;
696     }
697
698     /* Get destination address. */
699     if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
700         char dst_addr[32];
701
702         /* Get the address. */
703         packet->dst16 = tvb_get_letohs(tvb, offset);
704
705         /* Display the destination address. */
706         if ( packet->dst16 == IEEE802154_BCAST_ADDR ) {
707             g_snprintf(dst_addr, 32, "Broadcast");
708         }
709         else {
710             g_snprintf(dst_addr, 32, "0x%04x", packet->dst16);
711         }
712         /* Provide address hints to higher layers that need it. */
713         if (ieee_hints) {
714             ieee_hints->dst16 = packet->dst16;
715         }
716
717         TVB_SET_ADDRESS(&pinfo->dl_dst, AT_IEEE_802_15_4_SHORT, tvb, offset, 2);
718         TVB_SET_ADDRESS(&pinfo->dst, AT_IEEE_802_15_4_SHORT, tvb, offset, 2);
719
720         if (tree) {
721             proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst16, tvb, offset, 2, packet->dst16);
722             proto_item_append_text(proto_root, ", Dst: %s", dst_addr);
723         }
724
725         col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_addr);
726         offset += 2;
727     }
728     else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
729         static guint64 addr; /* has to be static due to SET_ADDRESS */
730
731         /* Get the address */
732         packet->dst64 = tvb_get_letoh64(tvb, offset);
733
734         /* Copy and convert the address to network byte order. */
735         addr = pntoh64(&(packet->dst64));
736
737         /* Display the destination address. */
738         /* XXX - OUI resolution doesn't happen when displaying resolved
739          * EUI64 addresses; that should probably be fixed in
740          * epan/addr_resolv.c.
741          */
742         SET_ADDRESS(&pinfo->dl_dst, AT_EUI64, 8, &addr);
743         SET_ADDRESS(&pinfo->dst, AT_EUI64, 8, &addr);
744         if (tree) {
745             proto_tree_add_item(ieee802154_tree, hf_ieee802154_dst64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
746             proto_item_append_text(proto_root, ", Dst: %s", get_eui64_name(packet->dst64));
747         }
748         col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", get_eui64_name(packet->dst64));
749         offset += 8;
750     }
751     else if (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) {
752         /* Invalid Destination Address Mode. Abort Dissection. */
753         expert_add_info(pinfo, proto_root, &ei_ieee802154_dst);
754         return;
755     }
756
757     /* Get the source PAN if it exists. The source address will be present if:
758      *  - The Source addressing exists and
759      *  - The Destination addressing doesn't exist, or the Intra-PAN bit is unset.
760      */
761     if ( ((packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) || (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT)) &&
762          ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) || (!packet->intra_pan)) ) {
763         /* Source PAN is present, extract it and add it to the tree. */
764         packet->src_pan = tvb_get_letohs(tvb, offset);
765         if (tree) {
766             proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src_panID, tvb, offset, 2, packet->src_pan);
767         }
768         offset += 2;
769     }
770     else {
771         /* Set the panID field in case the intra-pan condition was met. */
772         packet->src_pan = packet->dst_pan;
773     }
774
775     if (ieee_hints) {
776         ieee_hints->src_pan = packet->src_pan;
777     }
778
779     /* Get short source address if present. */
780     if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
781         char src_addr[32];
782
783         /* Get the address. */
784         packet->src16 = tvb_get_letohs(tvb, offset);
785
786         /* Update the Address fields. */
787         if (packet->src16==IEEE802154_BCAST_ADDR) {
788             g_snprintf(src_addr, 32, "Broadcast");
789         }
790         else {
791             g_snprintf(src_addr, 32, "0x%04x", packet->src16);
792
793             if (!pinfo->fd->flags.visited) {
794                 /* If we know our extended source address from previous packets,
795                  * provide a pointer to it in a hint for upper layers */
796                 addr16.addr = packet->src16;
797                 addr16.pan = packet->src_pan;
798
799                 if (ieee_hints) {
800                     ieee_hints->src16 = packet->src16;
801                     ieee_hints->map_rec = (ieee802154_map_rec *)
802                         g_hash_table_lookup(ieee802154_map.short_table, &addr16);
803                 }
804             }
805         }
806
807         TVB_SET_ADDRESS(&pinfo->dl_src, AT_IEEE_802_15_4_SHORT, tvb, offset, 2);
808         TVB_SET_ADDRESS(&pinfo->src, AT_IEEE_802_15_4_SHORT, tvb, offset, 2);
809
810         /* Add the addressing info to the tree. */
811         if (tree) {
812             proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src16, tvb, offset, 2, packet->src16);
813             proto_item_append_text(proto_root, ", Src: %s", src_addr);
814
815             if (ieee_hints && ieee_hints->map_rec) {
816                 /* Display inferred source address info */
817                 ti = proto_tree_add_eui64(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 0,
818                         ieee_hints->map_rec->addr64);
819                 PROTO_ITEM_SET_GENERATED(ti);
820
821                 if ( ieee_hints->map_rec->start_fnum ) {
822                     ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src64_origin, tvb, 0, 0,
823                         ieee_hints->map_rec->start_fnum);
824                 }
825                 else {
826                     ti = proto_tree_add_text(ieee802154_tree, tvb, 0, 0, "Origin: Pre-configured");
827                 }
828                 PROTO_ITEM_SET_GENERATED(ti);
829             }
830         }
831
832         col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_addr);
833
834         offset += 2;
835     }
836     else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
837         static guint64 addr; /* has to be static due to SET_ADDRESS */
838
839         /* Get the address. */
840         packet->src64 = tvb_get_letoh64(tvb, offset);
841
842         /* Copy and convert the address to network byte order. */
843         addr = pntoh64(&(packet->src64));
844
845         /* Display the source address. */
846         /* XXX - OUI resolution doesn't happen when displaying resolved
847          * EUI64 addresses; that should probably be fixed in
848          * epan/addr_resolv.c.
849          */
850         SET_ADDRESS(&pinfo->dl_src, AT_EUI64, 8, &addr);
851         SET_ADDRESS(&pinfo->src, AT_EUI64, 8, &addr);
852         if (tree) {
853             proto_tree_add_item(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
854             proto_item_append_text(proto_root, ", Src: %s", get_eui64_name(packet->src64));
855         }
856
857         col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", get_eui64_name(packet->src64));
858         offset += 8;
859     }
860     else if (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) {
861         /* Invalid Destination Address Mode. Abort Dissection. */
862         expert_add_info(pinfo, proto_root, &ei_ieee802154_src);
863         return;
864     }
865
866     /*=====================================================
867      * VERIFY FRAME CHECK SEQUENCE
868      *=====================================================
869      */
870     /* Check, but don't display the FCS yet, otherwise the payload dissection
871      * may be out of place in the tree. But we want to know if the FCS is OK in
872      * case the CRC is bad (don't want to continue dissection to the NWK layer).
873      */
874     if (tvb_bytes_exist(tvb, tvb_reported_length(tvb)-IEEE802154_FCS_LEN, IEEE802154_FCS_LEN)) {
875         /* The FCS is in the last two bytes of the packet. */
876         guint16     fcs = tvb_get_letohs(tvb, tvb_reported_length(tvb)-IEEE802154_FCS_LEN);
877         /* Check if we are expecting a CC2420-style FCS*/
878         if (options & DISSECT_IEEE802154_OPTION_CC24xx) {
879             fcs_ok = (fcs & IEEE802154_CC24xx_CRC_OK);
880         }
881         else {
882             guint16 fcs_calc = ieee802154_crc_tvb(tvb, tvb_reported_length(tvb)-IEEE802154_FCS_LEN);
883             fcs_ok = (fcs == fcs_calc);
884         }
885     }
886
887     /*=====================================================
888      * AUXILIARY SECURITY HEADER
889      *=====================================================
890      */
891     /* The Auxiliary Security Header only exists in IEEE 802.15.4-2006 */
892     if (packet->security_enable && (packet->version == IEEE802154_VERSION_2006)) {
893       proto_tree *header_tree, *field_tree;
894       guint8                    security_control;
895       guint                     aux_length = 5; /* Minimum length of the auxiliary header. */
896
897       /* Parse the security control field. */
898       security_control = tvb_get_guint8(tvb, offset);
899       packet->security_level = (ieee802154_security_level)(security_control & IEEE802154_AUX_SEC_LEVEL_MASK);
900       packet->key_id_mode = (ieee802154_key_id_mode)((security_control & IEEE802154_AUX_KEY_ID_MODE_MASK) >> IEEE802154_AUX_KEY_ID_MODE_SHIFT);
901
902       /* Compute the length of the auxiliary header and create a subtree.  */
903       if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) aux_length++;
904       if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) aux_length += 4;
905       if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) aux_length += 8;
906       ti = proto_tree_add_text(ieee802154_tree, tvb, offset, aux_length, "Auxiliary Security Header");
907       header_tree = proto_item_add_subtree(ti, ett_ieee802154_auxiliary_security);
908
909       /* Security Control Field */
910       ti = proto_tree_add_text(header_tree, tvb, offset, 1, "Security Control Field (0x%02x)", security_control);
911       field_tree = proto_item_add_subtree(ti, ett_ieee802154_aux_sec_control);
912       proto_tree_add_uint(field_tree, hf_ieee802154_security_level, tvb, offset, 1, security_control & IEEE802154_AUX_SEC_LEVEL_MASK);
913       proto_tree_add_uint(field_tree, hf_ieee802154_key_id_mode, tvb, offset, 1, security_control & IEEE802154_AUX_KEY_ID_MODE_MASK);
914       proto_tree_add_uint(field_tree, hf_ieee802154_aux_sec_reserved, tvb, offset, 1, security_control & IEEE802154_AUX_KEY_RESERVED_MASK);
915       offset++;
916
917       /* Frame Counter Field */
918       packet->frame_counter = tvb_get_letohl (tvb, offset);
919       proto_tree_add_uint(header_tree, hf_ieee802154_aux_sec_frame_counter, tvb, offset,4, packet->frame_counter);
920       offset +=4;
921
922       /* Key identifier field(s). */
923       if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) {
924         /* Create a subtree. */
925         ti = proto_tree_add_text(header_tree, tvb, offset, 1, "Key Identifier Field"); /* Will fix length later. */
926         field_tree = proto_item_add_subtree(ti, ett_ieee802154_aux_sec_key_id);
927         /* Add key source, if it exists. */
928         if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) {
929           packet->key_source.addr32 = tvb_get_ntohl(tvb, offset);
930           proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, offset, 4, packet->key_source.addr32);
931           proto_item_set_len(ti, 1 + 4);
932           offset += (int)sizeof (guint32);
933         }
934         if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) {
935           packet->key_source.addr64 = tvb_get_ntoh64(tvb, offset);
936           proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, offset, 8, packet->key_source.addr64);
937           proto_item_set_len(ti, 1 + 8);
938           offset += 8;
939         }
940         /* Add key identifier. */
941         packet->key_index = tvb_get_guint8(tvb, offset);
942         proto_tree_add_uint(field_tree, hf_ieee802154_aux_sec_key_index, tvb, offset,1, packet->key_index);
943         offset++;
944       }
945     }
946
947     /*=====================================================
948      * NONPAYLOAD FIELDS
949      *=====================================================
950      */
951     /* All of the beacon fields, except the beacon payload are considered nonpayload. */
952     if (packet->frame_type == IEEE802154_FCF_BEACON) {
953         /* Parse the superframe spec. */
954         dissect_ieee802154_superframe(tvb, pinfo, ieee802154_tree, &offset);
955         /* Parse the GTS information fields. */
956         dissect_ieee802154_gtsinfo(tvb, pinfo, ieee802154_tree, &offset);
957         /* Parse the Pending address list. */
958         dissect_ieee802154_pendaddr(tvb, pinfo, ieee802154_tree, &offset);
959     }
960     /* Only the Command ID is considered nonpayload. */
961     if (packet->frame_type == IEEE802154_FCF_CMD) {
962         packet->command_id = tvb_get_guint8(tvb, offset);
963         if (tree) {
964             proto_tree_add_uint(ieee802154_tree, hf_ieee802154_cmd_id, tvb, offset, 1, packet->command_id);
965         }
966         offset++;
967
968         /* Display the command identifier in the info column. */
969         col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
970     }
971     /* No other frame types have nonpayload fields. */
972
973     /*=====================================================
974      * PAYLOAD DISSECTION
975      *=====================================================
976      */
977     /* IEEE 802.15.4-2003 may have security information pre-pended to payload */
978     if (packet->security_enable && (packet->version == IEEE802154_VERSION_2003)) {
979         /* Store security suite preference in the 2006 security level identifier to simplify 2003 integration! */
980         packet->security_level = (ieee802154_security_level)ieee802154_sec_suite;
981
982         /* Frame Counter and Key Sequence Counter prepended to the payload of an encrypted frame */
983         if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
984             packet->frame_counter = tvb_get_letohl (tvb, offset);
985             proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_frame_counter, tvb, offset, (int)sizeof(guint32), packet->frame_counter);
986             offset += (int)sizeof(guint32);
987
988             packet->key_sequence_counter = tvb_get_guint8 (tvb, offset);
989             proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_key_sequence_counter, tvb, offset, (int)sizeof(guint8), packet->key_sequence_counter);
990             offset += (int)sizeof(guint8);
991         }
992     }
993
994     /* Encrypted Payload. */
995     if (packet->security_enable) {
996         payload_tvb = dissect_ieee802154_decrypt(tvb, offset, pinfo, packet, &status);
997
998         /* Get the unencrypted data if decryption failed.  */
999         if (!payload_tvb) {
1000             /* Deal with possible truncation and the FCS field at the end. */
1001             gint            reported_len = tvb_reported_length(tvb)-offset-IEEE802154_FCS_LEN;
1002             gint            captured_len = tvb_length(tvb)-offset;
1003             if (reported_len < captured_len) captured_len = reported_len;
1004             payload_tvb = tvb_new_subset(tvb, offset, captured_len, reported_len);
1005         }
1006
1007         /* Display the reason for failure, and abort if the error was fatal. */
1008         switch (status) {
1009         case DECRYPT_PACKET_SUCCEEDED:
1010         case DECRYPT_NOT_ENCRYPTED:
1011             /* No problem. */
1012             break;
1013
1014         case DECRYPT_VERSION_UNSUPPORTED:
1015             /* We don't support decryption with that version of the protocol */
1016             expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "We don't support decryption with protocol version %u", packet->version);
1017             call_dissector(data_handle, payload_tvb, pinfo, tree);
1018             goto dissect_ieee802154_fcs;
1019
1020         case DECRYPT_PACKET_TOO_SMALL:
1021             expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "Packet was too small to include the CRC and MIC");
1022             call_dissector(data_handle, payload_tvb, pinfo, tree);
1023             goto dissect_ieee802154_fcs;
1024
1025         case DECRYPT_PACKET_NO_EXT_SRC_ADDR:
1026             expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "No extended source address - can't decrypt");
1027             call_dissector(data_handle, payload_tvb, pinfo, tree);
1028             goto dissect_ieee802154_fcs;
1029
1030         case DECRYPT_PACKET_NO_KEY:
1031             expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "No encryption key set - can't decrypt");
1032             call_dissector(data_handle, payload_tvb, pinfo, tree);
1033             goto dissect_ieee802154_fcs;
1034
1035         case DECRYPT_PACKET_DECRYPT_FAILED:
1036             expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "Decrypt failed");
1037             call_dissector(data_handle, payload_tvb, pinfo, tree);
1038             goto dissect_ieee802154_fcs;
1039
1040         case DECRYPT_PACKET_MIC_CHECK_FAILED:
1041             expert_add_info_format(pinfo, proto_root, &ei_ieee802154_decrypt_error, "MIC check failed");
1042             /*
1043              * Abort only if the payload was encrypted, in which case we
1044              * probably didn't decrypt the packet right (eg: wrong key).
1045              */
1046             if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
1047                 call_dissector(data_handle, payload_tvb, pinfo, tree);
1048                 goto dissect_ieee802154_fcs;
1049             }
1050             break;
1051         }
1052     }
1053     /* Plaintext Payload. */
1054     else {
1055         /* Deal with possible truncation and the FCS field at the end. */
1056         gint            reported_len = tvb_reported_length(tvb)-offset-IEEE802154_FCS_LEN;
1057         gint            captured_len = tvb_length(tvb)-offset;
1058         if (reported_len < captured_len) captured_len = reported_len;
1059         payload_tvb = tvb_new_subset(tvb, offset, captured_len, reported_len);
1060     }
1061
1062     /*
1063      * Wrap the sub-dissection in a try/catch block in case the payload is
1064      * broken. First we store the current protocol so we can fix it if an
1065      * exception is thrown by the subdissectors.
1066      */
1067     saved_proto = pinfo->current_proto;
1068     /* Try to dissect the payload. */
1069     TRY {
1070         if ((packet->frame_type == IEEE802154_FCF_BEACON) ||
1071             (packet->frame_type == IEEE802154_FCF_DATA)) {
1072             /* Beacon and Data packets contain a payload. */
1073             if ((fcs_ok || !ieee802154_fcs_ok) && (tvb_reported_length(payload_tvb)>0)) {
1074                 /* Attempt heuristic subdissection. */
1075                 if (!dissector_try_heuristic(ieee802154_heur_subdissector_list, payload_tvb, pinfo, tree, packet)) {
1076                     /* Could not subdissect, call the data dissector instead. */
1077                     call_dissector(data_handle, payload_tvb, pinfo, tree);
1078                 }
1079             }
1080             else {
1081                 /* If no sub-dissector was called, call the data dissector. */
1082                 call_dissector(data_handle, payload_tvb, pinfo, tree);
1083             }
1084         }
1085         /* If the packet is a command, try to dissect the payload. */
1086         else if (packet->frame_type == IEEE802154_FCF_CMD) {
1087             switch (packet->command_id) {
1088               case IEEE802154_CMD_ASRQ:
1089                 IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
1090                     (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
1091                     (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
1092                 dissect_ieee802154_assoc_req(payload_tvb, pinfo, ieee802154_tree, packet);
1093                 break;
1094
1095               case IEEE802154_CMD_ASRSP:
1096                 IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
1097                     (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
1098                     (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
1099                 dissect_ieee802154_assoc_rsp(payload_tvb, pinfo, ieee802154_tree, packet);
1100                 break;
1101
1102               case IEEE802154_CMD_DISAS:
1103                 IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
1104                     (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
1105                     (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
1106                 dissect_ieee802154_disassoc(payload_tvb, pinfo, ieee802154_tree, packet);
1107                 break;
1108
1109               case IEEE802154_CMD_DATA_RQ:
1110                 IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id, packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE);
1111                 /* No payload expected. */
1112                 break;
1113
1114               case IEEE802154_CMD_PANID_ERR:
1115                 IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
1116                     (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
1117                     (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
1118                 /* No payload expected. */
1119                 break;
1120
1121               case IEEE802154_CMD_ORPH_NOTIF:
1122                 IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
1123                     (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
1124                     (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
1125                     (packet->dst16 == IEEE802154_BCAST_ADDR) &&
1126                     (packet->src_pan == IEEE802154_BCAST_PAN) &&
1127                     (packet->dst_pan == IEEE802154_BCAST_PAN));
1128                 /* No payload expected. */
1129                 break;
1130
1131               case IEEE802154_CMD_BCN_RQ:
1132                 IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
1133                     (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
1134                     (packet->src_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
1135                     (packet->dst16 == IEEE802154_BCAST_ADDR) &&
1136                     (packet->dst_pan == IEEE802154_BCAST_PAN));
1137                 /* No payload expected. */
1138                 break;
1139
1140               case IEEE802154_CMD_COORD_REAL:
1141                 IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
1142                     (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
1143                     (packet->dst_pan == IEEE802154_BCAST_PAN) &&
1144                     (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
1145                 if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
1146                     /* If directed to a 16-bit address, check that it is being broadcast. */
1147                     IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id, packet->dst16 == IEEE802154_BCAST_ADDR);
1148                 }
1149                 dissect_ieee802154_realign(payload_tvb, pinfo, ieee802154_tree, packet);
1150                 break;
1151
1152               case IEEE802154_CMD_GTS_REQ:
1153                 /* Check that the addressing is correct for this command type. */
1154                 IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
1155                     (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
1156                     (packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) &&
1157                     (packet->src16 != IEEE802154_BCAST_ADDR) &&
1158                     (packet->src16 != IEEE802154_NO_ADDR16));
1159                 dissect_ieee802154_gtsreq(payload_tvb, pinfo, ieee802154_tree, packet);
1160                 break;
1161
1162               default:
1163                 /* Unknown Command */
1164                 call_dissector(data_handle, payload_tvb, pinfo, ieee802154_tree);
1165                 break;
1166             } /* switch */
1167         }
1168         /* Otherwise, dump whatever is left over to the data dissector. */
1169         else {
1170             call_dissector(data_handle, payload_tvb, pinfo, tree);
1171         }
1172     }
1173     CATCH_ALL {
1174         /*
1175          * Someone encountered an error while dissecting the payload. But
1176          * we haven't yet finished processing all of our layer. Catch and
1177          * display the exception, then fall-through to finish displaying
1178          * the FCS (which we display last so the frame is ordered correctly
1179          * in the tree).
1180          */
1181         show_exception(payload_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1182         pinfo->current_proto = saved_proto;
1183     }
1184     ENDTRY;
1185
1186     /*=====================================================
1187      * FRAME CHECK SEQUENCE
1188      *=====================================================
1189      */
1190 dissect_ieee802154_fcs:
1191     /* The FCS should be the last bytes of the reported packet. */
1192     offset = tvb_reported_length(tvb)-IEEE802154_FCS_LEN;
1193     /* Dissect the FCS only if it exists (captures which don't or can't get the
1194      * FCS will simply truncate the packet to omit it, but should still set the
1195      * reported length to cover the original packet length), so if the snapshot
1196      * is too short for an FCS don't make a fuss.
1197      */
1198     if (tvb_bytes_exist(tvb, offset, IEEE802154_FCS_LEN) && (tree)) {
1199         proto_tree  *field_tree;
1200         guint16     fcs = tvb_get_letohs(tvb, offset);
1201
1202         /* Display the FCS depending on expected FCS format */
1203         if ((options & DISSECT_IEEE802154_OPTION_CC24xx)) {
1204             /* Create a subtree for the FCS. */
1205             ti = proto_tree_add_text(ieee802154_tree, tvb, offset, 2, "Frame Check Sequence (TI CC24xx format): FCS %s", (fcs_ok) ? "OK" : "Bad");
1206             field_tree = proto_item_add_subtree(ti, ett_ieee802154_fcs);
1207             /* Display FCS contents.  */
1208             ti = proto_tree_add_int(field_tree, hf_ieee802154_rssi, tvb, offset++, 1, (gint8) (fcs & IEEE802154_CC24xx_RSSI));
1209             proto_item_append_text(ti, " dB");  /*  Displaying Units */
1210             proto_tree_add_boolean(field_tree, hf_ieee802154_fcs_ok, tvb, offset, 1, (gboolean) (fcs & IEEE802154_CC24xx_CRC_OK));
1211             proto_tree_add_uint(field_tree, hf_ieee802154_correlation, tvb, offset, 1, (guint8) ((fcs & IEEE802154_CC24xx_CORRELATION) >> 8));
1212         }
1213         else {
1214             ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_fcs, tvb, offset, 2, fcs);
1215             if (fcs_ok) {
1216                 proto_item_append_text(ti, " (Correct)");
1217             }
1218             else {
1219                 proto_item_append_text(ti, " (Incorrect, expected FCS=0x%04x", ieee802154_crc_tvb(tvb, offset));
1220             }
1221             /* To Help with filtering, add the fcs_ok field to the tree.  */
1222             ti = proto_tree_add_boolean(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, offset, 2, fcs_ok);
1223             PROTO_ITEM_SET_HIDDEN(ti);
1224         }
1225     }
1226     else if (tree) {
1227         /* Even if the FCS isn't present, add the fcs_ok field to the tree to
1228          * help with filter. Be sure not to make it visible though.
1229          */
1230         ti = proto_tree_add_boolean_format_value(ieee802154_tree, hf_ieee802154_fcs_ok, tvb, offset, 2, fcs_ok, "Unknown");
1231         PROTO_ITEM_SET_HIDDEN(ti);
1232     }
1233
1234     /* If the CRC is invalid, make a note of it in the info column. */
1235     if (!fcs_ok) {
1236         col_append_str(pinfo->cinfo, COL_INFO, ", Bad FCS");
1237         if (tree) proto_item_append_text(proto_root, ", Bad FCS");
1238
1239         /* Flag packet as having a bad crc. */
1240         expert_add_info(pinfo, proto_root, &ei_ieee802154_fcs);
1241     }
1242 } /* dissect_ieee802154_common */
1243
1244 /*FUNCTION:------------------------------------------------------
1245  *  NAME
1246  *      dissect_ieee802154_superframe
1247  *  DESCRIPTION
1248  *      Subdissector command for the Superframe specification
1249  *      sub-field within the beacon frame.
1250  *  PARAMETERS
1251  *      tvbuff_t    *tvb            - pointer to buffer containing raw packet.
1252  *      packet_info *pinfo          - pointer to packet information fields (unused).
1253  *      proto_tree  *tree           - pointer to command subtree.
1254  *      ieee802154_packet *packet   - IEEE 802.15.4 packet information (unused).
1255  *      guint       *offset         - offset into the tvbuff to begin dissection.
1256  *  RETURNS
1257  *      void
1258  *---------------------------------------------------------------
1259  */
1260 static void
1261 dissect_ieee802154_superframe(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
1262 {
1263     proto_tree *field_tree = NULL;
1264     proto_item *ti;
1265     guint16     superframe;
1266
1267     /* Parse the superframe spec. */
1268     superframe = tvb_get_letohs(tvb, *offset);
1269     if (tree) {
1270         /*  Add Subtree for superframe specification */
1271         ti = proto_tree_add_text(tree, tvb, *offset, 2, "Superframe Specification");
1272         field_tree = proto_item_add_subtree(ti, ett_ieee802154_superframe);
1273
1274         /*  Add Beacon Order to the superframe spec. */
1275         proto_tree_add_uint(field_tree, hf_ieee802154_beacon_order, tvb, *offset, 2, superframe & IEEE802154_BEACON_ORDER_MASK);
1276         proto_tree_add_uint(field_tree, hf_ieee802154_superframe_order, tvb, *offset, 2, superframe & IEEE802154_SUPERFRAME_ORDER_MASK);
1277         proto_tree_add_uint(field_tree, hf_ieee802154_cap, tvb, *offset, 2, superframe & IEEE802154_SUPERFRAME_CAP_MASK);
1278         proto_tree_add_boolean(field_tree, hf_ieee802154_superframe_battery_ext, tvb, *offset, 2, superframe & IEEE802154_BATT_EXTENSION_MASK);
1279         proto_tree_add_boolean(field_tree, hf_ieee802154_superframe_coord, tvb, *offset, 2, superframe & IEEE802154_SUPERFRAME_COORD_MASK);
1280         proto_tree_add_boolean(field_tree, hf_ieee802154_assoc_permit, tvb, *offset, 2, superframe & IEEE802154_ASSOC_PERMIT_MASK);
1281     }
1282     (*offset) += 2;
1283 } /* dissect_ieee802154_superframe */
1284
1285 /*FUNCTION:------------------------------------------------------
1286  *  NAME
1287  *      dissect_ieee802154_gtsinfo
1288  *  DESCRIPTION
1289  *      Subdissector command for the GTS information fields within
1290  *      the beacon frame.
1291  *  PARAMETERS
1292  *      tvbuff_t    *tvb            - pointer to buffer containing raw packet.
1293  *      packet_info *pinfo          - pointer to packet information fields (unused).
1294  *      proto_tree  *tree           - pointer to command subtree.
1295  *      ieee802154_packet *packet   - IEEE 802.15.4 packet information (unused).
1296  *      guint       *offset         - offset into the tvbuff to begin dissection.
1297  *  RETURNS
1298  *      void
1299  *---------------------------------------------------------------
1300  */
1301 static void
1302 dissect_ieee802154_gtsinfo(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
1303 {
1304     proto_tree *field_tree = NULL;
1305     proto_tree *subtree    = NULL;
1306     proto_item *ti;
1307     guint8      gts_spec;
1308     guint8      gts_count;
1309
1310     /*  Get and display the GTS specification field */
1311     gts_spec = tvb_get_guint8(tvb, *offset);
1312     gts_count = gts_spec & IEEE802154_GTS_COUNT_MASK;
1313     if (tree) {
1314         /*  Add Subtree for GTS information. */
1315         if (gts_count) {
1316             ti = proto_tree_add_text(tree, tvb, *offset, 2 + (gts_count * 3), "GTS");
1317         }
1318         else {
1319             ti = proto_tree_add_text(tree, tvb, *offset, 1, "GTS");
1320         }
1321         field_tree = proto_item_add_subtree(ti, ett_ieee802154_gts);
1322
1323         proto_tree_add_uint(field_tree, hf_ieee802154_gts_count, tvb, *offset, 1, gts_count);
1324         proto_tree_add_boolean(field_tree, hf_ieee802154_gts_permit, tvb, *offset, 1, gts_spec & IEEE802154_GTS_PERMIT_MASK);
1325     }
1326     (*offset) += 1;
1327
1328     /* If the GTS descriptor count is nonzero, then the GTS directions mask and descriptor list are present. */
1329     if (gts_count) {
1330         guint8  gts_directions = tvb_get_guint8(tvb, *offset);
1331         guint   gts_rx = 0;
1332         int     i;
1333
1334         /* Display the directions mask. */
1335         if (tree) {
1336             proto_tree  *dir_tree = NULL;
1337
1338             /* Create a subtree. */
1339             ti = proto_tree_add_text(field_tree, tvb, *offset, 1, "GTS Directions");
1340             dir_tree = proto_item_add_subtree(ti, ett_ieee802154_gts_direction);
1341
1342             /* Add the directions to the subtree. */
1343             for (i=0; i<gts_count; i++) {
1344                 gboolean    dir = gts_directions & IEEE802154_GTS_DIRECTION_SLOT(i);
1345                 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");
1346                 if (dir) gts_rx++;
1347             } /* for */
1348             proto_item_append_text(ti, ": %i Receive & %i Transmit", gts_rx, gts_count - gts_rx);
1349         }
1350         (*offset) += 1;
1351
1352         /* Create a subtree for the GTS descriptors. */
1353         if (tree) {
1354             ti = proto_tree_add_text(field_tree, tvb, *offset, gts_count * 3, "GTS Descriptors");
1355             subtree = proto_item_add_subtree(ti, ett_ieee802154_gts_descriptors);
1356         }
1357
1358         /* Get and display the GTS descriptors. */
1359         for (i=0; i<gts_count; i++) {
1360             guint16 gts_addr        = tvb_get_letohs(tvb, (*offset));
1361             guint8  gts_slot        = tvb_get_guint8(tvb, (*offset)+2);
1362             guint8  gts_length      = (gts_slot & IEEE802154_GTS_LENGTH_MASK) >> IEEE802154_GTS_LENGTH_SHIFT;
1363
1364             gts_slot = (gts_slot & IEEE802154_GTS_SLOT_MASK);
1365
1366             if (tree) {
1367                 /* Add address, slot, and time length fields. */
1368                 ti = proto_tree_add_text(subtree, tvb, (*offset), 3, "{Address: 0x%04x", gts_addr);
1369                 proto_item_append_text(ti, ", Slot: %i", gts_slot);
1370                 proto_item_append_text(ti, ", Length: %i}", gts_length);
1371             }
1372             (*offset) += 3;
1373         } /* for */
1374     }
1375 } /* dissect_ieee802154_gtsinfo */
1376
1377 /*FUNCTION:------------------------------------------------------
1378  *  NAME
1379  *      dissect_ieee802154_pendaddr
1380  *  DESCRIPTION
1381  *      Subdissector command for the pending address list fields
1382  *      within the beacon frame.
1383  *  PARAMETERS
1384  *      tvbuff_t    *tvb            - pointer to buffer containing raw packet.
1385  *      packet_info *pinfo          - pointer to packet information fields (unused).
1386  *      proto_tree  *tree           - pointer to command subtree.
1387  *      ieee802154_packet *packet   - IEEE 802.15.4 packet information (unused).
1388  *      guint       *offset         - offset into the tvbuff to begin dissection.
1389  *  RETURNS
1390  *      void
1391  *---------------------------------------------------------------
1392  */
1393 static void
1394 dissect_ieee802154_pendaddr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint *offset)
1395 {
1396     proto_tree *subtree = NULL;
1397     proto_item *ti;
1398     guint8      pend_spec;
1399     guint8      pend_num16;
1400     guint8      pend_num64;
1401     int         i;
1402
1403     /*  Get the Pending Addresses specification fields */
1404     pend_spec = tvb_get_guint8(tvb, *offset);
1405     pend_num16 = pend_spec & IEEE802154_PENDADDR_SHORT_MASK;
1406     pend_num64 = (pend_spec & IEEE802154_PENDADDR_LONG_MASK) >> IEEE802154_PENDADDR_LONG_SHIFT;
1407     if (tree) {
1408         /*  Add Subtree for the addresses */
1409         ti = proto_tree_add_text(tree, tvb, *offset, 1 + 2*pend_num16 + 8*pend_num64, "Pending Addresses: %i Short and %i Long", pend_num16, pend_num64);
1410         subtree = proto_item_add_subtree(ti, ett_ieee802154_pendaddr);
1411     }
1412     (*offset) += 1;
1413
1414     for (i=0; i<pend_num16; i++) {
1415         guint16 addr = tvb_get_letohs(tvb, *offset);
1416         proto_tree_add_uint(subtree, hf_ieee802154_pending16, tvb, *offset, 2, addr);
1417         (*offset) += 2;
1418     } /* for */
1419     for (i=0; i<pend_num64; i++) {
1420         proto_tree_add_item(subtree, hf_ieee802154_pending64, tvb, *offset, 8, ENC_LITTLE_ENDIAN);
1421         (*offset) += 8;
1422     } /* for */
1423 } /* dissect_ieee802154_pendaddr */
1424
1425 /*FUNCTION:------------------------------------------------------
1426  *  NAME
1427  *      dissect_ieee802154_assoc_req
1428  *  DESCRIPTION
1429  *      Command subdissector routine for the Association request
1430  *      command.
1431  *  PARAMETERS
1432  *      tvbuff_t    *tvb            - pointer to buffer containing raw packet.
1433  *      packet_info *pinfo          - pointer to packet information fields.
1434  *      proto_tree  *tree           - pointer to protocol tree.
1435  *      ieee802154_packet *packet   - IEEE 802.15.4 packet information.
1436  *  RETURNS
1437  *      void
1438  *---------------------------------------------------------------
1439  */
1440 static void
1441 dissect_ieee802154_assoc_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
1442 {
1443     proto_tree   *subtree = NULL;
1444     proto_item *  ti;
1445     guint8        capability;
1446
1447     /* Create a subtree for this command frame. */
1448     if (tree) {
1449         ti = proto_tree_add_text(tree, tvb, 0, 1, "%s", val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
1450         subtree = proto_item_add_subtree(ti, ett_ieee802154_cmd);
1451     }
1452
1453     /* Get and display capability info. */
1454     capability = tvb_get_guint8(tvb, 0);
1455     if (tree) {
1456         /* Enter the capability bits. */
1457         proto_tree_add_boolean(subtree, hf_ieee802154_cinfo_alt_coord, tvb, 0, 1, capability & IEEE802154_CMD_CINFO_ALT_PAN_COORD);
1458         ti = proto_tree_add_boolean(subtree, hf_ieee802154_cinfo_device_type, tvb, 0, 1, capability & IEEE802154_CMD_CINFO_DEVICE_TYPE);
1459         if (capability & IEEE802154_CMD_CINFO_DEVICE_TYPE) proto_item_append_text(ti, " (FFD)");
1460         else proto_item_append_text(ti, " (RFD)");
1461         ti = proto_tree_add_boolean(subtree, hf_ieee802154_cinfo_power_src, tvb, 0, 1, capability & IEEE802154_CMD_CINFO_POWER_SRC);
1462         if (capability & IEEE802154_CMD_CINFO_POWER_SRC) proto_item_append_text(ti, " (AC/Mains Power)");
1463         else proto_item_append_text(ti, " (Battery)");
1464         proto_tree_add_boolean(subtree, hf_ieee802154_cinfo_idle_rx, tvb, 0, 1, capability & IEEE802154_CMD_CINFO_IDLE_RX);
1465         proto_tree_add_boolean(subtree, hf_ieee802154_cinfo_sec_capable, tvb, 0, 1, capability & IEEE802154_CMD_CINFO_SEC_CAPABLE);
1466         proto_tree_add_boolean(subtree, hf_ieee802154_cinfo_alloc_addr, tvb, 0, 1, capability & IEEE802154_CMD_CINFO_ALLOC_ADDR);
1467     }
1468
1469     /* Call the data dissector for any leftover bytes. */
1470     if (tvb_length(tvb) > 1) {
1471         call_dissector(data_handle, tvb_new_subset_remaining(tvb, 1), pinfo, tree);
1472     }
1473 } /* dissect_ieee802154_assoc_req */
1474
1475 /*FUNCTION:------------------------------------------------------
1476  *  NAME
1477  *      dissect_ieee802154_assoc_rsp
1478  *  DESCRIPTION
1479  *      Command subdissector routine for the Association response
1480  *      command.
1481  *  PARAMETERS
1482  *      tvbuff_t    *tvb            - pointer to buffer containing raw packet.
1483  *      packet_info *pinfo          - pointer to packet information fields.
1484  *      proto_tree  *tree           - pointer to protocol tree.
1485  *      ieee802154_packet *packet   - IEEE 802.15.4 packet information.
1486  *  RETURNS
1487  *      void
1488  *---------------------------------------------------------------
1489  */
1490 static void
1491 dissect_ieee802154_assoc_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
1492 {
1493     proto_tree *subtree = NULL;
1494     proto_item *ti;
1495     guint16     short_addr;
1496     guint8      status;
1497     guint       offset  = 0;
1498
1499     /* Create a subtree for this command frame. */
1500     if (tree) {
1501         ti = proto_tree_add_text(tree, tvb, offset, 3, "%s", val_to_str_const(packet->command_id,
1502                     ieee802154_cmd_names, "Unknown Command"));
1503         subtree = proto_item_add_subtree(ti, ett_ieee802154_cmd);
1504     }
1505
1506     /* Get and display the short address. */
1507     short_addr = tvb_get_letohs(tvb, offset);
1508     if (tree) {
1509         proto_tree_add_uint(subtree, hf_ieee802154_assoc_addr, tvb, offset, 2, short_addr);
1510     }
1511     offset += 2;
1512
1513     /* Get and display the status. */
1514     status = tvb_get_guint8(tvb, offset);
1515     if (tree) {
1516         ti = proto_tree_add_uint(subtree, hf_ieee802154_assoc_status, tvb, offset, 1, status);
1517         if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) proto_item_append_text(ti, " (Association Successful)");
1518         else if (status == IEEE802154_CMD_ASRSP_PAN_FULL) proto_item_append_text(ti, " (PAN Full)");
1519         else if (status == IEEE802154_CMD_ASRSP_PAN_DENIED) proto_item_append_text(ti, " (Association Denied)");
1520         else proto_item_append_text(ti, " (Reserved)");
1521     }
1522     offset += 1;
1523
1524     /* Update the info column. */
1525     if (status == IEEE802154_CMD_ASRSP_AS_SUCCESS) {
1526         /* Association was successful. */
1527         if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {
1528             col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", packet->dst_pan);
1529         }
1530         if (short_addr != IEEE802154_NO_ADDR16) {
1531             col_append_fstr(pinfo->cinfo, COL_INFO, " Addr: 0x%04x", short_addr);
1532         }
1533     }
1534     else {
1535         /* Association was unsuccessful. */
1536         col_append_fstr(pinfo->cinfo, COL_INFO, ", Unsuccessful");
1537     }
1538
1539     /* Update the address table. */
1540     if ((status == IEEE802154_CMD_ASRSP_AS_SUCCESS) && (short_addr != IEEE802154_NO_ADDR16)) {
1541         ieee802154_addr_update(&ieee802154_map, short_addr, packet->dst_pan, packet->dst64,
1542                 pinfo->current_proto, pinfo->fd->num);
1543     }
1544
1545     /* Call the data dissector for any leftover bytes. */
1546     if (tvb_length(tvb) > offset) {
1547         call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree);
1548     }
1549 } /* dissect_ieee802154_assoc_rsp */
1550
1551 /*FUNCTION:------------------------------------------------------
1552  *  NAME
1553  *      dissect_ieee802154_disassoc
1554  *  DESCRIPTION
1555  *      Command subdissector routine for the Disassociate command.
1556  *  PARAMETERS
1557  *      tvbuff_t    *tvb            - pointer to buffer containing raw packet.
1558  *      packet_info *pinfo          - pointer to packet information fields.
1559  *      proto_tree  *tree           - pointer to protocol tree.
1560  *      ieee802154_packet *packet   - IEEE 802.15.4 packet information.
1561  *  RETURNS
1562  *      void
1563  *---------------------------------------------------------------
1564  */
1565 static void
1566 dissect_ieee802154_disassoc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
1567 {
1568     proto_tree *subtree = NULL;
1569     proto_item *ti;
1570     guint8      reason;
1571
1572     /* Create a subtree for this command frame. */
1573     if (tree) {
1574         ti = proto_tree_add_text(tree, tvb, 0, 1, "%s", val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
1575         subtree = proto_item_add_subtree(ti, ett_ieee802154_cmd);
1576     }
1577
1578     /* Get and display the disassociation reason. */
1579     reason = tvb_get_guint8(tvb, 0);
1580     if (tree) {
1581         ti = proto_tree_add_uint(subtree, hf_ieee802154_disassoc_reason, tvb, 0, 1, reason);
1582         switch(reason) {
1583             case 0x01:
1584                 proto_item_append_text(ti, " (Coordinator requests device to leave)");
1585                 break;
1586
1587             case 0x02:
1588                 proto_item_append_text(ti, " (Device wishes to leave)");
1589                 break;
1590
1591             default:
1592                 proto_item_append_text(ti, " (Reserved)");
1593                 break;
1594         } /* switch */
1595     }
1596
1597     if (!pinfo->fd->flags.visited) {
1598         /* Update the address tables */
1599         if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT ) {
1600             ieee802154_long_addr_invalidate(packet->dst64, pinfo->fd->num);
1601         } else if ( packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT ) {
1602             ieee802154_short_addr_invalidate(packet->dst16, packet->dst_pan, pinfo->fd->num);
1603         }
1604     }
1605
1606     /* Call the data dissector for any leftover bytes. */
1607     if (tvb_length(tvb) > 1) {
1608         call_dissector(data_handle, tvb_new_subset_remaining(tvb, 1), pinfo, tree);
1609     }
1610 } /* dissect_ieee802154_disassoc */
1611
1612 /*FUNCTION:------------------------------------------------------
1613  *  NAME
1614  *      dissect_ieee802154_realign
1615  *  DESCRIPTION
1616  *      Command subdissector routine for the Coordinator Realignment
1617  *      command.
1618  *  PARAMETERS
1619  *      tvbuff_t    *tvb            - pointer to buffer containing raw packet.
1620  *      packet_info *pinfo          - pointer to packet information fields.
1621  *      proto_tree  *tree           - pointer to protocol tree.
1622  *      ieee802154_packet *packet   - IEEE 802.15.4 packet information.
1623  *  RETURNS
1624  *      void
1625  *---------------------------------------------------------------
1626  */
1627 static void
1628 dissect_ieee802154_realign(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
1629 {
1630     proto_tree *subtree = NULL;
1631     proto_item *ti;
1632     guint16     pan_id;
1633     guint16     coord_addr;
1634     guint8      channel;
1635     guint16     short_addr;
1636     guint       offset  = 0;
1637
1638     /* Create a subtree for this command frame. */
1639     if (tree) {
1640         ti = proto_tree_add_text(tree, tvb, offset, 0, "%s", val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
1641         subtree = proto_item_add_subtree(ti, ett_ieee802154_cmd);
1642     }
1643
1644     /* Get and display the command PAN ID. */
1645     pan_id = tvb_get_letohs(tvb, offset);
1646     proto_tree_add_uint(subtree, hf_ieee802154_realign_pan, tvb, offset, 2, pan_id);
1647     col_append_fstr(pinfo->cinfo, COL_INFO, ", PAN: 0x%04x", pan_id);
1648     offset += 2;
1649
1650     /* Get and display the coordinator address. */
1651     coord_addr = tvb_get_letohs(tvb, offset);
1652     proto_tree_add_uint(subtree, hf_ieee802154_realign_caddr, tvb, offset, 2, coord_addr);
1653     col_append_fstr(pinfo->cinfo, COL_INFO, ", Coordinator: 0x%04x", coord_addr);
1654     offset += 2;
1655
1656     /* Get and display the channel. */
1657     channel = tvb_get_guint8(tvb, offset);
1658     proto_tree_add_uint(subtree, hf_ieee802154_realign_channel, tvb, offset, 1, channel);
1659     col_append_fstr(pinfo->cinfo, COL_INFO, ", Channel: %u", channel);
1660     offset += 1;
1661
1662     /* Get and display the short address. */
1663     short_addr = tvb_get_letohs(tvb, offset);
1664     if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_addr, tvb, offset, 2, short_addr);
1665     if ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)
1666         && (short_addr != IEEE802154_NO_ADDR16)) {
1667         col_append_fstr(pinfo->cinfo, COL_INFO, ", Addr: 0x%04x", short_addr);
1668     }
1669     offset += 2;
1670     /* Update the address table. */
1671     if ((short_addr != IEEE802154_NO_ADDR16) && (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT)) {
1672         ieee802154_addr_update(&ieee802154_map, short_addr, packet->dst_pan, packet->dst64,
1673                 pinfo->current_proto, pinfo->fd->num);
1674     }
1675
1676     /* Get and display the channel page, if it exists. Added in IEEE802.15.4-2006 */
1677     if (tvb_bytes_exist(tvb, offset, 1)) {
1678         guint8  channel_page = tvb_get_guint8(tvb, offset);
1679         if (tree) proto_tree_add_uint(subtree, hf_ieee802154_realign_channel_page, tvb, offset, 1, channel_page);
1680         offset += 1;
1681     }
1682
1683     /* Fix the length of the command subtree. */
1684     if (tree) {
1685         proto_item_set_len(subtree, offset);
1686     }
1687
1688     /* Call the data dissector for any leftover bytes. */
1689     if (tvb_length(tvb) > offset) {
1690         call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree);
1691     }
1692 } /* dissect_ieee802154_realign */
1693
1694 /*FUNCTION:------------------------------------------------------
1695  *  NAME
1696  *      dissect_ieee802154_gtsreq
1697  *  DESCRIPTION
1698  *      Command subdissector routine for the GTS request command.
1699  *
1700  *      Assumes that COL_INFO will be set to the command name,
1701  *      command name will already be appended to the command subtree
1702  *      and protocol root. In addition, assumes that the command ID
1703  *      has already been parsed.
1704  *  PARAMETERS
1705  *      tvbuff_t    *tvb            - pointer to buffer containing raw packet.
1706  *      packet_info *pinfo          - pointer to packet information fields (unused).
1707  *      proto_tree  *tree           - pointer to protocol tree.
1708  *      ieee802154_packet *packet   - IEEE 802.15.4 packet information (unused).
1709  *  RETURNS
1710  *      void
1711  *---------------------------------------------------------------
1712  */
1713 static void
1714 dissect_ieee802154_gtsreq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet)
1715 {
1716     proto_tree *subtree = NULL;
1717     proto_item *ti;
1718     guint8      characteristics;
1719     guint8      length;
1720     guint8      direction;
1721     guint8      type;
1722
1723     /* Create a subtree for this command frame. */
1724     if (tree) {
1725         ti = proto_tree_add_text(tree, tvb, 0, 1, "%s", val_to_str_const(packet->command_id, ieee802154_cmd_names,
1726                                                                          "Unknown Command"));
1727         subtree = proto_item_add_subtree(ti, ett_ieee802154_cmd);
1728     }
1729
1730     /* Get the characteristics field. */
1731     characteristics = tvb_get_guint8(tvb, 0);
1732     length = characteristics & IEEE802154_CMD_GTS_REQ_LEN;
1733     direction = characteristics & IEEE802154_CMD_GTS_REQ_DIR;
1734     type = characteristics & IEEE802154_CMD_GTS_REQ_TYPE;
1735
1736     /* Display the characteristics field. */
1737     if (tree) {
1738         proto_tree_add_uint(subtree, hf_ieee802154_gtsreq_len, tvb, 0, 1, length);
1739         ti = proto_tree_add_boolean(subtree, hf_ieee802154_gtsreq_dir, tvb, 0, 1, direction);
1740         if (direction) proto_item_append_text(ti, " (Receive)");
1741         else proto_item_append_text(ti, " (Transmit)");
1742         ti = proto_tree_add_boolean(subtree, hf_ieee802154_gtsreq_type, tvb, 0, 1, type);
1743         if (type) proto_item_append_text(ti, " (Allocate GTS)");
1744         else proto_item_append_text(ti, " (Deallocate GTS)");
1745     }
1746
1747     /* Call the data dissector for any leftover bytes. */
1748     if (tvb_length(tvb) > 1) {
1749         call_dissector(data_handle, tvb_new_subset_remaining(tvb, 1), pinfo, tree);
1750     }
1751 } /* dissect_ieee802154_gtsreq */
1752
1753 /*FUNCTION:------------------------------------------------------
1754  *  NAME
1755  *      dissect_ieee802154_decrypt
1756  *  DESCRIPTION
1757  *      IEEE 802.15.4 decryption algorithm. Tries to find the
1758  *      appropriate key from the information in the IEEE 802.15.4
1759  *      packet structure and dissector config.
1760  *
1761  *      This function implements the security proceedures for the
1762  *      2006 version of the spec only. IEEE 802.15.4-2003 is
1763  *      unsupported.
1764  *  PARAMETERS
1765  *      tvbuff_t *tvb               - IEEE 802.15.4 packet.
1766  *      packet_info * pinfo         - Packet info structure.
1767  *      guint offset                - Offset where the ciphertext 'c' starts.
1768  *      ieee802154_packet *packet   - IEEE 802.15.4 packet information.
1769  *      ws_decrypt_status *status   - status of decryption returned through here on failure.
1770  *  RETURNS
1771  *      tvbuff_t *                  - Decrypted payload.
1772  *---------------------------------------------------------------
1773  */
1774 static tvbuff_t *
1775 dissect_ieee802154_decrypt(tvbuff_t * tvb, guint offset, packet_info * pinfo, ieee802154_packet * packet, ws_decrypt_status * status)
1776 {
1777     tvbuff_t *          ptext_tvb;
1778     gboolean            have_mic = FALSE;
1779     guint64             srcAddr;
1780     unsigned char       key[16];
1781     unsigned char       tmp[16];
1782     unsigned char       rx_mic[16];
1783     guint               M;
1784     gint                captured_len;
1785     gint                reported_len;
1786     ieee802154_hints_t *ieee_hints;
1787
1788     /*
1789      * Check the version; we only support IEEE 802.15.4-2003 and IEEE 802.15.4-2006.
1790      * We must do this first, as, if this isn't IEEE 802.15.4-2003 or IEEE 802.15.4-2006,
1791      * we don't have the Auxiliary Security Header, and haven't
1792      * filled in the information for it, and none of the stuff
1793      * we do afterwards, which uses that information, is doable.
1794      */
1795     if ((packet->version != IEEE802154_VERSION_2006) && (packet->version != IEEE802154_VERSION_2003)) {
1796         *status = DECRYPT_VERSION_UNSUPPORTED;
1797         return NULL;
1798     }
1799
1800     ieee_hints = (ieee802154_hints_t *)p_get_proto_data(pinfo->fd, proto_ieee802154, 0);
1801
1802     /* Get the captured and on-the-wire length of the payload. */
1803     M = IEEE802154_MIC_LENGTH(packet->security_level);
1804     reported_len = tvb_reported_length_remaining(tvb, offset) - IEEE802154_FCS_LEN - M;
1805     if (reported_len < 0) {
1806         *status = DECRYPT_PACKET_TOO_SMALL;
1807         return NULL;
1808     }
1809     /* Check of the payload is truncated.  */
1810     if (tvb_bytes_exist(tvb, offset, reported_len)) {
1811         captured_len = reported_len;
1812     }
1813     else {
1814         captured_len = tvb_length_remaining(tvb, offset);
1815     }
1816
1817     /* Check if the MIC is present in the captured data. */
1818     have_mic = tvb_bytes_exist(tvb, offset + reported_len, M);
1819     if (have_mic) {
1820         tvb_memcpy(tvb, rx_mic, offset + reported_len, M);
1821     }
1822
1823     /*=====================================================
1824      * Key Lookup - Need to find the appropriate key.
1825      *=====================================================
1826      */
1827     /*
1828      * Oh God! The specification is so bad. This is the worst
1829      * case of design-by-committee I've ever seen in my life.
1830      * The IEEE has created an unintelligable mess in order
1831      * to decipher which key is used for which message.
1832      *
1833      * Let's hope it's simpler to implement for dissecting only.
1834      *
1835      * Also need to find the extended address of the sender.
1836      */
1837     if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
1838         /* The source EUI-64 is included in the headers. */
1839         srcAddr = packet->src64;
1840     }
1841     else if (ieee_hints && ieee_hints->map_rec && ieee_hints->map_rec->addr64) {
1842         /* Use the hint */
1843         srcAddr = ieee_hints->map_rec->addr64;
1844     }
1845     else {
1846         /* Lookup failed.  */
1847         *status = DECRYPT_PACKET_NO_EXT_SRC_ADDR;
1848         return NULL;
1849     }
1850
1851     /* Lookup the key. */
1852     /*
1853      * TODO: What this dissector really needs is a UAT to store multiple keys
1854      * and a variety of key configuration data. However, a single shared key
1855      * should be sufficient to get packet encryption off to a start.
1856      */
1857     if (!ieee802154_key_valid) {
1858         *status = DECRYPT_PACKET_NO_KEY;
1859         return NULL;
1860     }
1861     memcpy(key, ieee802154_key, IEEE802154_CIPHER_SIZE);
1862
1863     /*=====================================================
1864      * CCM* - CTR mode payload encryption
1865      *=====================================================
1866      */
1867     /* Create the CCM* initial block for decryption (Adata=0, M=0, counter=0). */
1868     ccm_init_block(tmp, FALSE, 0, srcAddr, packet, 0);
1869
1870     /* Decrypt the ciphertext, and place the plaintext in a new tvb. */
1871     if (IEEE802154_IS_ENCRYPTED(packet->security_level) && captured_len) {
1872         guint8 *          text;
1873         /*
1874          * Make a copy of the ciphertext in heap memory.
1875          *
1876          * We will decrypt the message in-place and then use the buffer as the
1877          * real data for the new tvb.
1878          */
1879         text = (guint8 *)tvb_memdup(NULL, tvb, offset, captured_len);
1880
1881         /* Perform CTR-mode transformation. */
1882         if (!ccm_ctr_encrypt(key, tmp, rx_mic, text, captured_len)) {
1883             g_free(text);
1884             *status = DECRYPT_PACKET_DECRYPT_FAILED;
1885             return NULL;
1886         }
1887
1888         /* Create a tvbuff for the plaintext. */
1889         ptext_tvb = tvb_new_child_real_data(tvb, text, captured_len, reported_len);
1890         tvb_set_free_cb(ptext_tvb, g_free);
1891         add_new_data_source(pinfo, ptext_tvb, "Decrypted IEEE 802.15.4 payload");
1892         *status = DECRYPT_PACKET_SUCCEEDED;
1893     }
1894     /* There is no ciphertext. Wrap the plaintext in a new tvb. */
1895     else {
1896         /* Decrypt the MIC (if present). */
1897         if ((have_mic) && (!ccm_ctr_encrypt(key, tmp, rx_mic, NULL, 0))) {
1898             *status = DECRYPT_PACKET_DECRYPT_FAILED;
1899             return NULL;
1900         }
1901
1902         /* Create a tvbuff for the plaintext. This might result in a zero-length tvbuff. */
1903         ptext_tvb = tvb_new_subset(tvb, offset, captured_len, reported_len);
1904         *status = DECRYPT_PACKET_SUCCEEDED;
1905     }
1906
1907     /*=====================================================
1908      * CCM* - CBC-mode message authentication
1909      *=====================================================
1910      */
1911     /* We can only verify the message if the MIC wasn't truncated. */
1912     if (have_mic) {
1913         unsigned char           dec_mic[16];
1914         guint                   l_m = captured_len;
1915         guint                   l_a = offset;
1916
1917         /* Adjust the lengths of the plantext and additional data if unencrypted. */
1918         if (!IEEE802154_IS_ENCRYPTED(packet->security_level)) {
1919             l_a += l_m;
1920             l_m = 0;
1921         }
1922         else if ((packet->version == IEEE802154_VERSION_2003) && !ieee802154_extend_auth)
1923             l_a -= 5;   /* Exclude Frame Counter (4 bytes) and Key Sequence Counter (1 byte) from authentication data */
1924
1925
1926         /* Create the CCM* initial block for authentication (Adata!=0, M!=0, counter=l(m)). */
1927         ccm_init_block(tmp, TRUE, M, srcAddr, packet, l_m);
1928
1929         /* Compute CBC-MAC authentication tag. */
1930         /*
1931          * And yes, despite the warning in tvbuff.h, I think tvb_get_ptr is the
1932          * right function here since either A) the payload wasn't encrypted, in
1933          * which case l_m is zero, or B) the payload was encrypted, and the tvb
1934          * already points to contiguous memory, since we just allocated it in
1935          * decryption phase.
1936          */
1937         if (!ccm_cbc_mac(key, tmp, (const gchar *)tvb_memdup(wmem_packet_scope(), tvb, 0, l_a), l_a, tvb_get_ptr(ptext_tvb, 0, l_m), l_m, dec_mic)) {
1938             *status = DECRYPT_PACKET_MIC_CHECK_FAILED;
1939         }
1940         /* Compare the received MIC with the one we generated. */
1941         else if (memcmp(rx_mic, dec_mic, M) != 0) {
1942             *status = DECRYPT_PACKET_MIC_CHECK_FAILED;
1943         }
1944     }
1945
1946     /* Done! */
1947     return ptext_tvb;
1948 } /* dissect_ieee802154_decrypt */
1949
1950 /*FUNCTION:------------------------------------------------------
1951  *  NAME
1952  *      ccm_init_block
1953  *  DESCRIPTION
1954  *      Creates the CCM* initial block value for IEEE 802.15.4.
1955  *  PARAMETERS
1956  *      gchar *block        - Output pointer for the initial block.
1957  *      gboolean adata      - TRUE if additional auth data is present
1958  *      gint M              - CCM* parameter M.
1959  *      guint64 addr        - Source extended address.
1960  *      ieee802154_packet *packet - IEEE 802.15.4 packet information.
1961  *      guint16 ctr_val     - Value in the last L bytes of the block.
1962  *  RETURNS
1963  *      void
1964  *---------------------------------------------------------------
1965  */
1966 static void
1967 ccm_init_block(gchar *block, gboolean adata, gint M, guint64 addr, ieee802154_packet * packet, gint ctr_val)
1968 {
1969     gint                i = 0;
1970
1971     /* Flags: Reserved(0) || Adata || (M-2)/2 || (L-1) */
1972     block[i] = (0x2 - 1); /* (L-1) */
1973     if (M > 0) block[i] |= (((M-2)/2) << 3); /* (M-2)/2 */
1974     if (adata) block[i] |= (1 << 6); /* Adata */
1975     i++;
1976     /* 2003 CCM Nonce:  Source Address || Frame Counter || Key Sequence Counter */
1977     /* 2006 CCM* Nonce: Source Address || Frame Counter || Security Level */
1978     block[i++] = (guint8)((addr >> 56) & 0xff);
1979     block[i++] = (guint8)((addr >> 48) & 0xff);
1980     block[i++] = (guint8)((addr >> 40) & 0xff);
1981     block[i++] = (guint8)((addr >> 32) & 0xff);
1982     block[i++] = (guint8)((addr >> 24) & 0xff);
1983     block[i++] = (guint8)((addr >> 16) & 0xff);
1984     block[i++] = (guint8)((addr >> 8) & 0xff);
1985     block[i++] = (guint8)((addr >> 0) & 0xff);
1986     block[i++] = (guint8)((packet->frame_counter >> 24) & 0xff);
1987     block[i++] = (guint8)((packet->frame_counter >> 16) & 0xff);
1988     block[i++] = (guint8)((packet->frame_counter >> 8) & 0xff);
1989     block[i++] = (guint8)((packet->frame_counter >> 0) & 0xff);
1990     if (packet->version == IEEE802154_VERSION_2003)
1991         block[i++] = packet->key_sequence_counter;
1992     else
1993         block[i++] = packet->security_level;
1994     /* Plaintext length. */
1995     block[i++] = (guint8)((ctr_val >> 8) & 0xff);
1996     block[i] = (guint8)((ctr_val >> 0) & 0xff);
1997 } /* ccm_init_block */
1998
1999 /*FUNCTION:------------------------------------------------------
2000  *  NAME
2001  *      ccm_ctr_encrypt
2002  *  DESCRIPTION
2003  *      Performs an in-place CTR-mode encryption/decryption.
2004  *  PARAMETERS
2005  *      const gchar *key    - Encryption Key.
2006  *      const gchar *iv     - Counter initial value.
2007  *      gchar *mic          - MIC to encrypt/decrypt.
2008  *      gchar *data         - Buffer to encrypt/decrypt.
2009  *      gint length         - Length of the buffer.
2010  *  RETURNS
2011  *      gboolean            - TRUE on SUCCESS, FALSE on error.
2012  *---------------------------------------------------------------
2013  */
2014 static gboolean
2015 ccm_ctr_encrypt(const gchar *key _U_, const gchar *iv _U_, gchar *mic _U_, gchar *data _U_, gint length _U_)
2016 {
2017 #ifdef HAVE_LIBGCRYPT
2018     gcry_cipher_hd_t    cipher_hd;
2019
2020     /* Open the cipher. */
2021     if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0)) {
2022         return FALSE;
2023     }
2024
2025     /* Set the key and initial value. */
2026     if (gcry_cipher_setkey(cipher_hd, key, 16)) {
2027         gcry_cipher_close(cipher_hd);
2028         return FALSE;
2029     }
2030     if (gcry_cipher_setctr(cipher_hd, iv, 16)) {
2031         gcry_cipher_close(cipher_hd);
2032         return FALSE;
2033     }
2034
2035     /* Decrypt the MIC. */
2036     if (gcry_cipher_encrypt(cipher_hd, mic, 16, NULL, 0)) {
2037         gcry_cipher_close(cipher_hd);
2038         return FALSE;
2039     }
2040     /* Decrypt the payload. */
2041     if (gcry_cipher_encrypt(cipher_hd, data, length, NULL, 0)) {
2042         gcry_cipher_close(cipher_hd);
2043         return FALSE;
2044     }
2045
2046     /* Done with the cipher. */
2047     gcry_cipher_close(cipher_hd);
2048     return TRUE;
2049 #else
2050     return FALSE;
2051 #endif
2052 } /* ccm_ctr_encrypt */
2053
2054 /*FUNCTION:------------------------------------------------------
2055  *  NAME
2056  *      ccm_cbc_mac
2057  *  DESCRIPTION
2058  *      Generates a CBC-MAC of the decrypted payload and additional
2059  *      authentication headers.
2060  *  PARAMETERS
2061  *      const gchar key     - Encryption Key.
2062  *      const gchar iv      - Counter initial value.
2063  *      const gchar a       - Additional auth headers.
2064  *      gint a_len                  - Length of the additional headers.
2065  *      const gchar m       - Plaintext message.
2066  *      gint m_len                  - Length of plaintext message.
2067  *      gchar *mic          - Output for CBC-MAC.
2068  *  RETURNS
2069  *      gboolean            - TRUE on SUCCESS, FALSE on error.
2070  *---------------------------------------------------------------
2071  */
2072 static gboolean
2073 ccm_cbc_mac(const gchar *key _U_, const gchar *iv _U_, const gchar *a _U_, gint a_len _U_, const gchar *m _U_, gint m_len _U_, gchar *mic _U_)
2074 {
2075 #ifdef HAVE_LIBGCRYPT
2076     gcry_cipher_hd_t cipher_hd;
2077     guint            i = 0;
2078     unsigned char    block[16];
2079
2080     /* Open the cipher. */
2081     if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_MAC)) return FALSE;
2082
2083     /* Set the key. */
2084     if (gcry_cipher_setkey(cipher_hd, key, 16)) {
2085         gcry_cipher_close(cipher_hd);
2086         return FALSE;
2087     }
2088
2089     /* Process the initial value. */
2090     if (gcry_cipher_encrypt(cipher_hd, mic, 16, iv, 16)) {
2091         gcry_cipher_close(cipher_hd);
2092         return FALSE;
2093     }
2094
2095     /* Encode L(a) */
2096     i = 0;
2097 #if (GINT_MAX >= (1LL << 32))
2098     if (a_len >= (1LL << 32)) {
2099         block[i++] = 0xff;
2100         block[i++] = 0xff;
2101         block[i++] = (a_len >> 56) & 0xff;
2102         block[i++] = (a_len >> 48) & 0xff;
2103         block[i++] = (a_len >> 40) & 0xff;
2104         block[i++] = (a_len >> 32) & 0xff;
2105         block[i++] = (a_len >> 24) & 0xff;
2106         block[i++] = (a_len >> 16) & 0xff;
2107         block[i++] = (a_len >> 8) & 0xff;
2108         block[i++] = (a_len >> 0) & 0xff;
2109     }
2110     else
2111 #endif
2112     if (a_len >= ((1 << 16) - (1 << 8))) {
2113         block[i++] = 0xff;
2114         block[i++] = 0xfe;
2115         block[i++] = (a_len >> 24) & 0xff;
2116         block[i++] = (a_len >> 16) & 0xff;
2117         block[i++] = (a_len >> 8) & 0xff;
2118         block[i++] = (a_len >> 0) & 0xff;
2119     }
2120     else {
2121         block[i++] = (a_len >> 8) & 0xff;
2122         block[i++] = (a_len >> 0) & 0xff;
2123     }
2124     /* Append a to get the first block of input (pad if we encounter the end of a). */
2125     while ((i < sizeof(block)) && (a_len-- > 0)) block[i++] = *a++;
2126     while (i < sizeof(block)) block[i++] = 0;
2127
2128     /* Process the first block of AuthData. */
2129     if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, 16)) {
2130         gcry_cipher_close(cipher_hd);
2131         return FALSE;
2132     }
2133
2134     /* Transform and process the remainder of a. */
2135     while (a_len > 0) {
2136         /* Copy and pad. */
2137         if ((guint)a_len >= sizeof(block)) memcpy(block, a, sizeof(block));
2138         else {memcpy(block, a, a_len); memset(block+a_len, 0, sizeof(block)-a_len);}
2139         /* Adjust pointers. */
2140         a += sizeof(block);
2141         a_len -= (int)sizeof(block);
2142         /* Execute the CBC-MAC algorithm. */
2143         if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, sizeof(block))) {
2144             gcry_cipher_close(cipher_hd);
2145             return FALSE;
2146         }
2147     } /* while */
2148
2149     /* Process the message, m. */
2150     while (m_len > 0) {
2151         /* Copy and pad. */
2152         if ((guint)m_len >= sizeof(block)) memcpy(block, m, sizeof(block));
2153         else {memcpy(block, m, m_len); memset(block+m_len, 0, sizeof(block)-m_len);}
2154         /* Adjust pointers. */
2155         m += sizeof(block);
2156         m_len -= (int)sizeof(block);
2157         /* Execute the CBC-MAC algorithm. */
2158         if (gcry_cipher_encrypt(cipher_hd, mic, 16, block, sizeof(block))) {
2159             gcry_cipher_close(cipher_hd);
2160             return FALSE;
2161         }
2162     }
2163
2164     /* Done with the cipher. */
2165     gcry_cipher_close(cipher_hd);
2166     return TRUE;
2167 #else
2168     return FALSE;
2169 #endif
2170 } /* ccm_cbc_mac */
2171
2172 /* Key hash function. */
2173 guint ieee802154_short_addr_hash(gconstpointer key)
2174 {
2175     return (((ieee802154_short_addr *)key)->addr) | (((ieee802154_short_addr *)key)->pan << 16);
2176 }
2177
2178 /* Key equal function. */
2179 gboolean ieee802154_short_addr_equal(gconstpointer a, gconstpointer b)
2180 {
2181     return (((ieee802154_short_addr *)a)->pan == ((ieee802154_short_addr *)b)->pan) &&
2182            (((ieee802154_short_addr *)a)->addr == ((ieee802154_short_addr *)b)->addr);
2183 }
2184
2185 /* Key hash function. */
2186 guint ieee802154_long_addr_hash(gconstpointer key)
2187 {
2188     return (guint)(((ieee802154_long_addr *)key)->addr) & 0xFFFFFFFF;
2189 }
2190
2191 /* Key equal function. */
2192 gboolean ieee802154_long_addr_equal(gconstpointer a, gconstpointer b)
2193 {
2194     return (((ieee802154_long_addr *)a)->addr == ((ieee802154_long_addr *)b)->addr);
2195 }
2196
2197 /*FUNCTION:------------------------------------------------------
2198  *  NAME
2199  *      ieee802154_addr_update
2200  *  DESCRIPTION
2201  *      Creates a record that maps the given short address and pan
2202  *      to a long (extended) address.
2203  *  PARAMETERS
2204  *      guint16 short_addr  - 16-bit short address
2205  *      guint16 pan         - 16-bit PAN id
2206  *      guint64 long_addr   - 64-bit long (extended) address
2207  *      const char *        - Pointer to name of current protocol
2208  *      guint               - Frame number this mapping became valid
2209  *  RETURNS
2210  *      TRUE                - Record was updated
2211  *      FALSE               - Couldn't find it
2212  *---------------------------------------------------------------
2213  */
2214 ieee802154_map_rec *ieee802154_addr_update(ieee802154_map_tab_t *au_ieee802154_map,
2215         guint16 short_addr, guint16 pan, guint64 long_addr, const char *proto, guint fnum)
2216 {
2217     ieee802154_short_addr  addr16;
2218     ieee802154_map_rec    *p_map_rec;
2219     gpointer               old_key;
2220
2221     /* Look up short address hash */
2222     addr16.pan = pan;
2223     addr16.addr = short_addr;
2224     p_map_rec = (ieee802154_map_rec *)g_hash_table_lookup(au_ieee802154_map->short_table, &addr16);
2225
2226     /* Update mapping record */
2227     if (p_map_rec) {
2228         /* record already exists */
2229         if ( p_map_rec->addr64 == long_addr ) {
2230             /* no change */
2231             return p_map_rec;
2232         }
2233         else {
2234             /* mark current mapping record invalid */
2235             p_map_rec->end_fnum = fnum;
2236         }
2237     }
2238
2239     /* create a new mapping record */
2240     p_map_rec = wmem_new(wmem_file_scope(), ieee802154_map_rec);
2241     p_map_rec->proto = proto;
2242     p_map_rec->start_fnum = fnum;
2243     p_map_rec->end_fnum = 0;
2244     p_map_rec->addr64 = long_addr;
2245
2246     /* link new mapping record to addr hash tables */
2247     if ( g_hash_table_lookup_extended(au_ieee802154_map->short_table, &addr16, &old_key, NULL) ) {
2248         /* update short addr hash table, reusing pointer to old key */
2249         g_hash_table_insert(au_ieee802154_map->short_table, old_key, p_map_rec);
2250     } else {
2251         /* create new hash entry */
2252         g_hash_table_insert(au_ieee802154_map->short_table, wmem_memdup(wmem_file_scope(), &addr16, sizeof(addr16)), p_map_rec);
2253     }
2254
2255     if ( g_hash_table_lookup_extended(au_ieee802154_map->long_table, &long_addr, &old_key, NULL) ) {
2256         /* update long addr hash table, reusing pointer to old key */
2257         g_hash_table_insert(au_ieee802154_map->long_table, old_key, p_map_rec);
2258     } else {
2259         /* create new hash entry */
2260         g_hash_table_insert(au_ieee802154_map->long_table, wmem_memdup(wmem_file_scope(), &long_addr, sizeof(long_addr)), p_map_rec);
2261     }
2262
2263     return p_map_rec;
2264 } /* ieee802154_addr_update */
2265
2266 /*FUNCTION:------------------------------------------------------
2267  *  NAME
2268  *      ieee802154_short_addr_invalidate
2269  *  DESCRIPTION
2270  *      Marks a mapping record associated with device with short_addr
2271  *      as invalid at a certain frame number, typically when a
2272  *      dissassociation occurs.
2273  *  PARAMETERS
2274  *      guint16 short_addr  - 16-bit short address
2275  *      guint16 pan         - 16-bit PAN id
2276  *      guint               - Frame number when mapping became invalid
2277  *  RETURNS
2278  *      TRUE                - Record was updated
2279  *      FALSE               - Couldn't find it
2280  *---------------------------------------------------------------
2281  */
2282 gboolean ieee802154_short_addr_invalidate(guint16 short_addr, guint16 pan, guint fnum)
2283 {
2284     ieee802154_short_addr  addr16;
2285     ieee802154_map_rec    *map_rec;
2286
2287     addr16.pan = pan;
2288     addr16.addr = short_addr;
2289
2290     map_rec = (ieee802154_map_rec *)g_hash_table_lookup(ieee802154_map.short_table, &addr16);
2291     if ( map_rec ) {
2292         /* indicates this mapping is invalid at frame fnum */
2293         map_rec->end_fnum = fnum;
2294         return TRUE;
2295     }
2296
2297     return FALSE;
2298 } /* ieee802154_short_addr_invalidate */
2299
2300 /*FUNCTION:------------------------------------------------------
2301  *  NAME
2302  *      ieee802154_long_addr_invalidate
2303  *  DESCRIPTION
2304  *      Marks a mapping record associated with device with long_addr
2305  *      as invalid at a certain frame number, typically when a
2306  *      dissassociation occurs.
2307  *  PARAMETERS
2308  *      guint64 long_addr   - 16-bit short address
2309  *      guint               - Frame number when mapping became invalid
2310  *  RETURNS
2311  *      TRUE                - If record was updated
2312  *      FALSE               - If record wasn't updated
2313  *---------------------------------------------------------------
2314  */
2315 gboolean ieee802154_long_addr_invalidate(guint64 long_addr, guint fnum)
2316 {
2317     ieee802154_map_rec   *map_rec;
2318
2319     map_rec = (ieee802154_map_rec *)g_hash_table_lookup(ieee802154_map.long_table, &long_addr);
2320     if ( map_rec ) {
2321         /* indicates this mapping is invalid at frame fnum */
2322         map_rec->end_fnum = fnum;
2323         return TRUE;
2324     }
2325
2326     return FALSE;
2327 } /* ieee802154_long_addr_invalidate */
2328
2329
2330 /*FUNCTION:------------------------------------------------------
2331  *  NAME
2332  *      proto_init_ieee802154
2333  *  DESCRIPTION
2334  *      Init routine for the IEEE 802.15.4 dissector. Creates hash
2335  *      tables for mapping between 16-bit to 64-bit addresses and
2336  *      populates them with static address pairs from a UAT
2337  *      preference table.
2338  *  PARAMETERS
2339  *      none
2340  *  RETURNS
2341  *      void
2342  *---------------------------------------------------------------
2343  */
2344 static void
2345 proto_init_ieee802154(void)
2346 {
2347     guint       i;
2348
2349     /* Destroy hash tables, if they exist. */
2350     if (ieee802154_map.short_table)
2351         g_hash_table_destroy(ieee802154_map.short_table);
2352     if (ieee802154_map.long_table)
2353         g_hash_table_destroy(ieee802154_map.long_table);
2354
2355     /* Create the hash tables. */
2356     ieee802154_map.short_table = g_hash_table_new(ieee802154_short_addr_hash, ieee802154_short_addr_equal);
2357     ieee802154_map.long_table = g_hash_table_new(ieee802154_long_addr_hash, ieee802154_long_addr_equal);
2358     /* Re-load the hash table from the static address UAT. */
2359     for (i=0; (i<num_static_addrs) && (static_addrs); i++) {
2360         ieee802154_addr_update(&ieee802154_map,(guint16)static_addrs[i].addr16, (guint16)static_addrs[i].pan,
2361                pntoh64(static_addrs[i].eui64), ieee802154_user, IEEE802154_USER_MAPPING);
2362     } /* for */
2363 } /* proto_init_ieee802154 */
2364
2365
2366 /*FUNCTION:------------------------------------------------------
2367  *  NAME
2368  *      proto_register_ieee802154
2369  *  DESCRIPTION
2370  *      IEEE 802.15.4 protocol registration routine.
2371  *  PARAMETERS
2372  *      none
2373  *  RETURNS
2374  *      void
2375  *---------------------------------------------------------------
2376  */
2377 void proto_register_ieee802154(void)
2378 {
2379     /* Protocol fields  */
2380     static hf_register_info hf_phy[] = {
2381         /* PHY level */
2382
2383         { &hf_ieee802154_nonask_phy_preamble,
2384         { "Preamble",                       "wpan-nonask-phy.preamble", FT_UINT32, BASE_HEX, NULL, 0x0,
2385             NULL, HFILL }},
2386
2387         { &hf_ieee802154_nonask_phy_sfd,
2388         { "Start of Frame Delimiter",       "wpan-nonask-phy.sfd", FT_UINT8, BASE_HEX, NULL, 0x0,
2389             NULL, HFILL }},
2390
2391         { &hf_ieee802154_nonask_phy_length,
2392         { "Frame Length",                   "wpan-nonask-phy.frame_length", FT_UINT8, BASE_HEX, NULL,
2393             IEEE802154_PHY_LENGTH_MASK, NULL, HFILL }},
2394     };
2395
2396     static hf_register_info hf[] = {
2397
2398         { &hf_ieee802154_frame_length,
2399         { "Frame Length",                   "wpan.frame_length", FT_UINT8, BASE_DEC, NULL, 0x0,
2400             "Frame Length as reported from lower layer", HFILL }},
2401
2402         { &hf_ieee802154_frame_type,
2403         { "Frame Type",                     "wpan.frame_type", FT_UINT16, BASE_HEX, VALS(ieee802154_frame_types),
2404             IEEE802154_FCF_TYPE_MASK, NULL, HFILL }},
2405
2406         { &hf_ieee802154_security,
2407         { "Security Enabled",               "wpan.security", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_SEC_EN,
2408             "Whether security operations are performed at the MAC layer or not.", HFILL }},
2409
2410         { &hf_ieee802154_pending,
2411         { "Frame Pending",                  "wpan.pending", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_FRAME_PND,
2412             "Indication of additional packets waiting to be transferred from the source device.", HFILL }},
2413
2414         { &hf_ieee802154_ack_request,
2415         { "Acknowledge Request",            "wpan.ack_request", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_ACK_REQ,
2416             "Whether the sender of this packet requests acknowledgement or not.", HFILL }},
2417
2418         { &hf_ieee802154_intra_pan,
2419         { "Intra-PAN",                      "wpan.intra_pan", FT_BOOLEAN, 16, NULL, IEEE802154_FCF_INTRA_PAN,
2420             "Whether this packet originated and terminated within the same PAN or not.", HFILL }},
2421
2422         { &hf_ieee802154_seqno,
2423         { "Sequence Number",                "wpan.seq_no", FT_UINT8, BASE_DEC, NULL, 0x0,
2424             NULL, HFILL }},
2425
2426         { &hf_ieee802154_dst_addr_mode,
2427         { "Destination Addressing Mode",    "wpan.dst_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
2428             IEEE802154_FCF_DADDR_MASK, NULL, HFILL }},
2429
2430         { &hf_ieee802154_src_addr_mode,
2431         { "Source Addressing Mode",         "wpan.src_addr_mode", FT_UINT16, BASE_HEX, VALS(ieee802154_addr_modes),
2432             IEEE802154_FCF_SADDR_MASK, NULL, HFILL }},
2433
2434         { &hf_ieee802154_version,
2435         { "Frame Version",                  "wpan.version", FT_UINT16, BASE_DEC, NULL, IEEE802154_FCF_VERSION,
2436             NULL, HFILL }},
2437
2438         { &hf_ieee802154_dst_panID,
2439         { "Destination PAN",                "wpan.dst_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
2440             NULL, HFILL }},
2441
2442         { &hf_ieee802154_dst16,
2443         { "Destination",                    "wpan.dst16", FT_UINT16, BASE_HEX, NULL, 0x0,
2444             NULL, HFILL }},
2445
2446         { &hf_ieee802154_dst64,
2447         { "Destination",                    "wpan.dst64", FT_EUI64, BASE_NONE, NULL, 0x0,
2448             NULL, HFILL }},
2449
2450         { &hf_ieee802154_src_panID,
2451         { "Source PAN",                     "wpan.src_pan", FT_UINT16, BASE_HEX, NULL, 0x0,
2452             NULL, HFILL }},
2453
2454         { &hf_ieee802154_src16,
2455         { "Source",                         "wpan.src16", FT_UINT16, BASE_HEX, NULL, 0x0,
2456             NULL, HFILL }},
2457
2458         { &hf_ieee802154_src64,
2459         { "Extended Source",                "wpan.src64", FT_EUI64, BASE_NONE, NULL, 0x0,
2460             NULL, HFILL }},
2461
2462         { &hf_ieee802154_src64_origin,
2463         { "Origin",                           "wpan.src64.origin", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2464             NULL, HFILL }},
2465
2466         { &hf_ieee802154_fcs,
2467         { "FCS",                            "wpan.fcs", FT_UINT16, BASE_HEX, NULL, 0x0,
2468             NULL, HFILL }},
2469
2470         { &hf_ieee802154_rssi,
2471         { "RSSI",                           "wpan.rssi", FT_INT8, BASE_DEC, NULL, 0x0,
2472             "Received Signal Strength", HFILL }},
2473
2474         { &hf_ieee802154_fcs_ok,
2475         { "FCS Valid",                      "wpan.fcs_ok", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2476             NULL, HFILL }},
2477
2478         { &hf_ieee802154_correlation,
2479         { "LQI Correlation Value",          "wpan.correlation", FT_UINT8, BASE_DEC, NULL, 0x0,
2480             NULL, HFILL }},
2481
2482             /*  Command Frame Specific Fields */
2483             /*--------------------------------*/
2484
2485         { &hf_ieee802154_cmd_id,
2486         { "Command Identifier",         "wpan.cmd", FT_UINT8, BASE_HEX, VALS(ieee802154_cmd_names), 0x0,
2487             NULL, HFILL }},
2488
2489             /*  Capability Information Fields */
2490         { &hf_ieee802154_cinfo_alt_coord,
2491         { "Alternate PAN Coordinator",  "wpan.cinfo.alt_coord", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALT_PAN_COORD,
2492             "Whether this device can act as a PAN coordinator or not.", HFILL }},
2493
2494         { &hf_ieee802154_cinfo_device_type,
2495         { "Device Type",                "wpan.cinfo.device_type", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_DEVICE_TYPE,
2496             "Whether this device is RFD (reduced-function device) or FFD (full-function device).", HFILL }},
2497
2498         { &hf_ieee802154_cinfo_power_src,
2499         { "Power Source",               "wpan.cinfo.power_src", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_POWER_SRC,
2500             "Whether this device is operating on AC/mains or battery power.", HFILL }},
2501
2502         { &hf_ieee802154_cinfo_idle_rx,
2503         { "Receive On When Idle",       "wpan.cinfo.idle_rx", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_IDLE_RX,
2504             "Whether this device can receive packets while idle or not.", HFILL }},
2505
2506         { &hf_ieee802154_cinfo_sec_capable,
2507         { "Security Capability",        "wpan.cinfo.sec_capable", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_SEC_CAPABLE,
2508             "Whether this device is capable of receiving encrypted packets.", HFILL }},
2509
2510         { &hf_ieee802154_cinfo_alloc_addr,
2511         { "Allocate Address",           "wpan.cinfo.alloc_addr", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_CINFO_ALLOC_ADDR,
2512             "Whether this device wishes to use a 16-bit short address instead of its IEEE 802.15.4 64-bit long address.", HFILL }},
2513
2514             /*  Association response fields */
2515         { &hf_ieee802154_assoc_addr,
2516         { "Short Address",              "wpan.asoc.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
2517             "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 }},
2518
2519         { &hf_ieee802154_assoc_status,
2520         { "Association Status",         "wpan.assoc.status", FT_UINT8, BASE_HEX, NULL, 0x0,
2521             NULL, HFILL }},
2522
2523         { &hf_ieee802154_disassoc_reason,
2524         { "Disassociation Reason",      "wpan.disassoc.reason", FT_UINT8, BASE_HEX, NULL, 0x0,
2525             NULL, HFILL }},
2526
2527             /*  Coordinator Realignment fields */
2528         { &hf_ieee802154_realign_pan,
2529         { "PAN ID",                     "wpan.realign.pan", FT_UINT16, BASE_HEX, NULL, 0x0,
2530             "The PAN identifier the coordinator wishes to use for future communication.", HFILL }},
2531
2532         { &hf_ieee802154_realign_caddr,
2533         { "Coordinator Short Address",  "wpan.realign.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
2534             "The 16-bit address the coordinator wishes to use for future communication.", HFILL }},
2535
2536         { &hf_ieee802154_realign_channel,
2537         { "Logical Channel",            "wpan.realign.channel", FT_UINT8, BASE_DEC, NULL, 0x0,
2538             "The logical channel the coordinator wishes to use for future communication.", HFILL }},
2539
2540         { &hf_ieee802154_realign_addr,
2541         { "Short Address",              "wpan.realign.addr", FT_UINT16, BASE_HEX, NULL, 0x0,
2542             "A short-address that the orphaned device shall assume if applicable.", HFILL }},
2543
2544         { &hf_ieee802154_realign_channel_page,
2545         { "Channel Page",               "wpan.realign.channel_page", FT_UINT8, BASE_DEC, NULL, 0x0,
2546             "The logical channel page the coordinator wishes to use for future communication.", HFILL }},
2547
2548         { &hf_ieee802154_gtsreq_len,
2549         { "GTS Length",                 "wpan.gtsreq.length", FT_UINT8, BASE_DEC, NULL, IEEE802154_CMD_GTS_REQ_LEN,
2550             "Number of superframe slots the device is requesting.", HFILL }},
2551
2552         { &hf_ieee802154_gtsreq_dir,
2553         { "GTS Direction",              "wpan.gtsreq.direction", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_GTS_REQ_DIR,
2554             "The direction of traffic in the guaranteed timeslot.", HFILL }},
2555
2556         { &hf_ieee802154_gtsreq_type,
2557         { "Characteristic Type",        "wpan.gtsreq.type", FT_BOOLEAN, 8, NULL, IEEE802154_CMD_GTS_REQ_TYPE,
2558             "Whether this request is to allocate or deallocate a timeslot.", HFILL }},
2559
2560             /*  Beacon Frame Specific Fields */
2561             /*-------------------------------*/
2562         { &hf_ieee802154_beacon_order,
2563         { "Beacon Interval",            "wpan.beacon_order", FT_UINT16, BASE_DEC, NULL, IEEE802154_BEACON_ORDER_MASK,
2564             "Specifies the transmission interval of the beacons.", HFILL }},
2565
2566         { &hf_ieee802154_superframe_order,
2567         { "Superframe Interval",        "wpan.superframe_order", FT_UINT16, BASE_DEC, NULL,
2568             IEEE802154_SUPERFRAME_ORDER_MASK,
2569             "Specifies the length of time the coordinator will interact with the PAN.", HFILL }},
2570
2571         { &hf_ieee802154_cap,
2572         { "Final CAP Slot",             "wpan.cap", FT_UINT16, BASE_DEC, NULL, IEEE802154_SUPERFRAME_CAP_MASK,
2573             "Specifies the final superframe slot used by the CAP.", HFILL }},
2574
2575         { &hf_ieee802154_superframe_battery_ext,
2576         { "Battery Extension",          "wpan.battery_ext", FT_BOOLEAN, 16, NULL, IEEE802154_BATT_EXTENSION_MASK,
2577             "Whether transmissions may not extend past the length of the beacon frame.", HFILL }},
2578
2579         { &hf_ieee802154_superframe_coord,
2580         { "PAN Coordinator",            "wpan.bcn_coord", FT_BOOLEAN, 16, NULL, IEEE802154_SUPERFRAME_COORD_MASK,
2581             "Whether this beacon frame is being transmitted by the PAN coordinator or not.", HFILL }},
2582
2583         { &hf_ieee802154_assoc_permit,
2584         { "Association Permit",         "wpan.assoc_permit", FT_BOOLEAN, 16, NULL, IEEE802154_ASSOC_PERMIT_MASK,
2585             "Whether this PAN is accepting association requests or not.", HFILL }},
2586
2587         { &hf_ieee802154_gts_count,
2588         { "GTS Descriptor Count",       "wpan.gts.count", FT_UINT8, BASE_DEC, NULL, 0x0,
2589             "The number of GTS descriptors present in this beacon frame.", HFILL }},
2590
2591         { &hf_ieee802154_gts_permit,
2592         { "GTS Permit",                 "wpan.gts.permit", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2593             "Whether the PAN coordinator is accepting GTS requests or not.", HFILL }},
2594
2595         { &hf_ieee802154_gts_direction,
2596         { "Direction",                  "wpan.gts.direction", FT_BOOLEAN, BASE_NONE, TFS(&ieee802154_gts_direction_tfs), 0x0,
2597             "A flag defining the direction of the GTS Slot.", HFILL }},
2598
2599         { &hf_ieee802154_pending16,
2600         { "Address",                    "wpan.pending16", FT_UINT16, BASE_HEX, NULL, 0x0,
2601             "Device with pending data to receive.", HFILL }},
2602
2603         { &hf_ieee802154_pending64,
2604         { "Address",                    "wpan.pending64", FT_EUI64, BASE_NONE, NULL, 0x0,
2605             "Device with pending data to receive.", HFILL }},
2606
2607             /* Auxiliary Security Header Fields */
2608             /*----------------------------------*/
2609         { &hf_ieee802154_security_level,
2610         { "Security Level", "wpan.aux_sec.sec_level", FT_UINT8, BASE_HEX, VALS(ieee802154_sec_level_names),
2611             IEEE802154_AUX_SEC_LEVEL_MASK, "The Security Level of the frame", HFILL }},
2612
2613         { &hf_ieee802154_key_id_mode,
2614         { "Key Identifier Mode", "wpan.aux_sec.key_id_mode", FT_UINT8, BASE_HEX, VALS(ieee802154_key_id_mode_names),
2615             IEEE802154_AUX_KEY_ID_MODE_MASK,
2616             "The scheme to use by the recipient to lookup the key in its key table", HFILL }},
2617
2618         { &hf_ieee802154_aux_sec_reserved,
2619         { "Reserved", "wpan.aux_sec.reserved", FT_UINT8, BASE_HEX, NULL, IEEE802154_AUX_KEY_RESERVED_MASK,
2620             NULL, HFILL }},
2621
2622         { &hf_ieee802154_aux_sec_frame_counter,
2623         { "Frame Counter", "wpan.aux_sec.frame_counter", FT_UINT32, BASE_DEC, NULL, 0x0,
2624             "Frame counter of the originator of the protected frame", HFILL }},
2625
2626         { &hf_ieee802154_aux_sec_key_source,
2627         { "Key Source", "wpan.aux_sec.key_source", FT_UINT64, BASE_HEX, NULL, 0x0,
2628             "Key Source for processing of the protected frame", HFILL }},
2629
2630         { &hf_ieee802154_aux_sec_key_index,
2631         { "Key Index", "wpan.aux_sec.key_index", FT_UINT8, BASE_HEX, NULL, 0x0,
2632             "Key Index for processing of the protected frame", HFILL }},
2633
2634             /* IEEE 802.15.4-2003 Security Header Fields */
2635         { &hf_ieee802154_sec_frame_counter,
2636         { "Frame Counter", "wpan.sec_frame_counter", FT_UINT32, BASE_HEX, NULL, 0x0,
2637             "Frame counter of the originator of the protected frame (802.15.4-2003)", HFILL }},
2638
2639         { &hf_ieee802154_sec_key_sequence_counter,
2640         { "Key Sequence Counter", "wpan.sec_key_sequence_counter", FT_UINT8, BASE_HEX, NULL, 0x0,
2641             "Key Sequence counter of the originator of the protected frame (802.15.4-2003)", HFILL }}
2642     };
2643
2644     /* Subtrees */
2645     static gint *ett[] = {
2646         &ett_ieee802154_nonask_phy,
2647         &ett_ieee802154_nonask_phy_phr,
2648         &ett_ieee802154,
2649         &ett_ieee802154_fcf,
2650         &ett_ieee802154_auxiliary_security,
2651         &ett_ieee802154_aux_sec_control,
2652         &ett_ieee802154_aux_sec_key_id,
2653         &ett_ieee802154_fcs,
2654         &ett_ieee802154_cmd,
2655         &ett_ieee802154_superframe,
2656         &ett_ieee802154_gts,
2657         &ett_ieee802154_gts_direction,
2658         &ett_ieee802154_gts_descriptors,
2659         &ett_ieee802154_pendaddr
2660     };
2661
2662     static ei_register_info ei[] = {
2663         { &ei_ieee802154_invalid_addressing, { "wpan.invalid_addressing", PI_MALFORMED, PI_WARN, "Invalid Addressing", EXPFILL }},
2664         { &ei_ieee802154_dst, { "wpan.dst_invalid", PI_MALFORMED, PI_ERROR, "Invalid Destination Address Mode", EXPFILL }},
2665         { &ei_ieee802154_src, { "wpan.src_invalid", PI_MALFORMED, PI_ERROR, "Invalid Source Address Mode", EXPFILL }},
2666         { &ei_ieee802154_decrypt_error, { "wpan.decrypt_error", PI_UNDECODED, PI_WARN, "Decryption error", EXPFILL }},
2667         { &ei_ieee802154_fcs, { "wpan.fcs.bad", PI_CHECKSUM, PI_WARN, "Bad FCS", EXPFILL }},
2668     };
2669
2670     /* Preferences. */
2671     module_t *ieee802154_module;
2672     expert_module_t* expert_ieee802154;
2673
2674     static uat_field_t addr_uat_flds[] = {
2675         UAT_FLD_HEX(addr_uat,addr16,"Short Address",
2676                 "16-bit short address in hexadecimal."),
2677         UAT_FLD_HEX(addr_uat,pan,"PAN Identifier",
2678                 "16-bit PAN identifier in hexadecimal."),
2679         UAT_FLD_BUFFER(addr_uat,eui64,"EUI-64",
2680                 "64-bit extended unique identifier."),
2681         UAT_END_FIELDS
2682     };
2683
2684     /* Register the init routine. */
2685     register_init_routine(proto_init_ieee802154);
2686
2687     /*  Register Protocol name and description. */
2688     proto_ieee802154 = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN", "IEEE 802.15.4",
2689            IEEE802154_PROTOABBREV_WPAN);
2690     proto_ieee802154_nonask_phy = proto_register_protocol("IEEE 802.15.4 Low-Rate Wireless PAN non-ASK PHY",
2691             "IEEE 802.15.4 non-ASK PHY", "wpan-nonask-phy");
2692
2693     /*  Register header fields and subtrees. */
2694     proto_register_field_array(proto_ieee802154, hf, array_length(hf));
2695     proto_register_field_array(proto_ieee802154, hf_phy, array_length(hf_phy));
2696
2697     proto_register_subtree_array(ett, array_length(ett));
2698
2699     expert_ieee802154 = expert_register_protocol(proto_ieee802154);
2700     expert_register_field_array(expert_ieee802154, ei, array_length(ei));
2701
2702     /* add a user preference to set the 802.15.4 ethertype */
2703     ieee802154_module = prefs_register_protocol(proto_ieee802154,
2704                                    proto_reg_handoff_ieee802154);
2705     prefs_register_uint_preference(ieee802154_module, "802154_ethertype",
2706                                    "802.15.4 Ethertype (in hex)",
2707                                    "(Hexadecimal) Ethertype used to indicate IEEE 802.15.4 frame.",
2708                                    16, &ieee802154_ethertype);
2709     prefs_register_bool_preference(ieee802154_module, "802154_cc24xx",
2710                                    "TI CC24xx FCS format",
2711                                    "Set if the FCS field is in TI CC24xx format.",
2712                                    &ieee802154_cc24xx);
2713     prefs_register_bool_preference(ieee802154_module, "802154_fcs_ok",
2714                                    "Dissect only good FCS",
2715                                    "Dissect payload only if FCS is valid.",
2716                                    &ieee802154_fcs_ok);
2717
2718     /* Create a UAT for static address mappings. */
2719     static_addr_uat = uat_new("Static Addresses",
2720             sizeof(static_addr_t),      /* record size */
2721             "802154_addresses",         /* filename */
2722             TRUE,                       /* from_profile */
2723             (void**)&static_addrs,      /* data_ptr */
2724             &num_static_addrs,          /* numitems_ptr */
2725             UAT_AFFECTS_DISSECTION,     /* affects dissection of packets, but not set of named fields */
2726             NULL,                       /* help */
2727             NULL,                       /* copy callback */
2728             addr_uat_update_cb,         /* update callback */
2729             NULL,                       /* free callback */
2730             NULL,                       /* post update callback */
2731             addr_uat_flds);             /* UAT field definitions */
2732     prefs_register_uat_preference(ieee802154_module, "static_addr",
2733                 "Static Addresses",
2734                 "A table of static address mappings between 16-bit short addressing and EUI-64 addresses",
2735                 static_addr_uat);
2736
2737     /* Register preferences for a decryption key */
2738     /* TODO: Implement a UAT for multiple keys, and with more advanced key management. */
2739     prefs_register_string_preference(ieee802154_module, "802154_key", "Decryption key",
2740             "128-bit decryption key in hexadecimal format", (const char **)&ieee802154_key_str);
2741
2742     prefs_register_enum_preference(ieee802154_module, "802154_sec_suite",
2743                                    "Security Suite (802.15.4-2003)",
2744                                    "Specifies the security suite to use for 802.15.4-2003 secured frames"
2745                                    " (only supported suites are listed). Option ignored for 802.15.4-2006"
2746                                    " and unsecured frames.",
2747                                    &ieee802154_sec_suite, ieee802154_2003_sec_suite_enums, FALSE);
2748
2749     prefs_register_bool_preference(ieee802154_module, "802154_extend_auth",
2750                                    "Extend authentication data (802.15.4-2003)",
2751                                    "Set if the manufacturer extends the authentication data with the"
2752                                    " security header. Option ignored for 802.15.4-2006 and unsecured frames.",
2753                                    &ieee802154_extend_auth);
2754
2755     /* Register the subdissector list */
2756     register_heur_dissector_list(IEEE802154_PROTOABBREV_WPAN, &ieee802154_heur_subdissector_list);
2757
2758     /*  Register dissectors with Wireshark. */
2759     register_dissector(IEEE802154_PROTOABBREV_WPAN, dissect_ieee802154, proto_ieee802154);
2760     register_dissector("wpan_nofcs", dissect_ieee802154_nofcs, proto_ieee802154);
2761     register_dissector("wpan_cc24xx", dissect_ieee802154_cc24xx, proto_ieee802154);
2762     register_dissector("wpan-nonask-phy", dissect_ieee802154_nonask_phy, proto_ieee802154_nonask_phy);
2763 } /* proto_register_ieee802154 */
2764
2765
2766 /*FUNCTION:------------------------------------------------------
2767  *  NAME
2768  *      proto_reg_handoff_ieee802154
2769  *  DESCRIPTION
2770  *      Registers the IEEE 802.15.4 dissector with Wireshark.
2771  *      Will be called every time 'apply' is pressed in the preferences menu.
2772  *       as well as during Wireshark initialization
2773  *  PARAMETERS
2774  *      none
2775  *  RETURNS
2776  *      void
2777  *---------------------------------------------------------------
2778  */
2779 void proto_reg_handoff_ieee802154(void)
2780 {
2781     static gboolean            prefs_initialized = FALSE;
2782     static dissector_handle_t  ieee802154_handle;
2783     static dissector_handle_t  ieee802154_nonask_phy_handle;
2784     static dissector_handle_t  ieee802154_nofcs_handle;
2785     static unsigned int        old_ieee802154_ethertype;
2786     GByteArray                *bytes;
2787     gboolean                   res;
2788
2789     if (!prefs_initialized){
2790         /* Get the dissector handles. */
2791         ieee802154_handle   = find_dissector(IEEE802154_PROTOABBREV_WPAN);
2792         ieee802154_nonask_phy_handle = find_dissector("wpan-nonask-phy");
2793         ieee802154_nofcs_handle = find_dissector("wpan_nofcs");
2794         data_handle         = find_dissector("data");
2795
2796         dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4, ieee802154_handle);
2797         dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_NONASK_PHY, ieee802154_nonask_phy_handle);
2798         dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE802_15_4_NOFCS, ieee802154_nofcs_handle);
2799         dissector_add_uint("sll.ltype", LINUX_SLL_P_IEEE802154, ieee802154_handle);
2800
2801         prefs_initialized = TRUE;
2802     } else {
2803         dissector_delete_uint("ethertype", old_ieee802154_ethertype, ieee802154_handle);
2804     }
2805
2806     old_ieee802154_ethertype = ieee802154_ethertype;
2807
2808     /* Get the IEEE 802.15.4 decryption key. */
2809     bytes = g_byte_array_new();
2810     res = hex_str_to_bytes(ieee802154_key_str, bytes, FALSE);
2811     ieee802154_key_valid =  (res && bytes->len >= IEEE802154_CIPHER_SIZE);
2812     if (ieee802154_key_valid) {
2813         memcpy(ieee802154_key, bytes->data, IEEE802154_CIPHER_SIZE);
2814     }
2815     g_byte_array_free(bytes, TRUE);
2816
2817     /* Register dissector handles. */
2818     dissector_add_uint("ethertype", ieee802154_ethertype, ieee802154_handle);
2819 } /* proto_reg_handoff_ieee802154 */