LLDP: Add CIP TLVs

This commit is contained in:
Dylan Ulis 2022-06-11 00:18:11 +00:00 committed by A Wireshark GitLab Utility
parent bcb8558be2
commit c758e9d9c0
6 changed files with 111 additions and 26 deletions

View File

@ -4833,6 +4833,40 @@ static int dissect_segment_ansi_extended_symbol(packet_info* pinfo, tvbuff_t* tv
return 2 + seg_size;
}
// offset - Starts with the 'Key Data' section of the Electronic Key Segment Format.
int dissect_electronic_key_format(tvbuff_t* tvb, int offset, proto_tree* tree, gboolean generate, guint8 key_format)
{
int key_len;
if (key_format == CI_E_KEY_FORMAT_VAL)
{
key_len = 8;
}
else // CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL
{
key_len = 12;
}
if (generate)
{
dissect_deviceid(tvb, offset, tree,
hf_cip_ekey_vendor, hf_cip_ekey_devtype, hf_cip_ekey_prodcode,
hf_cip_ekey_compatibility, hf_cip_ekey_comp_bit, hf_cip_ekey_majorrev, hf_cip_ekey_minorrev, TRUE);
}
else
{
dissect_deviceid(tvb, offset, tree,
hf_cip_ekey_vendor, hf_cip_ekey_devtype, hf_cip_ekey_prodcode,
hf_cip_ekey_compatibility, hf_cip_ekey_comp_bit, hf_cip_ekey_majorrev, hf_cip_ekey_minorrev, FALSE);
if (key_format == CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL)
{
proto_tree_add_item(tree, hf_cip_ekey_serial_number, tvb, offset + 8, 4, ENC_LITTLE_ENDIAN);
}
}
return key_len;
}
static int dissect_segment_logical_special(packet_info* pinfo, tvbuff_t* tvb, int offset,
gboolean generate, proto_tree* path_seg_tree,
proto_item* path_seg_item, proto_item* epath_item)
@ -4847,40 +4881,20 @@ static int dissect_segment_logical_special(packet_info* pinfo, tvbuff_t* tvb, in
guint8 key_format = tvb_get_guint8(tvb, offset + 1);
if (key_format == CI_E_KEY_FORMAT_VAL || key_format == CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL)
{
if (key_format == CI_E_KEY_FORMAT_VAL)
{
segment_len = 10;
}
else // CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL
{
segment_len = 14;
}
if (generate)
{
proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_ekey_format, tvb, 0, 0, key_format);
proto_item_set_generated(it);
dissect_deviceid(tvb, offset + 2, path_seg_tree,
hf_cip_ekey_vendor, hf_cip_ekey_devtype, hf_cip_ekey_prodcode,
hf_cip_ekey_compatibility, hf_cip_ekey_comp_bit, hf_cip_ekey_majorrev, hf_cip_ekey_minorrev, TRUE);
}
else
{
proto_tree_add_item(path_seg_tree, hf_cip_ekey_format, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
/* dissect the device ID */
dissect_deviceid(tvb, offset + 2, path_seg_tree,
hf_cip_ekey_vendor, hf_cip_ekey_devtype, hf_cip_ekey_prodcode,
hf_cip_ekey_compatibility, hf_cip_ekey_comp_bit, hf_cip_ekey_majorrev, hf_cip_ekey_minorrev, FALSE);
if (key_format == CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL)
{
proto_tree_add_item(path_seg_tree, hf_cip_ekey_serial_number, tvb, offset + 12, 4, ENC_LITTLE_ENDIAN);
}
proto_item_set_len(path_seg_item, segment_len);
}
segment_len = 2;
segment_len += dissect_electronic_key_format(tvb, offset + 2, path_seg_tree, generate, key_format);
proto_item_set_len(path_seg_item, segment_len);
/* Add "summary" information to parent item */
guint16 vendor_id = tvb_get_letohs(tvb, offset + 2);

View File

@ -607,6 +607,7 @@ extern void dissect_deviceid(tvbuff_t *tvb, int offset, proto_tree *tree,
int hf_vendor, int hf_devtype, int hf_prodcode,
int hf_compatibility, int hf_comp_bit, int hf_majrev, int hf_minrev,
gboolean generate);
extern int dissect_electronic_key_format(tvbuff_t* tvb, int offset, proto_tree* tree, gboolean generate, guint8 key_format);
extern int dissect_optional_attr_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
int offset, int total_len);
extern int dissect_optional_service_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,

View File

@ -4,7 +4,7 @@
*
* This dissector includes items from:
* CIP Volume 1: Common Industrial Protocol, Edition 3.24
* CIP Volume 2: EtherNet/IP Adaptation of CIP, Edition 1.27
* CIP Volume 2: EtherNet/IP Adaptation of CIP, Edition 1.30
* CIP Volume 8: CIP Security, Edition 1.13
*
* Copyright 2003-2004
@ -368,6 +368,8 @@ static int hf_eip_cert_capflags_reserved = -1;
static int hf_eip_cert_capability_flags = -1;
static int hf_eip_cert_num_certs = -1;
static int hf_eip_cert_cert_name = -1;
static int hf_lldp_subtype = -1;
static int hf_lldp_mac_address = -1;
/* Initialize the subtree pointers */
static gint ett_enip = -1;
@ -4670,6 +4672,16 @@ proto_register_enip(void)
{ "Certificate name", "cip.eip_cert.cert_name",
FT_STRING, BASE_NONE, NULL, 0,
NULL, HFILL }},
{ &hf_lldp_subtype,
{ "ODVA LLDP Subtype", "cip.lldp.subtype",
FT_UINT8, BASE_DEC, VALS(lldp_cip_subtypes), 0,
NULL, HFILL }
},
{ &hf_lldp_mac_address,
{ "MAC Address", "cip.lldp.mac_address",
FT_ETHER, BASE_NONE, NULL, 0,
NULL, HFILL }},
};
/* Setup protocol subtree array */
@ -5020,6 +5032,53 @@ proto_register_enip(void)
subdissector_decode_as_io_table = register_decode_as_next_proto(proto_enip, "cip.io", "CIP I/O Payload", enip_prompt);
} /* end of proto_register_enip() */
const value_string lldp_cip_subtypes[] = {
{ 1, "CIP Identification" },
{ 2, "CIP MAC Address" },
{ 3, "CIP Interface Label" },
{ 4, "Position ID" },
{ 5, "T1S PHY Data" },
{ 6, "Commission Request" },
{ 7, "Commission Response" },
{ 8, "Discover Topology Response" },
{ 0, NULL }
};
int dissect_lldp_cip_tlv(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
{
int total_len = tvb_reported_length_remaining(tvb, 0);
int offset = 0;
guint32 subtype;
proto_tree_add_item_ret_uint(tree, hf_lldp_subtype, tvb, offset, 1, ENC_BIG_ENDIAN, &subtype);
offset++;
switch (subtype)
{
case 1:
{
dissect_electronic_key_format(tvb, offset, tree, FALSE, CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL);
break;
}
case 2:
proto_tree_add_item(tree, hf_lldp_mac_address, tvb, offset, 6, ENC_NA);
break;
case 3:
{
// The string is all the data, minus Subtype (1 byte).
int string_len = total_len - 1;
proto_tree_add_item(tree, hf_elink_interface_label, tvb, offset, string_len, ENC_ASCII | ENC_NA);
break;
}
default:
break;
}
return tvb_reported_length(tvb);
}
void
proto_reg_handoff_enip(void)

View File

@ -109,6 +109,9 @@ void display_fwd_open_connection_path(cip_conn_info_t* conn_info, proto_tree* tr
void enip_close_cip_connection(packet_info *pinfo, const cip_connection_triad_t* triad);
void enip_mark_connection_triad(packet_info *pinfo, const cip_connection_triad_t* triad);
extern int dissect_lldp_cip_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
extern const value_string lldp_cip_subtypes[];
extern attribute_info_t enip_attribute_vals[106];
#endif /* PACKET_ENIP_H */

View File

@ -39,6 +39,7 @@
#include <epan/wmem_scopes.h>
#include <epan/oui.h>
#include "packet-enip.h"
#define DEFAULT_COLUMN_INFO 1
#define PROFINET_SPECIAL_COLUMN_INFO 2
@ -4515,6 +4516,9 @@ dissect_organizational_specific_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tre
case OUI_ONOS:
subTypeStr = val_to_str(subType, onos_subtypes, "Unknown subtype (0x%x)");
break;
case OUI_ODVA:
subTypeStr = val_to_str(subType, lldp_cip_subtypes, "Unknown subtype (0x%x)");
break;
default:
subTypeStr = wmem_strdup_printf(pinfo->pool, "Unknown (%d)",subType);
break;
@ -4578,6 +4582,9 @@ dissect_organizational_specific_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tre
case OUI_ONOS:
dissect_onos_tlv(vendor_tvb, pinfo, org_tlv_tree);
break;
case OUI_ODVA:
dissect_lldp_cip_tlv(vendor_tvb, pinfo, org_tlv_tree);
break;
default:
dissect_oui_default_tlv(vendor_tvb, pinfo, org_tlv_tree);
}

View File

@ -64,6 +64,7 @@
#define OUI_IEEE_802_1QBG 0x001B3F /* IEEE 802.1 Qbg */
#define OUI_NINTENDO 0x001F32
#define OUI_TURBOCELL 0x0020F6 /* KarlNet, who brought you Turbocell */
#define OUI_ODVA 0x00216C /* ODVA */
#define OUI_AVAYA 0x00400D /* Avaya */
#define OUI_CISCOWL 0x004096 /* Cisco Wireless (Aironet) */
#define OUI_MARVELL 0x005043 /* Marvell Semiconductor */