diff options
-rw-r--r-- | epan/CMakeLists.txt | 1 | ||||
-rw-r--r-- | epan/dissectors/Makefile.common | 1 | ||||
-rw-r--r-- | epan/dissectors/packet-llrp.c | 994 |
3 files changed, 996 insertions, 0 deletions
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt index 6eec6dc16c..7d3465acdf 100644 --- a/epan/CMakeLists.txt +++ b/epan/CMakeLists.txt @@ -787,6 +787,7 @@ set(DISSECTOR_SRC dissectors/packet-lisp.c dissectors/packet-llc.c dissectors/packet-lldp.c + dissectors/packet-llrp.c dissectors/packet-llt.c dissectors/packet-lmi.c dissectors/packet-lmp.c diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index 7cc85a1dad..b34274061a 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -706,6 +706,7 @@ DISSECTOR_SRC = \ packet-lisp.c \ packet-llc.c \ packet-lldp.c \ + packet-llrp.c \ packet-llt.c \ packet-lmi.c \ packet-lmp.c \ diff --git a/epan/dissectors/packet-llrp.c b/epan/dissectors/packet-llrp.c new file mode 100644 index 0000000000..de5c92d3fb --- /dev/null +++ b/epan/dissectors/packet-llrp.c @@ -0,0 +1,994 @@ +/* packet-llrp.c + * Routines for Low Level Reader Protocol dissection + * Copyright 2012, Evan Huus <eapache@gmail.com> + * + * http://www.gs1.org/gsmp/kc/epcglobal/llrp + * + * $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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <glib.h> + +#include <epan/packet.h> +#include <epan/prefs.h> +#include <epan/expert.h> + +#define LLRP_PORT 5084 + +/* Initialize the protocol and registered fields */ +static int proto_llrp = -1; +static int hf_llrp_version = -1; +static int hf_llrp_type = -1; +static int hf_llrp_length = -1; +static int hf_llrp_id = -1; +static int hf_llrp_cur_ver = -1; +static int hf_llrp_sup_ver = -1; +static int hf_llrp_req_cap = -1; +static int hf_llrp_req_conf = -1; +static int hf_llrp_rospec = -1; +static int hf_llrp_antenna_id = -1; +static int hf_llrp_gpi_port = -1; +static int hf_llrp_gpo_port = -1; +static int hf_llrp_rest_fact = -1; +static int hf_llrp_accessspec = -1; +static int hf_llrp_vendor = -1; +static int hf_llrp_tlv_type = -1; +static int hf_llrp_tv_type = -1; +static int hf_llrp_tlv_len = -1; +static int hf_llrp_param = -1; + +/* Initialize the subtree pointers */ +static gint ett_llrp = -1; +static gint ett_llrp_param = -1; + +/* Message Types */ +#define LLRP_TYPE_GET_READER_CAPABILITES 1 +#define LLRP_TYPE_GET_READER_CONFIG 2 +#define LLRP_TYPE_SET_READER_CONFIG 3 +#define LLRP_TYPE_CLOSE_CONNECTION_RESPONSE 4 +#define LLRP_TYPE_GET_READER_CAPABILITES_RESPONSE 11 +#define LLRP_TYPE_GET_READER_CONFIG_RESPONSE 12 +#define LLRP_TYPE_SET_READER_CONFIG_RESPONSE 13 +#define LLRP_TYPE_CLOSE_CONNECTION 14 +#define LLRP_TYPE_ADD_ROSPEC 20 +#define LLRP_TYPE_DELETE_ROSPEC 21 +#define LLRP_TYPE_START_ROSPEC 22 +#define LLRP_TYPE_STOP_ROSPEC 23 +#define LLRP_TYPE_ENABLE_ROSPEC 24 +#define LLRP_TYPE_DISABLE_ROSPEC 25 +#define LLRP_TYPE_GET_ROSPECS 26 +#define LLRP_TYPE_ADD_ROSPEC_RESPONSE 30 +#define LLRP_TYPE_DELETE_ROSPEC_RESPONSE 31 +#define LLRP_TYPE_START_ROSPEC_RESPONSE 32 +#define LLRP_TYPE_STOP_ROSPEC_RESPONSE 33 +#define LLRP_TYPE_ENABLE_ROSPEC_RESPONSE 34 +#define LLRP_TYPE_DISABLE_ROSPEC_RESPONSE 35 +#define LLRP_TYPE_GET_ROSPECS_RESPONSE 36 +#define LLRP_TYPE_ADD_ACCESSSPEC 40 +#define LLRP_TYPE_DELETE_ACCESSSPEC 41 +#define LLRP_TYPE_ENABLE_ACCESSSPEC 42 +#define LLRP_TYPE_DISABLE_ACCESSSPEC 43 +#define LLRP_TYPE_GET_ACCESSSPECS 44 +#define LLRP_TYPE_CLIENT_REQUEST_OP 45 +#define LLRP_TYPE_GET_SUPPORTED_VERSION 46 +#define LLRP_TYPE_SET_PROTOCOL_VERSION 47 +#define LLRP_TYPE_ADD_ACCESSSPEC_RESPONSE 50 +#define LLRP_TYPE_DELETE_ACCESSSPEC_RESPONSE 51 +#define LLRP_TYPE_ENABLE_ACCESSSPEC_RESPONSE 52 +#define LLRP_TYPE_DISABLE_ACCESSSPEC_RESPONSE 53 +#define LLRP_TYPE_GET_ACCESSSPECS_RESPONSE 54 +#define LLRP_TYPE_CLIENT_RESQUEST_OP_RESPONSE 55 +#define LLRP_TYPE_GET_SUPPORTED_VERSION_RESPONSE 56 +#define LLRP_TYPE_SET_PROTOCOL_VERSION_RESPONSE 57 +#define LLRP_TYPE_GET_REPORT 60 +#define LLRP_TYPE_RO_ACCESS_REPORT 61 +#define LLRP_TYPE_KEEPALIVE 62 +#define LLRP_TYPE_READER_EVENT_NOTIFICATION 63 +#define LLRP_TYPE_ENABLE_EVENTS_AND_REPORTS 64 +#define LLRP_TYPE_KEEPALIVE_ACK 72 +#define LLRP_TYPE_ERROR_MESSAGE 100 +#define LLRP_TYPE_CUSTOM_MESSAGE 1023 + +static const value_string message_types[] = { + { LLRP_TYPE_GET_READER_CAPABILITES, "Get Reader Capabilites" }, + { LLRP_TYPE_GET_READER_CONFIG, "Get Reader Config" }, + { LLRP_TYPE_SET_READER_CONFIG, "Set Reader Config" }, + { LLRP_TYPE_CLOSE_CONNECTION_RESPONSE, "Close Connection Response" }, + { LLRP_TYPE_GET_READER_CAPABILITES_RESPONSE, "Get Reader Capabilites Response" }, + { LLRP_TYPE_GET_READER_CONFIG_RESPONSE, "Get Reader Config Response" }, + { LLRP_TYPE_SET_READER_CONFIG_RESPONSE, "Set Reader Config Response" }, + { LLRP_TYPE_CLOSE_CONNECTION, "Close Connection" }, + { LLRP_TYPE_ADD_ROSPEC, "Add ROSpec" }, + { LLRP_TYPE_DELETE_ROSPEC, "Delete ROSpec" }, + { LLRP_TYPE_START_ROSPEC, "Start ROSpec" }, + { LLRP_TYPE_STOP_ROSPEC, "Stop ROSpec" }, + { LLRP_TYPE_ENABLE_ROSPEC, "Enable ROSpec" }, + { LLRP_TYPE_DISABLE_ROSPEC, "Disable ROSpec" }, + { LLRP_TYPE_GET_ROSPECS, "Get ROSpecs" }, + { LLRP_TYPE_ADD_ROSPEC_RESPONSE, "Add ROSpec Response" }, + { LLRP_TYPE_DELETE_ROSPEC_RESPONSE, "Delete ROSpec Response" }, + { LLRP_TYPE_START_ROSPEC_RESPONSE, "Start ROSpec Response" }, + { LLRP_TYPE_STOP_ROSPEC_RESPONSE, "Stop ROSpec Response" }, + { LLRP_TYPE_ENABLE_ROSPEC_RESPONSE, "Enable ROSpec Response" }, + { LLRP_TYPE_DISABLE_ROSPEC_RESPONSE, "Disable ROSpec Response" }, + { LLRP_TYPE_GET_ROSPECS_RESPONSE, "Get ROSpecs Response" }, + { LLRP_TYPE_ADD_ACCESSSPEC, "Add AccessSpec" }, + { LLRP_TYPE_DELETE_ACCESSSPEC, "Delete AccessSpec" }, + { LLRP_TYPE_ENABLE_ACCESSSPEC, "Enable AccessSpec" }, + { LLRP_TYPE_DISABLE_ACCESSSPEC, "Disable AccessSpec" }, + { LLRP_TYPE_GET_ACCESSSPECS, "Get AccessSpecs" }, + { LLRP_TYPE_CLIENT_REQUEST_OP, "Client Request OP" }, + { LLRP_TYPE_GET_SUPPORTED_VERSION, "Get Supported Version" }, + { LLRP_TYPE_SET_PROTOCOL_VERSION, "Set Protocol Version" }, + { LLRP_TYPE_ADD_ACCESSSPEC_RESPONSE, "Add AccessSpec Response" }, + { LLRP_TYPE_DELETE_ACCESSSPEC_RESPONSE, "Delete AccessSpec Response" }, + { LLRP_TYPE_ENABLE_ACCESSSPEC_RESPONSE, "Enable AccessSpec Response" }, + { LLRP_TYPE_DISABLE_ACCESSSPEC_RESPONSE, "Disable AccessSpec Response" }, + { LLRP_TYPE_GET_ACCESSSPECS_RESPONSE, "Get AccessSpecs Response" }, + { LLRP_TYPE_CLIENT_RESQUEST_OP_RESPONSE, "Client Resquest OP Response" }, + { LLRP_TYPE_GET_SUPPORTED_VERSION_RESPONSE, "Get Supported Version Response" }, + { LLRP_TYPE_SET_PROTOCOL_VERSION_RESPONSE, "Set Protocol Version Response" }, + { LLRP_TYPE_GET_REPORT, "Get Report" }, + { LLRP_TYPE_RO_ACCESS_REPORT, "RO Access Report" }, + { LLRP_TYPE_KEEPALIVE, "Keepalive" }, + { LLRP_TYPE_READER_EVENT_NOTIFICATION, "Reader Event Notification" }, + { LLRP_TYPE_ENABLE_EVENTS_AND_REPORTS, "Enable Events And Reports" }, + { LLRP_TYPE_KEEPALIVE_ACK, "Keepalive Ack" }, + { LLRP_TYPE_ERROR_MESSAGE, "Error Message" }, + { LLRP_TYPE_CUSTOM_MESSAGE, "Custom Message" }, + { 0, NULL } +}; + +/* Versions */ +#define LLRP_VERS_1_0_1 0x01 +#define LLRP_VERS_1_1 0x02 + +static const value_string llrp_versions[] = { + { LLRP_VERS_1_0_1, "1.0.1" }, + { LLRP_VERS_1_1, "1.1" }, + { 0, NULL } +}; + +/* Capabilities */ +#define LLRP_CAP_ALL 0 +#define LLRP_CAP_GENERAL_DEVICE 1 +#define LLRP_CAP_LLRP 2 +#define LLRP_CAP_REGULATORY 3 +#define LLRP_CAP_AIR_PROTOCOL 4 + +static const value_string capabilities_request[] = { + { LLRP_CAP_ALL, "All" }, + { LLRP_CAP_GENERAL_DEVICE, "General Device Capabilities" }, + { LLRP_CAP_LLRP, "LLRP Capabilites" }, + { LLRP_CAP_REGULATORY, "Regulatory Capabilities" }, + { LLRP_CAP_AIR_PROTOCOL, "Air Protocol LLRP Capabilities" }, + { 0, NULL } +}; + +/* Configurations */ +#define LLRP_CONF_ALL 0 +#define LLRP_CONF_IDENTIFICATION 1 +#define LLRP_CONF_ANTENNA_PROPERTIES 2 +#define LLRP_CONF_ANTENNA_CONFIGURATION 3 +#define LLRP_CONF_RO_REPORT_SPEC 4 +#define LLRP_CONF_READER_EVENT_NOTIFICATION_SPEC 5 +#define LLRP_CONF_ACCESS_REPORT_SPEC 6 +#define LLRP_CONF_LLRP_CONFIGURATION_STATE 7 +#define LLRP_CONF_KEEPALIVE_SPEC 8 +#define LLRP_CONF_GPI_PORT_CURRENT_STATE 9 +#define LLRP_CONF_GPO_WRITE_DATA 10 +#define LLRP_CONF_EVENTS_AND_REPORTS 11 + +static const value_string config_request[] = { + { LLRP_CONF_ALL, "All" }, + { LLRP_CONF_IDENTIFICATION, "Identification" }, + { LLRP_CONF_ANTENNA_PROPERTIES, "Antenna Properties" }, + { LLRP_CONF_ANTENNA_CONFIGURATION, "Antenna Configuration" }, + { LLRP_CONF_RO_REPORT_SPEC, "RO Report Spec" }, + { LLRP_CONF_READER_EVENT_NOTIFICATION_SPEC, "Reader Event Notification Spec" }, + { LLRP_CONF_ACCESS_REPORT_SPEC, "Access Report Spec" }, + { LLRP_CONF_LLRP_CONFIGURATION_STATE, "LLRP Configuration State" }, + { LLRP_CONF_KEEPALIVE_SPEC, "Keepalive Spec" }, + { LLRP_CONF_GPI_PORT_CURRENT_STATE, "GPI Port Current State" }, + { LLRP_CONF_GPO_WRITE_DATA, "GPO Write Data" }, + { LLRP_CONF_EVENTS_AND_REPORTS, "Events and Reports" }, + { 0, NULL } +}; + +/* TLV Parameter Types */ +#define LLRP_TLV_UTC_TIMESTAMP 128 +#define LLRP_TLV_UPTIME 129 +#define LLRP_TLV_GENERAL_DEVICE_CAP 137 +#define LLRP_TLV_RECEIVE_SENSE_ENTRY 139 +#define LLRP_TLV_ANTENNA_AIR_PROTO 140 +#define LLRP_TLV_GPIO_CAPABILITIES 141 +#define LLRP_TLV_LLRP_CAPABILITIES 142 +#define LLRP_TLV_REGU_CAPABILITIES 143 +#define LLRP_TLV_UHF_CAPABILITIES 144 +#define LLRP_TLV_XMIT_POWER_LEVEL_ENTRY 145 +#define LLRP_TLV_FREQ_INFORMATION 146 +#define LLRP_TLV_FREQ_HOP_TABLE 147 +#define LLRP_TLV_FIXED_FREQ_TABLE 148 +#define LLRP_TLV_ANTENNA_RCV_SENSE_RANGE 149 +#define LLRP_TLV_RO_SPEC 177 +#define LLRP_TLV_RO_BOUND_SPEC 178 +#define LLRP_TLV_RO_SPEC_START_TRIGGER 179 +#define LLRP_TLV_PER_TRIGGER_VAL 180 +#define LLRP_TLV_GPI_TRIGGER_VAL 181 +#define LLRP_TLV_RO_SPEC_STOP_TRIGGER 182 +#define LLRP_TLV_AI_SPEC 183 +#define LLRP_TLV_AI_SPEC_STOP 184 +#define LLRP_TLV_TAG_OBSERV_TRIGGER 185 +#define LLRP_TLV_INVENTORY_PARAM_SPEC 186 +#define LLRP_TLV_RF_SURVEY_SPEC 187 +#define LLRP_TLV_RF_SURVEY_SPEC_STOP_TR 188 +#define LLRP_TLV_ACCESS_SPEC 207 +#define LLRP_TLV_ACCESS_SPEC_STOP_TRIG 208 +#define LLRP_TLV_ACCESS_COMMAND 209 +#define LLRP_TLV_CLIENT_REQ_OP_SPEC 210 +#define LLRP_TLV_CLIENT_REQ_RESPONSE 211 +#define LLRP_TLV_LLRP_CONF_STATE_VAL 217 +#define LLRP_TLV_IDENT 218 +#define LLRP_TLV_GPO_WRITE_DATA 219 +#define LLRP_TLV_KEEPALIVE_SPEC 220 +#define LLRP_TLV_ANTENNA_PROPS 221 +#define LLRP_TLV_ANTENNA_CONF 222 +#define LLRP_TLV_RF_RECEIVER 223 +#define LLRP_TLV_RF_TRANSMITTER 224 +#define LLRP_TLV_GPI_PORT_CURRENT_STATE 225 +#define LLRP_TLV_EVENTS_AND_REPORTS 226 +#define LLRP_TLV_RO_REPORT_SPEC 237 +#define LLRP_TLV_TAG_REPORT_CONTENT_SEL 238 +#define LLRP_TLV_ACCESS_REPORT_SPEC 239 +#define LLRP_TLV_TAG_REPORT_DATA 240 +#define LLRP_TLV_EPC_DATA 241 +#define LLRP_TLV_RF_SURVEY_REPORT_DATA 242 +#define LLRP_TLV_FREQ_RSSI_LEVEL_ENTRY 243 +#define LLRP_TLV_READER_EVENT_NOTI_SPEC 244 +#define LLRP_TLV_EVENT_NOTIF_STATE 245 +#define LLRP_TLV_READER_EVENT_NOTI_DATA 246 +#define LLRP_TLV_HOPPING_EVENT 247 +#define LLRP_TLV_GPI_EVENT 248 +#define LLRP_TLV_RO_SPEC_EVENT 249 +#define LLRP_TLV_REPORT_BUF_LEVEL_WARN 250 +#define LLRP_TLV_REPORT_BUF_OVERFLOW_ERR 251 +#define LLRP_TLV_READER_EXCEPTION_EVENT 252 +#define LLRP_TLV_RF_SURVEY_EVENT 253 +#define LLRP_TLV_AI_SPEC_EVENT 254 +#define LLRP_TLV_ANTENNA_EVENT 255 +#define LLRP_TLV_CONN_ATTEMPT_EVENT 256 +#define LLRP_TLV_CONN_CLOSE_EVENT 257 +#define LLRP_TLV_LLRP_STATUS 287 +#define LLRP_TLV_FIELD_ERROR 288 +#define LLRP_TLV_PARAM_ERROR 289 +#define LLRP_TLV_C1G2_LLRP_CAP 327 +#define LLRP_TLV_C1G2_UHF_RF_MD_TBL 328 +#define LLRP_TLV_C1G2_UHF_RF_MD_TBL_ENT 329 +#define LLRP_TLV_C1G2_INVENTORY_COMMAND 330 +#define LLRP_TLV_C1G2_FILTER 331 +#define LLRP_TLV_C1G2_TAG_INV_MASK 332 +#define LLRP_TLV_C1G2_TAG_INV_AWARE_FLTR 333 +#define LLRP_TLV_C1G2_TAG_INV_UNAWR_FLTR 334 +#define LLRP_TLV_C1G2_RF_CONTROL 335 +#define LLRP_TLV_C1G2_SINGULATION_CTRL 336 +#define LLRP_TLV_C1G2_TAG_INV_AWARE_SING 337 +#define LLRP_TLV_C1G2_TAG_SPEC 338 +#define LLRP_TLV_C1G2_TARGET_TAG 339 +#define LLRP_TLV_C1G2_READ 341 +#define LLRP_TLV_C1G2_WRITE 342 +#define LLRP_TLV_C1G2_KILL 343 +#define LLRP_TLV_C1G2_LOCK 344 +#define LLRP_TLV_C1G2_LOCK_PAYLOAD 345 +#define LLRP_TLV_C1G2_BLK_ERASE 346 +#define LLRP_TLV_C1G2_BLK_WRITE 347 +#define LLRP_TLV_C1G2_EPC_MEMORY_SLCTOR 348 +#define LLRP_TLV_C1G2_READ_OP_SPEC_RES 349 +#define LLRP_TLV_C1G2_WRT_OP_SPEC_RES 350 +#define LLRP_TLV_C1G2_KILL_OP_SPEC_RES 351 +#define LLRP_TLV_C1G2_LOCK_OP_SPEC_RES 352 +#define LLRP_TLV_C1G2_BLK_ERS_OP_SPC_RES 353 +#define LLRP_TLV_C1G2_BLK_WRT_OP_SPC_RES 354 +#define LLRP_TLV_LOOP_SPEC 355 +#define LLRP_TLV_MAX_RECEIVE_SENSE 363 +#define LLRP_TLV_RF_SURVEY_FREQ_CAP 365 + +static const value_string tlv_type[] = { + { LLRP_TLV_UTC_TIMESTAMP, "UTC Timestamp" }, + { LLRP_TLV_UPTIME, "Uptime" }, + { LLRP_TLV_GENERAL_DEVICE_CAP, "General Device Capabilities" }, + { LLRP_TLV_RECEIVE_SENSE_ENTRY, "Receive Sensitivity Entry" }, + { LLRP_TLV_ANTENNA_AIR_PROTO, "Antenna Air Protocol" }, + { LLRP_TLV_GPIO_CAPABILITIES, "GPIO Capabilities" }, + { LLRP_TLV_LLRP_CAPABILITIES, "LLRP Capabilities" }, + { LLRP_TLV_REGU_CAPABILITIES, "REGU Capabilities" }, + { LLRP_TLV_UHF_CAPABILITIES, "UHF Capabilities" }, + { LLRP_TLV_XMIT_POWER_LEVEL_ENTRY, "Transmit Power Level Entry" }, + { LLRP_TLV_FREQ_INFORMATION, "Frequency Information" }, + { LLRP_TLV_FREQ_HOP_TABLE, "Frequenct Hop Table" }, + { LLRP_TLV_FIXED_FREQ_TABLE, "Fixed Frequency Table" }, + { LLRP_TLV_ANTENNA_RCV_SENSE_RANGE, "Antenna RCV Sensitivity Range" }, + { LLRP_TLV_RO_SPEC, "RO Spec" }, + { LLRP_TLV_RO_BOUND_SPEC, "RO Bound Spec" }, + { LLRP_TLV_RO_SPEC_START_TRIGGER, "RO Spec Start Trigger" }, + { LLRP_TLV_PER_TRIGGER_VAL, "PER Trigger Value" }, + { LLRP_TLV_GPI_TRIGGER_VAL, "GPI Trigger Value" }, + { LLRP_TLV_RO_SPEC_STOP_TRIGGER, "RO Spec Stop Trigger" }, + { LLRP_TLV_AI_SPEC, "AI Spec" }, + { LLRP_TLV_AI_SPEC_STOP, "AI Spec Stop" }, + { LLRP_TLV_TAG_OBSERV_TRIGGER, "Tag Observation Trigger" }, + { LLRP_TLV_INVENTORY_PARAM_SPEC, "Inventory Parameter Spec ID" }, + { LLRP_TLV_RF_SURVEY_SPEC, "RF Survey Spec" }, + { LLRP_TLV_RF_SURVEY_SPEC_STOP_TR, "RF Survey Spec Stop Trigger" }, + { LLRP_TLV_ACCESS_SPEC, "Access Spec" }, + { LLRP_TLV_ACCESS_SPEC_STOP_TRIG, "Access Spec Stop Trigger" }, + { LLRP_TLV_ACCESS_COMMAND, "Access Command" }, + { LLRP_TLV_CLIENT_REQ_OP_SPEC, "Client Request Op Spec" }, + { LLRP_TLV_CLIENT_REQ_RESPONSE, "Client Request Response" }, + { LLRP_TLV_LLRP_CONF_STATE_VAL, "LLRP Configuration State Value" }, + { LLRP_TLV_IDENT, "Identification" }, + { LLRP_TLV_GPO_WRITE_DATA, "GPO Write Data" }, + { LLRP_TLV_KEEPALIVE_SPEC, "Keepalive Spec" }, + { LLRP_TLV_ANTENNA_PROPS, "Antenna Properties" }, + { LLRP_TLV_ANTENNA_CONF, "Antenna Configuration" }, + { LLRP_TLV_RF_RECEIVER, "RF Receiver" }, + { LLRP_TLV_RF_TRANSMITTER, "RF Transmitter" }, + { LLRP_TLV_GPI_PORT_CURRENT_STATE, "GPI Port Current State" }, + { LLRP_TLV_EVENTS_AND_REPORTS, "Events And Reports" }, + { LLRP_TLV_RO_REPORT_SPEC, "RO Report Spec" }, + { LLRP_TLV_TAG_REPORT_CONTENT_SEL, "Tag Report Content Selector" }, + { LLRP_TLV_ACCESS_REPORT_SPEC, "Access Report Spec" }, + { LLRP_TLV_TAG_REPORT_DATA, "Tag Report Data" }, + { LLRP_TLV_EPC_DATA, "EPC Data" }, + { LLRP_TLV_RF_SURVEY_REPORT_DATA, "RF Survey Report Data" }, + { LLRP_TLV_FREQ_RSSI_LEVEL_ENTRY, "Frequency RSSI Level Entry" }, + { LLRP_TLV_READER_EVENT_NOTI_SPEC, "Reader Event Notification Spec" }, + { LLRP_TLV_EVENT_NOTIF_STATE, "Event Notification State" }, + { LLRP_TLV_READER_EVENT_NOTI_DATA, "Reader Event Notification Data" }, + { LLRP_TLV_HOPPING_EVENT, "Hopping Event" }, + { LLRP_TLV_GPI_EVENT, "GPI Event" }, + { LLRP_TLV_RO_SPEC_EVENT, "RO Spec Event" }, + { LLRP_TLV_REPORT_BUF_LEVEL_WARN, "Report Buffer Level Warning Event" }, + { LLRP_TLV_REPORT_BUF_OVERFLOW_ERR, "Report Buffer Overflow Error Event" }, + { LLRP_TLV_READER_EXCEPTION_EVENT, "Reader Exception Event" }, + { LLRP_TLV_RF_SURVEY_EVENT, "RF Survey Event" }, + { LLRP_TLV_AI_SPEC_EVENT, "AI Spec Event" }, + { LLRP_TLV_ANTENNA_EVENT, "ANTENNA Event" }, + { LLRP_TLV_CONN_ATTEMPT_EVENT, "CONN Attempt Event" }, + { LLRP_TLV_CONN_CLOSE_EVENT, "CONN Close Event" }, + { LLRP_TLV_LLRP_STATUS, "LLRP Status" }, + { LLRP_TLV_FIELD_ERROR, "Field Error" }, + { LLRP_TLV_PARAM_ERROR, "Param Error" }, + { LLRP_TLV_C1G2_LLRP_CAP, "C1G2 LLRP Capabilities" }, + { LLRP_TLV_C1G2_UHF_RF_MD_TBL, "C1G2 UHF RF Mode Table" }, + { LLRP_TLV_C1G2_UHF_RF_MD_TBL_ENT, "C1G2 UHF RF Mode Table Entry" }, + { LLRP_TLV_C1G2_INVENTORY_COMMAND, "C1G2 Inventory Command" }, + { LLRP_TLV_C1G2_FILTER, "C1G2 Filter" }, + { LLRP_TLV_C1G2_TAG_INV_MASK, "C1G2 Tag Inventory Mask" }, + { LLRP_TLV_C1G2_TAG_INV_AWARE_FLTR, "C1G2 Tag Inventory State-Aware Filtre Action" }, + { LLRP_TLV_C1G2_TAG_INV_UNAWR_FLTR, "C1G2 Tag Inventory State-Unaware Filter Action" }, + { LLRP_TLV_C1G2_RF_CONTROL, "C1G2 RF Control" }, + { LLRP_TLV_C1G2_SINGULATION_CTRL, "C1G2 Singulation Control" }, + { LLRP_TLV_C1G2_TAG_INV_AWARE_SING, "C1G2 Tag Inventory State-Aware Singulation" }, + { LLRP_TLV_C1G2_TAG_SPEC, "C1G2 Tag Spec" }, + { LLRP_TLV_C1G2_TARGET_TAG, "C1G2 Target Tag" }, + { LLRP_TLV_C1G2_READ, "C1G2 Read" }, + { LLRP_TLV_C1G2_WRITE, "C1G2 Write" }, + { LLRP_TLV_C1G2_KILL, "C1G2 Kill" }, + { LLRP_TLV_C1G2_LOCK, "C1G2 Lock" }, + { LLRP_TLV_C1G2_LOCK_PAYLOAD, "C1G2 Lock Payload" }, + { LLRP_TLV_C1G2_BLK_ERASE, "C1G2 Block Erase" }, + { LLRP_TLV_C1G2_BLK_WRITE, "C1G2 Block Write" }, + { LLRP_TLV_C1G2_EPC_MEMORY_SLCTOR, "C1G2 EPC Memory Selector" }, + { LLRP_TLV_C1G2_READ_OP_SPEC_RES, "C1G2 Read Op Spec Result" }, + { LLRP_TLV_C1G2_WRT_OP_SPEC_RES, "C1G2 Write Op Spec Result" }, + { LLRP_TLV_C1G2_KILL_OP_SPEC_RES, "C1G2 Kill Op Spec Result" }, + { LLRP_TLV_C1G2_LOCK_OP_SPEC_RES, "C1G2 Lock Op Spec Result" }, + { LLRP_TLV_C1G2_BLK_ERS_OP_SPC_RES, "C1G2 Block Erase Op Spec Result" }, + { LLRP_TLV_C1G2_BLK_WRT_OP_SPC_RES, "C1G2 Block Write Op Spec Result" }, + { LLRP_TLV_LOOP_SPEC, "Loop Spec" }, + { LLRP_TLV_MAX_RECEIVE_SENSE, "Maximum Receive Sensitivity" }, + { LLRP_TLV_RF_SURVEY_FREQ_CAP, "RF Survey Frequency Capabilities" }, + { 0, NULL } +}; + +/* TV Parameter Types */ +#define LLRP_TV_ANTENNA_ID 1 +#define LLRP_TV_FIRST_SEEN_TIME_UTC 2 +#define LLRP_TV_FIRST_SEEN_TIME_UPTIME 3 +#define LLRP_TV_LAST_SEEN_TIME_UTC 4 +#define LLRP_TV_LAST_SEEN_TIME_UPTIME 5 +#define LLRP_TV_PEAK_RSSI 6 +#define LLRP_TV_CHANNEL_INDEX 7 +#define LLRP_TV_TAG_SEEN_COUNT 8 +#define LLRP_TV_RO_SPEC_ID 9 +#define LLRP_TV_INVENTORY_PARAM_SPEC_ID 10 +#define LLRP_TV_C1G2_CRC 11 +#define LLRP_TV_C1G2_PC 12 +#define LLRP_TV_EPC96 13 +#define LLRP_TV_SPEC_INDEX 14 +#define LLRP_TV_CLIENT_REQ_OP_SPEC_RES 15 +#define LLRP_TV_ACCESS_SPEC_ID 16 +#define LLRP_TV_OP_SPEC_ID 17 +#define LLRP_TV_C1G2_SINGULATION_DET 18 +#define LLRP_TV_C1G2_XPC_W1 19 +#define LLRP_TV_C1G2_XPC_W2 20 + +/* Since TV's don't have a length field, + * use these values instead */ +#define LLRP_TV_LEN_ANTENNA_ID 2 +#define LLRP_TV_LEN_FIRST_SEEN_TIME_UTC 8 +#define LLRP_TV_LEN_FIRST_SEEN_TIME_UPTIME 8 +#define LLRP_TV_LEN_LAST_SEEN_TIME_UTC 8 +#define LLRP_TV_LEN_LAST_SEEN_TIME_UPTIME 8 +#define LLRP_TV_LEN_PEAK_RSSI 1 +#define LLRP_TV_LEN_CHANNEL_INDEX 2 +#define LLRP_TV_LEN_TAG_SEEN_COUNT 2 +#define LLRP_TV_LEN_RO_SPEC_ID 4 +#define LLRP_TV_LEN_INVENTORY_PARAM_SPEC_ID 2 +#define LLRP_TV_LEN_C1G2_CRC 2 +#define LLRP_TV_LEN_C1G2_PC 2 +#define LLRP_TV_LEN_EPC96 2 +#define LLRP_TV_LEN_SPEC_INDEX 2 +#define LLRP_TV_LEN_CLIENT_REQ_OP_SPEC_RES 2 +#define LLRP_TV_LEN_ACCESS_SPEC_ID 4 +#define LLRP_TV_LEN_OP_SPEC_ID 2 +#define LLRP_TV_LEN_C1G2_SINGULATION_DET 4 +#define LLRP_TV_LEN_C1G2_XPC_W1 2 +#define LLRP_TV_LEN_C1G2_XPC_W2 2 + +static const value_string tv_type[] = { + { LLRP_TV_ANTENNA_ID, "Antenna ID" }, + { LLRP_TV_FIRST_SEEN_TIME_UTC, "First Seen Timestamp UTC" }, + { LLRP_TV_FIRST_SEEN_TIME_UPTIME, "First Seen Timestamp Uptime" }, + { LLRP_TV_LAST_SEEN_TIME_UTC, "Last Seen Timestamp UTC" }, + { LLRP_TV_LAST_SEEN_TIME_UPTIME, "Last Seen Timestamp Uptime" }, + { LLRP_TV_PEAK_RSSI, "Peak RSSI" }, + { LLRP_TV_CHANNEL_INDEX, "Channel Index" }, + { LLRP_TV_TAG_SEEN_COUNT, "Tag Seen Count" }, + { LLRP_TV_RO_SPEC_ID, "RO Spec ID" }, + { LLRP_TV_INVENTORY_PARAM_SPEC_ID, "Inventory Parameter Spec ID" }, + { LLRP_TV_C1G2_CRC, "C1G2 CRC" }, + { LLRP_TV_C1G2_PC, "C1G2 PC" }, + { LLRP_TV_EPC96, "EPC-96" }, + { LLRP_TV_SPEC_INDEX, "Spec Index" }, + { LLRP_TV_CLIENT_REQ_OP_SPEC_RES, "Client Request Op Spec Result" }, + { LLRP_TV_ACCESS_SPEC_ID, "Access Spec ID" }, + { LLRP_TV_OP_SPEC_ID, "Op Spec ID" }, + { LLRP_TV_C1G2_SINGULATION_DET, "C1G2 Singulation Details" }, + { LLRP_TV_C1G2_XPC_W1, "C1G2 XPC W1" }, + { LLRP_TV_C1G2_XPC_W2, "C1G2 XPC W2" }, + { 0, NULL } +}; + +/* Misc */ +#define LLRP_ROSPEC_ALL 0 +#define LLRP_ANTENNA_ALL 0 +#define LLRP_GPI_PORT_ALL 0 +#define LLRP_GPO_PORT_ALL 0 +#define LLRP_ACCESSSPEC_ALL 0 +#define LLRP_TLV_LEN_MIN 4 +#define LLRP_LEN_MIN 10 + +static void +dissect_llrp_parameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + guint offset) +{ + guint8 has_length; + guint16 len, type; + guint real_len; + proto_item *ti; + proto_tree *param_tree; + + while (tvb_reported_length_remaining(tvb, offset) > 0) + { + has_length = !(tvb_get_guint8(tvb, offset) & 0x80); + + if (has_length) + { + len = tvb_get_ntohs(tvb, offset + 2); + + if (len < LLRP_TLV_LEN_MIN) + real_len = LLRP_TLV_LEN_MIN; + else if (len > tvb_reported_length_remaining(tvb, offset)) + real_len = tvb_reported_length_remaining(tvb, offset); + else + real_len = len; + + ti = proto_tree_add_none_format(tree, hf_llrp_param, tvb, + offset, real_len, "TLV Parameter"); + param_tree = proto_item_add_subtree(ti, ett_llrp_param); + + proto_tree_add_item(param_tree, hf_llrp_tlv_type, tvb, + offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + ti = proto_tree_add_item(param_tree, hf_llrp_tlv_len, tvb, + offset, 2, ENC_BIG_ENDIAN); + if (len != real_len) + expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, + "Invalid length field: claimed %u, should be %u.", + len, real_len); + offset += 2; + + /* TODO: Decode actual TLV parameter fields */ + + /* The len field includes the 4-byte parameter header that we've + * already accounted for in offset */ + offset += real_len - 4; + } + else + { + type = tvb_get_guint8(tvb, offset) & 0x7F; + + /* TODO: Decode actual TV fields rather than just jumping + * ahead the correct length */ + switch (type) + { + case LLRP_TV_ANTENNA_ID: + real_len = LLRP_TV_LEN_ANTENNA_ID; break; + case LLRP_TV_FIRST_SEEN_TIME_UTC: + real_len = LLRP_TV_LEN_FIRST_SEEN_TIME_UTC; break; + case LLRP_TV_FIRST_SEEN_TIME_UPTIME: + real_len = LLRP_TV_LEN_FIRST_SEEN_TIME_UPTIME; break; + case LLRP_TV_LAST_SEEN_TIME_UTC: + real_len = LLRP_TV_LEN_LAST_SEEN_TIME_UTC; break; + case LLRP_TV_LAST_SEEN_TIME_UPTIME: + real_len = LLRP_TV_LEN_LAST_SEEN_TIME_UPTIME; break; + case LLRP_TV_PEAK_RSSI: + real_len = LLRP_TV_LEN_PEAK_RSSI; break; + case LLRP_TV_CHANNEL_INDEX: + real_len = LLRP_TV_LEN_CHANNEL_INDEX; break; + case LLRP_TV_TAG_SEEN_COUNT: + real_len = LLRP_TV_LEN_TAG_SEEN_COUNT; break; + case LLRP_TV_RO_SPEC_ID: + real_len = LLRP_TV_LEN_RO_SPEC_ID; break; + case LLRP_TV_INVENTORY_PARAM_SPEC_ID: + real_len = LLRP_TV_LEN_INVENTORY_PARAM_SPEC_ID; break; + case LLRP_TV_C1G2_CRC: + real_len = LLRP_TV_LEN_C1G2_CRC; break; + case LLRP_TV_C1G2_PC: + real_len = LLRP_TV_LEN_C1G2_PC; break; + case LLRP_TV_EPC96: + real_len = LLRP_TV_LEN_EPC96; break; + case LLRP_TV_SPEC_INDEX: + real_len = LLRP_TV_LEN_SPEC_INDEX; break; + case LLRP_TV_CLIENT_REQ_OP_SPEC_RES: + real_len = LLRP_TV_LEN_CLIENT_REQ_OP_SPEC_RES; break; + case LLRP_TV_ACCESS_SPEC_ID: + real_len = LLRP_TV_LEN_ACCESS_SPEC_ID; break; + case LLRP_TV_OP_SPEC_ID: + real_len = LLRP_TV_LEN_OP_SPEC_ID; break; + case LLRP_TV_C1G2_SINGULATION_DET: + real_len = LLRP_TV_LEN_C1G2_SINGULATION_DET; break; + case LLRP_TV_C1G2_XPC_W1: + real_len = LLRP_TV_LEN_C1G2_XPC_W1; break; + case LLRP_TV_C1G2_XPC_W2: + real_len = LLRP_TV_LEN_C1G2_XPC_W2; break; + default: + /* ??? + * No need to mark it, since the hf_llrp_tv_type field + * will already show up as 'unknown'. */ + real_len = 0; + break; + }; + + ti = proto_tree_add_none_format(tree, hf_llrp_param, tvb, + offset, real_len + 1, "TV Parameter"); + param_tree = proto_item_add_subtree(ti, ett_llrp_param); + + proto_tree_add_item(param_tree, hf_llrp_tv_type, tvb, + offset, 1, ENC_NA); + offset++; + + /* Unlike for TLV's, real_len for TV's doesn't include the standard + * header length, so just add it straight to the offset. */ + offset += real_len; + } + } +} + +static void +dissect_llrp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + guint16 type, guint offset) +{ + guint8 requested_data; + guint16 antenna_id, gpi_port, gpo_port; + guint32 spec_id; + proto_item *ti; + + switch (type) + { + /* Simple cases just have normal TLV or TV parameters */ + case LLRP_TYPE_CLOSE_CONNECTION_RESPONSE: + case LLRP_TYPE_GET_READER_CAPABILITES_RESPONSE: + case LLRP_TYPE_ADD_ROSPEC: + case LLRP_TYPE_ADD_ROSPEC_RESPONSE: + case LLRP_TYPE_DELETE_ROSPEC_RESPONSE: + case LLRP_TYPE_START_ROSPEC_RESPONSE: + case LLRP_TYPE_STOP_ROSPEC_RESPONSE: + case LLRP_TYPE_ENABLE_ROSPEC_RESPONSE: + case LLRP_TYPE_DISABLE_ROSPEC_RESPONSE: + case LLRP_TYPE_GET_ROSPECS_RESPONSE: + case LLRP_TYPE_ADD_ACCESSSPEC: + case LLRP_TYPE_ADD_ACCESSSPEC_RESPONSE: + case LLRP_TYPE_DELETE_ACCESSSPEC_RESPONSE: + case LLRP_TYPE_ENABLE_ACCESSSPEC_RESPONSE: + case LLRP_TYPE_DISABLE_ACCESSSPEC_RESPONSE: + case LLRP_TYPE_GET_ACCESSSPECS: + case LLRP_TYPE_CLIENT_REQUEST_OP: + case LLRP_TYPE_CLIENT_RESQUEST_OP_RESPONSE: + case LLRP_TYPE_RO_ACCESS_REPORT: + case LLRP_TYPE_READER_EVENT_NOTIFICATION: + case LLRP_TYPE_ERROR_MESSAGE: + case LLRP_TYPE_GET_READER_CONFIG_RESPONSE: + case LLRP_TYPE_SET_READER_CONFIG_RESPONSE: + case LLRP_TYPE_SET_PROTOCOL_VERSION_RESPONSE: + case LLRP_TYPE_GET_ACCESSSPECS_RESPONSE: + case LLRP_TYPE_GET_REPORT: + case LLRP_TYPE_ENABLE_EVENTS_AND_REPORTS: + dissect_llrp_parameters(tvb, pinfo, tree, offset); + break; + /* Some just have an ROSpec ID */ + case LLRP_TYPE_START_ROSPEC: + case LLRP_TYPE_STOP_ROSPEC: + case LLRP_TYPE_ENABLE_ROSPEC: + case LLRP_TYPE_DISABLE_ROSPEC: + case LLRP_TYPE_DELETE_ROSPEC: + spec_id = tvb_get_ntohl(tvb, offset); + if (spec_id == LLRP_ROSPEC_ALL) + proto_tree_add_uint_format(tree, hf_llrp_rospec, tvb, + offset, 4, spec_id, "All ROSpecs (%u)", spec_id); + else + proto_tree_add_item(tree, hf_llrp_rospec, tvb, + offset, 4, ENC_BIG_ENDIAN); + break; + /* Some just have an AccessSpec ID */ + case LLRP_TYPE_ENABLE_ACCESSSPEC: + case LLRP_TYPE_DELETE_ACCESSSPEC: + case LLRP_TYPE_DISABLE_ACCESSSPEC: + spec_id = tvb_get_ntohl(tvb, offset); + if (spec_id == LLRP_ACCESSSPEC_ALL) + proto_tree_add_uint_format(tree, hf_llrp_accessspec, tvb, + offset, 4, spec_id, "All Access Specs (%u)", spec_id); + else + proto_tree_add_item(tree, hf_llrp_accessspec, tvb, + offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_llrp_accessspec, tvb, offset, 4, ENC_BIG_ENDIAN); + break; + case LLRP_TYPE_GET_READER_CAPABILITES: + proto_tree_add_item(tree, hf_llrp_req_cap, tvb, offset, 1, ENC_NA); + offset++; + dissect_llrp_parameters(tvb, pinfo, tree, offset); + break; + /* GET_READER_CONFIG is complicated */ + case LLRP_TYPE_GET_READER_CONFIG: + requested_data = tvb_get_guint8(tvb, offset + 2); + switch (requested_data) + { + case LLRP_CONF_ALL: + antenna_id = tvb_get_ntohs(tvb, offset); + if (antenna_id == LLRP_ANTENNA_ALL) + proto_tree_add_uint_format(tree, hf_llrp_antenna_id, tvb, + offset, 2, antenna_id, "All Antennas (%u)", antenna_id); + else + proto_tree_add_item(tree, hf_llrp_antenna_id, tvb, + offset, 2, ENC_BIG_ENDIAN); + offset += 2; + proto_tree_add_item(tree, hf_llrp_req_conf, tvb, + offset, 1, ENC_NA); + offset++; + gpi_port = tvb_get_ntohs(tvb, offset); + if (gpi_port == LLRP_GPI_PORT_ALL) + proto_tree_add_uint_format(tree, hf_llrp_gpi_port, tvb, + offset, 2, gpi_port, "All GPI Ports (%u)", gpi_port); + else + proto_tree_add_item(tree, hf_llrp_gpi_port, tvb, + offset, 2, ENC_BIG_ENDIAN); + offset += 2; + gpo_port = tvb_get_ntohs(tvb, offset); + if (gpo_port == LLRP_GPO_PORT_ALL) + proto_tree_add_uint_format(tree, hf_llrp_gpo_port, tvb, + offset, 2, gpo_port, "All GPO Ports (%u)", gpo_port); + else + proto_tree_add_item(tree, hf_llrp_gpo_port, tvb, + offset, 2, ENC_BIG_ENDIAN); + offset += 2; + break; + case LLRP_CONF_ANTENNA_PROPERTIES: + case LLRP_CONF_ANTENNA_CONFIGURATION: + antenna_id = tvb_get_ntohs(tvb, offset); + if (antenna_id == LLRP_ANTENNA_ALL) + proto_tree_add_uint_format(tree, hf_llrp_antenna_id, tvb, + offset, 2, antenna_id, "All Antennas (%u)", antenna_id); + else + proto_tree_add_item(tree, hf_llrp_antenna_id, tvb, + offset, 2, ENC_BIG_ENDIAN); + offset += 2; + proto_tree_add_item(tree, hf_llrp_req_conf, tvb, + offset, 1, ENC_NA); + offset++; + offset += 4; /* Skip both GPI and GPO ports */ + break; + case LLRP_CONF_IDENTIFICATION: + case LLRP_CONF_RO_REPORT_SPEC: + case LLRP_CONF_READER_EVENT_NOTIFICATION_SPEC: + case LLRP_CONF_ACCESS_REPORT_SPEC: + case LLRP_CONF_LLRP_CONFIGURATION_STATE: + case LLRP_CONF_KEEPALIVE_SPEC: + case LLRP_CONF_EVENTS_AND_REPORTS: + offset += 2; /* Skip antenna ID */ + proto_tree_add_item(tree, hf_llrp_req_conf, tvb, + offset, 1, ENC_NA); + offset++; + offset += 4; /* Skip both GPI and GPO ports */ + break; + case LLRP_CONF_GPI_PORT_CURRENT_STATE: + offset += 2; /* Skip antenna ID */ + proto_tree_add_item(tree, hf_llrp_req_conf, tvb, + offset, 1, ENC_NA); + offset++; + gpi_port = tvb_get_ntohs(tvb, offset); + if (gpi_port == LLRP_GPI_PORT_ALL) + proto_tree_add_uint_format(tree, hf_llrp_gpi_port, tvb, + offset, 2, gpi_port, "All GPI Ports (%u)", gpi_port); + else + proto_tree_add_item(tree, hf_llrp_gpi_port, tvb, + offset, 2, ENC_BIG_ENDIAN); + offset += 2; + offset += 2; /* Skip GPO Port */ + break; + case LLRP_CONF_GPO_WRITE_DATA: + offset += 2; /* Skip antenna ID */ + proto_tree_add_item(tree, hf_llrp_req_conf, tvb, + offset, 1, ENC_NA); + offset++; + offset += 2; /* Skip GPI Port */ + gpo_port = tvb_get_ntohs(tvb, offset); + if (gpo_port == LLRP_GPO_PORT_ALL) + proto_tree_add_uint_format(tree, hf_llrp_gpo_port, tvb, + offset, 2, gpo_port, "All GPO Ports (%u)", gpo_port); + else + proto_tree_add_item(tree, hf_llrp_gpo_port, tvb, + offset, 2, ENC_BIG_ENDIAN); + offset += 2; + break; + default: + offset += 2; /* Skip antenna ID */ + ti = proto_tree_add_item(tree, hf_llrp_req_conf, tvb, + offset, 1, ENC_NA); + expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, + "Unrecognized configuration request: %u", + requested_data); + offset++; + offset += 4; /* Skip both GPI and GPO ports */ + break; + }; + dissect_llrp_parameters(tvb, pinfo, tree, offset); + break; + /* END GET_READER_CONFIG */ + /* Misc */ + case LLRP_TYPE_SET_READER_CONFIG: + proto_tree_add_item(tree, hf_llrp_rest_fact, tvb, offset, 1, ENC_NA); + offset++; + dissect_llrp_parameters(tvb, pinfo, tree, offset); + break; + case LLRP_TYPE_SET_PROTOCOL_VERSION: + proto_tree_add_item(tree, hf_llrp_version, tvb, offset, 1, ENC_NA); + break; + case LLRP_TYPE_GET_SUPPORTED_VERSION_RESPONSE: + proto_tree_add_item(tree, hf_llrp_cur_ver, tvb, offset, 1, ENC_NA); + offset++; + proto_tree_add_item(tree, hf_llrp_sup_ver, tvb, offset, 1, ENC_NA); + offset++; + dissect_llrp_parameters(tvb, pinfo, tree, offset); + break; + case LLRP_TYPE_CUSTOM_MESSAGE: + proto_tree_add_item(tree, hf_llrp_vendor, tvb, offset, 4, ENC_BIG_ENDIAN); + break; + /* Some have no extra data expected */ + case LLRP_TYPE_KEEPALIVE: + case LLRP_TYPE_KEEPALIVE_ACK: + case LLRP_TYPE_CLOSE_CONNECTION: + case LLRP_TYPE_GET_ROSPECS: + case LLRP_TYPE_GET_SUPPORTED_VERSION: + break; + default: + /* We shouldn't be called if we don't already recognize the value */ + DISSECTOR_ASSERT_NOT_REACHED(); + }; +} + +/* Code to actually dissect the packets */ +static int +dissect_llrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti; + proto_tree *llrp_tree; + guint16 type; + guint32 len; + guint offset = 0; + + /* Check that there's enough data */ + if (tvb_reported_length(tvb) < LLRP_LEN_MIN) + return 0; + + /* Make entries in Protocol column and Info column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "LLRP"); + + col_set_str(pinfo->cinfo, COL_INFO, "LLRP Message"); + + type = tvb_get_ntohs(tvb, offset) & 0x03FF; + + col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", + val_to_str(type, message_types, "Unknown Type: %d")); + + if (tree) + { + ti = proto_tree_add_item(tree, proto_llrp, tvb, offset, -1, ENC_NA); + llrp_tree = proto_item_add_subtree(ti, ett_llrp); + + proto_tree_add_item(llrp_tree, hf_llrp_version, tvb, offset, 1, ENC_NA); + proto_tree_add_item(llrp_tree, hf_llrp_type, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + ti = proto_tree_add_item(llrp_tree, hf_llrp_length, tvb, offset, 4, ENC_BIG_ENDIAN); + len = tvb_get_ntohl(tvb, offset); + if (len > tvb_reported_length(tvb)) + { + expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, + "Incorrect length field: claimed %u, but only have %u.", + len, tvb_reported_length(tvb)); + } + offset += 4; + + proto_tree_add_item(llrp_tree, hf_llrp_id, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + if (match_strval(type, message_types)) + dissect_llrp_message(tvb, pinfo, llrp_tree, type, offset); + } + + return tvb_length(tvb); +} + +void +proto_register_llrp(void) +{ + /* Setup list of header fields See Section 1.6.1 for details*/ + static hf_register_info hf[] = { + { &hf_llrp_version, + { "Version", "llrp.version", FT_UINT8, BASE_DEC, VALS(llrp_versions), 0x1C, + "The protocol version number.", HFILL }}, + + { &hf_llrp_type, + { "Type", "llrp.type", FT_UINT16, BASE_DEC, VALS(message_types), 0x03FF, + "The type of message being carried.", HFILL }}, + + { &hf_llrp_length, + { "Length", "llrp.length", FT_UINT32, BASE_DEC, NULL, 0, + "The message length.", HFILL }}, + + { &hf_llrp_id, + { "ID", "llrp.id", FT_UINT32, BASE_DEC, NULL, 0, + "The message sequence number.", HFILL }}, + + { &hf_llrp_cur_ver, + { "Current Version", "llrp.cur_ver", FT_UINT8, BASE_DEC, VALS(llrp_versions), 0, + "The current protocol version.", HFILL }}, + + { &hf_llrp_sup_ver, + { "Supported Version", "llrp.sup_ver", FT_UINT8, BASE_DEC, VALS(llrp_versions), 0, + "The max supported protocol version.", HFILL }}, + + { &hf_llrp_req_cap, + { "Requested Capabilities", "llrp.req_cap", FT_UINT8, BASE_DEC, VALS(capabilities_request), 0, + "Which capabilities data was requested.", HFILL }}, + + { &hf_llrp_req_conf, + { "Requested Configuration", "llrp.req_conf", FT_UINT8, BASE_DEC, VALS(config_request), 0, + "Which configuration data was requested.", HFILL }}, + + { &hf_llrp_rospec, + { "ROSpec ID", "llrp.rospec", FT_UINT32, BASE_DEC, NULL, 0, + "The ID of the ROSpec.", HFILL }}, + + { &hf_llrp_antenna_id, + { "Antenna ID", "llrp.annena_id", FT_UINT16, BASE_DEC, NULL, 0, + "The ID of the antenna.", HFILL }}, + + { &hf_llrp_gpi_port, + { "GPI Port Number", "llrp.gpi_port", FT_UINT16, BASE_DEC, NULL, 0, + "The GPI port number.", HFILL }}, + + { &hf_llrp_gpo_port, + { "GOP Port Number", "llrp.gpo_port", FT_UINT16, BASE_DEC, NULL, 0, + "The GPO port number.", HFILL }}, + + { &hf_llrp_rest_fact, + { "Restore Factory Settings", "llrp.rest_fact", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80, + "Whether or not the receiver should restore factory settings.", HFILL }}, + + { &hf_llrp_accessspec, + { "Access Spec ID", "llrp.accessspec", FT_UINT32, BASE_DEC, NULL, 0, + "The access spec ID.", HFILL }}, + + { &hf_llrp_vendor, + { "Vendor ID", "llrp.vendor", FT_UINT32, BASE_DEC, NULL, 0, + "The access spec ID.", HFILL }}, + + { &hf_llrp_tlv_type, + { "Type", "llrp.tlv_type", FT_UINT16, BASE_DEC, VALS(tlv_type), 0x03FF, + "The type of TLV.", HFILL }}, + + { &hf_llrp_tv_type, + { "Type", "llrp.tv_type", FT_UINT8, BASE_DEC, VALS(tv_type), 0x7F, + "The type of TV.", HFILL }}, + + { &hf_llrp_tlv_len, + { "Length", "llrp.tlv_len", FT_UINT16, BASE_DEC, NULL, 0, + "The length of this TLV.", HFILL }}, + + { &hf_llrp_param, + { "Parameter", "llrp.param", FT_NONE, BASE_NONE, NULL, 0, + "A TLV or TV parameter.", HFILL }} + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_llrp, + &ett_llrp_param + }; + + /* Register the protocol name and description */ + proto_llrp = proto_register_protocol("Low Level Reader Protocol", + "LLRP", "llrp"); + + /* Required function calls to register the header fields and subtrees used */ + proto_register_field_array(proto_llrp, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + +void +proto_reg_handoff_llrp(void) +{ + dissector_handle_t llrp_handle; + + llrp_handle = new_create_dissector_handle(dissect_llrp, proto_llrp); + dissector_add_uint("tcp.port", LLRP_PORT, llrp_handle); +} + + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=4 expandtab: + * :indentSize=4:tabSize=4:noTabs=true: + */ |