diff options
author | D. Ulis <daulis0@gmail.com> | 2015-12-10 11:39:46 -0500 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2015-12-11 07:07:31 +0000 |
commit | e6dc9a725bfe30c0435b9c32423b1c5804572f52 (patch) | |
tree | 4c72498b3768834136f735ae013e02f9ede19030 /epan/dissectors/packet-cip.c | |
parent | 00eb71ac32e2736c85147ad5addf7ceed1e20db6 (diff) |
CIP: Add support for common class attributes
Change-Id: Iaa297340708170e8efb2d73d0c164e0358507eb2
Reviewed-on: https://code.wireshark.org/review/12502
Reviewed-by: Michael Mann <mmann78@netscape.net>
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-cip.c')
-rw-r--r-- | epan/dissectors/packet-cip.c | 90 |
1 files changed, 89 insertions, 1 deletions
diff --git a/epan/dissectors/packet-cip.c b/epan/dissectors/packet-cip.c index 3fcc72a7a2..2eedd44926 100644 --- a/epan/dissectors/packet-cip.c +++ b/epan/dissectors/packet-cip.c @@ -70,6 +70,15 @@ static int proto_cip_class_cco = -1; static int proto_enip = -1; static int proto_modbus = -1; +static int hf_attr_class_revision = -1; +static int hf_attr_class_max_instance = -1; +static int hf_attr_class_num_instance = -1; +static int hf_attr_class_opt_attr_num = -1; +static int hf_attr_class_attr_num = -1; +static int hf_attr_class_opt_service_num = -1; +static int hf_attr_class_service_code = -1; +static int hf_attr_class_num_class_attr = -1; +static int hf_attr_class_num_inst_attr = -1; static int hf_cip_data = -1; static int hf_cip_service = -1; static int hf_cip_service_code = -1; @@ -571,7 +580,8 @@ static expert_field ei_mal_inv_config_size = EI_INIT; static expert_field ei_mal_ot_size = EI_INIT; static expert_field ei_mal_to_size = EI_INIT; static expert_field ei_mal_fwd_close_missing_data = EI_INIT; - +static expert_field ei_mal_opt_attr_list = EI_INIT; +static expert_field ei_mal_opt_service_list = EI_INIT; dissector_table_t subdissector_class_table; static dissector_table_t subdissector_symbol_table; @@ -3030,6 +3040,50 @@ static int dissect_time_sync_sys_time_and_offset(packet_info *pinfo, proto_tree return 16; } +static int dissect_optional_attr_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, + int offset, int total_len) +{ + guint32 i; + guint32 num_attr = 0; + + proto_tree_add_item_ret_uint(tree, hf_attr_class_opt_attr_num, tvb, offset, 2, ENC_LITTLE_ENDIAN, &num_attr); + + if (total_len < (int)(2 + num_attr * 2)) + { + expert_add_info(pinfo, item, &ei_mal_opt_attr_list); + return total_len; + } + + for (i = 0; i < num_attr; ++i) + { + proto_tree_add_item(tree, hf_attr_class_attr_num, tvb, offset + 2 + 2 * i, 2, ENC_LITTLE_ENDIAN); + } + + return 2 + num_attr * 2; +} + +static int dissect_optional_service_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, + int offset, int total_len) +{ + guint32 i; + guint32 num_services = 0; + + proto_tree_add_item_ret_uint(tree, hf_attr_class_opt_service_num, tvb, offset, 2, ENC_LITTLE_ENDIAN, &num_services); + + if (total_len < (int)(2 + num_services * 2)) + { + expert_add_info(pinfo, item, &ei_mal_opt_service_list); + return total_len; + } + + for (i = 0; i < num_services; ++i) + { + proto_tree_add_item(tree, hf_attr_class_service_code, tvb, offset + 2 + 2 * i, 2, ENC_LITTLE_ENDIAN); + } + + return 2 + num_services * 2; +} + static attribute_info_t cip_attribute_vals[] = { @@ -3101,6 +3155,16 @@ static attribute_val_array_t all_attribute_vals[] = { {sizeof(cip_safety_attribute_vals)/sizeof(attribute_info_t), cip_safety_attribute_vals} }; +attribute_info_t class_attribute_vals[] = { + { 0, TRUE, 1, "Revision", cip_uint, &hf_attr_class_revision, NULL }, + { 0, TRUE, 2, "Max Instance", cip_uint, &hf_attr_class_max_instance, NULL }, + { 0, TRUE, 3, "Number of Instances", cip_uint, &hf_attr_class_num_instance, NULL }, + { 0, TRUE, 4, "Optional Attribute List", cip_dissector_func, NULL, dissect_optional_attr_list }, + { 0, TRUE, 5, "Optional Service List", cip_dissector_func, NULL, dissect_optional_service_list }, + { 0, TRUE, 6, "Maximum ID Number Class Attributes", cip_uint, &hf_attr_class_num_class_attr, NULL }, + { 0, TRUE, 7, "Maximum ID Number Instance Attributes", cip_uint, &hf_attr_class_num_inst_attr, NULL }, +}; + static void dissect_cip_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, packet_info *pinfo, cip_req_info_t *preq_info ); @@ -3126,6 +3190,19 @@ attribute_info_t* cip_get_attribute(guint class_id, guint instance, guint attrib } } + /* Check against common class attributes. */ + if (instance == 0) + { + for (i = 0; i < sizeof(class_attribute_vals) / sizeof(attribute_info_t); i++) + { + pattr = &class_attribute_vals[i]; + if (pattr->attribute == attribute) + { + return pattr; + } + } + } + return NULL; } @@ -6482,6 +6559,15 @@ proto_register_cip(void) { /* Setup list of header fields */ static hf_register_info hf[] = { + { &hf_attr_class_revision, { "Revision", "cip.class_revision", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, + { &hf_attr_class_max_instance, { "Max Instance", "cip.max_instance", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, + { &hf_attr_class_num_instance, { "Number of Instances", "cip.num_instance", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, + { &hf_attr_class_opt_attr_num, { "Number of Attributes", "cip.num_attr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, + { &hf_attr_class_attr_num, { "Attribute Number", "cip.attr_num", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, + { &hf_attr_class_opt_service_num, { "Number of Services", "cip.num_service", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, + { &hf_attr_class_service_code, { "Service Code", "cip.service_code", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, + { &hf_attr_class_num_class_attr, { "Maximum ID Number Class Attributes", "cip.num_class_attr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, + { &hf_attr_class_num_inst_attr, { "Maximum ID Number Instance Attributes", "cip.num_inst_attr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_cip_service, { "Service", "cip.service", FT_UINT8, BASE_HEX, NULL, 0, "Service Code + Request/Response", HFILL }}, { &hf_cip_reqrsp, { "Request/Response", "cip.rr", FT_UINT8, BASE_HEX, VALS(cip_sc_rr), CIP_SC_RESPONSE_MASK, "Request or Response message", HFILL }}, @@ -7003,6 +7089,8 @@ proto_register_cip(void) { &ei_mal_ot_size, { "cip.malformed.ot_size", PI_MALFORMED, PI_WARN, "Invalid O->T size - missing size field", EXPFILL }}, { &ei_mal_to_size, { "cip.malformed.to_size", PI_MALFORMED, PI_WARN, "Invalid T->O size - missing size field", EXPFILL }}, { &ei_mal_fwd_close_missing_data, { "cip.malformed.fwd_close_missing_data", PI_MALFORMED, PI_ERROR, "Forward Close response missing application reply data", EXPFILL }}, + { &ei_mal_opt_attr_list, { "cip.malformed.opt_attr_list", PI_MALFORMED, PI_ERROR, "Optional attribute list missing data", EXPFILL }}, + { &ei_mal_opt_service_list, { "cip.malformed.opt_service_list", PI_MALFORMED, PI_ERROR, "Optional service list missing data", EXPFILL }}, }; expert_module_t* expert_cip; |