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