/epan/dissectors/packet-ieee802154.c
C | 2806 lines | 1635 code | 326 blank | 845 comment | 300 complexity | d478e8a8a02678e6e8f8e4e714a3f0ec MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
Large files files are truncated, but you can click here to view the full file
- /* packet-ieee802154.c
- *
- * $Id$
- *
- * Auxiliary Security Header support and
- * option to force TI CC24xx FCS format
- * By Jean-Francois Wauthy <jfw@info.fundp.ac.be>
- * Copyright 2009 The University of Namur, Belgium
- *
- * IEEE 802.15.4 Dissectors for Wireshark
- * By Owen Kirby <osk@exegin.com>
- * Copyright 2007 Exegin Technologies Limited
- *
- * Wireshark - Network traffic analyzer
- * By Gerald Combs <gerald@wireshark.org>
- * Copyright 1998 Gerald Combs
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *------------------------------------------------------------
- *
- * In IEEE 802.15.4 packets, all fields are little endian. And
- * Each byte is transmitted least significant bit first (reflected
- * bit ordering).
- *------------------------------------------------------------
- *
- * IEEE 802.15.4 Packets have the following format:
- * | FCF |Seq No| Addressing | Data | FCS |
- * |2 bytes|1 byte|0 to 20 bytes|Length-(Overhead) bytes|2 Bytes|
- *------------------------------------------------------------
- *
- * CRC16 is calculated using the x^16 + x^12 + x^5 + 1 polynomial
- * as specified by ITU-T, and is calculated over the IEEE 802.15.4
- * packet (excluding the FCS) as transmitted over the air. Note,
- * that because the least significan bits are transmitted first, this
- * will require reversing the bit-order in each byte. Also, unlike
- * most CRC algorithms, IEEE 802.15.4 uses an initial and final value
- * of 0x0000, instead of 0xffff (which is used by the CCITT).
- *------------------------------------------------------------
- *
- * This dissector supports both link-layer IEEE 802.15.4 captures
- * and IEEE 802.15.4 packets encapsulated within other layers.
- * Additionally, support has been provided for various formats
- * of the frame check sequence:
- * - IEEE 802.15.4 compliant FCS.
- * - ChipCon/Texas Instruments CC24xx style FCS.
- *------------------------------------------------------------
- */
- /* Include files */
- #include "config.h"
- #include <string.h>
- #include <sys/stat.h>
- #include <glib.h>
- #include <epan/wmem/wmem.h>
- #include <epan/packet.h>
- #include <epan/crc16-tvb.h>
- #include <epan/expert.h>
- #include <epan/addr_resolv.h>
- #include <epan/prefs.h>
- #include <epan/uat.h>
- #include <epan/strutil.h>
- #include <epan/show_exception.h>
- /* Use libgcrypt for cipher libraries. */
- #ifdef HAVE_LIBGCRYPT
- #include <wsutil/wsgcrypt.h>
- #endif /* HAVE_LIBGCRYPT */
- #include "packet-ieee802154.h"
- #include "packet-sll.h"
- /* Dissection Options for dissect_ieee802154_common */
- #define DISSECT_IEEE802154_OPTION_CC24xx 0x00000001 /* FCS field contains a TI CC24xx style FCS. */
- #define DISSECT_IEEE802154_OPTION_LINUX 0x00000002 /* Addressing fields are padded DLT_IEEE802_15_4_LINUX, not implemented. */
- /* ethertype for 802.15.4 tag - encapsulating an Ethernet packet */
- static unsigned int ieee802154_ethertype = 0x809A;
- /* boolean value set if the FCS field is using the TI CC24xx format */
- static gboolean ieee802154_cc24xx = FALSE;
- /* boolean value set if the FCS must be ok before payload is dissected */
- static gboolean ieee802154_fcs_ok = TRUE;
- /* User string with the decryption key. */
- static const gchar *ieee802154_key_str = NULL;
- static gboolean ieee802154_key_valid;
- static guint8 ieee802154_key[IEEE802154_CIPHER_SIZE];
- static const char *ieee802154_user = "User";
- /*-------------------------------------
- * Address Hash Tables
- *-------------------------------------
- */
- static ieee802154_map_tab_t ieee802154_map = { NULL, NULL };
- /*-------------------------------------
- * Static Address Mapping UAT
- *-------------------------------------
- */
- /* UAT entry structure. */
- typedef struct {
- guchar *eui64;
- guint eui64_len;
- guint addr16;
- guint pan;
- } static_addr_t;
- /* UAT variables */
- static uat_t *static_addr_uat = NULL;
- static static_addr_t *static_addrs = NULL;
- static guint num_static_addrs = 0;
- /* Sanity-checks a UAT record. */
- static void
- addr_uat_update_cb(void *r, const char **err)
- {
- static_addr_t *map = (static_addr_t *)r;
- /* Ensure a valid short address */
- if (map->addr16 >= IEEE802154_NO_ADDR16) {
- *err = "Invalid short address";
- }
- /* Ensure a valid PAN identifier. */
- if (map->pan >= IEEE802154_BCAST_PAN) {
- *err = "Invalid PAN identifier";
- }
- /* Ensure a valid EUI-64 length */
- if (map->eui64_len != sizeof(guint64)) {
- *err = "Invalid EUI-64 length";
- }
- } /* ieee802154_addr_uat_update_cb */
- /* Field callbacks. */
- UAT_HEX_CB_DEF(addr_uat, addr16, static_addr_t)
- UAT_HEX_CB_DEF(addr_uat, pan, static_addr_t)
- UAT_BUFFER_CB_DEF(addr_uat, eui64, static_addr_t, eui64, eui64_len)
- /*-------------------------------------
- * Dissector Function Prototypes
- *-------------------------------------
- */
- /* Register Functions. Loads the dissector into Wireshark. */
- void proto_reg_handoff_ieee802154 (void);
- /* Dissection Routines. */
- static void dissect_ieee802154_nonask_phy (tvbuff_t *, packet_info *, proto_tree *);
- static void dissect_ieee802154 (tvbuff_t *, packet_info *, proto_tree *);
- static void dissect_ieee802154_nofcs (tvbuff_t *, packet_info *, proto_tree *);
- static void dissect_ieee802154_cc24xx (tvbuff_t *, packet_info *, proto_tree *);
- /*static void dissect_ieee802154_linux (tvbuff_t *, packet_info *, proto_tree *); TODO: Implement Me. */
- static void dissect_ieee802154_common (tvbuff_t *, packet_info *, proto_tree *, guint);
- /* Sub-dissector helpers. */
- static void dissect_ieee802154_fcf (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *, guint *);
- static void dissect_ieee802154_superframe (tvbuff_t *, packet_info *, proto_tree *, guint *);
- static void dissect_ieee802154_gtsinfo (tvbuff_t *, packet_info *, proto_tree *, guint *);
- static void dissect_ieee802154_pendaddr (tvbuff_t *, packet_info *, proto_tree *, guint *);
- static void dissect_ieee802154_assoc_req (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
- static void dissect_ieee802154_assoc_rsp (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
- static void dissect_ieee802154_disassoc (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
- static void dissect_ieee802154_realign (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
- static void dissect_ieee802154_gtsreq (tvbuff_t *, packet_info *, proto_tree *, ieee802154_packet *);
- /* Decryption helpers. */
- typedef enum {
- DECRYPT_PACKET_SUCCEEDED,
- DECRYPT_NOT_ENCRYPTED,
- DECRYPT_VERSION_UNSUPPORTED,
- DECRYPT_PACKET_TOO_SMALL,
- DECRYPT_PACKET_NO_EXT_SRC_ADDR,
- DECRYPT_PACKET_NO_KEY,
- DECRYPT_PACKET_DECRYPT_FAILED,
- DECRYPT_PACKET_MIC_CHECK_FAILED
- } ws_decrypt_status;
- static tvbuff_t * dissect_ieee802154_decrypt(tvbuff_t *, guint, packet_info *, ieee802154_packet *,
- ws_decrypt_status *);
- static void ccm_init_block (gchar *, gboolean, gint, guint64, ieee802154_packet *, gint);
- static gboolean ccm_ctr_encrypt (const gchar *, const gchar *, gchar *, gchar *, gint);
- static gboolean ccm_cbc_mac (const gchar *, const gchar *, const gchar *, gint, const gchar *, gint, gchar *);
- /* Initialize Protocol and Registered fields */
- static int proto_ieee802154_nonask_phy = -1;
- static int hf_ieee802154_nonask_phy_preamble = -1;
- static int hf_ieee802154_nonask_phy_sfd = -1;
- static int hf_ieee802154_nonask_phy_length = -1;
- static int proto_ieee802154 = -1;
- static int hf_ieee802154_frame_length = -1;
- static int hf_ieee802154_frame_type = -1;
- static int hf_ieee802154_security = -1;
- static int hf_ieee802154_pending = -1;
- static int hf_ieee802154_ack_request = -1;
- static int hf_ieee802154_intra_pan = -1;
- static int hf_ieee802154_seqno = -1;
- static int hf_ieee802154_src_addr_mode = -1;
- static int hf_ieee802154_dst_addr_mode = -1;
- static int hf_ieee802154_version = -1;
- static int hf_ieee802154_dst_panID = -1;
- static int hf_ieee802154_dst16 = -1;
- static int hf_ieee802154_dst64 = -1;
- static int hf_ieee802154_src_panID = -1;
- static int hf_ieee802154_src16 = -1;
- static int hf_ieee802154_src64 = -1;
- static int hf_ieee802154_src64_origin = -1;
- static int hf_ieee802154_fcs = -1;
- static int hf_ieee802154_rssi = -1;
- static int hf_ieee802154_fcs_ok = -1;
- static int hf_ieee802154_correlation = -1;
- /* Registered fields for Command Packets */
- static int hf_ieee802154_cmd_id = -1;
- static int hf_ieee802154_cinfo_alt_coord = -1;
- static int hf_ieee802154_cinfo_device_type = -1;
- static int hf_ieee802154_cinfo_power_src = -1;
- static int hf_ieee802154_cinfo_idle_rx = -1;
- static int hf_ieee802154_cinfo_sec_capable = -1;
- static int hf_ieee802154_cinfo_alloc_addr = -1;
- static int hf_ieee802154_assoc_addr = -1;
- static int hf_ieee802154_assoc_status = -1;
- static int hf_ieee802154_disassoc_reason = -1;
- static int hf_ieee802154_realign_pan = -1;
- static int hf_ieee802154_realign_caddr = -1;
- static int hf_ieee802154_realign_channel = -1;
- static int hf_ieee802154_realign_addr = -1;
- static int hf_ieee802154_realign_channel_page = -1;
- static int hf_ieee802154_gtsreq_len = -1;
- static int hf_ieee802154_gtsreq_dir = -1;
- static int hf_ieee802154_gtsreq_type = -1;
- /* Registered fields for Beacon Packets */
- static int hf_ieee802154_beacon_order = -1;
- static int hf_ieee802154_superframe_order = -1;
- static int hf_ieee802154_cap = -1;
- static int hf_ieee802154_superframe_battery_ext = -1;
- static int hf_ieee802154_superframe_coord = -1;
- static int hf_ieee802154_assoc_permit = -1;
- static int hf_ieee802154_gts_count = -1;
- static int hf_ieee802154_gts_permit = -1;
- static int hf_ieee802154_gts_direction = -1;
- static int hf_ieee802154_pending16 = -1;
- static int hf_ieee802154_pending64 = -1;
- /* Registered fields for Auxiliary Security Header */
- static int hf_ieee802154_security_level = -1;
- static int hf_ieee802154_key_id_mode = -1;
- static int hf_ieee802154_aux_sec_reserved = -1;
- static int hf_ieee802154_aux_sec_frame_counter = -1;
- static int hf_ieee802154_aux_sec_key_source = -1;
- static int hf_ieee802154_aux_sec_key_index = -1;
- /* 802.15.4-2003 security */
- static int hf_ieee802154_sec_frame_counter = -1;
- static int hf_ieee802154_sec_key_sequence_counter = -1;
- /* Initialize Subtree Pointers */
- static gint ett_ieee802154_nonask_phy = -1;
- static gint ett_ieee802154_nonask_phy_phr = -1;
- static gint ett_ieee802154 = -1;
- static gint ett_ieee802154_fcf = -1;
- static gint ett_ieee802154_auxiliary_security = -1;
- static gint ett_ieee802154_aux_sec_control = -1;
- static gint ett_ieee802154_aux_sec_key_id = -1;
- static gint ett_ieee802154_fcs = -1;
- static gint ett_ieee802154_cmd = -1;
- static gint ett_ieee802154_superframe = -1;
- static gint ett_ieee802154_gts = -1;
- static gint ett_ieee802154_gts_direction = -1;
- static gint ett_ieee802154_gts_descriptors = -1;
- static gint ett_ieee802154_pendaddr = -1;
- /* Dissector handles */
- static dissector_handle_t data_handle;
- static heur_dissector_list_t ieee802154_heur_subdissector_list;
- /* Name Strings */
- static const value_string ieee802154_frame_types[] = {
- { IEEE802154_FCF_BEACON, "Beacon" },
- { IEEE802154_FCF_DATA, "Data" },
- { IEEE802154_FCF_ACK, "Ack" },
- { IEEE802154_FCF_CMD, "Command" },
- { 0, NULL }
- };
- static const value_string ieee802154_addr_modes[] = {
- { IEEE802154_FCF_ADDR_NONE, "None" },
- { IEEE802154_FCF_ADDR_SHORT,"Short/16-bit" },
- { IEEE802154_FCF_ADDR_EXT, "Long/64-bit" },
- { 0, NULL }
- };
- static const value_string ieee802154_cmd_names[] = {
- { IEEE802154_CMD_ASRQ, "Association Request" },
- { IEEE802154_CMD_ASRSP, "Association Response" },
- { IEEE802154_CMD_DISAS, "Disassociation Notification" },
- { IEEE802154_CMD_DATA_RQ, "Data Request" },
- { IEEE802154_CMD_PANID_ERR, "PAN ID Conflict" },
- { IEEE802154_CMD_ORPH_NOTIF,"Orphan Notification" },
- { IEEE802154_CMD_BCN_RQ, "Beacon Request" },
- { IEEE802154_CMD_COORD_REAL,"Coordinator Realignment" },
- { IEEE802154_CMD_GTS_REQ, "GTS Request" },
- { 0, NULL }
- };
- static const value_string ieee802154_sec_level_names[] = {
- { SECURITY_LEVEL_NONE, "No Security" },
- { SECURITY_LEVEL_MIC_32, "32-bit Message Integrity Code" },
- { SECURITY_LEVEL_MIC_64, "64-bit Message Integrity Code" },
- { SECURITY_LEVEL_MIC_128, "128-bit Message Integrity Code" },
- { SECURITY_LEVEL_ENC, "Encryption" },
- { SECURITY_LEVEL_ENC_MIC_32, "Encryption with 32-bit Message Integrity Code" },
- { SECURITY_LEVEL_ENC_MIC_64, "Encryption with 64-bit Message Integrity Code" },
- { SECURITY_LEVEL_ENC_MIC_128, "Encryption with 128-bit Message Integrity Code" },
- { 0, NULL }
- };
- static const value_string ieee802154_key_id_mode_names[] = {
- { KEY_ID_MODE_IMPLICIT, "Implicit Key" },
- { KEY_ID_MODE_KEY_INDEX, "Indexed Key using the Default Key Source" },
- { KEY_ID_MODE_KEY_EXPLICIT_4, "Explicit Key with 4-octet Key Source" },
- { KEY_ID_MODE_KEY_EXPLICIT_8, "Explicit Key with 8-octet Key Source" },
- { 0, NULL }
- };
- static const true_false_string ieee802154_gts_direction_tfs = {
- "Receive Only",
- "Transmit Only"
- };
- /* The 802.15.4-2003 security suites for the security preferences (only AES-CCM suites are supported). */
- /* NOTE: The equivalent 2006 security level identifer enumerations are used to simplify 2003 & 2006 integration! */
- static const enum_val_t ieee802154_2003_sec_suite_enums[] = {
- { "AES-CCM-128", "AES-128 Encryption, 128-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_128 },
- { "AES-CCM-64", "AES-128 Encryption, 64-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_64 },
- { "AES-CCM-32", "AES-128 Encryption, 32-bit Integrity Protection", SECURITY_LEVEL_ENC_MIC_32 },
- { NULL, NULL, 0 }
- };
- /* Preferences for 2003 security */
- static gint ieee802154_sec_suite = SECURITY_LEVEL_ENC_MIC_64;
- static gboolean ieee802154_extend_auth = TRUE;
- /* Macro to check addressing, and throw a warning flag if incorrect. */
- #define IEEE802154_CMD_ADDR_CHECK(_pinfo_, _item_, _cmdid_, _x_) \
- if (!(_x_)) \
- expert_add_info_format(_pinfo_, _item_, PI_MALFORMED, PI_WARN, \
- "Invalid Addressing for %s", \
- val_to_str_const(_cmdid_, ieee802154_cmd_names, "Unknown Command"))
- /* CRC definitions. IEEE 802.15.4 CRCs vary from CCITT by using an initial value of
- * 0x0000, and no XOR out. IEEE802154_CRC_XOR is defined as 0xFFFF in order to un-XOR
- * the output from the CCITT CRC routines in Wireshark.
- */
- #define IEEE802154_CRC_SEED 0x0000
- #define IEEE802154_CRC_XOROUT 0xFFFF
- #define ieee802154_crc_tvb(tvb, offset) (crc16_ccitt_tvb_seed(tvb, offset, IEEE802154_CRC_SEED) ^ IEEE802154_CRC_XOROUT)
- /*FUNCTION:------------------------------------------------------
- * NAME
- * dissect_ieee802154_fcf
- * DESCRIPTION
- * Dissector helper, parses and displays the frame control
- * field.
- *
- * PARAMETERS
- * ieee802154_packet *packet - Packet info structure.
- * tvbuff_t *tvb - pointer to buffer containing raw packet.
- * packet_info *pinfo - pointer to packet information fields
- * proto_tree *tree - pointer to data tree wireshark uses to display packet.
- * ieee802154_packet *packet - IEEE 802.15.4 packet information.
- * guint offset - offset into the tvb to find the FCF.
- * RETURNS
- * void
- *---------------------------------------------------------------
- */
- static void
- dissect_ieee802154_fcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ieee802154_packet *packet, guint *offset)
- {
- guint16 fcf;
- proto_tree *field_tree;
- proto_item *ti;
- /* Get the FCF field. */
- fcf = tvb_get_letohs(tvb, *offset);
- /* Parse FCF Flags. */
- packet->frame_type = fcf & IEEE802154_FCF_TYPE_MASK;
- packet->security_enable = fcf & IEEE802154_FCF_SEC_EN;
- packet->frame_pending = fcf & IEEE802154_FCF_FRAME_PND;
- packet->ack_request = fcf & IEEE802154_FCF_ACK_REQ;
- packet->intra_pan = fcf & IEEE802154_FCF_INTRA_PAN;
- packet->version = (fcf & IEEE802154_FCF_VERSION) >> 12;
- packet->dst_addr_mode = (fcf & IEEE802154_FCF_DADDR_MASK) >> 10;
- packet->src_addr_mode = (fcf & IEEE802154_FCF_SADDR_MASK) >> 14;
- /* Display the frame type. */
- proto_item_append_text(tree, " %s", val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
- col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->frame_type, ieee802154_frame_types, "Reserved"));
- /* Add the FCF to the protocol tree. */
- if (tree) {
- /* Create the FCF subtree. */
- ti = proto_tree_add_text(tree, tvb, *offset, 2, "Frame Control Field: %s (0x%04x)",
- val_to_str_const(packet->frame_type, ieee802154_frame_types, "Unknown"), fcf);
- field_tree = proto_item_add_subtree(ti, ett_ieee802154_fcf);
- /* FCF Fields. */
- proto_tree_add_uint(field_tree, hf_ieee802154_frame_type, tvb, *offset, 1, fcf & IEEE802154_FCF_TYPE_MASK);
- proto_tree_add_boolean(field_tree, hf_ieee802154_security, tvb, *offset, 1, fcf & IEEE802154_FCF_SEC_EN);
- proto_tree_add_boolean(field_tree, hf_ieee802154_pending, tvb, *offset, 1, fcf & IEEE802154_FCF_FRAME_PND);
- proto_tree_add_boolean(field_tree, hf_ieee802154_ack_request, tvb, *offset, 1, fcf & IEEE802154_FCF_ACK_REQ);
- proto_tree_add_boolean(field_tree, hf_ieee802154_intra_pan, tvb, *offset, 1, fcf & IEEE802154_FCF_INTRA_PAN);
- proto_tree_add_uint(field_tree, hf_ieee802154_dst_addr_mode, tvb, (*offset)+1, 1, fcf & IEEE802154_FCF_DADDR_MASK);
- proto_tree_add_uint(field_tree, hf_ieee802154_version, tvb, (*offset)+1, 1, fcf & IEEE802154_FCF_VERSION);
- proto_tree_add_uint(field_tree, hf_ieee802154_src_addr_mode, tvb, (*offset)+1, 1, fcf & IEEE802154_FCF_SADDR_MASK);
- }
- *offset += 2;
- } /* dissect_ieee802154_fcf */
- /*FUNCTION:------------------------------------------------------
- * NAME
- * dissect_ieee802154_nonask_phy
- * DESCRIPTION
- * Dissector for IEEE 802.15.4 non-ASK PHY packet with an FCS containing
- * a 16-bit CRC value.
- *
- * PARAMETERS
- * tvbuff_t *tvb - pointer to buffer containing raw packet.
- * packet_info *pinfo - pointer to packet information fields
- * proto_tree *tree - pointer to data tree wireshark uses to display packet.
- * RETURNS
- * void
- *---------------------------------------------------------------
- */
- static void
- dissect_ieee802154_nonask_phy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
- {
- proto_tree *ieee802154_tree = NULL;
- proto_item *proto_root = NULL;
- guint offset = 0;
- guint32 preamble;
- guint8 sfd,phr;
- tvbuff_t* mac;
- /* Create the protocol tree. */
- if (tree) {
- proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154_nonask_phy, tvb, 0, tvb_length(tvb), "IEEE 802.15.4 non-ASK PHY");
- ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154_nonask_phy);
- }
- /* Add the protocol name. */
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4 non-ASK PHY");
- /* Add the packet length. */
- col_clear(pinfo->cinfo, COL_PACKET_LENGTH);
- col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, "%i", tvb_length(tvb));
- preamble=tvb_get_letohl(tvb,offset);
- sfd=tvb_get_guint8(tvb,offset+4);
- phr=tvb_get_guint8(tvb,offset+4+1);
- if(tree) {
- proto_tree *phr_tree;
- proto_item *pi;
- guint loffset=offset;
- proto_tree_add_uint(ieee802154_tree, hf_ieee802154_nonask_phy_preamble, tvb, loffset, 4, preamble);
- loffset+=4;
- proto_tree_add_uint(ieee802154_tree, hf_ieee802154_nonask_phy_sfd, tvb, loffset, 1, sfd);
- loffset+=1;
- pi = proto_tree_add_text(ieee802154_tree, tvb, loffset, 1, "PHR: 0x%02x", phr);
- phr_tree = proto_item_add_subtree(pi, ett_ieee802154_nonask_phy_phr);
- proto_tree_add_uint(phr_tree, hf_ieee802154_nonask_phy_length, tvb, loffset, 1, phr);
- }
- offset+=4+2*1;
- mac=tvb_new_subset(tvb,offset,-1, phr & IEEE802154_PHY_LENGTH_MASK);
- /* Call the common dissector. */
- dissect_ieee802154(mac, pinfo, ieee802154_tree);
- } /* dissect_ieee802154_nonask_phy */
- /*FUNCTION:------------------------------------------------------
- * NAME
- * dissect_ieee802154
- * DESCRIPTION
- * Dissector for IEEE 802.15.4 packet with an FCS containing
- * a 16-bit CRC value.
- *
- * PARAMETERS
- * tvbuff_t *tvb - pointer to buffer containing raw packet.
- * packet_info *pinfo - pointer to packet information fields
- * proto_tree *tree - pointer to data tree wireshark uses to display packet.
- * RETURNS
- * void
- *---------------------------------------------------------------
- */
- static void
- dissect_ieee802154(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
- {
- /* Call the common dissector. */
- dissect_ieee802154_common(tvb, pinfo, tree, (ieee802154_cc24xx ? DISSECT_IEEE802154_OPTION_CC24xx : 0));
- } /* dissect_ieee802154 */
- /*FUNCTION:------------------------------------------------------
- * NAME
- * dissect_ieee802154_nofcs
- * DESCRIPTION
- * Dissector for IEEE 802.15.4 packet with no FCS present.
- *
- * PARAMETERS
- * tvbuff_t *tvb - pointer to buffer containing raw packet.
- * packet_info *pinfo - pointer to packet information fields
- * proto_tree *tree - pointer to data tree wireshark uses to display packet.
- * RETURNS
- * void
- *---------------------------------------------------------------
- */
- static void
- dissect_ieee802154_nofcs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
- {
- tvbuff_t *new_tvb;
- /* If there is no FCS present in the reported packet, then the length of
- * the true IEEE 802.15.4 packet is actually 2 bytes longer. Re-create
- * the buffer with an extended reported length so that the packet will
- * be handled as though the FCS were truncated.
- *
- * Note, we can't just call tvb_set_reported_length(), because it includes
- * checks to ensure that the new reported length is not longer than the old
- * reported length (why?), and will throw an exception.
- */
- new_tvb = tvb_new_subset(tvb, 0, -1, tvb_reported_length(tvb)+IEEE802154_FCS_LEN);
- /* Call the common dissector. */
- dissect_ieee802154_common(new_tvb, pinfo, tree, 0);
- } /* dissect_ieee802154_nofcs */
- /*FUNCTION:------------------------------------------------------
- * NAME
- * dissect_ieee802154_cc24xx
- * DESCRIPTION
- * Dissector for IEEE 802.15.4 packet with a ChipCon/Texas
- * Instruments compatible FCS. This is typically called by
- * layers encapsulating an IEEE 802.15.4 packet.
- *
- * PARAMETERS
- * tvbuff_t *tvb - pointer to buffer containing raw packet.
- * packet_info *pinfo - pointer to packet information fields
- * proto_tree *tree - pointer to data tree wireshark uses to display packet.
- * RETURNS
- * void
- *---------------------------------------------------------------
- */
- static void
- dissect_ieee802154_cc24xx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
- {
- /* Call the common dissector. */
- dissect_ieee802154_common(tvb, pinfo, tree, DISSECT_IEEE802154_OPTION_CC24xx);
- } /* dissect_ieee802154_cc24xx */
- /*FUNCTION:------------------------------------------------------
- * NAME
- * dissect_ieee802154_common
- * DESCRIPTION
- * IEEE 802.15.4 packet dissection routine for Wireshark.
- * This function extracts all the information first before displaying.
- * If payload exists, that portion will be passed into another dissector
- * for further processing.
- *
- * This is called after the individual dissect_ieee802154* functions
- * have been called to determine what sort of FCS is present.
- * The dissect_ieee802154* functions will set the parameters
- * in the ieee802154_packet structure, and pass it to this one
- * through the pinfo->private_data pointer.
- *
- * PARAMETERS
- * tvbuff_t *tvb - pointer to buffer containing raw packet.
- * packet_info *pinfo - pointer to packet information fields
- * proto_tree *tree - pointer to data tree wireshark uses to display packet.
- * guint options - bitwise or of dissector options (see DISSECT_IEEE802154_OPTION_xxx).
- * RETURNS
- * void
- *---------------------------------------------------------------
- */
- static void
- dissect_ieee802154_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint options)
- {
- tvbuff_t *volatile payload_tvb;
- proto_tree *volatile ieee802154_tree = NULL;
- proto_item *volatile proto_root = NULL;
- proto_item *hidden_item;
- proto_item *ti;
- void *pd_save;
- guint offset = 0;
- volatile gboolean fcs_ok = TRUE;
- const char *saved_proto;
- ws_decrypt_status status;
- ieee802154_packet *packet = wmem_new(wmem_packet_scope(), ieee802154_packet);
- ieee802154_short_addr addr16;
- ieee802154_hints_t *ieee_hints;
- /* Link our packet info structure into the private data field for the
- * Network-Layer heuristic subdissectors. */
- pd_save = pinfo->private_data;
- pinfo->private_data = packet;
- packet->short_table = ieee802154_map.short_table;
- /* Allocate frame data with hints for upper layers */
- if(!pinfo->fd->flags.visited){
- ieee_hints = se_new0(ieee802154_hints_t);
- p_add_proto_data(pinfo->fd, proto_ieee802154, 0, ieee_hints);
- } else {
- ieee_hints = (ieee802154_hints_t *)p_get_proto_data(pinfo->fd, proto_ieee802154, 0);
- }
- /* Create the protocol tree. */
- if (tree) {
- proto_root = proto_tree_add_protocol_format(tree, proto_ieee802154, tvb, 0, tvb_length(tvb), "IEEE 802.15.4");
- ieee802154_tree = proto_item_add_subtree(proto_root, ett_ieee802154);
- }
- /* Add the protocol name. */
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.15.4");
- /* Add the packet length. */
- col_clear(pinfo->cinfo, COL_PACKET_LENGTH);
- col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, "%i", tvb_length(tvb));
- /* Add the packet length to the filter field */
- hidden_item = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_frame_length, NULL, 0, 0, tvb_reported_length(tvb));
- PROTO_ITEM_SET_HIDDEN(hidden_item);
- /*=====================================================
- * FRAME CONTROL FIELD
- *=====================================================
- */
- dissect_ieee802154_fcf(tvb, pinfo, ieee802154_tree, packet, &offset);
- /*=====================================================
- * SEQUENCE NUMBER
- *=====================================================
- */
- packet->seqno = tvb_get_guint8(tvb, offset);
- if (tree) {
- proto_tree_add_uint(ieee802154_tree, hf_ieee802154_seqno, tvb, offset, 1, packet->seqno);
- /* For Ack packets display this in the root. */
- if (packet->frame_type == IEEE802154_FCF_ACK) {
- proto_item_append_text(proto_root, ", Sequence Number: %u", packet->seqno);
- }
- }
- offset += 1;
- /*=====================================================
- * ADDRESSING FIELDS
- *=====================================================
- */
- /* Clear out the addressing strings. */
- SET_ADDRESS(&pinfo->dst, AT_NONE, 0, NULL);
- SET_ADDRESS(&pinfo->src, AT_NONE, 0, NULL);
- SET_ADDRESS(&pinfo->dl_dst, AT_NONE, 0, NULL);
- SET_ADDRESS(&pinfo->dl_src, AT_NONE, 0, NULL);
- SET_ADDRESS(&pinfo->net_dst, AT_NONE, 0, NULL);
- SET_ADDRESS(&pinfo->net_src, AT_NONE, 0, NULL);
- /* Get and display the destination PAN, if present. */
- if ( (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) ||
- (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) ) {
- packet->dst_pan = tvb_get_letohs(tvb, offset);
- if (tree) {
- proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst_panID, tvb, offset, 2, packet->dst_pan);
- }
- offset += 2;
- }
- /* Get destination address. */
- if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
- char dst_addr[32];
- /* Get the address. */
- packet->dst16 = tvb_get_letohs(tvb, offset);
- /* Display the destination address. */
- if ( packet->dst16 == IEEE802154_BCAST_ADDR ) {
- g_snprintf(dst_addr, 32, "Broadcast");
- }
- else {
- g_snprintf(dst_addr, 32, "0x%04x", packet->dst16);
- }
- /* Provide address hints to higher layers that need it. */
- if (ieee_hints) {
- ieee_hints->dst16 = packet->dst16;
- }
- TVB_SET_ADDRESS(&pinfo->dl_dst, AT_IEEE_802_15_4_SHORT, tvb, offset, 2);
- TVB_SET_ADDRESS(&pinfo->dst, AT_IEEE_802_15_4_SHORT, tvb, offset, 2);
- if (tree) {
- proto_tree_add_uint(ieee802154_tree, hf_ieee802154_dst16, tvb, offset, 2, packet->dst16);
- proto_item_append_text(proto_root, ", Dst: %s", dst_addr);
- }
- col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", dst_addr);
- offset += 2;
- }
- else if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT) {
- static guint64 addr; /* has to be static due to SET_ADDRESS */
- /* Get the address */
- packet->dst64 = tvb_get_letoh64(tvb, offset);
- /* Copy and convert the address to network byte order. */
- addr = pntoh64(&(packet->dst64));
- /* Display the destination address. */
- /* XXX - OUI resolution doesn't happen when displaying resolved
- * EUI64 addresses; that should probably be fixed in
- * epan/addr_resolv.c.
- */
- SET_ADDRESS(&pinfo->dl_dst, AT_EUI64, 8, &addr);
- SET_ADDRESS(&pinfo->dst, AT_EUI64, 8, &addr);
- if (tree) {
- proto_tree_add_item(ieee802154_tree, hf_ieee802154_dst64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
- proto_item_append_text(proto_root, ", Dst: %s", get_eui64_name(packet->dst64));
- }
- col_append_fstr(pinfo->cinfo, COL_INFO, ", Dst: %s", get_eui64_name(packet->dst64));
- offset += 8;
- }
- else if (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE) {
- /* Invalid Destination Address Mode. Abort Dissection. */
- expert_add_info_format(pinfo, proto_root, PI_MALFORMED, PI_ERROR, "Invalid Destination Address Mode");
- pinfo->private_data = pd_save;
- return;
- }
- /* Get the source PAN if it exists. The source address will be present if:
- * - The Source addressing exists and
- * - The Destination addressing doesn't exist, or the Intra-PAN bit is unset.
- */
- if ( ((packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) || (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT)) &&
- ((packet->dst_addr_mode == IEEE802154_FCF_ADDR_NONE) || (!packet->intra_pan)) ) {
- /* Source PAN is present, extract it and add it to the tree. */
- packet->src_pan = tvb_get_letohs(tvb, offset);
- if (tree) {
- proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src_panID, tvb, offset, 2, packet->src_pan);
- }
- offset += 2;
- }
- else {
- /* Set the panID field in case the intra-pan condition was met. */
- packet->src_pan = packet->dst_pan;
- }
- if (ieee_hints) {
- ieee_hints->src_pan = packet->src_pan;
- }
- /* Get short source address if present. */
- if (packet->src_addr_mode == IEEE802154_FCF_ADDR_SHORT) {
- char src_addr[32];
- /* Get the address. */
- packet->src16 = tvb_get_letohs(tvb, offset);
- /* Update the Address fields. */
- if (packet->src16==IEEE802154_BCAST_ADDR) {
- g_snprintf(src_addr, 32, "Broadcast");
- }
- else {
- g_snprintf(src_addr, 32, "0x%04x", packet->src16);
- if (!pinfo->fd->flags.visited) {
- /* If we know our extended source address from previous packets,
- * provide a pointer to it in a hint for upper layers */
- addr16.addr = packet->src16;
- addr16.pan = packet->src_pan;
- if (ieee_hints) {
- ieee_hints->src16 = packet->src16;
- ieee_hints->map_rec = (ieee802154_map_rec *)
- g_hash_table_lookup(ieee802154_map.short_table, &addr16);
- }
- }
- }
- TVB_SET_ADDRESS(&pinfo->dl_src, AT_IEEE_802_15_4_SHORT, tvb, offset, 2);
- TVB_SET_ADDRESS(&pinfo->src, AT_IEEE_802_15_4_SHORT, tvb, offset, 2);
- /* Add the addressing info to the tree. */
- if (tree) {
- proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src16, tvb, offset, 2, packet->src16);
- proto_item_append_text(proto_root, ", Src: %s", src_addr);
- if (ieee_hints && ieee_hints->map_rec) {
- /* Display inferred source address info */
- ti = proto_tree_add_eui64(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 0,
- ieee_hints->map_rec->addr64);
- PROTO_ITEM_SET_GENERATED(ti);
- if ( ieee_hints->map_rec->start_fnum ) {
- ti = proto_tree_add_uint(ieee802154_tree, hf_ieee802154_src64_origin, tvb, 0, 0,
- ieee_hints->map_rec->start_fnum);
- }
- else {
- ti = proto_tree_add_text(ieee802154_tree, tvb, 0, 0, "Origin: Pre-configured");
- }
- PROTO_ITEM_SET_GENERATED(ti);
- }
- }
- col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", src_addr);
- offset += 2;
- }
- else if (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) {
- static guint64 addr; /* has to be static due to SET_ADDRESS */
- /* Get the address. */
- packet->src64 = tvb_get_letoh64(tvb, offset);
- /* Copy and convert the address to network byte order. */
- addr = pntoh64(&(packet->src64));
- /* Display the source address. */
- /* XXX - OUI resolution doesn't happen when displaying resolved
- * EUI64 addresses; that should probably be fixed in
- * epan/addr_resolv.c.
- */
- SET_ADDRESS(&pinfo->dl_src, AT_EUI64, 8, &addr);
- SET_ADDRESS(&pinfo->src, AT_EUI64, 8, &addr);
- if (tree) {
- proto_tree_add_item(ieee802154_tree, hf_ieee802154_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
- proto_item_append_text(proto_root, ", Src: %s", get_eui64_name(packet->src64));
- }
- col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: %s", get_eui64_name(packet->src64));
- offset += 8;
- }
- else if (packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE) {
- /* Invalid Destination Address Mode. Abort Dissection. */
- expert_add_info_format(pinfo, proto_root, PI_MALFORMED, PI_ERROR, "Invalid Source Address Mode");
- pinfo->private_data = pd_save;
- return;
- }
- /*=====================================================
- * VERIFY FRAME CHECK SEQUENCE
- *=====================================================
- */
- /* Check, but don't display the FCS yet, otherwise the payload dissection
- * may be out of place in the tree. But we want to know if the FCS is OK in
- * case the CRC is bad (don't want to continue dissection to the NWK layer).
- */
- if (tvb_bytes_exist(tvb, tvb_reported_length(tvb)-IEEE802154_FCS_LEN, IEEE802154_FCS_LEN)) {
- /* The FCS is in the last two bytes of the packet. */
- guint16 fcs = tvb_get_letohs(tvb, tvb_reported_length(tvb)-IEEE802154_FCS_LEN);
- /* Check if we are expecting a CC2420-style FCS*/
- if (options & DISSECT_IEEE802154_OPTION_CC24xx) {
- fcs_ok = (fcs & IEEE802154_CC24xx_CRC_OK);
- }
- else {
- guint16 fcs_calc = ieee802154_crc_tvb(tvb, tvb_reported_length(tvb)-IEEE802154_FCS_LEN);
- fcs_ok = (fcs == fcs_calc);
- }
- }
- /*=====================================================
- * AUXILIARY SECURITY HEADER
- *=====================================================
- */
- /* The Auxiliary Security Header only exists in IEEE 802.15.4-2006 */
- if (packet->security_enable && (packet->version == IEEE802154_VERSION_2006)) {
- proto_tree *header_tree, *field_tree;
- guint8 security_control;
- guint aux_length = 5; /* Minimum length of the auxiliary header. */
- /* Parse the security control field. */
- security_control = tvb_get_guint8(tvb, offset);
- packet->security_level = (ieee802154_security_level)(security_control & IEEE802154_AUX_SEC_LEVEL_MASK);
- packet->key_id_mode = (ieee802154_key_id_mode)((security_control & IEEE802154_AUX_KEY_ID_MODE_MASK) >> IEEE802154_AUX_KEY_ID_MODE_SHIFT);
- /* Compute the length of the auxiliary header and create a subtree. */
- if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) aux_length++;
- if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) aux_length += 4;
- if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) aux_length += 8;
- ti = proto_tree_add_text(ieee802154_tree, tvb, offset, aux_length, "Auxiliary Security Header");
- header_tree = proto_item_add_subtree(ti, ett_ieee802154_auxiliary_security);
- /* Security Control Field */
- ti = proto_tree_add_text(header_tree, tvb, offset, 1, "Security Control Field (0x%02x)", security_control);
- field_tree = proto_item_add_subtree(ti, ett_ieee802154_aux_sec_control);
- proto_tree_add_uint(field_tree, hf_ieee802154_security_level, tvb, offset, 1, security_control & IEEE802154_AUX_SEC_LEVEL_MASK);
- proto_tree_add_uint(field_tree, hf_ieee802154_key_id_mode, tvb, offset, 1, security_control & IEEE802154_AUX_KEY_ID_MODE_MASK);
- proto_tree_add_uint(field_tree, hf_ieee802154_aux_sec_reserved, tvb, offset, 1, security_control & IEEE802154_AUX_KEY_RESERVED_MASK);
- offset++;
- /* Frame Counter Field */
- packet->frame_counter = tvb_get_letohl (tvb, offset);
- proto_tree_add_uint(header_tree, hf_ieee802154_aux_sec_frame_counter, tvb, offset,4, packet->frame_counter);
- offset +=4;
- /* Key identifier field(s). */
- if (packet->key_id_mode != KEY_ID_MODE_IMPLICIT) {
- /* Create a subtree. */
- ti = proto_tree_add_text(header_tree, tvb, offset, 1, "Key Identifier Field"); /* Will fix length later. */
- field_tree = proto_item_add_subtree(ti, ett_ieee802154_aux_sec_key_id);
- /* Add key source, if it exists. */
- if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_4) {
- packet->key_source.addr32 = tvb_get_ntohl(tvb, offset);
- proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, offset, 4, packet->key_source.addr32);
- proto_item_set_len(ti, 1 + 4);
- offset += (int)sizeof (guint32);
- }
- if (packet->key_id_mode == KEY_ID_MODE_KEY_EXPLICIT_8) {
- packet->key_source.addr64 = tvb_get_ntoh64(tvb, offset);
- proto_tree_add_uint64(field_tree, hf_ieee802154_aux_sec_key_source, tvb, offset, 8, packet->key_source.addr64);
- proto_item_set_len(ti, 1 + 8);
- offset += 8;
- }
- /* Add key identifier. */
- packet->key_index = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(field_tree, hf_ieee802154_aux_sec_key_index, tvb, offset,1, packet->key_index);
- offset++;
- }
- }
- /*=====================================================
- * NONPAYLOAD FIELDS
- *=====================================================
- */
- /* All of the beacon fields, except the beacon payload are considered nonpayload. */
- if (packet->frame_type == IEEE802154_FCF_BEACON) {
- /* Parse the superframe spec. */
- dissect_ieee802154_superframe(tvb, pinfo, ieee802154_tree, &offset);
- /* Parse the GTS information fields. */
- dissect_ieee802154_gtsinfo(tvb, pinfo, ieee802154_tree, &offset);
- /* Parse the Pending address list. */
- dissect_ieee802154_pendaddr(tvb, pinfo, ieee802154_tree, &offset);
- }
- /* Only the Command ID is considered nonpayload. */
- if (packet->frame_type == IEEE802154_FCF_CMD) {
- packet->command_id = tvb_get_guint8(tvb, offset);
- if (tree) {
- proto_tree_add_uint(ieee802154_tree, hf_ieee802154_cmd_id, tvb, offset, 1, packet->command_id);
- }
- offset++;
- /* Display the command identifier in the info column. */
- col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet->command_id, ieee802154_cmd_names, "Unknown Command"));
- }
- /* No other frame types have nonpayload fields. */
- /*=====================================================
- * PAYLOAD DISSECTION
- *=====================================================
- */
- /* IEEE 802.15.4-2003 may have security information pre-pended to payload */
- if (packet->security_enable && (packet->version == IEEE802154_VERSION_2003)) {
- /* Store security suite preference in the 2006 security level identifier to simplify 2003 integration! */
- packet->security_level = (ieee802154_security_level)ieee802154_sec_suite;
- /* Frame Counter and Key Sequence Counter prepended to the payload of an encrypted frame */
- if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
- packet->frame_counter = tvb_get_letohl (tvb, offset);
- proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_frame_counter, tvb, offset, (int)sizeof(guint32), packet->frame_counter);
- offset += (int)sizeof(guint32);
- packet->key_sequence_counter = tvb_get_guint8 (tvb, offset);
- proto_tree_add_uint(ieee802154_tree, hf_ieee802154_sec_key_sequence_counter, tvb, offset, (int)sizeof(guint8), packet->key_sequence_counter);
- offset += (int)sizeof(guint8);
- }
- }
- /* Encrypted Payload. */
- if (packet->security_enable) {
- payload_tvb = dissect_ieee802154_decrypt(tvb, offset, pinfo, packet, &status);
- /* Get the unencrypted data if decryption failed. */
- if (!payload_tvb) {
- /* Deal with possible truncation and the FCS field at the end. */
- gint reported_len = tvb_reported_length(tvb)-offset-IEEE802154_FCS_LEN;
- gint captured_len = tvb_length(tvb)-offset;
- if (reported_len < captured_len) captured_len = reported_len;
- payload_tvb = tvb_new_subset(tvb, offset, captured_len, reported_len);
- }
- /* Display the reason for failure, and abort if the error was fatal. */
- switch (status) {
- case DECRYPT_PACKET_SUCCEEDED:
- case DECRYPT_NOT_ENCRYPTED:
- /* No problem. */
- break;
- case DECRYPT_VERSION_UNSUPPORTED:
- /* We don't support decryption with that version of the protocol */
- expert_add_info_format(pinfo, proto_root, PI_UNDECODED, PI_WARN, "We don't support decryption with protocol version %u",
- packet->version);
- call_dissector(data_handle, payload_tvb, pinfo, tree);
- goto dissect_ieee802154_fcs;
- case DECRYPT_PACKET_TOO_SMALL:
- expert_add_info_format(pinfo, proto_root, PI_UNDECODED, PI_WARN, "Packet was too small to include the CRC and MIC");
- call_dissector(data_handle, payload_tvb, pinfo, tree);
- goto dissect_ieee802154_fcs;
- case DECRYPT_PACKET_NO_EXT_SRC_ADDR:
- expert_add_info_format(pinfo, proto_root, PI_UNDECODED, PI_WARN, "No extended source address - can't decrypt");
- call_dissector(data_handle, payload_tvb, pinfo, tree);
- goto dissect_ieee802154_fcs;
- case DECRYPT_PACKET_NO_KEY:
- expert_add_info_format(pinfo, proto_root, PI_UNDECODED, PI_WARN, "No encryption key set - can't decrypt");
- call_dissector(data_handle, payload_tvb, pinfo, tree);
- goto dissect_ieee802154_fcs;
- case DECRYPT_PACKET_DECRYPT_FAILED:
- expert_add_info_format(pinfo, proto_root, PI_UNDECODED, PI_WARN, "Decrypt failed");
- call_dissector(data_handle, payload_tvb, pinfo, tree);
- goto dissect_ieee802154_fcs;
- case DECRYPT_PACKET_MIC_CHECK_FAILED:
- expert_add_info_format(pinfo, proto_root, PI_UNDECODED, PI_WARN, "MIC check failed");
- /*
- * Abort only if the payload was encrypted, in which case we
- * probably didn't decrypt the packet right (eg: wrong key).
- */
- if (IEEE802154_IS_ENCRYPTED(packet->security_level)) {
- call_dissector(data_handle, payload_tvb, pinfo, tree);
- goto dissect_ieee802154_fcs;
- }
- break;
- }
- }
- /* Plaintext Payload. */
- else {
- /* Deal with possible truncation and the FCS field at the end. */
- gint reported_len = tvb_reported_length(tvb)-offset-IEEE802154_FCS_LEN;
- gint captured_len = tvb_length(tvb)-offset;
- if (reported_len < captured_len) captured_len = reported_len;
- payload_tvb = tvb_new_subset(tvb, offset, captured_len, reported_len);
- }
- /*
- * Wrap the sub-dissection in a try/catch block in case the payload is
- * broken. First we store the current protocol so we can fix it if an
- * exception is thrown by the subdissectors.
- */
- saved_proto = pinfo->current_proto;
- /* Try to dissect the payload. */
- TRY {
- if ((packet->frame_type == IEEE802154_FCF_BEACON) ||
- (packet->frame_type == IEEE802154_FCF_DATA)) {
- /* Beacon and Data packets contain a payload. */
- if ((fcs_ok || !ieee802154_fcs_ok) && (tvb_reported_length(payload_tvb)>0)) {
- /* Attempt heuristic subdissection. */
- if (!dissector_try_heuristic(ieee802154_heur_subdissector_list, payload_tvb, pinfo, tree, NULL)) {
- /* Could not subdissect, call the data dissector instead. */
- call_dissector(data_handle, payload_tvb, pinfo, tree);
- }
- }
- else {
- /* If no sub-dissector was called, call the data dissector. */
- call_dissector(data_handle, payload_tvb, pinfo, tree);
- }
- }
- /* If the packet is a command, try to dissect the payload. */
- else if (packet->frame_type == IEEE802154_FCF_CMD) {
- switch (packet->command_id) {
- case IEEE802154_CMD_ASRQ:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
- (packet->dst_addr_mode != IEEE802154_FCF_ADDR_NONE));
- dissect_ieee802154_assoc_req(payload_tvb, pinfo, ieee802154_tree, packet);
- break;
- case IEEE802154_CMD_ASRSP:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
- (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
- dissect_ieee802154_assoc_rsp(payload_tvb, pinfo, ieee802154_tree, packet);
- break;
- case IEEE802154_CMD_DISAS:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
- (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
- dissect_ieee802154_disassoc(payload_tvb, pinfo, ieee802154_tree, packet);
- break;
- case IEEE802154_CMD_DATA_RQ:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id, packet->src_addr_mode != IEEE802154_FCF_ADDR_NONE);
- /* No payload expected. */
- break;
- case IEEE802154_CMD_PANID_ERR:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
- (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT));
- /* No payload expected. */
- break;
- case IEEE802154_CMD_ORPH_NOTIF:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->src_addr_mode == IEEE802154_FCF_ADDR_EXT) &&
- (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
- (packet->dst16 == IEEE802154_BCAST_ADDR) &&
- (packet->src_pan == IEEE802154_BCAST_PAN) &&
- (packet->dst_pan == IEEE802154_BCAST_PAN));
- /* No payload expected. */
- break;
- case IEEE802154_CMD_BCN_RQ:
- IEEE802154_CMD_ADDR_CHECK(pinfo, proto_root, packet->command_id,
- (packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT) &&
- …
Large files files are truncated, but you can click here to view the full file