-/* packet-cfdp.c\r
- * Routines for CCSDS File Delivery Protocol (CFDP) dissection\r
- * Copyright 2013, Juan Antonio Montesinos juan.mondl@gmail.com\r
- *\r
- * $Id$\r
- *\r
- * Wireshark - Network traffic analyzer\r
- * By Gerald Combs <gerald@wireshark.org>\r
- * Copyright 1998 Gerald Combs\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#include "config.h"\r
-#include <glib.h>\r
-#include <epan/packet.h>\r
-#include <epan/expert.h>\r
-#include <epan/prefs.h>\r
-\r
-\r
-/* The CFDP standard can be found here:\r
- * http://public.ccsds.org/publications/archive/727x0b4.pdf\r
- * \r
- * The Store and Forward Overlay Operations are not included.\r
- */\r
-\r
-/* Initialize the protocol and registered fields */\r
-static int proto_cfdp = -1;\r
-static int hf_cfdp_version = -1;\r
-static int hf_cfdp_pdu_type = -1;\r
-static int hf_cfdp_direction = -1;\r
-static int hf_cfdp_trans_mode = -1;\r
-static int hf_cfdp_crc_flag = -1;\r
-static int hf_cfdp_res1 = -1;\r
-static int hf_cfdp_data_length = -1;\r
-static int hf_cfdp_res2 = -1;\r
-static int hf_cfdp_entid_length = -1;\r
-static int hf_cfdp_res3 = -1;\r
-static int hf_cfdp_transeqnum_length = -1;\r
-static int hf_cfdp_srcid = -1;\r
-static int hf_cfdp_transeqnum = -1;\r
-static int hf_cfdp_dstid = -1;\r
-static int hf_cfdp_file_directive_type = -1;\r
-static int hf_cfdp_file_data_offset = -1;\r
-static int hf_cfdp_progress = -1;\r
-static int hf_cfdp_dir_code_ack = -1;\r
-static int hf_cfdp_dir_subtype_ack = -1;\r
-static int hf_cfdp_condition_code = -1;\r
-static int hf_cfdp_spare_one = -1;\r
-static int hf_cfdp_spare_one_2 = -1;\r
-static int hf_cfdp_spare_two = -1;\r
-static int hf_cfdp_spare_four = -1;\r
-static int hf_cfdp_spare_five = -1;\r
-static int hf_cfdp_spare_seven = -1;\r
-static int hf_cfdp_spare_seven_2 = -1;\r
-static int hf_cfdp_trans_stat_ack = -1;\r
-static int hf_cfdp_file_checksum = -1;\r
-static int hf_cfdp_file_size = -1;\r
-static int hf_cfdp_end_system_stat = -1;\r
-static int hf_cfdp_delivery_code = -1;\r
-static int hf_cfdp_file_stat = -1;\r
-static int hf_cfdp_segment_control = -1;\r
-static int hf_cfdp_src_file_name = -1;\r
-static int hf_cfdp_dst_file_name = -1;\r
-static int hf_cfdp_first_file_name = -1;\r
-static int hf_cfdp_second_file_name = -1;\r
-static int hf_cfdp_nak_st_scope = -1;\r
-static int hf_cfdp_nak_sp_scope = -1;\r
-static int hf_cfdp_crc = -1;\r
-static int hf_cfdp_action_code = -1;\r
-static int hf_cfdp_status_code_1 = -1;\r
-static int hf_cfdp_status_code_2 = -1;\r
-static int hf_cfdp_status_code_3 = -1;\r
-static int hf_cfdp_status_code_4 = -1;\r
-static int hf_cfdp_status_code_5 = -1;\r
-static int hf_cfdp_status_code_6 = -1;\r
-static int hf_cfdp_status_code_7 = -1;\r
-static int hf_cfdp_status_code_8 = -1;\r
-static int hf_cfdp_handler_code = -1;\r
-static int hf_cfdp_trans_mode_msg = -1;\r
-static int hf_cfdp_proxy_msg_type = -1;\r
-static int hf_cfdp_proxy_segment_control = -1;\r
-static int hf_cfdp_proxy_delivery_code = -1;\r
-static int hf_cfdp_response_req = -1;\r
-static int hf_cfdp_directory_name = -1;\r
-static int hf_cfdp_directory_file_name = -1;\r
-static int hf_cfdp_listing_resp_code = -1;\r
-static int hf_cfdp_report_file_name = -1;\r
-static int hf_cfdp_trans_stat = -1;\r
-static int hf_cfdp_trans_stat_2 = -1;\r
-static int hf_cfdp_rep_resp_code = -1;\r
-static int hf_cfdp_suspension_ind = -1;\r
-static int hf_cfdp_tlv_len =- 1;\r
-\r
-/* Initialize the subtree pointers */\r
-static gint ett_cfdp = -1;\r
-static gint ett_cfdp_header = -1;\r
-static gint ett_cfdp_file_directive_header = -1;\r
-static gint ett_cfdp_file_data_header = -1;\r
-static gint ett_cfdp_fault_location = -1;\r
-static gint ett_cfdp_crc = -1;\r
-static gint ett_cfdp_filestore_req = -1;\r
-static gint ett_cfdp_filestore_resp = -1;\r
-static gint ett_cfdp_msg_to_user = -1;\r
-static gint ett_cfdp_fault_hdl_overr = -1;\r
-static gint ett_cfdp_flow_label = -1;\r
-\r
-/* Generic data handle */\r
-static dissector_handle_t data_handle;\r
-\r
-/* Some parameters */\r
-#define CFDP_HEADER_FIXED_FIELDS_LEN 4\r
-#define CFDP_APID 2045\r
-\r
-/* Bitmask for the first byte of the Header */\r
-#define HDR_VERSION_CFDP 0xe0\r
-#define HDR_TYPE_CFDP 0x10\r
-#define HDR_DIR 0x08\r
-#define HDR_TMODE 0x04\r
-#define HDR_CRCF 0x02\r
-#define HDR_RES1 0x01\r
-\r
-/* Bitmask for the second byte of the Header */\r
-#define HDR_RES2 0x80\r
-#define HDR_LEN_ENT_ID 0x70\r
-#define HDR_RES3 0x08\r
-#define HDR_LEN_TSEQ_NUM 0x07\r
-\r
-/* File Directive Codes */\r
-#define EOF_PDU 4\r
-#define FINISHED_PDU 5\r
-#define ACK_PDU 6\r
-#define METADATA_PDU 7\r
-#define NAK_PDU 8\r
-#define PROMPT_PDU 9\r
-#define KEEP_ALIVE_PDU 12\r
-\r
-/* TLV Types */\r
-#define FILESTORE_REQ 0\r
-#define FILESTORE_RESP 1\r
-#define MSG_TO_USER 2\r
-#define FAULT_HDL_OVERR 4\r
-#define FLOW_LABEL 5\r
-#define FAULT_LOCATION 6\r
-\r
-/* ID for reserved CFDP Messages */\r
-#define CFDP_MSG_TO_USER 0x63666470\r
-\r
-/* Proxy Operations Message Types */\r
-#define PROXY_PUT_REQ 0x00\r
-#define PROXY_MSG_TO_USER 0x01\r
-#define PROXY_FILESTORE_REQ 0x02\r
-#define PROXY_FAULT_HDL_OVERR 0x03\r
-#define PROXY_TRANS_MODE 0x04\r
-#define PROXY_FLOW_LABEL 0x05\r
-#define PROXY_SEGMENT_CONTROL 0x06\r
-#define PROXY_PUT_RESP 0x07\r
-#define PROXY_FILESTORE_RESP 0x08\r
-#define PROXY_PUT_CANCEL 0x09\r
-#define ORIG_TRANS_ID 0x0A\r
-#define DIRECTORY_LIST_REQ 0x10\r
-#define DIRECTORY_LIST_RESP 0x11\r
-#define REMOTE_STAT_REP_REQ 0x20\r
-#define REMOTE_STAT_REP_RESP 0x21\r
-#define REMOTE_SUSPEND_REQ 0x30\r
-#define REMOTE_SUSPEND_RESP 0x31\r
-#define REMOTE_RESUME_REQ 0x38\r
-#define REMOTE_RESUME_RESP 0x39\r
-\r
-/* PDU Type */\r
-static const value_string cfdp_pdu_type[] = {\r
- { 0, "File Directive" },\r
- { 1, "File Data" },\r
- { 0, NULL }\r
-};\r
-\r
-/* PDU Direction */\r
-static const value_string cfdp_direction[] = {\r
- { 0, "Toward file receiver" },\r
- { 1, "Toward file sender" },\r
- { 0, NULL }\r
-};\r
-\r
-/* Transmission mode */\r
-static const value_string cfdp_trans_mode[] = {\r
- { 0, "Acknowledged" },\r
- { 1, "Unacknowledged" },\r
- { 0, NULL }\r
-};\r
-\r
-/* CRC */\r
-static const value_string cfdp_crc_flag[] = {\r
- { 0, "CRC not present" },\r
- { 1, "CRC present" },\r
- { 0, NULL }\r
-};\r
-\r
-/* File Directive PDU Type */\r
-static const value_string cfdp_file_directive_type[] = {\r
- {4, "EOF PDU"},\r
- {5, "Finished PDU"},\r
- {6, "ACK PDU"},\r
- {7, "Metadata PDU"},\r
- {8, "NACK PDU"},\r
- {9, "Prompt PDU"},\r
- {12, "Keep Alive PDU"},\r
- {0, NULL}\r
-};\r
-\r
-/* Condition codes */\r
-static const value_string cfdp_condition_codes[] = {\r
- {0, "No error"},\r
- {1, "Positive ACK limit reached"},\r
- {2, "Keep alive limit reached"},\r
- {3, "Invalid transmission mode"},\r
- {4, "Filestore rejection"},\r
- {5, "File checksum failure"},\r
- {6, "File size error"},\r
- {7, "NAK limit reached"},\r
- {8, "Inactivity detected"},\r
- {9, "Check limit reached"},\r
- {14, "Suspend.request received"},\r
- {15, "Cancel.request received"},\r
- { 0, NULL }\r
-};\r
-\r
-/* Transaction status */\r
-static const value_string cfdp_trans_stat_ack[] = {\r
- { 0, "Undefined" },\r
- { 1, "Active" },\r
- { 2, "Terminated" },\r
- { 3, "Unrecognized" },\r
- { 0, NULL }\r
-};\r
-\r
-/* End system status */\r
-static const value_string cfdp_end_system_stat[] = {\r
- { 0, "Generated by Waypoint" },\r
- { 1, "Generated by End System" },\r
- { 0, NULL }\r
-};\r
-\r
-/* Delivery code */\r
-static const value_string cfdp_delivery_code[] = {\r
- { 0, "Data Complete" },\r
- { 1, "Data incomplete" },\r
- { 0, NULL }\r
-};\r
-\r
-/* Filestore operations action code */\r
-static const value_string cfdp_action_code[] = {\r
- { 0, "Create File" },\r
- { 1, "Delete File" },\r
- { 2, "Rename File" },\r
- { 3, "Append File" },\r
- { 4, "Replace File" },\r
- { 5, "Create Directory" },\r
- { 6, "Remove Directory" },\r
- { 7, "Deny File (delete if present)" },\r
- { 8, "Deny Directory (remove if present)" },\r
- { 0, NULL }\r
-};\r
-\r
-/* Filestore operations status codes */\r
-static const value_string cfdp_status_code_1[] = {\r
- { 0, "Successful" },\r
- { 1, "Create not allowed" },\r
- { 8, "Not performed" },\r
- { 0, NULL }\r
-};\r
-\r
-static const value_string cfdp_status_code_2[] = {\r
- { 0, "Successful" },\r
- { 1, "File does not exist" },\r
- { 2, "Delete not allowed" },\r
- { 8, "Not performed" },\r
- { 0, NULL }\r
-};\r
-\r
-static const value_string cfdp_status_code_3[] = {\r
- { 0, "Successful" },\r
- { 1, "Old File Name does not exist" },\r
- { 2, "New File Name already exists" },\r
- { 3, "Rename not allowed" },\r
- { 8, "Not performed" },\r
- { 0, NULL }\r
-};\r
-\r
-static const value_string cfdp_status_code_4[] = {\r
- { 0, "Successful" },\r
- { 1, "File Name 1 does not exist" },\r
- { 2, "File Name 2 does not exist" },\r
- { 3, "Append not allowed" },\r
- { 8, "Not performed" },\r
- { 0, NULL }\r
-};\r
-\r
-static const value_string cfdp_status_code_5[] = {\r
- { 0, "Successful" },\r
- { 1, "File Name 1 does not exist" },\r
- { 2, "File Name 2 does not exist" },\r
- { 3, "Replace not allowed" },\r
- { 8, "Not performed" },\r
- { 0, NULL }\r
-};\r
-\r
-static const value_string cfdp_status_code_6[] = {\r
- { 0, "Successful" },\r
- { 1, "Directory cannot be created" },\r
- { 8, "Not performed" },\r
- { 0, NULL }\r
-};\r
-\r
-static const value_string cfdp_status_code_7[] = {\r
- { 0, "Successful" },\r
- { 1, "Directory does not exist" },\r
- { 2, "Delete not allowed" },\r
- { 8, "Not performed" },\r
- { 0, NULL }\r
-};\r
-\r
-static const value_string cfdp_status_code_8[] = {\r
- { 0, "Successful" },\r
- { 1, "Delete not allowed" },\r
- { 8, "Not performed" },\r
- { 0, NULL }\r
-};\r
-\r
-/* Finished PDU File Status */\r
-static const value_string cfdp_file_stat[] = {\r
- { 0, "Delivery file discarded deliberately" },\r
- { 1, "Delivery file discarded due to filestore rejection" },\r
- { 2, "Delivery file retained in filestore successfully" },\r
- { 3, "Delivery file status unreported" },\r
- { 0, NULL }\r
-};\r
-\r
-/* Segmentation control */\r
-static const value_string cfdp_segment_control[] = {\r
- { 0, "Record boundaries respected" },\r
- { 1, "Record boundaries not respected" },\r
- { 0, NULL }\r
-};\r
-\r
-/* Fault handler override Handler code*/\r
-static const value_string cfdp_handler_codes[] = {\r
- { 1, "issue Notice of Cancellation" },\r
- { 2, "issue Notice of Suspension" },\r
- { 3, "Ignore error" },\r
- { 4, "Abandon transaction" },\r
- { 0, NULL }\r
-};\r
-\r
-/* Type of Proxy message */\r
-static const value_string cfdp_proxy_msg_type[] = {\r
- {0x00, "Proxy Put Request"},\r
- {0x01, "Proxy Message To User"},\r
- {0x02, "Proxy Filestore Request"},\r
- {0x03, "Proxy Fault Handler Override"},\r
- {0x04, "Proxy Transmission Mode"},\r
- {0x05, "Proxy Flow Label"},\r
- {0x06, "Proxy Segmentation Control"},\r
- {0x07, "Proxy Put Response"},\r
- {0x08, "Proxy Filestore Response"},\r
- {0x09, "Proxy Put Cancel"},\r
- {0x0A, "Originating Transaction ID"},\r
- {0x10, "Directory Listing Request"},\r
- {0x11, "Directory Listing Response"},\r
- {0x20, "Remote Status Report Request"},\r
- {0x21, "Remote Status Report Response"},\r
- {0x30, "Remote Suspend Request"},\r
- {0x31, "Remote Suspend Response"},\r
- {0x38, "Remote Resume Request"},\r
- {0x39, "Remote Resume Response"},\r
- { 0, NULL }\r
-};\r
-\r
-/* Prompt PDU Response required */\r
-static const value_string cfdp_response_req[] = {\r
- { 0, "NAK" },\r
- { 1, "Keep Alive" },\r
- { 0, NULL }\r
-};\r
-\r
-/* Listing response code */\r
-static const value_string cfdp_listing_resp_code[] = {\r
- { 0, "Successful" },\r
- { 1, "Unsuccessful" },\r
- { 0, NULL }\r
-};\r
-\r
-/* Report response code */\r
-static const value_string cfdp_rep_resp_code[] = {\r
- { 0, "Unsuccessful" },\r
- { 1, "Successful" },\r
- { 0, NULL }\r
-};\r
-\r
-/* Suspension indication */\r
-static const value_string cfdp_suspension_ind[] = {\r
- { 0, "Not Suspended" },\r
- { 1, "Suspended" },\r
- { 0, NULL }\r
-};\r
-\r
-/* File Directive codes */\r
-static const value_string cfdp_directive_codes[] = {\r
- { 0x04, "EOF" },\r
- { 0x05, "Finished" },\r
- { 0x06, "ACK" },\r
- { 0x07, "Metadata" },\r
- { 0x08, "NAK" },\r
- { 0x09, "Prompt" },\r
- { 0x0C, "Keep Alive" },\r
- { 0, NULL }\r
-};\r
-\r
-/* Dissect the Source Entity ID field */\r
-static void\r
-dissect_cfdp_src_entity_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 len_ent_id)\r
-{\r
- if(len_ent_id > 0 && len_ent_id <= 8){\r
- proto_tree_add_item(tree, hf_cfdp_srcid, tvb, offset, len_ent_id, ENC_BIG_ENDIAN);\r
- }\r
- else{\r
- proto_tree_add_text(tree, tvb, offset, 0, "Wrong length for the entity ID");\r
- }\r
-}\r
-\r
-/* Dissect the Destination Entity ID field */\r
-static void\r
-dissect_cfdp_dst_entity_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 len_ent_id)\r
-{\r
- if(len_ent_id > 0 && len_ent_id <= 8){\r
- proto_tree_add_item(tree, hf_cfdp_dstid, tvb, offset, len_ent_id, ENC_BIG_ENDIAN);\r
- }\r
- else{\r
- proto_tree_add_text(tree, tvb, offset, 0, "Wrong length for the entity ID");\r
- }\r
-}\r
-\r
-/* Dissect the Transaction Sequence Number field */\r
-static void\r
-dissect_cfdp_tseq_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 len_tseq_num)\r
-{\r
- if(len_tseq_num > 0 && len_tseq_num <= 8){\r
- proto_tree_add_item(tree, hf_cfdp_transeqnum, tvb, offset, len_tseq_num, ENC_BIG_ENDIAN);\r
- }\r
- else{\r
- proto_tree_add_text(tree, tvb, offset, 0, "Wrong length for transaction sequence number");\r
- }\r
-}\r
-\r
-/* Dissect the Filestore Request TLV */\r
-static guint32 dissect_cfdp_filestore_req_tlv(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){\r
- \r
- guint8 aux_byte, tlv_len;\r
- proto_item *cfdp_filestore_req = NULL;\r
- proto_tree *cfdp_filestore_req_tree;\r
- \r
- guint32 offset = ext_offset;\r
- \r
- /* Get field length */\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- if(tlv_len > 0){\r
- /* Create a TLV subtree */\r
- cfdp_filestore_req = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Filestore Request TLV");\r
- cfdp_filestore_req_tree = proto_item_add_subtree(cfdp_filestore_req, ett_cfdp_filestore_req);\r
-\r
- proto_tree_add_uint(cfdp_filestore_req_tree, hf_cfdp_tlv_len, tvb, offset-1, 1, tlv_len);\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_filestore_req_tree, hf_cfdp_action_code, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_filestore_req_tree, hf_cfdp_spare_four, tvb, offset, 1, aux_byte);\r
- offset += 1;\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- proto_tree_add_item(cfdp_filestore_req_tree, hf_cfdp_first_file_name, tvb, offset, aux_byte, ENC_ASCII|ENC_NA);\r
- offset += aux_byte;\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- if(aux_byte > 0){\r
- proto_tree_add_item(cfdp_filestore_req_tree, hf_cfdp_second_file_name, tvb, offset, aux_byte, ENC_ASCII|ENC_NA);\r
- offset += aux_byte;\r
- }\r
- }\r
-\r
- return offset;\r
-}\r
-\r
-/* Dissect the Filestore Response TLV */\r
-static guint32 dissect_cfdp_filestore_resp_tlv(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){\r
-\r
- guint8 aux_byte, tlv_len;\r
- proto_item *cfdp_filestore_resp = NULL;\r
- proto_tree *cfdp_filestore_resp_tree;\r
-\r
- guint32 offset = ext_offset;\r
-\r
- /* Get field length */\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- if(tlv_len > 0){\r
- /* Create a subtree */\r
- cfdp_filestore_resp = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Filestore Response TLV");\r
- cfdp_filestore_resp_tree = proto_item_add_subtree(cfdp_filestore_resp, ett_cfdp_filestore_resp);\r
-\r
- proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_tlv_len, tvb, offset-1, 1, tlv_len);\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_action_code, tvb, offset, 1, aux_byte);\r
- switch(aux_byte & 0xF0){\r
- case 0:\r
- proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_1, tvb, offset, 1, aux_byte);\r
- break;\r
- case 1:\r
- proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_2, tvb, offset, 1, aux_byte);\r
- break;\r
- case 2:\r
- proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_3, tvb, offset, 1, aux_byte);\r
- break;\r
- case 3:\r
- proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_4, tvb, offset, 1, aux_byte);\r
- break;\r
- case 4:\r
- proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_5, tvb, offset, 1, aux_byte);\r
- break;\r
- case 5:\r
- proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_6, tvb, offset, 1, aux_byte);\r
- break;\r
- case 6:\r
- proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_7, tvb, offset, 1, aux_byte);\r
- break;\r
- case 7: case 8:\r
- proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_8, tvb, offset, 1, aux_byte);\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- offset += 1;\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- proto_tree_add_item(cfdp_filestore_resp_tree, hf_cfdp_first_file_name, tvb, offset, aux_byte, ENC_ASCII|ENC_NA);\r
- offset += aux_byte;\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- if(aux_byte > 0){\r
- proto_tree_add_item(cfdp_filestore_resp_tree, hf_cfdp_second_file_name, tvb, offset, aux_byte, ENC_ASCII|ENC_NA);\r
- offset += aux_byte;\r
- }\r
- /* Filestore Message */\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- if(aux_byte > 0){\r
- proto_tree_add_text(cfdp_filestore_resp_tree, tvb, offset, tlv_len, "Filestore Message");\r
- offset += aux_byte;\r
- }\r
- }\r
-\r
- return offset;\r
-}\r
-\r
-/* Dissect the Fault Location TLV */\r
-static guint32 dissect_cfdp_fault_location_tlv(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){\r
-\r
- guint8 tlv_len;\r
- proto_item *cfdp_fault_location = NULL;\r
- proto_tree *cfdp_fault_location_tree;\r
-\r
- guint32 offset = ext_offset;\r
-\r
- /* Get field length */\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- if(tlv_len > 0){\r
- /* Create a subtree */\r
- cfdp_fault_location = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Fault location TLV");\r
- cfdp_fault_location_tree = proto_item_add_subtree(cfdp_fault_location, ett_cfdp_fault_location);\r
-\r
- proto_tree_add_uint(cfdp_fault_location_tree, hf_cfdp_tlv_len, tvb, offset-1, 1, tlv_len);\r
-\r
- proto_tree_add_text(cfdp_fault_location_tree, tvb, offset, tlv_len, "Entity");\r
- offset +=tlv_len;\r
- }\r
-\r
- return offset;\r
-}\r
-\r
-/* Dissect the Message to User TLV */\r
-static guint32 dissect_cfdp_msg_to_user_tlv(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){\r
-\r
- guint8 aux_byte, tlv_type, tlv_len;\r
- proto_item *cfdp_msg_to_user = NULL;\r
- proto_tree *cfdp_msg_to_user_tree;\r
-\r
- guint32 offset = ext_offset;\r
- guint32 msg_to_user_id =0;\r
- int len_ent_id = 0;\r
- int len_tseq_num = 0;\r
-\r
- /* Get tlv len */\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
-\r
- /* Create a subtree */\r
- cfdp_msg_to_user = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Message To User TLV");\r
- cfdp_msg_to_user_tree = proto_item_add_subtree(cfdp_msg_to_user, ett_cfdp_filestore_resp);\r
-\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_tlv_len, tvb, offset-1, 1, tlv_len);\r
-\r
- msg_to_user_id = tvb_get_ntohl(tvb, offset);\r
- /* Proxy operations */\r
- if(msg_to_user_id == CFDP_MSG_TO_USER){\r
- offset += 4;\r
- tlv_type = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_proxy_msg_type, tvb, offset, 1, tlv_type);\r
- offset += 1;\r
- switch(tlv_type){\r
-\r
- case PROXY_PUT_REQ:\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- dissect_cfdp_dst_entity_id(tvb, cfdp_msg_to_user_tree, offset, tlv_len);\r
- offset += tlv_len;\r
-\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_src_file_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);\r
- offset += tlv_len;\r
-\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_dst_file_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);\r
- offset += tlv_len;\r
-\r
- break;\r
-\r
- case PROXY_MSG_TO_USER:\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- proto_tree_add_text(cfdp_msg_to_user_tree, tvb, offset, tlv_len, "Message to User");\r
- break;\r
-\r
- case PROXY_FILESTORE_REQ:\r
- offset = dissect_cfdp_filestore_req_tlv(tvb, cfdp_msg_to_user_tree, offset);\r
- break;\r
-\r
- case PROXY_FAULT_HDL_OVERR:\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_handler_code, tvb, offset, 1, aux_byte);\r
- offset += 1;\r
- break;\r
-\r
- case PROXY_TRANS_MODE:\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_seven_2, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_trans_mode_msg, tvb, offset, 1, aux_byte);\r
- offset += 1;\r
- break;\r
-\r
- case PROXY_FLOW_LABEL:\r
- proto_tree_add_text(cfdp_msg_to_user_tree, tvb, offset, tlv_len, "Flow label");\r
- break;\r
-\r
- case PROXY_SEGMENT_CONTROL:\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_seven_2, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_proxy_segment_control, tvb, offset, 1, aux_byte);\r
- offset += 1;\r
- break;\r
-\r
- case PROXY_PUT_RESP:\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_proxy_delivery_code, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_file_stat, tvb, offset, 1, aux_byte);\r
- offset += 1;\r
- break;\r
-\r
- case PROXY_FILESTORE_RESP:\r
- offset = dissect_cfdp_filestore_req_tlv(tvb, cfdp_msg_to_user_tree, offset);\r
- break;\r
-\r
- case PROXY_PUT_CANCEL:\r
- break;\r
-\r
- case ORIG_TRANS_ID:\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_res2, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_res3, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);\r
- offset += 1;\r
-\r
- len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;\r
- dissect_cfdp_src_entity_id(tvb, cfdp_msg_to_user_tree, offset, len_ent_id);\r
- offset += len_ent_id;\r
-\r
- len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;\r
- dissect_cfdp_tseq_num(tvb, cfdp_msg_to_user_tree, offset, len_tseq_num);\r
- offset += len_tseq_num;\r
-\r
- break;\r
-\r
- case DIRECTORY_LIST_REQ:\r
- /* Directory Name */\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_directory_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);\r
- offset += tlv_len;\r
- /* Directory File Name */\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_directory_file_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);\r
- offset += tlv_len;\r
- break;\r
-\r
- case DIRECTORY_LIST_RESP:\r
- /* Listing Response Code */\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_listing_resp_code, tvb, offset, 1, aux_byte);\r
- offset += 1;\r
- /* Directory Name */\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_directory_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);\r
- offset += tlv_len;\r
- /* Directory File Name */\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_directory_file_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);\r
- offset += tlv_len;\r
- break;\r
-\r
- case REMOTE_STAT_REP_REQ:\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_res2, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_res3, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);\r
- offset += 1;\r
-\r
- len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;\r
- dissect_cfdp_src_entity_id(tvb, cfdp_msg_to_user_tree, offset, len_ent_id);\r
- offset += len_ent_id;\r
-\r
- len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;\r
- dissect_cfdp_tseq_num(tvb, cfdp_msg_to_user_tree, offset, len_tseq_num);\r
- offset += len_tseq_num;\r
-\r
- /* Report File Name */\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_report_file_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);\r
- offset += tlv_len;\r
- break;\r
-\r
- case REMOTE_STAT_REP_RESP:\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_trans_stat, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_five, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_rep_resp_code, tvb, offset, 1, aux_byte);\r
- offset +=1;\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one_2, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);\r
- offset +=1;\r
-\r
- len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;\r
- dissect_cfdp_src_entity_id(tvb, cfdp_msg_to_user_tree, offset, len_ent_id);\r
- offset += len_ent_id;\r
-\r
- len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;\r
- dissect_cfdp_tseq_num(tvb, cfdp_msg_to_user_tree, offset, len_tseq_num);\r
- offset += len_tseq_num;\r
- break;\r
-\r
- case REMOTE_SUSPEND_REQ:\r
- case REMOTE_RESUME_REQ:\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one_2, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);\r
- offset += 1;\r
-\r
- len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;\r
- dissect_cfdp_src_entity_id(tvb, cfdp_msg_to_user_tree, offset, len_ent_id);\r
- offset += len_ent_id;\r
-\r
- len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;\r
- dissect_cfdp_tseq_num(tvb, cfdp_msg_to_user_tree, offset, len_tseq_num);\r
- offset += len_tseq_num;\r
- break;\r
-\r
- case REMOTE_SUSPEND_RESP:\r
- case REMOTE_RESUME_RESP:\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_suspension_ind, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_trans_stat_2, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_five, tvb, offset, 1, aux_byte);\r
- offset += 1;\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one_2, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);\r
- offset += 1;\r
-\r
- len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;\r
- dissect_cfdp_src_entity_id(tvb, cfdp_msg_to_user_tree, offset, len_ent_id);\r
- offset += len_ent_id;\r
- \r
- len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;\r
- dissect_cfdp_tseq_num(tvb, cfdp_msg_to_user_tree, offset, len_tseq_num);\r
- offset += len_tseq_num;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- }else{\r
- proto_tree_add_text(cfdp_msg_to_user_tree, tvb, offset, tlv_len, "Message to User");\r
- offset += tlv_len;\r
- }\r
-\r
- return offset;\r
-}\r
-\r
-/* Dissect the Fault Handler Override TLV */\r
-static guint32 dissect_cfdp_fault_handler_overr_tlv(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){\r
-\r
- guint8 aux_byte, tlv_len;\r
- proto_item *cfdp_fault_hdl_overr = NULL;\r
- proto_tree *cfdp_fault_hdl_overr_tree;\r
-\r
- guint32 offset = ext_offset;\r
-\r
- /* Get tlv len */\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
-\r
- /* Create a subtree */\r
- cfdp_fault_hdl_overr = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Fault Handler Override TLV");\r
- cfdp_fault_hdl_overr_tree = proto_item_add_subtree(cfdp_fault_hdl_overr, ett_cfdp_fault_hdl_overr);\r
-\r
- proto_tree_add_uint(cfdp_fault_hdl_overr_tree, hf_cfdp_tlv_len, tvb, offset-1, 1, tlv_len);\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_fault_hdl_overr_tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(cfdp_fault_hdl_overr_tree, hf_cfdp_handler_code, tvb, offset, 1, aux_byte);\r
- offset += 1;\r
-\r
- return offset;\r
-}\r
-\r
-/* Dissect the Flow Label TLV */\r
-static guint32 dissect_cfdp_flow_label_tlv(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){\r
-\r
- guint8 tlv_len;\r
- proto_item *cfdp_flow_label = NULL;\r
- proto_tree *cfdp_flow_label_tree;\r
-\r
- guint32 offset = ext_offset;\r
-\r
- /* Get tlv len */\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
-\r
- /* Create a subtree */\r
- cfdp_flow_label = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Flow Label TLV");\r
- cfdp_flow_label_tree = proto_item_add_subtree(cfdp_flow_label, ett_cfdp_flow_label);\r
-\r
- /* It is undefined, so no specific encoding */\r
- proto_tree_add_text(cfdp_flow_label_tree, tvb, offset, tlv_len, "Flow label");\r
-\r
- return offset;\r
-}\r
-\r
-/* Dissect the End of File PDU */\r
-static guint32 dissect_cfdp_eof_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ext_offset, guint ext_packet_len){\r
-\r
- guint8 aux_byte, tlv_type, tlv_len;\r
- proto_item *cfdp_fault_location = NULL;\r
- proto_tree *cfdp_fault_location_tree;\r
-\r
- guint32 offset = ext_offset;\r
- guint cfdp_packet_data_length = ext_packet_len;\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(tree, hf_cfdp_spare_four, tvb, offset, 1, aux_byte);\r
- offset +=1;\r
-\r
- col_add_fstr(pinfo->cinfo, COL_INFO, "EOF (%s)", val_to_str((aux_byte & 0xF0) >> 4, cfdp_condition_codes, "Reserved Code"));\r
-\r
- proto_tree_add_item(tree, hf_cfdp_file_checksum, tvb, offset, 4, ENC_BIG_ENDIAN);\r
- offset += 4;\r
-\r
- proto_tree_add_item(tree, hf_cfdp_file_size, tvb, offset, 4, ENC_BIG_ENDIAN);\r
- offset += 4;\r
-\r
- if(offset < cfdp_packet_data_length){\r
- tlv_type = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- if(tlv_type == FAULT_LOCATION){\r
- tlv_len = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- cfdp_fault_location = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Fault location TLV");\r
- cfdp_fault_location_tree = proto_item_add_subtree(cfdp_fault_location, ett_cfdp_fault_location);\r
-\r
- proto_tree_add_text(cfdp_fault_location_tree, tvb, offset, tlv_len, "Entity");\r
- offset +=tlv_len;\r
- }\r
- }\r
-\r
- return offset;\r
-}\r
-\r
-/* Dissect the Finished PDU */\r
-static guint32 dissect_cfdp_finished_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ext_offset, guint ext_packet_len){\r
-\r
- guint32 offset = ext_offset;\r
- guint8 aux_byte, tlv_type;\r
-\r
-\r
- guint cfdp_packet_data_length = ext_packet_len;\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(tree, hf_cfdp_end_system_stat, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(tree, hf_cfdp_delivery_code, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(tree, hf_cfdp_file_stat, tvb, offset, 1, aux_byte);\r
- offset +=1;\r
-\r
- col_add_fstr(pinfo->cinfo, COL_INFO, "Finished PDU (%s)", val_to_str((aux_byte & 0xF0) >> 4, cfdp_condition_codes, "Reserved Code"));\r
-\r
- /* Add TLV fields */\r
- while(offset < cfdp_packet_data_length){\r
- tlv_type = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- switch(tlv_type){\r
- case FILESTORE_RESP:\r
- offset = dissect_cfdp_filestore_resp_tlv(tvb, tree, offset);\r
- break;\r
-\r
- case FAULT_LOCATION:\r
- offset = dissect_cfdp_fault_location_tlv(tvb, tree, offset);\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- }\r
-\r
- return offset;\r
-}\r
-\r
-/* Dissect the ACK PDU */\r
-static guint32 dissect_cfdp_ack_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ext_offset){\r
-\r
- guint8 aux_byte;\r
- guint32 offset = ext_offset;\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(tree, hf_cfdp_dir_code_ack, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(tree, hf_cfdp_dir_subtype_ack, tvb, offset, 1, aux_byte);\r
- offset +=1;\r
-\r
- col_add_fstr(pinfo->cinfo, COL_INFO, "ACK PDU (%s)", val_to_str((aux_byte & 0xF0) >> 4, cfdp_directive_codes, "Unknown PDU"));\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(tree, hf_cfdp_spare_two, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(tree, hf_cfdp_trans_stat_ack, tvb, offset, 1, aux_byte);\r
- offset +=1;\r
-\r
- return offset;\r
-}\r
-\r
-/* Dissect the Metadata PDU */\r
-static guint32 dissect_cfdp_metadata_pdu(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset, guint ext_packet_len){\r
-\r
- guint8 aux_byte, tlv_type;\r
- guint cfdp_packet_data_length = ext_packet_len;\r
-\r
- guint32 offset = ext_offset;\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(tree, hf_cfdp_segment_control, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(tree, hf_cfdp_spare_seven, tvb, offset, 1, aux_byte);\r
- offset +=1;\r
- proto_tree_add_item(tree, hf_cfdp_file_size, tvb, offset, 4, ENC_BIG_ENDIAN);\r
- offset += 4;\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- if(aux_byte >0){\r
- proto_tree_add_item(tree, hf_cfdp_src_file_name, tvb, offset+1, aux_byte, ENC_ASCII|ENC_NA);\r
- offset += aux_byte+1;\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_item(tree, hf_cfdp_dst_file_name, tvb, offset+1, aux_byte, ENC_ASCII|ENC_NA);\r
- offset += aux_byte+1;\r
- }\r
- /* Add TLV fields */\r
- while(offset < cfdp_packet_data_length){\r
- tlv_type = tvb_get_guint8(tvb, offset);\r
- offset += 1;\r
- switch(tlv_type){\r
- case FILESTORE_REQ:\r
- offset = dissect_cfdp_filestore_req_tlv(tvb, tree, offset);\r
- break;\r
-\r
- case MSG_TO_USER:\r
- offset = dissect_cfdp_msg_to_user_tlv(tvb, tree, offset);\r
- break;\r
-\r
- case FAULT_HDL_OVERR:\r
- offset = dissect_cfdp_fault_handler_overr_tlv(tvb, tree, offset);\r
- break; \r
-\r
- case FLOW_LABEL:\r
- offset = dissect_cfdp_flow_label_tlv(tvb, tree, offset);\r
- break;\r
- \r
- default:\r
- break;\r
- }\r
- }\r
-\r
- return offset;\r
-}\r
-\r
-/* Dissect the NAK PDU */\r
-static guint32 dissect_cfdp_nak_pdu(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset, guint ext_packet_len){\r
-\r
- guint32 offset = ext_offset;\r
- guint cfdp_packet_data_length = ext_packet_len;\r
-\r
- proto_tree_add_item(tree, hf_cfdp_nak_st_scope, tvb, offset, 4, ENC_BIG_ENDIAN);\r
- offset += 4;\r
- proto_tree_add_item(tree, hf_cfdp_nak_sp_scope, tvb, offset, 4, ENC_BIG_ENDIAN);\r
- offset += 4;\r
- proto_tree_add_text(tree, tvb, offset, cfdp_packet_data_length-9, "Segment requests");\r
- offset += cfdp_packet_data_length-9;\r
-\r
- return offset;\r
-}\r
-\r
-/* Dissect the Prompt PDU */\r
-static guint32 dissect_cfdp_prompt_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ext_offset){\r
-\r
- guint8 aux_byte;\r
- guint32 offset = ext_offset;\r
-\r
- aux_byte = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(tree, hf_cfdp_response_req, tvb, offset, 1, aux_byte);\r
- proto_tree_add_uint(tree, hf_cfdp_spare_seven, tvb, offset, 1, aux_byte);\r
- offset +=1;\r
-\r
- col_add_fstr(pinfo->cinfo, COL_INFO, "Prompt PDU (%s)", val_to_str((aux_byte & 0x80) >> 7, cfdp_response_req, "Unknown"));\r
-\r
- return offset;\r
-}\r
-\r
-/* Dissect the Keep Alive PDU */\r
-static guint32 dissect_cfdp_keep_alive_pdu(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){\r
-\r
- guint32 offset = ext_offset;\r
-\r
- proto_tree_add_item(tree, hf_cfdp_progress, tvb, offset, 4, ENC_BIG_ENDIAN);\r
- offset += 4;\r
-\r
- return offset;\r
-}\r
-\r
-/* Code to actually dissect the packets */\r
-static void\r
-dissect_cfdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)\r
-{\r
- int offset = 0;\r
- proto_item *cfdp_packet;\r
- proto_item *cfdp_tree = NULL;\r
- proto_item *cfdp_header = NULL;\r
- proto_item *cfdp_file_directive_header = NULL;\r
- proto_item *cfdp_file_data_header = NULL;\r
- proto_item *cfdp_crc = NULL;\r
- proto_tree *cfdp_header_tree;\r
- proto_tree *cfdp_file_directive_header_tree;\r
- proto_tree *cfdp_file_data_header_tree;\r
- proto_tree *cfdp_crc_tree;\r
- gint cfdp_packet_length;\r
- gint cfdp_packet_reported_length;\r
- gint cfdp_packet_header_length;\r
- gint cfdp_packet_data_length;\r
- gint length;\r
- guint8 first_byte = 0;\r
- guint8 second_byte = 0;\r
- guint8 directive_code = 0;\r
- gint len_ent_id = 0;\r
- gint len_tseq_num = 0;\r
-\r
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "CFDP");\r
-\r
- cfdp_packet_reported_length = tvb_reported_length_remaining(tvb, 0);\r
- cfdp_packet_header_length = (tvb_get_guint8(tvb, 3) & HDR_LEN_TSEQ_NUM) + 1 + 2*(((tvb_get_guint8(tvb, 3) & HDR_LEN_ENT_ID) >>4) +1) + CFDP_HEADER_FIXED_FIELDS_LEN;\r
- cfdp_packet_length = tvb_get_ntohs(tvb, 1) + cfdp_packet_header_length;\r
-\r
-\r
-\r
- /* Min length is size of header plus 2 octets, whereas max length is reported length.\r
- * If the length field in the CFDP header is outside of these bounds,\r
- * use the value it violates. Otherwise, use the length field value.\r
- */\r
- if (cfdp_packet_length > cfdp_packet_reported_length)\r
- length = cfdp_packet_reported_length;\r
- else if (cfdp_packet_length < cfdp_packet_header_length + 2)\r
- length = cfdp_packet_header_length + 2;\r
- else\r
- length = cfdp_packet_length;\r
-\r
- /* Build the cfdp tree */\r
- cfdp_packet = proto_tree_add_item(tree, proto_cfdp, tvb, 0, length, ENC_NA);\r
- cfdp_tree = proto_item_add_subtree(cfdp_packet, ett_cfdp);\r
-\r
- cfdp_header = proto_tree_add_text(cfdp_tree, tvb, offset, cfdp_packet_header_length, "CFDP Header");\r
- cfdp_header_tree=proto_item_add_subtree(cfdp_header, ett_cfdp_header);\r
-\r
- first_byte = tvb_get_guint8(tvb, offset);\r
-\r
- /* CRC code is not included in the packet data length */\r
- cfdp_packet_data_length = tvb_get_ntohs(tvb, 1)-2*((first_byte & HDR_CRCF) >>1);\r
-\r
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_version, tvb, offset, 1, first_byte);\r
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_pdu_type, tvb, offset, 1, first_byte);\r
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_direction, tvb, offset, 1, first_byte);\r
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_trans_mode, tvb, offset, 1, first_byte);\r
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_crc_flag, tvb, offset, 1, first_byte);\r
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_res1, tvb, offset, 1, first_byte);\r
- offset += 1;\r
-\r
- proto_tree_add_item(cfdp_header_tree, hf_cfdp_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);\r
- offset += 2;\r
-\r
- second_byte = tvb_get_guint8(tvb, offset);\r
-\r
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_res2, tvb, offset, 1, second_byte);\r
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_entid_length, tvb, offset, 1, second_byte);\r
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_res3, tvb, offset, 1, second_byte);\r
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, second_byte);\r
- offset += 1;\r
-\r
- len_ent_id = ((second_byte & HDR_LEN_ENT_ID) >> 4) + 1;\r
- dissect_cfdp_src_entity_id(tvb, cfdp_header_tree, offset, len_ent_id);\r
- offset += len_ent_id;\r
-\r
- len_tseq_num = (second_byte & HDR_LEN_TSEQ_NUM) +1;\r
- dissect_cfdp_tseq_num(tvb, cfdp_header_tree, offset, len_tseq_num);\r
- offset += len_tseq_num;\r
-\r
- dissect_cfdp_dst_entity_id(tvb, cfdp_header_tree, offset, len_ent_id);\r
- offset += len_ent_id;\r
-\r
- proto_item_set_end(cfdp_header, tvb, offset);\r
-\r
- /* Build the File Directive or the File Data tree */\r
- if(!(first_byte & HDR_TYPE_CFDP))\r
- {\r
-\r
- cfdp_file_directive_header = proto_tree_add_text(cfdp_tree, tvb, offset, cfdp_packet_data_length, "CFDP File Directive");\r
- cfdp_file_directive_header_tree = proto_item_add_subtree(cfdp_file_directive_header, ett_cfdp_file_directive_header);\r
-\r
- directive_code = tvb_get_guint8(tvb, offset);\r
- proto_tree_add_uint(cfdp_file_directive_header_tree, hf_cfdp_file_directive_type, tvb, offset, 1, directive_code);\r
- offset += 1;\r
-\r
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s PDU", val_to_str(directive_code, cfdp_directive_codes, "Reserved (%d)"));\r
-\r
- switch(directive_code)\r
- {\r
- case EOF_PDU:\r
- offset = dissect_cfdp_eof_pdu(tvb, pinfo, cfdp_file_directive_header_tree, offset, cfdp_packet_data_length);\r
- break;\r
-\r
- case FINISHED_PDU:\r
- offset = dissect_cfdp_finished_pdu(tvb, pinfo, cfdp_file_directive_header_tree, offset, cfdp_packet_data_length);\r
- break;\r
-\r
- case ACK_PDU:\r
- offset = dissect_cfdp_ack_pdu(tvb, pinfo, cfdp_file_directive_header_tree, offset);\r
- break;\r
-\r
- case METADATA_PDU:\r
- offset = dissect_cfdp_metadata_pdu(tvb, cfdp_file_directive_header_tree, offset, cfdp_packet_data_length);\r
- break;\r
-\r
- case NAK_PDU:\r
- offset = dissect_cfdp_nak_pdu(tvb, cfdp_file_directive_header_tree, offset, cfdp_packet_data_length);\r
- break;\r
-\r
- case PROMPT_PDU:\r
- offset = dissect_cfdp_prompt_pdu(tvb, pinfo, cfdp_file_directive_header_tree, offset);\r
- break;\r
-\r
- case KEEP_ALIVE_PDU:\r
- offset = dissect_cfdp_keep_alive_pdu(tvb, cfdp_file_directive_header_tree, offset);\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- proto_item_set_end(cfdp_file_directive_header, tvb, offset);\r
-\r
- }else{\r
-\r
- col_add_fstr(pinfo->cinfo, COL_INFO, "File Data PDU");\r
-\r
- cfdp_file_data_header = proto_tree_add_text(cfdp_tree, tvb, offset, cfdp_packet_data_length, "CFDP File Data");\r
- cfdp_file_data_header_tree = proto_item_add_subtree(cfdp_file_data_header, ett_cfdp_file_data_header);\r
-\r
- proto_tree_add_item(cfdp_file_data_header_tree, hf_cfdp_file_data_offset, tvb, offset, 4, ENC_BIG_ENDIAN);\r
-\r
- offset += 4;\r
-\r
- proto_tree_add_text(cfdp_file_data_header_tree, tvb, offset, cfdp_packet_data_length-4, "User Data");\r
- offset += cfdp_packet_data_length-4;\r
-\r
- }\r
- if(first_byte & HDR_CRCF){\r
- cfdp_crc = proto_tree_add_text(cfdp_tree, tvb, offset, 2, "CRC");\r
- cfdp_crc_tree = proto_item_add_subtree(cfdp_crc, ett_cfdp_crc);\r
-\r
- proto_tree_add_item(cfdp_crc_tree, hf_cfdp_crc, tvb, offset, 2, ENC_BIG_ENDIAN);\r
- offset+=2;\r
-\r
- proto_item_set_end(cfdp_crc, tvb, offset);\r
- }\r
- /* Give the data dissector any bytes past the CFDP packet length */\r
- call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree);\r
-}\r
-\r
-void\r
-proto_register_cfdp(void)\r
-{\r
- static hf_register_info hf[] = {\r
-\r
- { &hf_cfdp_version,\r
- { "Version", "cfdp.version",\r
- FT_UINT8, BASE_DEC, NULL, HDR_VERSION_CFDP,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_pdu_type,\r
- { "PDU Type", "cfdp.pdu_type",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_pdu_type), HDR_TYPE_CFDP,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_direction,\r
- { "Direction", "cfdp.direction",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_direction), HDR_DIR,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_trans_mode,\r
- { "Trans. Mode", "cfdp.trans_mode",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_trans_mode), HDR_TMODE,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_crc_flag,\r
- { "CRC Flag", "cfdp.crc_flag",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_crc_flag), HDR_CRCF,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_res1,\r
- { "Bit reserved 1", "cfdp.res1",\r
- FT_UINT8, BASE_DEC, NULL, HDR_RES1,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_data_length,\r
- { "PDU Data length", "cfdp.data_length",\r
- FT_UINT16, BASE_DEC, NULL, 0x0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_res2,\r
- { "Bit reserved 2", "cfdp.res2",\r
- FT_UINT8, BASE_DEC, NULL, 0x80,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_entid_length,\r
- { "Length of entity IDs", "cfdp.entid_length",\r
- FT_UINT8, BASE_DEC, NULL, 0x70,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_res3,\r
- { "Bit reserved 3", "cfdp.res3",\r
- FT_UINT8, BASE_DEC, NULL, 0x08,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_transeqnum_length,\r
- { "Length of Transaction sequence number", "cfdp.transeqnum_length",\r
- FT_UINT8, BASE_DEC, NULL, 0x07,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_srcid,\r
- { "Source entity ID", "cfdp.srcid",\r
- FT_UINT64, BASE_DEC, NULL, 0x0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_transeqnum,\r
- { "Transaction sequence number", "cfdp.transeqnum",\r
- FT_UINT64, BASE_DEC, NULL, 0x0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_dstid,\r
- { "Destination entity ID", "cfdp.dstid",\r
- FT_UINT64, BASE_DEC, NULL, 0x0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_file_directive_type,\r
- { "File Directive type", "cfdp.fdtype",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_file_directive_type), 0x0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_file_data_offset,\r
- { "Offset", "cfdp.offset",\r
- FT_UINT32, BASE_DEC, NULL, 0x0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_progress,\r
- { "Progress", "cfdp.progress",\r
- FT_UINT32, BASE_DEC, NULL, 0x0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_dir_code_ack,\r
- { "PDU acknowledged", "cfdp.dir_code_ack",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_file_directive_type), 0xf0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_dir_subtype_ack,\r
- { "Directive subtype code", "cfdp.dir_subtype_ack",\r
- FT_UINT8, BASE_DEC, NULL, 0x0f,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_condition_code,\r
- { "Condition Code", "cfdp.condition_code",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_condition_codes), 0xf0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_spare_one,\r
- { "Spare", "cfdp.spare_one",\r
- FT_UINT8, BASE_DEC, NULL, 0x08,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_spare_one_2,\r
- { "Spare", "cfdp.spare_one_2",\r
- FT_UINT8, BASE_DEC, NULL, 0x80,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_spare_two,\r
- { "Spare", "cfdp.spare_two",\r
- FT_UINT8, BASE_DEC, NULL, 0x0c,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_spare_four,\r
- { "Spare", "cfdp.spare_four",\r
- FT_UINT8, BASE_DEC, NULL, 0x0f,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_spare_five,\r
- { "Spare", "cfdp.spare_five",\r
- FT_UINT8, BASE_DEC, NULL, 0x3E,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_spare_seven,\r
- { "Spare", "cfdp.spare_seven",\r
- FT_UINT8, BASE_DEC, NULL, 0x7f,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_spare_seven_2,\r
- { "Spare", "cfdp.spare_seven_2",\r
- FT_UINT8, BASE_DEC, NULL, 0xfe,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_trans_stat_ack,\r
- { "Transaction status", "cfdp.trans_stat_ack",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_trans_stat_ack), 0x03,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_trans_stat,\r
- { "Transaction status", "cfdp.trans_stat",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_trans_stat_ack), 0xC0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_trans_stat_2,\r
- { "Transaction status", "cfdp.trans_stat_2",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_trans_stat_ack), 0x60,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_file_checksum,\r
- { "Checksum", "cfdp.checksum",\r
- FT_UINT32, BASE_HEX, NULL, 0x0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_file_size,\r
- { "File size", "cfdp.file_size",\r
- FT_UINT32, BASE_DEC, NULL, 0x0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_end_system_stat,\r
- { "End system status", "cfdp.end_system_stat",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_end_system_stat), 0x08,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_delivery_code,\r
- { "Delivery code", "cfdp.delivery_code",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_delivery_code), 0x04,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_file_stat,\r
- { "File status", "cfdp.file_status",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_file_stat), 0x03,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_segment_control,\r
- { "Segmentation control", "cfdp.segment_control",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_segment_control), 0x80,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_tlv_len,\r
- { "Length", "cfdp.tlv_length",\r
- FT_UINT8, BASE_DEC, NULL, 0x0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_src_file_name,\r
- {"Source file name", "cfdp.src_file_name", FT_STRING, BASE_NONE, NULL, 0x0,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_dst_file_name,\r
- {"Destination file name", "cfdp.dst_file_name", FT_STRING, BASE_NONE, NULL, 0x0,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_first_file_name,\r
- {"First file name", "cfdp.first_file_name", FT_STRING, BASE_NONE, NULL, 0x0,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_second_file_name,\r
- {"Second file name", "cfdp.second_file_name", FT_STRING, BASE_NONE, NULL, 0x0,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_nak_st_scope,\r
- {"Start of scope", "cfdp.nak_st_scope", FT_UINT32, BASE_DEC, NULL, 0x0,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_nak_sp_scope,\r
- {"End of scope", "cfdp.nak_sp_scope", FT_UINT32, BASE_DEC, NULL, 0x0,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_crc,\r
- {"CRC", "cfdp.crc", FT_UINT16, BASE_HEX, NULL, 0x0,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_action_code,\r
- {"Action code", "cfdp.action_code", FT_UINT8, BASE_DEC, VALS(cfdp_action_code), 0xF0,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_status_code_1,\r
- {"Status code", "cfdp.status_code_1", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_1), 0x0F,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_status_code_2,\r
- {"Status code", "cfdp.status_code_2", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_2), 0x0F,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_status_code_3,\r
- {"Status code", "cfdp.status_code_3", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_3), 0x0F,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_status_code_4,\r
- {"Status code", "cfdp.status_code_4", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_4), 0x0F,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_status_code_5,\r
- {"Status code", "cfdp.status_code_5", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_5), 0x0F,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_status_code_6,\r
- {"Status code", "cfdp.status_code_6", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_6), 0x0F,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_status_code_7,\r
- {"Status code", "cfdp.status_code_7", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_7), 0x0F,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_status_code_8,\r
- {"Status code", "cfdp.status_code_8", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_8), 0x0F,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_handler_code,\r
- { "Handler Code", "cfdp.handler_code",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_handler_codes), 0x0F,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_trans_mode_msg,\r
- { "Trans. Mode", "cfdp.trans_mode_msg",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_trans_mode), 0x01,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_proxy_msg_type,\r
- { "Proxy Message Type", "cfdp.proxy_msg_type",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_proxy_msg_type), 0x0,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_proxy_segment_control,\r
- { "Segmentation control", "cfdp.proxy_segment_control",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_segment_control), 0x01,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_proxy_delivery_code,\r
- { "Delivery code", "cfdp.proxy_delivery_code",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_delivery_code), 0x04,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_response_req,\r
- { "Response required", "cfdp.response_req",\r
- FT_UINT8, BASE_DEC, VALS(cfdp_response_req), 0x80,\r
- NULL, HFILL }\r
- },\r
- { &hf_cfdp_directory_name,\r
- {"Directory Name", "cfdp.directory_name", FT_STRING, BASE_NONE, NULL, 0x0,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_directory_file_name,\r
- {"Directory File Name", "cfdp.directory_file_name", FT_STRING, BASE_NONE, NULL, 0x0,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_listing_resp_code,\r
- {"Listing Response Code", "cfdp.listing_resp_code", \r
- FT_UINT8, BASE_DEC, VALS(cfdp_listing_resp_code), 0x80,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_report_file_name,\r
- {"Report File Name", "cfdp.report_file_name", FT_STRING, BASE_NONE, NULL, 0x0,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_rep_resp_code,\r
- {"Report Response Code", "cfdp.rep_resp_code", \r
- FT_UINT8, BASE_DEC, VALS(cfdp_rep_resp_code), 0x01,\r
- NULL, HFILL}\r
- },\r
- { &hf_cfdp_suspension_ind,\r
- {"Suspension indicator", "cfdp.suspension_ind", \r
- FT_UINT8, BASE_DEC, VALS(cfdp_suspension_ind), 0x80,\r
- NULL, HFILL}\r
- }\r
-\r
- };\r
-\r
- /* Setup protocol subtree array */\r
- static gint *ett[] = {\r
- &ett_cfdp,\r
- &ett_cfdp_header,\r
- &ett_cfdp_file_directive_header,\r
- &ett_cfdp_file_data_header,\r
- &ett_cfdp_fault_location,\r
- &ett_cfdp_crc,\r
- &ett_cfdp_filestore_req,\r
- &ett_cfdp_filestore_resp,\r
- &ett_cfdp_msg_to_user,\r
- &ett_cfdp_fault_hdl_overr,\r
- &ett_cfdp_flow_label\r
- };\r
-\r
- /* Register the protocol name and description */\r
- proto_cfdp = proto_register_protocol("CFDP", "CFDP", "cfdp");\r
-\r
- /* Required function calls to register the header fields and subtrees used */\r
- proto_register_field_array(proto_cfdp, hf, array_length(hf));\r
- proto_register_subtree_array(ett, array_length(ett));\r
-\r
- register_dissector ( "cfdp", dissect_cfdp, proto_cfdp );\r
-}\r
-\r
-void\r
-proto_reg_handoff_cfdp(void)\r
-{\r
- static dissector_handle_t cfdp_handle;\r
-\r
- cfdp_handle = create_dissector_handle(dissect_cfdp, proto_cfdp);\r
- dissector_add_uint("ccsds.apid", CFDP_APID, cfdp_handle);\r
- dissector_add_handle ( "udp.port", cfdp_handle ); /* for 'decode as' */\r
- data_handle = find_dissector("data");\r
-}\r
-\r
-/*\r
- * Editor modelines - http://www.wireshark.org/tools/modelines.html\r
- *\r
- * Local variables:\r
- * c-basic-offset: 4\r
- * tab-width: 4\r
- * indent-tabs-mode: t\r
- * End:\r
- *\r
- * vi: set shiftwidth=4 tabstop=4 noexpandtab:\r
- * :indentSize=4:tabSize=4:noTabs=false:\r
- */ \r
+/* packet-cfdp.c
+ * Routines for CCSDS File Delivery Protocol (CFDP) dissection
+ * Copyright 2013, Juan Antonio Montesinos juan.mondl@gmail.com
+ *
+ * $Id$
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/expert.h>
+#include <epan/prefs.h>
+
+
+/* The CFDP standard can be found here:
+ * http://public.ccsds.org/publications/archive/727x0b4.pdf
+ *
+ * The Store and Forward Overlay Operations are not included.
+ */
+
+/* Initialize the protocol and registered fields */
+static int proto_cfdp = -1;
+static int hf_cfdp_version = -1;
+static int hf_cfdp_pdu_type = -1;
+static int hf_cfdp_direction = -1;
+static int hf_cfdp_trans_mode = -1;
+static int hf_cfdp_crc_flag = -1;
+static int hf_cfdp_res1 = -1;
+static int hf_cfdp_data_length = -1;
+static int hf_cfdp_res2 = -1;
+static int hf_cfdp_entid_length = -1;
+static int hf_cfdp_res3 = -1;
+static int hf_cfdp_transeqnum_length = -1;
+static int hf_cfdp_srcid = -1;
+static int hf_cfdp_transeqnum = -1;
+static int hf_cfdp_dstid = -1;
+static int hf_cfdp_file_directive_type = -1;
+static int hf_cfdp_file_data_offset = -1;
+static int hf_cfdp_progress = -1;
+static int hf_cfdp_dir_code_ack = -1;
+static int hf_cfdp_dir_subtype_ack = -1;
+static int hf_cfdp_condition_code = -1;
+static int hf_cfdp_spare_one = -1;
+static int hf_cfdp_spare_one_2 = -1;
+static int hf_cfdp_spare_two = -1;
+static int hf_cfdp_spare_four = -1;
+static int hf_cfdp_spare_five = -1;
+static int hf_cfdp_spare_seven = -1;
+static int hf_cfdp_spare_seven_2 = -1;
+static int hf_cfdp_trans_stat_ack = -1;
+static int hf_cfdp_file_checksum = -1;
+static int hf_cfdp_file_size = -1;
+static int hf_cfdp_end_system_stat = -1;
+static int hf_cfdp_delivery_code = -1;
+static int hf_cfdp_file_stat = -1;
+static int hf_cfdp_segment_control = -1;
+static int hf_cfdp_src_file_name = -1;
+static int hf_cfdp_dst_file_name = -1;
+static int hf_cfdp_first_file_name = -1;
+static int hf_cfdp_second_file_name = -1;
+static int hf_cfdp_nak_st_scope = -1;
+static int hf_cfdp_nak_sp_scope = -1;
+static int hf_cfdp_crc = -1;
+static int hf_cfdp_action_code = -1;
+static int hf_cfdp_status_code_1 = -1;
+static int hf_cfdp_status_code_2 = -1;
+static int hf_cfdp_status_code_3 = -1;
+static int hf_cfdp_status_code_4 = -1;
+static int hf_cfdp_status_code_5 = -1;
+static int hf_cfdp_status_code_6 = -1;
+static int hf_cfdp_status_code_7 = -1;
+static int hf_cfdp_status_code_8 = -1;
+static int hf_cfdp_handler_code = -1;
+static int hf_cfdp_trans_mode_msg = -1;
+static int hf_cfdp_proxy_msg_type = -1;
+static int hf_cfdp_proxy_segment_control = -1;
+static int hf_cfdp_proxy_delivery_code = -1;
+static int hf_cfdp_response_req = -1;
+static int hf_cfdp_directory_name = -1;
+static int hf_cfdp_directory_file_name = -1;
+static int hf_cfdp_listing_resp_code = -1;
+static int hf_cfdp_report_file_name = -1;
+static int hf_cfdp_trans_stat = -1;
+static int hf_cfdp_trans_stat_2 = -1;
+static int hf_cfdp_rep_resp_code = -1;
+static int hf_cfdp_suspension_ind = -1;
+static int hf_cfdp_tlv_len =- 1;
+
+/* Initialize the subtree pointers */
+static gint ett_cfdp = -1;
+static gint ett_cfdp_header = -1;
+static gint ett_cfdp_file_directive_header = -1;
+static gint ett_cfdp_file_data_header = -1;
+static gint ett_cfdp_fault_location = -1;
+static gint ett_cfdp_crc = -1;
+static gint ett_cfdp_filestore_req = -1;
+static gint ett_cfdp_filestore_resp = -1;
+static gint ett_cfdp_msg_to_user = -1;
+static gint ett_cfdp_fault_hdl_overr = -1;
+static gint ett_cfdp_flow_label = -1;
+
+/* Generic data handle */
+static dissector_handle_t data_handle;
+
+/* Some parameters */
+#define CFDP_HEADER_FIXED_FIELDS_LEN 4
+#define CFDP_APID 2045
+
+/* Bitmask for the first byte of the Header */
+#define HDR_VERSION_CFDP 0xe0
+#define HDR_TYPE_CFDP 0x10
+#define HDR_DIR 0x08
+#define HDR_TMODE 0x04
+#define HDR_CRCF 0x02
+#define HDR_RES1 0x01
+
+/* Bitmask for the second byte of the Header */
+#define HDR_RES2 0x80
+#define HDR_LEN_ENT_ID 0x70
+#define HDR_RES3 0x08
+#define HDR_LEN_TSEQ_NUM 0x07
+
+/* File Directive Codes */
+#define EOF_PDU 4
+#define FINISHED_PDU 5
+#define ACK_PDU 6
+#define METADATA_PDU 7
+#define NAK_PDU 8
+#define PROMPT_PDU 9
+#define KEEP_ALIVE_PDU 12
+
+/* TLV Types */
+#define FILESTORE_REQ 0
+#define FILESTORE_RESP 1
+#define MSG_TO_USER 2
+#define FAULT_HDL_OVERR 4
+#define FLOW_LABEL 5
+#define FAULT_LOCATION 6
+
+/* ID for reserved CFDP Messages */
+#define CFDP_MSG_TO_USER 0x63666470
+
+/* Proxy Operations Message Types */
+#define PROXY_PUT_REQ 0x00
+#define PROXY_MSG_TO_USER 0x01
+#define PROXY_FILESTORE_REQ 0x02
+#define PROXY_FAULT_HDL_OVERR 0x03
+#define PROXY_TRANS_MODE 0x04
+#define PROXY_FLOW_LABEL 0x05
+#define PROXY_SEGMENT_CONTROL 0x06
+#define PROXY_PUT_RESP 0x07
+#define PROXY_FILESTORE_RESP 0x08
+#define PROXY_PUT_CANCEL 0x09
+#define ORIG_TRANS_ID 0x0A
+#define DIRECTORY_LIST_REQ 0x10
+#define DIRECTORY_LIST_RESP 0x11
+#define REMOTE_STAT_REP_REQ 0x20
+#define REMOTE_STAT_REP_RESP 0x21
+#define REMOTE_SUSPEND_REQ 0x30
+#define REMOTE_SUSPEND_RESP 0x31
+#define REMOTE_RESUME_REQ 0x38
+#define REMOTE_RESUME_RESP 0x39
+
+/* PDU Type */
+static const value_string cfdp_pdu_type[] = {
+ { 0, "File Directive" },
+ { 1, "File Data" },
+ { 0, NULL }
+};
+
+/* PDU Direction */
+static const value_string cfdp_direction[] = {
+ { 0, "Toward file receiver" },
+ { 1, "Toward file sender" },
+ { 0, NULL }
+};
+
+/* Transmission mode */
+static const value_string cfdp_trans_mode[] = {
+ { 0, "Acknowledged" },
+ { 1, "Unacknowledged" },
+ { 0, NULL }
+};
+
+/* CRC */
+static const value_string cfdp_crc_flag[] = {
+ { 0, "CRC not present" },
+ { 1, "CRC present" },
+ { 0, NULL }
+};
+
+/* File Directive PDU Type */
+static const value_string cfdp_file_directive_type[] = {
+ {4, "EOF PDU"},
+ {5, "Finished PDU"},
+ {6, "ACK PDU"},
+ {7, "Metadata PDU"},
+ {8, "NACK PDU"},
+ {9, "Prompt PDU"},
+ {12, "Keep Alive PDU"},
+ {0, NULL}
+};
+
+/* Condition codes */
+static const value_string cfdp_condition_codes[] = {
+ {0, "No error"},
+ {1, "Positive ACK limit reached"},
+ {2, "Keep alive limit reached"},
+ {3, "Invalid transmission mode"},
+ {4, "Filestore rejection"},
+ {5, "File checksum failure"},
+ {6, "File size error"},
+ {7, "NAK limit reached"},
+ {8, "Inactivity detected"},
+ {9, "Check limit reached"},
+ {14, "Suspend.request received"},
+ {15, "Cancel.request received"},
+ { 0, NULL }
+};
+
+/* Transaction status */
+static const value_string cfdp_trans_stat_ack[] = {
+ { 0, "Undefined" },
+ { 1, "Active" },
+ { 2, "Terminated" },
+ { 3, "Unrecognized" },
+ { 0, NULL }
+};
+
+/* End system status */
+static const value_string cfdp_end_system_stat[] = {
+ { 0, "Generated by Waypoint" },
+ { 1, "Generated by End System" },
+ { 0, NULL }
+};
+
+/* Delivery code */
+static const value_string cfdp_delivery_code[] = {
+ { 0, "Data Complete" },
+ { 1, "Data incomplete" },
+ { 0, NULL }
+};
+
+/* Filestore operations action code */
+static const value_string cfdp_action_code[] = {
+ { 0, "Create File" },
+ { 1, "Delete File" },
+ { 2, "Rename File" },
+ { 3, "Append File" },
+ { 4, "Replace File" },
+ { 5, "Create Directory" },
+ { 6, "Remove Directory" },
+ { 7, "Deny File (delete if present)" },
+ { 8, "Deny Directory (remove if present)" },
+ { 0, NULL }
+};
+
+/* Filestore operations status codes */
+static const value_string cfdp_status_code_1[] = {
+ { 0, "Successful" },
+ { 1, "Create not allowed" },
+ { 8, "Not performed" },
+ { 0, NULL }
+};
+
+static const value_string cfdp_status_code_2[] = {
+ { 0, "Successful" },
+ { 1, "File does not exist" },
+ { 2, "Delete not allowed" },
+ { 8, "Not performed" },
+ { 0, NULL }
+};
+
+static const value_string cfdp_status_code_3[] = {
+ { 0, "Successful" },
+ { 1, "Old File Name does not exist" },
+ { 2, "New File Name already exists" },
+ { 3, "Rename not allowed" },
+ { 8, "Not performed" },
+ { 0, NULL }
+};
+
+static const value_string cfdp_status_code_4[] = {
+ { 0, "Successful" },
+ { 1, "File Name 1 does not exist" },
+ { 2, "File Name 2 does not exist" },
+ { 3, "Append not allowed" },
+ { 8, "Not performed" },
+ { 0, NULL }
+};
+
+static const value_string cfdp_status_code_5[] = {
+ { 0, "Successful" },
+ { 1, "File Name 1 does not exist" },
+ { 2, "File Name 2 does not exist" },
+ { 3, "Replace not allowed" },
+ { 8, "Not performed" },
+ { 0, NULL }
+};
+
+static const value_string cfdp_status_code_6[] = {
+ { 0, "Successful" },
+ { 1, "Directory cannot be created" },
+ { 8, "Not performed" },
+ { 0, NULL }
+};
+
+static const value_string cfdp_status_code_7[] = {
+ { 0, "Successful" },
+ { 1, "Directory does not exist" },
+ { 2, "Delete not allowed" },
+ { 8, "Not performed" },
+ { 0, NULL }
+};
+
+static const value_string cfdp_status_code_8[] = {
+ { 0, "Successful" },
+ { 1, "Delete not allowed" },
+ { 8, "Not performed" },
+ { 0, NULL }
+};
+
+/* Finished PDU File Status */
+static const value_string cfdp_file_stat[] = {
+ { 0, "Delivery file discarded deliberately" },
+ { 1, "Delivery file discarded due to filestore rejection" },
+ { 2, "Delivery file retained in filestore successfully" },
+ { 3, "Delivery file status unreported" },
+ { 0, NULL }
+};
+
+/* Segmentation control */
+static const value_string cfdp_segment_control[] = {
+ { 0, "Record boundaries respected" },
+ { 1, "Record boundaries not respected" },
+ { 0, NULL }
+};
+
+/* Fault handler override Handler code*/
+static const value_string cfdp_handler_codes[] = {
+ { 1, "issue Notice of Cancellation" },
+ { 2, "issue Notice of Suspension" },
+ { 3, "Ignore error" },
+ { 4, "Abandon transaction" },
+ { 0, NULL }
+};
+
+/* Type of Proxy message */
+static const value_string cfdp_proxy_msg_type[] = {
+ {0x00, "Proxy Put Request"},
+ {0x01, "Proxy Message To User"},
+ {0x02, "Proxy Filestore Request"},
+ {0x03, "Proxy Fault Handler Override"},
+ {0x04, "Proxy Transmission Mode"},
+ {0x05, "Proxy Flow Label"},
+ {0x06, "Proxy Segmentation Control"},
+ {0x07, "Proxy Put Response"},
+ {0x08, "Proxy Filestore Response"},
+ {0x09, "Proxy Put Cancel"},
+ {0x0A, "Originating Transaction ID"},
+ {0x10, "Directory Listing Request"},
+ {0x11, "Directory Listing Response"},
+ {0x20, "Remote Status Report Request"},
+ {0x21, "Remote Status Report Response"},
+ {0x30, "Remote Suspend Request"},
+ {0x31, "Remote Suspend Response"},
+ {0x38, "Remote Resume Request"},
+ {0x39, "Remote Resume Response"},
+ { 0, NULL }
+};
+
+/* Prompt PDU Response required */
+static const value_string cfdp_response_req[] = {
+ { 0, "NAK" },
+ { 1, "Keep Alive" },
+ { 0, NULL }
+};
+
+/* Listing response code */
+static const value_string cfdp_listing_resp_code[] = {
+ { 0, "Successful" },
+ { 1, "Unsuccessful" },
+ { 0, NULL }
+};
+
+/* Report response code */
+static const value_string cfdp_rep_resp_code[] = {
+ { 0, "Unsuccessful" },
+ { 1, "Successful" },
+ { 0, NULL }
+};
+
+/* Suspension indication */
+static const value_string cfdp_suspension_ind[] = {
+ { 0, "Not Suspended" },
+ { 1, "Suspended" },
+ { 0, NULL }
+};
+
+/* File Directive codes */
+static const value_string cfdp_directive_codes[] = {
+ { 0x04, "EOF" },
+ { 0x05, "Finished" },
+ { 0x06, "ACK" },
+ { 0x07, "Metadata" },
+ { 0x08, "NAK" },
+ { 0x09, "Prompt" },
+ { 0x0C, "Keep Alive" },
+ { 0, NULL }
+};
+
+/* Dissect the Source Entity ID field */
+static void
+dissect_cfdp_src_entity_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 len_ent_id)
+{
+ if(len_ent_id > 0 && len_ent_id <= 8){
+ proto_tree_add_item(tree, hf_cfdp_srcid, tvb, offset, len_ent_id, ENC_BIG_ENDIAN);
+ }
+ else{
+ proto_tree_add_text(tree, tvb, offset, 0, "Wrong length for the entity ID");
+ }
+}
+
+/* Dissect the Destination Entity ID field */
+static void
+dissect_cfdp_dst_entity_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 len_ent_id)
+{
+ if(len_ent_id > 0 && len_ent_id <= 8){
+ proto_tree_add_item(tree, hf_cfdp_dstid, tvb, offset, len_ent_id, ENC_BIG_ENDIAN);
+ }
+ else{
+ proto_tree_add_text(tree, tvb, offset, 0, "Wrong length for the entity ID");
+ }
+}
+
+/* Dissect the Transaction Sequence Number field */
+static void
+dissect_cfdp_tseq_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 len_tseq_num)
+{
+ if(len_tseq_num > 0 && len_tseq_num <= 8){
+ proto_tree_add_item(tree, hf_cfdp_transeqnum, tvb, offset, len_tseq_num, ENC_BIG_ENDIAN);
+ }
+ else{
+ proto_tree_add_text(tree, tvb, offset, 0, "Wrong length for transaction sequence number");
+ }
+}
+
+/* Dissect the Filestore Request TLV */
+static guint32 dissect_cfdp_filestore_req_tlv(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){
+
+ guint8 aux_byte, tlv_len;
+ proto_item *cfdp_filestore_req = NULL;
+ proto_tree *cfdp_filestore_req_tree;
+
+ guint32 offset = ext_offset;
+
+ /* Get field length */
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ if(tlv_len > 0){
+ /* Create a TLV subtree */
+ cfdp_filestore_req = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Filestore Request TLV");
+ cfdp_filestore_req_tree = proto_item_add_subtree(cfdp_filestore_req, ett_cfdp_filestore_req);
+
+ proto_tree_add_uint(cfdp_filestore_req_tree, hf_cfdp_tlv_len, tvb, offset-1, 1, tlv_len);
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_filestore_req_tree, hf_cfdp_action_code, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_filestore_req_tree, hf_cfdp_spare_four, tvb, offset, 1, aux_byte);
+ offset += 1;
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ proto_tree_add_item(cfdp_filestore_req_tree, hf_cfdp_first_file_name, tvb, offset, aux_byte, ENC_ASCII|ENC_NA);
+ offset += aux_byte;
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ if(aux_byte > 0){
+ proto_tree_add_item(cfdp_filestore_req_tree, hf_cfdp_second_file_name, tvb, offset, aux_byte, ENC_ASCII|ENC_NA);
+ offset += aux_byte;
+ }
+ }
+
+ return offset;
+}
+
+/* Dissect the Filestore Response TLV */
+static guint32 dissect_cfdp_filestore_resp_tlv(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){
+
+ guint8 aux_byte, tlv_len;
+ proto_item *cfdp_filestore_resp = NULL;
+ proto_tree *cfdp_filestore_resp_tree;
+
+ guint32 offset = ext_offset;
+
+ /* Get field length */
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ if(tlv_len > 0){
+ /* Create a subtree */
+ cfdp_filestore_resp = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Filestore Response TLV");
+ cfdp_filestore_resp_tree = proto_item_add_subtree(cfdp_filestore_resp, ett_cfdp_filestore_resp);
+
+ proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_tlv_len, tvb, offset-1, 1, tlv_len);
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_action_code, tvb, offset, 1, aux_byte);
+ switch(aux_byte & 0xF0){
+ case 0:
+ proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_1, tvb, offset, 1, aux_byte);
+ break;
+ case 1:
+ proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_2, tvb, offset, 1, aux_byte);
+ break;
+ case 2:
+ proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_3, tvb, offset, 1, aux_byte);
+ break;
+ case 3:
+ proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_4, tvb, offset, 1, aux_byte);
+ break;
+ case 4:
+ proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_5, tvb, offset, 1, aux_byte);
+ break;
+ case 5:
+ proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_6, tvb, offset, 1, aux_byte);
+ break;
+ case 6:
+ proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_7, tvb, offset, 1, aux_byte);
+ break;
+ case 7: case 8:
+ proto_tree_add_uint(cfdp_filestore_resp_tree, hf_cfdp_status_code_8, tvb, offset, 1, aux_byte);
+ break;
+
+ default:
+ break;
+ }
+ offset += 1;
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ proto_tree_add_item(cfdp_filestore_resp_tree, hf_cfdp_first_file_name, tvb, offset, aux_byte, ENC_ASCII|ENC_NA);
+ offset += aux_byte;
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ if(aux_byte > 0){
+ proto_tree_add_item(cfdp_filestore_resp_tree, hf_cfdp_second_file_name, tvb, offset, aux_byte, ENC_ASCII|ENC_NA);
+ offset += aux_byte;
+ }
+ /* Filestore Message */
+ aux_byte = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ if(aux_byte > 0){
+ proto_tree_add_text(cfdp_filestore_resp_tree, tvb, offset, tlv_len, "Filestore Message");
+ offset += aux_byte;
+ }
+ }
+
+ return offset;
+}
+
+/* Dissect the Fault Location TLV */
+static guint32 dissect_cfdp_fault_location_tlv(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){
+
+ guint8 tlv_len;
+ proto_item *cfdp_fault_location = NULL;
+ proto_tree *cfdp_fault_location_tree;
+
+ guint32 offset = ext_offset;
+
+ /* Get field length */
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ if(tlv_len > 0){
+ /* Create a subtree */
+ cfdp_fault_location = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Fault location TLV");
+ cfdp_fault_location_tree = proto_item_add_subtree(cfdp_fault_location, ett_cfdp_fault_location);
+
+ proto_tree_add_uint(cfdp_fault_location_tree, hf_cfdp_tlv_len, tvb, offset-1, 1, tlv_len);
+
+ proto_tree_add_text(cfdp_fault_location_tree, tvb, offset, tlv_len, "Entity");
+ offset +=tlv_len;
+ }
+
+ return offset;
+}
+
+/* Dissect the Message to User TLV */
+static guint32 dissect_cfdp_msg_to_user_tlv(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){
+
+ guint8 aux_byte, tlv_type, tlv_len;
+ proto_item *cfdp_msg_to_user = NULL;
+ proto_tree *cfdp_msg_to_user_tree;
+
+ guint32 offset = ext_offset;
+ guint32 msg_to_user_id =0;
+ int len_ent_id = 0;
+ int len_tseq_num = 0;
+
+ /* Get tlv len */
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ /* Create a subtree */
+ cfdp_msg_to_user = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Message To User TLV");
+ cfdp_msg_to_user_tree = proto_item_add_subtree(cfdp_msg_to_user, ett_cfdp_filestore_resp);
+
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_tlv_len, tvb, offset-1, 1, tlv_len);
+
+ msg_to_user_id = tvb_get_ntohl(tvb, offset);
+ /* Proxy operations */
+ if(msg_to_user_id == CFDP_MSG_TO_USER){
+ offset += 4;
+ tlv_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_proxy_msg_type, tvb, offset, 1, tlv_type);
+ offset += 1;
+ switch(tlv_type){
+
+ case PROXY_PUT_REQ:
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ dissect_cfdp_dst_entity_id(tvb, cfdp_msg_to_user_tree, offset, tlv_len);
+ offset += tlv_len;
+
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_src_file_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);
+ offset += tlv_len;
+
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_dst_file_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);
+ offset += tlv_len;
+
+ break;
+
+ case PROXY_MSG_TO_USER:
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ proto_tree_add_text(cfdp_msg_to_user_tree, tvb, offset, tlv_len, "Message to User");
+ break;
+
+ case PROXY_FILESTORE_REQ:
+ offset = dissect_cfdp_filestore_req_tlv(tvb, cfdp_msg_to_user_tree, offset);
+ break;
+
+ case PROXY_FAULT_HDL_OVERR:
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_handler_code, tvb, offset, 1, aux_byte);
+ offset += 1;
+ break;
+
+ case PROXY_TRANS_MODE:
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_seven_2, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_trans_mode_msg, tvb, offset, 1, aux_byte);
+ offset += 1;
+ break;
+
+ case PROXY_FLOW_LABEL:
+ proto_tree_add_text(cfdp_msg_to_user_tree, tvb, offset, tlv_len, "Flow label");
+ break;
+
+ case PROXY_SEGMENT_CONTROL:
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_seven_2, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_proxy_segment_control, tvb, offset, 1, aux_byte);
+ offset += 1;
+ break;
+
+ case PROXY_PUT_RESP:
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_proxy_delivery_code, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_file_stat, tvb, offset, 1, aux_byte);
+ offset += 1;
+ break;
+
+ case PROXY_FILESTORE_RESP:
+ offset = dissect_cfdp_filestore_req_tlv(tvb, cfdp_msg_to_user_tree, offset);
+ break;
+
+ case PROXY_PUT_CANCEL:
+ break;
+
+ case ORIG_TRANS_ID:
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_res2, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_res3, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);
+ offset += 1;
+
+ len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;
+ dissect_cfdp_src_entity_id(tvb, cfdp_msg_to_user_tree, offset, len_ent_id);
+ offset += len_ent_id;
+
+ len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;
+ dissect_cfdp_tseq_num(tvb, cfdp_msg_to_user_tree, offset, len_tseq_num);
+ offset += len_tseq_num;
+
+ break;
+
+ case DIRECTORY_LIST_REQ:
+ /* Directory Name */
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_directory_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);
+ offset += tlv_len;
+ /* Directory File Name */
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_directory_file_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);
+ offset += tlv_len;
+ break;
+
+ case DIRECTORY_LIST_RESP:
+ /* Listing Response Code */
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_listing_resp_code, tvb, offset, 1, aux_byte);
+ offset += 1;
+ /* Directory Name */
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_directory_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);
+ offset += tlv_len;
+ /* Directory File Name */
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_directory_file_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);
+ offset += tlv_len;
+ break;
+
+ case REMOTE_STAT_REP_REQ:
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_res2, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_res3, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);
+ offset += 1;
+
+ len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;
+ dissect_cfdp_src_entity_id(tvb, cfdp_msg_to_user_tree, offset, len_ent_id);
+ offset += len_ent_id;
+
+ len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;
+ dissect_cfdp_tseq_num(tvb, cfdp_msg_to_user_tree, offset, len_tseq_num);
+ offset += len_tseq_num;
+
+ /* Report File Name */
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_report_file_name, tvb, offset, tlv_len, ENC_ASCII|ENC_NA);
+ offset += tlv_len;
+ break;
+
+ case REMOTE_STAT_REP_RESP:
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_trans_stat, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_five, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_rep_resp_code, tvb, offset, 1, aux_byte);
+ offset +=1;
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one_2, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);
+ offset +=1;
+
+ len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;
+ dissect_cfdp_src_entity_id(tvb, cfdp_msg_to_user_tree, offset, len_ent_id);
+ offset += len_ent_id;
+
+ len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;
+ dissect_cfdp_tseq_num(tvb, cfdp_msg_to_user_tree, offset, len_tseq_num);
+ offset += len_tseq_num;
+ break;
+
+ case REMOTE_SUSPEND_REQ:
+ case REMOTE_RESUME_REQ:
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one_2, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);
+ offset += 1;
+
+ len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;
+ dissect_cfdp_src_entity_id(tvb, cfdp_msg_to_user_tree, offset, len_ent_id);
+ offset += len_ent_id;
+
+ len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;
+ dissect_cfdp_tseq_num(tvb, cfdp_msg_to_user_tree, offset, len_tseq_num);
+ offset += len_tseq_num;
+ break;
+
+ case REMOTE_SUSPEND_RESP:
+ case REMOTE_RESUME_RESP:
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_suspension_ind, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_trans_stat_2, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_five, tvb, offset, 1, aux_byte);
+ offset += 1;
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one_2, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);
+ offset += 1;
+
+ len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;
+ dissect_cfdp_src_entity_id(tvb, cfdp_msg_to_user_tree, offset, len_ent_id);
+ offset += len_ent_id;
+
+ len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;
+ dissect_cfdp_tseq_num(tvb, cfdp_msg_to_user_tree, offset, len_tseq_num);
+ offset += len_tseq_num;
+ break;
+
+ default:
+ break;
+ }
+ }else{
+ proto_tree_add_text(cfdp_msg_to_user_tree, tvb, offset, tlv_len, "Message to User");
+ offset += tlv_len;
+ }
+
+ return offset;
+}
+
+/* Dissect the Fault Handler Override TLV */
+static guint32 dissect_cfdp_fault_handler_overr_tlv(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){
+
+ guint8 aux_byte, tlv_len;
+ proto_item *cfdp_fault_hdl_overr = NULL;
+ proto_tree *cfdp_fault_hdl_overr_tree;
+
+ guint32 offset = ext_offset;
+
+ /* Get tlv len */
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ /* Create a subtree */
+ cfdp_fault_hdl_overr = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Fault Handler Override TLV");
+ cfdp_fault_hdl_overr_tree = proto_item_add_subtree(cfdp_fault_hdl_overr, ett_cfdp_fault_hdl_overr);
+
+ proto_tree_add_uint(cfdp_fault_hdl_overr_tree, hf_cfdp_tlv_len, tvb, offset-1, 1, tlv_len);
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_fault_hdl_overr_tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(cfdp_fault_hdl_overr_tree, hf_cfdp_handler_code, tvb, offset, 1, aux_byte);
+ offset += 1;
+
+ return offset;
+}
+
+/* Dissect the Flow Label TLV */
+static guint32 dissect_cfdp_flow_label_tlv(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){
+
+ guint8 tlv_len;
+ proto_item *cfdp_flow_label = NULL;
+ proto_tree *cfdp_flow_label_tree;
+
+ guint32 offset = ext_offset;
+
+ /* Get tlv len */
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ /* Create a subtree */
+ cfdp_flow_label = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Flow Label TLV");
+ cfdp_flow_label_tree = proto_item_add_subtree(cfdp_flow_label, ett_cfdp_flow_label);
+
+ /* It is undefined, so no specific encoding */
+ proto_tree_add_text(cfdp_flow_label_tree, tvb, offset, tlv_len, "Flow label");
+
+ return offset;
+}
+
+/* Dissect the End of File PDU */
+static guint32 dissect_cfdp_eof_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ext_offset, guint ext_packet_len){
+
+ guint8 aux_byte, tlv_type, tlv_len;
+ proto_item *cfdp_fault_location = NULL;
+ proto_tree *cfdp_fault_location_tree;
+
+ guint32 offset = ext_offset;
+ guint cfdp_packet_data_length = ext_packet_len;
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(tree, hf_cfdp_spare_four, tvb, offset, 1, aux_byte);
+ offset +=1;
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "EOF (%s)", val_to_str((aux_byte & 0xF0) >> 4, cfdp_condition_codes, "Reserved Code"));
+
+ proto_tree_add_item(tree, hf_cfdp_file_checksum, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_cfdp_file_size, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ if(offset < cfdp_packet_data_length){
+ tlv_type = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ if(tlv_type == FAULT_LOCATION){
+ tlv_len = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ cfdp_fault_location = proto_tree_add_text(tree, tvb, offset-2, tlv_len+2, "Fault location TLV");
+ cfdp_fault_location_tree = proto_item_add_subtree(cfdp_fault_location, ett_cfdp_fault_location);
+
+ proto_tree_add_text(cfdp_fault_location_tree, tvb, offset, tlv_len, "Entity");
+ offset +=tlv_len;
+ }
+ }
+
+ return offset;
+}
+
+/* Dissect the Finished PDU */
+static guint32 dissect_cfdp_finished_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ext_offset, guint ext_packet_len){
+
+ guint32 offset = ext_offset;
+ guint8 aux_byte, tlv_type;
+
+
+ guint cfdp_packet_data_length = ext_packet_len;
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(tree, hf_cfdp_end_system_stat, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(tree, hf_cfdp_delivery_code, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(tree, hf_cfdp_file_stat, tvb, offset, 1, aux_byte);
+ offset +=1;
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Finished PDU (%s)", val_to_str((aux_byte & 0xF0) >> 4, cfdp_condition_codes, "Reserved Code"));
+
+ /* Add TLV fields */
+ while(offset < cfdp_packet_data_length){
+ tlv_type = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ switch(tlv_type){
+ case FILESTORE_RESP:
+ offset = dissect_cfdp_filestore_resp_tlv(tvb, tree, offset);
+ break;
+
+ case FAULT_LOCATION:
+ offset = dissect_cfdp_fault_location_tlv(tvb, tree, offset);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return offset;
+}
+
+/* Dissect the ACK PDU */
+static guint32 dissect_cfdp_ack_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ext_offset){
+
+ guint8 aux_byte;
+ guint32 offset = ext_offset;
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_cfdp_dir_code_ack, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(tree, hf_cfdp_dir_subtype_ack, tvb, offset, 1, aux_byte);
+ offset +=1;
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "ACK PDU (%s)", val_to_str((aux_byte & 0xF0) >> 4, cfdp_directive_codes, "Unknown PDU"));
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(tree, hf_cfdp_spare_two, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(tree, hf_cfdp_trans_stat_ack, tvb, offset, 1, aux_byte);
+ offset +=1;
+
+ return offset;
+}
+
+/* Dissect the Metadata PDU */
+static guint32 dissect_cfdp_metadata_pdu(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset, guint ext_packet_len){
+
+ guint8 aux_byte, tlv_type;
+ guint cfdp_packet_data_length = ext_packet_len;
+
+ guint32 offset = ext_offset;
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_cfdp_segment_control, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(tree, hf_cfdp_spare_seven, tvb, offset, 1, aux_byte);
+ offset +=1;
+ proto_tree_add_item(tree, hf_cfdp_file_size, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ aux_byte = tvb_get_guint8(tvb, offset);
+ if(aux_byte >0){
+ proto_tree_add_item(tree, hf_cfdp_src_file_name, tvb, offset+1, aux_byte, ENC_ASCII|ENC_NA);
+ offset += aux_byte+1;
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_cfdp_dst_file_name, tvb, offset+1, aux_byte, ENC_ASCII|ENC_NA);
+ offset += aux_byte+1;
+ }
+ /* Add TLV fields */
+ while(offset < cfdp_packet_data_length){
+ tlv_type = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ switch(tlv_type){
+ case FILESTORE_REQ:
+ offset = dissect_cfdp_filestore_req_tlv(tvb, tree, offset);
+ break;
+
+ case MSG_TO_USER:
+ offset = dissect_cfdp_msg_to_user_tlv(tvb, tree, offset);
+ break;
+
+ case FAULT_HDL_OVERR:
+ offset = dissect_cfdp_fault_handler_overr_tlv(tvb, tree, offset);
+ break;
+
+ case FLOW_LABEL:
+ offset = dissect_cfdp_flow_label_tlv(tvb, tree, offset);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return offset;
+}
+
+/* Dissect the NAK PDU */
+static guint32 dissect_cfdp_nak_pdu(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset, guint ext_packet_len){
+
+ guint32 offset = ext_offset;
+ guint cfdp_packet_data_length = ext_packet_len;
+
+ proto_tree_add_item(tree, hf_cfdp_nak_st_scope, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(tree, hf_cfdp_nak_sp_scope, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_text(tree, tvb, offset, cfdp_packet_data_length-9, "Segment requests");
+ offset += cfdp_packet_data_length-9;
+
+ return offset;
+}
+
+/* Dissect the Prompt PDU */
+static guint32 dissect_cfdp_prompt_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ext_offset){
+
+ guint8 aux_byte;
+ guint32 offset = ext_offset;
+
+ aux_byte = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_cfdp_response_req, tvb, offset, 1, aux_byte);
+ proto_tree_add_uint(tree, hf_cfdp_spare_seven, tvb, offset, 1, aux_byte);
+ offset +=1;
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Prompt PDU (%s)", val_to_str((aux_byte & 0x80) >> 7, cfdp_response_req, "Unknown"));
+
+ return offset;
+}
+
+/* Dissect the Keep Alive PDU */
+static guint32 dissect_cfdp_keep_alive_pdu(tvbuff_t *tvb, proto_tree *tree, guint32 ext_offset){
+
+ guint32 offset = ext_offset;
+
+ proto_tree_add_item(tree, hf_cfdp_progress, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ return offset;
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_cfdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_item *cfdp_packet;
+ proto_item *cfdp_tree = NULL;
+ proto_item *cfdp_header = NULL;
+ proto_item *cfdp_file_directive_header = NULL;
+ proto_item *cfdp_file_data_header = NULL;
+ proto_item *cfdp_crc = NULL;
+ proto_tree *cfdp_header_tree;
+ proto_tree *cfdp_file_directive_header_tree;
+ proto_tree *cfdp_file_data_header_tree;
+ proto_tree *cfdp_crc_tree;
+ gint cfdp_packet_length;
+ gint cfdp_packet_reported_length;
+ gint cfdp_packet_header_length;
+ gint cfdp_packet_data_length;
+ gint length;
+ guint8 first_byte = 0;
+ guint8 second_byte = 0;
+ guint8 directive_code = 0;
+ gint len_ent_id = 0;
+ gint len_tseq_num = 0;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "CFDP");
+
+ cfdp_packet_reported_length = tvb_reported_length_remaining(tvb, 0);
+ cfdp_packet_header_length = (tvb_get_guint8(tvb, 3) & HDR_LEN_TSEQ_NUM) + 1 + 2*(((tvb_get_guint8(tvb, 3) & HDR_LEN_ENT_ID) >>4) +1) + CFDP_HEADER_FIXED_FIELDS_LEN;
+ cfdp_packet_length = tvb_get_ntohs(tvb, 1) + cfdp_packet_header_length;
+
+
+
+ /* Min length is size of header plus 2 octets, whereas max length is reported length.
+ * If the length field in the CFDP header is outside of these bounds,
+ * use the value it violates. Otherwise, use the length field value.
+ */
+ if (cfdp_packet_length > cfdp_packet_reported_length)
+ length = cfdp_packet_reported_length;
+ else if (cfdp_packet_length < cfdp_packet_header_length + 2)
+ length = cfdp_packet_header_length + 2;
+ else
+ length = cfdp_packet_length;
+
+ /* Build the cfdp tree */
+ cfdp_packet = proto_tree_add_item(tree, proto_cfdp, tvb, 0, length, ENC_NA);
+ cfdp_tree = proto_item_add_subtree(cfdp_packet, ett_cfdp);
+
+ cfdp_header = proto_tree_add_text(cfdp_tree, tvb, offset, cfdp_packet_header_length, "CFDP Header");
+ cfdp_header_tree=proto_item_add_subtree(cfdp_header, ett_cfdp_header);
+
+ first_byte = tvb_get_guint8(tvb, offset);
+
+ /* CRC code is not included in the packet data length */
+ cfdp_packet_data_length = tvb_get_ntohs(tvb, 1)-2*((first_byte & HDR_CRCF) >>1);
+
+ proto_tree_add_uint(cfdp_header_tree, hf_cfdp_version, tvb, offset, 1, first_byte);
+ proto_tree_add_uint(cfdp_header_tree, hf_cfdp_pdu_type, tvb, offset, 1, first_byte);
+ proto_tree_add_uint(cfdp_header_tree, hf_cfdp_direction, tvb, offset, 1, first_byte);
+ proto_tree_add_uint(cfdp_header_tree, hf_cfdp_trans_mode, tvb, offset, 1, first_byte);
+ proto_tree_add_uint(cfdp_header_tree, hf_cfdp_crc_flag, tvb, offset, 1, first_byte);
+ proto_tree_add_uint(cfdp_header_tree, hf_cfdp_res1, tvb, offset, 1, first_byte);
+ offset += 1;
+
+ proto_tree_add_item(cfdp_header_tree, hf_cfdp_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ second_byte = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(cfdp_header_tree, hf_cfdp_res2, tvb, offset, 1, second_byte);
+ proto_tree_add_uint(cfdp_header_tree, hf_cfdp_entid_length, tvb, offset, 1, second_byte);
+ proto_tree_add_uint(cfdp_header_tree, hf_cfdp_res3, tvb, offset, 1, second_byte);
+ proto_tree_add_uint(cfdp_header_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, second_byte);
+ offset += 1;
+
+ len_ent_id = ((second_byte & HDR_LEN_ENT_ID) >> 4) + 1;
+ dissect_cfdp_src_entity_id(tvb, cfdp_header_tree, offset, len_ent_id);
+ offset += len_ent_id;
+
+ len_tseq_num = (second_byte & HDR_LEN_TSEQ_NUM) +1;
+ dissect_cfdp_tseq_num(tvb, cfdp_header_tree, offset, len_tseq_num);
+ offset += len_tseq_num;
+
+ dissect_cfdp_dst_entity_id(tvb, cfdp_header_tree, offset, len_ent_id);
+ offset += len_ent_id;
+
+ proto_item_set_end(cfdp_header, tvb, offset);
+
+ /* Build the File Directive or the File Data tree */
+ if(!(first_byte & HDR_TYPE_CFDP))
+ {
+
+ cfdp_file_directive_header = proto_tree_add_text(cfdp_tree, tvb, offset, cfdp_packet_data_length, "CFDP File Directive");
+ cfdp_file_directive_header_tree = proto_item_add_subtree(cfdp_file_directive_header, ett_cfdp_file_directive_header);
+
+ directive_code = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_file_directive_header_tree, hf_cfdp_file_directive_type, tvb, offset, 1, directive_code);
+ offset += 1;
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s PDU", val_to_str(directive_code, cfdp_directive_codes, "Reserved (%d)"));
+
+ switch(directive_code)
+ {
+ case EOF_PDU:
+ offset = dissect_cfdp_eof_pdu(tvb, pinfo, cfdp_file_directive_header_tree, offset, cfdp_packet_data_length);
+ break;
+
+ case FINISHED_PDU:
+ offset = dissect_cfdp_finished_pdu(tvb, pinfo, cfdp_file_directive_header_tree, offset, cfdp_packet_data_length);
+ break;
+
+ case ACK_PDU:
+ offset = dissect_cfdp_ack_pdu(tvb, pinfo, cfdp_file_directive_header_tree, offset);
+ break;
+
+ case METADATA_PDU:
+ offset = dissect_cfdp_metadata_pdu(tvb, cfdp_file_directive_header_tree, offset, cfdp_packet_data_length);
+ break;
+
+ case NAK_PDU:
+ offset = dissect_cfdp_nak_pdu(tvb, cfdp_file_directive_header_tree, offset, cfdp_packet_data_length);
+ break;
+
+ case PROMPT_PDU:
+ offset = dissect_cfdp_prompt_pdu(tvb, pinfo, cfdp_file_directive_header_tree, offset);
+ break;
+
+ case KEEP_ALIVE_PDU:
+ offset = dissect_cfdp_keep_alive_pdu(tvb, cfdp_file_directive_header_tree, offset);
+ break;
+
+ default:
+ break;
+ }
+
+ proto_item_set_end(cfdp_file_directive_header, tvb, offset);
+
+ }else{
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "File Data PDU");
+
+ cfdp_file_data_header = proto_tree_add_text(cfdp_tree, tvb, offset, cfdp_packet_data_length, "CFDP File Data");
+ cfdp_file_data_header_tree = proto_item_add_subtree(cfdp_file_data_header, ett_cfdp_file_data_header);
+
+ proto_tree_add_item(cfdp_file_data_header_tree, hf_cfdp_file_data_offset, tvb, offset, 4, ENC_BIG_ENDIAN);
+
+ offset += 4;
+
+ proto_tree_add_text(cfdp_file_data_header_tree, tvb, offset, cfdp_packet_data_length-4, "User Data");
+ offset += cfdp_packet_data_length-4;
+
+ }
+ if(first_byte & HDR_CRCF){
+ cfdp_crc = proto_tree_add_text(cfdp_tree, tvb, offset, 2, "CRC");
+ cfdp_crc_tree = proto_item_add_subtree(cfdp_crc, ett_cfdp_crc);
+
+ proto_tree_add_item(cfdp_crc_tree, hf_cfdp_crc, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset+=2;
+
+ proto_item_set_end(cfdp_crc, tvb, offset);
+ }
+ /* Give the data dissector any bytes past the CFDP packet length */
+ call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree);
+}
+
+void
+proto_register_cfdp(void)
+{
+ static hf_register_info hf[] = {
+
+ { &hf_cfdp_version,
+ { "Version", "cfdp.version",
+ FT_UINT8, BASE_DEC, NULL, HDR_VERSION_CFDP,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_pdu_type,
+ { "PDU Type", "cfdp.pdu_type",
+ FT_UINT8, BASE_DEC, VALS(cfdp_pdu_type), HDR_TYPE_CFDP,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_direction,
+ { "Direction", "cfdp.direction",
+ FT_UINT8, BASE_DEC, VALS(cfdp_direction), HDR_DIR,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_trans_mode,
+ { "Trans. Mode", "cfdp.trans_mode",
+ FT_UINT8, BASE_DEC, VALS(cfdp_trans_mode), HDR_TMODE,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_crc_flag,
+ { "CRC Flag", "cfdp.crc_flag",
+ FT_UINT8, BASE_DEC, VALS(cfdp_crc_flag), HDR_CRCF,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_res1,
+ { "Bit reserved 1", "cfdp.res1",
+ FT_UINT8, BASE_DEC, NULL, HDR_RES1,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_data_length,
+ { "PDU Data length", "cfdp.data_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_res2,
+ { "Bit reserved 2", "cfdp.res2",
+ FT_UINT8, BASE_DEC, NULL, 0x80,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_entid_length,
+ { "Length of entity IDs", "cfdp.entid_length",
+ FT_UINT8, BASE_DEC, NULL, 0x70,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_res3,
+ { "Bit reserved 3", "cfdp.res3",
+ FT_UINT8, BASE_DEC, NULL, 0x08,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_transeqnum_length,
+ { "Length of Transaction sequence number", "cfdp.transeqnum_length",
+ FT_UINT8, BASE_DEC, NULL, 0x07,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_srcid,
+ { "Source entity ID", "cfdp.srcid",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_transeqnum,
+ { "Transaction sequence number", "cfdp.transeqnum",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_dstid,
+ { "Destination entity ID", "cfdp.dstid",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_file_directive_type,
+ { "File Directive type", "cfdp.fdtype",
+ FT_UINT8, BASE_DEC, VALS(cfdp_file_directive_type), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_file_data_offset,
+ { "Offset", "cfdp.offset",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_progress,
+ { "Progress", "cfdp.progress",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_dir_code_ack,
+ { "PDU acknowledged", "cfdp.dir_code_ack",
+ FT_UINT8, BASE_DEC, VALS(cfdp_file_directive_type), 0xf0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_dir_subtype_ack,
+ { "Directive subtype code", "cfdp.dir_subtype_ack",
+ FT_UINT8, BASE_DEC, NULL, 0x0f,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_condition_code,
+ { "Condition Code", "cfdp.condition_code",
+ FT_UINT8, BASE_DEC, VALS(cfdp_condition_codes), 0xf0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_spare_one,
+ { "Spare", "cfdp.spare_one",
+ FT_UINT8, BASE_DEC, NULL, 0x08,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_spare_one_2,
+ { "Spare", "cfdp.spare_one_2",
+ FT_UINT8, BASE_DEC, NULL, 0x80,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_spare_two,
+ { "Spare", "cfdp.spare_two",
+ FT_UINT8, BASE_DEC, NULL, 0x0c,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_spare_four,
+ { "Spare", "cfdp.spare_four",
+ FT_UINT8, BASE_DEC, NULL, 0x0f,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_spare_five,
+ { "Spare", "cfdp.spare_five",
+ FT_UINT8, BASE_DEC, NULL, 0x3E,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_spare_seven,
+ { "Spare", "cfdp.spare_seven",
+ FT_UINT8, BASE_DEC, NULL, 0x7f,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_spare_seven_2,
+ { "Spare", "cfdp.spare_seven_2",
+ FT_UINT8, BASE_DEC, NULL, 0xfe,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_trans_stat_ack,
+ { "Transaction status", "cfdp.trans_stat_ack",
+ FT_UINT8, BASE_DEC, VALS(cfdp_trans_stat_ack), 0x03,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_trans_stat,
+ { "Transaction status", "cfdp.trans_stat",
+ FT_UINT8, BASE_DEC, VALS(cfdp_trans_stat_ack), 0xC0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_trans_stat_2,
+ { "Transaction status", "cfdp.trans_stat_2",
+ FT_UINT8, BASE_DEC, VALS(cfdp_trans_stat_ack), 0x60,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_file_checksum,
+ { "Checksum", "cfdp.checksum",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_file_size,
+ { "File size", "cfdp.file_size",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_end_system_stat,
+ { "End system status", "cfdp.end_system_stat",
+ FT_UINT8, BASE_DEC, VALS(cfdp_end_system_stat), 0x08,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_delivery_code,
+ { "Delivery code", "cfdp.delivery_code",
+ FT_UINT8, BASE_DEC, VALS(cfdp_delivery_code), 0x04,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_file_stat,
+ { "File status", "cfdp.file_status",
+ FT_UINT8, BASE_DEC, VALS(cfdp_file_stat), 0x03,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_segment_control,
+ { "Segmentation control", "cfdp.segment_control",
+ FT_UINT8, BASE_DEC, VALS(cfdp_segment_control), 0x80,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_tlv_len,
+ { "Length", "cfdp.tlv_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_src_file_name,
+ {"Source file name", "cfdp.src_file_name", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_dst_file_name,
+ {"Destination file name", "cfdp.dst_file_name", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_first_file_name,
+ {"First file name", "cfdp.first_file_name", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_second_file_name,
+ {"Second file name", "cfdp.second_file_name", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_nak_st_scope,
+ {"Start of scope", "cfdp.nak_st_scope", FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_nak_sp_scope,
+ {"End of scope", "cfdp.nak_sp_scope", FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_crc,
+ {"CRC", "cfdp.crc", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_action_code,
+ {"Action code", "cfdp.action_code", FT_UINT8, BASE_DEC, VALS(cfdp_action_code), 0xF0,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_status_code_1,
+ {"Status code", "cfdp.status_code_1", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_1), 0x0F,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_status_code_2,
+ {"Status code", "cfdp.status_code_2", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_2), 0x0F,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_status_code_3,
+ {"Status code", "cfdp.status_code_3", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_3), 0x0F,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_status_code_4,
+ {"Status code", "cfdp.status_code_4", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_4), 0x0F,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_status_code_5,
+ {"Status code", "cfdp.status_code_5", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_5), 0x0F,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_status_code_6,
+ {"Status code", "cfdp.status_code_6", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_6), 0x0F,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_status_code_7,
+ {"Status code", "cfdp.status_code_7", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_7), 0x0F,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_status_code_8,
+ {"Status code", "cfdp.status_code_8", FT_UINT8, BASE_DEC, VALS(cfdp_status_code_8), 0x0F,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_handler_code,
+ { "Handler Code", "cfdp.handler_code",
+ FT_UINT8, BASE_DEC, VALS(cfdp_handler_codes), 0x0F,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_trans_mode_msg,
+ { "Trans. Mode", "cfdp.trans_mode_msg",
+ FT_UINT8, BASE_DEC, VALS(cfdp_trans_mode), 0x01,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_proxy_msg_type,
+ { "Proxy Message Type", "cfdp.proxy_msg_type",
+ FT_UINT8, BASE_DEC, VALS(cfdp_proxy_msg_type), 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_proxy_segment_control,
+ { "Segmentation control", "cfdp.proxy_segment_control",
+ FT_UINT8, BASE_DEC, VALS(cfdp_segment_control), 0x01,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_proxy_delivery_code,
+ { "Delivery code", "cfdp.proxy_delivery_code",
+ FT_UINT8, BASE_DEC, VALS(cfdp_delivery_code), 0x04,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_response_req,
+ { "Response required", "cfdp.response_req",
+ FT_UINT8, BASE_DEC, VALS(cfdp_response_req), 0x80,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_directory_name,
+ {"Directory Name", "cfdp.directory_name", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_directory_file_name,
+ {"Directory File Name", "cfdp.directory_file_name", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_listing_resp_code,
+ {"Listing Response Code", "cfdp.listing_resp_code",
+ FT_UINT8, BASE_DEC, VALS(cfdp_listing_resp_code), 0x80,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_report_file_name,
+ {"Report File Name", "cfdp.report_file_name", FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_rep_resp_code,
+ {"Report Response Code", "cfdp.rep_resp_code",
+ FT_UINT8, BASE_DEC, VALS(cfdp_rep_resp_code), 0x01,
+ NULL, HFILL}
+ },
+ { &hf_cfdp_suspension_ind,
+ {"Suspension indicator", "cfdp.suspension_ind",
+ FT_UINT8, BASE_DEC, VALS(cfdp_suspension_ind), 0x80,
+ NULL, HFILL}
+ }
+
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_cfdp,
+ &ett_cfdp_header,
+ &ett_cfdp_file_directive_header,
+ &ett_cfdp_file_data_header,
+ &ett_cfdp_fault_location,
+ &ett_cfdp_crc,
+ &ett_cfdp_filestore_req,
+ &ett_cfdp_filestore_resp,
+ &ett_cfdp_msg_to_user,
+ &ett_cfdp_fault_hdl_overr,
+ &ett_cfdp_flow_label
+ };
+
+ /* Register the protocol name and description */
+ proto_cfdp = proto_register_protocol("CFDP", "CFDP", "cfdp");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_cfdp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector ( "cfdp", dissect_cfdp, proto_cfdp );
+}
+
+void
+proto_reg_handoff_cfdp(void)
+{
+ static dissector_handle_t cfdp_handle;
+
+ cfdp_handle = create_dissector_handle(dissect_cfdp, proto_cfdp);
+ dissector_add_uint("ccsds.apid", CFDP_APID, cfdp_handle);
+ dissector_add_handle ( "udp.port", cfdp_handle ); /* for 'decode as' */
+ data_handle = find_dissector("data");
+}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=4 noexpandtab:
+ * :indentSize=4:tabSize=4:noTabs=false:
+ */
-/* packet-zbee-nwk-gp.c\r
- * Dissector routines for the ZigBee Green Power profile (GP)\r
- * Copyright 2013 DSR Corporation, http://dsr-wireless.com/\r
- *\r
- * $Id: packet-zbee-nwk-gp.c 54208 2013-12-18 01:00:00Z DSR Corporation $\r
- *\r
- * Wireshark - Network traffic analyzer\r
- * By Gerald Combs <gerald@wireshark.org>\r
- * Copyright 1998 Gerald Combs\r
- *\r
- * Used Owen Kirby's packet-zbee-aps module as a template. Based\r
- * on ZigBee Cluster Library Specification document 075123r02ZB\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/* Include files. */\r
-#include "config.h"\r
-\r
-#include <glib.h>\r
-#include <epan/packet.h>\r
-#include <epan/exceptions.h>\r
-#include <epan/prefs.h>\r
-#include <epan/addr_resolv.h>\r
-#include <epan/expert.h>\r
-#include <epan/uat.h>\r
-#include "packet-ieee802154.h"\r
-#include "packet-zbee.h"\r
-#include "packet-zbee-nwk.h"\r
-#include "packet-zbee-security.h"\r
-#include "packet-zbee-aps.h"\r
-#include "packet-zbee-zcl.h"\r
-#include <wsutil/wsgcrypt.h>\r
-\r
-/**************************/\r
-/* Defines. */\r
-/**************************/\r
-\r
-/* ZigBee NWK GP FCF frame types. */\r
-#define ZBEE_NWK_GP_FCF_DATA 0x00\r
-#define ZBEE_NWK_GP_FCF_MAINTENANCE 0x01\r
-\r
-/* ZigBee NWK GP FCF fields. */\r
-#define ZBEE_NWK_GP_FCF_AUTO_COMMISSIONING 0x40\r
-#define ZBEE_NWK_GP_FCF_CONTROL_EXTENSION 0x80\r
-#define ZBEE_NWK_GP_FCF_FRAME_TYPE 0x03\r
-#define ZBEE_NWK_GP_FCF_VERSION 0x3C\r
-\r
-/* Extended NWK Frame Control field. */\r
-#define ZBEE_NWK_GP_FCF_EXT_APP_ID 0x07 /* 0 - 2 b. */\r
-#define ZBEE_NWK_GP_FCF_EXT_SECURITY_LEVEL 0x18 /* 3 - 4 b. */\r
-#define ZBEE_NWK_GP_FCF_EXT_SECURITY_KEY 0x20 /* 5 b. */\r
-#define ZBEE_NWK_GP_FCF_EXT_RX_AFTER_TX 0x40 /* 6 b. */\r
-#define ZBEE_NWK_GP_FCF_EXT_DIRECTION 0x80 /* 7 b. */\r
-\r
-/* Definitions for application IDs. */\r
-#define ZBEE_NWK_GP_APP_ID_DEFAULT 0x00\r
-#define ZBEE_NWK_GP_APP_ID_LPED 0x01\r
-#define ZBEE_NWK_GP_APP_ID_ZGP 0x02\r
-\r
-/* Definitions for GP directions. */\r
-#define ZBEE_NWK_GP_FC_EXT_DIRECTION_DEFAULT 0x00\r
-#define ZBEE_NWK_GP_FC_EXT_DIRECTION_FROM_ZGPD 0x00\r
-#define ZBEE_NWK_GP_FC_EXT_DIRECTION_FROM_ZGPP 0x01\r
-\r
-/* Definitions for ZGPD Source IDs. */\r
-#define ZBEE_NWK_GP_ZGPD_SRCID_ALL 0xFFFFFFFF\r
-#define ZBEE_NWK_GP_ZGPD_SRCID_UNKNOWN 0x00000000\r
-\r
-/* Security level values. */\r
-#define ZBEE_NWK_GP_SECURITY_LEVEL_NO 0x00\r
-#define ZBEE_NWK_GP_SECURITY_LEVEL_1LSB 0x01\r
-#define ZBEE_NWK_GP_SECURITY_LEVEL_FULL 0x02\r
-#define ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR 0x03\r
-\r
-/* GP Security key types. */\r
-#define ZBEE_NWK_GP_SECURITY_KEY_TYPE_NO_KEY 0x00\r
-#define ZBEE_NWK_GP_SECURITY_KEY_TYPE_ZB_NWK_KEY 0x01\r
-#define ZBEE_NWK_GP_SECURITY_KEY_TYPE_GPD_GROUP_KEY 0x02\r
-#define ZBEE_NWK_GP_SECURITY_KEY_TYPE_NWK_KEY_DERIVED_GPD_KEY_GROUP_KEY 0x03\r
-#define ZBEE_NWK_GP_SECURITY_KEY_TYPE_PRECONFIGURED_INDIVIDUAL_GPD_KEY 0x04\r
-#define ZBEE_NWK_GP_SECURITY_KEY_TYPE_DERIVED_INDIVIDUAL_GPD_KEY 0x07\r
-\r
-typedef struct {\r
- /* FCF Data. */\r
- guint8 frame_type;\r
- gboolean nwk_frame_control_extension;\r
-\r
- /* Ext FCF Data. */\r
- guint8 application_id;\r
- guint8 security_level;\r
- guint8 direction;\r
-\r
- /* Src ID. */\r
- guint32 source_id;\r
-\r
- /* Security Frame Counter. */\r
- guint32 security_frame_counter;\r
-\r
- /* MIC. */\r
- guint8 mic_size;\r
- guint32 mic;\r
-\r
- /* Application Payload. */\r
- guint8 payload_len;\r
-} zbee_nwk_green_power_packet;\r
-\r
-/* Commissioning command payload. */\r
-guint8 nwk_cmd_security_key[16];\r
-\r
-/* Definitions for GP Commissioning command opt field (bitmask). */\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_MAC_SEQ 0x01\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_RX_ON_CAP 0x02\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_MANUFACTURER_INFO 0x04\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_PAN_ID_REQ 0x10\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_GP_SEC_KEY_REQ 0x20\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_FIXED_LOCATION 0x40\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_EXT_OPTIONS 0x80\r
-\r
-/* Definitions for GP Commissioning command ext_opt field (bitmask). */\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_SEC_LEVEL_CAP 0x03\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_KEY_TYPE 0x1C\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_GPD_KEY_PRESENT 0x20\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_GPD_KEY_ENCR 0x40\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_OUT_COUNTER 0x80\r
-\r
-/* Definitions for GP Commissioning command MS Extensions field (bitmask). */\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_MIP 0x01\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_MMIP 0x02\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_GCLP 0x04\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_CRP 0x08\r
-\r
-/* Definitions for GP Decommissioning command opt field (bitmask). */\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_PAN_ID_PRESENT 0x01\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_SEC_KEY_PRESENT 0x02\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_KEY_ENCR 0x04\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_SEC_LEVEL 0x18\r
-#define ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_KEY_TYPE 0xE0\r
-\r
-/* Definitions for GP Channel Request command. */\r
-#define ZBEE_NWK_GP_CMD_CHANNEL_REQUEST_1ST 0x0F\r
-#define ZBEE_NWK_GP_CMD_CHANNEL_REQUEST_2ND 0xF0\r
-\r
-/* GP Channel Configuration command. */\r
-#define ZBEE_NWK_GP_CMD_CHANNEL_CONFIGURATION_OPERATION_CH 0x0F\r
-\r
-/* GP GENERIC IDS. */\r
-#define GPD_DEVICE_ID_GENERIC_GP_SIMPLE_GENERIC_1STATE_SWITCH 0x00\r
-#define GPD_DEVICE_ID_GENERIC_GP_SIMPLE_GENERIC_2STATE_SWITCH 0x01\r
-#define GPD_DEVICE_ID_GENERIC_GP_ON_OFF_SWITCH 0x02\r
-#define GPD_DEVICE_ID_GENERIC_GP_LEVEL_CONTROL_SWITCH 0x03\r
-#define GPD_DEVICE_ID_GENERIC_GP_SIMPLE_SENSOR 0x04\r
-#define GPD_DEVICE_ID_GENERIC_GP_ADVANCED_GENERIC_1STATE_SWITCH 0x05\r
-#define GPD_DEVICE_ID_GENERIC_GP_ADVANCED_GENERIC_2STATE_SWITCH 0x06\r
-\r
-/* GP LIGHTING IDS. */\r
-#define GPD_DEVICE_ID_LIGHTING_GP_COLOR_DIMMER_SWITCH 0x10\r
-#define GPD_DEVICE_ID_LIGHTING_GP_LIGHT_SENSOR 0x11\r
-#define GPD_DEVICE_ID_LIGHTING_GP_OCCUPANCY_SENSOR 0x12\r
-\r
-/* GP CLOSURES IDS. */\r
-#define GPD_DEVICE_ID_CLOSURES_GP_DOOR_LOCK_CONTROLLER 0x20\r
-\r
-/* HVAC IDS. */\r
-#define GPD_DEVICE_ID_HVAC_GP_TEMPERATURE_SENSOR 0x30\r
-#define GPD_DEVICE_ID_HVAC_GP_PRESSURE_SENSOR 0x31\r
-#define GPD_DEVICE_ID_HVAC_GP_FLOW_SENSOR 0x32\r
-#define GPD_DEVICE_ID_HVAC_GP_INDOOR_ENVIRONMENT_SENSOR 0x33\r
-\r
-/* Manufacturer specific device. */\r
-#define GPD_DEVICE_ID_MANUFACTURER_SPECIFIC 0xFE\r
-\r
-/* Payloadless GPDF commands sent by GPD. */\r
-#define ZB_GP_CMD_ID_IDENTIFY 0x00\r
-#define ZB_GP_CMD_ID_SCENE0 0x10\r
-#define ZB_GP_CMD_ID_SCENE1 0x11\r
-#define ZB_GP_CMD_ID_SCENE2 0x12\r
-#define ZB_GP_CMD_ID_SCENE3 0x13\r
-#define ZB_GP_CMD_ID_SCENE4 0x14\r
-#define ZB_GP_CMD_ID_SCENE5 0x15\r
-#define ZB_GP_CMD_ID_SCENE6 0x16\r
-#define ZB_GP_CMD_ID_SCENE7 0x17\r
-#define ZB_GP_CMD_ID_SCENE8 0x18\r
-#define ZB_GP_CMD_ID_SCENE9 0x19\r
-#define ZB_GP_CMD_ID_SCENE10 0x1A\r
-#define ZB_GP_CMD_ID_SCENE11 0x1B\r
-#define ZB_GP_CMD_ID_SCENE12 0x1C\r
-#define ZB_GP_CMD_ID_SCENE13 0x1D\r
-#define ZB_GP_CMD_ID_SCENE14 0x1E\r
-#define ZB_GP_CMD_ID_SCENE15 0x1F\r
-#define ZB_GP_CMD_ID_OFF 0x20\r
-#define ZB_GP_CMD_ID_ON 0x21\r
-#define ZB_GP_CMD_ID_TOGGLE 0x22\r
-#define ZB_GP_CMD_ID_RELEASE 0x23\r
-#define ZB_GP_CMD_ID_LEVEL_CONTROL_STOP 0x34\r
-#define ZB_GP_CMD_ID_MOVE_HUE_STOP 0x40\r
-#define ZB_GP_CMD_ID_MOVE_SATURATION_STOP 0x45\r
-#define ZB_GP_CMD_ID_LOCK_DOOR 0x50\r
-#define ZB_GP_CMD_ID_UNLOCK_DOOR 0x51\r
-#define ZB_GP_CMD_ID_PRESS11 0x60\r
-#define ZB_GP_CMD_ID_RELEASE11 0x61\r
-#define ZB_GP_CMD_ID_PRESS12 0x62\r
-#define ZB_GP_CMD_ID_RELEASE12 0x63\r
-#define ZB_GP_CMD_ID_PRESS22 0x64\r
-#define ZB_GP_CMD_ID_RELEASE22 0x65\r
-#define ZB_GP_CMD_ID_SHORT_PRESS11 0x66\r
-#define ZB_GP_CMD_ID_SHORT_PRESS12 0x67\r
-#define ZB_GP_CMD_ID_SHORT_PRESS22 0x68\r
-#define ZB_GP_CMD_ID_DECOMMISSIONING 0xE1\r
-#define ZB_GP_CMD_ID_SUCCESS 0xE2\r
-\r
-/* GPDF commands with payload sent by GPD. */\r
-#define ZB_GP_CMD_ID_MOVE_UP 0x30\r
-#define ZB_GP_CMD_ID_MOVE_DOWN 0x31\r
-#define ZB_GP_CMD_ID_STEP_UP 0x32\r
-#define ZB_GP_CMD_ID_STEP_DOWN 0x33\r
-#define ZB_GP_CMD_ID_MOVE_UP_WITH_ON_OFF 0x35\r
-#define ZB_GP_CMD_ID_MOVE_DOWN_WITH_ON_OFF 0x36\r
-#define ZB_GP_CMD_ID_STEP_UP_WITH_ON_OFF 0x37\r
-#define ZB_GP_CMD_ID_STEP_DOWN_WITH_ON_OFF 0x38\r
-#define ZB_GP_CMD_ID_MOVE_HUE_UP 0x41\r
-#define ZB_GP_CMD_ID_MOVE_HUE_DOWN 0x42\r
-#define ZB_GP_CMD_ID_STEP_HUE_UP 0x43\r
-#define ZB_GP_CMD_ID_STEP_HUW_DOWN 0x44\r
-#define ZB_GP_CMD_ID_MOVE_SATUREATION_UP 0x46\r
-#define ZB_GP_CMD_ID_MOVE_SATUREATION_DOWN 0x47\r
-#define ZB_GP_CMD_ID_STEP_SATURATION_UP 0x48\r
-#define ZB_GP_CMD_ID_STEP_SATURATION_DOWN 0x49\r
-#define ZB_GP_CMD_ID_MOVE_COLOR 0x4A\r
-#define ZB_GP_CMD_ID_STEP_COLOR 0x4B\r
-#define ZB_GP_CMD_ID_ATTRIBUTE_REPORTING 0xA0\r
-#define ZB_GP_CMD_ID_MANUFACTURE_SPECIFIC_ATTR_REPORTING 0xA1\r
-#define ZB_GP_CMD_ID_MULTI_CLUSTER_REPORTING 0xA2\r
-#define ZB_GP_CMD_ID_MANUFACTURER_SPECIFIC_MCLUSTER_REPORTING 0xA3\r
-#define ZB_GP_CMD_ID_REQUEST_ATTRIBUTES 0xA4\r
-#define ZB_GP_CMD_ID_READ_ATTRIBUTES_RESPONSE 0xA5\r
-#define ZB_GP_CMD_ID_ANY_SENSOR_COMMAND_A0_A3 0xAF\r
-#define ZB_GP_CMD_ID_COMMISSIONING 0xE0\r
-#define ZB_GP_CMD_ID_CHANNEL_REQUEST 0xE3\r
-\r
-/* GPDF commands sent to GPD. */\r
-#define ZB_GP_CMD_ID_COMMISSIONING_REPLY 0xF0\r
-#define ZB_GP_CMD_ID_WRITE_ATTRIBUTES 0xF1\r
-#define ZB_GP_CMD_ID_READ_ATTRIBUTES 0xF2\r
-#define ZB_GP_CMD_ID_CHANNEL_CONFIGURATION 0xF3\r
-\r
-/* GPD manufacturers. */\r
-#define ZBEE_NWK_GP_MANUF_ID_GREENPEAK 0x10D0\r
-\r
-/* GPD devices by GreenPeak. */\r
-#define ZBEE_NWK_GP_MANUF_GREENPEAK_IZDS 0x0000\r
-#define ZBEE_NWK_GP_MANUF_GREENPEAK_IZDWS 0x0001\r
-#define ZBEE_NWK_GP_MANUF_GREENPEAK_IZLS 0x0002\r
-#define ZBEE_NWK_GP_MANUF_GREENPEAK_IZRHS 0x0003\r
-\r
-/*********************/\r
-/* Extern Constants. */\r
-/*********************/\r
-\r
-extern const value_string zbee_aps_cid_names[];\r
-\r
-/*********************/\r
-/* Global variables. */\r
-/*********************/\r
-\r
-/* GP proto handle. */\r
-static int proto_zbee_nwk_gp = -1;\r
-\r
-/* GP NWK FC. */\r
-static int hf_zbee_nwk_gp_auto_commissioning = -1;\r
-static int hf_zbee_nwk_gp_fc_ext = -1;\r
-static int hf_zbee_nwk_gp_frame_type = -1;\r
-static int hf_zbee_nwk_gp_proto_version = -1;\r
-\r
-/* GP NWK FC extension. */\r
-static int hf_zbee_nwk_gp_fc_ext_app_id = -1;\r
-static int hf_zbee_nwk_gp_fc_ext_direction = -1;\r
-static int hf_zbee_nwk_gp_fc_ext_rx_after_tx = -1;\r
-static int hf_zbee_nwk_gp_fc_ext_sec_key = -1;\r
-static int hf_zbee_nwk_gp_fc_ext_sec_level = -1;\r
-\r
-/* ZGPD Src ID. */\r
-static int hf_zbee_nwk_gp_zgpd_src_id = -1;\r
-\r
-/* Security frame counter. */\r
-static int hf_zbee_nwk_gp_security_frame_counter = -1;\r
-\r
-/* Security MIC. */\r
-static int hf_zbee_nwk_gp_security_mic_2b = -1;\r
-static int hf_zbee_nwk_gp_security_mic_4b = -1;\r
-\r
-/* Payload subframe. */\r
-static int hf_zbee_nwk_gp_command_id = -1;\r
-\r
-/* Commissioning. */\r
-static int hf_zbee_nwk_gp_cmd_comm_device_id = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_ext_opt_gpd_key_encr = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_ext_opt_gpd_key_present = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_ext_opt_key_type = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_ext_opt_outgoing_counter = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_ext_opt_sec_level_cap = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_gpd_sec_key_mic = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_opt_ext_opt = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_opt_fixed_location = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_opt_mac_sec_num_cap = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_opt_ms_ext_present = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_opt_panid_req = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_opt_rx_on_cap = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_opt_sec_key_req = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_outgoing_counter = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_manufacturer_greenpeak_dev_id = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_manufacturer_id = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_ms_ext_crp = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_ms_ext_gclp = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_ms_ext_mip = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_ms_ext_mmip = -1;\r
-\r
-/* Commissioning reply. */\r
-static int hf_zbee_nwk_gp_cmd_comm_rep_opt_key_encr = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_rep_opt_panid_present = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_key_present = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_level = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_type = -1;\r
-static int hf_zbee_nwk_gp_cmd_comm_rep_pan_id = -1;\r
-\r
-/* Attribute reporting. */\r
-static int hf_zbee_nwk_gp_cmd_attr_report_cluster_id = -1;\r
-\r
-/* Channel request. */\r
-static int hf_zbee_nwk_gp_cmd_channel_request_toggling_behaviour_1st = -1;\r
-static int hf_zbee_nwk_gp_cmd_channel_request_toggling_behaviour_2nd = -1;\r
-\r
-/* Channel Configuration command. */\r
-static int hf_zbee_nwk_gp_cmd_channel_configuration = -1;\r
-\r
-/* Move Color command. */\r
-static int hf_zbee_nwk_gp_cmd_move_color_ratex = -1;\r
-static int hf_zbee_nwk_gp_cmd_move_color_ratey = -1;\r
-\r
-/* Move Up/Down command. */\r
-static int hf_zbee_nwk_gp_cmd_move_up_down_rate = -1;\r
-\r
-/* Step Color command. */\r
-static int hf_zbee_nwk_gp_cmd_step_color_stepx = -1;\r
-static int hf_zbee_nwk_gp_cmd_step_color_stepy = -1;\r
-static int hf_zbee_nwk_gp_cmd_step_color_transition_time = -1;\r
-\r
-/* Step Up/Down command. */\r
-static int hf_zbee_nwk_gp_cmd_step_up_down_step_size = -1;\r
-static int hf_zbee_nwk_gp_cmd_step_up_down_transition_time = -1;\r
-\r
-/* Proto tree elements. */\r
-static gint ett_zbee_nwk = -1;\r
-static gint ett_zbee_nwk_cmd = -1;\r
-static gint ett_zbee_nwk_cmd_cinfo = -1;\r
-static gint ett_zbee_nwk_cmd_ms_ext = -1;\r
-static gint ett_zbee_nwk_cmd_options = -1;\r
-static gint ett_zbee_nwk_fcf = -1;\r
-static gint ett_zbee_nwk_fcf_ext = -1;\r
-\r
-/* Common. */\r
-static dissector_handle_t data_handle;\r
-static GSList *zbee_gp_keyring = NULL;\r
-static guint num_uat_key_records = 0;\r
-\r
-typedef struct {\r
- gchar *string;\r
- guint8 byte_order;\r
- gchar *label;\r
- guint8 key[ZBEE_SEC_CONST_KEYSIZE];\r
-} uat_key_record_t;\r
-\r
-static uat_key_record_t *gp_uat_key_records = NULL;\r
-static uat_t *zbee_gp_sec_key_table_uat;\r
-\r
-/* UAT. */\r
-UAT_CSTRING_CB_DEF(gp_uat_key_records, string, uat_key_record_t)\r
-UAT_VS_DEF(gp_uat_key_records, byte_order, uat_key_record_t, guint8, 0, "Normal")\r
-UAT_CSTRING_CB_DEF(gp_uat_key_records, label, uat_key_record_t)\r
-\r
-/****************/\r
-/* Field names. */\r
-/****************/\r
-\r
-/* Byte order. */\r
-static const value_string byte_order_vals[] = {\r
- { 0, "Normal"},\r
- { 1, "Reverse"},\r
-\r
- { 0, NULL }\r
-};\r
-\r
-/* Application ID names. */\r
-static const value_string zbee_nwk_gp_app_id_names[] = {\r
- { ZBEE_NWK_GP_APP_ID_LPED, "LPED" },\r
- { ZBEE_NWK_GP_APP_ID_ZGP, "ZGP" },\r
-\r
- { 0, NULL }\r
-};\r
-\r
-/* Green Power commands. */\r
-static const value_string zbee_nwk_gp_cmd_names[] = {\r
- { ZB_GP_CMD_ID_ANY_SENSOR_COMMAND_A0_A3, "Any GPD sensor command (0xA0 - 0xA3)" },\r
- { ZB_GP_CMD_ID_ATTRIBUTE_REPORTING, "Attribute reporting" },\r
- { ZB_GP_CMD_ID_CHANNEL_CONFIGURATION, "Channel Configuration" },\r
- { ZB_GP_CMD_ID_CHANNEL_REQUEST, "Channel Request" },\r
- { ZB_GP_CMD_ID_COMMISSIONING, "Commissioning" },\r
- { ZB_GP_CMD_ID_COMMISSIONING_REPLY, "Commissioning Reply" },\r
- { ZB_GP_CMD_ID_DECOMMISSIONING, "Decommissioning" },\r
- { ZB_GP_CMD_ID_IDENTIFY, "Identify" },\r
- { ZB_GP_CMD_ID_LEVEL_CONTROL_STOP, "Level Control/Stop" },\r
- { ZB_GP_CMD_ID_LOCK_DOOR, "Lock Door" },\r
- { ZB_GP_CMD_ID_MANUFACTURER_SPECIFIC_MCLUSTER_REPORTING, "Manufacturer-specific multi-cluster reporting" },\r
- { ZB_GP_CMD_ID_MANUFACTURE_SPECIFIC_ATTR_REPORTING, "Manufacturer-specific attribute reporting" },\r
- { ZB_GP_CMD_ID_MOVE_COLOR, "Move Color" },\r
- { ZB_GP_CMD_ID_MOVE_DOWN, "Move Down" },\r
- { ZB_GP_CMD_ID_MOVE_DOWN_WITH_ON_OFF, "Move Down (with On/Off)" },\r
- { ZB_GP_CMD_ID_MOVE_HUE_DOWN, "Move Hue Down" },\r
- { ZB_GP_CMD_ID_MOVE_HUE_STOP, "Move Hue Stop" },\r
- { ZB_GP_CMD_ID_MOVE_HUE_UP, "Move Hue Up" },\r
- { ZB_GP_CMD_ID_MOVE_SATURATION_STOP, "Move Saturation Stop" },\r
- { ZB_GP_CMD_ID_MOVE_SATUREATION_DOWN, "Move Saturation Down" },\r
- { ZB_GP_CMD_ID_MOVE_SATUREATION_UP, "Move Saturation Up" },\r
- { ZB_GP_CMD_ID_MOVE_UP, "Move Up" },\r
- { ZB_GP_CMD_ID_MOVE_UP_WITH_ON_OFF, "Move Up (with On/Off)" },\r
- { ZB_GP_CMD_ID_MULTI_CLUSTER_REPORTING, "Multi-cluster reporting" },\r
- { ZB_GP_CMD_ID_OFF, "Off" },\r
- { ZB_GP_CMD_ID_ON, "On" },\r
- { ZB_GP_CMD_ID_PRESS11, "Press 1 of 1" },\r
- { ZB_GP_CMD_ID_PRESS12, "Press 1 of 2" },\r
- { ZB_GP_CMD_ID_PRESS22, "Press 2 of 2" },\r
- { ZB_GP_CMD_ID_READ_ATTRIBUTES, "Read Attributes" },\r
- { ZB_GP_CMD_ID_READ_ATTRIBUTES_RESPONSE, "Read Attributes Response" },\r
- { ZB_GP_CMD_ID_RELEASE11, "Release 1 of 1" },\r
- { ZB_GP_CMD_ID_RELEASE12, "Release 1 of 2" },\r
- { ZB_GP_CMD_ID_RELEASE22, "Release 2 of 2" },\r
- { ZB_GP_CMD_ID_RELEASE, "Release" },\r
- { ZB_GP_CMD_ID_REQUEST_ATTRIBUTES, "Request Attributes" },\r
- { ZB_GP_CMD_ID_SCENE0, "Scene 0" },\r
- { ZB_GP_CMD_ID_SCENE10, "Scene 10" },\r
- { ZB_GP_CMD_ID_SCENE11, "Scene 11" },\r
- { ZB_GP_CMD_ID_SCENE12, "Scene 12" },\r
- { ZB_GP_CMD_ID_SCENE13, "Scene 13" },\r
- { ZB_GP_CMD_ID_SCENE14, "Scene 14" },\r
- { ZB_GP_CMD_ID_SCENE15, "Scene 15" },\r
- { ZB_GP_CMD_ID_SCENE1, "Scene 1" },\r
- { ZB_GP_CMD_ID_SCENE2, "Scene 2" },\r
- { ZB_GP_CMD_ID_SCENE3, "Scene 3" },\r
- { ZB_GP_CMD_ID_SCENE4, "Scene 4" },\r
- { ZB_GP_CMD_ID_SCENE5, "Scene 5" },\r
- { ZB_GP_CMD_ID_SCENE6, "Scene 6" },\r
- { ZB_GP_CMD_ID_SCENE7, "Scene 7" },\r
- { ZB_GP_CMD_ID_SCENE8, "Scene 8" },\r
- { ZB_GP_CMD_ID_SCENE9, "Scene 9" },\r
- { ZB_GP_CMD_ID_SHORT_PRESS11, "Short press 1 of 1" },\r
- { ZB_GP_CMD_ID_SHORT_PRESS12, "Short press 1 of 2" },\r
- { ZB_GP_CMD_ID_SHORT_PRESS22, "Short press 2 of 2" },\r
- { ZB_GP_CMD_ID_STEP_COLOR, "Step Color" },\r
- { ZB_GP_CMD_ID_STEP_DOWN, "Step Down" },\r
- { ZB_GP_CMD_ID_STEP_DOWN_WITH_ON_OFF, "Step Down (with On/Off)" },\r
- { ZB_GP_CMD_ID_STEP_HUE_UP, "Step Hue Up" },\r
- { ZB_GP_CMD_ID_STEP_HUW_DOWN, "Step Hue Down" },\r
- { ZB_GP_CMD_ID_STEP_SATURATION_DOWN, "Step Saturation Down" },\r
- { ZB_GP_CMD_ID_STEP_SATURATION_UP, "Step Saturation Up" },\r
- { ZB_GP_CMD_ID_STEP_UP, "Step Up" },\r
- { ZB_GP_CMD_ID_STEP_UP_WITH_ON_OFF, "Step Up (with On/Off)" },\r
- { ZB_GP_CMD_ID_SUCCESS, "Success" },\r
- { ZB_GP_CMD_ID_TOGGLE, "Toggle" },\r
- { ZB_GP_CMD_ID_UNLOCK_DOOR, "Unlock Door" },\r
- { ZB_GP_CMD_ID_WRITE_ATTRIBUTES, "Write Attributes" },\r
-\r
- { 0, NULL }\r
-};\r
-\r
-/* Green Power devices. */\r
-static const value_string zbee_nwk_gp_device_ids_names[] = {\r
-\r
- /* GP GENERIC */\r
- { GPD_DEVICE_ID_GENERIC_GP_ADVANCED_GENERIC_1STATE_SWITCH, "Generic: GP Advanced Generic 1-state Switch" },\r
- { GPD_DEVICE_ID_GENERIC_GP_ADVANCED_GENERIC_2STATE_SWITCH, "Generic: GP Advanced Generic 2-state Switch" },\r
- { GPD_DEVICE_ID_GENERIC_GP_LEVEL_CONTROL_SWITCH, "Generic: GP Level Control Switch" },\r
- { GPD_DEVICE_ID_GENERIC_GP_ON_OFF_SWITCH, "Generic: GP On/Off Switch" },\r
- { GPD_DEVICE_ID_GENERIC_GP_SIMPLE_GENERIC_1STATE_SWITCH, "Generic: GP Simple Generic 1-state Switch" },\r
- { GPD_DEVICE_ID_GENERIC_GP_SIMPLE_GENERIC_2STATE_SWITCH, "Generic: GP Simple Generic 2-state Switch" },\r
- { GPD_DEVICE_ID_GENERIC_GP_SIMPLE_SENSOR, "Generic: GP Simple Sensor" },\r
-\r
- /* GP LIGHTING */\r
- { GPD_DEVICE_ID_LIGHTING_GP_COLOR_DIMMER_SWITCH, "Lighting: GP Color Dimmer Switch" },\r
- { GPD_DEVICE_ID_LIGHTING_GP_LIGHT_SENSOR, "Lighting: GP Light Sensor" },\r
- { GPD_DEVICE_ID_LIGHTING_GP_OCCUPANCY_SENSOR, "Lighting: GP Occupancy Sensor" },\r
-\r
- /* GP CLOSURES */\r
- { GPD_DEVICE_ID_CLOSURES_GP_DOOR_LOCK_CONTROLLER, "Closures: GP Door Lock Controller" },\r
-\r
- /* HVAC */\r
- { GPD_DEVICE_ID_HVAC_GP_FLOW_SENSOR, "HVAC: GP Flow Sensor" },\r
- { GPD_DEVICE_ID_HVAC_GP_INDOOR_ENVIRONMENT_SENSOR, "HVAC: GP Indoor Environment Sensor" },\r
- { GPD_DEVICE_ID_HVAC_GP_PRESSURE_SENSOR, "HVAC: GP Pressure Sensor" },\r
- { GPD_DEVICE_ID_HVAC_GP_TEMPERATURE_SENSOR, "HVAC: GP Temperature Sensor" },\r
-\r
- /* CUSTOM */\r
- { GPD_DEVICE_ID_MANUFACTURER_SPECIFIC, "Manufacturer Specific" },\r
-\r
- { 0, NULL }\r
-};\r
-\r
-/* GP directions. */\r
-static const value_string zbee_nwk_gp_directions[] = {\r
- { ZBEE_NWK_GP_FC_EXT_DIRECTION_FROM_ZGPD, "From ZGPD" },\r
- { ZBEE_NWK_GP_FC_EXT_DIRECTION_FROM_ZGPP, "From ZGPP" },\r
-\r
- { 0, NULL }\r
-};\r
-\r
-/* Frame types for Green Power profile. */\r
-static const value_string zbee_nwk_gp_frame_types[] = {\r
- { ZBEE_NWK_GP_FCF_DATA, "Data" },\r
- { ZBEE_NWK_GP_FCF_MAINTENANCE, "Maintenance" },\r
-\r
- { 0, NULL }\r
-};\r
-\r
-/* GreenPeak Green Power devices. */\r
-static const value_string zbee_nwk_gp_manufacturer_greenpeak_dev_names[] = {\r
- { ZBEE_NWK_GP_MANUF_GREENPEAK_IZDS, "IAS Zone Door Sensor" },\r
- { ZBEE_NWK_GP_MANUF_GREENPEAK_IZDWS, "IAS Zone Door/Window Sensor" },\r
- { ZBEE_NWK_GP_MANUF_GREENPEAK_IZLS, "IAS Zone Leakage Sensor" },\r
- { ZBEE_NWK_GP_MANUF_GREENPEAK_IZRHS, "IAS Zone Relative Humidity Sensor" },\r
-\r
- { 0, NULL }\r
-};\r
-\r
-/* GP manufacturers. */\r
-static const value_string zbee_nwk_gp_manufacturers_ids_names[] = {\r
- { ZBEE_NWK_GP_MANUF_ID_GREENPEAK, "GreenPeak" },\r
-\r
- { 0, NULL }\r
-};\r
-\r
-/* GP Src ID names. */\r
-static const value_string zbee_nwk_gp_src_id_names[] = {\r
- { ZBEE_NWK_GP_ZGPD_SRCID_ALL, "All" },\r
- { ZBEE_NWK_GP_ZGPD_SRCID_UNKNOWN, "Unspecified" },\r
-\r
- { 0, NULL }\r
-};\r
-\r
-/* GP security key type names. */\r
-static const value_string zbee_nwk_gp_src_sec_keys_type_names[] = {\r
- { ZBEE_NWK_GP_SECURITY_KEY_TYPE_DERIVED_INDIVIDUAL_GPD_KEY, "Derived individual GPD key" },\r
- { ZBEE_NWK_GP_SECURITY_KEY_TYPE_GPD_GROUP_KEY, "GPD group key" },\r
- { ZBEE_NWK_GP_SECURITY_KEY_TYPE_NO_KEY, "No key" },\r
- { ZBEE_NWK_GP_SECURITY_KEY_TYPE_NWK_KEY_DERIVED_GPD_KEY_GROUP_KEY, "NWK key derived GPD group key" },\r
- { ZBEE_NWK_GP_SECURITY_KEY_TYPE_PRECONFIGURED_INDIVIDUAL_GPD_KEY, "Individual, out of the box GPD key" },\r
- { ZBEE_NWK_GP_SECURITY_KEY_TYPE_ZB_NWK_KEY, "ZigBee NWK key" },\r
-\r
- { 0, NULL }\r
-};\r
-\r
-/* GP security levels. */\r
-static const value_string zbee_nwk_gp_src_sec_levels_names[] = {\r
- { ZBEE_NWK_GP_SECURITY_LEVEL_1LSB, "1 LSB of frame counter and short MIC only" },\r
- { ZBEE_NWK_GP_SECURITY_LEVEL_FULL, "Full frame counter and full MIC only" },\r
- { ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR, "Encryption with full frame counter and full MIC" },\r
- { ZBEE_NWK_GP_SECURITY_LEVEL_NO, "No security" },\r
-\r
- { 0, NULL }\r
-};\r
-\r
-/*************************/\r
-/* Function definitions. */\r
-/*************************/\r
-\r
-/* UAT record copy callback. */\r
-static void *\r
-uat_key_record_copy_cb(void *n, const void *o, size_t siz _U_)\r
-{\r
- uat_key_record_t *new_key = (uat_key_record_t *)n;\r
- const uat_key_record_t *old_key = (uat_key_record_t *)o;\r
-\r
- if (old_key->string) {\r
- new_key->string = g_strdup(old_key->string);\r
- } else {\r
- new_key->string = NULL;\r
- }\r
- if (old_key->label) {\r
- new_key->label = g_strdup(old_key->label);\r
- } else {\r
- new_key->label = NULL;\r
- }\r
- return new_key;\r
-}\r
-\r
-/* UAT record free callback. */\r
-static void\r
-uat_key_record_free_cb(void *r)\r
-{\r
- uat_key_record_t *key = (uat_key_record_t *)r;\r
- if (key->string) {\r
- g_free(key->string);\r
- }\r
- if (key->label) {\r
- g_free(key->label);\r
- }\r
-}\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * zbee_gp_security_parse_key\r
- * DESCRIPTION\r
- * Parses a key string from left to right into a buffer with increasing (normal byte order) or decreasing (reverse\r
- * byte order) address.\r
- * PARAMETERS\r
- * const gchar *key_str - pointer to the string\r
- * guint8 *key_buf - destination buffer in memory\r
- * gboolean byte_order - byte order\r
- * RETURNS\r
- * gboolean\r
- *---------------------------------------------------------------\r
- */\r
-static gboolean\r
-zbee_gp_security_parse_key(const gchar *key_str, guint8 *key_buf, gboolean byte_order)\r
-{\r
- gboolean string_mode = FALSE;\r
- gchar temp;\r
- int i, j;\r
-\r
- memset(key_buf, 0, ZBEE_SEC_CONST_KEYSIZE);\r
- if (key_str == NULL) {\r
- return FALSE;\r
- }\r
- if ((temp = *key_str++) == '"') {\r
- string_mode = TRUE;\r
- temp = *key_str++;\r
- }\r
- j = byte_order ? ZBEE_SEC_CONST_KEYSIZE - 1 : 0;\r
- for (i = ZBEE_SEC_CONST_KEYSIZE - 1; i >= 0; i--) {\r
- if (string_mode) {\r
- if (g_ascii_isprint(temp)) {\r
- key_buf[j] = temp;\r
- temp = *key_str++;\r
- } else {\r
- return FALSE;\r
- }\r
- } else {\r
- if ((temp == ':') || (temp == '-') || (temp == ' ')) {\r
- temp = *(key_str++);\r
- }\r
- if (g_ascii_isxdigit(temp)) {\r
- key_buf[j] = g_ascii_xdigit_value(temp) << 4;\r
- } else {\r
- return FALSE;\r
- }\r
- temp = *(key_str++);\r
- if (g_ascii_isxdigit(temp)) {\r
- key_buf[j] |= g_ascii_xdigit_value(temp);\r
- } else {\r
- return FALSE;\r
- }\r
- temp = *(key_str++);\r
- }\r
- if (byte_order) {\r
- j--;\r
- } else {\r
- j++;\r
- }\r
- }\r
- return TRUE;\r
-}\r
-\r
-/* UAT record update callback. */\r
-static void\r
-uat_key_record_update_cb(void *r, const char **err)\r
-{\r
- uat_key_record_t *rec = (uat_key_record_t *)r;\r
-\r
- if (rec->string == NULL) {\r
- *err = g_strdup_printf("Key can't be blank.");\r
- } else {\r
- g_strstrip(rec->string);\r
- if (rec->string[0] != 0) {\r
- *err = NULL;\r
- if (!zbee_gp_security_parse_key(rec->string, rec->key, rec->byte_order)) {\r
- *err = g_strdup_printf("Expecting %d hexadecimal bytes or a %d character double-quoted string",\r
- ZBEE_SEC_CONST_KEYSIZE, ZBEE_SEC_CONST_KEYSIZE);\r
- }\r
- } else {\r
- *err = g_strdup_printf("Key can't be blank.");\r
- }\r
- }\r
-}\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * dissect_zbee_nwk_gp_cmd_commissioning\r
- * DESCRIPTION\r
- * Dissector for ZigBee Green Power commissioning.\r
- * PARAMETERS\r
- * tvbuff_t *tvb - pointer to buffer containing raw packet.\r
- * packet_into *pinfo - pointer to packet information fields.\r
- * proto_tree *tree - pointer to data tree Wireshark uses to display packet.\r
- * zbee_nwk_green_power_packet *packet - packet data.\r
- * guint offset - current payload offset.\r
- * RETURNS\r
- * guint - payload processed offset.\r
- *---------------------------------------------------------------\r
- */\r
-static guint\r
-dissect_zbee_nwk_gp_cmd_commissioning(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,\r
- zbee_nwk_green_power_packet *packet _U_, guint offset)\r
-{\r
- guint8 comm_options = 0;\r
- guint8 comm_ext_options = 0;\r
- guint8 ms_ext_options = 0;\r
- guint16 manufacturer_id = 0;\r
- proto_item *ti = NULL;\r
- proto_tree *field_tree = NULL;\r
-\r
- /* Get Device ID and display it. */\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_device_id, tvb, offset, 1, ENC_NA);\r
- offset += 1;\r
- /* Get Options Field, build subtree and display the results. */\r
- comm_options = tvb_get_guint8(tvb, offset);\r
- if (tree) {\r
- ti = proto_tree_add_text(tree, tvb, offset, 1, "Options Field: 0x%02x", comm_options);\r
- field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_mac_sec_num_cap, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_rx_on_cap, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_ms_ext_present, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_panid_req, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_sec_key_req, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_fixed_location, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_ext_opt, tvb, offset, 1, ENC_NA);\r
- }\r
- offset += 1;\r
- if (comm_options & ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_EXT_OPTIONS) {\r
- /* Get extended Options Field, build subtree and display the results. */\r
- comm_ext_options = tvb_get_guint8(tvb, offset);\r
- if (tree) {\r
- ti = proto_tree_add_text(tree, tvb, offset, 1, "Extended Options Field: 0x%02x", comm_ext_options);\r
- field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ext_opt_sec_level_cap, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ext_opt_key_type, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ext_opt_gpd_key_present, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ext_opt_gpd_key_encr, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ext_opt_outgoing_counter, tvb, offset, 1, ENC_NA);\r
- }\r
- offset += 1;\r
- if (comm_ext_options & ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_GPD_KEY_PRESENT) {\r
- /* Get security key and display it. */\r
- proto_tree_add_text(tree, tvb, offset, sizeof(nwk_cmd_security_key), "Security Key: %s",\r
- tvb_get_string(wmem_packet_scope(), tvb, offset, sizeof(nwk_cmd_security_key)));\r
- offset += sizeof(nwk_cmd_security_key);\r
- }\r
- if (comm_ext_options & ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_GPD_KEY_ENCR) {\r
- /* Get Security MIC and display it. */\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_gpd_sec_key_mic, tvb, offset, 4, ENC_LITTLE_ENDIAN);\r
- offset += 4;\r
- }\r
- if (comm_ext_options & ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_OUT_COUNTER) {\r
- /* Get GPD Outgoing Frame Counter and display it. */\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_outgoing_counter, tvb, offset, 4, ENC_LITTLE_ENDIAN);\r
- offset += 4;\r
- }\r
- }\r
- /* Display manufacturer specific data. */\r
- if (comm_options & ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_MANUFACTURER_INFO) {\r
- /* Display MS extensions. */\r
- ms_ext_options = tvb_get_guint8(tvb, offset);\r
- if (tree) {\r
- ti = proto_tree_add_text(tree, tvb, offset, 1, "MS Extensions Field: 0x%02x", ms_ext_options);\r
- field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_ms_ext);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ms_ext_mip, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ms_ext_mmip, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ms_ext_gclp, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ms_ext_crp, tvb, offset, 1, ENC_NA);\r
- }\r
- offset += 1;\r
- if (ms_ext_options & ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_MIP) {\r
- /* Get Manufacturer ID. */\r
- manufacturer_id = tvb_get_letohs(tvb, offset);\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_manufacturer_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);\r
- offset += 2;\r
- }\r
- if (ms_ext_options & ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_MMIP) {\r
- /* Get Manufacturer Device ID. */\r
- switch (manufacturer_id) {\r
- case ZBEE_NWK_GP_MANUF_ID_GREENPEAK:\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_manufacturer_greenpeak_dev_id, tvb, offset, 2,\r
- ENC_LITTLE_ENDIAN);\r
- offset += 2;\r
- break;\r
- }\r
- }\r
- }\r
- return offset;\r
-} /* dissect_zbee_nwk_gp_cmd_commissioning */\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * dissect_zbee_nwk_gp_cmd_channel_request\r
- * DESCRIPTION\r
- * Dissector for ZigBee Green Power channel request.\r
- * PARAMETERS\r
- * tvbuff_t *tvb - pointer to buffer containing raw packet.\r
- * packet_into *pinfo - pointer to packet information fields.\r
- * proto_tree *tree - pointer to data tree Wireshark uses to display packet.\r
- * zbee_nwk_green_power_packet *packet - packet data.\r
- * guint offset - current payload offset.\r
- * RETURNS\r
- * guint - payload processed offset.\r
- *---------------------------------------------------------------\r
- */\r
-static guint\r
-dissect_zbee_nwk_gp_cmd_channel_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,\r
- zbee_nwk_green_power_packet *packet _U_, guint offset)\r
-{\r
- proto_item *ti;\r
- proto_tree *field_tree;\r
-\r
- /* Get Command Options Field, build subtree and display the results. */\r
- if (tree) {\r
- ti = proto_tree_add_text(tree, tvb, offset, 1, "Channel Toggling Behaviour: 0x%02x", tvb_get_guint8(tvb,\r
- offset));\r
- field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_channel_request_toggling_behaviour_1st, tvb, offset, 1,\r
- ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_channel_request_toggling_behaviour_2nd, tvb, offset, 1,\r
- ENC_NA);\r
- }\r
- offset += 1;\r
- return offset;\r
-} /* dissect_zbee_nwk_gp_cmd_channel_request */\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * dissect_zbee_nwk_gp_cmd_channel_configuration\r
- * DESCRIPTION\r
- * Dissector for ZigBee Green Power channel configuration.\r
- * PARAMETERS\r
- * tvbuff_t *tvb - pointer to buffer containing raw packet.\r
- * packet_into *pinfo - pointer to packet information fields.\r
- * proto_tree *tree - pointer to data tree Wireshark uses to display packet.\r
- * zbee_nwk_green_power_packet *packet - packet data.\r
- * guint offset - current payload offset.\r
- * RETURNS\r
- * guint - payload processed offset.\r
- *---------------------------------------------------------------\r
- */\r
-static guint\r
-dissect_zbee_nwk_gp_cmd_channel_configuration(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,\r
- zbee_nwk_green_power_packet *packet _U_, guint offset)\r
-{\r
- proto_item *ti;\r
- proto_tree *field_tree;\r
-\r
- /* Get Command Options Field, build subtree and display the results. */\r
- if (tree) {\r
- ti = proto_tree_add_text(tree, tvb, offset, 1, "Operational Channel: 0x%02x", tvb_get_guint8(tvb, offset));\r
- field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_channel_configuration, tvb, offset, 1, ENC_NA);\r
- }\r
- offset += 1;\r
- return offset;\r
-} /* dissect_zbee_nwk_gp_cmd_channel_configuration */\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * dissect_zbee_nwk_gp_cmd_attr_reporting\r
- * DESCRIPTION\r
- * Dissector for ZigBee Green Power commands attrib reporting.\r
- * PARAMETERS\r
- * tvbuff_t *tvb - pointer to buffer containing raw packet.\r
- * packet_into *pinfo - pointer to packet information fields.\r
- * proto_tree *tree - pointer to data tree Wireshark uses to display packet.\r
- * zbee_nwk_green_power_packet *packet - packet data.\r
- * guint offset - current payload offset.\r
- * RETURNS\r
- * guint - payload processed offset.\r
- *---------------------------------------------------------------\r
- */\r
-static guint\r
-dissect_zbee_nwk_gp_cmd_attr_reporting(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,\r
- zbee_nwk_green_power_packet *packet _U_, guint offset)\r
-{\r
- guint16 cluster_id;\r
- proto_item *ti;\r
- proto_tree *field_tree;\r
-\r
- /* Get cluster ID and add it into the tree. */\r
- cluster_id = tvb_get_letohs(tvb, offset);\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_attr_report_cluster_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);\r
-\r
- offset += 2;\r
- /* Create subtree and parse ZCL Write Attribute Payload. */\r
- ti = proto_tree_add_text(tree, tvb, offset, 2, "Attribute reporting command for cluster: 0x%02X", cluster_id);\r
- field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);\r
- dissect_zcl_write_attr(tvb, pinfo, field_tree, &offset, cluster_id);\r
-\r
- return offset;\r
-} /* dissect_zbee_nwk_gp_cmd_attr_reporting */\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * dissect_zbee_nwk_gp_cmd_commissioning_reply\r
- * DESCRIPTION\r
- * Dissector for ZigBee Green Power comissioning reply.\r
- * PARAMETERS\r
- * tvbuff_t *tvb - pointer to buffer containing raw packet.\r
- * packet_into *pinfo - pointer to packet information fields.\r
- * proto_tree *tree - pointer to data tree Wireshark uses to display packet.\r
- * zbee_nwk_green_power_packet *packet - packet data.\r
- * guint offset - current payload offset.\r
- * RETURNS\r
- * guint - payload processed offset.\r
- *---------------------------------------------------------------\r
- */\r
-static guint\r
-dissect_zbee_nwk_gp_cmd_commissioning_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,\r
- zbee_nwk_green_power_packet *packet _U_, guint offset)\r
-{\r
- guint8 cr_options = 0;\r
- proto_item *ti = NULL;\r
- proto_tree *field_tree = NULL;\r
-\r
- /* Get Options Field, build subtree and display the results. */\r
- cr_options = tvb_get_guint8(tvb, offset);\r
- if (tree) {\r
- ti = proto_tree_add_text(tree, tvb, offset, 1, "Options Field: 0x%02x", cr_options);\r
- field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_rep_opt_panid_present, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_key_present, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_rep_opt_key_encr, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_level, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_type, tvb, offset, 1, ENC_NA);\r
- }\r
- offset += 1;\r
- /* Parse and display security Pan ID value. */\r
- if (cr_options & ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_PAN_ID_PRESENT) {\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_rep_pan_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);\r
- offset += 2;\r
- }\r
- /* Parse and display security key. */\r
- if (cr_options & ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_SEC_KEY_PRESENT) {\r
- proto_tree_add_text(tree, tvb, offset, sizeof(nwk_cmd_security_key), "Security Key: %s",\r
- tvb_get_string(wmem_packet_scope(), tvb, offset, sizeof(nwk_cmd_security_key)));\r
- offset += sizeof(nwk_cmd_security_key);\r
- }\r
- /* Parse and display security MIC. */\r
- if ((cr_options & ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_KEY_ENCR) && (cr_options &\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_SEC_KEY_PRESENT)) {\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_gpd_sec_key_mic, tvb, offset, 4, ENC_LITTLE_ENDIAN);\r
- offset += 4;\r
- }\r
- return offset;\r
-} /* dissect_zbee_nwk_gp_cmd_commissioning_reply */\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * dissect_zbee_nwk_gp_cmd_move_color\r
- * DESCRIPTION\r
- * Dissector for ZigBee Green Power Move Color.\r
- * PARAMETERS\r
- * tvbuff_t *tvb - pointer to buffer containing raw packet.\r
- * packet_into *pinfo - pointer to packet information fields.\r
- * proto_tree *tree - pointer to data tree Wireshark uses to display packet.\r
- * zbee_nwk_green_power_packet *packet - packet data.\r
- * guint offset - current payload offset.\r
- * RETURNS\r
- * guint - payload processed offset.\r
- *---------------------------------------------------------------\r
- */\r
-static guint\r
-dissect_zbee_nwk_gp_cmd_move_color(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,\r
- zbee_nwk_green_power_packet *packet _U_, guint offset)\r
-{\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_move_color_ratex, tvb, offset, 2, ENC_LITTLE_ENDIAN);\r
- offset += 2;\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_move_color_ratey, tvb, offset, 2, ENC_LITTLE_ENDIAN);\r
- offset += 2;\r
- return offset;\r
-} /* dissect_zbee_nwk_gp_cmd_move_color */\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * dissect_zbee_nwk_gp_cmd_move_up_down\r
- * DESCRIPTION\r
- * Dissector for ZigBee Green Power Move Up/Down.\r
- * PARAMETERS\r
- * tvbuff_t *tvb - pointer to buffer containing raw packet.\r
- * packet_into *pinfo - pointer to packet information fields.\r
- * proto_tree *tree - pointer to data tree Wireshark uses to display packet.\r
- * zbee_nwk_green_power_packet *packet - packet data.\r
- * guint offset - current payload offset.\r
- * RETURNS\r
- * guint - payload processed offset.\r
- *---------------------------------------------------------------\r
- */\r
-static guint\r
-dissect_zbee_nwk_gp_cmd_move_up_down(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,\r
- zbee_nwk_green_power_packet *packet _U_, guint offset)\r
-{\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_move_up_down_rate, tvb, offset, 1, ENC_NA);\r
- offset += 1;\r
- return offset;\r
-} /* dissect_zbee_nwk_gp_cmd_move_up_down */\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * dissect_zbee_nwk_gp_cmd_step_color\r
- * DESCRIPTION\r
- * Dissector for ZigBee Green Power Step Color.\r
- * PARAMETERS\r
- * tvbuff_t *tvb - pointer to buffer containing raw packet.\r
- * packet_into *pinfo - pointer to packet information fields.\r
- * proto_tree *tree - pointer to data tree Wireshark uses to display packet.\r
- * zbee_nwk_green_power_packet *packet - packet data.\r
- * guint offset - current payload offset.\r
- * RETURNS\r
- * guint - payload processed offset.\r
- *---------------------------------------------------------------\r
- */\r
-static guint\r
-dissect_zbee_nwk_gp_cmd_step_color(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,\r
- zbee_nwk_green_power_packet *packet _U_, guint offset)\r
-{\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_step_color_stepx, tvb, offset, 2, ENC_LITTLE_ENDIAN);\r
- offset += 2;\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_step_color_stepy, tvb, offset, 2, ENC_LITTLE_ENDIAN);\r
- offset += 2;\r
- /* Optional time field. */\r
- if (tvb_reported_length(tvb) - offset >= 2) {\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_step_color_transition_time, tvb, offset, 2, ENC_LITTLE_ENDIAN);\r
- offset += 2;\r
- }\r
- return offset;\r
-} /* dissect_zbee_nwk_gp_cmd_step_color */\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * dissect_zbee_nwk_gp_cmd_step_up_down\r
- * DESCRIPTION\r
- * Dissector for ZigBee Green Power Step Up/Down.\r
- * PARAMETERS\r
- * tvbuff_t *tvb - pointer to buffer containing raw packet.\r
- * packet_into *pinfo - pointer to packet information fields.\r
- * proto_tree *tree - pointer to data tree Wireshark uses to display packet.\r
- * zbee_nwk_green_power_packet *packet - packet data.\r
- * guint offset - current payload offset.\r
- * RETURNS\r
- * guint - payload processed offset.\r
- *---------------------------------------------------------------\r
- */\r
-static guint\r
-dissect_zbee_nwk_gp_cmd_step_up_down(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,\r
- zbee_nwk_green_power_packet *packet _U_, guint offset)\r
-{\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_step_up_down_step_size, tvb, offset, 1, ENC_NA);\r
- offset += 1;\r
- proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_step_up_down_transition_time, tvb, offset, 2, ENC_LITTLE_ENDIAN);\r
- offset += 2;\r
- return offset;\r
-} /* dissect_zbee_nwk_gp_cmd_step_up_down */\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * dissect_zbee_nwk_gp_cmd\r
- * DESCRIPTION\r
- * Dissector for ZigBee Green Power commands.\r
- * PARAMETERS\r
- * tvbuff_t *tvb - pointer to buffer containing raw packet.\r
- * packet_into *pinfo - pointer to packet information fields.\r
- * proto_tree *tree - pointer to data tree Wireshark uses to display packet.\r
- * void *data - raw packet private data.\r
- * RETURNS\r
- * guint - payload processed offset\r
- *---------------------------------------------------------------\r
- */\r
-static guint\r
-dissect_zbee_nwk_gp_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)\r
-{\r
- guint offset = 0;\r
- guint8 cmd_id = tvb_get_guint8(tvb, offset);\r
- proto_item *cmd_root = NULL;\r
- proto_tree *cmd_tree = NULL;\r
- zbee_nwk_green_power_packet *packet = (zbee_nwk_green_power_packet *)data;\r
-\r
- /* Create a subtree for the command. */\r
- if (tree) {\r
- cmd_root = proto_tree_add_text(tree, tvb, offset, tvb_length(tvb), "Command Frame: %s", val_to_str(cmd_id,\r
- zbee_nwk_gp_cmd_names, "Unknown Command Frame"));\r
- cmd_tree = proto_item_add_subtree(cmd_root, ett_zbee_nwk_cmd);\r
- /* Add the command ID. */\r
- proto_tree_add_uint(cmd_tree, hf_zbee_nwk_gp_command_id, tvb, offset, 1, cmd_id);\r
- }\r
- offset += 1;\r
- /* Add the command name to the info column. */\r
- col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(cmd_id, zbee_nwk_gp_cmd_names, "Unknown command"));\r
- /* Handle the command for one of the following devices:\r
- * - Door Lock Controller (IDs: 0x50 - 0x51);\r
- * - GP Flow Sensor (IDs: 0xE0, 0xA0 - 0xA3);\r
- * - GP Temperature Sensor (IDs: 0xE0, 0xA0 - 0xA3); */\r
- switch(cmd_id) {\r
- /* Payloadless GPDF commands sent by GPD. */\r
- case ZB_GP_CMD_ID_IDENTIFY:\r
- case ZB_GP_CMD_ID_SCENE0:\r
- case ZB_GP_CMD_ID_SCENE1:\r
- case ZB_GP_CMD_ID_SCENE2:\r
- case ZB_GP_CMD_ID_SCENE3:\r
- case ZB_GP_CMD_ID_SCENE4:\r
- case ZB_GP_CMD_ID_SCENE5:\r
- case ZB_GP_CMD_ID_SCENE6:\r
- case ZB_GP_CMD_ID_SCENE7:\r
- case ZB_GP_CMD_ID_SCENE8:\r
- case ZB_GP_CMD_ID_SCENE9:\r
- case ZB_GP_CMD_ID_SCENE10:\r
- case ZB_GP_CMD_ID_SCENE11:\r
- case ZB_GP_CMD_ID_SCENE12:\r
- case ZB_GP_CMD_ID_SCENE13:\r
- case ZB_GP_CMD_ID_SCENE14:\r
- case ZB_GP_CMD_ID_SCENE15:\r
- case ZB_GP_CMD_ID_OFF:\r
- case ZB_GP_CMD_ID_ON:\r
- case ZB_GP_CMD_ID_TOGGLE:\r
- case ZB_GP_CMD_ID_RELEASE:\r
- case ZB_GP_CMD_ID_LEVEL_CONTROL_STOP:\r
- case ZB_GP_CMD_ID_MOVE_HUE_STOP:\r
- case ZB_GP_CMD_ID_MOVE_SATURATION_STOP:\r
- case ZB_GP_CMD_ID_LOCK_DOOR:\r
- case ZB_GP_CMD_ID_UNLOCK_DOOR:\r
- case ZB_GP_CMD_ID_PRESS11:\r
- case ZB_GP_CMD_ID_RELEASE11:\r
- case ZB_GP_CMD_ID_PRESS12:\r
- case ZB_GP_CMD_ID_RELEASE12:\r
- case ZB_GP_CMD_ID_PRESS22:\r
- case ZB_GP_CMD_ID_RELEASE22:\r
- case ZB_GP_CMD_ID_SHORT_PRESS11:\r
- case ZB_GP_CMD_ID_SHORT_PRESS12:\r
- case ZB_GP_CMD_ID_SHORT_PRESS22:\r
- case ZB_GP_CMD_ID_DECOMMISSIONING:\r
- case ZB_GP_CMD_ID_SUCCESS:\r
- break;\r
- /* GPDF commands with payload sent by GPD. */\r
- case ZB_GP_CMD_ID_MOVE_UP:\r
- case ZB_GP_CMD_ID_MOVE_DOWN:\r
- case ZB_GP_CMD_ID_MOVE_UP_WITH_ON_OFF:\r
- case ZB_GP_CMD_ID_MOVE_DOWN_WITH_ON_OFF:\r
- case ZB_GP_CMD_ID_MOVE_HUE_UP:\r
- case ZB_GP_CMD_ID_MOVE_HUE_DOWN:\r
- case ZB_GP_CMD_ID_MOVE_SATUREATION_UP:\r
- case ZB_GP_CMD_ID_MOVE_SATUREATION_DOWN:\r
- offset = dissect_zbee_nwk_gp_cmd_move_up_down(tvb, pinfo, cmd_tree, packet, offset);\r
- break;\r
- case ZB_GP_CMD_ID_STEP_UP:\r
- case ZB_GP_CMD_ID_STEP_DOWN:\r
- case ZB_GP_CMD_ID_STEP_UP_WITH_ON_OFF:\r
- case ZB_GP_CMD_ID_STEP_DOWN_WITH_ON_OFF:\r
- case ZB_GP_CMD_ID_STEP_HUE_UP:\r
- case ZB_GP_CMD_ID_STEP_HUW_DOWN:\r
- case ZB_GP_CMD_ID_STEP_SATURATION_UP:\r
- case ZB_GP_CMD_ID_STEP_SATURATION_DOWN:\r
- offset = dissect_zbee_nwk_gp_cmd_step_up_down(tvb, pinfo, cmd_tree, packet, offset);\r
- break;\r
- case ZB_GP_CMD_ID_MOVE_COLOR:\r
- offset = dissect_zbee_nwk_gp_cmd_move_color(tvb, pinfo, cmd_tree, packet, offset);\r
- break;\r
- case ZB_GP_CMD_ID_STEP_COLOR:\r
- offset = dissect_zbee_nwk_gp_cmd_step_color(tvb, pinfo, cmd_tree, packet, offset);\r
- break;\r
- case ZB_GP_CMD_ID_ATTRIBUTE_REPORTING:\r
- offset = dissect_zbee_nwk_gp_cmd_attr_reporting(tvb, pinfo, cmd_tree, packet, offset);\r
- break;\r
- case ZB_GP_CMD_ID_MANUFACTURE_SPECIFIC_ATTR_REPORTING:\r
- case ZB_GP_CMD_ID_MULTI_CLUSTER_REPORTING:\r
- case ZB_GP_CMD_ID_MANUFACTURER_SPECIFIC_MCLUSTER_REPORTING:\r
- case ZB_GP_CMD_ID_REQUEST_ATTRIBUTES:\r
- case ZB_GP_CMD_ID_READ_ATTRIBUTES_RESPONSE:\r
- case ZB_GP_CMD_ID_ANY_SENSOR_COMMAND_A0_A3:\r
- /* TODO: implement it. */\r
- break;\r
- case ZB_GP_CMD_ID_COMMISSIONING:\r
- offset = dissect_zbee_nwk_gp_cmd_commissioning(tvb, pinfo, cmd_tree, packet, offset);\r
- break;\r
- case ZB_GP_CMD_ID_CHANNEL_REQUEST:\r
- offset = dissect_zbee_nwk_gp_cmd_channel_request(tvb, pinfo, cmd_tree, packet, offset);\r
- break;\r
- /* GPDF commands sent to GPD. */\r
- case ZB_GP_CMD_ID_COMMISSIONING_REPLY:\r
- offset = dissect_zbee_nwk_gp_cmd_commissioning_reply(tvb, pinfo, cmd_tree, packet, offset);\r
- break;\r
- case ZB_GP_CMD_ID_WRITE_ATTRIBUTES:\r
- case ZB_GP_CMD_ID_READ_ATTRIBUTES:\r
- /* TODO: implement it. */\r
- break;\r
- case ZB_GP_CMD_ID_CHANNEL_CONFIGURATION:\r
- offset = dissect_zbee_nwk_gp_cmd_channel_configuration(tvb, pinfo, cmd_tree, packet, offset);\r
- break;\r
- }\r
- if (offset < tvb_reported_length(tvb)) {\r
- /* There are leftover bytes! */\r
- proto_tree *root = NULL;\r
- tvbuff_t *leftover_tvb = tvb_new_subset_remaining(tvb, offset);\r
-\r
- /* Correct the length of the command tree. */\r
- if (tree) {\r
- root = proto_tree_get_root(tree);\r
- proto_item_set_len(cmd_root, offset);\r
- }\r
- /* Dump the tail. */\r
- call_dissector(data_handle, leftover_tvb, pinfo, root);\r
- }\r
- return offset;\r
-} /* dissect_zbee_nwk_gp_cmd */\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * zbee_sec_make_nonce\r
- * DESCRIPTION\r
- * Fills in ZigBee GP security nonce from the provided packet structure.\r
- * PARAMETERS\r
- * zbee_nwk_green_power_packet *packet - ZigBee NWK packet.\r
- * gchar *nonce - nonce buffer.\r
- * RETURNS\r
- * void\r
- *---------------------------------------------------------------\r
- */\r
-static void\r
-zbee_gp_make_nonce(zbee_nwk_green_power_packet *packet, gchar *nonce)\r
-{\r
- memset(nonce, 0, ZBEE_SEC_CONST_NONCE_LEN);\r
- if (packet->direction == ZBEE_NWK_GP_FC_EXT_DIRECTION_FROM_ZGPD) {\r
- nonce[0] = (guint8)((packet->source_id) & 0xff);\r
- nonce[1] = (guint8)((packet->source_id) >> 8 & 0xff);\r
- nonce[2] = (guint8)((packet->source_id) >> 16 & 0xff);\r
- nonce[3] = (guint8)((packet->source_id) >> 24 & 0xff);\r
- }\r
- nonce[4] = (guint8)((packet->source_id) & 0xff);\r
- nonce[5] = (guint8)((packet->source_id) >> 8 & 0xff);\r
- nonce[6] = (guint8)((packet->source_id) >> 16 & 0xff);\r
- nonce[7] = (guint8)((packet->source_id) >> 24 & 0xff);\r
- nonce[8] = (guint8)((packet->security_frame_counter) & 0xff);\r
- nonce[9] = (guint8)((packet->security_frame_counter) >> 8 & 0xff);\r
- nonce[10] = (guint8)((packet->security_frame_counter) >> 16 & 0xff);\r
- nonce[11] = (guint8)((packet->security_frame_counter) >> 24 & 0xff);\r
- if ((packet->application_id == ZBEE_NWK_GP_APP_ID_ZGP) && (packet->direction !=\r
- ZBEE_NWK_GP_FC_EXT_DIRECTION_FROM_ZGPD)) {\r
- nonce[12] = 0xa3;\r
- } else {\r
- nonce[12] = 0x05;\r
- }\r
- /* TODO: implement if application_id == ZB_ZGP_APP_ID_0000. */\r
- /* TODO: implement if application_id != ZB_ZGP_APP_ID_0000. */\r
-}\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * zbee_sec_decrypt_payload\r
- * DESCRIPTION\r
- * Creates a nonce and decrypts secured ZigBee GP payload.\r
- * PARAMETERS\r
- * zbee_nwk_green_power_packet *packet - ZigBee NWK packet.\r
- * const gchar *enc_buffer - encoded payload buffer.\r
- * const gchar offset - payload offset.\r
- * guint8 *dec_buffer - decoded payload buffer.\r
- * guint payload_len - payload length.\r
- * guint mic_len - MIC length.\r
- * guint8 *key - key.\r
- * RETURNS\r
- * gboolean\r
- *---------------------------------------------------------------\r
- */\r
-static gboolean\r
-zbee_gp_decrypt_payload(zbee_nwk_green_power_packet *packet, const gchar *enc_buffer, const gchar offset, guint8\r
- *dec_buffer, guint payload_len, guint mic_len, guint8 *key)\r
-{\r
- guint8 *key_buffer = key;\r
- guint8 nonce[ZBEE_SEC_CONST_NONCE_LEN];\r
-\r
- zbee_gp_make_nonce(packet, nonce);\r
- if (zbee_sec_ccm_decrypt(key_buffer, nonce, enc_buffer, enc_buffer + offset, dec_buffer, offset, payload_len,\r
- mic_len)) {\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * dissect_zbee_nwk_gp\r
- * DESCRIPTION\r
- * ZigBee NWK packet dissection routine for Green Power profile.\r
- * PARAMETERS\r
- * tvbuff_t *tvb - pointer to buffer containing raw packet.\r
- * packet_into *pinfo - pointer to packet information fields.\r
- * proto_tree *tree - pointer to data tree Wireshark uses to display packet.\r
- * void *data - raw packet private data.\r
- * RETURNS\r
- * int\r
- *---------------------------------------------------------------\r
- */\r
-static int\r
-dissect_zbee_nwk_gp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)\r
-{\r
- gboolean gp_decrypted;\r
- GSList *GSList_i;\r
- guint offset = 0;\r
- guint8 *dec_buffer;\r
- guint8 *enc_buffer;\r
- guint8 fcf;\r
- proto_tree *field_tree = NULL;\r
- proto_tree *nwk_tree = NULL;\r
- proto_item *proto_root = NULL;\r
- proto_item *ti = NULL;\r
- tvbuff_t *payload_tvb = NULL;\r
- zbee_nwk_green_power_packet packet;\r
-\r
- memset(&packet, 0, sizeof(packet));\r
- /* Add ourself to the protocol column, clear the info column and create the protocol tree. */\r
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZigBee Green Power");\r
- col_clear(pinfo->cinfo, COL_INFO);\r
- if (tree) {\r
- proto_root = proto_tree_add_protocol_format(tree, proto_zbee_nwk_gp, tvb, offset, tvb_length(tvb),\r
- "ZGP stub NWK header");\r
- nwk_tree = proto_item_add_subtree(proto_root, ett_zbee_nwk);\r
- }\r
- enc_buffer = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 0, tvb_length(tvb));\r
- /* Get and parse the FCF. */\r
- fcf = tvb_get_guint8(tvb, offset);\r
- packet.frame_type = zbee_get_bit_field(fcf, ZBEE_NWK_GP_FCF_FRAME_TYPE);\r
- packet.nwk_frame_control_extension = zbee_get_bit_field(fcf, ZBEE_NWK_GP_FCF_CONTROL_EXTENSION);\r
- /* Display the FCF. */\r
- if (tree) {\r
- /* Create a subtree for the FCF. */\r
- ti = proto_tree_add_text(nwk_tree, tvb, offset, 1, "Frame Control Field: %s (0x%02x)",\r
- val_to_str(packet.frame_type, zbee_nwk_gp_frame_types, "Unknown Frame Type"), fcf);\r
- field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_fcf);\r
- proto_tree_add_uint(field_tree, hf_zbee_nwk_gp_frame_type, tvb, offset, 1, fcf & ZBEE_NWK_GP_FCF_FRAME_TYPE);\r
- proto_tree_add_uint(field_tree, hf_zbee_nwk_gp_proto_version, tvb, offset, 1, fcf & ZBEE_NWK_GP_FCF_VERSION);\r
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_gp_auto_commissioning, tvb, offset, 1, fcf &\r
- ZBEE_NWK_GP_FCF_AUTO_COMMISSIONING);\r
- proto_tree_add_boolean(field_tree, hf_zbee_nwk_gp_fc_ext, tvb, offset, 1, fcf &\r
- ZBEE_NWK_GP_FCF_CONTROL_EXTENSION);\r
- }\r
- offset += 1;\r
- /* Add the frame type to the info column and protocol root. */\r
- if (tree) {\r
- proto_item_append_text(proto_root, " %s", val_to_str(packet.frame_type, zbee_nwk_gp_frame_types,\r
- "Unknown type"));\r
- }\r
- col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet.frame_type, zbee_nwk_gp_frame_types,\r
- "Reserved frame type"));\r
- if (packet.nwk_frame_control_extension) {\r
- /* Display ext FCF. */\r
- fcf = tvb_get_guint8(tvb, offset);\r
- packet.application_id = zbee_get_bit_field(fcf, ZBEE_NWK_GP_FCF_EXT_APP_ID);\r
- packet.security_level = zbee_get_bit_field(fcf, ZBEE_NWK_GP_FCF_EXT_SECURITY_LEVEL);\r
- packet.direction = zbee_get_bit_field(fcf, ZBEE_NWK_GP_FCF_EXT_DIRECTION);\r
- /* Create a subtree for the extended FCF. */\r
- if (tree) {\r
- ti = proto_tree_add_text(nwk_tree, tvb, offset, 1, "Extended NWK Frame Control Field");\r
- field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_fcf_ext);\r
- /* Add the fields. */\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_fc_ext_app_id, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_fc_ext_sec_level, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_fc_ext_sec_key, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_fc_ext_rx_after_tx, tvb, offset, 1, ENC_NA);\r
- proto_tree_add_item(field_tree, hf_zbee_nwk_gp_fc_ext_direction, tvb, offset, 1, ENC_NA);\r
- }\r
- offset += 1;\r
- }\r
- if ((packet.frame_type == ZBEE_NWK_GP_FCF_DATA && !packet.nwk_frame_control_extension) || (packet.frame_type ==\r
- ZBEE_NWK_GP_FCF_DATA && packet.nwk_frame_control_extension && packet.application_id ==\r
- ZBEE_NWK_GP_APP_ID_DEFAULT) || (packet.frame_type == ZBEE_NWK_GP_FCF_MAINTENANCE &&\r
- packet.nwk_frame_control_extension && packet.application_id == ZBEE_NWK_GP_APP_ID_DEFAULT && tvb_get_guint8(tvb,\r
- offset) != ZB_GP_CMD_ID_CHANNEL_CONFIGURATION)) {\r
- /* Display GPD Src ID. */\r
- packet.source_id = tvb_get_letohl(tvb, offset);\r
- proto_tree_add_item(nwk_tree, hf_zbee_nwk_gp_zgpd_src_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);\r
- proto_item_append_text(proto_root, ", GPD Src ID: 0x%04x", packet.source_id);\r
-\r
- col_append_fstr(pinfo->cinfo, COL_INFO, ", GPD Src ID: 0x%04x", packet.source_id);\r
- offset += 4;\r
- }\r
- /* Display Security Frame Counter. */\r
- packet.mic_size = 0;\r
- if (packet.nwk_frame_control_extension) {\r
- if (packet.application_id == ZBEE_NWK_GP_APP_ID_DEFAULT || packet.application_id == ZBEE_NWK_GP_APP_ID_ZGP) {\r
- if (packet.security_level == ZBEE_NWK_GP_SECURITY_LEVEL_1LSB) {\r
- packet.mic_size = 2;\r
- } else if (packet.security_level == ZBEE_NWK_GP_SECURITY_LEVEL_FULL || packet.security_level ==\r
- ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR) {\r
- /* Get Security Frame Counter and display it. */\r
- packet.mic_size = 4;\r
- packet.security_frame_counter = tvb_get_letohl(tvb, offset);\r
- proto_tree_add_item(nwk_tree, hf_zbee_nwk_gp_security_frame_counter, tvb, offset, 4,\r
- ENC_LITTLE_ENDIAN);\r
- offset += 4;\r
- }\r
- }\r
- }\r
- /* Parse application payload. */\r
- packet.payload_len = tvb_reported_length(tvb) - offset - packet.mic_size;\r
- /* Ensure that the payload exists. */\r
- if (packet.payload_len <= 0) {\r
- THROW(BoundsError);\r
- }\r
- /* OK, payload exists. Parse MIC field if needed. */\r
- if (packet.mic_size == 2) {\r
- packet.mic = tvb_get_letohs(tvb, offset + packet.payload_len);\r
- } else if (packet.mic_size == 4) {\r
- packet.mic = tvb_get_letohl(tvb, offset + packet.payload_len);\r
- }\r
- payload_tvb = tvb_new_subset(tvb, offset, packet.payload_len, packet.payload_len);\r
- if (packet.security_level != ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR) {\r
- dissect_zbee_nwk_gp_cmd(payload_tvb, pinfo, nwk_tree, data);\r
- }\r
- offset += packet.payload_len;\r
- /* Display MIC field. */\r
- if (packet.mic_size) {\r
- proto_tree_add_uint(nwk_tree, packet.mic_size == 4 ? hf_zbee_nwk_gp_security_mic_4b :\r
- hf_zbee_nwk_gp_security_mic_2b, tvb, offset, packet.mic_size, packet.mic);\r
- offset += packet.mic_size;\r
- }\r
- /* Save packet private data. */\r
- data = (void *)&packet;\r
- if ((offset < tvb_length(tvb)) && (packet.security_level != ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR)) {\r
- THROW(BoundsError);\r
- }\r
- if (packet.security_level == ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR) {\r
- dec_buffer = (guint8 *)g_malloc(packet.payload_len);\r
- gp_decrypted = FALSE;\r
- if (packet.security_level == ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR) {\r
- GSList_i = zbee_gp_keyring;\r
- while (GSList_i && !gp_decrypted) {\r
- gp_decrypted = zbee_gp_decrypt_payload(&packet, enc_buffer, offset - packet.payload_len -\r
- packet.mic_size, dec_buffer, packet.payload_len, packet.mic_size,\r
- ((key_record_t *)(GSList_i->data))->key);\r
- if (!gp_decrypted) {\r
- GSList_i = g_slist_next(GSList_i);\r
- }\r
- }\r
- }\r
- if (gp_decrypted) {\r
- payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, packet.payload_len, packet.payload_len);\r
- add_new_data_source(pinfo, payload_tvb, "Decrypted GP Payload");\r
- dissect_zbee_nwk_gp_cmd(payload_tvb, pinfo, nwk_tree, data);\r
- g_free(dec_buffer);\r
- return packet.payload_len;\r
- } else {\r
- g_free(dec_buffer);\r
- payload_tvb = tvb_new_subset(tvb, offset - packet.payload_len - packet.mic_size, packet.payload_len, -1);\r
- call_dissector(data_handle, payload_tvb, pinfo, tree);\r
- }\r
- }\r
- return 0;\r
-} /* dissect_zbee_nwk_gp */\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * dissect_zbee_nwk_heur_gp\r
- * DESCRIPTION\r
- * Heuristic interpreter for the ZigBee Green Power dissectors.\r
- * PARAMETERS\r
- * tvbuff_t *tvb - pointer to buffer containing raw packet.\r
- * packet_into *pinfo - pointer to packet information fields.\r
- * proto_tree *tree - pointer to data tree Wireshark uses to display packet.\r
- * void *data - raw packet private data.\r
- * RETURNS\r
- * Boolean value, whether it handles the packet or not.\r
- *---------------------------------------------------------------\r
- */\r
-static gboolean\r
-dissect_zbee_nwk_heur_gp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)\r
-{\r
- ieee802154_packet *packet = (ieee802154_packet *)data;\r
-\r
- /* Skip ZigBee beacons. */\r
- if ((packet->frame_type == IEEE802154_FCF_BEACON) && (tvb_get_guint8(tvb, 0) == ZBEE_NWK_BEACON_PROCOL_ID))\r
- return FALSE;\r
-\r
- if (packet->dst_pan == IEEE802154_BCAST_PAN && packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT &&\r
- packet->dst16 == IEEE802154_BCAST_ADDR && packet->frame_type != IEEE802154_FCF_BEACON &&\r
- packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {\r
- dissect_zbee_nwk_gp(tvb, pinfo, tree, data);\r
- return TRUE;\r
- }\r
- /* 64-bit destination addressing mode support. */\r
- if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT && packet->frame_type != IEEE802154_FCF_BEACON &&\r
- packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {\r
- dissect_zbee_nwk_gp(tvb, pinfo, tree, data);\r
- return TRUE;\r
- }\r
- /* All ZigBee 2006, 2007 and PRO frames must always have a 16-bit source address. */\r
- if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-} /* dissect_zbee_nwk_heur_gp */\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * gp_init_zbee_security\r
- * DESCRIPTION\r
- * Init routine for the ZigBee GP profile security.\r
- * PARAMETERS\r
- * none\r
- * RETURNS\r
- * void\r
- *---------------------------------------------------------------\r
- */\r
-static void\r
-gp_init_zbee_security(void)\r
-{\r
- guint i;\r
- key_record_t key_record;\r
-\r
- if (zbee_gp_keyring) {\r
- g_slist_free(zbee_gp_keyring);\r
- zbee_gp_keyring = NULL;\r
- }\r
- for (i = 0; gp_uat_key_records && (i < num_uat_key_records); i++) {\r
- key_record.frame_num = 0;\r
- key_record.label = g_strdup(gp_uat_key_records[i].label);\r
- memcpy(&key_record.key, &gp_uat_key_records[i].key, ZBEE_SEC_CONST_KEYSIZE);\r
- zbee_gp_keyring = g_slist_prepend(zbee_gp_keyring, g_memdup(&key_record, sizeof(key_record_t)));\r
- }\r
-}\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * proto_register_zbee_nwk_gp\r
- * DESCRIPTION\r
- * ZigBee NWK GP protocol registration routine.\r
- * PARAMETERS\r
- * none\r
- * RETURNS\r
- * void\r
- *---------------------------------------------------------------\r
- */\r
-void\r
-proto_register_zbee_nwk_gp(void)\r
-{\r
- module_t *gp_zbee_prefs = NULL;\r
-\r
- static hf_register_info hf[] = {\r
- { &hf_zbee_nwk_gp_auto_commissioning,\r
- { "Auto Commissioning", "zbee_nwk_gp.auto_commissioning", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_FCF_AUTO_COMMISSIONING, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_fc_ext,\r
- { "NWK Frame Extension", "zbee_nwk_gp.fc_extension", FT_BOOLEAN, 8, NULL, ZBEE_NWK_GP_FCF_CONTROL_EXTENSION,\r
- NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_frame_type,\r
- { "Frame Type", "zbee_nwk_gp.frame_type", FT_UINT8, BASE_HEX, VALS(zbee_nwk_gp_frame_types),\r
- ZBEE_NWK_GP_FCF_FRAME_TYPE, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_proto_version,\r
- { "Protocol Version", "zbee_nwk_gp.proto_version", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_GP_FCF_VERSION, NULL,\r
- HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_fc_ext_app_id,\r
- { "Application ID", "zbee_nwk_gp.fc_ext_app_id", FT_UINT8, BASE_HEX, VALS(zbee_nwk_gp_app_id_names),\r
- ZBEE_NWK_GP_FCF_EXT_APP_ID, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_fc_ext_direction,\r
- { "Direction", "zbee_nwk_gp.fc_ext_direction", FT_UINT8, BASE_HEX, VALS(zbee_nwk_gp_directions),\r
- ZBEE_NWK_GP_FCF_EXT_DIRECTION, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_fc_ext_rx_after_tx,\r
- { "Rx After Tx", "zbee_nwk_gp.fc_ext_rxaftertx", FT_BOOLEAN, 8, NULL, ZBEE_NWK_GP_FCF_EXT_RX_AFTER_TX, NULL,\r
- HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_fc_ext_sec_key,\r
- { "Security Key", "zbee_nwk_gp.fc_ext_security_key", FT_BOOLEAN, 8, NULL, ZBEE_NWK_GP_FCF_EXT_SECURITY_KEY,\r
- NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_fc_ext_sec_level,\r
- { "Security Level", "zbee_nwk_gp.fc_ext_security_level", FT_UINT8, BASE_HEX,\r
- VALS(zbee_nwk_gp_src_sec_levels_names), ZBEE_NWK_GP_FCF_EXT_SECURITY_LEVEL, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_zgpd_src_id,\r
- { "Src ID", "zbee_nwk_gp.source_id", FT_UINT32, BASE_HEX, VALS(zbee_nwk_gp_src_id_names), 0x0, NULL,\r
- HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_security_frame_counter,\r
- { "Security Frame Counter", "zbee_nwk_gp.security_frame_counter", FT_UINT32, BASE_DEC, NULL, 0x0, NULL,\r
- HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_security_mic_2b,\r
- { "Security MIC", "zbee_nwk_gp.security_mic2", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_security_mic_4b,\r
- { "Security MIC", "zbee_nwk_gp.security_mic4", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_command_id,\r
- { "ZGPD Command ID", "zbee_nwk_gp.command_id", FT_UINT8, BASE_HEX, VALS(zbee_nwk_gp_cmd_names), 0x0, NULL,\r
- HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_device_id,\r
- { "ZGPD Device ID", "zbee_nwk_gp.cmd.comm.dev_id", FT_UINT8, BASE_HEX, VALS(zbee_nwk_gp_device_ids_names),\r
- 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_ext_opt_gpd_key_encr,\r
- { "GPD Key Encryption", "zbee_nwk_gp.cmd.comm.ext_opt.gpd_key_encr", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_GPD_KEY_ENCR, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_ext_opt_gpd_key_present,\r
- { "GPD Key Present", "zbee_nwk_gp.cmd.comm.ext_opt.gpd_key_present", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_GPD_KEY_PRESENT, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_ext_opt_key_type,\r
- { "Key Type", "zbee_nwk_gp.cmd.comm.ext_opt.key_type", FT_UINT8, BASE_HEX,\r
- VALS(zbee_nwk_gp_src_sec_keys_type_names), ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_KEY_TYPE, NULL,\r
- HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_outgoing_counter,\r
- { "GPD Outgoing Counter", "zbee_nwk_gp.cmd.comm.out_counter", FT_UINT32, BASE_HEX, NULL, 0x0, NULL,\r
- HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_ext_opt_sec_level_cap,\r
- { "Security Level Capabilities", "zbee_nwk_gp.cmd.comm.ext_opt.seclevel_cap", FT_UINT8, BASE_HEX, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_SEC_LEVEL_CAP, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_gpd_sec_key_mic,\r
- { "GPD Key MIC", "zbee_nwk_gp.cmd.comm.gpd_key_mic", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_opt_ext_opt,\r
- { "Extended Option Field", "zbee_nwk_gp.cmd.comm.opt.ext_opt_field", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_EXT_OPTIONS, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_opt_fixed_location,\r
- { "Fixed Location", "zbee_nwk_gp.cmd.comm.opt.fixed_location", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_FIXED_LOCATION, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_opt_mac_sec_num_cap,\r
- { "MAC Sequence number capability", "zbee_nwk_gp.cmd.comm.opt.mac_seq_num_cap", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_MAC_SEQ, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_opt_ms_ext_present,\r
- { "MS Extensions Present", "zbee_nwk_gp.cmd.comm.opt.ms_ext_present", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_MANUFACTURER_INFO, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_opt_panid_req,\r
- { "PANId request", "zbee_nwk_gp.cmd.comm.opt.panid_req", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_PAN_ID_REQ, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_opt_rx_on_cap,\r
- { "RxOnCapability", "zbee_nwk_gp.cmd.comm.opt.rxon_cap", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_RX_ON_CAP, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_opt_sec_key_req,\r
- { "GP Security Key Request", "zbee_nwk_gp.cmd.comm.opt.seq_key_req", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_GP_SEC_KEY_REQ, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_ext_opt_outgoing_counter,\r
- { "GPD Outgoing present", "zbee_nwk_gp.cmd.comm.ext_opt.outgoing_counter", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_OUT_COUNTER, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_manufacturer_greenpeak_dev_id,\r
- { "Manufacturer Model ID", "zbee_nwk_gp.cmd.comm.manufacturer_model_id", FT_UINT16, BASE_HEX,\r
- VALS(zbee_nwk_gp_manufacturer_greenpeak_dev_names), 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_manufacturer_id,\r
- { "Manufacturer ID", "zbee_nwk_gp.cmd.comm.manufacturer_id", FT_UINT16, BASE_HEX,\r
- VALS(zbee_nwk_gp_manufacturers_ids_names), 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_ms_ext_crp,\r
- { "Cluster reports present", "zbee_nwk_gp.cmd.comm.ms_ext.crp", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_CRP , NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_ms_ext_gclp,\r
- { "GP commands list present", "zbee_nwk_gp.cmd.comm.ms_ext.gclp", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_GCLP , NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_ms_ext_mip,\r
- { "Manufacturer ID present", "zbee_nwk_gp.cmd.comm.ms_ext.mip", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_MIP , NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_ms_ext_mmip,\r
- { "Manufacturer Model ID present", "zbee_nwk_gp.cmd.comm.ms_ext.mmip", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_MMIP , NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_rep_opt_key_encr,\r
- { "GPD Key Encryption", "zbee_nwk_gp.cmd.comm_reply.opt.sec_key_encr", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_KEY_ENCR, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_rep_opt_panid_present,\r
- { "PANID Present", "zbee_nwk_gp.cmd.comm_reply.opt.pan_id_present", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_PAN_ID_PRESENT, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_key_present,\r
- { "GPD Security Key Present", "zbee_nwk_gp.cmd.comm_reply.opt.sec_key_present", FT_BOOLEAN, 8, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_SEC_KEY_PRESENT, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_level,\r
- { "Security Level", "zbee_nwk_gp.cmd.comm_reply.opt.sec_level", FT_UINT8, BASE_HEX, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_SEC_LEVEL, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_type,\r
- { "Key Type", "zbee_nwk_gp.cmd.comm_reply.opt.key_type", FT_UINT8, BASE_HEX, NULL,\r
- ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_KEY_TYPE, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_comm_rep_pan_id,\r
- { "Manufacturer ID", "zbee_nwk_gp.cmd.comm_reply.pan_id", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_attr_report_cluster_id,\r
- { "ZigBee Cluster ID", "zbee_nwk_gp.cmd.comm.attr_report", FT_UINT16, BASE_HEX, VALS(zbee_aps_cid_names),\r
- 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_channel_request_toggling_behaviour_1st,\r
- { "Rx channel in the next attempt", "zbee_nwk_gp.cmd.ch_req.1st", FT_UINT8, BASE_HEX, NULL,\r
- ZBEE_NWK_GP_CMD_CHANNEL_REQUEST_1ST, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_channel_request_toggling_behaviour_2nd,\r
- { "Rx channel in the second next attempt", "zbee_nwk_gp.ch_req.2nd", FT_UINT8, BASE_HEX, NULL,\r
- ZBEE_NWK_GP_CMD_CHANNEL_REQUEST_2ND, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_channel_configuration,\r
- { "Operation channel", "zbee_nwk_gp.cmd.configuration_ch.operation_ch", FT_UINT8, BASE_HEX, NULL,\r
- ZBEE_NWK_GP_CMD_CHANNEL_CONFIGURATION_OPERATION_CH, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_move_color_ratex,\r
- { "RateX", "zbee_nwk_gp.cmd.move_color.ratex", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_move_color_ratey,\r
- { "RateY", "zbee_nwk_gp.cmd.move_color.ratey", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_move_up_down_rate,\r
- { "Rate", "zbee_nwk_gp.cmd.move_up_down.rate", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_step_color_stepx,\r
- { "StepX", "zbee_nwk_gp.cmd.step_color.stepx", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_step_color_stepy,\r
- { "StepY", "zbee_nwk_gp.cmd.step_color.stepy", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_step_color_transition_time,\r
- { "Transition Time", "zbee_nwk_gp.cmd.step_color.transition_time", FT_UINT16, BASE_DEC, NULL, 0x0, NULL,\r
- HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_step_up_down_step_size,\r
- { "Step Size", "zbee_nwk_gp.cmd.step_up_down.step_size", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},\r
-\r
- { &hf_zbee_nwk_gp_cmd_step_up_down_transition_time,\r
- { "Transition Time", "zbee_nwk_gp.cmd.step_up_down.transition_time", FT_UINT16, BASE_DEC, NULL, 0x0, NULL,\r
- HFILL }}\r
- };\r
-\r
- static gint *ett[] = {\r
- &ett_zbee_nwk,\r
- &ett_zbee_nwk_cmd,\r
- &ett_zbee_nwk_cmd_cinfo,\r
- &ett_zbee_nwk_cmd_ms_ext,\r
- &ett_zbee_nwk_cmd_options,\r
- &ett_zbee_nwk_fcf,\r
- &ett_zbee_nwk_fcf_ext\r
- };\r
-\r
- static uat_field_t key_uat_fields[] = {\r
- UAT_FLD_CSTRING(gp_uat_key_records, string, "Key", "A 16-byte key."),\r
- UAT_FLD_VS(gp_uat_key_records, byte_order, "Byte Order", byte_order_vals, "Byte order of a key."),\r
- UAT_FLD_LSTRING(gp_uat_key_records, label, "Label", "User label for a key."),\r
- UAT_END_FIELDS\r
- };\r
-\r
- proto_zbee_nwk_gp = proto_register_protocol("ZigBee Green Power Profile", "ZigBee Green Power",\r
- ZBEE_PROTOABBREV_NWK_GP);\r
-\r
- if (gp_zbee_prefs == NULL) {\r
- gp_zbee_prefs = prefs_register_protocol(proto_zbee_nwk_gp, NULL);\r
- }\r
-\r
- zbee_gp_sec_key_table_uat = uat_new("ZigBee GP Security Keys", sizeof(uat_key_record_t), "zigbee_gp_keys", TRUE,\r
- (void **)&gp_uat_key_records, &num_uat_key_records, UAT_AFFECTS_DISSECTION, NULL, uat_key_record_copy_cb,\r
- uat_key_record_update_cb, uat_key_record_free_cb, NULL, key_uat_fields);\r
-\r
- prefs_register_uat_preference(gp_zbee_prefs, "gp_key_table", "Pre-configured GP Security Keys",\r
- "Pre-configured GP Security Keys.", zbee_gp_sec_key_table_uat);\r
-\r
- register_init_routine(gp_init_zbee_security);\r
-\r
- /* Register the Wireshark protocol. */\r
- proto_register_field_array(proto_zbee_nwk_gp, hf, array_length(hf));\r
- proto_register_subtree_array(ett, array_length(ett));\r
-\r
- /* Register the dissectors. */\r
- new_register_dissector(ZBEE_PROTOABBREV_NWK_GP, dissect_zbee_nwk_gp, proto_zbee_nwk_gp);\r
-} /* proto_register_zbee_nwk_gp */\r
-\r
-/*FUNCTION:------------------------------------------------------\r
- * NAME\r
- * proto_reg_handoff_zbee_nwk_gp\r
- * DESCRIPTION\r
- * Registers the ZigBee dissector with Wireshark.\r
- * PARAMETERS\r
- * none\r
- * RETURNS\r
- * void\r
- *---------------------------------------------------------------\r
- */\r
-void\r
-proto_reg_handoff_zbee_nwk_gp(void)\r
-{\r
- /* Find the other dissectors we need. */\r
- data_handle = find_dissector("data");\r
- /* Register our dissector with IEEE 802.15.4. */\r
- heur_dissector_add(IEEE802154_PROTOABBREV_WPAN, dissect_zbee_nwk_heur_gp, proto_zbee_nwk_gp);\r
-} /* proto_reg_handoff_zbee */\r
+/* packet-zbee-nwk-gp.c
+ * Dissector routines for the ZigBee Green Power profile (GP)
+ * Copyright 2013 DSR Corporation, http://dsr-wireless.com/
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * Used Owen Kirby's packet-zbee-aps module as a template. Based
+ * on ZigBee Cluster Library Specification document 075123r02ZB
+ *
+ * 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.
+ */
+
+/* Include files. */
+#include "config.h"
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/exceptions.h>
+#include <epan/prefs.h>
+#include <epan/addr_resolv.h>
+#include <epan/expert.h>
+#include <epan/uat.h>
+#include "packet-ieee802154.h"
+#include "packet-zbee.h"
+#include "packet-zbee-nwk.h"
+#include "packet-zbee-security.h"
+#include "packet-zbee-aps.h"
+#include "packet-zbee-zcl.h"
+#include <wsutil/wsgcrypt.h>
+
+/**************************/
+/* Defines. */
+/**************************/
+
+/* ZigBee NWK GP FCF frame types. */
+#define ZBEE_NWK_GP_FCF_DATA 0x00
+#define ZBEE_NWK_GP_FCF_MAINTENANCE 0x01
+
+/* ZigBee NWK GP FCF fields. */
+#define ZBEE_NWK_GP_FCF_AUTO_COMMISSIONING 0x40
+#define ZBEE_NWK_GP_FCF_CONTROL_EXTENSION 0x80
+#define ZBEE_NWK_GP_FCF_FRAME_TYPE 0x03
+#define ZBEE_NWK_GP_FCF_VERSION 0x3C
+
+/* Extended NWK Frame Control field. */
+#define ZBEE_NWK_GP_FCF_EXT_APP_ID 0x07 /* 0 - 2 b. */
+#define ZBEE_NWK_GP_FCF_EXT_SECURITY_LEVEL 0x18 /* 3 - 4 b. */
+#define ZBEE_NWK_GP_FCF_EXT_SECURITY_KEY 0x20 /* 5 b. */
+#define ZBEE_NWK_GP_FCF_EXT_RX_AFTER_TX 0x40 /* 6 b. */
+#define ZBEE_NWK_GP_FCF_EXT_DIRECTION 0x80 /* 7 b. */
+
+/* Definitions for application IDs. */
+#define ZBEE_NWK_GP_APP_ID_DEFAULT 0x00
+#define ZBEE_NWK_GP_APP_ID_LPED 0x01
+#define ZBEE_NWK_GP_APP_ID_ZGP 0x02
+
+/* Definitions for GP directions. */
+#define ZBEE_NWK_GP_FC_EXT_DIRECTION_DEFAULT 0x00
+#define ZBEE_NWK_GP_FC_EXT_DIRECTION_FROM_ZGPD 0x00
+#define ZBEE_NWK_GP_FC_EXT_DIRECTION_FROM_ZGPP 0x01
+
+/* Definitions for ZGPD Source IDs. */
+#define ZBEE_NWK_GP_ZGPD_SRCID_ALL 0xFFFFFFFF
+#define ZBEE_NWK_GP_ZGPD_SRCID_UNKNOWN 0x00000000
+
+/* Security level values. */
+#define ZBEE_NWK_GP_SECURITY_LEVEL_NO 0x00
+#define ZBEE_NWK_GP_SECURITY_LEVEL_1LSB 0x01
+#define ZBEE_NWK_GP_SECURITY_LEVEL_FULL 0x02
+#define ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR 0x03
+
+/* GP Security key types. */
+#define ZBEE_NWK_GP_SECURITY_KEY_TYPE_NO_KEY 0x00
+#define ZBEE_NWK_GP_SECURITY_KEY_TYPE_ZB_NWK_KEY 0x01
+#define ZBEE_NWK_GP_SECURITY_KEY_TYPE_GPD_GROUP_KEY 0x02
+#define ZBEE_NWK_GP_SECURITY_KEY_TYPE_NWK_KEY_DERIVED_GPD_KEY_GROUP_KEY 0x03
+#define ZBEE_NWK_GP_SECURITY_KEY_TYPE_PRECONFIGURED_INDIVIDUAL_GPD_KEY 0x04
+#define ZBEE_NWK_GP_SECURITY_KEY_TYPE_DERIVED_INDIVIDUAL_GPD_KEY 0x07
+
+typedef struct {
+ /* FCF Data. */
+ guint8 frame_type;
+ gboolean nwk_frame_control_extension;
+
+ /* Ext FCF Data. */
+ guint8 application_id;
+ guint8 security_level;
+ guint8 direction;
+
+ /* Src ID. */
+ guint32 source_id;
+
+ /* Security Frame Counter. */
+ guint32 security_frame_counter;
+
+ /* MIC. */
+ guint8 mic_size;
+ guint32 mic;
+
+ /* Application Payload. */
+ guint8 payload_len;
+} zbee_nwk_green_power_packet;
+
+/* Commissioning command payload. */
+guint8 nwk_cmd_security_key[16];
+
+/* Definitions for GP Commissioning command opt field (bitmask). */
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_MAC_SEQ 0x01
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_RX_ON_CAP 0x02
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_MANUFACTURER_INFO 0x04
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_PAN_ID_REQ 0x10
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_GP_SEC_KEY_REQ 0x20
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_FIXED_LOCATION 0x40
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_EXT_OPTIONS 0x80
+
+/* Definitions for GP Commissioning command ext_opt field (bitmask). */
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_SEC_LEVEL_CAP 0x03
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_KEY_TYPE 0x1C
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_GPD_KEY_PRESENT 0x20
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_GPD_KEY_ENCR 0x40
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_OUT_COUNTER 0x80
+
+/* Definitions for GP Commissioning command MS Extensions field (bitmask). */
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_MIP 0x01
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_MMIP 0x02
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_GCLP 0x04
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_CRP 0x08
+
+/* Definitions for GP Decommissioning command opt field (bitmask). */
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_PAN_ID_PRESENT 0x01
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_SEC_KEY_PRESENT 0x02
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_KEY_ENCR 0x04
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_SEC_LEVEL 0x18
+#define ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_KEY_TYPE 0xE0
+
+/* Definitions for GP Channel Request command. */
+#define ZBEE_NWK_GP_CMD_CHANNEL_REQUEST_1ST 0x0F
+#define ZBEE_NWK_GP_CMD_CHANNEL_REQUEST_2ND 0xF0
+
+/* GP Channel Configuration command. */
+#define ZBEE_NWK_GP_CMD_CHANNEL_CONFIGURATION_OPERATION_CH 0x0F
+
+/* GP GENERIC IDS. */
+#define GPD_DEVICE_ID_GENERIC_GP_SIMPLE_GENERIC_1STATE_SWITCH 0x00
+#define GPD_DEVICE_ID_GENERIC_GP_SIMPLE_GENERIC_2STATE_SWITCH 0x01
+#define GPD_DEVICE_ID_GENERIC_GP_ON_OFF_SWITCH 0x02
+#define GPD_DEVICE_ID_GENERIC_GP_LEVEL_CONTROL_SWITCH 0x03
+#define GPD_DEVICE_ID_GENERIC_GP_SIMPLE_SENSOR 0x04
+#define GPD_DEVICE_ID_GENERIC_GP_ADVANCED_GENERIC_1STATE_SWITCH 0x05
+#define GPD_DEVICE_ID_GENERIC_GP_ADVANCED_GENERIC_2STATE_SWITCH 0x06
+
+/* GP LIGHTING IDS. */
+#define GPD_DEVICE_ID_LIGHTING_GP_COLOR_DIMMER_SWITCH 0x10
+#define GPD_DEVICE_ID_LIGHTING_GP_LIGHT_SENSOR 0x11
+#define GPD_DEVICE_ID_LIGHTING_GP_OCCUPANCY_SENSOR 0x12
+
+/* GP CLOSURES IDS. */
+#define GPD_DEVICE_ID_CLOSURES_GP_DOOR_LOCK_CONTROLLER 0x20
+
+/* HVAC IDS. */
+#define GPD_DEVICE_ID_HVAC_GP_TEMPERATURE_SENSOR 0x30
+#define GPD_DEVICE_ID_HVAC_GP_PRESSURE_SENSOR 0x31
+#define GPD_DEVICE_ID_HVAC_GP_FLOW_SENSOR 0x32
+#define GPD_DEVICE_ID_HVAC_GP_INDOOR_ENVIRONMENT_SENSOR 0x33
+
+/* Manufacturer specific device. */
+#define GPD_DEVICE_ID_MANUFACTURER_SPECIFIC 0xFE
+
+/* Payloadless GPDF commands sent by GPD. */
+#define ZB_GP_CMD_ID_IDENTIFY 0x00
+#define ZB_GP_CMD_ID_SCENE0 0x10
+#define ZB_GP_CMD_ID_SCENE1 0x11
+#define ZB_GP_CMD_ID_SCENE2 0x12
+#define ZB_GP_CMD_ID_SCENE3 0x13
+#define ZB_GP_CMD_ID_SCENE4 0x14
+#define ZB_GP_CMD_ID_SCENE5 0x15
+#define ZB_GP_CMD_ID_SCENE6 0x16
+#define ZB_GP_CMD_ID_SCENE7 0x17
+#define ZB_GP_CMD_ID_SCENE8 0x18
+#define ZB_GP_CMD_ID_SCENE9 0x19
+#define ZB_GP_CMD_ID_SCENE10 0x1A
+#define ZB_GP_CMD_ID_SCENE11 0x1B
+#define ZB_GP_CMD_ID_SCENE12 0x1C
+#define ZB_GP_CMD_ID_SCENE13 0x1D
+#define ZB_GP_CMD_ID_SCENE14 0x1E
+#define ZB_GP_CMD_ID_SCENE15 0x1F
+#define ZB_GP_CMD_ID_OFF 0x20
+#define ZB_GP_CMD_ID_ON 0x21
+#define ZB_GP_CMD_ID_TOGGLE 0x22
+#define ZB_GP_CMD_ID_RELEASE 0x23
+#define ZB_GP_CMD_ID_LEVEL_CONTROL_STOP 0x34
+#define ZB_GP_CMD_ID_MOVE_HUE_STOP 0x40
+#define ZB_GP_CMD_ID_MOVE_SATURATION_STOP 0x45
+#define ZB_GP_CMD_ID_LOCK_DOOR 0x50
+#define ZB_GP_CMD_ID_UNLOCK_DOOR 0x51
+#define ZB_GP_CMD_ID_PRESS11 0x60
+#define ZB_GP_CMD_ID_RELEASE11 0x61
+#define ZB_GP_CMD_ID_PRESS12 0x62
+#define ZB_GP_CMD_ID_RELEASE12 0x63
+#define ZB_GP_CMD_ID_PRESS22 0x64
+#define ZB_GP_CMD_ID_RELEASE22 0x65
+#define ZB_GP_CMD_ID_SHORT_PRESS11 0x66
+#define ZB_GP_CMD_ID_SHORT_PRESS12 0x67
+#define ZB_GP_CMD_ID_SHORT_PRESS22 0x68
+#define ZB_GP_CMD_ID_DECOMMISSIONING 0xE1
+#define ZB_GP_CMD_ID_SUCCESS 0xE2
+
+/* GPDF commands with payload sent by GPD. */
+#define ZB_GP_CMD_ID_MOVE_UP 0x30
+#define ZB_GP_CMD_ID_MOVE_DOWN 0x31
+#define ZB_GP_CMD_ID_STEP_UP 0x32
+#define ZB_GP_CMD_ID_STEP_DOWN 0x33
+#define ZB_GP_CMD_ID_MOVE_UP_WITH_ON_OFF 0x35
+#define ZB_GP_CMD_ID_MOVE_DOWN_WITH_ON_OFF 0x36
+#define ZB_GP_CMD_ID_STEP_UP_WITH_ON_OFF 0x37
+#define ZB_GP_CMD_ID_STEP_DOWN_WITH_ON_OFF 0x38
+#define ZB_GP_CMD_ID_MOVE_HUE_UP 0x41
+#define ZB_GP_CMD_ID_MOVE_HUE_DOWN 0x42
+#define ZB_GP_CMD_ID_STEP_HUE_UP 0x43
+#define ZB_GP_CMD_ID_STEP_HUW_DOWN 0x44
+#define ZB_GP_CMD_ID_MOVE_SATUREATION_UP 0x46
+#define ZB_GP_CMD_ID_MOVE_SATUREATION_DOWN 0x47
+#define ZB_GP_CMD_ID_STEP_SATURATION_UP 0x48
+#define ZB_GP_CMD_ID_STEP_SATURATION_DOWN 0x49
+#define ZB_GP_CMD_ID_MOVE_COLOR 0x4A
+#define ZB_GP_CMD_ID_STEP_COLOR 0x4B
+#define ZB_GP_CMD_ID_ATTRIBUTE_REPORTING 0xA0
+#define ZB_GP_CMD_ID_MANUFACTURE_SPECIFIC_ATTR_REPORTING 0xA1
+#define ZB_GP_CMD_ID_MULTI_CLUSTER_REPORTING 0xA2
+#define ZB_GP_CMD_ID_MANUFACTURER_SPECIFIC_MCLUSTER_REPORTING 0xA3
+#define ZB_GP_CMD_ID_REQUEST_ATTRIBUTES 0xA4
+#define ZB_GP_CMD_ID_READ_ATTRIBUTES_RESPONSE 0xA5
+#define ZB_GP_CMD_ID_ANY_SENSOR_COMMAND_A0_A3 0xAF
+#define ZB_GP_CMD_ID_COMMISSIONING 0xE0
+#define ZB_GP_CMD_ID_CHANNEL_REQUEST 0xE3
+
+/* GPDF commands sent to GPD. */
+#define ZB_GP_CMD_ID_COMMISSIONING_REPLY 0xF0
+#define ZB_GP_CMD_ID_WRITE_ATTRIBUTES 0xF1
+#define ZB_GP_CMD_ID_READ_ATTRIBUTES 0xF2
+#define ZB_GP_CMD_ID_CHANNEL_CONFIGURATION 0xF3
+
+/* GPD manufacturers. */
+#define ZBEE_NWK_GP_MANUF_ID_GREENPEAK 0x10D0
+
+/* GPD devices by GreenPeak. */
+#define ZBEE_NWK_GP_MANUF_GREENPEAK_IZDS 0x0000
+#define ZBEE_NWK_GP_MANUF_GREENPEAK_IZDWS 0x0001
+#define ZBEE_NWK_GP_MANUF_GREENPEAK_IZLS 0x0002
+#define ZBEE_NWK_GP_MANUF_GREENPEAK_IZRHS 0x0003
+
+/*********************/
+/* Extern Constants. */
+/*********************/
+
+extern const value_string zbee_aps_cid_names[];
+
+/*********************/
+/* Global variables. */
+/*********************/
+
+/* GP proto handle. */
+static int proto_zbee_nwk_gp = -1;
+
+/* GP NWK FC. */
+static int hf_zbee_nwk_gp_auto_commissioning = -1;
+static int hf_zbee_nwk_gp_fc_ext = -1;
+static int hf_zbee_nwk_gp_frame_type = -1;
+static int hf_zbee_nwk_gp_proto_version = -1;
+
+/* GP NWK FC extension. */
+static int hf_zbee_nwk_gp_fc_ext_app_id = -1;
+static int hf_zbee_nwk_gp_fc_ext_direction = -1;
+static int hf_zbee_nwk_gp_fc_ext_rx_after_tx = -1;
+static int hf_zbee_nwk_gp_fc_ext_sec_key = -1;
+static int hf_zbee_nwk_gp_fc_ext_sec_level = -1;
+
+/* ZGPD Src ID. */
+static int hf_zbee_nwk_gp_zgpd_src_id = -1;
+
+/* Security frame counter. */
+static int hf_zbee_nwk_gp_security_frame_counter = -1;
+
+/* Security MIC. */
+static int hf_zbee_nwk_gp_security_mic_2b = -1;
+static int hf_zbee_nwk_gp_security_mic_4b = -1;
+
+/* Payload subframe. */
+static int hf_zbee_nwk_gp_command_id = -1;
+
+/* Commissioning. */
+static int hf_zbee_nwk_gp_cmd_comm_device_id = -1;
+static int hf_zbee_nwk_gp_cmd_comm_ext_opt_gpd_key_encr = -1;
+static int hf_zbee_nwk_gp_cmd_comm_ext_opt_gpd_key_present = -1;
+static int hf_zbee_nwk_gp_cmd_comm_ext_opt_key_type = -1;
+static int hf_zbee_nwk_gp_cmd_comm_ext_opt_outgoing_counter = -1;
+static int hf_zbee_nwk_gp_cmd_comm_ext_opt_sec_level_cap = -1;
+static int hf_zbee_nwk_gp_cmd_comm_gpd_sec_key_mic = -1;
+static int hf_zbee_nwk_gp_cmd_comm_opt_ext_opt = -1;
+static int hf_zbee_nwk_gp_cmd_comm_opt_fixed_location = -1;
+static int hf_zbee_nwk_gp_cmd_comm_opt_mac_sec_num_cap = -1;
+static int hf_zbee_nwk_gp_cmd_comm_opt_ms_ext_present = -1;
+static int hf_zbee_nwk_gp_cmd_comm_opt_panid_req = -1;
+static int hf_zbee_nwk_gp_cmd_comm_opt_rx_on_cap = -1;
+static int hf_zbee_nwk_gp_cmd_comm_opt_sec_key_req = -1;
+static int hf_zbee_nwk_gp_cmd_comm_outgoing_counter = -1;
+static int hf_zbee_nwk_gp_cmd_comm_manufacturer_greenpeak_dev_id = -1;
+static int hf_zbee_nwk_gp_cmd_comm_manufacturer_id = -1;
+static int hf_zbee_nwk_gp_cmd_comm_ms_ext_crp = -1;
+static int hf_zbee_nwk_gp_cmd_comm_ms_ext_gclp = -1;
+static int hf_zbee_nwk_gp_cmd_comm_ms_ext_mip = -1;
+static int hf_zbee_nwk_gp_cmd_comm_ms_ext_mmip = -1;
+
+/* Commissioning reply. */
+static int hf_zbee_nwk_gp_cmd_comm_rep_opt_key_encr = -1;
+static int hf_zbee_nwk_gp_cmd_comm_rep_opt_panid_present = -1;
+static int hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_key_present = -1;
+static int hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_level = -1;
+static int hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_type = -1;
+static int hf_zbee_nwk_gp_cmd_comm_rep_pan_id = -1;
+
+/* Attribute reporting. */
+static int hf_zbee_nwk_gp_cmd_attr_report_cluster_id = -1;
+
+/* Channel request. */
+static int hf_zbee_nwk_gp_cmd_channel_request_toggling_behaviour_1st = -1;
+static int hf_zbee_nwk_gp_cmd_channel_request_toggling_behaviour_2nd = -1;
+
+/* Channel Configuration command. */
+static int hf_zbee_nwk_gp_cmd_channel_configuration = -1;
+
+/* Move Color command. */
+static int hf_zbee_nwk_gp_cmd_move_color_ratex = -1;
+static int hf_zbee_nwk_gp_cmd_move_color_ratey = -1;
+
+/* Move Up/Down command. */
+static int hf_zbee_nwk_gp_cmd_move_up_down_rate = -1;
+
+/* Step Color command. */
+static int hf_zbee_nwk_gp_cmd_step_color_stepx = -1;
+static int hf_zbee_nwk_gp_cmd_step_color_stepy = -1;
+static int hf_zbee_nwk_gp_cmd_step_color_transition_time = -1;
+
+/* Step Up/Down command. */
+static int hf_zbee_nwk_gp_cmd_step_up_down_step_size = -1;
+static int hf_zbee_nwk_gp_cmd_step_up_down_transition_time = -1;
+
+/* Proto tree elements. */
+static gint ett_zbee_nwk = -1;
+static gint ett_zbee_nwk_cmd = -1;
+static gint ett_zbee_nwk_cmd_cinfo = -1;
+static gint ett_zbee_nwk_cmd_ms_ext = -1;
+static gint ett_zbee_nwk_cmd_options = -1;
+static gint ett_zbee_nwk_fcf = -1;
+static gint ett_zbee_nwk_fcf_ext = -1;
+
+/* Common. */
+static dissector_handle_t data_handle;
+static GSList *zbee_gp_keyring = NULL;
+static guint num_uat_key_records = 0;
+
+typedef struct {
+ gchar *string;
+ guint8 byte_order;
+ gchar *label;
+ guint8 key[ZBEE_SEC_CONST_KEYSIZE];
+} uat_key_record_t;
+
+static uat_key_record_t *gp_uat_key_records = NULL;
+static uat_t *zbee_gp_sec_key_table_uat;
+
+/* UAT. */
+UAT_CSTRING_CB_DEF(gp_uat_key_records, string, uat_key_record_t)
+UAT_VS_DEF(gp_uat_key_records, byte_order, uat_key_record_t, guint8, 0, "Normal")
+UAT_CSTRING_CB_DEF(gp_uat_key_records, label, uat_key_record_t)
+
+/****************/
+/* Field names. */
+/****************/
+
+/* Byte order. */
+static const value_string byte_order_vals[] = {
+ { 0, "Normal"},
+ { 1, "Reverse"},
+
+ { 0, NULL }
+};
+
+/* Application ID names. */
+static const value_string zbee_nwk_gp_app_id_names[] = {
+ { ZBEE_NWK_GP_APP_ID_LPED, "LPED" },
+ { ZBEE_NWK_GP_APP_ID_ZGP, "ZGP" },
+
+ { 0, NULL }
+};
+
+/* Green Power commands. */
+static const value_string zbee_nwk_gp_cmd_names[] = {
+ { ZB_GP_CMD_ID_ANY_SENSOR_COMMAND_A0_A3, "Any GPD sensor command (0xA0 - 0xA3)" },
+ { ZB_GP_CMD_ID_ATTRIBUTE_REPORTING, "Attribute reporting" },
+ { ZB_GP_CMD_ID_CHANNEL_CONFIGURATION, "Channel Configuration" },
+ { ZB_GP_CMD_ID_CHANNEL_REQUEST, "Channel Request" },
+ { ZB_GP_CMD_ID_COMMISSIONING, "Commissioning" },
+ { ZB_GP_CMD_ID_COMMISSIONING_REPLY, "Commissioning Reply" },
+ { ZB_GP_CMD_ID_DECOMMISSIONING, "Decommissioning" },
+ { ZB_GP_CMD_ID_IDENTIFY, "Identify" },
+ { ZB_GP_CMD_ID_LEVEL_CONTROL_STOP, "Level Control/Stop" },
+ { ZB_GP_CMD_ID_LOCK_DOOR, "Lock Door" },
+ { ZB_GP_CMD_ID_MANUFACTURER_SPECIFIC_MCLUSTER_REPORTING, "Manufacturer-specific multi-cluster reporting" },
+ { ZB_GP_CMD_ID_MANUFACTURE_SPECIFIC_ATTR_REPORTING, "Manufacturer-specific attribute reporting" },
+ { ZB_GP_CMD_ID_MOVE_COLOR, "Move Color" },
+ { ZB_GP_CMD_ID_MOVE_DOWN, "Move Down" },
+ { ZB_GP_CMD_ID_MOVE_DOWN_WITH_ON_OFF, "Move Down (with On/Off)" },
+ { ZB_GP_CMD_ID_MOVE_HUE_DOWN, "Move Hue Down" },
+ { ZB_GP_CMD_ID_MOVE_HUE_STOP, "Move Hue Stop" },
+ { ZB_GP_CMD_ID_MOVE_HUE_UP, "Move Hue Up" },
+ { ZB_GP_CMD_ID_MOVE_SATURATION_STOP, "Move Saturation Stop" },
+ { ZB_GP_CMD_ID_MOVE_SATUREATION_DOWN, "Move Saturation Down" },
+ { ZB_GP_CMD_ID_MOVE_SATUREATION_UP, "Move Saturation Up" },
+ { ZB_GP_CMD_ID_MOVE_UP, "Move Up" },
+ { ZB_GP_CMD_ID_MOVE_UP_WITH_ON_OFF, "Move Up (with On/Off)" },
+ { ZB_GP_CMD_ID_MULTI_CLUSTER_REPORTING, "Multi-cluster reporting" },
+ { ZB_GP_CMD_ID_OFF, "Off" },
+ { ZB_GP_CMD_ID_ON, "On" },
+ { ZB_GP_CMD_ID_PRESS11, "Press 1 of 1" },
+ { ZB_GP_CMD_ID_PRESS12, "Press 1 of 2" },
+ { ZB_GP_CMD_ID_PRESS22, "Press 2 of 2" },
+ { ZB_GP_CMD_ID_READ_ATTRIBUTES, "Read Attributes" },
+ { ZB_GP_CMD_ID_READ_ATTRIBUTES_RESPONSE, "Read Attributes Response" },
+ { ZB_GP_CMD_ID_RELEASE11, "Release 1 of 1" },
+ { ZB_GP_CMD_ID_RELEASE12, "Release 1 of 2" },
+ { ZB_GP_CMD_ID_RELEASE22, "Release 2 of 2" },
+ { ZB_GP_CMD_ID_RELEASE, "Release" },
+ { ZB_GP_CMD_ID_REQUEST_ATTRIBUTES, "Request Attributes" },
+ { ZB_GP_CMD_ID_SCENE0, "Scene 0" },
+ { ZB_GP_CMD_ID_SCENE10, "Scene 10" },
+ { ZB_GP_CMD_ID_SCENE11, "Scene 11" },
+ { ZB_GP_CMD_ID_SCENE12, "Scene 12" },
+ { ZB_GP_CMD_ID_SCENE13, "Scene 13" },
+ { ZB_GP_CMD_ID_SCENE14, "Scene 14" },
+ { ZB_GP_CMD_ID_SCENE15, "Scene 15" },
+ { ZB_GP_CMD_ID_SCENE1, "Scene 1" },
+ { ZB_GP_CMD_ID_SCENE2, "Scene 2" },
+ { ZB_GP_CMD_ID_SCENE3, "Scene 3" },
+ { ZB_GP_CMD_ID_SCENE4, "Scene 4" },
+ { ZB_GP_CMD_ID_SCENE5, "Scene 5" },
+ { ZB_GP_CMD_ID_SCENE6, "Scene 6" },
+ { ZB_GP_CMD_ID_SCENE7, "Scene 7" },
+ { ZB_GP_CMD_ID_SCENE8, "Scene 8" },
+ { ZB_GP_CMD_ID_SCENE9, "Scene 9" },
+ { ZB_GP_CMD_ID_SHORT_PRESS11, "Short press 1 of 1" },
+ { ZB_GP_CMD_ID_SHORT_PRESS12, "Short press 1 of 2" },
+ { ZB_GP_CMD_ID_SHORT_PRESS22, "Short press 2 of 2" },
+ { ZB_GP_CMD_ID_STEP_COLOR, "Step Color" },
+ { ZB_GP_CMD_ID_STEP_DOWN, "Step Down" },
+ { ZB_GP_CMD_ID_STEP_DOWN_WITH_ON_OFF, "Step Down (with On/Off)" },
+ { ZB_GP_CMD_ID_STEP_HUE_UP, "Step Hue Up" },
+ { ZB_GP_CMD_ID_STEP_HUW_DOWN, "Step Hue Down" },
+ { ZB_GP_CMD_ID_STEP_SATURATION_DOWN, "Step Saturation Down" },
+ { ZB_GP_CMD_ID_STEP_SATURATION_UP, "Step Saturation Up" },
+ { ZB_GP_CMD_ID_STEP_UP, "Step Up" },
+ { ZB_GP_CMD_ID_STEP_UP_WITH_ON_OFF, "Step Up (with On/Off)" },
+ { ZB_GP_CMD_ID_SUCCESS, "Success" },
+ { ZB_GP_CMD_ID_TOGGLE, "Toggle" },
+ { ZB_GP_CMD_ID_UNLOCK_DOOR, "Unlock Door" },
+ { ZB_GP_CMD_ID_WRITE_ATTRIBUTES, "Write Attributes" },
+
+ { 0, NULL }
+};
+
+/* Green Power devices. */
+static const value_string zbee_nwk_gp_device_ids_names[] = {
+
+ /* GP GENERIC */
+ { GPD_DEVICE_ID_GENERIC_GP_ADVANCED_GENERIC_1STATE_SWITCH, "Generic: GP Advanced Generic 1-state Switch" },
+ { GPD_DEVICE_ID_GENERIC_GP_ADVANCED_GENERIC_2STATE_SWITCH, "Generic: GP Advanced Generic 2-state Switch" },
+ { GPD_DEVICE_ID_GENERIC_GP_LEVEL_CONTROL_SWITCH, "Generic: GP Level Control Switch" },
+ { GPD_DEVICE_ID_GENERIC_GP_ON_OFF_SWITCH, "Generic: GP On/Off Switch" },
+ { GPD_DEVICE_ID_GENERIC_GP_SIMPLE_GENERIC_1STATE_SWITCH, "Generic: GP Simple Generic 1-state Switch" },
+ { GPD_DEVICE_ID_GENERIC_GP_SIMPLE_GENERIC_2STATE_SWITCH, "Generic: GP Simple Generic 2-state Switch" },
+ { GPD_DEVICE_ID_GENERIC_GP_SIMPLE_SENSOR, "Generic: GP Simple Sensor" },
+
+ /* GP LIGHTING */
+ { GPD_DEVICE_ID_LIGHTING_GP_COLOR_DIMMER_SWITCH, "Lighting: GP Color Dimmer Switch" },
+ { GPD_DEVICE_ID_LIGHTING_GP_LIGHT_SENSOR, "Lighting: GP Light Sensor" },
+ { GPD_DEVICE_ID_LIGHTING_GP_OCCUPANCY_SENSOR, "Lighting: GP Occupancy Sensor" },
+
+ /* GP CLOSURES */
+ { GPD_DEVICE_ID_CLOSURES_GP_DOOR_LOCK_CONTROLLER, "Closures: GP Door Lock Controller" },
+
+ /* HVAC */
+ { GPD_DEVICE_ID_HVAC_GP_FLOW_SENSOR, "HVAC: GP Flow Sensor" },
+ { GPD_DEVICE_ID_HVAC_GP_INDOOR_ENVIRONMENT_SENSOR, "HVAC: GP Indoor Environment Sensor" },
+ { GPD_DEVICE_ID_HVAC_GP_PRESSURE_SENSOR, "HVAC: GP Pressure Sensor" },
+ { GPD_DEVICE_ID_HVAC_GP_TEMPERATURE_SENSOR, "HVAC: GP Temperature Sensor" },
+
+ /* CUSTOM */
+ { GPD_DEVICE_ID_MANUFACTURER_SPECIFIC, "Manufacturer Specific" },
+
+ { 0, NULL }
+};
+
+/* GP directions. */
+static const value_string zbee_nwk_gp_directions[] = {
+ { ZBEE_NWK_GP_FC_EXT_DIRECTION_FROM_ZGPD, "From ZGPD" },
+ { ZBEE_NWK_GP_FC_EXT_DIRECTION_FROM_ZGPP, "From ZGPP" },
+
+ { 0, NULL }
+};
+
+/* Frame types for Green Power profile. */
+static const value_string zbee_nwk_gp_frame_types[] = {
+ { ZBEE_NWK_GP_FCF_DATA, "Data" },
+ { ZBEE_NWK_GP_FCF_MAINTENANCE, "Maintenance" },
+
+ { 0, NULL }
+};
+
+/* GreenPeak Green Power devices. */
+static const value_string zbee_nwk_gp_manufacturer_greenpeak_dev_names[] = {
+ { ZBEE_NWK_GP_MANUF_GREENPEAK_IZDS, "IAS Zone Door Sensor" },
+ { ZBEE_NWK_GP_MANUF_GREENPEAK_IZDWS, "IAS Zone Door/Window Sensor" },
+ { ZBEE_NWK_GP_MANUF_GREENPEAK_IZLS, "IAS Zone Leakage Sensor" },
+ { ZBEE_NWK_GP_MANUF_GREENPEAK_IZRHS, "IAS Zone Relative Humidity Sensor" },
+
+ { 0, NULL }
+};
+
+/* GP manufacturers. */
+static const value_string zbee_nwk_gp_manufacturers_ids_names[] = {
+ { ZBEE_NWK_GP_MANUF_ID_GREENPEAK, "GreenPeak" },
+
+ { 0, NULL }
+};
+
+/* GP Src ID names. */
+static const value_string zbee_nwk_gp_src_id_names[] = {
+ { ZBEE_NWK_GP_ZGPD_SRCID_ALL, "All" },
+ { ZBEE_NWK_GP_ZGPD_SRCID_UNKNOWN, "Unspecified" },
+
+ { 0, NULL }
+};
+
+/* GP security key type names. */
+static const value_string zbee_nwk_gp_src_sec_keys_type_names[] = {
+ { ZBEE_NWK_GP_SECURITY_KEY_TYPE_DERIVED_INDIVIDUAL_GPD_KEY, "Derived individual GPD key" },
+ { ZBEE_NWK_GP_SECURITY_KEY_TYPE_GPD_GROUP_KEY, "GPD group key" },
+ { ZBEE_NWK_GP_SECURITY_KEY_TYPE_NO_KEY, "No key" },
+ { ZBEE_NWK_GP_SECURITY_KEY_TYPE_NWK_KEY_DERIVED_GPD_KEY_GROUP_KEY, "NWK key derived GPD group key" },
+ { ZBEE_NWK_GP_SECURITY_KEY_TYPE_PRECONFIGURED_INDIVIDUAL_GPD_KEY, "Individual, out of the box GPD key" },
+ { ZBEE_NWK_GP_SECURITY_KEY_TYPE_ZB_NWK_KEY, "ZigBee NWK key" },
+
+ { 0, NULL }
+};
+
+/* GP security levels. */
+static const value_string zbee_nwk_gp_src_sec_levels_names[] = {
+ { ZBEE_NWK_GP_SECURITY_LEVEL_1LSB, "1 LSB of frame counter and short MIC only" },
+ { ZBEE_NWK_GP_SECURITY_LEVEL_FULL, "Full frame counter and full MIC only" },
+ { ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR, "Encryption with full frame counter and full MIC" },
+ { ZBEE_NWK_GP_SECURITY_LEVEL_NO, "No security" },
+
+ { 0, NULL }
+};
+
+/*************************/
+/* Function definitions. */
+/*************************/
+
+/* UAT record copy callback. */
+static void *
+uat_key_record_copy_cb(void *n, const void *o, size_t siz _U_)
+{
+ uat_key_record_t *new_key = (uat_key_record_t *)n;
+ const uat_key_record_t *old_key = (uat_key_record_t *)o;
+
+ if (old_key->string) {
+ new_key->string = g_strdup(old_key->string);
+ } else {
+ new_key->string = NULL;
+ }
+ if (old_key->label) {
+ new_key->label = g_strdup(old_key->label);
+ } else {
+ new_key->label = NULL;
+ }
+ return new_key;
+}
+
+/* UAT record free callback. */
+static void
+uat_key_record_free_cb(void *r)
+{
+ uat_key_record_t *key = (uat_key_record_t *)r;
+ if (key->string) {
+ g_free(key->string);
+ }
+ if (key->label) {
+ g_free(key->label);
+ }
+}
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * zbee_gp_security_parse_key
+ * DESCRIPTION
+ * Parses a key string from left to right into a buffer with increasing (normal byte order) or decreasing (reverse
+ * byte order) address.
+ * PARAMETERS
+ * const gchar *key_str - pointer to the string
+ * guint8 *key_buf - destination buffer in memory
+ * gboolean byte_order - byte order
+ * RETURNS
+ * gboolean
+ *---------------------------------------------------------------
+ */
+static gboolean
+zbee_gp_security_parse_key(const gchar *key_str, guint8 *key_buf, gboolean byte_order)
+{
+ gboolean string_mode = FALSE;
+ gchar temp;
+ int i, j;
+
+ memset(key_buf, 0, ZBEE_SEC_CONST_KEYSIZE);
+ if (key_str == NULL) {
+ return FALSE;
+ }
+ if ((temp = *key_str++) == '"') {
+ string_mode = TRUE;
+ temp = *key_str++;
+ }
+ j = byte_order ? ZBEE_SEC_CONST_KEYSIZE - 1 : 0;
+ for (i = ZBEE_SEC_CONST_KEYSIZE - 1; i >= 0; i--) {
+ if (string_mode) {
+ if (g_ascii_isprint(temp)) {
+ key_buf[j] = temp;
+ temp = *key_str++;
+ } else {
+ return FALSE;
+ }
+ } else {
+ if ((temp == ':') || (temp == '-') || (temp == ' ')) {
+ temp = *(key_str++);
+ }
+ if (g_ascii_isxdigit(temp)) {
+ key_buf[j] = g_ascii_xdigit_value(temp) << 4;
+ } else {
+ return FALSE;
+ }
+ temp = *(key_str++);
+ if (g_ascii_isxdigit(temp)) {
+ key_buf[j] |= g_ascii_xdigit_value(temp);
+ } else {
+ return FALSE;
+ }
+ temp = *(key_str++);
+ }
+ if (byte_order) {
+ j--;
+ } else {
+ j++;
+ }
+ }
+ return TRUE;
+}
+
+/* UAT record update callback. */
+static void
+uat_key_record_update_cb(void *r, const char **err)
+{
+ uat_key_record_t *rec = (uat_key_record_t *)r;
+
+ if (rec->string == NULL) {
+ *err = g_strdup_printf("Key can't be blank.");
+ } else {
+ g_strstrip(rec->string);
+ if (rec->string[0] != 0) {
+ *err = NULL;
+ if (!zbee_gp_security_parse_key(rec->string, rec->key, rec->byte_order)) {
+ *err = g_strdup_printf("Expecting %d hexadecimal bytes or a %d character double-quoted string",
+ ZBEE_SEC_CONST_KEYSIZE, ZBEE_SEC_CONST_KEYSIZE);
+ }
+ } else {
+ *err = g_strdup_printf("Key can't be blank.");
+ }
+ }
+}
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_zbee_nwk_gp_cmd_commissioning
+ * DESCRIPTION
+ * Dissector for ZigBee Green Power commissioning.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_into *pinfo - pointer to packet information fields.
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * zbee_nwk_green_power_packet *packet - packet data.
+ * guint offset - current payload offset.
+ * RETURNS
+ * guint - payload processed offset.
+ *---------------------------------------------------------------
+ */
+static guint
+dissect_zbee_nwk_gp_cmd_commissioning(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ zbee_nwk_green_power_packet *packet _U_, guint offset)
+{
+ guint8 comm_options = 0;
+ guint8 comm_ext_options = 0;
+ guint8 ms_ext_options = 0;
+ guint16 manufacturer_id = 0;
+ proto_item *ti = NULL;
+ proto_tree *field_tree = NULL;
+
+ /* Get Device ID and display it. */
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_device_id, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ /* Get Options Field, build subtree and display the results. */
+ comm_options = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, 1, "Options Field: 0x%02x", comm_options);
+ field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_mac_sec_num_cap, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_rx_on_cap, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_ms_ext_present, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_panid_req, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_sec_key_req, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_fixed_location, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_opt_ext_opt, tvb, offset, 1, ENC_NA);
+ }
+ offset += 1;
+ if (comm_options & ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_EXT_OPTIONS) {
+ /* Get extended Options Field, build subtree and display the results. */
+ comm_ext_options = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, 1, "Extended Options Field: 0x%02x", comm_ext_options);
+ field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ext_opt_sec_level_cap, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ext_opt_key_type, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ext_opt_gpd_key_present, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ext_opt_gpd_key_encr, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ext_opt_outgoing_counter, tvb, offset, 1, ENC_NA);
+ }
+ offset += 1;
+ if (comm_ext_options & ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_GPD_KEY_PRESENT) {
+ /* Get security key and display it. */
+ proto_tree_add_text(tree, tvb, offset, sizeof(nwk_cmd_security_key), "Security Key: %s",
+ tvb_get_string(wmem_packet_scope(), tvb, offset, sizeof(nwk_cmd_security_key)));
+ offset += sizeof(nwk_cmd_security_key);
+ }
+ if (comm_ext_options & ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_GPD_KEY_ENCR) {
+ /* Get Security MIC and display it. */
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_gpd_sec_key_mic, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+ }
+ if (comm_ext_options & ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_OUT_COUNTER) {
+ /* Get GPD Outgoing Frame Counter and display it. */
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_outgoing_counter, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+ }
+ }
+ /* Display manufacturer specific data. */
+ if (comm_options & ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_MANUFACTURER_INFO) {
+ /* Display MS extensions. */
+ ms_ext_options = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, 1, "MS Extensions Field: 0x%02x", ms_ext_options);
+ field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_ms_ext);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ms_ext_mip, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ms_ext_mmip, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ms_ext_gclp, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_ms_ext_crp, tvb, offset, 1, ENC_NA);
+ }
+ offset += 1;
+ if (ms_ext_options & ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_MIP) {
+ /* Get Manufacturer ID. */
+ manufacturer_id = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_manufacturer_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ }
+ if (ms_ext_options & ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_MMIP) {
+ /* Get Manufacturer Device ID. */
+ switch (manufacturer_id) {
+ case ZBEE_NWK_GP_MANUF_ID_GREENPEAK:
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_manufacturer_greenpeak_dev_id, tvb, offset, 2,
+ ENC_LITTLE_ENDIAN);
+ offset += 2;
+ break;
+ }
+ }
+ }
+ return offset;
+} /* dissect_zbee_nwk_gp_cmd_commissioning */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_zbee_nwk_gp_cmd_channel_request
+ * DESCRIPTION
+ * Dissector for ZigBee Green Power channel request.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_into *pinfo - pointer to packet information fields.
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * zbee_nwk_green_power_packet *packet - packet data.
+ * guint offset - current payload offset.
+ * RETURNS
+ * guint - payload processed offset.
+ *---------------------------------------------------------------
+ */
+static guint
+dissect_zbee_nwk_gp_cmd_channel_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ zbee_nwk_green_power_packet *packet _U_, guint offset)
+{
+ proto_item *ti;
+ proto_tree *field_tree;
+
+ /* Get Command Options Field, build subtree and display the results. */
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, 1, "Channel Toggling Behaviour: 0x%02x", tvb_get_guint8(tvb,
+ offset));
+ field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_channel_request_toggling_behaviour_1st, tvb, offset, 1,
+ ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_channel_request_toggling_behaviour_2nd, tvb, offset, 1,
+ ENC_NA);
+ }
+ offset += 1;
+ return offset;
+} /* dissect_zbee_nwk_gp_cmd_channel_request */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_zbee_nwk_gp_cmd_channel_configuration
+ * DESCRIPTION
+ * Dissector for ZigBee Green Power channel configuration.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_into *pinfo - pointer to packet information fields.
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * zbee_nwk_green_power_packet *packet - packet data.
+ * guint offset - current payload offset.
+ * RETURNS
+ * guint - payload processed offset.
+ *---------------------------------------------------------------
+ */
+static guint
+dissect_zbee_nwk_gp_cmd_channel_configuration(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ zbee_nwk_green_power_packet *packet _U_, guint offset)
+{
+ proto_item *ti;
+ proto_tree *field_tree;
+
+ /* Get Command Options Field, build subtree and display the results. */
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, 1, "Operational Channel: 0x%02x", tvb_get_guint8(tvb, offset));
+ field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_channel_configuration, tvb, offset, 1, ENC_NA);
+ }
+ offset += 1;
+ return offset;
+} /* dissect_zbee_nwk_gp_cmd_channel_configuration */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_zbee_nwk_gp_cmd_attr_reporting
+ * DESCRIPTION
+ * Dissector for ZigBee Green Power commands attrib reporting.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_into *pinfo - pointer to packet information fields.
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * zbee_nwk_green_power_packet *packet - packet data.
+ * guint offset - current payload offset.
+ * RETURNS
+ * guint - payload processed offset.
+ *---------------------------------------------------------------
+ */
+static guint
+dissect_zbee_nwk_gp_cmd_attr_reporting(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ zbee_nwk_green_power_packet *packet _U_, guint offset)
+{
+ guint16 cluster_id;
+ proto_item *ti;
+ proto_tree *field_tree;
+
+ /* Get cluster ID and add it into the tree. */
+ cluster_id = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_attr_report_cluster_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+
+ offset += 2;
+ /* Create subtree and parse ZCL Write Attribute Payload. */
+ ti = proto_tree_add_text(tree, tvb, offset, 2, "Attribute reporting command for cluster: 0x%02X", cluster_id);
+ field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);
+ dissect_zcl_write_attr(tvb, pinfo, field_tree, &offset, cluster_id);
+
+ return offset;
+} /* dissect_zbee_nwk_gp_cmd_attr_reporting */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_zbee_nwk_gp_cmd_commissioning_reply
+ * DESCRIPTION
+ * Dissector for ZigBee Green Power comissioning reply.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_into *pinfo - pointer to packet information fields.
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * zbee_nwk_green_power_packet *packet - packet data.
+ * guint offset - current payload offset.
+ * RETURNS
+ * guint - payload processed offset.
+ *---------------------------------------------------------------
+ */
+static guint
+dissect_zbee_nwk_gp_cmd_commissioning_reply(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ zbee_nwk_green_power_packet *packet _U_, guint offset)
+{
+ guint8 cr_options = 0;
+ proto_item *ti = NULL;
+ proto_tree *field_tree = NULL;
+
+ /* Get Options Field, build subtree and display the results. */
+ cr_options = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, 1, "Options Field: 0x%02x", cr_options);
+ field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_cmd_options);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_rep_opt_panid_present, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_key_present, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_rep_opt_key_encr, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_level, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_type, tvb, offset, 1, ENC_NA);
+ }
+ offset += 1;
+ /* Parse and display security Pan ID value. */
+ if (cr_options & ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_PAN_ID_PRESENT) {
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_rep_pan_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ }
+ /* Parse and display security key. */
+ if (cr_options & ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_SEC_KEY_PRESENT) {
+ proto_tree_add_text(tree, tvb, offset, sizeof(nwk_cmd_security_key), "Security Key: %s",
+ tvb_get_string(wmem_packet_scope(), tvb, offset, sizeof(nwk_cmd_security_key)));
+ offset += sizeof(nwk_cmd_security_key);
+ }
+ /* Parse and display security MIC. */
+ if ((cr_options & ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_KEY_ENCR) && (cr_options &
+ ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_SEC_KEY_PRESENT)) {
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_comm_gpd_sec_key_mic, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+ }
+ return offset;
+} /* dissect_zbee_nwk_gp_cmd_commissioning_reply */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_zbee_nwk_gp_cmd_move_color
+ * DESCRIPTION
+ * Dissector for ZigBee Green Power Move Color.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_into *pinfo - pointer to packet information fields.
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * zbee_nwk_green_power_packet *packet - packet data.
+ * guint offset - current payload offset.
+ * RETURNS
+ * guint - payload processed offset.
+ *---------------------------------------------------------------
+ */
+static guint
+dissect_zbee_nwk_gp_cmd_move_color(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ zbee_nwk_green_power_packet *packet _U_, guint offset)
+{
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_move_color_ratex, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_move_color_ratey, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ return offset;
+} /* dissect_zbee_nwk_gp_cmd_move_color */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_zbee_nwk_gp_cmd_move_up_down
+ * DESCRIPTION
+ * Dissector for ZigBee Green Power Move Up/Down.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_into *pinfo - pointer to packet information fields.
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * zbee_nwk_green_power_packet *packet - packet data.
+ * guint offset - current payload offset.
+ * RETURNS
+ * guint - payload processed offset.
+ *---------------------------------------------------------------
+ */
+static guint
+dissect_zbee_nwk_gp_cmd_move_up_down(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ zbee_nwk_green_power_packet *packet _U_, guint offset)
+{
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_move_up_down_rate, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ return offset;
+} /* dissect_zbee_nwk_gp_cmd_move_up_down */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_zbee_nwk_gp_cmd_step_color
+ * DESCRIPTION
+ * Dissector for ZigBee Green Power Step Color.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_into *pinfo - pointer to packet information fields.
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * zbee_nwk_green_power_packet *packet - packet data.
+ * guint offset - current payload offset.
+ * RETURNS
+ * guint - payload processed offset.
+ *---------------------------------------------------------------
+ */
+static guint
+dissect_zbee_nwk_gp_cmd_step_color(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ zbee_nwk_green_power_packet *packet _U_, guint offset)
+{
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_step_color_stepx, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_step_color_stepy, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ /* Optional time field. */
+ if (tvb_reported_length(tvb) - offset >= 2) {
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_step_color_transition_time, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ }
+ return offset;
+} /* dissect_zbee_nwk_gp_cmd_step_color */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_zbee_nwk_gp_cmd_step_up_down
+ * DESCRIPTION
+ * Dissector for ZigBee Green Power Step Up/Down.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_into *pinfo - pointer to packet information fields.
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * zbee_nwk_green_power_packet *packet - packet data.
+ * guint offset - current payload offset.
+ * RETURNS
+ * guint - payload processed offset.
+ *---------------------------------------------------------------
+ */
+static guint
+dissect_zbee_nwk_gp_cmd_step_up_down(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ zbee_nwk_green_power_packet *packet _U_, guint offset)
+{
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_step_up_down_step_size, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(tree, hf_zbee_nwk_gp_cmd_step_up_down_transition_time, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ return offset;
+} /* dissect_zbee_nwk_gp_cmd_step_up_down */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_zbee_nwk_gp_cmd
+ * DESCRIPTION
+ * Dissector for ZigBee Green Power commands.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_into *pinfo - pointer to packet information fields.
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * void *data - raw packet private data.
+ * RETURNS
+ * guint - payload processed offset
+ *---------------------------------------------------------------
+ */
+static guint
+dissect_zbee_nwk_gp_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ guint offset = 0;
+ guint8 cmd_id = tvb_get_guint8(tvb, offset);
+ proto_item *cmd_root = NULL;
+ proto_tree *cmd_tree = NULL;
+ zbee_nwk_green_power_packet *packet = (zbee_nwk_green_power_packet *)data;
+
+ /* Create a subtree for the command. */
+ if (tree) {
+ cmd_root = proto_tree_add_text(tree, tvb, offset, tvb_length(tvb), "Command Frame: %s", val_to_str(cmd_id,
+ zbee_nwk_gp_cmd_names, "Unknown Command Frame"));
+ cmd_tree = proto_item_add_subtree(cmd_root, ett_zbee_nwk_cmd);
+ /* Add the command ID. */
+ proto_tree_add_uint(cmd_tree, hf_zbee_nwk_gp_command_id, tvb, offset, 1, cmd_id);
+ }
+ offset += 1;
+ /* Add the command name to the info column. */
+ col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(cmd_id, zbee_nwk_gp_cmd_names, "Unknown command"));
+ /* Handle the command for one of the following devices:
+ * - Door Lock Controller (IDs: 0x50 - 0x51);
+ * - GP Flow Sensor (IDs: 0xE0, 0xA0 - 0xA3);
+ * - GP Temperature Sensor (IDs: 0xE0, 0xA0 - 0xA3); */
+ switch(cmd_id) {
+ /* Payloadless GPDF commands sent by GPD. */
+ case ZB_GP_CMD_ID_IDENTIFY:
+ case ZB_GP_CMD_ID_SCENE0:
+ case ZB_GP_CMD_ID_SCENE1:
+ case ZB_GP_CMD_ID_SCENE2:
+ case ZB_GP_CMD_ID_SCENE3:
+ case ZB_GP_CMD_ID_SCENE4:
+ case ZB_GP_CMD_ID_SCENE5:
+ case ZB_GP_CMD_ID_SCENE6:
+ case ZB_GP_CMD_ID_SCENE7:
+ case ZB_GP_CMD_ID_SCENE8:
+ case ZB_GP_CMD_ID_SCENE9:
+ case ZB_GP_CMD_ID_SCENE10:
+ case ZB_GP_CMD_ID_SCENE11:
+ case ZB_GP_CMD_ID_SCENE12:
+ case ZB_GP_CMD_ID_SCENE13:
+ case ZB_GP_CMD_ID_SCENE14:
+ case ZB_GP_CMD_ID_SCENE15:
+ case ZB_GP_CMD_ID_OFF:
+ case ZB_GP_CMD_ID_ON:
+ case ZB_GP_CMD_ID_TOGGLE:
+ case ZB_GP_CMD_ID_RELEASE:
+ case ZB_GP_CMD_ID_LEVEL_CONTROL_STOP:
+ case ZB_GP_CMD_ID_MOVE_HUE_STOP:
+ case ZB_GP_CMD_ID_MOVE_SATURATION_STOP:
+ case ZB_GP_CMD_ID_LOCK_DOOR:
+ case ZB_GP_CMD_ID_UNLOCK_DOOR:
+ case ZB_GP_CMD_ID_PRESS11:
+ case ZB_GP_CMD_ID_RELEASE11:
+ case ZB_GP_CMD_ID_PRESS12:
+ case ZB_GP_CMD_ID_RELEASE12:
+ case ZB_GP_CMD_ID_PRESS22:
+ case ZB_GP_CMD_ID_RELEASE22:
+ case ZB_GP_CMD_ID_SHORT_PRESS11:
+ case ZB_GP_CMD_ID_SHORT_PRESS12:
+ case ZB_GP_CMD_ID_SHORT_PRESS22:
+ case ZB_GP_CMD_ID_DECOMMISSIONING:
+ case ZB_GP_CMD_ID_SUCCESS:
+ break;
+ /* GPDF commands with payload sent by GPD. */
+ case ZB_GP_CMD_ID_MOVE_UP:
+ case ZB_GP_CMD_ID_MOVE_DOWN:
+ case ZB_GP_CMD_ID_MOVE_UP_WITH_ON_OFF:
+ case ZB_GP_CMD_ID_MOVE_DOWN_WITH_ON_OFF:
+ case ZB_GP_CMD_ID_MOVE_HUE_UP:
+ case ZB_GP_CMD_ID_MOVE_HUE_DOWN:
+ case ZB_GP_CMD_ID_MOVE_SATUREATION_UP:
+ case ZB_GP_CMD_ID_MOVE_SATUREATION_DOWN:
+ offset = dissect_zbee_nwk_gp_cmd_move_up_down(tvb, pinfo, cmd_tree, packet, offset);
+ break;
+ case ZB_GP_CMD_ID_STEP_UP:
+ case ZB_GP_CMD_ID_STEP_DOWN:
+ case ZB_GP_CMD_ID_STEP_UP_WITH_ON_OFF:
+ case ZB_GP_CMD_ID_STEP_DOWN_WITH_ON_OFF:
+ case ZB_GP_CMD_ID_STEP_HUE_UP:
+ case ZB_GP_CMD_ID_STEP_HUW_DOWN:
+ case ZB_GP_CMD_ID_STEP_SATURATION_UP:
+ case ZB_GP_CMD_ID_STEP_SATURATION_DOWN:
+ offset = dissect_zbee_nwk_gp_cmd_step_up_down(tvb, pinfo, cmd_tree, packet, offset);
+ break;
+ case ZB_GP_CMD_ID_MOVE_COLOR:
+ offset = dissect_zbee_nwk_gp_cmd_move_color(tvb, pinfo, cmd_tree, packet, offset);
+ break;
+ case ZB_GP_CMD_ID_STEP_COLOR:
+ offset = dissect_zbee_nwk_gp_cmd_step_color(tvb, pinfo, cmd_tree, packet, offset);
+ break;
+ case ZB_GP_CMD_ID_ATTRIBUTE_REPORTING:
+ offset = dissect_zbee_nwk_gp_cmd_attr_reporting(tvb, pinfo, cmd_tree, packet, offset);
+ break;
+ case ZB_GP_CMD_ID_MANUFACTURE_SPECIFIC_ATTR_REPORTING:
+ case ZB_GP_CMD_ID_MULTI_CLUSTER_REPORTING:
+ case ZB_GP_CMD_ID_MANUFACTURER_SPECIFIC_MCLUSTER_REPORTING:
+ case ZB_GP_CMD_ID_REQUEST_ATTRIBUTES:
+ case ZB_GP_CMD_ID_READ_ATTRIBUTES_RESPONSE:
+ case ZB_GP_CMD_ID_ANY_SENSOR_COMMAND_A0_A3:
+ /* TODO: implement it. */
+ break;
+ case ZB_GP_CMD_ID_COMMISSIONING:
+ offset = dissect_zbee_nwk_gp_cmd_commissioning(tvb, pinfo, cmd_tree, packet, offset);
+ break;
+ case ZB_GP_CMD_ID_CHANNEL_REQUEST:
+ offset = dissect_zbee_nwk_gp_cmd_channel_request(tvb, pinfo, cmd_tree, packet, offset);
+ break;
+ /* GPDF commands sent to GPD. */
+ case ZB_GP_CMD_ID_COMMISSIONING_REPLY:
+ offset = dissect_zbee_nwk_gp_cmd_commissioning_reply(tvb, pinfo, cmd_tree, packet, offset);
+ break;
+ case ZB_GP_CMD_ID_WRITE_ATTRIBUTES:
+ case ZB_GP_CMD_ID_READ_ATTRIBUTES:
+ /* TODO: implement it. */
+ break;
+ case ZB_GP_CMD_ID_CHANNEL_CONFIGURATION:
+ offset = dissect_zbee_nwk_gp_cmd_channel_configuration(tvb, pinfo, cmd_tree, packet, offset);
+ break;
+ }
+ if (offset < tvb_reported_length(tvb)) {
+ /* There are leftover bytes! */
+ proto_tree *root = NULL;
+ tvbuff_t *leftover_tvb = tvb_new_subset_remaining(tvb, offset);
+
+ /* Correct the length of the command tree. */
+ if (tree) {
+ root = proto_tree_get_root(tree);
+ proto_item_set_len(cmd_root, offset);
+ }
+ /* Dump the tail. */
+ call_dissector(data_handle, leftover_tvb, pinfo, root);
+ }
+ return offset;
+} /* dissect_zbee_nwk_gp_cmd */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * zbee_sec_make_nonce
+ * DESCRIPTION
+ * Fills in ZigBee GP security nonce from the provided packet structure.
+ * PARAMETERS
+ * zbee_nwk_green_power_packet *packet - ZigBee NWK packet.
+ * gchar *nonce - nonce buffer.
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+static void
+zbee_gp_make_nonce(zbee_nwk_green_power_packet *packet, gchar *nonce)
+{
+ memset(nonce, 0, ZBEE_SEC_CONST_NONCE_LEN);
+ if (packet->direction == ZBEE_NWK_GP_FC_EXT_DIRECTION_FROM_ZGPD) {
+ nonce[0] = (guint8)((packet->source_id) & 0xff);
+ nonce[1] = (guint8)((packet->source_id) >> 8 & 0xff);
+ nonce[2] = (guint8)((packet->source_id) >> 16 & 0xff);
+ nonce[3] = (guint8)((packet->source_id) >> 24 & 0xff);
+ }
+ nonce[4] = (guint8)((packet->source_id) & 0xff);
+ nonce[5] = (guint8)((packet->source_id) >> 8 & 0xff);
+ nonce[6] = (guint8)((packet->source_id) >> 16 & 0xff);
+ nonce[7] = (guint8)((packet->source_id) >> 24 & 0xff);
+ nonce[8] = (guint8)((packet->security_frame_counter) & 0xff);
+ nonce[9] = (guint8)((packet->security_frame_counter) >> 8 & 0xff);
+ nonce[10] = (guint8)((packet->security_frame_counter) >> 16 & 0xff);
+ nonce[11] = (guint8)((packet->security_frame_counter) >> 24 & 0xff);
+ if ((packet->application_id == ZBEE_NWK_GP_APP_ID_ZGP) && (packet->direction !=
+ ZBEE_NWK_GP_FC_EXT_DIRECTION_FROM_ZGPD)) {
+ nonce[12] = 0xa3;
+ } else {
+ nonce[12] = 0x05;
+ }
+ /* TODO: implement if application_id == ZB_ZGP_APP_ID_0000. */
+ /* TODO: implement if application_id != ZB_ZGP_APP_ID_0000. */
+}
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * zbee_sec_decrypt_payload
+ * DESCRIPTION
+ * Creates a nonce and decrypts secured ZigBee GP payload.
+ * PARAMETERS
+ * zbee_nwk_green_power_packet *packet - ZigBee NWK packet.
+ * const gchar *enc_buffer - encoded payload buffer.
+ * const gchar offset - payload offset.
+ * guint8 *dec_buffer - decoded payload buffer.
+ * guint payload_len - payload length.
+ * guint mic_len - MIC length.
+ * guint8 *key - key.
+ * RETURNS
+ * gboolean
+ *---------------------------------------------------------------
+ */
+static gboolean
+zbee_gp_decrypt_payload(zbee_nwk_green_power_packet *packet, const gchar *enc_buffer, const gchar offset, guint8
+ *dec_buffer, guint payload_len, guint mic_len, guint8 *key)
+{
+ guint8 *key_buffer = key;
+ guint8 nonce[ZBEE_SEC_CONST_NONCE_LEN];
+
+ zbee_gp_make_nonce(packet, nonce);
+ if (zbee_sec_ccm_decrypt(key_buffer, nonce, enc_buffer, enc_buffer + offset, dec_buffer, offset, payload_len,
+ mic_len)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_zbee_nwk_gp
+ * DESCRIPTION
+ * ZigBee NWK packet dissection routine for Green Power profile.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_into *pinfo - pointer to packet information fields.
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * void *data - raw packet private data.
+ * RETURNS
+ * int
+ *---------------------------------------------------------------
+ */
+static int
+dissect_zbee_nwk_gp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ gboolean gp_decrypted;
+ GSList *GSList_i;
+ guint offset = 0;
+ guint8 *dec_buffer;
+ guint8 *enc_buffer;
+ guint8 fcf;
+ proto_tree *field_tree = NULL;
+ proto_tree *nwk_tree = NULL;
+ proto_item *proto_root = NULL;
+ proto_item *ti = NULL;
+ tvbuff_t *payload_tvb = NULL;
+ zbee_nwk_green_power_packet packet;
+
+ memset(&packet, 0, sizeof(packet));
+ /* Add ourself to the protocol column, clear the info column and create the protocol tree. */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZigBee Green Power");
+ col_clear(pinfo->cinfo, COL_INFO);
+ if (tree) {
+ proto_root = proto_tree_add_protocol_format(tree, proto_zbee_nwk_gp, tvb, offset, tvb_length(tvb),
+ "ZGP stub NWK header");
+ nwk_tree = proto_item_add_subtree(proto_root, ett_zbee_nwk);
+ }
+ enc_buffer = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 0, tvb_length(tvb));
+ /* Get and parse the FCF. */
+ fcf = tvb_get_guint8(tvb, offset);
+ packet.frame_type = zbee_get_bit_field(fcf, ZBEE_NWK_GP_FCF_FRAME_TYPE);
+ packet.nwk_frame_control_extension = zbee_get_bit_field(fcf, ZBEE_NWK_GP_FCF_CONTROL_EXTENSION);
+ /* Display the FCF. */
+ if (tree) {
+ /* Create a subtree for the FCF. */
+ ti = proto_tree_add_text(nwk_tree, tvb, offset, 1, "Frame Control Field: %s (0x%02x)",
+ val_to_str(packet.frame_type, zbee_nwk_gp_frame_types, "Unknown Frame Type"), fcf);
+ field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_fcf);
+ proto_tree_add_uint(field_tree, hf_zbee_nwk_gp_frame_type, tvb, offset, 1, fcf & ZBEE_NWK_GP_FCF_FRAME_TYPE);
+ proto_tree_add_uint(field_tree, hf_zbee_nwk_gp_proto_version, tvb, offset, 1, fcf & ZBEE_NWK_GP_FCF_VERSION);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_gp_auto_commissioning, tvb, offset, 1, fcf &
+ ZBEE_NWK_GP_FCF_AUTO_COMMISSIONING);
+ proto_tree_add_boolean(field_tree, hf_zbee_nwk_gp_fc_ext, tvb, offset, 1, fcf &
+ ZBEE_NWK_GP_FCF_CONTROL_EXTENSION);
+ }
+ offset += 1;
+ /* Add the frame type to the info column and protocol root. */
+ if (tree) {
+ proto_item_append_text(proto_root, " %s", val_to_str(packet.frame_type, zbee_nwk_gp_frame_types,
+ "Unknown type"));
+ }
+ col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(packet.frame_type, zbee_nwk_gp_frame_types,
+ "Reserved frame type"));
+ if (packet.nwk_frame_control_extension) {
+ /* Display ext FCF. */
+ fcf = tvb_get_guint8(tvb, offset);
+ packet.application_id = zbee_get_bit_field(fcf, ZBEE_NWK_GP_FCF_EXT_APP_ID);
+ packet.security_level = zbee_get_bit_field(fcf, ZBEE_NWK_GP_FCF_EXT_SECURITY_LEVEL);
+ packet.direction = zbee_get_bit_field(fcf, ZBEE_NWK_GP_FCF_EXT_DIRECTION);
+ /* Create a subtree for the extended FCF. */
+ if (tree) {
+ ti = proto_tree_add_text(nwk_tree, tvb, offset, 1, "Extended NWK Frame Control Field");
+ field_tree = proto_item_add_subtree(ti, ett_zbee_nwk_fcf_ext);
+ /* Add the fields. */
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_fc_ext_app_id, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_fc_ext_sec_level, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_fc_ext_sec_key, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_fc_ext_rx_after_tx, tvb, offset, 1, ENC_NA);
+ proto_tree_add_item(field_tree, hf_zbee_nwk_gp_fc_ext_direction, tvb, offset, 1, ENC_NA);
+ }
+ offset += 1;
+ }
+ if ((packet.frame_type == ZBEE_NWK_GP_FCF_DATA && !packet.nwk_frame_control_extension) || (packet.frame_type ==
+ ZBEE_NWK_GP_FCF_DATA && packet.nwk_frame_control_extension && packet.application_id ==
+ ZBEE_NWK_GP_APP_ID_DEFAULT) || (packet.frame_type == ZBEE_NWK_GP_FCF_MAINTENANCE &&
+ packet.nwk_frame_control_extension && packet.application_id == ZBEE_NWK_GP_APP_ID_DEFAULT && tvb_get_guint8(tvb,
+ offset) != ZB_GP_CMD_ID_CHANNEL_CONFIGURATION)) {
+ /* Display GPD Src ID. */
+ packet.source_id = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(nwk_tree, hf_zbee_nwk_gp_zgpd_src_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_item_append_text(proto_root, ", GPD Src ID: 0x%04x", packet.source_id);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", GPD Src ID: 0x%04x", packet.source_id);
+ offset += 4;
+ }
+ /* Display Security Frame Counter. */
+ packet.mic_size = 0;
+ if (packet.nwk_frame_control_extension) {
+ if (packet.application_id == ZBEE_NWK_GP_APP_ID_DEFAULT || packet.application_id == ZBEE_NWK_GP_APP_ID_ZGP) {
+ if (packet.security_level == ZBEE_NWK_GP_SECURITY_LEVEL_1LSB) {
+ packet.mic_size = 2;
+ } else if (packet.security_level == ZBEE_NWK_GP_SECURITY_LEVEL_FULL || packet.security_level ==
+ ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR) {
+ /* Get Security Frame Counter and display it. */
+ packet.mic_size = 4;
+ packet.security_frame_counter = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(nwk_tree, hf_zbee_nwk_gp_security_frame_counter, tvb, offset, 4,
+ ENC_LITTLE_ENDIAN);
+ offset += 4;
+ }
+ }
+ }
+ /* Parse application payload. */
+ packet.payload_len = tvb_reported_length(tvb) - offset - packet.mic_size;
+ /* Ensure that the payload exists. */
+ if (packet.payload_len <= 0) {
+ THROW(BoundsError);
+ }
+ /* OK, payload exists. Parse MIC field if needed. */
+ if (packet.mic_size == 2) {
+ packet.mic = tvb_get_letohs(tvb, offset + packet.payload_len);
+ } else if (packet.mic_size == 4) {
+ packet.mic = tvb_get_letohl(tvb, offset + packet.payload_len);
+ }
+ payload_tvb = tvb_new_subset(tvb, offset, packet.payload_len, packet.payload_len);
+ if (packet.security_level != ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR) {
+ dissect_zbee_nwk_gp_cmd(payload_tvb, pinfo, nwk_tree, data);
+ }
+ offset += packet.payload_len;
+ /* Display MIC field. */
+ if (packet.mic_size) {
+ proto_tree_add_uint(nwk_tree, packet.mic_size == 4 ? hf_zbee_nwk_gp_security_mic_4b :
+ hf_zbee_nwk_gp_security_mic_2b, tvb, offset, packet.mic_size, packet.mic);
+ offset += packet.mic_size;
+ }
+ /* Save packet private data. */
+ data = (void *)&packet;
+ if ((offset < tvb_length(tvb)) && (packet.security_level != ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR)) {
+ THROW(BoundsError);
+ }
+ if (packet.security_level == ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR) {
+ dec_buffer = (guint8 *)g_malloc(packet.payload_len);
+ gp_decrypted = FALSE;
+ if (packet.security_level == ZBEE_NWK_GP_SECURITY_LEVEL_FULLENCR) {
+ GSList_i = zbee_gp_keyring;
+ while (GSList_i && !gp_decrypted) {
+ gp_decrypted = zbee_gp_decrypt_payload(&packet, enc_buffer, offset - packet.payload_len -
+ packet.mic_size, dec_buffer, packet.payload_len, packet.mic_size,
+ ((key_record_t *)(GSList_i->data))->key);
+ if (!gp_decrypted) {
+ GSList_i = g_slist_next(GSList_i);
+ }
+ }
+ }
+ if (gp_decrypted) {
+ payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, packet.payload_len, packet.payload_len);
+ add_new_data_source(pinfo, payload_tvb, "Decrypted GP Payload");
+ dissect_zbee_nwk_gp_cmd(payload_tvb, pinfo, nwk_tree, data);
+ g_free(dec_buffer);
+ return packet.payload_len;
+ } else {
+ g_free(dec_buffer);
+ payload_tvb = tvb_new_subset(tvb, offset - packet.payload_len - packet.mic_size, packet.payload_len, -1);
+ call_dissector(data_handle, payload_tvb, pinfo, tree);
+ }
+ }
+ return 0;
+} /* dissect_zbee_nwk_gp */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * dissect_zbee_nwk_heur_gp
+ * DESCRIPTION
+ * Heuristic interpreter for the ZigBee Green Power dissectors.
+ * PARAMETERS
+ * tvbuff_t *tvb - pointer to buffer containing raw packet.
+ * packet_into *pinfo - pointer to packet information fields.
+ * proto_tree *tree - pointer to data tree Wireshark uses to display packet.
+ * void *data - raw packet private data.
+ * RETURNS
+ * Boolean value, whether it handles the packet or not.
+ *---------------------------------------------------------------
+ */
+static gboolean
+dissect_zbee_nwk_heur_gp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ ieee802154_packet *packet = (ieee802154_packet *)data;
+
+ /* Skip ZigBee beacons. */
+ if ((packet->frame_type == IEEE802154_FCF_BEACON) && (tvb_get_guint8(tvb, 0) == ZBEE_NWK_BEACON_PROCOL_ID))
+ return FALSE;
+
+ if (packet->dst_pan == IEEE802154_BCAST_PAN && packet->dst_addr_mode == IEEE802154_FCF_ADDR_SHORT &&
+ packet->dst16 == IEEE802154_BCAST_ADDR && packet->frame_type != IEEE802154_FCF_BEACON &&
+ packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {
+ dissect_zbee_nwk_gp(tvb, pinfo, tree, data);
+ return TRUE;
+ }
+ /* 64-bit destination addressing mode support. */
+ if (packet->dst_addr_mode == IEEE802154_FCF_ADDR_EXT && packet->frame_type != IEEE802154_FCF_BEACON &&
+ packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {
+ dissect_zbee_nwk_gp(tvb, pinfo, tree, data);
+ return TRUE;
+ }
+ /* All ZigBee 2006, 2007 and PRO frames must always have a 16-bit source address. */
+ if (packet->src_addr_mode != IEEE802154_FCF_ADDR_SHORT) {
+ return TRUE;
+ }
+
+ return FALSE;
+} /* dissect_zbee_nwk_heur_gp */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * gp_init_zbee_security
+ * DESCRIPTION
+ * Init routine for the ZigBee GP profile security.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+static void
+gp_init_zbee_security(void)
+{
+ guint i;
+ key_record_t key_record;
+
+ if (zbee_gp_keyring) {
+ g_slist_free(zbee_gp_keyring);
+ zbee_gp_keyring = NULL;
+ }
+ for (i = 0; gp_uat_key_records && (i < num_uat_key_records); i++) {
+ key_record.frame_num = 0;
+ key_record.label = g_strdup(gp_uat_key_records[i].label);
+ memcpy(&key_record.key, &gp_uat_key_records[i].key, ZBEE_SEC_CONST_KEYSIZE);
+ zbee_gp_keyring = g_slist_prepend(zbee_gp_keyring, g_memdup(&key_record, sizeof(key_record_t)));
+ }
+}
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * proto_register_zbee_nwk_gp
+ * DESCRIPTION
+ * ZigBee NWK GP protocol registration routine.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+void
+proto_register_zbee_nwk_gp(void)
+{
+ module_t *gp_zbee_prefs = NULL;
+
+ static hf_register_info hf[] = {
+ { &hf_zbee_nwk_gp_auto_commissioning,
+ { "Auto Commissioning", "zbee_nwk_gp.auto_commissioning", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_FCF_AUTO_COMMISSIONING, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_fc_ext,
+ { "NWK Frame Extension", "zbee_nwk_gp.fc_extension", FT_BOOLEAN, 8, NULL, ZBEE_NWK_GP_FCF_CONTROL_EXTENSION,
+ NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_frame_type,
+ { "Frame Type", "zbee_nwk_gp.frame_type", FT_UINT8, BASE_HEX, VALS(zbee_nwk_gp_frame_types),
+ ZBEE_NWK_GP_FCF_FRAME_TYPE, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_proto_version,
+ { "Protocol Version", "zbee_nwk_gp.proto_version", FT_UINT8, BASE_DEC, NULL, ZBEE_NWK_GP_FCF_VERSION, NULL,
+ HFILL }},
+
+ { &hf_zbee_nwk_gp_fc_ext_app_id,
+ { "Application ID", "zbee_nwk_gp.fc_ext_app_id", FT_UINT8, BASE_HEX, VALS(zbee_nwk_gp_app_id_names),
+ ZBEE_NWK_GP_FCF_EXT_APP_ID, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_fc_ext_direction,
+ { "Direction", "zbee_nwk_gp.fc_ext_direction", FT_UINT8, BASE_HEX, VALS(zbee_nwk_gp_directions),
+ ZBEE_NWK_GP_FCF_EXT_DIRECTION, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_fc_ext_rx_after_tx,
+ { "Rx After Tx", "zbee_nwk_gp.fc_ext_rxaftertx", FT_BOOLEAN, 8, NULL, ZBEE_NWK_GP_FCF_EXT_RX_AFTER_TX, NULL,
+ HFILL }},
+
+ { &hf_zbee_nwk_gp_fc_ext_sec_key,
+ { "Security Key", "zbee_nwk_gp.fc_ext_security_key", FT_BOOLEAN, 8, NULL, ZBEE_NWK_GP_FCF_EXT_SECURITY_KEY,
+ NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_fc_ext_sec_level,
+ { "Security Level", "zbee_nwk_gp.fc_ext_security_level", FT_UINT8, BASE_HEX,
+ VALS(zbee_nwk_gp_src_sec_levels_names), ZBEE_NWK_GP_FCF_EXT_SECURITY_LEVEL, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_zgpd_src_id,
+ { "Src ID", "zbee_nwk_gp.source_id", FT_UINT32, BASE_HEX, VALS(zbee_nwk_gp_src_id_names), 0x0, NULL,
+ HFILL }},
+
+ { &hf_zbee_nwk_gp_security_frame_counter,
+ { "Security Frame Counter", "zbee_nwk_gp.security_frame_counter", FT_UINT32, BASE_DEC, NULL, 0x0, NULL,
+ HFILL }},
+
+ { &hf_zbee_nwk_gp_security_mic_2b,
+ { "Security MIC", "zbee_nwk_gp.security_mic2", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_security_mic_4b,
+ { "Security MIC", "zbee_nwk_gp.security_mic4", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_command_id,
+ { "ZGPD Command ID", "zbee_nwk_gp.command_id", FT_UINT8, BASE_HEX, VALS(zbee_nwk_gp_cmd_names), 0x0, NULL,
+ HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_device_id,
+ { "ZGPD Device ID", "zbee_nwk_gp.cmd.comm.dev_id", FT_UINT8, BASE_HEX, VALS(zbee_nwk_gp_device_ids_names),
+ 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_ext_opt_gpd_key_encr,
+ { "GPD Key Encryption", "zbee_nwk_gp.cmd.comm.ext_opt.gpd_key_encr", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_GPD_KEY_ENCR, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_ext_opt_gpd_key_present,
+ { "GPD Key Present", "zbee_nwk_gp.cmd.comm.ext_opt.gpd_key_present", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_GPD_KEY_PRESENT, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_ext_opt_key_type,
+ { "Key Type", "zbee_nwk_gp.cmd.comm.ext_opt.key_type", FT_UINT8, BASE_HEX,
+ VALS(zbee_nwk_gp_src_sec_keys_type_names), ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_KEY_TYPE, NULL,
+ HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_outgoing_counter,
+ { "GPD Outgoing Counter", "zbee_nwk_gp.cmd.comm.out_counter", FT_UINT32, BASE_HEX, NULL, 0x0, NULL,
+ HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_ext_opt_sec_level_cap,
+ { "Security Level Capabilities", "zbee_nwk_gp.cmd.comm.ext_opt.seclevel_cap", FT_UINT8, BASE_HEX, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_SEC_LEVEL_CAP, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_gpd_sec_key_mic,
+ { "GPD Key MIC", "zbee_nwk_gp.cmd.comm.gpd_key_mic", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_opt_ext_opt,
+ { "Extended Option Field", "zbee_nwk_gp.cmd.comm.opt.ext_opt_field", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_EXT_OPTIONS, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_opt_fixed_location,
+ { "Fixed Location", "zbee_nwk_gp.cmd.comm.opt.fixed_location", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_FIXED_LOCATION, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_opt_mac_sec_num_cap,
+ { "MAC Sequence number capability", "zbee_nwk_gp.cmd.comm.opt.mac_seq_num_cap", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_MAC_SEQ, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_opt_ms_ext_present,
+ { "MS Extensions Present", "zbee_nwk_gp.cmd.comm.opt.ms_ext_present", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_MANUFACTURER_INFO, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_opt_panid_req,
+ { "PANId request", "zbee_nwk_gp.cmd.comm.opt.panid_req", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_PAN_ID_REQ, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_opt_rx_on_cap,
+ { "RxOnCapability", "zbee_nwk_gp.cmd.comm.opt.rxon_cap", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_RX_ON_CAP, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_opt_sec_key_req,
+ { "GP Security Key Request", "zbee_nwk_gp.cmd.comm.opt.seq_key_req", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_OPT_GP_SEC_KEY_REQ, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_ext_opt_outgoing_counter,
+ { "GPD Outgoing present", "zbee_nwk_gp.cmd.comm.ext_opt.outgoing_counter", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_EXT_OPT_OUT_COUNTER, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_manufacturer_greenpeak_dev_id,
+ { "Manufacturer Model ID", "zbee_nwk_gp.cmd.comm.manufacturer_model_id", FT_UINT16, BASE_HEX,
+ VALS(zbee_nwk_gp_manufacturer_greenpeak_dev_names), 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_manufacturer_id,
+ { "Manufacturer ID", "zbee_nwk_gp.cmd.comm.manufacturer_id", FT_UINT16, BASE_HEX,
+ VALS(zbee_nwk_gp_manufacturers_ids_names), 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_ms_ext_crp,
+ { "Cluster reports present", "zbee_nwk_gp.cmd.comm.ms_ext.crp", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_CRP , NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_ms_ext_gclp,
+ { "GP commands list present", "zbee_nwk_gp.cmd.comm.ms_ext.gclp", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_GCLP , NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_ms_ext_mip,
+ { "Manufacturer ID present", "zbee_nwk_gp.cmd.comm.ms_ext.mip", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_MIP , NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_ms_ext_mmip,
+ { "Manufacturer Model ID present", "zbee_nwk_gp.cmd.comm.ms_ext.mmip", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_MS_EXT_MMIP , NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_rep_opt_key_encr,
+ { "GPD Key Encryption", "zbee_nwk_gp.cmd.comm_reply.opt.sec_key_encr", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_KEY_ENCR, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_rep_opt_panid_present,
+ { "PANID Present", "zbee_nwk_gp.cmd.comm_reply.opt.pan_id_present", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_PAN_ID_PRESENT, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_key_present,
+ { "GPD Security Key Present", "zbee_nwk_gp.cmd.comm_reply.opt.sec_key_present", FT_BOOLEAN, 8, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_SEC_KEY_PRESENT, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_level,
+ { "Security Level", "zbee_nwk_gp.cmd.comm_reply.opt.sec_level", FT_UINT8, BASE_HEX, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_SEC_LEVEL, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_rep_opt_sec_type,
+ { "Key Type", "zbee_nwk_gp.cmd.comm_reply.opt.key_type", FT_UINT8, BASE_HEX, NULL,
+ ZBEE_NWK_GP_CMD_COMMISSIONING_REP_OPT_KEY_TYPE, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_comm_rep_pan_id,
+ { "Manufacturer ID", "zbee_nwk_gp.cmd.comm_reply.pan_id", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_attr_report_cluster_id,
+ { "ZigBee Cluster ID", "zbee_nwk_gp.cmd.comm.attr_report", FT_UINT16, BASE_HEX, VALS(zbee_aps_cid_names),
+ 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_channel_request_toggling_behaviour_1st,
+ { "Rx channel in the next attempt", "zbee_nwk_gp.cmd.ch_req.1st", FT_UINT8, BASE_HEX, NULL,
+ ZBEE_NWK_GP_CMD_CHANNEL_REQUEST_1ST, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_channel_request_toggling_behaviour_2nd,
+ { "Rx channel in the second next attempt", "zbee_nwk_gp.ch_req.2nd", FT_UINT8, BASE_HEX, NULL,
+ ZBEE_NWK_GP_CMD_CHANNEL_REQUEST_2ND, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_channel_configuration,
+ { "Operation channel", "zbee_nwk_gp.cmd.configuration_ch.operation_ch", FT_UINT8, BASE_HEX, NULL,
+ ZBEE_NWK_GP_CMD_CHANNEL_CONFIGURATION_OPERATION_CH, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_move_color_ratex,
+ { "RateX", "zbee_nwk_gp.cmd.move_color.ratex", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_move_color_ratey,
+ { "RateY", "zbee_nwk_gp.cmd.move_color.ratey", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_move_up_down_rate,
+ { "Rate", "zbee_nwk_gp.cmd.move_up_down.rate", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_step_color_stepx,
+ { "StepX", "zbee_nwk_gp.cmd.step_color.stepx", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_step_color_stepy,
+ { "StepY", "zbee_nwk_gp.cmd.step_color.stepy", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_step_color_transition_time,
+ { "Transition Time", "zbee_nwk_gp.cmd.step_color.transition_time", FT_UINT16, BASE_DEC, NULL, 0x0, NULL,
+ HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_step_up_down_step_size,
+ { "Step Size", "zbee_nwk_gp.cmd.step_up_down.step_size", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_zbee_nwk_gp_cmd_step_up_down_transition_time,
+ { "Transition Time", "zbee_nwk_gp.cmd.step_up_down.transition_time", FT_UINT16, BASE_DEC, NULL, 0x0, NULL,
+ HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_zbee_nwk,
+ &ett_zbee_nwk_cmd,
+ &ett_zbee_nwk_cmd_cinfo,
+ &ett_zbee_nwk_cmd_ms_ext,
+ &ett_zbee_nwk_cmd_options,
+ &ett_zbee_nwk_fcf,
+ &ett_zbee_nwk_fcf_ext
+ };
+
+ static uat_field_t key_uat_fields[] = {
+ UAT_FLD_CSTRING(gp_uat_key_records, string, "Key", "A 16-byte key."),
+ UAT_FLD_VS(gp_uat_key_records, byte_order, "Byte Order", byte_order_vals, "Byte order of a key."),
+ UAT_FLD_LSTRING(gp_uat_key_records, label, "Label", "User label for a key."),
+ UAT_END_FIELDS
+ };
+
+ proto_zbee_nwk_gp = proto_register_protocol("ZigBee Green Power Profile", "ZigBee Green Power",
+ ZBEE_PROTOABBREV_NWK_GP);
+
+ if (gp_zbee_prefs == NULL) {
+ gp_zbee_prefs = prefs_register_protocol(proto_zbee_nwk_gp, NULL);
+ }
+
+ zbee_gp_sec_key_table_uat = uat_new("ZigBee GP Security Keys", sizeof(uat_key_record_t), "zigbee_gp_keys", TRUE,
+ (void **)&gp_uat_key_records, &num_uat_key_records, UAT_AFFECTS_DISSECTION, NULL, uat_key_record_copy_cb,
+ uat_key_record_update_cb, uat_key_record_free_cb, NULL, key_uat_fields);
+
+ prefs_register_uat_preference(gp_zbee_prefs, "gp_key_table", "Pre-configured GP Security Keys",
+ "Pre-configured GP Security Keys.", zbee_gp_sec_key_table_uat);
+
+ register_init_routine(gp_init_zbee_security);
+
+ /* Register the Wireshark protocol. */
+ proto_register_field_array(proto_zbee_nwk_gp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register the dissectors. */
+ new_register_dissector(ZBEE_PROTOABBREV_NWK_GP, dissect_zbee_nwk_gp, proto_zbee_nwk_gp);
+} /* proto_register_zbee_nwk_gp */
+
+/*FUNCTION:------------------------------------------------------
+ * NAME
+ * proto_reg_handoff_zbee_nwk_gp
+ * DESCRIPTION
+ * Registers the ZigBee dissector with Wireshark.
+ * PARAMETERS
+ * none
+ * RETURNS
+ * void
+ *---------------------------------------------------------------
+ */
+void
+proto_reg_handoff_zbee_nwk_gp(void)
+{
+ /* Find the other dissectors we need. */
+ data_handle = find_dissector("data");
+ /* Register our dissector with IEEE 802.15.4. */
+ heur_dissector_add(IEEE802154_PROTOABBREV_WPAN, dissect_zbee_nwk_heur_gp, proto_zbee_nwk_gp);
+} /* proto_reg_handoff_zbee */