wireshark/epan/dissectors/packet-knxnetip.c

1855 lines
85 KiB
C

/* packet-knxnetip.c
* Routines for KNXnet/IP dissection
* Copyright 2014, Alexander Gaertner <gaertner.alex@gmx.de>
*
* 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 <epan/packet.h>
#include <epan/expert.h>
#define KNXNETIP_PROTOCOL_VERSION 0x10
#define KNXNETIP_HEADER_LENGTH 0x06
#define SEARCH_REQ 0x0201
#define SEARCH_RES 0x0202
#define DESCRIPTION_REQ 0x0203
#define DESCRIPTION_RES 0x0204
#define CONNECT_REQ 0x0205
#define CONNECT_RES 0x0206
#define CONNECTIONSTATE_REQ 0x0207
#define CONNECTIONSTATE_RES 0x0208
#define DISCONNECT_REQ 0x0209
#define DISCONNECT_RES 0x020A
#define DEVICE_CONFIGURATION_REQ 0x0310
#define DEVICE_CONFIGURATION_ACK 0x0311
#define TUNNELLING_REQ 0x0420
#define TUNNELLING_ACK 0x0421
#define ROUTING_INDICATION 0x0530
#define ROUTING_LOST 0x0531
#define ROUTING_BUSY 0x0532
#define REMOTE_DIAG_REQ 0x0740
#define REMOTE_DIAG_RES 0x0741
#define REMOTE_BASIC_CONF_REQ 0x0742
#define REMOTE_RESET_REQ 0x0743
#define DIB_DEVICE_INFO 0x01
#define DIB_SUPP_SVC 0x02
#define DIB_IP_CONF 0x03
#define DIB_IP_CURRENT 0x04
#define DIB_KNX_ADDRESS 0x05
#define DIB_MFR_DATA 0xFE
#define KNX_TUNNEL_CONNECTION 0x04
#define FLAGS_DEVICESTATUS_RESERVED 0xFE
#define FLAGS_DEVICESTATUS_PROGRAM 0x01
#define FLAGS_IPCAPABILITES_RESERVED 0xF8
#define FLAGS_IPCAPABILITES_BOOTIP 0x01
#define FLAGS_IPCAPABILITES_DHCP 0x02
#define FLAGS_IPCAPABILITES_AUTOIP 0x04
#define FLAGS_DEVICESTATE_RESERVED 0xFC
#define FLAGS_DEVICESTATE_KNX 0x01
#define FLAGS_DEVICESTATE_IP 0x02
/*for CEMI*/
#define RAW_REQ 0x10
#define DATA_REQ 0x11
#define POLL_DATA_REQ 0x13
#define POLL_DATA_CON 0x25
#define DATA_IND 0x29
#define BUSMON_IND 0x2B
#define RAW_IND 0x2D
#define DATA_CON 0x2E
#define RAW_CON 0x2F
#define DATA_CONNEC_REQ 0x41
#define DATA_INDV_REQ 0x4A
#define DATA_CONNEC_IND 0x89
#define DATA_INDV_IND 0x94
#define RESET_IND 0xF0
#define RESET_REQ 0xF1
#define PROPWRITE_CON 0xF5
#define PROPWRITE_REQ 0xF6
#define PROPINFO_IND 0xF7
#define FUNCPROPCOM_REQ 0xF8
#define FUNCPROPSTATREAD_REQ 0xF9
#define FUNCPROPCOM_CON 0xFA
#define PROPREAD_CON 0xFB
#define PROPREAD_REQ 0xFC
#define PL_INFO 0x1
#define RF_INFO 0x2
#define BUSMON_INFO 0x3
#define TIME_REL 0x4
#define TIME_DELAY 0x5
#define EXEND_TIME 0x6
#define BIBAT_INFO 0x7
#define RF_MULTI 0x8
#define PREAMBEL 0x9
#define RF_FAST_ACK 0xA
#define MANU_DATA 0xFE
#define RESER 0xFF
#define A_GROUPVALUE_RES 0x040
#define A_GROUPVALUE_WRT 0x080
#define A_ADC_RED 0x180
#define A_ADC_RES 0x1C0
#define A_MEM_RED 0x200
#define A_MEM_RES 0x240
#define A_MEM_WRT 0x280
#define A_SYS_RED 0x1C8
#define A_SYS_RES 0x1C9
#define A_SYS_WRT 0x1CA
#define A_SYS_BROAD 0x1CB
#define GROUPADD 0x80
#define COUPLER_SPECIFIC_SERVICE 0x3C0
#define A_AUTHORIZE_REQ 0x3D1
#define A_AUTHORIZE_RES 0x3D2
#define A_KEY_WRT 0x3D3
#define A_KEY_RES 0x3D4
#define A_PROPVALUE_RED 0x3D5
#define A_PROPVALUE_RES 0x3D6
#define FLAGS_CEMI_CONTROL1_FT 0x80
#define FLAGS_CEMI_CONTROL1_R 0x20
#define FLAGS_CEMI_CONTROL1_SB 0x10
#define FLAGS_CEMI_CONTROL1_P 0x0C
#define FLAGS_CEMI_CONTROL1_A 0x02
#define FLAGS_CEMI_CONTROL1_C 0x01
#define FLAGS_CEMI_CONTROL2_AT 0x80
#define FLAGS_CEMI_CONTROL2_HC 0x70
#define FLAGS_CEMI_CONTROL2_EFF 0x0F
#define FLAGS_CEMI_RF_RESERVED 0xC0
#define FLAGS_CEMI_RF_MESURE 0x30
#define FLAGS_CEMI_RF_MESURE_RE 0x0C
#define FLAGS_CEMI_RF_BATTERY 0x02
#define FLAGS_CEMI_RF_BIDIRETIONAL 0x01
#define FLAGS_CEMI_BUS_F 0x80
#define FLAGS_CEMI_BUS_B 0x40
#define FLAGS_CEMI_BUS_P 0x20
#define FLAGS_CEMI_BUS_D 0x10
#define FLAGS_CEMI_BUS_L 0x08
#define FLAGS_CEMI_BUS_SSS 0x07
#define FLAGS_CEMI_FASTACK_CRC 0x400
#define FLAGS_CEMI_FASTACK_ERROR 0x200
#define FLAGS_CEMI_FASTACK_RES 0x100
#define FLAGS_CEMI_FASTACK_INFO 0xFF
void proto_register_knxnetip(void);
void proto_reg_handoff_knxnetip(void);
static int proto_knxnetip = -1;
static int hf_knxnetip_headerlength = -1;
static int hf_knxnetip_version = -1;
static int hf_knxnetip_servicetype = -1;
static int hf_knxnetip_totallength = -1;
static int hf_knxnetip_hpai = -1;
static int hf_knxnetip_hpai_structure_length = -1;
static int hf_knxnetip_hpai_host_protocol = -1;
static int hf_knxnetip_hpai_ip_address = -1;
static int hf_knxnetip_hpai_port = -1;
static int hf_knxnetip_dib = -1;
static int hf_knxnetip_structure_length = -1;
static int hf_knxnetip_dib_type = -1;
static int hf_knxnetip_dib_medium = -1;
static int hf_knxnetip_knxaddress = -1;
static int hf_knxnetip_dib_projectid = -1;
static int hf_knxnetip_dib_serialnumber = -1;
static int hf_knxnetip_dib_multicast_address = -1;
static int hf_knxnetip_mac_address = -1;
static int hf_knxnetip_dib_friendly = -1;
static int hf_knxnetip_dib_service = -1;
static int hf_knxnetip_dib_ipaddress = -1;
static int hf_knxnetip_dib_subnet = -1;
static int hf_knxnetip_dib_gateway = -1;
static int hf_knxnetip_dib_ipassign = -1;
static int hf_knxnetip_dib_dhcp = -1;
static int hf_knxnetip_dib_manuid = -1;
static int hf_knxnetip_dib_manudata = -1;
static int hf_knxnetip_cri = -1;
static int hf_knxnetip_connection_type = -1;
static int hf_knxnetip_cri_protocol_data = -1;
static int hf_knxnetip_communication_channel_id = -1;
static int hf_knxnetip_crd_protocol_data = -1;
static int hf_knxnetip_crd = -1;
static int hf_knxnetip_connect_status = -1;
static int hf_knxnetip_connectionstate_status = -1;
static int hf_knxnetip_counter = -1;
static int hf_knxnetip_confack_status = -1;
static int hf_knxnetip_tunnelack_status = -1;
static int hf_knxnetip_numberoflost = -1;
static int hf_knxnetip_busywaittime = -1;
static int hf_knxnetip_busycontrol = -1;
static int hf_knxnetip_knxlayer = -1;
static int hf_knxnetip_selector_type = -1;
static int hf_knxnetip_reset = -1;
static int hf_knxnetip_projectnumber = -1;
static int hf_knxnetip_installnumber = -1;
static int hf_knxnetip_dib_svc_version = -1;
static int hf_knxnetip_reserved = -1;
static int hf_knxnetip_raw = -1;
static int hf_knxnetip_data = -1;
static int hf_knxnetip_additional = -1;
static int hf_knxnetip_unknown = -1;
static int hf_knxnetip_polldata = -1;
static int hf_knxnetip_cemi = -1;
static int hf_knxnetip_cemi_mc = -1;
static int hf_knxnetip_cemi_addlength = -1;
static int hf_knxnetip_cemi_additemlength = -1;
static int hf_knxnetip_cemi_typid = -1;
static int hf_knxnetip_cemi_type_pl = -1;
static int hf_knxnetip_cemi_type_relt = -1;
static int hf_knxnetip_cemi_type_delay = -1;
static int hf_knxnetip_cemi_type_exttime = -1;
static int hf_knxnetip_cemi_type_bibat = -1;
static int hf_knxnetip_cemi_sourceaddress = -1;
static int hf_knxnetip_cemi_destaddress = -1;
static int hf_knxnetip_cemi_tpci = -1;
static int hf_knxnetip_cemi_counter = -1;
static int hf_knxnetip_cemi_npdu_length = -1;
static int hf_knxnetip_cemi_tpdu_length = -1;
static int hf_knxnetip_cemi_apci = -1;
static int hf_knxnetip_cemi_data = -1;
static int hf_knxnetip_cemi_numberofslots = -1;
static int hf_knxnetip_cemi_iot = -1;
static int hf_knxnetip_cemi_oi = -1;
static int hf_knxnetip_cemi_six = -1;
static int hf_knxnetip_cemi_pid = -1;
static int hf_knxnetip_cemi_reserved = -1;
static int hf_knxnetip_cemi_noe = -1;
static int hf_knxnetip_cemi_error = -1;
static int hf_knxnetip_cemi_return = -1;
static int hf_knxnetip_cemi_numberofelements = -1;
static int hf_knxnetip_cemi_apci_memory_number = -1;
static int hf_knxnetip_cemi_rf_lfn = -1;
static int hf_knxnetip_cemi_type_bibat_block = -1;
static int hf_knxnetip_cemi_type_rf_multi_fastack = -1;
static int hf_knxnetip_cemi_type_rf_multi_freq = -1;
static int hf_knxnetip_cemi_type_rf_multi_channel = -1;
static int hf_knxnetip_cemi_type_rf_multi_recep_freq = -1;
static int hf_knxnetip_cemi_rf_sn = -1;
static int hf_knxnetip_cemi_type_preamble_length = -1;
static int hf_knxnetip_cemi_type_postamble_length = -1;
static int hf_knxnetip_cemi_subfunction = -1;
static int hf_knxnetip_cemi_manuspecificdata = -1;
static int hf_knxnetip_cemi_apci_mem_address = -1;
static int hf_knxnetip_cemi_channel = -1;
static int hf_knxnetip_cemi_apci_key = -1;
static int hf_knxnetip_cemi_apci_level = -1;
static int hf_knxnetip_cemi_apci_object = -1;
static int hf_knxnetip_cemi_apci_propid = -1;
/*FLAGS
DIB Device Status Flags*/
static int hf_knxnetip_dib_status = -1;
static int hf_knxnetip_dib_status_flag_reserved = -1;
static int hf_knxnetip_dib_status_flag_program = -1;
static const int *dib_device_status_flags[] = {
&hf_knxnetip_dib_status_flag_reserved,
&hf_knxnetip_dib_status_flag_program,
NULL
};
/*DIB IP Capabilities Flags*/
static int hf_knxnetip_dib_ipcapa = -1;
static int hf_knxnetip_dib_ipcapa_flag_bootip = -1;
static int hf_knxnetip_dib_ipcapa_flag_dhcp = -1;
static int hf_knxnetip_dib_ipcapa_flag_autoip = -1;
static int hf_knxnetip_dib_ipcapa_flag_reserved = -1;
static const int *dib_ipcapabilities_flags[] = {
&hf_knxnetip_dib_ipcapa_flag_bootip,
&hf_knxnetip_dib_ipcapa_flag_dhcp,
&hf_knxnetip_dib_ipcapa_flag_autoip,
&hf_knxnetip_dib_ipcapa_flag_reserved,
NULL
};
/*Device State*/
static int hf_knxnetip_devicestate = -1;
static int hf_knxnetip_devicestate_reserved = -1;
static int hf_knxnetip_devicestate_knx = -1;
static int hf_knxnetip_devicestate_ip = -1;
static const int *devicestate_flags[] = {
&hf_knxnetip_devicestate_knx,
&hf_knxnetip_devicestate_ip,
&hf_knxnetip_devicestate_reserved,
NULL
};
/*cEMI FLAGS
controlfield 1*/
static int hf_knxnetip_cemi_controlfield1 = -1;
static int hf_knxnetip_cemi_flag_frametype = -1;
static int hf_knxnetip_cemi_flag_repeat = -1;
static int hf_knxnetip_cemi_flag_sb = -1;
static int hf_knxnetip_cemi_flag_priority = -1;
static int hf_knxnetip_cemi_flag_ack = -1;
static int hf_knxnetip_cemi_flag_confirm = -1;
static const int *cemi_control1_flags[] = {
&hf_knxnetip_cemi_flag_frametype,
&hf_knxnetip_cemi_flag_repeat,
&hf_knxnetip_cemi_flag_sb,
&hf_knxnetip_cemi_flag_priority,
&hf_knxnetip_cemi_flag_ack,
&hf_knxnetip_cemi_flag_confirm,
NULL
};
/*controlfield 2*/
static int hf_knxnetip_cemi_controlfield2 = -1;
static int hf_knxnetip_flag_destaddress = -1;
static int hf_knxnetip_flag_hop = -1;
static int hf_knxnetip_flag_eff = -1;
static const int *cemi_control2_flags[] = {
&hf_knxnetip_flag_destaddress,
&hf_knxnetip_flag_hop,
&hf_knxnetip_flag_eff,
NULL
};
static int hf_knxnetip_cemi_type_rf_info = -1;
static int hf_knxnetip_cemi_type_rf_reserved = -1;
static int hf_knxnetip_cemi_type_rf_mesure = -1;
static int hf_knxnetip_cemi_type_rf_mesure_re = -1;
static int hf_knxnetip_cemi_type_rf_battery = -1;
static int hf_knxnetip_cemi_type_rf_bidirekt = -1;
static const int *cemi_rf_info[] = {
&hf_knxnetip_cemi_type_rf_reserved,
&hf_knxnetip_cemi_type_rf_mesure,
&hf_knxnetip_cemi_type_rf_mesure_re,
&hf_knxnetip_cemi_type_rf_battery,
&hf_knxnetip_cemi_type_rf_bidirekt,
NULL
};
static int hf_knxnetip_cemi_type_bus = -1;
static int hf_knxnetip_cemi_type_bus_flag_f = -1;
static int hf_knxnetip_cemi_type_bus_flag_b = -1;
static int hf_knxnetip_cemi_type_bus_flag_p = -1;
static int hf_knxnetip_cemi_type_bus_flag_d = -1;
static int hf_knxnetip_cemi_type_bus_flag_l = -1;
static int hf_knxnetip_cemi_type_bus_flag_sss = -1;
static const int *cemi_bus_flags[] = {
&hf_knxnetip_cemi_type_bus_flag_f,
&hf_knxnetip_cemi_type_bus_flag_b,
&hf_knxnetip_cemi_type_bus_flag_p,
&hf_knxnetip_cemi_type_bus_flag_d,
&hf_knxnetip_cemi_type_bus_flag_l,
&hf_knxnetip_cemi_type_bus_flag_sss,
NULL
};
static int hf_knxnetip_cemi_type_fastack = -1;
static int hf_knxnetip_cemi_type_fastack_crc = -1;
static int hf_knxnetip_cemi_type_fastack_error = -1;
static int hf_knxnetip_cemi_type_fastack_received = -1;
static int hf_knxnetip_cemi_type_fastack_info = -1;
static const int *cemi_fastack_flags[] = {
&hf_knxnetip_cemi_type_fastack_crc,
&hf_knxnetip_cemi_type_fastack_error,
&hf_knxnetip_cemi_type_fastack_received,
&hf_knxnetip_cemi_type_fastack_info,
NULL
};
static const value_string knxnetip_service_identifier[] = {
{ SEARCH_REQ, "SEARCH_REQUEST" },
{ SEARCH_RES, "SEARCH_RESPONSE" },
{ DESCRIPTION_REQ, "DESCRIPTION_REQUEST" },
{ DESCRIPTION_RES, "DESCRIPTION_RESPONSE" },
{ CONNECT_REQ, "CONNECT_REQUEST" },
{ CONNECT_RES, "CONNECT_RESPONSE" },
{ CONNECTIONSTATE_REQ, "CONNECTIONSTATE_REQUEST" },
{ CONNECTIONSTATE_RES, "CONNECTIONSTATE_RESPONSE" },
{ DISCONNECT_REQ, "DISCONNECT_REQUEST" },
{ DISCONNECT_RES, "DISCONNECT_RESPONSE" },
{ DEVICE_CONFIGURATION_REQ, "DEVICE_CONFIGURATION_REQUEST" },
{ DEVICE_CONFIGURATION_ACK, "DEVICE_CONFIGURATION_ACK" },
{ TUNNELLING_REQ, "TUNNELLING_REQUEST" },
{ TUNNELLING_ACK, "TUNNELING_ACK" },
{ ROUTING_INDICATION, "ROUTING_INDICATION" },
{ ROUTING_LOST, "ROUTING_LOST_MESSAGE" },
{ ROUTING_BUSY, "ROUTING_BUSY" },
{ REMOTE_DIAG_REQ, "REMOTE_DIAGNOSTIC_REQUEST" },
{ REMOTE_DIAG_RES, "REMOTE_DIAGNOSTIC_RESPONSE" },
{ REMOTE_BASIC_CONF_REQ, "REMOTE_BASIC_CONFIGURATION_REQUEST" },
{ REMOTE_RESET_REQ, "REMOTE_RESET_REQUEST" },
{ 0, NULL }
};
static const value_string knxnetip_service_types[] = {
{ 0x02, "KNXnet/IP Core" },
{ 0x03, "KNXnet/IP Device Management" },
{ 0x04, "KNXnet/IP Tunneling" },
{ 0x05, "KNXnet/IP Routing" },
{ 0x06, "KNXnet/IP Remote Logging" },
{ 0x07, "KNXnet/IP Remote Configuration and Diagnosis" },
{ 0x08, "KNXnet/IP Object Server" },
{ 0, NULL }
};
static const value_string knxnetip_connection_types[] = {
{ 0x03, "DEVICE_MGMT_CONNECTION" },
{ 0x04, "TUNNEL_CONNECTION" },
{ 0x06, "REMLOG_CONNECTION" },
{ 0x07, "REMCONF_CONNECTION" },
{ 0x08, "OBJSVR_CONNECTION" },
{ 0, NULL }
};
static const value_string knxnetip_connect_response_status_codes[] = {
{ 0x00, "E_NO_ERROR - The connection was established successfully" },
{ 0x22, "E_CONNECTION_TYPE - The KNXnet/IP server device does not support the requested connection type" },
{ 0x23, "E_CONNECTION_OPTION - The KNXnet/IP server device does not support one or more requested connection options" },
{ 0x24, "E_NO_MORE_CONNECTIONS - The KNXnet/IP server device could not accept the new data connection (busy)" },
{ 0, NULL }
};
static const value_string knxnetip_connectionstate_response_status_codes[] = {
{ 0x00, "E_NO_ERROR - The connection state is normal" },
{ 0x21, "E_CONNECTION_ID - The KNXnet/IP server device could not find an active data connection with the specified ID" },
{ 0x26, "E_DATA_CONNECTION - The KNXnet/IP server device detected an error concerning the data connection with the specified ID" },
{ 0x27, "E_KNX_CONNECTION - The KNXnet/IP server device detected an error concerning the EIB bus / KNX subsystem connection with the specified ID" },
{ 0, NULL }
};
static const value_string knxnetip_tunneling_error_codes[] = {
{ 0x00, "E_NO_ERROR - The message was received successfully" },
{ 0x29, "E_TUNNELLING_LAYER - The KNXnet/IP server device does not support the requested tunnelling layer" },
{ 0, NULL }
};
static const value_string knxnetip_device_configuration_ack_status_codes[] = {
{ 0x00, "E_NO_ERROR - The message was received successfully" },
{ 0, NULL }
};
static const value_string knxnetip_dib_description_type_codes[] = {
{ DIB_DEVICE_INFO, "DEVICE_INFO" },
{ DIB_SUPP_SVC, "SUPP_SVC_FAMILIES" },
{ DIB_IP_CONF, "IP_CONFIG" },
{ DIB_IP_CURRENT, "IP_CUR_CONFIG" },
{ DIB_KNX_ADDRESS, "KNX_ADDRESSES" },
{ DIB_MFR_DATA, "MFR_DATA" },
{ 0, NULL }
};
static const value_string knxnetip_dib_medium_codes[] = {
{ 0x01, "reserved" },
{ 0x02, "KNX TP" },
{ 0x04, "KNX PL110" },
{ 0x08, "reserved" },
{ 0x10, "KNX RF" },
{ 0x20, "KNX IP" },
{ 0, NULL }
};
static const value_string knxnetip_host_protocol_codes[] = {
{ 0x01, "IPV4_UDP" },
{ 0x02, "IPV4_TCP" },
{ 0, NULL }
};
static const value_string knxnetip_ip_assignment_method[] = {
{ 0x01, "manuell" },
{ 0x02, "BootP" },
{ 0x04, "DHCP" },
{ 0x08, "AutoIP" },
{ 0, NULL }
};
static const value_string knxnetip_knxlayer_values[] = {
{ 0x02, "TUNNEL_LINKLAYER" },
{ 0x04, "TUNNEL_RAW"},
{ 0x80, "TUNNEL_BUSMONITOR"},
{ 0, NULL}
};
static const value_string knxnetip_selector_types[] = {
{ 0x01, "PrgMode Selector" },
{ 0x02, "MAC Selector" },
{ 0, NULL }
};
static const value_string knxnetip_reset_codes[] = {
{ 0x01, "Restart" },
{ 0x02, "Master Reset" },
{ 0, NULL }
};
/*for CEMI*/
static const value_string cemi_messagecodes[] = {
{ RAW_REQ, "L_Raw.req"},
{ DATA_REQ, "L_Data.req"},
{ POLL_DATA_REQ, "L_Poll_Data.req"},
{ POLL_DATA_CON, "L_Poll_Data.con"},
{ DATA_IND, "L_Data.ind"},
{ BUSMON_IND, "L_Busmon.ind"},
{ RAW_IND, "L_Raw.ind"},
{ DATA_CON, "L_Data.con"},
{ RAW_CON, "L_Raw.con"},
{ DATA_CONNEC_REQ, "T_Data_Connected.req"},
{ DATA_INDV_REQ, "T_Data_Individual.req"},
{ DATA_CONNEC_IND, "T_Data_Connected.ind"},
{ DATA_INDV_IND, "T_Data_Individual.ind"},
{ RESET_IND, "M_Reset.ind"},
{ RESET_REQ, "M_Reset.req"},
{ PROPWRITE_CON, "M_PropWrite.con"},
{ PROPWRITE_REQ, "M_PropWrite.req"},
{ PROPINFO_IND, "M_PropInfo.ind"},
{ FUNCPROPCOM_REQ, "M_FuncPropCommand.req"},
{ FUNCPROPSTATREAD_REQ, "M_FuncPropStateRead.req"},
{ FUNCPROPCOM_CON, "M_FuncPropCommand/StateRead.con"},
{ PROPREAD_CON, "M_PropRead.con"},
{ PROPREAD_REQ, "M_PropRead.req"},
{ 0, NULL }
};
static const value_string cemi_add_type_id[] = {
{ 0x00, "reserved" },
{ PL_INFO, "PL Info"},
{ RF_INFO, "RF Info"},
{ BUSMON_INFO, "Busmonitor Info"},
{ TIME_REL, "relative timestamp"},
{ TIME_DELAY, "time delay until send"},
{ EXEND_TIME, "extended relative timestamp"},
{ BIBAT_INFO, "BiBat information"},
{ RF_MULTI, "RF Multi information"},
{ PREAMBEL, "Preamble and postamble"},
{ RF_FAST_ACK, "RF Fast Ack information"},
{ MANU_DATA, "Manufacturer specific data"},
{ RESER, "reserved"},
{ 0, NULL}
};
static const value_string cemi_tpci_vals[] = {
{ 0x0, "UDT (Unnumbered Data Packet)" },
{ 0x2, "UCD (Unnumbered)"},
{ 0x1, "NDT (Numbered Data Packet)"},
{ 0x3, "NCD (Numbered Control Data)"},
{ 0, NULL}
};
static const value_string cemi_apci_codes[] = {
{ 0x000, "A_GroupValue_Read" },
{ 0x001, "A_GroupValue_Response"},
{ 0x002, "A_GroupValue_Write"},
{ 0x0C0, "A_IndividualAddress_Write"},
{ 0x100, "A_IndividualAddress_Read"},
{ 0x140, "A_IndividualAddress_Response"},
{ 0x006, "A_ADC_Read"},
{ 0x1C0, "A_ADC_Response"},
{ 0x1C4, "A_SystemNetworkParameter_Read"},
{ 0x1C9, "A_SystemNetworkParameter_Response"},
{ 0x1CA, "A_SystemNetworkParameter_Write"},
{ 0x020, "A_Memory_Read"},
{ 0x024, "A_Memory_Response"},
{ 0x028, "A_Memory_Write"},
{ 0x2C0, "A_UserMemory_Read"},
{ 0x2C1, "A_UserMemory_Response"},
{ 0x2C2, "A_UserMemory_Write"},
{ 0x2C5, "A_UserManufacturerInfo_Read"},
{ 0x2C6, "A_UserManufacturerInfo_Response"},
{ 0x2C7, "A_FunctionPropertyCommand"},
{ 0x2C8, "A_FunctionPropertyState_Read"},
{ 0x2C9, "A_FunctionPropertyState_Response"},
{ 0x300, "A_DeviceDescriptor_Read"},
{ 0x340, "A_DeviceDescriptor_Response"},
{ 0x380, "A_Restart"},
{ 0x3D1, "A_Authorize_Request"},
{ 0x3D2, "A_Authorize_Response"},
{ 0x3D3, "A_Key_Write"},
{ 0x3D4, "A_Key_Response"},
{ 0x3D5, "A_PropertyValue_Read"},
{ 0x3D6, "A_PropertyValue_Response"},
{ 0x3D7, "A_PropertyValue_Write"},
{ 0x3D8, "A_PropertyDescription_Read"},
{ 0x3D9, "A_PropertyDescription_Response"},
{ 0x3DA, "A_NetworkParameter_Read"},
{ 0x3DB, "A_NetworkParameter_Response"},
{ 0x3DC, "A_IndividualAddressSerialNumber_Read"},
{ 0x3DD, "A_IndividualAddressSerialNumber_Response"},
{ 0x3DF, "A_IndividualAddressSerialNumber_Write"},
{ 0x3E0, "A_DomainAddress_Write"},
{ 0x3E1, "A_DomainAddress_Read"},
{ 0x3E2, "A_DomainAddress_Response"},
{ 0x3E3, "A_DomainAddressSelective_Read"},
{ 0x3E4, "A_NetworkParameter_Write"},
{ 0x3E5, "A_Link_Read"},
{ 0x3E6, "A_Link_Response"},
{ 0x3E7, "A_Link_Write"},
{ 0x3E8, "A_GroupPropValue_Read"},
{ 0x3E9, "A_GroupPropValue_Response"},
{ 0x3EA, "A_GroupPropValue_Write"},
{ 0x3EB, "A_GroupPropValue_InfoReport"},
{ 0x3EC, "A_DomainAddressSerialNumber_Read"},
{ 0x3ED, "A_DomainAddressSerialNumber_Response"},
{ 0x3EE, "A_DomainAddressSerialNumber_Write"},
{ 0x3F0, "A_FileStream_InforReport"},
{ 0, NULL}
};
static const value_string cemi_propertyid[] = {
{ 1, "PID_OBJECT_TYPE" },
{ 8, "PID_SERVICE_CONTROL" },
{ 9, "PID_FIRMWARE_REVISION" },
{ 11, "PID_SERIAL_NUMBER" },
{ 12, "PID_MANUFACTURER_ID" },
{ 14, "PID_DEVICE_CONTROL" },
{ 19, "PID_MANUFACTURE_DATA" },
{ 51, "PID_ROUTING_COUNT" },
{ 52, "PID_MAX_RETRY_COUNT " },
{ 53, "PID_ERROR_FLAGS" },
{ 54, "PID_PROGMODE" },
{ 56, "PID_MAX_APDULENGTH" },
{ 57, "PID_SUBNET_ADDR" },
{ 58, "PID_DEVICE_ADDR" },
{ 59, "PID_PB_CONFIG" },
{ 60, "PID_ADDR_REPORT" },
{ 61, "PID_ADDR_CHECK" },
{ 62, "PID_OBJECT_VALUE" },
{ 63, "PID_OBJECTLINK" },
{ 64, "PID_APPLICATION" },
{ 65, "PID_PARAMETER" },
{ 66, "PID_OBJECTADDRESS" },
{ 67, "PID_PSU_TYPE" },
{ 68, "PID_PSU_STATUS" },
{ 70, "PID_DOMAIN_ADDR"},
{ 71, "PID_IO_LIST"},
{ 0, NULL }
};
static const value_string cemi_error_codes[] = {
{ 0x00, "Unspecified Error"},
{ 0x01, "Out of range"},
{ 0x02, "Out of maxrange"},
{ 0x03, "Out of minrange"},
{ 0x04, "Memory Error"},
{ 0x05, "Read only"},
{ 0x06, "Illegal command"},
{ 0x07, "Void DP"},
{ 0x08, "Type conflict"},
{ 0x09, "Prop. Index range error"},
{ 0x0A, "Value temporarily not writeable"},
{ 0, NULL }
};
static const value_string cemi_bibat_ctrl[] = {
{ 0x0, "asynchr. RF frame"},
{ 0x1, "Fast_ACK"},
{ 0x4, "synchronous L_Data frames"},
{ 0x5, "Sync frame"},
{ 0x6, "Help Call"},
{ 0x7, "Help Call Response"},
{ 0, NULL }
};
static gint ett_knxnetip = -1;
static gint ett_knxnetip_header = -1;
static gint ett_knxnetip_body = -1;
static gint ett_knxnetip_hpai = -1;
static gint ett_knxnetip_dib = -1;
static gint ett_knxnetip_dib_projectid = -1;
static gint ett_knxnetip_dib_service = -1;
static gint ett_knxnetip_cri = -1;
static gint ett_knxnetip_crd = -1;
static gint ett_knxnetip_dib_status = -1;
static gint ett_knxnetip_dib_ipcapa = -1;
static gint ett_knxnetip_devicestate = -1;
static gint ett_knxnetip_cemi = -1;
static gint ett_knxnetip_cemi_additional = -1;
static gint ett_knxnetip_cemi_additional_item = -1;
static gint ett_knxnetip_cemi_control1 = -1;
static gint ett_knxnetip_cemi_control2 = -1;
static gint ett_knxnetip_cemi_rf_info = -1;
static gint ett_knxnetip_cemi_bus_info = -1;
static gint ett_knxnetip_cemi_fastack = -1;
static expert_field ei_knxnetip_length = EI_INIT;
static void dissect_hpai(tvbuff_t *tvb, guint32 *offset, proto_tree *insert_tree, const char *append_text) {
proto_item *hpai_item;
proto_tree *hpai_tree;
hpai_item = proto_tree_add_item( insert_tree, hf_knxnetip_hpai, tvb, *offset, 8, ENC_NA );
hpai_tree = proto_item_add_subtree(hpai_item, ett_knxnetip_hpai);
proto_item_append_text(hpai_item, "%s", append_text);
proto_tree_add_item(hpai_tree, hf_knxnetip_hpai_structure_length, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(hpai_tree, hf_knxnetip_hpai_host_protocol, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(hpai_tree, hf_knxnetip_hpai_ip_address, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset+=4;
proto_tree_add_item(hpai_tree, hf_knxnetip_hpai_port, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset+=2;
}
static gboolean dissect_dib(tvbuff_t *tvb, guint32 *offset, proto_tree *insert_tree) {
proto_item *dib_item = NULL;
proto_item *projectid_item = NULL;
proto_item *service_item = NULL;
proto_tree *dib_tree = NULL;
proto_tree *projectid_tree = NULL;
proto_tree *service_tree = NULL;
guint8 i;
guint8 dib_type;
guint8 length;
guint16 knx_address;
guint16 install_id;
length = tvb_get_guint8(tvb, *offset);
dib_item = proto_tree_add_item(insert_tree, hf_knxnetip_dib, tvb, *offset, length, ENC_NA);
dib_tree = proto_item_add_subtree(dib_item, ett_knxnetip_dib);
proto_tree_add_item(dib_tree, hf_knxnetip_structure_length, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(dib_tree, hf_knxnetip_dib_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
dib_type = tvb_get_guint8(tvb, *offset);
proto_item_append_text(dib_item, ": %s", val_to_str_const(dib_type, knxnetip_dib_description_type_codes, "Unknown Type"));
*offset+=1;
switch (dib_type){
case(DIB_DEVICE_INFO):
proto_tree_add_item(dib_tree, hf_knxnetip_dib_medium, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_bitmask(dib_tree, tvb, *offset, hf_knxnetip_dib_status, ett_knxnetip_dib_status, dib_device_status_flags, ENC_BIG_ENDIAN);
*offset+=1;
knx_address = tvb_get_ntohs(tvb, *offset);
proto_tree_add_uint_format(dib_tree, hf_knxnetip_knxaddress, tvb, *offset, 2, knx_address, "KNX Address %d.%d.%d", ((knx_address & 0xF000)>>12),((knx_address & 0x0F00)>>8),(knx_address & 0xFF));
*offset+=2;
projectid_item = proto_tree_add_item(dib_tree, hf_knxnetip_dib_projectid, tvb, *offset, 2, ENC_BIG_ENDIAN);
projectid_tree = proto_item_add_subtree(projectid_item, ett_knxnetip_dib_projectid);
install_id = tvb_get_ntohs(tvb, *offset);
proto_tree_add_uint_format(projectid_tree, hf_knxnetip_projectnumber, tvb, *offset, 2, install_id, "Project number %d", (install_id & 0xFFF0)>>4);
proto_tree_add_uint_format(projectid_tree, hf_knxnetip_installnumber, tvb, *offset, 2, install_id, "Installation number %d", (install_id & 0xF));
*offset+=2;
proto_tree_add_item(dib_tree, hf_knxnetip_dib_serialnumber, tvb, *offset, 6, ENC_NA);
*offset+=6;
proto_tree_add_item(dib_tree, hf_knxnetip_dib_multicast_address, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset+=4;
proto_tree_add_item(dib_tree, hf_knxnetip_mac_address, tvb, *offset, 6, ENC_NA);
*offset+=6;
proto_tree_add_item(dib_tree, hf_knxnetip_dib_friendly, tvb, *offset, 30, ENC_ASCII|ENC_NA );
*offset+=30;
break;
case(DIB_SUPP_SVC):
if (length > 4) {
length-=4;
} else {
return TRUE;
}
for (i = 0; i <= length; i+=2) {
service_item = proto_tree_add_item(dib_tree, hf_knxnetip_dib_service, tvb, *offset, 1, ENC_BIG_ENDIAN);
service_tree = proto_item_add_subtree(service_item, ett_knxnetip_dib_service);
*offset+=1;
proto_tree_add_item(service_tree, hf_knxnetip_dib_svc_version, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
}
break;
case(DIB_IP_CONF):
proto_tree_add_item(dib_tree, hf_knxnetip_dib_ipaddress, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset+=4;
proto_tree_add_item(dib_tree, hf_knxnetip_dib_subnet, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset+=4;
proto_tree_add_item(dib_tree, hf_knxnetip_dib_gateway, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset+=4;
proto_tree_add_bitmask(dib_tree, tvb, *offset, hf_knxnetip_dib_ipcapa, ett_knxnetip_dib_ipcapa, dib_ipcapabilities_flags, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(dib_tree, hf_knxnetip_dib_ipassign, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
break;
case(DIB_IP_CURRENT):
proto_tree_add_item(dib_tree, hf_knxnetip_dib_ipaddress, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset+=4;
proto_tree_add_item(dib_tree, hf_knxnetip_dib_subnet, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset+=4;
proto_tree_add_item(dib_tree, hf_knxnetip_dib_gateway, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset+=4;
proto_tree_add_item(dib_tree, hf_knxnetip_dib_dhcp, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset+=4;
proto_tree_add_item(dib_tree, hf_knxnetip_dib_ipassign, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(dib_tree, hf_knxnetip_reserved, tvb, *offset, 1, ENC_NA);
*offset+=1;
break;
case(DIB_KNX_ADDRESS):
if (length > 4) {
length-=4;
} else {
return TRUE;
}
for (i = 0; i <= length; i+=2) {
knx_address = tvb_get_ntohs(tvb, *offset);
proto_tree_add_uint_format(dib_tree, hf_knxnetip_knxaddress, tvb, *offset, 2, knx_address, "KNX Address %d.%d.%d", ((knx_address & 0xF000)>>12),((knx_address & 0x0F00)>>8),(knx_address & 0xFF));
*offset+=2;
}
break;
case(DIB_MFR_DATA):
if (length > 4) {
length-=4;
} else {
return TRUE;
}
proto_tree_add_item(dib_tree, hf_knxnetip_dib_manuid, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset+=2;
proto_tree_add_item(dib_tree, hf_knxnetip_dib_manudata, tvb, *offset, length, ENC_ASCII|ENC_NA);
*offset+=length;
break;
}
return FALSE;
}
static guint dissect_cri(tvbuff_t *tvb, guint32 offset, proto_tree *insert_tree) {
proto_item *cri_item = NULL;
proto_tree *cri_tree = NULL;
guint8 length;
length = tvb_get_guint8(tvb ,offset);
cri_item = proto_tree_add_item(insert_tree, hf_knxnetip_cri, tvb, offset, length, ENC_NA);
cri_tree = proto_item_add_subtree(cri_item, ett_knxnetip_cri);
proto_tree_add_item(cri_tree, hf_knxnetip_structure_length, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_item(cri_tree, hf_knxnetip_connection_type, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
if (tvb_get_guint8(tvb,offset-1)== KNX_TUNNEL_CONNECTION ){
proto_tree_add_item(cri_tree, hf_knxnetip_knxlayer, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_item(cri_tree, hf_knxnetip_reserved, tvb, offset, 1, ENC_NA);
offset+=1;
}
else if (length > 2) {
proto_tree_add_item(cri_tree, hf_knxnetip_cri_protocol_data, tvb, offset, (length-2), ENC_NA);
offset+=(length-2);
}
return offset;
}
static void dissect_crd(tvbuff_t *tvb, guint32 *offset, proto_tree *insert_tree) {
proto_item *crd_item = NULL;
proto_tree *crd_tree = NULL;
guint8 length;
guint16 knx_address;
length = tvb_get_guint8(tvb, *offset);
crd_item = proto_tree_add_item(insert_tree, hf_knxnetip_crd, tvb, *offset, length, ENC_NA);
crd_tree = proto_item_add_subtree(crd_item, ett_knxnetip_crd);
proto_tree_add_item(crd_tree, hf_knxnetip_structure_length, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(crd_tree, hf_knxnetip_connection_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
if (tvb_get_guint8(tvb, *offset-1) == KNX_TUNNEL_CONNECTION){
knx_address = tvb_get_ntohs(tvb, *offset);
proto_tree_add_uint_format(crd_tree, hf_knxnetip_knxaddress, tvb, *offset, 2, knx_address, "KNX Address %d.%d.%d", ((knx_address & 0xF000)>>12),((knx_address & 0x0F00)>>8),(knx_address & 0xFF));
*offset+=2;
}
else if (length > 2) {
proto_tree_add_item(crd_tree, hf_knxnetip_crd_protocol_data, tvb, *offset, (length-2), ENC_NA);
*offset+=(length-2);
}
}
static guint dissect_connection_header(tvbuff_t *tvb, guint32 offset, proto_tree *insert_tree, gboolean have_status) {
proto_tree_add_item(insert_tree, hf_knxnetip_structure_length, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_item(insert_tree, hf_knxnetip_communication_channel_id, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_item(insert_tree, hf_knxnetip_counter, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
if (have_status == FALSE){
proto_tree_add_item(insert_tree, hf_knxnetip_reserved, tvb, offset, 1, ENC_NA);
offset+=1;
}
return offset;
}
static guint dissect_selector(tvbuff_t *tvb, guint32 offset, proto_tree *insert_tree){
proto_tree_add_item(insert_tree, hf_knxnetip_structure_length, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_item(insert_tree, hf_knxnetip_selector_type, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
if (tvb_get_guint8(tvb, offset-1)==0x02){
proto_tree_add_item(insert_tree, hf_knxnetip_mac_address, tvb, offset, 6, ENC_NA);
offset+=6;
}
return offset;
}
static void dissect_apci(tvbuff_t *tvb, guint32 *offset, proto_tree *insert_tree, gboolean tpdu){
guint16 type;
guint16 sub_type;
guint8 length;
length = tvb_get_guint8(tvb, *offset-1);
if (tpdu == TRUE){
proto_tree_add_item(insert_tree, hf_knxnetip_cemi_reserved, tvb, *offset, 1, ENC_BIG_ENDIAN);
}
else {
proto_tree_add_item(insert_tree, hf_knxnetip_cemi_tpci, tvb, *offset, 1, ENC_BIG_ENDIAN);
type = (tvb_get_guint8(tvb, *offset)&0xC0);
if (type == 0x40 || type == 0xC0){
proto_tree_add_item(insert_tree, hf_knxnetip_cemi_counter, tvb, *offset, 1, ENC_BIG_ENDIAN);
}
}
if (length != 0) {
type = (tvb_get_ntohs(tvb, *offset) & 0x03C0);
switch (type){
case(A_ADC_RED):
case(A_ADC_RES):
type = (tvb_get_ntohs(tvb, *offset) & 0x1FF);
if (type == A_SYS_RED || type == A_SYS_RES || type == A_SYS_WRT || type == A_SYS_BROAD){
proto_tree_add_bits_item(insert_tree, hf_knxnetip_cemi_apci, tvb, (*offset*8)+6, 10, ENC_BIG_ENDIAN);
}
else {
proto_tree_add_bits_item(insert_tree, hf_knxnetip_cemi_apci, tvb, (*offset*8)+6, 4, ENC_BIG_ENDIAN);
proto_tree_add_bits_item(insert_tree, hf_knxnetip_cemi_channel, tvb, (*offset*8)+10, 6, ENC_BIG_ENDIAN);
}
*offset+=2;
break;
case(A_GROUPVALUE_RES):
case(A_GROUPVALUE_WRT):
proto_tree_add_bits_item(insert_tree, hf_knxnetip_cemi_apci, tvb, (*offset*8)+6, 4, ENC_BIG_ENDIAN);
if (length == 1){
proto_tree_add_bits_item(insert_tree, hf_knxnetip_cemi_data, tvb, (*offset*8)+10, 6, ENC_BIG_ENDIAN);
}
*offset+=2;
break;
case(A_MEM_RED):
case(A_MEM_RES):
case(A_MEM_WRT):
proto_tree_add_bits_item(insert_tree, hf_knxnetip_cemi_apci, tvb, (*offset*8)+6, 6, ENC_BIG_ENDIAN);
proto_tree_add_bits_item(insert_tree, hf_knxnetip_cemi_apci_memory_number, tvb, (*offset*8)+12, 4, ENC_BIG_ENDIAN);
*offset+=2;
proto_tree_add_item(insert_tree, hf_knxnetip_cemi_apci_mem_address, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset+=2;
break;
case(COUPLER_SPECIFIC_SERVICE):
sub_type = (tvb_get_ntohs(tvb, *offset) & 0x3FF);
proto_tree_add_bits_item(insert_tree, hf_knxnetip_cemi_apci, tvb, (*offset*8)+6, 10, ENC_BIG_ENDIAN);
*offset+=2;
switch(sub_type){
case(A_AUTHORIZE_REQ):
case(A_KEY_WRT):
proto_tree_add_item(insert_tree, hf_knxnetip_reserved, tvb, *offset, 1, ENC_NA);
*offset+=1;
proto_tree_add_item(insert_tree, hf_knxnetip_cemi_apci_key, tvb, *offset, 4, ENC_NA);
*offset+=4;
break;
case(A_AUTHORIZE_RES):
case(A_KEY_RES):
proto_tree_add_item(insert_tree, hf_knxnetip_cemi_apci_level, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
break;
case(A_PROPVALUE_RED):
case(A_PROPVALUE_RES):
proto_tree_add_item(insert_tree, hf_knxnetip_cemi_apci_object, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(insert_tree, hf_knxnetip_cemi_apci_propid, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(insert_tree, hf_knxnetip_cemi_noe, tvb, *offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(insert_tree, hf_knxnetip_cemi_six, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset+=2;
}
break;
default:
proto_tree_add_bits_item(insert_tree, hf_knxnetip_cemi_apci, tvb, (*offset*8)+6, 10, ENC_BIG_ENDIAN);
*offset+=2;
}
if (length >= 1){
length-=1;
}
if (length >= 1 && (tvb_reported_length_remaining(tvb, *offset) > 0)){
proto_tree_add_item(insert_tree, hf_knxnetip_data, tvb, *offset, -1, ENC_NA);
*offset+=length;
}
}
else {
*offset+=1;
}
}
static gboolean dissect_cemi(tvbuff_t *tvb, guint32 *offset, proto_tree *insert_tree, packet_info *pinfo){
proto_item *cemi_item = NULL;
proto_item *additional_item = NULL;
proto_item *additional_info = NULL;
proto_tree *cemi_tree = NULL;
proto_tree *additional_tree = NULL;
proto_tree *additional_subtree = NULL;
guint8 i;
guint8 messagecode;
guint8 length;
guint8 type_id;
guint8 noe;
guint8 num_of_octets;
guint16 knx_address;
guint16 six;
cemi_item = proto_tree_add_item(insert_tree, hf_knxnetip_cemi, tvb, *offset, -1, ENC_NA);
cemi_tree = proto_item_add_subtree(cemi_item, ett_knxnetip_cemi);
messagecode = tvb_get_guint8(tvb, *offset);
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_mc, tvb, *offset, 1, ENC_BIG_ENDIAN);
col_append_fstr(pinfo->cinfo, COL_INFO, "| cEMI: %s", val_to_str(messagecode, cemi_messagecodes, "Unknown MC:0x%0x"));
*offset+=1;
/*check if M_ Message*/
if ((messagecode & 0xF0) < 0xF0){
length = tvb_get_guint8(tvb, *offset);
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_addlength, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
if (length != 0){
additional_info = proto_tree_add_item(cemi_tree, hf_knxnetip_additional, tvb, *offset, length, ENC_NA);
additional_tree = proto_item_add_subtree(additional_info, ett_knxnetip_cemi_additional);
do {
type_id = tvb_get_guint8(tvb, *offset);
additional_item = proto_tree_add_item(additional_tree, hf_knxnetip_cemi_typid, tvb, *offset, 1, ENC_BIG_ENDIAN);
additional_subtree = proto_item_add_subtree(additional_item, ett_knxnetip_cemi_additional_item);
*offset+=1;
proto_tree_add_item(additional_item, hf_knxnetip_cemi_additemlength, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
if (length >= 2){
length-=2;
}
else{
return TRUE;
}
switch(type_id){
case(PL_INFO):
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_type_pl, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset+=2;
if (length >= 2){
length-=2;
}
else{
return TRUE;
}
break;
case(RF_INFO):
proto_tree_add_bitmask(additional_subtree, tvb, *offset, hf_knxnetip_cemi_type_rf_info, ett_knxnetip_cemi_rf_info, cemi_rf_info, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_rf_sn, tvb, *offset, 6, ENC_BIG_ENDIAN);
*offset+=6;
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_rf_lfn, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
if (length >= 8){
length-=8;
}
else{
return TRUE;
}
break;
case(BUSMON_INFO):
proto_tree_add_bitmask(additional_subtree, tvb, *offset, hf_knxnetip_cemi_type_bus, ett_knxnetip_cemi_bus_info, cemi_bus_flags, ENC_BIG_ENDIAN);
*offset+=1;
if (length >= 1){
length-=1;
}
else{
return TRUE;
}
break;
case(TIME_REL):
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_type_relt, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset+=2;
if (length >= 2){
length-=2;
}
else{
return TRUE;
}
break;
case(TIME_DELAY):
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_type_delay, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset+=4;
if (length >= 4){
length-=4;
}
else{
return TRUE;
}
break;
case(EXEND_TIME):
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_type_exttime, tvb, *offset, 4, ENC_BIG_ENDIAN);
*offset+=4;
if (length >= 4){
length-=4;
}
else{
return TRUE;
}
break;
case(BIBAT_INFO):
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_type_bibat, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_type_bibat_block, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
if (length >= 2){
length-=2;
}
else{
return TRUE;
}
break;
case(RF_MULTI):
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_type_rf_multi_freq, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_type_rf_multi_channel, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_type_rf_multi_fastack, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_type_rf_multi_recep_freq, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
if (length >= 4){
length-=4;
}
else{
return TRUE;
}
break;
case(PREAMBEL):
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_type_preamble_length, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset+=2;
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_type_postamble_length, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
if (length >= 3){
length-=3;
}
else{
return TRUE;
}
break;
case(RF_FAST_ACK):
num_of_octets = tvb_get_guint8(tvb, *offset-1);
for(i=0; i<num_of_octets; i++) {
proto_tree_add_bitmask(additional_subtree, tvb, *offset, hf_knxnetip_cemi_type_fastack, ett_knxnetip_cemi_fastack, cemi_fastack_flags, ENC_BIG_ENDIAN);
*offset+=2;
if (length >= 2){
length-=2;
}
else{
return TRUE;
}
}
break;
case(MANU_DATA):
num_of_octets = tvb_get_guint8(tvb, *offset-1);
proto_tree_add_item(additional_subtree, hf_knxnetip_dib_manuid, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset+=2;
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_subfunction, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(additional_subtree, hf_knxnetip_cemi_manuspecificdata, tvb, *offset, (num_of_octets-3), ENC_NA);
*offset+=(num_of_octets-3);
if (length >= num_of_octets){
length-=num_of_octets;
}
else{
return TRUE;
}
break;
default:
proto_tree_add_item(additional_subtree, hf_knxnetip_unknown, tvb, *offset, -1, ENC_NA);
return *offset;
}
} while (length > 0);
}
}
switch (messagecode){
case(DATA_REQ):
case(DATA_CON):
case(DATA_IND):
case(POLL_DATA_REQ):
case(POLL_DATA_CON):
proto_tree_add_bitmask(cemi_tree, tvb, *offset, hf_knxnetip_cemi_controlfield1, ett_knxnetip_cemi_control1, cemi_control1_flags, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_bitmask(cemi_tree, tvb, *offset, hf_knxnetip_cemi_controlfield2, ett_knxnetip_cemi_control2, cemi_control2_flags, ENC_BIG_ENDIAN);
*offset+=1;
knx_address = tvb_get_ntohs(tvb, *offset);
proto_tree_add_uint_format(cemi_tree, hf_knxnetip_cemi_sourceaddress, tvb, *offset, 2, knx_address, "Source Address %d.%d.%d", ((knx_address & 0xF000)>>12),((knx_address & 0x0F00)>>8),(knx_address & 0xFF));
*offset+=2;
knx_address = tvb_get_ntohs(tvb, *offset);
if ((tvb_get_guint8(tvb, *offset-3) & 0x80) == GROUPADD){
proto_tree_add_uint_format(cemi_tree, hf_knxnetip_cemi_destaddress, tvb, *offset, 2, knx_address, "Destination Address %d/%d/%d or %d/%d", ((knx_address & 0x7800)>>11),((knx_address & 0x0700)>>8),(knx_address & 0xFF), ((knx_address & 0x7800)>>11),(knx_address & 0x7FF));
}
else {
proto_tree_add_uint_format(cemi_tree, hf_knxnetip_cemi_destaddress, tvb, *offset, 2, knx_address, "Destination Address %d.%d.%d", ((knx_address & 0xF000)>>12),((knx_address & 0x0F00)>>8),(knx_address & 0xFF));
}
*offset+=2;
if (messagecode == POLL_DATA_REQ){
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_numberofslots, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
}
else if (messagecode == POLL_DATA_CON){
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_numberofslots, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(cemi_tree, hf_knxnetip_polldata, tvb, *offset, -1, ENC_NA);
}
else {
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_npdu_length, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
dissect_apci(tvb, offset, cemi_tree, FALSE);
}
break;
case(RAW_REQ):
case(RAW_CON):
case(RAW_IND):
case(BUSMON_IND):
proto_tree_add_item(cemi_tree, hf_knxnetip_raw, tvb, *offset, -1, ENC_NA);
break;
case(DATA_INDV_IND):
case(DATA_INDV_REQ):
case(DATA_CONNEC_IND):
case(DATA_CONNEC_REQ):
proto_tree_add_item(cemi_tree, hf_knxnetip_reserved, tvb, *offset, 6, ENC_NA);
*offset+=6;
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_tpdu_length, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
dissect_apci(tvb, offset, cemi_tree, TRUE);
break;
case(PROPREAD_REQ):
case(PROPREAD_CON):
case(PROPWRITE_REQ):
case(PROPWRITE_CON):
case(PROPINFO_IND):
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_iot, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset+=2;
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_oi, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_pid, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
noe = ((tvb_get_guint8(tvb, *offset)& 0xF0)>>4);
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_noe, tvb, *offset, 1, ENC_BIG_ENDIAN);
six = tvb_get_bits16(tvb, (*offset*8+4), 12, ENC_BIG_ENDIAN);
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_six, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset+=2;
if (messagecode == PROPREAD_REQ || (messagecode == PROPREAD_CON && noe > 0)){
break;
}
else if (noe == 0){
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_error, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
}
else if (noe == 1 && six == 0){
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_numberofelements, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset+=2;
}
else {
proto_tree_add_item(cemi_tree, hf_knxnetip_data, tvb, *offset, -1, ENC_NA);
}
break;
case(FUNCPROPCOM_REQ):
case(FUNCPROPSTATREAD_REQ):
case(FUNCPROPCOM_CON):
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_iot, tvb, *offset, 2, ENC_BIG_ENDIAN);
*offset+=2;
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_oi, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_pid, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
if (messagecode == FUNCPROPCOM_CON){
proto_tree_add_item(cemi_tree, hf_knxnetip_cemi_return, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset+=1;
}
proto_tree_add_item(cemi_tree, hf_knxnetip_data, tvb, *offset, -1, ENC_NA);
break;
case(RESET_REQ):
case(RESET_IND):
break;
default:
proto_tree_add_item(cemi_tree, hf_knxnetip_data, tvb, *offset, -1, ENC_NA);
}
return FALSE;
}
static void dissect_knxnetip (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
proto_item *knx_item = NULL;
proto_tree *knx_tree = NULL;
proto_tree *header_tree = NULL;
proto_tree *body_tree = NULL;
guint offset = 0;
guint16 service_type = 0;
gboolean err = FALSE;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "KNXnetIP");
col_clear(pinfo->cinfo,COL_INFO);
knx_item = proto_tree_add_item(tree, proto_knxnetip, tvb, 0, -1, ENC_NA);
knx_tree = proto_item_add_subtree(knx_item, ett_knxnetip);
/* HEADER*/
header_tree = proto_tree_add_subtree(knx_tree, tvb, offset, 6, ett_knxnetip_header, NULL, "Header");
proto_tree_add_item(header_tree, hf_knxnetip_headerlength, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_item(header_tree, hf_knxnetip_version, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
service_type = tvb_get_ntohs(tvb, offset);
proto_tree_add_item(header_tree, hf_knxnetip_servicetype, tvb, offset, 2, ENC_BIG_ENDIAN);
col_add_fstr(pinfo->cinfo, COL_INFO, "%s %d > %d", val_to_str(service_type, knxnetip_service_identifier, "Unknown Identifier:0x%02x"), pinfo->srcport, pinfo->destport);
offset+=2;
proto_tree_add_item(header_tree, hf_knxnetip_totallength, tvb, offset, 2, ENC_BIG_ENDIAN);
offset+=2;
/* BODY */
body_tree = proto_tree_add_subtree(knx_tree, tvb, offset, -1, ett_knxnetip_body, NULL, "Body");
switch(service_type) {
case(SEARCH_REQ):
dissect_hpai(tvb, &offset, body_tree, ": Discovery endpoint");
break;
case(SEARCH_RES):
dissect_hpai(tvb, &offset, body_tree, ": Control endpoint");
err = dissect_dib(tvb, &offset, body_tree);
if (err == TRUE){
proto_tree_add_expert(body_tree, pinfo, &ei_knxnetip_length, tvb, offset, -1);
break;
}
err = dissect_dib(tvb, &offset, body_tree);
if (err == TRUE){
proto_tree_add_expert(body_tree, pinfo, &ei_knxnetip_length, tvb, offset, -1);
break;
}
break;
case(DESCRIPTION_REQ):
dissect_hpai(tvb, &offset, body_tree, ": Control endpoint");
break;
case(DESCRIPTION_RES):
err = dissect_dib(tvb, &offset, body_tree);
if (err == TRUE){
proto_tree_add_expert(body_tree, pinfo, &ei_knxnetip_length, tvb, offset, -1);
break;
}
err = dissect_dib(tvb, &offset, body_tree);
if (err == TRUE){
proto_tree_add_expert(body_tree, pinfo, &ei_knxnetip_length, tvb, offset, -1);
break;
}
if (tvb_reported_length_remaining(tvb, offset) != 0){
err = dissect_dib(tvb, &offset, body_tree);
if (err == TRUE){
proto_tree_add_expert(body_tree, pinfo, &ei_knxnetip_length, tvb, offset, -1);
}
}
break;
case(CONNECT_REQ):
dissect_hpai(tvb, &offset, body_tree, ": Discovery endpoint");
dissect_hpai(tvb, &offset, body_tree, ": Data endpoint");
offset = dissect_cri(tvb, offset, body_tree);
break;
case(CONNECT_RES):
proto_tree_add_item(body_tree, hf_knxnetip_communication_channel_id, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_item(body_tree, hf_knxnetip_connect_status, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
dissect_hpai(tvb, &offset, body_tree, ": Data endpoint");
dissect_crd(tvb, &offset, body_tree);
break;
case(CONNECTIONSTATE_REQ):
case(DISCONNECT_REQ):
proto_tree_add_item(body_tree, hf_knxnetip_communication_channel_id, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_item(body_tree, hf_knxnetip_reserved, tvb, offset, 1, ENC_NA);
offset+=1;
dissect_hpai(tvb, &offset, body_tree, ": Control endpoint");
break;
case(DISCONNECT_RES):
case(CONNECTIONSTATE_RES):
proto_tree_add_item(body_tree, hf_knxnetip_communication_channel_id, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_item(body_tree, hf_knxnetip_connectionstate_status, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
break;
case(DEVICE_CONFIGURATION_ACK):
offset = dissect_connection_header(tvb, offset, body_tree, TRUE);
proto_tree_add_item(body_tree, hf_knxnetip_confack_status, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
break;
case(DEVICE_CONFIGURATION_REQ):
case(TUNNELLING_REQ):
offset = dissect_connection_header(tvb, offset, body_tree, FALSE);
err = dissect_cemi (tvb, &offset, body_tree, pinfo);
if (err == TRUE){
proto_tree_add_expert(body_tree, pinfo, &ei_knxnetip_length, tvb, offset, -1);
}
break;
case(TUNNELLING_ACK):
offset = dissect_connection_header(tvb, offset, body_tree, TRUE);
proto_tree_add_item(body_tree, hf_knxnetip_tunnelack_status, tvb, offset, 1, ENC_BIG_ENDIAN);
break;
case(ROUTING_INDICATION):
err = dissect_cemi (tvb, &offset, body_tree, pinfo);
if (err == TRUE){
proto_tree_add_expert(body_tree, pinfo, &ei_knxnetip_length, tvb, offset, -1);
}
break;
case(ROUTING_LOST):
proto_tree_add_item(body_tree, hf_knxnetip_structure_length, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_bitmask(body_tree, tvb, offset, hf_knxnetip_devicestate, ett_knxnetip_devicestate, devicestate_flags, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_item(body_tree, hf_knxnetip_numberoflost, tvb, offset, 2, ENC_BIG_ENDIAN);
offset+=2;
break;
case(ROUTING_BUSY):
proto_tree_add_item(body_tree, hf_knxnetip_structure_length, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_bitmask(body_tree, tvb, offset, hf_knxnetip_devicestate, ett_knxnetip_devicestate, devicestate_flags, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_item(body_tree, hf_knxnetip_busywaittime, tvb, offset, 2, ENC_BIG_ENDIAN);
offset+=2;
proto_tree_add_item(body_tree, hf_knxnetip_busycontrol, tvb, offset, 2, ENC_BIG_ENDIAN);
offset+=2;
break;
case(REMOTE_DIAG_REQ):
dissect_hpai(tvb, &offset, body_tree, ": Discovery endpoint");
offset = dissect_selector(tvb ,offset, body_tree);
break;
case(REMOTE_DIAG_RES):
offset = dissect_selector(tvb ,offset, body_tree);
do{
err = dissect_dib(tvb, &offset, body_tree);
if (err == TRUE){
proto_tree_add_expert(body_tree, pinfo, &ei_knxnetip_length, tvb, offset, -1);
break;
}
} while (tvb_reported_length_remaining(tvb,offset) > 0);
break;
case(REMOTE_BASIC_CONF_REQ):
dissect_hpai(tvb, &offset, body_tree, ": Discovery endpoint");
offset = dissect_selector(tvb ,offset, body_tree);
err = dissect_dib(tvb, &offset, body_tree);
if (err == TRUE){
proto_tree_add_expert(body_tree, pinfo, &ei_knxnetip_length, tvb, offset, -1);
break;
}
if (tvb_reported_length_remaining(tvb,offset) > 0) {
err = dissect_dib(tvb, &offset, body_tree);
if (err == TRUE){
proto_tree_add_expert(body_tree, pinfo, &ei_knxnetip_length, tvb, offset, -1);
}
}
break;
case(REMOTE_RESET_REQ):
offset = dissect_selector(tvb ,offset, body_tree);
proto_tree_add_item(body_tree, hf_knxnetip_reset, tvb, offset, 1, ENC_BIG_ENDIAN);
offset+=1;
proto_tree_add_item(body_tree, hf_knxnetip_reserved, tvb, offset, 1, ENC_NA);
offset+=1;
break;
default:
proto_tree_add_item(body_tree, hf_knxnetip_unknown, tvb, offset, -1, ENC_NA);
}
}
static gboolean dissect_knxnetip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
gint idx;
idx = 0;
if (tvb_captured_length(tvb) < 8){
return (FALSE);
}
if ( tvb_get_guint8(tvb, 0) != KNXNETIP_HEADER_LENGTH) {
return (FALSE);
}
if ( tvb_get_guint8(tvb, 1) != KNXNETIP_PROTOCOL_VERSION){
return (FALSE);
}
try_val_to_str_idx((guint32)tvb_get_ntohs(tvb, 2), knxnetip_service_identifier, &idx);
if (idx == -1){
return (FALSE);
}
dissect_knxnetip(tvb, pinfo, tree);
return (TRUE);
}
void proto_register_knxnetip (void) {
expert_module_t* expert_knxnetip;
static hf_register_info hf[] = {
{ &hf_knxnetip_headerlength,
{ "Header Length", "knxnetip.header_length", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_version,
{ "Protocol Version", "knxnetip.version", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_servicetype,
{ "Service Type Identifier", "knxnetip.service_type_identifier", FT_UINT16, BASE_HEX, VALS(knxnetip_service_identifier), 0x0, NULL, HFILL }},
{ &hf_knxnetip_totallength,
{ "Total Length", "knxnetip.total_length", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_octet_octets, 0x0, NULL, HFILL }},
{ &hf_knxnetip_hpai,
{ "HPAI", "knxnetip.hpai", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_hpai_structure_length,
{ "Structure Length", "knxnetip.hpai_structure_length", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_octet_octets, 0x0, NULL, HFILL }},
{ &hf_knxnetip_structure_length,
{ "Structure Length", "knxnetip.struct_length", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_octet_octets, 0x0, NULL, HFILL }},
{ &hf_knxnetip_hpai_host_protocol,
{ "Host Protocol Code", "knxnetip.hpai_host_protocol", FT_UINT8, BASE_HEX, VALS(knxnetip_host_protocol_codes), 0x0, NULL, HFILL }},
{ &hf_knxnetip_hpai_ip_address,
{ "IP Address", "knxnetip.hpai_ip_address", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_hpai_port,
{ "IP Port", "knxnetip.hpai_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib,
{ "DIB", "knxnetip.dib", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cri,
{ "Connection Request Information", "knxnetip.cri", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_type,
{ "Description Type", "knxnetip.dib_type", FT_UINT8, BASE_HEX, VALS(knxnetip_dib_description_type_codes), 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_medium,
{ "KNX medium", "knxnetip.dib_medium", FT_UINT8, BASE_HEX, VALS(knxnetip_dib_medium_codes), 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_status,
{ "Device Status", "knxnetip.dib_status", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_projectid,
{ "Project-Installation identifier", "knxnetip.dib_projectid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_knxaddress,
{ "KNX Individual Address", "knxnetip.knxaddress", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_serialnumber,
{ "KNXnet/IP device serial number", "knxnetip.serialnumber", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_multicast_address,
{ "KNXnet/IP device multicast address", "knxnetip.multicast", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_mac_address,
{ "KNXnet/IP device MAC address", "knxnetip.macaddress", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_friendly,
{ "Device Friendly Name", "knxnetip.devicename", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_service,
{ "Service ID", "knxnetip.dib_service", FT_UINT8, BASE_HEX, VALS(knxnetip_service_types), 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_ipaddress,
{ "IP Address", "knxnetip.dib_ipaddress", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_subnet,
{ "Subnet Mask", "knxnetip.dib_subnet", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_gateway,
{ "Default Gateway", "knxnetip.dib_gateway", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_ipcapa,
{ "IP Capabilities", "knxnetip.dib_ipcapabilities", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_ipassign,
{ "IP assignment method", "knxnetip.dib_assignment", FT_UINT8, BASE_HEX, VALS(knxnetip_ip_assignment_method), 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_dhcp,
{ "DHCP Server", "knxnetip.dib_dhcp", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_manuid,
{ "Manufacturer ID", "knxnetip.manufacturer_id", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_manudata,
{ "Manufacturer specific data", "knxnetip.manufacturer_data", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_connection_type,
{ "Connection Type", "knxnetip.connection_type", FT_UINT8, BASE_HEX, VALS(knxnetip_connection_types), 0x0, NULL, HFILL }},
{ &hf_knxnetip_cri_protocol_data,
{ "Protocol Data", "knxnetip.cri_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_communication_channel_id,
{ "Communication Channel ID", "knxnetip.communication_channel_id", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_connect_status,
{ "Status", "knxnetip.connect_status", FT_UINT8, BASE_HEX, VALS(knxnetip_connect_response_status_codes), 0x0, NULL, HFILL }},
{ &hf_knxnetip_crd_protocol_data,
{ "Protocol Data", "knxnetip.crd_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_crd,
{ "Connection Response Data Block", "knxnetip.crd", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_connectionstate_status,
{ "Status", "knxnetip.connect_state_status", FT_UINT8, BASE_HEX, VALS(knxnetip_connectionstate_response_status_codes), 0x0, NULL, HFILL }},
{ &hf_knxnetip_counter,
{ "Sequence Counter", "knxnetip.sequence_counter", FT_UINT8, BASE_DEC, 0x0, 0x0, NULL, HFILL }},
{ &hf_knxnetip_confack_status,
{ "Status", "knxnetip.confirm_ack_status", FT_UINT8, BASE_HEX, VALS(knxnetip_device_configuration_ack_status_codes), 0x0, NULL, HFILL }},
{ &hf_knxnetip_tunnelack_status,
{ "Status", "knxnetip.tunnel_status", FT_UINT8, BASE_HEX, VALS(knxnetip_tunneling_error_codes), 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_status_flag_reserved,
{ "reserved", "knxnetip.dib_reserved", FT_UINT8, BASE_HEX, NULL, FLAGS_DEVICESTATUS_RESERVED, NULL, HFILL }},
{ &hf_knxnetip_dib_status_flag_program,
{ "program mode", "knxnetip.dib_program_mode", FT_UINT8, BASE_DEC, NULL, FLAGS_DEVICESTATUS_PROGRAM, NULL , HFILL }},
{ &hf_knxnetip_dib_ipcapa_flag_reserved,
{ "reserved", "knxnetip.ip_capabilities_reserved", FT_UINT8, BASE_HEX, NULL, FLAGS_IPCAPABILITES_RESERVED, NULL, HFILL }},
{ &hf_knxnetip_dib_ipcapa_flag_bootip,
{ "BootIP", "knxnetip.ip_capabilities_bootip", FT_UINT8, BASE_DEC, NULL, FLAGS_IPCAPABILITES_BOOTIP, NULL, HFILL }},
{ &hf_knxnetip_dib_ipcapa_flag_dhcp,
{ "DHCP", "knxnetip.ip_capabilities_dhcp", FT_UINT8, BASE_DEC, NULL, FLAGS_IPCAPABILITES_DHCP, NULL, HFILL }},
{ &hf_knxnetip_dib_ipcapa_flag_autoip,
{ "AutoIP", "knxnetip.ip_capabilities_autoip", FT_UINT8, BASE_DEC, NULL, FLAGS_IPCAPABILITES_AUTOIP, NULL, HFILL }},
{ &hf_knxnetip_devicestate,
{ "DeviceState", "knxnetip.devicestate", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_devicestate_reserved,
{ "reserved", "knxnetip.devicestate_reserved", FT_UINT8, BASE_HEX, NULL, FLAGS_DEVICESTATE_RESERVED, NULL, HFILL }},
{ &hf_knxnetip_devicestate_knx,
{ "KNX Fault", "knxnetip.devicestate_knx", FT_UINT8, BASE_DEC, NULL, FLAGS_DEVICESTATE_KNX, "is set if KNX network cannot be accessed", HFILL }},
{ &hf_knxnetip_devicestate_ip,
{ "IP Fault", "knxnetip.devicestate_ip", FT_UINT8, BASE_DEC, NULL, FLAGS_DEVICESTATE_IP, "is set if IP network cannot be accessed", HFILL }},
{ &hf_knxnetip_numberoflost,
{ "NumberofLostMessages", "knxnetip.number_of_lost_msg", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_busywaittime,
{ "Busy Wait Time", "knxnetip.busy_time", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_milliseconds, 0x0, NULL, HFILL }},
{ &hf_knxnetip_busycontrol,
{ "Busy Control Field", "knxnetip.busy_control", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_knxlayer,
{ "KNX Layer", "knxnetip.layer", FT_UINT8, BASE_HEX, VALS(knxnetip_knxlayer_values), 0x0, NULL, HFILL }},
{ &hf_knxnetip_selector_type,
{ "Selector Type Code", "knxnetip.selector", FT_UINT8, BASE_HEX, VALS(knxnetip_selector_types), 0x0, NULL, HFILL }},
{ &hf_knxnetip_reset,
{ "Reset Command", "knxnetip.reset", FT_UINT8, BASE_HEX, VALS(knxnetip_reset_codes), 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi,
{ "cEMI", "knxnetip.cemi", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_mc,
{ "messagecode", "knxnetip.cemi_messagecode", FT_UINT8, BASE_HEX, VALS(cemi_messagecodes), 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_addlength,
{ "add information length", "knxnetip.additional_length", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_octet_octets, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_additemlength,
{ "Length", "knxnetip.additional_item_length", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_octet_octets, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_typid,
{ "Type id", "knxnetip.cemi_type_id", FT_UINT8, BASE_HEX, VALS(cemi_add_type_id), 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_pl,
{ "Domain-Address", "knxnetip.cemi_type_pl", FT_UINT16, BASE_HEX, 0x0, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_bus,
{ "Busmonitor error flags", "knxnetip.cemi_type_bus", FT_UINT8, BASE_HEX, 0x0, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_relt,
{ "relative timestamp", "knxnetip.cemi_type_reltime", FT_UINT16, BASE_HEX, 0x0, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_delay,
{ "delay", "knxnetip.cemi_type_delay", FT_UINT32, BASE_HEX, 0x0, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_exttime,
{ "extended timestamp", "knxnetip.cemi_type_exttime", FT_UINT32, BASE_HEX, 0x0, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_bibat,
{ "BiBat", "knxnetip.cemi_type_bibat", FT_UINT8, BASE_HEX, VALS(cemi_bibat_ctrl), 0xF8, NULL, HFILL }},
{ &hf_knxnetip_cemi_controlfield1,
{ "Controlfield 1", "knxnetip.controlfield_one", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_flag_frametype,
{ "Frametype", "knxnetip.controlfield_type", FT_UINT8, BASE_DEC, NULL, FLAGS_CEMI_CONTROL1_FT, "0: extended frame; 1: standard frame", HFILL }},
{ &hf_knxnetip_cemi_flag_repeat,
{ "Repeat", "knxnetip.controlfield_repeat", FT_UINT8, BASE_DEC, NULL, FLAGS_CEMI_CONTROL1_R, "0: repeat if error frame; 1: do not repeat", HFILL }},
{ &hf_knxnetip_cemi_flag_sb,
{ "System-Broadcast", "knxnetip.controlfield_broadcast", FT_UINT8, BASE_DEC, NULL, FLAGS_CEMI_CONTROL1_SB, "0: system-broadcast; 1: broadcast", HFILL }},
{ &hf_knxnetip_cemi_flag_priority,
{ "Priority", "knxnetip.controlfield_priority", FT_UINT8, BASE_HEX, NULL, FLAGS_CEMI_CONTROL1_P, NULL, HFILL }},
{ &hf_knxnetip_cemi_flag_ack,
{ "Acknowledge-Request", "knxnetip.controlfield_ack", FT_UINT8, BASE_DEC, NULL, FLAGS_CEMI_CONTROL1_A, "0: no request for ack; 1: request ack", HFILL }},
{ &hf_knxnetip_cemi_flag_confirm,
{ "Confirm-Flag", "knxnetip.controlfield_confirm", FT_UINT8, BASE_DEC, NULL, FLAGS_CEMI_CONTROL1_C, "0: no error in frame; 1: error in frame", HFILL }},
{ &hf_knxnetip_cemi_controlfield2,
{ "Controlfield 2", "knxnetip.controlfield_two", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_flag_destaddress,
{ "Destination address type", "knxnetip.controldestaddress", FT_UINT8, BASE_DEC, NULL, FLAGS_CEMI_CONTROL2_AT, "0: individual; 1: group", HFILL }},
{ &hf_knxnetip_flag_hop,
{ "Hop count", "knxnetip.controlhop", FT_UINT8, BASE_DEC, NULL, FLAGS_CEMI_CONTROL2_HC, NULL, HFILL }},
{ &hf_knxnetip_flag_eff,
{ "Extended Frame Format", "knxnetip.controleff", FT_UINT8, BASE_HEX, NULL, FLAGS_CEMI_CONTROL2_EFF, "0000b for standard frame", HFILL }},
{ &hf_knxnetip_cemi_sourceaddress,
{ "Source Address", "knxnetip.cemisource", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_destaddress,
{ "Destination Address", "knxnetip.cemidestination", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_tpci,
{ "TPCI", "knxnetip.cemitpci", FT_UINT8, BASE_HEX, VALS(cemi_tpci_vals), 0xC0, NULL, HFILL }},
{ &hf_knxnetip_cemi_npdu_length,
{ "NPDU length", "knxnetip.npdulength", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_octet_octets, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_tpdu_length,
{ "TPDU length", "knxnetip.tpdulength", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_octet_octets, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_counter,
{ "sequence NCD/NDT", "knxnetip.npduseq", FT_UINT8, BASE_DEC, NULL, 0x3C, NULL, HFILL }},
{ &hf_knxnetip_cemi_apci,
{ "APCI", "knxnetip.npduapci", FT_UINT16, BASE_HEX, VALS(cemi_apci_codes), 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_data,
{ "Data", "knxnetip.cemidata", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_numberofslots,
{ "number of slots", "knxnetip.ceminumberofslots", FT_UINT8, BASE_DEC, NULL, 0xF, NULL, HFILL }},
{ &hf_knxnetip_cemi_apci_memory_number,
{ "number of octets to be read/write", "knxnetip.cemidata", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_iot,
{ "Interface object type", "knxnetip.cemiiot", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_oi,
{ "Object Instance", "knxnetip.cemioi", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_pid,
{ "Property Identifier", "knxnetip.cemipid", FT_UINT8, BASE_DEC, VALS(cemi_propertyid), 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_noe,
{ "Number of Elements", "knxnetip.ceminoe", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }},
{ &hf_knxnetip_cemi_six,
{ "Startindex", "knxnetip.cemipid", FT_UINT16, BASE_DEC, NULL, 0xFFF, NULL, HFILL }},
{ &hf_knxnetip_cemi_numberofelements,
{ "Number of Elements", "knxnetip.ceminumber", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_error,
{ "Error Code", "knxnetip.cemierror", FT_UINT8, BASE_HEX, VALS(cemi_error_codes), 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_return,
{ "retrun code", "knxnetip.cemireturn", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_reserved,
{ "reserved", "knxnetip.cemireserved", FT_UINT8, BASE_HEX, NULL, 0xFC, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_rf_info,
{ "RF-Info", "knxnetip.cemirfinfo", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_rf_mesure,
{ "received signal strength", "knxnetip.cemirfmesure", FT_UINT8, BASE_HEX, NULL, FLAGS_CEMI_RF_MESURE, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_rf_reserved,
{ "reserved", "knxnetip.cemirfreserved", FT_UINT8, BASE_HEX, NULL, FLAGS_CEMI_RF_RESERVED, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_rf_mesure_re,
{ "retransmitter signal strrength", "knxnetip.cemirfmesurere", FT_UINT8, BASE_HEX, NULL, FLAGS_CEMI_RF_MESURE_RE, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_rf_battery,
{ "Battery state", "knxnetip.cemirfbattery", FT_UINT8, BASE_HEX, NULL, FLAGS_CEMI_RF_BATTERY, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_rf_bidirekt,
{ "is not bidirektional", "knxnetip.cemirfbattery", FT_UINT8, BASE_HEX, NULL, FLAGS_CEMI_RF_BIDIRETIONAL, NULL, HFILL }},
{ &hf_knxnetip_cemi_rf_sn,
{ "KNX Serial Number", "knxnetip.cemiknxsn", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_rf_lfn,
{ "Data Link Layer frame number", "knxnetip.cemilfn", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_bus_flag_f,
{ "Frame error flag", "knxnetip.cemibusferror", FT_UINT8, BASE_DEC, NULL, FLAGS_CEMI_BUS_F, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_bus_flag_b,
{ "Bit error flag", "knxnetip.cemibusberror", FT_UINT8, BASE_DEC, NULL, FLAGS_CEMI_BUS_B, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_bus_flag_p,
{ "Parity error flag", "knxnetip.cemibusparity", FT_UINT8, BASE_DEC, NULL, FLAGS_CEMI_BUS_P, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_bus_flag_d,
{ "dont care", "knxnetip.cemibusdont", FT_UINT8, BASE_DEC, NULL, FLAGS_CEMI_BUS_D, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_bus_flag_l,
{ "Lost flag", "knxnetip.cemibuslost", FT_UINT8, BASE_DEC, NULL, FLAGS_CEMI_BUS_L, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_bus_flag_sss,
{ "Sequence Number", "knxnetip.cemibusseq", FT_UINT8, BASE_DEC, NULL, FLAGS_CEMI_BUS_SSS, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_bibat_block,
{ "BiBat Block number", "knxnetip.cemibibbatblock", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_rf_multi_fastack,
{ "KNX RF Multi Fast Ack", "knxnetip.cemirffastack", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_rf_multi_freq,
{ "KNX RF Multi Transmission Frequency", "knxnetip.cemirffreq", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_rf_multi_channel,
{ "KNX RF Multi Call Channel", "knxnetip.cemirfchannel", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_rf_multi_recep_freq,
{ "KNX RF Multi Reception Frequency", "knxnetip.cemirfrecfreq", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_preamble_length,
{ "Preamble Length", "knxnetip.cemipreamblelength", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_postamble_length,
{ "Postamble Length", "knxnetip.cemipostamblelength", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_fastack,
{ "Fast Ack information", "knxnetip.cemifastack", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_fastack_crc,
{ "Fast Ack is received with a CRC", "knxnetip.cemifastackcrc", FT_UINT16, BASE_DEC, NULL, FLAGS_CEMI_FASTACK_CRC, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_fastack_error,
{ "Fast Ack is received with a Manchester error", "knxnetip.cemifastackerror", FT_UINT16, BASE_DEC, NULL, FLAGS_CEMI_FASTACK_ERROR, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_fastack_received,
{ "Fast Ack has been received", "knxnetip.cemifastackres", FT_UINT16, BASE_DEC, NULL, FLAGS_CEMI_FASTACK_RES, NULL, HFILL }},
{ &hf_knxnetip_cemi_type_fastack_info,
{ "Fast Ack Info", "knxnetip.cemifastackinfo", FT_UINT16, BASE_HEX, NULL, FLAGS_CEMI_FASTACK_INFO, NULL, HFILL }},
{ &hf_knxnetip_cemi_subfunction,
{ "Subfunction", "knxnetip.cemisubfunction", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_manuspecificdata,
{ "Manufacturer specific data", "knxnetip.cemimanuspecificdata", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_projectnumber,
{ "Project number", "knxnetip.projectnumber", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_installnumber,
{ "Installation number", "knxnetip.installnumber", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_dib_svc_version,
{ "Version", "knxnetip.svcversion", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_reserved,
{ "reserved", "knxnetip.reserved", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_data,
{ "data", "knxnetip.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_polldata,
{ "Poll data", "knxnetip.polldata", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_raw,
{ "RAW Frame", "knxnetip.raw", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_additional,
{ "Additional information", "knxnetip.additional", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_unknown,
{ "UNKNOWN", "knxnetip.unknown", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_apci_mem_address,
{ "Memory Address", "knxnetip.cemimemaddress", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_channel,
{ "Channel nr", "knxnetip.cemichannel", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_apci_key,
{ "key", "knxnetip.apcikey", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_apci_level,
{ "level", "knxnetip.apcilevel", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_apci_object,
{ "object index", "knxnetip.apciobjidx", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
{ &hf_knxnetip_cemi_apci_propid,
{ "property id", "knxnetip.apcipropid", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}
};
static gint *ett[] = {
&ett_knxnetip,
&ett_knxnetip_header,
&ett_knxnetip_body,
&ett_knxnetip_hpai,
&ett_knxnetip_dib,
&ett_knxnetip_dib_projectid,
&ett_knxnetip_dib_service,
&ett_knxnetip_cri,
&ett_knxnetip_crd,
&ett_knxnetip_dib_status,
&ett_knxnetip_dib_ipcapa,
&ett_knxnetip_devicestate,
&ett_knxnetip_cemi,
&ett_knxnetip_cemi_additional,
&ett_knxnetip_cemi_additional_item,
&ett_knxnetip_cemi_control1,
&ett_knxnetip_cemi_control2,
&ett_knxnetip_cemi_rf_info,
&ett_knxnetip_cemi_bus_info,
&ett_knxnetip_cemi_fastack
};
static ei_register_info ei[] = {
{ &ei_knxnetip_length, { "knxnetip.invalid.length", PI_PROTOCOL, PI_ERROR, "invalid length", EXPFILL }},
};
proto_knxnetip = proto_register_protocol("KNXnet/IP", "knxnetip", "knx");
proto_register_field_array(proto_knxnetip, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_knxnetip = expert_register_protocol(proto_knxnetip);
expert_register_field_array(expert_knxnetip, ei, array_length(ei));
}
void proto_reg_handoff_knxnetip(void) {
/* register as heuristic dissector for both TCP and UDP */
heur_dissector_add("tcp", dissect_knxnetip_heur, "KNXnet/IP over TCP", "knxnetip_tcp", proto_knxnetip, HEURISTIC_ENABLE);
heur_dissector_add("udp", dissect_knxnetip_heur, "KNXnet/IP over UDP", "knxnetip_udp", proto_knxnetip, HEURISTIC_ENABLE);
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/