1441 lines
56 KiB
C
1441 lines
56 KiB
C
/* packet-rf4ce-nwk.c
|
|
* Network layer related functions and objects for RF4CE dissector
|
|
* Copyright (C) Atmosic 2023
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include "config.h"
|
|
#include <epan/packet.h>
|
|
#include <epan/expert.h>
|
|
#include <epan/uat.h>
|
|
#include "packet-ieee802154.h"
|
|
#include "packet-rf4ce-secur.h"
|
|
|
|
#define RF4CE_MIN_NWK_LENGTH 5
|
|
#define RF4CE_MAX_NWK_LENGTH 148
|
|
|
|
/* Profile IDs */
|
|
#define RF4CE_NWK_PROFILE_ID_GDP 0x00
|
|
#define RF4CE_NWK_PROFILE_ID_ZRC10 0x01
|
|
#define RF4CE_NWK_PROFILE_ID_ZID 0x02
|
|
#define RF4CE_NWK_PROFILE_ID_ZRC20 0x03
|
|
|
|
#define RF4CE_PROTOABBREV_NWK "rf4ce_nwk"
|
|
#define RF4CE_PROTOABBREV_PROFILE "rf4ce_profile"
|
|
|
|
static int proto_rf4ce_nwk;
|
|
static dissector_handle_t rf4ce_gdp_handle;
|
|
|
|
/* UAT vars */
|
|
static uat_t *rf4ce_security_table_uat;
|
|
|
|
#define RF4CE_SEC_STR_TYPE_NWK_KEY 0
|
|
#define RF4CE_SEC_STR_TYPE_VENDOR_SECRET 1
|
|
|
|
static const value_string sec_str_type_vals[] = {
|
|
{ RF4CE_SEC_STR_TYPE_NWK_KEY, "NWK Key"},
|
|
{ RF4CE_SEC_STR_TYPE_VENDOR_SECRET, "Vendor Secret"},
|
|
{ 0, NULL }
|
|
};
|
|
|
|
UAT_CSTRING_CB_DEF(uat_security_records, sec_str, uat_security_record_t)
|
|
UAT_VS_DEF(uat_security_records, type, uat_security_record_t, guint8, 0, "NWK Key")
|
|
UAT_CSTRING_CB_DEF(uat_security_records, label, uat_security_record_t)
|
|
|
|
static uat_security_record_t *uat_security_records = NULL;
|
|
static guint num_uat_security_records = 0;
|
|
|
|
static gint ett_rf4ce_nwk;
|
|
static gint ett_rf4ce_nwk_payload;
|
|
static gint ett_rf4ce_nwk_vendor_info;
|
|
static gint ett_rf4ce_nwk_usr_str;
|
|
static gint ett_rf4ce_nwk_usr_str_class_descriptor;
|
|
static gint ett_rf4ce_nwk_dev_types_list;
|
|
static gint ett_rf4ce_nwk_profiles_list;
|
|
|
|
/* RF4CE NWK header */
|
|
static int hf_rf4ce_nwk_fcf;
|
|
static int hf_rf4ce_nwk_fcf_frame_type;
|
|
static int hf_rf4ce_nwk_fcf_security_enabled;
|
|
static int hf_rf4ce_nwk_fcf_protocol_version;
|
|
static int hf_rf4ce_nwk_fcf_reserved;
|
|
static int hf_rf4ce_nwk_fcf_channel_designator;
|
|
static int hf_rf4ce_nwk_seq_num;
|
|
static int hf_rf4ce_nwk_profile_id;
|
|
static int hf_rf4ce_nwk_vendor_id;
|
|
|
|
/* RF4CE NWK payload common */
|
|
static int hf_rf4ce_nwk_cmd_id;
|
|
|
|
static int hf_rf4ce_nwk_node_capabilities;
|
|
static int hf_rf4ce_nwk_node_capabilities_node_type;
|
|
static int hf_rf4ce_nwk_node_capabilities_power_source;
|
|
static int hf_rf4ce_nwk_node_capabilities_security;
|
|
static int hf_rf4ce_nwk_node_capabilities_channel_normalization;
|
|
static int hf_rf4ce_nwk_node_capabilities_reserved;
|
|
|
|
static int hf_rf4ce_nwk_disc_req_vendor_id;
|
|
|
|
#define RF4CE_NWK_VENDOR_STRING_MAX_LENGTH 7
|
|
static int hf_rf4ce_nwk_vendor_string;
|
|
|
|
static int hf_rf4ce_nwk_app_capabilities;
|
|
static int hf_rf4ce_nwk_app_capabilities_usr_str;
|
|
static int hf_rf4ce_nwk_app_capabilities_supported_dev_num;
|
|
static int hf_rf4ce_nwk_app_capabilities_reserved1;
|
|
static int hf_rf4ce_nwk_app_capabilities_supported_profiles_num;
|
|
static int hf_rf4ce_nwk_app_capabilities_reserved2;
|
|
|
|
static int hf_rf4ce_nwk_usr_str;
|
|
static int hf_rf4ce_nwk_usr_str_disc_rsp_app_usr_str;
|
|
static int hf_rf4ce_nwk_usr_str_disc_rsp_null;
|
|
static int hf_rf4ce_nwk_usr_str_disc_rsp_reserved;
|
|
|
|
static int hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_tertiary;
|
|
static int hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_secondary;
|
|
static int hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_primary;
|
|
|
|
static int hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_class_num;
|
|
static int hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_duplicate_class_num_handling;
|
|
static int hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_reserved;
|
|
|
|
static int hf_rf4ce_nwk_usr_str_disc_rsp_discovery_lqi_threshold;
|
|
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_MASK 0b00001111
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_MASK 0b00110000
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_RESERVED_MASK 0b11000000
|
|
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_PRE_COMMISSIONED 0x00
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_BUTTON_PRESS_INDICATION 0x01
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_RESERVED_2 0x02
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_RESERVED_3 0x03
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_04 0x04
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_05 0x05
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_06 0x06
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_07 0x07
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_08 0x08
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_09 0x09
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0A 0x0A
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0B 0x0B
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0C 0x0C
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0D 0x0D
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0E 0x0E
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_DISCOVERABLE_ONLY 0x0F
|
|
|
|
static const value_string rf4ce_nwk_usr_str_disc_rsp_class_desc_class_num_vals[] = {
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_PRE_COMMISSIONED, "Pre-Commissioned" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_BUTTON_PRESS_INDICATION, "Button Press Indication" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_RESERVED_2, "Reserved" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_RESERVED_3, "Reserved" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_04, "Implementation Specific" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_05, "Implementation Specific" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_06, "Implementation Specific" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_07, "Implementation Specific" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_08, "Implementation Specific" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_09, "Implementation Specific" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0A, "Implementation Specific" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0B, "Implementation Specific" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0C, "Implementation Specific" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0D, "Implementation Specific" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_IMPLEMENTATION_SPECIFIC_0E, "Implementation Specific" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_DISCOVERABLE_ONLY, "Discoverable Only" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_AS_IS 0x00
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_RECLASSIFY 0x01
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_ABORT_BINDING 0x02
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_RESERVED 0x03
|
|
|
|
static const value_string rf4ce_nwk_usr_str_disc_rsp_class_desc_duplicate_class_num_handling_vals[] = {
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_AS_IS, "Use node descriptor as is" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_RECLASSIFY, "Reclassify node descriptor" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_ABORT_BINDING, "Abort binding" },
|
|
{ RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_RESERVED, "Reserved" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
#define RF4CE_NWK_USR_STR_DISC_RSP_APP_USR_STR_LENGTH 9
|
|
|
|
#define RF4CE_NWK_USR_STR_PARSING_MASK_NONE 0b00000001
|
|
#define RF4CE_NWK_USR_STR_PARSING_MASK_DISC_RESP 0b00000010
|
|
|
|
static int hf_rf4ce_nwk_app_cap_dev_type;
|
|
static int hf_rf4ce_nwk_app_cap_profile_id;
|
|
|
|
/* RF4CE NWK Discovery Request */
|
|
static int hf_rf4ce_nwk_requested_dev_type;
|
|
|
|
/* RF4CE NWK Discovery Response */
|
|
static int hf_rf4ce_nwk_disc_resp_status;
|
|
static int hf_rf4ce_nwk_disc_resp_lqi;
|
|
|
|
/* RF4CE NWK Pair Request */
|
|
static int hf_rf4ce_nwk_pair_req_nwk_addr;
|
|
static int hf_rf4ce_nwk_pair_req_key_exch_num;
|
|
|
|
/* RF4CE NWK Pair Response */
|
|
static int hf_rf4ce_nwk_pair_rsp_status;
|
|
static int hf_rf4ce_nwk_pair_rsp_allocated_nwk_addr;
|
|
static int hf_rf4ce_nwk_pair_rsp_nwk_addr;
|
|
|
|
/* RF4CE NWK Key Seed */
|
|
static int hf_rf4ce_nwk_seed_seq_num;
|
|
|
|
#define RF4CE_NWK_KEY_SEED_DATA_LENGTH 80
|
|
static int hf_rf4ce_nwk_seed_data;
|
|
|
|
/* RF4CE NWK Ping Request and Response */
|
|
static int hf_rf4ce_nwk_ping_options;
|
|
static int hf_rf4ce_nwk_ping_payload;
|
|
|
|
#if 0
|
|
/* Should be at the end of a decrypted NWK packet */
|
|
static int hf_rf4ce_nwk_mic;
|
|
#endif
|
|
|
|
static int hf_rf4ce_nwk_unparsed_payload;
|
|
|
|
/* Frame Control Field */
|
|
#define RF4CE_NWK_FCF_FRAME_TYPE_MASK 0b00000011
|
|
#define RF4CE_NWK_FCF_SECURITY_MASK 0b00000100
|
|
#define RF4CE_NWK_FCF_PROTOCOL_VERSION_MASK 0b00011000
|
|
#define RF4CE_NWK_FCF_RESERVED_MASK 0b00100000
|
|
#define RF4CE_NWK_FCF_CHANNEL_DESIGNATOR_MASK 0b11000000
|
|
|
|
/* Frame types */
|
|
#define RF4CE_NWK_FCF_FRAME_TYPE_RESERVED 0
|
|
#define RF4CE_NWK_FCF_FRAME_TYPE_DATA 1
|
|
#define RF4CE_NWK_FCF_FRAME_TYPE_CMD 2
|
|
#define RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC 3
|
|
|
|
static const value_string rf4ce_nwk_frame_types[] = {
|
|
{ RF4CE_NWK_FCF_FRAME_TYPE_RESERVED, "Reserved" },
|
|
{ RF4CE_NWK_FCF_FRAME_TYPE_DATA, "Standard Data Frame" },
|
|
{ RF4CE_NWK_FCF_FRAME_TYPE_CMD, "NWK Command Frame" },
|
|
{ RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC, "Vendor-specific data frame" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
/* Channel Designators */
|
|
#define RF4CE_NWK_FCF_CHANNEL_NOT_SPECIFIED 0
|
|
#define RF4CE_NWK_FCF_CHANNEL_15 1
|
|
#define RF4CE_NWK_FCF_CHANNEL_20 2
|
|
#define RF4CE_NWK_FCF_CHANNEL_25 3
|
|
|
|
static const value_string rf4ce_nwk_channel_designators[] = {
|
|
{ RF4CE_NWK_FCF_CHANNEL_NOT_SPECIFIED, "Channel not specified" },
|
|
{ RF4CE_NWK_FCF_CHANNEL_15, "Channel 15" },
|
|
{ RF4CE_NWK_FCF_CHANNEL_20, "Channel 20" },
|
|
{ RF4CE_NWK_FCF_CHANNEL_25, "Channel 25" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
/* Profile IDs */
|
|
#define RF4CE_NWK_PROFILE_ID_GDP 0x00
|
|
#define RF4CE_NWK_PROFILE_ID_ZRC10 0x01
|
|
#define RF4CE_NWK_PROFILE_ID_ZID 0x02
|
|
#define RF4CE_NWK_PROFILE_ID_ZRC20 0x03
|
|
#define RF4CE_NWK_PROFILE_ID_WILDCARD 0xff
|
|
|
|
/* Vendor IDs */
|
|
#define RF4CE_VENDOR_ID_PANASONIC 0x0001
|
|
#define RF4CE_VENDOR_ID_SONY 0x0002
|
|
#define RF4CE_VENDOR_ID_SAMSUNG 0x0003
|
|
#define RF4CE_VENDOR_ID_PHILIPS 0x0004
|
|
#define RF4CE_VENDOR_ID_FREESCALE 0x0005
|
|
#define RF4CE_VENDOR_ID_OKI 0x0006
|
|
#define RF4CE_VENDOR_ID_TEXAS_INSTRUMENTS 0x0007
|
|
#define RF4CE_VENDOR_ID_TEST_1 0xfff1
|
|
#define RF4CE_VENDOR_ID_TEST_2 0xfff2
|
|
#define RF4CE_VENDOR_ID_TEST_3 0xfff3
|
|
|
|
static const value_string rf4ce_nwk_profile_ids[] = {
|
|
{ RF4CE_NWK_PROFILE_ID_GDP, "GDP" },
|
|
{ RF4CE_NWK_PROFILE_ID_ZRC10, "ZRC 1.0" },
|
|
{ RF4CE_NWK_PROFILE_ID_ZID, "ZID" },
|
|
{ RF4CE_NWK_PROFILE_ID_ZRC20, "ZRC 2.0" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
/* NWK Commands */
|
|
#define RF4CE_NWK_CMD_DISCOVERY_REQ 0x01
|
|
#define RF4CE_NWK_CMD_DISCOVERY_RSP 0x02
|
|
#define RF4CE_NWK_CMD_PAIR_REQ 0x03
|
|
#define RF4CE_NWK_CMD_PAIR_RSP 0x04
|
|
#define RF4CE_NWK_CMD_UNPAIR_REQ 0x05
|
|
#define RF4CE_NWK_CMD_KEY_SEED 0x06
|
|
#define RF4CE_NWK_CMD_PING_REQ 0x07
|
|
#define RF4CE_NWK_CMD_PING_RSP 0x08
|
|
|
|
static const value_string rf4ce_nwk_cmd_names[] = {
|
|
{ RF4CE_NWK_CMD_DISCOVERY_REQ, "Discovery Request" },
|
|
{ RF4CE_NWK_CMD_DISCOVERY_RSP, "Discovery Response" },
|
|
{ RF4CE_NWK_CMD_PAIR_REQ, "Pair Request" },
|
|
{ RF4CE_NWK_CMD_PAIR_RSP, "Pair Response" },
|
|
{ RF4CE_NWK_CMD_UNPAIR_REQ, "Unpair Request" },
|
|
{ RF4CE_NWK_CMD_KEY_SEED, "Key Seed" },
|
|
{ RF4CE_NWK_CMD_PING_REQ, "Ping Request" },
|
|
{ RF4CE_NWK_CMD_PING_RSP, "Ping Response" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
/* NWK Commands - Discovery Request - Node Capabilities */
|
|
#define RF4CE_NWK_NODE_TYPE_MASK 0b00000001
|
|
#define RF4CE_NWK_POWER_SOURCE_MASK 0b00000010
|
|
#define RF4CE_NWK_SECURITY_MASK 0b00000100
|
|
#define RF4CE_NWK_CHANNEL_NORMALIZATION_MASK 0b00001000
|
|
#define RF4CE_NWK_RESERVED_MASK 0b11110000
|
|
|
|
#define RF4CE_NWK_NODE_TYPE_CONTROLLER 0
|
|
#define RF4CE_NWK_NODE_TYPE_TARGET 1
|
|
|
|
static const value_string rf4ce_nwk_node_types[] = {
|
|
{ RF4CE_NWK_NODE_TYPE_CONTROLLER, "Controller" },
|
|
{ RF4CE_NWK_NODE_TYPE_TARGET, "Target" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
#define RF4CE_NWK_POWER_SOURCE_NO_ALTERNATING_CURRENT_MAINS 0
|
|
#define RF4CE_NWK_POWER_SOURCE_ALTERNATING_CURRENT_MAINS 1
|
|
|
|
static const value_string rf4ce_nwk_power_sources[] = {
|
|
{ RF4CE_NWK_POWER_SOURCE_NO_ALTERNATING_CURRENT_MAINS, "No Alternating Current Mains" },
|
|
{ RF4CE_NWK_POWER_SOURCE_ALTERNATING_CURRENT_MAINS, "Alternating Current Mains" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
#define RF4CE_DISC_REQ_VENDOR_ID_TEXAS_INSTRUMENTS 0x0007
|
|
static const value_string rf4ce_disc_req_vendor_ids[] = {
|
|
{ RF4CE_DISC_REQ_VENDOR_ID_TEXAS_INSTRUMENTS, "Texas Instruments" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
/* NWK Commands - Discovery Request - App Capabilities */
|
|
#define RF4CE_NWK_USR_STR_SPECIFIED_MASK 0b00000001
|
|
#define RF4CE_NWK_SUPPORTED_DEV_NUM_MASK 0b00000110
|
|
#define RF4CE_NWK_RESERVED1_MASK 0b00001000
|
|
#define RF4CE_NWK_SUPPORTED_PROFILES_NUM_MASK 0b01110000
|
|
#define RF4CE_NWK_RESERVED2_MASK 0b10000000
|
|
|
|
#define RF4CE_NWK_USR_STR_LENGTH 15
|
|
#define RF4CE_NWK_SUPPORTED_DEV_NUM_OFFSET 1
|
|
#define RF4CE_NWK_SUPPORTED_PROFILES_NUM_OFFSET 4
|
|
|
|
/* NWK Commands - Discovery Request - Device Types */
|
|
#define RF4CE_DEVICE_RESERVED_INVALID 0x00
|
|
#define RF4CE_DEVICE_REMOTE_CONTROL 0x01
|
|
#define RF4CE_DEVICE_TELEVISION 0x02
|
|
#define RF4CE_DEVICE_PROJECTOR 0x03
|
|
#define RF4CE_DEVICE_PLAYER 0x04
|
|
#define RF4CE_DEVICE_RECORDER 0x05
|
|
#define RF4CE_DEVICE_VIDEO_PLAYER_RECORDER 0x06
|
|
#define RF4CE_DEVICE_AUDIO_PLAYER_RECORDER 0x07
|
|
#define RF4CE_DEVICE_AUDIO_VIDEO_RECORDER 0x08
|
|
#define RF4CE_DEVICE_SET_TOP_BOX 0x09
|
|
#define RF4CE_DEVICE_HOME_THEATER_SYSTEM 0x0a
|
|
#define RF4CE_DEVICE_MEDIA_CENTER_PC 0x0b
|
|
#define RF4CE_DEVICE_GAME_CONSOLE 0x0c
|
|
#define RF4CE_DEVICE_SATELLITE_RADIO_RECEIVER 0x0d
|
|
#define RF4CE_DEVICE_IR_EXTENDER 0x0e
|
|
#define RF4CE_DEVICE_MONITOR 0x0f
|
|
#define RF4CE_DEVICE_ALL_DEVICES 0xff
|
|
|
|
static const value_string rf4ce_nwk_device_type_vals[] = {
|
|
{ RF4CE_DEVICE_RESERVED_INVALID, "Invalid" },
|
|
{ RF4CE_DEVICE_REMOTE_CONTROL, "Remote Control" },
|
|
{ RF4CE_DEVICE_TELEVISION, "Television" },
|
|
{ RF4CE_DEVICE_PROJECTOR, "Projector" },
|
|
{ RF4CE_DEVICE_PLAYER, "Player" },
|
|
{ RF4CE_DEVICE_RECORDER, "Recorder" },
|
|
{ RF4CE_DEVICE_VIDEO_PLAYER_RECORDER, "Video Player Recorder" },
|
|
{ RF4CE_DEVICE_AUDIO_PLAYER_RECORDER, "Audio Player Recorder" },
|
|
{ RF4CE_DEVICE_AUDIO_VIDEO_RECORDER, "Audio Video Recorder" },
|
|
{ RF4CE_DEVICE_SET_TOP_BOX, "Set Top Box" },
|
|
{ RF4CE_DEVICE_HOME_THEATER_SYSTEM, "Home Theater System" },
|
|
{ RF4CE_DEVICE_MEDIA_CENTER_PC, "Media Center PC" },
|
|
{ RF4CE_DEVICE_GAME_CONSOLE, "Game Console" },
|
|
{ RF4CE_DEVICE_SATELLITE_RADIO_RECEIVER, "Satellite Radio Receiver" },
|
|
{ RF4CE_DEVICE_IR_EXTENDER, "IR Extender" },
|
|
{ RF4CE_DEVICE_MONITOR, "Monitor" },
|
|
{ RF4CE_DEVICE_ALL_DEVICES, "All the Devices" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
#define RF4CE_NWK_STATUS_SUCCESS 0x00
|
|
#define RF4CE_NWK_STATUS_NO_ORG_CAPACITY 0xb0
|
|
#define RF4CE_NWK_STATUS_NO_REC_CAPACITY 0xb1
|
|
#define RF4CE_NWK_STATUS_NO_PAIRING 0xb2
|
|
#define RF4CE_NWK_STATUS_NO_RESPONSE 0xb3
|
|
#define RF4CE_NWK_STATUS_NOT_PERMITTED 0xb4
|
|
#define RF4CE_NWK_STATUS_DUPLICATE_PAIRING 0xb5
|
|
#define RF4CE_NWK_STATUS_FRAME_COUNTER_EXPIRED 0xb6
|
|
#define RF4CE_NWK_STATUS_DISCOVERY_ERROR 0xb7
|
|
#define RF4CE_NWK_STATUS_DISCOVERY_TIMEOUT 0xb8
|
|
#define RF4CE_NWK_STATUS_SECURITY_TIMEOUT 0xb9
|
|
#define RF4CE_NWK_STATUS_SECURITY_FAILURE 0xba
|
|
#define RF4CE_NWK_STATUS_INVALID_PARAMETER 0xe8
|
|
#define RF4CE_NWK_STATUS_UNSUPPORTED_ATTRIBUTE 0xf4
|
|
#define RF4CE_NWK_STATUS_INVALID_INDEX 0xf9
|
|
|
|
static const value_string rf4ce_nwk_disc_status_vals[] = {
|
|
{ RF4CE_NWK_STATUS_SUCCESS, "Success" },
|
|
{ RF4CE_NWK_STATUS_NO_ORG_CAPACITY, "No Org Capacity" },
|
|
{ RF4CE_NWK_STATUS_NO_REC_CAPACITY, "No Rec Capacity" },
|
|
{ RF4CE_NWK_STATUS_NO_PAIRING, "No Pairing" },
|
|
{ RF4CE_NWK_STATUS_NO_RESPONSE, "No Response" },
|
|
{ RF4CE_NWK_STATUS_NOT_PERMITTED, "Not Permitted" },
|
|
{ RF4CE_NWK_STATUS_DUPLICATE_PAIRING, "Duplicate Pairing" },
|
|
{ RF4CE_NWK_STATUS_FRAME_COUNTER_EXPIRED, "Frame Counter Expired" },
|
|
{ RF4CE_NWK_STATUS_DISCOVERY_ERROR, "Discovery Error" },
|
|
{ RF4CE_NWK_STATUS_DISCOVERY_TIMEOUT, "Discovery Timeout" },
|
|
{ RF4CE_NWK_STATUS_SECURITY_TIMEOUT, "Security Timeout" },
|
|
{ RF4CE_NWK_STATUS_SECURITY_FAILURE, "Security Failure" },
|
|
{ RF4CE_NWK_STATUS_INVALID_PARAMETER, "Invalid Parameter" },
|
|
{ RF4CE_NWK_STATUS_UNSUPPORTED_ATTRIBUTE, "Unsupported Attribute" },
|
|
{ RF4CE_NWK_STATUS_INVALID_INDEX, "Invalid Index" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static gboolean dissect_rf4ce_nwk_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data);
|
|
|
|
/* RF4CE NWK commands dissectors */
|
|
static int dissect_rf4ce_nwk_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_);
|
|
|
|
static void dissect_rf4ce_nwk_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset);
|
|
|
|
static void dissect_rf4ce_nwk_common_node_capabilities(tvbuff_t *tvb, proto_tree *tree, gint *offset);
|
|
static void dissect_rf4ce_nwk_common_vendor_info(tvbuff_t *tvb, proto_tree *tree, gint *offset);
|
|
static void dissect_rf4ce_nwk_common_app_capabilities(tvbuff_t *tvb, proto_tree *tree, gint *offset, guint8 parsing_mask);
|
|
static void dissect_rf4ce_nwk_disc_resp_class_descriptor(tvbuff_t *tvb, proto_tree *tree, gint *offset, int hf);
|
|
|
|
static void dissect_rf4ce_nwk_cmd_disc_req(tvbuff_t *tvb, proto_tree *tree, gint *offset);
|
|
static void dissect_rf4ce_nwk_cmd_disc_rsp(tvbuff_t *tvb, proto_tree *tree, gint *offset);
|
|
|
|
static void dissect_rf4ce_nwk_cmd_pair_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset);
|
|
static void dissect_rf4ce_nwk_cmd_pair_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset);
|
|
|
|
static void dissect_rf4ce_nwk_cmd_key_seed(tvbuff_t *tvb, proto_tree *tree, gint *offset);
|
|
|
|
static void dissect_rf4ce_nwk_cmd_ping(tvbuff_t *tvb, proto_tree *tree, gint *offset);
|
|
|
|
static void rf4ce_cleanup(void)
|
|
{
|
|
rf4ce_secur_cleanup();
|
|
}
|
|
|
|
static void *uat_sec_record_copy_cb(void *n, const void *o, size_t siz _U_)
|
|
{
|
|
uat_security_record_t *new_sec_rec = (uat_security_record_t *)n;
|
|
const uat_security_record_t *old_sec_rec = (const uat_security_record_t *)o;
|
|
|
|
new_sec_rec->sec_str = g_strdup(old_sec_rec->sec_str);
|
|
new_sec_rec->type = old_sec_rec->type;
|
|
new_sec_rec->label = g_strdup(old_sec_rec->label);
|
|
|
|
return new_sec_rec;
|
|
}
|
|
|
|
static gboolean rf4ce_security_parse_sec_str(const gchar *data_str, guint8 *dst_buf)
|
|
{
|
|
int i, j;
|
|
gchar temp;
|
|
gboolean string_mode = FALSE;
|
|
|
|
if (data_str == NULL || dst_buf == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Clear the key. */
|
|
memset(dst_buf, 0, SEC_STR_LEN);
|
|
|
|
/*
|
|
* Attempt to parse the key string. The key string must
|
|
* be at least 16 pairs of hexidecimal digits with the
|
|
* following optional separators: ':', '-', " ", or 16
|
|
* alphanumeric characters after a double-quote.
|
|
*/
|
|
temp = *data_str++;
|
|
if (temp == '"')
|
|
{
|
|
string_mode = TRUE;
|
|
temp = *data_str++;
|
|
}
|
|
|
|
j = 0;
|
|
for (i = SEC_STR_LEN - 1; i >= 0; i--)
|
|
{
|
|
if (string_mode)
|
|
{
|
|
if (g_ascii_isprint(temp))
|
|
{
|
|
dst_buf[j] = temp;
|
|
temp = *data_str++;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* If this character is a separator, skip it. */
|
|
if ((temp == ':') || (temp == '-') || (temp == ' '))
|
|
{
|
|
temp = *(data_str++);
|
|
}
|
|
|
|
/* Process a nibble. */
|
|
if (g_ascii_isxdigit(temp))
|
|
{
|
|
dst_buf[j] = g_ascii_xdigit_value(temp) << 4;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Get the next nibble. */
|
|
temp = *(data_str++);
|
|
|
|
/* Process another nibble. */
|
|
if (g_ascii_isxdigit(temp))
|
|
{
|
|
dst_buf[j] |= g_ascii_xdigit_value(temp);
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Get the next nibble. */
|
|
temp = *(data_str++);
|
|
}
|
|
|
|
j++;
|
|
} /* for */
|
|
|
|
/* If we get this far, then the key was good. */
|
|
return TRUE;
|
|
}
|
|
|
|
static bool uat_sec_record_update_cb(void *r, char **err)
|
|
{
|
|
uat_security_record_t *rec = (uat_security_record_t *)r;
|
|
guint8 sec_str[SEC_STR_LEN] = {0};
|
|
|
|
if (rec->sec_str == NULL)
|
|
{
|
|
*err = g_strdup("Data field can't be blank");
|
|
return FALSE;
|
|
}
|
|
|
|
g_strstrip(rec->sec_str);
|
|
|
|
if (rf4ce_security_parse_sec_str(rec->sec_str, sec_str))
|
|
{
|
|
*err = NULL;
|
|
|
|
if (rec->type == RF4CE_SEC_STR_TYPE_NWK_KEY)
|
|
{
|
|
nwk_key_storage_add_entry(
|
|
sec_str,
|
|
NULL, /* controller addr */
|
|
NULL, /* target addr */
|
|
TRUE, /* key from GUI */
|
|
FALSE /* packet number */);
|
|
|
|
vendor_secret_storage_release_entry(sec_str);
|
|
}
|
|
else
|
|
{
|
|
vendor_secret_storage_add_entry(sec_str);
|
|
nwk_key_storage_release_entry(sec_str, TRUE /* key from GUI */);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*err = ws_strdup_printf(
|
|
"Expecting %d hexadecimal bytes or a %d character double-quoted string", SEC_STR_LEN, SEC_STR_LEN);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void uat_sec_record_free_cb(void *r)
|
|
{
|
|
uat_security_record_t *sec_record = (uat_security_record_t *)r;
|
|
guint8 sec_str[SEC_STR_LEN];
|
|
|
|
if (rf4ce_security_parse_sec_str(sec_record->sec_str, sec_str))
|
|
{
|
|
if (sec_record->type == RF4CE_SEC_STR_TYPE_NWK_KEY)
|
|
{
|
|
nwk_key_storage_release_entry(sec_str, TRUE /* key from GUI */);
|
|
}
|
|
else
|
|
{
|
|
vendor_secret_storage_release_entry(sec_str);
|
|
}
|
|
}
|
|
|
|
g_free(sec_record->sec_str);
|
|
g_free(sec_record->label);
|
|
}
|
|
|
|
static void uat_sec_record_post_update(void)
|
|
{
|
|
guint8 sec_str[SEC_STR_LEN];
|
|
|
|
vendor_secret_storage_add_entry(DEFAULT_SECRET);
|
|
|
|
/* Load the pre-configured slist from the UAT. */
|
|
for (guint i = 0; (uat_security_records) && (i < num_uat_security_records); i++)
|
|
{
|
|
if (rf4ce_security_parse_sec_str(uat_security_records[i].sec_str, sec_str))
|
|
{
|
|
if (uat_security_records[i].type == RF4CE_SEC_STR_TYPE_NWK_KEY)
|
|
{
|
|
nwk_key_storage_add_entry(
|
|
sec_str,
|
|
NULL, /* controller addr */
|
|
NULL, /* target addr */
|
|
TRUE, /* key from GUI */
|
|
FALSE /* packet number */);
|
|
|
|
vendor_secret_storage_release_entry(sec_str);
|
|
}
|
|
else
|
|
{
|
|
vendor_secret_storage_add_entry(sec_str);
|
|
nwk_key_storage_release_entry(sec_str, TRUE /* key from GUI */);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static gboolean dissect_rf4ce_nwk_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
|
{
|
|
guint reported_length = tvb_reported_length(tvb);
|
|
guint length = tvb_captured_length(tvb);
|
|
guint8 fcf;
|
|
guint8 frame_type;
|
|
guint8 security_enabled;
|
|
guint8 reserved;
|
|
guint8 profile_id;
|
|
guint16 vendor_id;
|
|
guint8 command_id;
|
|
|
|
if (reported_length >= RF4CE_MIN_NWK_LENGTH && reported_length <= RF4CE_MAX_NWK_LENGTH)
|
|
{
|
|
if (length < RF4CE_MIN_NWK_LENGTH)
|
|
{
|
|
return FALSE;
|
|
}
|
|
fcf = tvb_get_guint8(tvb, 0);
|
|
frame_type = fcf & RF4CE_NWK_FCF_FRAME_TYPE_MASK;
|
|
security_enabled = fcf & RF4CE_NWK_FCF_SECURITY_MASK;
|
|
reserved = (fcf & RF4CE_NWK_FCF_RESERVED_MASK) >> 5;
|
|
|
|
switch (frame_type)
|
|
{
|
|
case RF4CE_NWK_FCF_FRAME_TYPE_DATA:
|
|
case RF4CE_NWK_FCF_FRAME_TYPE_CMD:
|
|
case RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC:
|
|
/* Accepted frame types */
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
/* Reserved value must be 1 */
|
|
if (reserved != 1)
|
|
{
|
|
return FALSE;
|
|
}
|
|
if((frame_type == RF4CE_NWK_FCF_FRAME_TYPE_DATA) || (frame_type == RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC))
|
|
{
|
|
if (length < 6)
|
|
{
|
|
return FALSE;
|
|
}
|
|
profile_id = tvb_get_guint8(tvb, 5);
|
|
if ((profile_id >= 0x04) && (profile_id <= 0xbf))
|
|
{
|
|
return FALSE;
|
|
}
|
|
if (frame_type == RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC)
|
|
{
|
|
if (length < 8)
|
|
{
|
|
return FALSE;
|
|
}
|
|
vendor_id = tvb_get_letohs(tvb, 6);
|
|
switch (vendor_id)
|
|
{
|
|
case RF4CE_VENDOR_ID_PANASONIC:
|
|
case RF4CE_VENDOR_ID_SONY:
|
|
case RF4CE_VENDOR_ID_SAMSUNG:
|
|
case RF4CE_VENDOR_ID_PHILIPS:
|
|
case RF4CE_VENDOR_ID_FREESCALE:
|
|
case RF4CE_VENDOR_ID_OKI:
|
|
case RF4CE_VENDOR_ID_TEXAS_INSTRUMENTS:
|
|
case RF4CE_VENDOR_ID_TEST_1:
|
|
case RF4CE_VENDOR_ID_TEST_2:
|
|
case RF4CE_VENDOR_ID_TEST_3:
|
|
/* Allowed vendor IDs */
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
else if(frame_type == RF4CE_NWK_FCF_FRAME_TYPE_CMD)
|
|
{
|
|
if (length < 6)
|
|
{
|
|
return FALSE;
|
|
}
|
|
/* If security is enabled, the command ID will be encrypted */
|
|
if (!security_enabled)
|
|
{
|
|
command_id = tvb_get_guint8(tvb, 5);
|
|
switch (command_id)
|
|
{
|
|
case RF4CE_NWK_CMD_DISCOVERY_REQ:
|
|
case RF4CE_NWK_CMD_DISCOVERY_RSP:
|
|
case RF4CE_NWK_CMD_PAIR_REQ:
|
|
case RF4CE_NWK_CMD_PAIR_RSP:
|
|
case RF4CE_NWK_CMD_UNPAIR_REQ:
|
|
case RF4CE_NWK_CMD_KEY_SEED:
|
|
case RF4CE_NWK_CMD_PING_REQ:
|
|
case RF4CE_NWK_CMD_PING_RSP:
|
|
/* Allowed command IDs */
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "RF4CE NWK");
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
|
|
|
dissect_rf4ce_nwk_common(tvb, pinfo, tree, data);
|
|
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static int dissect_rf4ce_nwk_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
|
{
|
|
guint offset = 0;
|
|
gboolean success;
|
|
guint8 *decrypted = (guint8 *)wmem_alloc(pinfo->pool, 512);
|
|
guint8 src_addr[RF4CE_IEEE_ADDR_LEN] = {0};
|
|
guint8 dst_addr[RF4CE_IEEE_ADDR_LEN] = {0};
|
|
|
|
guint8 fcf = 0xff;
|
|
guint8 frame_type = 0xff;
|
|
guint8 profile_id = 0xff;
|
|
guint16 size;
|
|
|
|
proto_item *ti = proto_tree_add_item(tree, proto_rf4ce_nwk, tvb, 0, -1, ENC_LITTLE_ENDIAN);
|
|
proto_tree *rf4ce_nwk_tree = proto_item_add_subtree(ti, ett_rf4ce_nwk);
|
|
|
|
static int *const nwk_fcf_bits[] = {
|
|
&hf_rf4ce_nwk_fcf_frame_type,
|
|
&hf_rf4ce_nwk_fcf_security_enabled,
|
|
&hf_rf4ce_nwk_fcf_protocol_version,
|
|
&hf_rf4ce_nwk_fcf_reserved,
|
|
&hf_rf4ce_nwk_fcf_channel_designator,
|
|
NULL};
|
|
|
|
proto_tree_add_bitmask(rf4ce_nwk_tree, tvb, offset, hf_rf4ce_nwk_fcf, ett_rf4ce_nwk, nwk_fcf_bits, ENC_LITTLE_ENDIAN);
|
|
fcf = tvb_get_guint8(tvb, offset);
|
|
offset += 1;
|
|
|
|
proto_tree_add_item(rf4ce_nwk_tree, hf_rf4ce_nwk_seq_num, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
|
|
frame_type = fcf & RF4CE_NWK_FCF_FRAME_TYPE_MASK;
|
|
|
|
if (frame_type == RF4CE_NWK_FCF_FRAME_TYPE_DATA || frame_type == RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC)
|
|
{
|
|
proto_tree_add_item(rf4ce_nwk_tree, hf_rf4ce_nwk_profile_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
profile_id = tvb_get_guint8(tvb, offset);
|
|
offset += 1;
|
|
}
|
|
|
|
if (frame_type == RF4CE_NWK_FCF_FRAME_TYPE_VENDOR_SPECIFIC)
|
|
{
|
|
proto_tree_add_item(rf4ce_nwk_tree, hf_rf4ce_nwk_vendor_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
|
offset += 2;
|
|
}
|
|
|
|
rf4ce_addr_table_get_ieee_addr(src_addr, pinfo, TRUE);
|
|
rf4ce_addr_table_get_ieee_addr(dst_addr, pinfo, FALSE);
|
|
|
|
size = tvb_captured_length_remaining(tvb, 0);
|
|
|
|
if (fcf & RF4CE_NWK_FCF_SECURITY_MASK)
|
|
{
|
|
success = decrypt_data(
|
|
tvb_get_ptr(tvb, 0, size),
|
|
decrypted,
|
|
offset,
|
|
&size,
|
|
src_addr,
|
|
dst_addr);
|
|
}
|
|
else if (size > offset)
|
|
{
|
|
size -= offset;
|
|
tvb_memcpy(tvb, decrypted, offset, size);
|
|
success = TRUE;
|
|
}
|
|
else
|
|
{
|
|
success = FALSE;
|
|
}
|
|
|
|
if (success)
|
|
{
|
|
guint decrypted_offset = 0;
|
|
|
|
/* On decryption success: replace the tvb, make offset point to its beginning */
|
|
tvb = tvb_new_child_real_data(tvb, decrypted, size, size);
|
|
add_new_data_source(pinfo, tvb, "CCM* decrypted payload");
|
|
|
|
if (frame_type == RF4CE_NWK_FCF_FRAME_TYPE_CMD)
|
|
{
|
|
proto_tree *nwk_payload_tree = proto_tree_add_subtree(rf4ce_nwk_tree, tvb, decrypted_offset, tvb_captured_length(tvb) - decrypted_offset, ett_rf4ce_nwk_payload, NULL, "NWK Payload");
|
|
dissect_rf4ce_nwk_cmd(tvb, pinfo, nwk_payload_tree, &decrypted_offset);
|
|
}
|
|
else if (frame_type == RF4CE_NWK_FCF_FRAME_TYPE_DATA)
|
|
{
|
|
if (profile_id == RF4CE_NWK_PROFILE_ID_GDP)
|
|
{
|
|
decrypted_offset += call_dissector_with_data(rf4ce_gdp_handle, tvb, pinfo, tree, (void *)("GDP"));
|
|
}
|
|
else if (profile_id == RF4CE_NWK_PROFILE_ID_ZRC20)
|
|
{
|
|
decrypted_offset += call_dissector_with_data(rf4ce_gdp_handle, tvb, pinfo, tree, (void *)("ZRC 2.0"));
|
|
}
|
|
else if (profile_id == RF4CE_NWK_PROFILE_ID_ZRC10)
|
|
{
|
|
decrypted_offset += call_dissector_with_data(rf4ce_gdp_handle, tvb, pinfo, tree, (void *)("ZRC 1.0"));
|
|
}
|
|
}
|
|
|
|
offset += decrypted_offset;
|
|
}
|
|
else
|
|
{
|
|
/* On decryption error: make offset point to the end of original tvb */
|
|
offset = tvb_reported_length(tvb);
|
|
}
|
|
|
|
if (offset < tvb_captured_length(tvb))
|
|
{
|
|
guint unparsed_length = tvb_captured_length(tvb) - offset;
|
|
proto_tree_add_item(rf4ce_nwk_tree, hf_rf4ce_nwk_unparsed_payload, tvb, offset, unparsed_length, ENC_NA);
|
|
#if 0
|
|
/* enable this block if you need to add NWK MIC */
|
|
offset += unparsed_length;
|
|
#endif
|
|
}
|
|
|
|
#if 0
|
|
if (fcf & RF4CE_NWK_FCF_SECURITY_MASK)
|
|
{
|
|
proto_tree_add_item(rf4ce_nwk_tree, hf_rf4ce_nwk_mic, tvb, offset, 4, ENC_LITTLE_ENDIAN);
|
|
offset += 4;
|
|
}
|
|
#endif
|
|
|
|
return tvb_captured_length(tvb);
|
|
}
|
|
|
|
static void dissect_rf4ce_nwk_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset)
|
|
{
|
|
gint cmd_id = tvb_get_guint8(tvb, *offset);
|
|
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_cmd_id, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
|
|
*offset += 1;
|
|
|
|
col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(cmd_id, rf4ce_nwk_cmd_names, "Unknown Command"));
|
|
|
|
switch (cmd_id)
|
|
{
|
|
case RF4CE_NWK_CMD_DISCOVERY_REQ:
|
|
dissect_rf4ce_nwk_cmd_disc_req(tvb, tree, offset);
|
|
break;
|
|
|
|
case RF4CE_NWK_CMD_DISCOVERY_RSP:
|
|
dissect_rf4ce_nwk_cmd_disc_rsp(tvb, tree, offset);
|
|
break;
|
|
|
|
case RF4CE_NWK_CMD_PAIR_REQ:
|
|
dissect_rf4ce_nwk_cmd_pair_req(tvb, pinfo, tree, offset);
|
|
break;
|
|
|
|
case RF4CE_NWK_CMD_PAIR_RSP:
|
|
dissect_rf4ce_nwk_cmd_pair_rsp(tvb, pinfo, tree, offset);
|
|
break;
|
|
|
|
case RF4CE_NWK_CMD_UNPAIR_REQ:
|
|
break;
|
|
|
|
case RF4CE_NWK_CMD_KEY_SEED:
|
|
dissect_rf4ce_nwk_cmd_key_seed(tvb, tree, offset);
|
|
break;
|
|
|
|
case RF4CE_NWK_CMD_PING_REQ:
|
|
dissect_rf4ce_nwk_cmd_ping(tvb, tree, offset);
|
|
break;
|
|
|
|
case RF4CE_NWK_CMD_PING_RSP:
|
|
dissect_rf4ce_nwk_cmd_ping(tvb, tree, offset);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void dissect_rf4ce_nwk_common_node_capabilities(tvbuff_t *tvb, proto_tree *tree, gint *offset)
|
|
{
|
|
static int *const nwk_node_capabilities_bits[] = {
|
|
&hf_rf4ce_nwk_node_capabilities_node_type,
|
|
&hf_rf4ce_nwk_node_capabilities_power_source,
|
|
&hf_rf4ce_nwk_node_capabilities_security,
|
|
&hf_rf4ce_nwk_node_capabilities_channel_normalization,
|
|
&hf_rf4ce_nwk_node_capabilities_reserved,
|
|
NULL};
|
|
|
|
proto_tree_add_bitmask(tree, tvb, *offset, hf_rf4ce_nwk_node_capabilities, ett_rf4ce_nwk, nwk_node_capabilities_bits, ENC_LITTLE_ENDIAN);
|
|
*offset += 1;
|
|
}
|
|
|
|
static void dissect_rf4ce_nwk_common_vendor_info(tvbuff_t *tvb, proto_tree *tree, gint *offset)
|
|
{
|
|
proto_tree *vendor_info_tree = proto_tree_add_subtree(tree, tvb, *offset, tvb_captured_length(tvb) - *offset, ett_rf4ce_nwk_vendor_info, NULL, "Vendor Information Fields");
|
|
|
|
proto_tree_add_item(vendor_info_tree, hf_rf4ce_nwk_disc_req_vendor_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
|
|
*offset += 2;
|
|
|
|
proto_tree_add_item(vendor_info_tree, hf_rf4ce_nwk_vendor_string, tvb, *offset, RF4CE_NWK_VENDOR_STRING_MAX_LENGTH, ENC_UTF_8);
|
|
*offset += RF4CE_NWK_VENDOR_STRING_MAX_LENGTH;
|
|
}
|
|
|
|
static void dissect_rf4ce_nwk_common_app_capabilities(tvbuff_t *tvb, proto_tree *tree, gint *offset, guint8 parsing_mask)
|
|
{
|
|
int nwk_app_capabilities = 0;
|
|
int supported_devices_num = 0;
|
|
int supported_profiles_num = 0;
|
|
|
|
static int *const nwk_app_capabilities_bits[] = {
|
|
&hf_rf4ce_nwk_app_capabilities_usr_str,
|
|
&hf_rf4ce_nwk_app_capabilities_supported_dev_num,
|
|
&hf_rf4ce_nwk_app_capabilities_reserved1,
|
|
&hf_rf4ce_nwk_app_capabilities_supported_profiles_num,
|
|
&hf_rf4ce_nwk_app_capabilities_reserved2,
|
|
NULL};
|
|
|
|
proto_tree_add_bitmask(tree, tvb, *offset, hf_rf4ce_nwk_app_capabilities, ett_rf4ce_nwk, nwk_app_capabilities_bits, ENC_LITTLE_ENDIAN);
|
|
nwk_app_capabilities = tvb_get_guint8(tvb, *offset);
|
|
*offset += 1;
|
|
|
|
if (nwk_app_capabilities & RF4CE_NWK_USR_STR_SPECIFIED_MASK)
|
|
{
|
|
if (parsing_mask & RF4CE_NWK_USR_STR_PARSING_MASK_DISC_RESP)
|
|
{
|
|
proto_tree *usr_str_tree = proto_tree_add_subtree(tree, tvb, *offset, RF4CE_NWK_USR_STR_LENGTH, ett_rf4ce_nwk_usr_str, NULL, "Extra Status Information");
|
|
|
|
proto_tree_add_item(usr_str_tree, hf_rf4ce_nwk_usr_str_disc_rsp_app_usr_str, tvb, *offset, RF4CE_NWK_USR_STR_DISC_RSP_APP_USR_STR_LENGTH, ENC_UTF_8);
|
|
/* -1: to show the NULL-terminator byte in a tree */
|
|
*offset += RF4CE_NWK_USR_STR_DISC_RSP_APP_USR_STR_LENGTH - 1;
|
|
|
|
proto_tree_add_item(usr_str_tree, hf_rf4ce_nwk_usr_str_disc_rsp_null, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
|
|
*offset += 1;
|
|
|
|
proto_tree_add_item(usr_str_tree, hf_rf4ce_nwk_usr_str_disc_rsp_reserved, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
|
|
*offset += 2;
|
|
|
|
dissect_rf4ce_nwk_disc_resp_class_descriptor(tvb, usr_str_tree, offset, hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_tertiary);
|
|
dissect_rf4ce_nwk_disc_resp_class_descriptor(tvb, usr_str_tree, offset, hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_secondary);
|
|
dissect_rf4ce_nwk_disc_resp_class_descriptor(tvb, usr_str_tree, offset, hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_primary);
|
|
|
|
proto_tree_add_item(usr_str_tree, hf_rf4ce_nwk_usr_str_disc_rsp_discovery_lqi_threshold, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
|
|
*offset += 1;
|
|
}
|
|
else
|
|
{
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_usr_str, tvb, *offset, RF4CE_NWK_USR_STR_LENGTH, ENC_NA);
|
|
*offset += RF4CE_NWK_USR_STR_LENGTH;
|
|
}
|
|
}
|
|
|
|
supported_devices_num = ((nwk_app_capabilities & RF4CE_NWK_SUPPORTED_DEV_NUM_MASK) >> RF4CE_NWK_SUPPORTED_DEV_NUM_OFFSET);
|
|
if (supported_devices_num > 0)
|
|
{
|
|
proto_tree *dev_type_tree = proto_tree_add_subtree(tree, tvb, *offset, supported_devices_num, ett_rf4ce_nwk_dev_types_list, NULL, "Device Type List");
|
|
|
|
for (int i = 0; i < supported_devices_num; i++)
|
|
{
|
|
proto_tree_add_item(dev_type_tree, hf_rf4ce_nwk_app_cap_dev_type, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
|
|
*offset += 1;
|
|
}
|
|
}
|
|
|
|
supported_profiles_num = ((nwk_app_capabilities & RF4CE_NWK_SUPPORTED_PROFILES_NUM_MASK) >> RF4CE_NWK_SUPPORTED_PROFILES_NUM_OFFSET);
|
|
if (supported_profiles_num > 0)
|
|
{
|
|
proto_tree *profiles_tree = proto_tree_add_subtree(tree, tvb, *offset, supported_profiles_num, ett_rf4ce_nwk_profiles_list, NULL, "Profiles ID List");
|
|
|
|
for (int i = 0; i < supported_profiles_num; i++)
|
|
{
|
|
proto_tree_add_item(profiles_tree, hf_rf4ce_nwk_app_cap_profile_id, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
|
|
*offset += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void dissect_rf4ce_nwk_disc_resp_class_descriptor(tvbuff_t *tvb, proto_tree *tree, gint *offset, int hf)
|
|
{
|
|
static int *const class_num_bits[] = {
|
|
&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_class_num,
|
|
&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_duplicate_class_num_handling,
|
|
&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_reserved,
|
|
NULL};
|
|
|
|
proto_tree_add_bitmask(tree, tvb, *offset, hf, ett_rf4ce_nwk_usr_str_class_descriptor, class_num_bits, ENC_LITTLE_ENDIAN);
|
|
*offset += 1;
|
|
}
|
|
|
|
static void dissect_rf4ce_nwk_cmd_disc_req(tvbuff_t *tvb, proto_tree *tree, gint *offset)
|
|
{
|
|
dissect_rf4ce_nwk_common_node_capabilities(tvb, tree, offset);
|
|
dissect_rf4ce_nwk_common_vendor_info(tvb, tree, offset);
|
|
dissect_rf4ce_nwk_common_app_capabilities(tvb, tree, offset, RF4CE_NWK_USR_STR_PARSING_MASK_NONE);
|
|
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_requested_dev_type, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
|
|
*offset += 1;
|
|
}
|
|
|
|
static void dissect_rf4ce_nwk_cmd_disc_rsp(tvbuff_t *tvb, proto_tree *tree, gint *offset)
|
|
{
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_disc_resp_status, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
|
|
*offset += 1;
|
|
|
|
dissect_rf4ce_nwk_common_node_capabilities(tvb, tree, offset);
|
|
dissect_rf4ce_nwk_common_vendor_info(tvb, tree, offset);
|
|
dissect_rf4ce_nwk_common_app_capabilities(tvb, tree, offset, RF4CE_NWK_USR_STR_PARSING_MASK_DISC_RESP);
|
|
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_disc_resp_lqi, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
|
|
*offset += 1;
|
|
}
|
|
|
|
static void dissect_rf4ce_nwk_cmd_pair_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset)
|
|
{
|
|
guint8 expected_transfer_count;
|
|
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_pair_req_nwk_addr, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
|
|
*offset += 2;
|
|
|
|
dissect_rf4ce_nwk_common_node_capabilities(tvb, tree, offset);
|
|
dissect_rf4ce_nwk_common_vendor_info(tvb, tree, offset);
|
|
dissect_rf4ce_nwk_common_app_capabilities(tvb, tree, offset, RF4CE_NWK_USR_STR_PARSING_MASK_NONE);
|
|
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_pair_req_key_exch_num, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
expected_transfer_count = tvb_get_guint8(tvb, *offset) + 1;
|
|
keypair_context_init((const guint8 *)pinfo->dl_src.data, (const guint8 *)pinfo->dl_dst.data, expected_transfer_count);
|
|
*offset += 1;
|
|
}
|
|
|
|
static void dissect_rf4ce_nwk_cmd_pair_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint *offset)
|
|
{
|
|
guint16 allocated_nwk_addr;
|
|
guint16 nwk_addr;
|
|
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_pair_rsp_status, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
|
|
*offset += 1;
|
|
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_pair_rsp_allocated_nwk_addr, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
|
|
allocated_nwk_addr = tvb_get_guint16(tvb, *offset, ENC_LITTLE_ENDIAN);
|
|
*offset += 2;
|
|
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_pair_rsp_nwk_addr, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
|
|
nwk_addr = tvb_get_guint16(tvb, *offset, ENC_LITTLE_ENDIAN);
|
|
*offset += 2;
|
|
|
|
dissect_rf4ce_nwk_common_node_capabilities(tvb, tree, offset);
|
|
dissect_rf4ce_nwk_common_vendor_info(tvb, tree, offset);
|
|
dissect_rf4ce_nwk_common_app_capabilities(tvb, tree, offset, RF4CE_NWK_USR_STR_PARSING_MASK_NONE);
|
|
|
|
rf4ce_addr_table_add_addrs(pinfo->dl_dst.data, allocated_nwk_addr);
|
|
rf4ce_addr_table_add_addrs(pinfo->dl_src.data, nwk_addr);
|
|
}
|
|
|
|
static void dissect_rf4ce_nwk_cmd_key_seed(tvbuff_t *tvb, proto_tree *tree, gint *offset)
|
|
{
|
|
guint8 seed_data[RF4CE_NWK_KEY_SEED_DATA_LENGTH] = {0};
|
|
guint8 seed_seq_num = 0;
|
|
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_seed_seq_num, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
|
|
seed_seq_num = tvb_get_guint8(tvb, *offset);
|
|
*offset += 1;
|
|
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_seed_data, tvb, *offset, RF4CE_NWK_KEY_SEED_DATA_LENGTH, ENC_NA);
|
|
tvb_memcpy(tvb, (void *)seed_data, *offset, RF4CE_NWK_KEY_SEED_DATA_LENGTH);
|
|
*offset += RF4CE_NWK_KEY_SEED_DATA_LENGTH;
|
|
|
|
keypair_context_update_seed(seed_data, seed_seq_num);
|
|
}
|
|
|
|
static void dissect_rf4ce_nwk_cmd_ping(tvbuff_t *tvb, proto_tree *tree, gint *offset)
|
|
{
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_ping_options, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
|
|
*offset += 1;
|
|
|
|
proto_tree_add_item(tree, hf_rf4ce_nwk_ping_payload, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
|
|
*offset += 4;
|
|
}
|
|
|
|
void proto_register_rf4ce_nwk(void)
|
|
{
|
|
static hf_register_info hf[] = {
|
|
{&hf_rf4ce_nwk_fcf,
|
|
{"Frame Control Field", "rf4ce-nwk.fcf",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, 0x00,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_fcf_frame_type,
|
|
{"Frame Type", "rf4ce-nwk.fcf.frame_type",
|
|
FT_UINT8, BASE_HEX,
|
|
VALS(rf4ce_nwk_frame_types), RF4CE_NWK_FCF_FRAME_TYPE_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_fcf_security_enabled,
|
|
{"Security enabled", "rf4ce-nwk.fcf.security_enabled",
|
|
FT_BOOLEAN, 8,
|
|
TFS(&tfs_yes_no), RF4CE_NWK_FCF_SECURITY_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_fcf_protocol_version,
|
|
{"Protocol version", "rf4ce-nwk.fcf.protocol_version",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, RF4CE_NWK_FCF_PROTOCOL_VERSION_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_fcf_reserved,
|
|
{"Reserved", "rf4ce-nwk.fcf.reserved",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, RF4CE_NWK_FCF_RESERVED_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_fcf_channel_designator,
|
|
{"Channel designator", "rf4ce-nwk.fcf.channel_designator",
|
|
FT_UINT8, BASE_HEX,
|
|
VALS(rf4ce_nwk_channel_designators), RF4CE_NWK_FCF_CHANNEL_DESIGNATOR_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_seq_num,
|
|
{"Sequence number", "rf4ce-nwk.seqn",
|
|
FT_UINT32, BASE_DEC,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_profile_id,
|
|
{"Profile ID", "rf4ce-nwk.profile_id",
|
|
FT_UINT8, BASE_HEX,
|
|
VALS(rf4ce_nwk_profile_ids), 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_vendor_id,
|
|
{"Vendor ID", "rf4ce-nwk.vendor_id",
|
|
FT_UINT16, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_cmd_id,
|
|
{"Command ID", "rf4ce-nwk.cmd_id",
|
|
FT_UINT8, BASE_HEX,
|
|
VALS(rf4ce_nwk_cmd_names), 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_node_capabilities,
|
|
{"Node Capabilities", "rf4ce-nwk.node_capabilities",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_node_capabilities_node_type,
|
|
{"Node Type", "rf4ce-nwk.node_capabilities.node_type",
|
|
FT_UINT8, BASE_HEX,
|
|
VALS(rf4ce_nwk_node_types), RF4CE_NWK_NODE_TYPE_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_node_capabilities_power_source,
|
|
{"Power Source", "rf4ce-nwk.node_capabilities.power_source",
|
|
FT_UINT8, BASE_HEX,
|
|
VALS(rf4ce_nwk_power_sources), RF4CE_NWK_POWER_SOURCE_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_node_capabilities_security,
|
|
{"Security Capable", "rf4ce-nwk.node_capabilities.security",
|
|
FT_BOOLEAN, 8,
|
|
TFS(&tfs_yes_no), RF4CE_NWK_SECURITY_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_node_capabilities_channel_normalization,
|
|
{"Channel Normalization", "rf4ce-nwk.node_capabilities.channel_normalization",
|
|
FT_BOOLEAN, 8,
|
|
TFS(&tfs_yes_no), RF4CE_NWK_CHANNEL_NORMALIZATION_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_node_capabilities_reserved,
|
|
{"Reserved", "rf4ce-nwk.node_capabilities.reserved",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, RF4CE_NWK_RESERVED_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_disc_req_vendor_id,
|
|
{"Vendor ID", "rf4ce-nwk.disc_req.vendor_id",
|
|
FT_UINT16, BASE_HEX,
|
|
VALS(rf4ce_disc_req_vendor_ids), 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_vendor_string,
|
|
{"Vendor String", "rf4ce-nwk.disc_req.vendor_str",
|
|
FT_STRING, BASE_NONE,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_app_capabilities,
|
|
{"App Capabilities", "rf4ce-nwk.app_capabilities",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_app_capabilities_usr_str,
|
|
{"User String Specified", "rf4ce-nwk.app_capabilities.usr_str",
|
|
FT_BOOLEAN, 8,
|
|
TFS(&tfs_yes_no), RF4CE_NWK_USR_STR_SPECIFIED_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_app_capabilities_supported_dev_num,
|
|
{"Number of Supported Device Types", "rf4ce-nwk.app_capabilities.supported_dev_num",
|
|
FT_UINT8, BASE_DEC,
|
|
NULL, RF4CE_NWK_SUPPORTED_DEV_NUM_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_app_capabilities_reserved1,
|
|
{"Reserved", "rf4ce-nwk.app_capabilities.reserved1",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, RF4CE_NWK_RESERVED1_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_app_capabilities_supported_profiles_num,
|
|
{"Number of Supported Profiles", "rf4ce-nwk.app_capabilities.supported_profiles_num",
|
|
FT_UINT8, BASE_DEC,
|
|
NULL, RF4CE_NWK_SUPPORTED_PROFILES_NUM_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_app_capabilities_reserved2,
|
|
{"Reserved", "rf4ce-nwk.app_capabilities.reserved2",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, RF4CE_NWK_RESERVED2_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_usr_str,
|
|
{"User String", "rf4ce-nwk.usr_str",
|
|
FT_BYTES, BASE_NONE,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_usr_str_disc_rsp_app_usr_str,
|
|
{"App Specific User String", "rf4ce-nwk.usr_str.disc_rsp.app_usr_str",
|
|
FT_STRING, BASE_NONE,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_usr_str_disc_rsp_null,
|
|
{"NULL-terminator", "rf4ce-nwk.usr_str.disc_rsp.null",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_usr_str_disc_rsp_reserved,
|
|
{"Reserved", "rf4ce-nwk.usr_str.disc_rsp.reserved",
|
|
FT_UINT16, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_tertiary,
|
|
{"Tertiary Class Descriptor", "rf4ce-nwk.usr_str.disc_rsp.class_descriptor.tertiary",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_secondary,
|
|
{"Secondary Class Descriptor", "rf4ce-nwk.usr_str.disc_rsp.class_descriptor.secondary",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_primary,
|
|
{"Primary Class Descriptor", "rf4ce-nwk.usr_str.disc_rsp.class_descriptor.primary",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_class_num,
|
|
{"Class Number", "rf4ce-nwk.usr_str.disc_rsp.class_descriptor.class_number",
|
|
FT_UINT8, BASE_HEX,
|
|
VALS(rf4ce_nwk_usr_str_disc_rsp_class_desc_class_num_vals), RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_CLASS_NUM_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_duplicate_class_num_handling,
|
|
{"Duplicate Class Number Handling", "rf4ce-nwk.usr_str.disc_rsp.class_descriptor.duplicate_class_num_handling",
|
|
FT_UINT8, BASE_HEX,
|
|
VALS(rf4ce_nwk_usr_str_disc_rsp_class_desc_duplicate_class_num_handling_vals), RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_DUPLICATE_CLASS_NUM_HANDLING_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_usr_str_disc_rsp_class_desc_reserved,
|
|
{"Reserved", "rf4ce-nwk.usr_str.disc_rsp.class_descriptor.reserved",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, RF4CE_NWK_USR_STR_DISC_RSP_CLASS_DESC_RESERVED_MASK,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_usr_str_disc_rsp_discovery_lqi_threshold,
|
|
{"Discovery LQI Threshold", "rf4ce-nwk.usr_str.disc_rsp.discovery_lqi_threshold",
|
|
FT_INT8, BASE_DEC,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_app_cap_dev_type,
|
|
{"Device Type", "rf4ce-nwk.app_cap.dev_type",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_app_cap_profile_id,
|
|
{"Profile ID", "rf4ce-nwk.app_cap.profile_id",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_requested_dev_type,
|
|
{"Requested Device Type", "rf4ce-nwk.requested_dev_type",
|
|
FT_UINT8, BASE_HEX,
|
|
VALS(rf4ce_nwk_device_type_vals), 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_disc_resp_status,
|
|
{"Status", "rf4ce-nwk.disc_resp.status",
|
|
FT_UINT8, BASE_HEX,
|
|
VALS(rf4ce_nwk_disc_status_vals), 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_disc_resp_lqi,
|
|
{"Discovery Request LQI", "rf4ce-nwk.disc_resp.lqi",
|
|
FT_INT8, BASE_DEC,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_pair_req_nwk_addr,
|
|
{"Network Address", "rf4ce-nwk.pair_req.nwk_addr",
|
|
FT_UINT16, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_pair_req_key_exch_num,
|
|
{"Key Exchange Transfer Count", "rf4ce-nwk.pair_req.key_exch_num",
|
|
FT_INT8, BASE_DEC,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_pair_rsp_status,
|
|
{"Status", "rf4ce-nwk.pair_rsp.status",
|
|
FT_UINT8, BASE_HEX,
|
|
VALS(rf4ce_nwk_disc_status_vals), 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_pair_rsp_allocated_nwk_addr,
|
|
{"Allocated Network Address", "rf4ce-nwk.pair_rsp.allocated_nwk_addr",
|
|
FT_UINT16, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_pair_rsp_nwk_addr,
|
|
{"Network Address", "rf4ce-nwk.pair_rsp.nwk_addr",
|
|
FT_UINT16, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_seed_seq_num,
|
|
{"Seed Sequence Number", "rf4ce-nwk.key_seed.seed_seq_num",
|
|
FT_INT8, BASE_DEC,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_seed_data,
|
|
{"Seed Data", "rf4ce-nwk.key_seed.seed_data",
|
|
FT_BYTES, SEP_COLON,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_ping_options,
|
|
{"Ping Options", "rf4ce-nwk.ping_options",
|
|
FT_UINT8, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
{&hf_rf4ce_nwk_ping_payload,
|
|
{"Ping Payload", "rf4ce-nwk.ping_payload",
|
|
FT_UINT32, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
#if 0
|
|
{&hf_rf4ce_nwk_mic,
|
|
{"Ping Payload", "rf4ce-nwk.mic",
|
|
FT_UINT32, BASE_HEX,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
#endif
|
|
{&hf_rf4ce_nwk_unparsed_payload,
|
|
{"Unparsed Payload", "rf4ce-nwk.unparsed_payload",
|
|
FT_BYTES, SEP_COLON,
|
|
NULL, 0x0,
|
|
NULL, HFILL}},
|
|
};
|
|
|
|
/* Setup protocol subtree array */
|
|
static gint *ett[] = {
|
|
&ett_rf4ce_nwk,
|
|
&ett_rf4ce_nwk_payload,
|
|
&ett_rf4ce_nwk_vendor_info,
|
|
&ett_rf4ce_nwk_usr_str,
|
|
&ett_rf4ce_nwk_usr_str_class_descriptor,
|
|
&ett_rf4ce_nwk_dev_types_list,
|
|
&ett_rf4ce_nwk_profiles_list,
|
|
};
|
|
|
|
proto_rf4ce_nwk = proto_register_protocol("RF4CE Network Layer", "RF4CE", RF4CE_PROTOABBREV_NWK);
|
|
proto_register_field_array(proto_rf4ce_nwk, hf, array_length(hf));
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
|
|
register_cleanup_routine(rf4ce_cleanup);
|
|
|
|
register_dissector(RF4CE_PROTOABBREV_NWK, dissect_rf4ce_nwk_common, proto_rf4ce_nwk);
|
|
|
|
static uat_field_t key_uat_fields[] =
|
|
{
|
|
UAT_FLD_CSTRING(uat_security_records, sec_str, "Byte sequence",
|
|
"In case of NWK key type it is a 16-byte key in hexadecimal with optional dash-,\n"
|
|
"colon-, or space-separator characters, or \n"
|
|
"a 16-character string in double-quotes.\n"
|
|
"In case of Vendor Secret type it is a secret byte sequence\n"
|
|
"to calculate NWK keys during Key Exchange procedure."),
|
|
UAT_FLD_VS(uat_security_records, type, "Type", sec_str_type_vals, "Type of a security string."),
|
|
UAT_FLD_CSTRING(uat_security_records, label, "Label", "User label for a security string."),
|
|
UAT_END_FIELDS};
|
|
|
|
rf4ce_security_table_uat =
|
|
uat_new("Pre-configured security table",
|
|
sizeof(uat_security_record_t),
|
|
"rf4ce_pc_sec",
|
|
TRUE,
|
|
&uat_security_records,
|
|
&num_uat_security_records,
|
|
UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
|
|
NULL, /* TODO: ptr to help manual? */
|
|
uat_sec_record_copy_cb,
|
|
uat_sec_record_update_cb,
|
|
uat_sec_record_free_cb,
|
|
uat_sec_record_post_update,
|
|
NULL,
|
|
key_uat_fields);
|
|
|
|
module_t *rf4ce_prefs = prefs_register_protocol(proto_rf4ce_nwk, NULL);
|
|
|
|
prefs_register_uat_preference(
|
|
rf4ce_prefs,
|
|
"security_table",
|
|
"Pre-configured security strings",
|
|
"Pre-configured vendor secrets or network keys.",
|
|
rf4ce_security_table_uat);
|
|
}
|
|
|
|
void proto_reg_handoff_rf4ce_nwk(void)
|
|
{
|
|
rf4ce_gdp_handle = find_dissector_add_dependency(RF4CE_PROTOABBREV_PROFILE, proto_rf4ce_nwk);
|
|
|
|
/* create_dissector_handle(dissect_rf4ce_nwk_common, proto_rf4ce_nwk); */
|
|
dissector_add_for_decode_as(IEEE802154_PROTOABBREV_WPAN_PANID, find_dissector(RF4CE_PROTOABBREV_NWK));
|
|
heur_dissector_add(IEEE802154_PROTOABBREV_WPAN, dissect_rf4ce_nwk_heur, "Radio Frequency for Consumer Electronics over IEEE 802.15.4", RF4CE_PROTOABBREV_NWK, proto_rf4ce_nwk, HEURISTIC_ENABLE);
|
|
}
|