aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/epan
diff options
context:
space:
mode:
authorMatthias Dietrich <matthias.dietrich@gmx.fr>2022-05-16 22:16:34 +0200
committerA Wireshark GitLab Utility <gerald+gitlab-utility@wireshark.org>2022-05-21 07:52:07 +0000
commit85eb9fba4d32ca9223b375f9456ba62437b45336 (patch)
treedcc8e7db3d9fff9b6aded78c4a4c287dd34f86cf /plugins/epan
parent225e90564d1b52fc99ddc88acdca87fe7858628d (diff)
Dissect PA Profile IO data
Diffstat (limited to 'plugins/epan')
-rw-r--r--plugins/epan/profinet/packet-dcerpc-pn-io.c15
-rw-r--r--plugins/epan/profinet/packet-pn-rtc-one.c226
-rw-r--r--plugins/epan/profinet/packet-pn.h3
3 files changed, 238 insertions, 6 deletions
diff --git a/plugins/epan/profinet/packet-dcerpc-pn-io.c b/plugins/epan/profinet/packet-dcerpc-pn-io.c
index 1fca9ab2ba..d2968cdcf8 100644
--- a/plugins/epan/profinet/packet-dcerpc-pn-io.c
+++ b/plugins/epan/profinet/packet-dcerpc-pn-io.c
@@ -3160,8 +3160,8 @@ static const value_string pn_io_pa_profile_physical_block_parent_class_vals[] =
static const value_string pn_io_pa_profile_function_block_class_vals[] = {
{ 1, "Input" },
{ 2, "Output" },
- { 3, "Further Inputs" },
- { 4, "Further Outputs" },
+ { 3, "Further Input" },
+ { 4, "Further Output" },
{ 128, "Manuf. specific Input" },
{ 129, "Manuf. specific Output" },
{ 0, NULL }
@@ -10935,6 +10935,7 @@ dissect_DataDescription(tvbuff_t *tvb, int offset,
io_data_object = (ioDataObject*)wmem_list_frame_data(frame);
if (io_data_object->slotNr == tmp_io_data_object->slotNr && io_data_object->subSlotNr == tmp_io_data_object->subSlotNr) {
/* Write additional data from dissect_ExpectedSubmoduleBlockReq_block() to corresponding io_data_object */
+ io_data_object->api = tmp_io_data_object->api;
io_data_object->moduleIdentNr = tmp_io_data_object->moduleIdentNr;
io_data_object->subModuleIdentNr = tmp_io_data_object->subModuleIdentNr;
io_data_object->length = u16SubmoduleDataLength;
@@ -11010,8 +11011,16 @@ resolve_pa_profile_submodule_name(ioDataObject *io_data_object)
break;
case PA_PROFILE_BLOCK_FB:
- parent_class_name = try_val_to_str(parent_class, pn_io_pa_profile_function_block_parent_class_vals);
class_name = try_val_to_str(class, pn_io_pa_profile_function_block_class_vals);
+ if (class <= 2u)
+ {
+ parent_class_name = try_val_to_str(parent_class, pn_io_pa_profile_function_block_parent_class_vals);
+ }
+ else
+ {
+ parent_class_name = (class <= 4u) ? "Analog" : "";
+ }
+
if ((parent_class_name != NULL) && (class_name != NULL))
{
(void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - %s %s", block_object_name, parent_class_name, class_name);
diff --git a/plugins/epan/profinet/packet-pn-rtc-one.c b/plugins/epan/profinet/packet-pn-rtc-one.c
index 037330faaa..9c8e1df979 100644
--- a/plugins/epan/profinet/packet-pn-rtc-one.c
+++ b/plugins/epan/profinet/packet-pn-rtc-one.c
@@ -69,6 +69,7 @@
#define PN_INPUT_CR 1 /* PROFINET Input Connect Request value */
#define PN_INPUT_DATADESCRITPION 1 /* PROFINET Input Data Description value */
+#define PA_PROFILE_API 0x9700u
static int proto_pn_io_rtc1 = -1;
@@ -122,9 +123,22 @@ static int hf_pn_io_ps_cb_toggelBitChange_subslot_nr = -1;
static int hf_pn_io_ps_f_dest_adr = -1;
static int hf_pn_io_ps_f_data = -1;
+/* PA Profile 4.02 */
+static int hf_pn_pa_profile_status = -1;
+static int hf_pn_pa_profile_status_quality = -1;
+static int hf_pn_pa_profile_status_substatus_bad = -1;
+static int hf_pn_pa_profile_status_substatus_uncertain = -1;
+static int hf_pn_pa_profile_status_substatus_good = -1;
+static int hf_pn_pa_profile_status_update_event = -1;
+static int hf_pn_pa_profile_status_simulate = -1;
+static int hf_pn_pa_profile_value_8bit = -1;
+static int hf_pn_pa_profile_value_16bit = -1;
+static int hf_pn_pa_profile_value_float = -1;
+
static gint ett_pn_io_rtc = -1;
static gint ett_pn_io_ioxs = -1;
static gint ett_pn_io_io_data_object = -1;
+static gint ett_pn_pa_profile_status = -1;
static expert_field ei_pn_io_too_many_data_objects = EI_INIT;
@@ -148,6 +162,53 @@ static const value_string pn_io_ioxs_datastate[] = {
{ 0, NULL }
};
+static const value_string pn_pa_profile_status_quality[] = {
+ { 0x00 /* 0*/, "BAD" },
+ { 0x01 /* 1*/, "UNCERTAIN" },
+ { 0x02 /* 2*/, "GOOD" },
+ { 0, NULL }
+};
+
+static const value_string pn_pa_profile_status_substatus_bad[] = {
+ { 0x0, "Non specific" },
+ { 0x2, "Not connected" },
+ { 0x8, "Passivated" },
+ { 0x9, "Maintenance alarm, more diagnosis" },
+ { 0xA, "Process related, no maintenance" },
+ { 0xF, "Function check, value not usable" },
+ { 0, NULL }
+};
+
+static const value_string pn_pa_profile_status_substatus_uncertain[] = {
+ { 0x2, "Substitute set" },
+ { 0x3, "Initial value" },
+ { 0xA, "Maintenance demanded" },
+ { 0xE, "Process related, no maintenance" },
+ { 0, NULL }
+};
+
+static const value_string pn_pa_profile_status_substatus_good[] = {
+ { 0x0, "Good" },
+ { 0x7, "Local override" },
+ { 0x8, "Initial fail safe" },
+ { 0x9, "Maintenance required" },
+ { 0xA, "Maintenance demanded" },
+ { 0xF, "Function check" },
+ { 0, NULL }
+};
+
+static const value_string pn_pa_profile_status_update_event[] = {
+ { 0x0, "No event" },
+ { 0x1, "Update event" },
+ { 0, NULL }
+};
+
+static const value_string pn_pa_profile_status_simulate[] = {
+ { 0x0, "Simulation off" },
+ { 0x1, "Simulation active" },
+ { 0, NULL }
+};
+
static int * const ps_sb_fields[] = {
&hf_pn_io_ps_sb_res,
@@ -181,6 +242,17 @@ static int * const ioxs_fields[] = {
NULL
};
+/*
+static int * const pa_profile_status_fields[] = {
+ &hf_pn_pa_profile_status_quality,
+ &hf_pn_pa_profile_status_substatus_bad,
+ &hf_pn_pa_profile_status_substatus_uncertain,
+ &hf_pn_pa_profile_status_substatus_good,
+ &hf_pn_pa_profile_status_update_event,
+ &hf_pn_pa_profile_status_simulate,
+ NULL
+};
+*/
/* Dissector for PROFIsafe Status Byte */
static int
@@ -594,7 +666,14 @@ dissect_PNIO_C_SDU_RTC1(tvbuff_t *tvb, int offset,
else {
/* Module is not PROFIsafe supported */
- offset = dissect_pn_user_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data");
+ if (io_data_object->api == PA_PROFILE_API)
+ {
+ offset = dissect_pn_pa_profile_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data");
+ }
+ else
+ {
+ offset = dissect_pn_user_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data");
+ }
}
if (io_data_object->discardIOXS == FALSE) {
@@ -794,7 +873,14 @@ dissect_PNIO_C_SDU_RTC1(tvbuff_t *tvb, int offset,
} /* End of PROFIsafe Module Handling */
else {
/* Module is not PROFIsafe supported */
- offset = dissect_pn_user_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data");
+ if (io_data_object->api == PA_PROFILE_API)
+ {
+ offset = dissect_pn_pa_profile_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data");
+ }
+ else
+ {
+ offset = dissect_pn_user_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data");
+ }
}
if (io_data_object->discardIOXS == FALSE) {
@@ -881,6 +967,89 @@ dissect_PNIO_C_SDU_RTC1(tvbuff_t *tvb, int offset,
}
+/* dissect the PA Profile status field */
+static int
+dissect_pn_pa_profile_status(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree, int hfindex)
+{
+
+ if (tree) {
+ guint8 u8status;
+ guint8 quality;
+ proto_item *status_item;
+ proto_tree *status_tree;
+ const gchar* quality_name = NULL;
+
+ u8status = tvb_get_guint8(tvb, offset);
+ quality = (u8status >> 6u) & 0x3u;
+
+ /* add ioxs subtree */
+ status_item = proto_tree_add_uint(tree, hfindex, tvb, offset, 1, u8status);
+
+ quality_name = try_val_to_str(quality, pn_pa_profile_status_quality);
+
+ proto_item_append_text(status_item,
+ " (%s)",
+ (quality_name != NULL) ? quality_name : "invalid");
+
+ status_tree = proto_item_add_subtree(status_item, ett_pn_pa_profile_status);
+
+ proto_tree_add_uint(status_tree, hf_pn_pa_profile_status_quality, tvb, offset, 1, u8status);
+ switch(quality)
+ {
+ case 0:
+ proto_tree_add_uint(status_tree, hf_pn_pa_profile_status_substatus_bad, tvb, offset, 1, u8status);
+ break;
+ case 1:
+ proto_tree_add_uint(status_tree, hf_pn_pa_profile_status_substatus_uncertain, tvb, offset, 1, u8status);
+ break;
+ case 2:
+ proto_tree_add_uint(status_tree, hf_pn_pa_profile_status_substatus_good, tvb, offset, 1, u8status);
+ break;
+ default:
+ break;
+ }
+ proto_tree_add_uint(status_tree, hf_pn_pa_profile_status_update_event, tvb, offset, 1, u8status);
+ proto_tree_add_uint(status_tree, hf_pn_pa_profile_status_simulate, tvb, offset, 1, u8status);
+ }
+
+ return offset + 1;
+}
+
+int
+dissect_pn_pa_profile_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint32 length, const char *text)
+{
+ (void)text;
+ /*
+ All PA Profile submodules carry an 8-bit "status" plus the real data, which
+ currently is a float, an 8-bit integer or a 16-bit integer.
+ So we will have either 2, 3 or 5 bytes.
+ */
+ if (length == 2u)
+ {
+ proto_tree_add_item(tree, hf_pn_pa_profile_value_8bit, tvb, offset, 1, ENC_BIG_ENDIAN);
+ dissect_pn_pa_profile_status(tvb, offset+1, pinfo, tree, hf_pn_pa_profile_status);
+ }
+ else if (length == 3u)
+ {
+ proto_tree_add_item(tree, hf_pn_pa_profile_value_16bit, tvb, offset, 2, ENC_BIG_ENDIAN);
+ dissect_pn_pa_profile_status(tvb, offset+2, pinfo, tree, hf_pn_pa_profile_status);
+ }
+ else if (length == 5u)
+ {
+ proto_tree_add_item(tree, hf_pn_pa_profile_value_float, tvb, offset, 4, ENC_BIG_ENDIAN);
+ dissect_pn_pa_profile_status(tvb, offset+4, pinfo, tree, hf_pn_pa_profile_status);
+ }
+ else
+ {
+ /* Delegate to standard user data if unknown */
+ (void)dissect_pn_user_data(tvb, offset, pinfo, tree, length, "IO Data");
+ }
+
+ return offset + length;
+}
+
void
init_pn_io_rtc1(int proto)
{
@@ -1099,12 +1268,63 @@ init_pn_io_rtc1(int proto)
FT_UINT64, BASE_HEX, NULL, 0x0,
NULL, HFILL }
},
+ { &hf_pn_pa_profile_status,
+ { "Status", "pn_io.pa.status",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_pn_pa_profile_status_quality,
+ { "Quality", "pn_io.pa.status.quality",
+ FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_quality), 0xC0,
+ NULL, HFILL }
+ },
+ { &hf_pn_pa_profile_status_substatus_bad,
+ { "Substatus", "pn_io.pa.status.substatus",
+ FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_substatus_bad), 0x3C,
+ NULL, HFILL }
+ },
+ { &hf_pn_pa_profile_status_substatus_uncertain,
+ { "Substatus", "pn_io.pa.status.substatus",
+ FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_substatus_uncertain), 0x3C,
+ NULL, HFILL }
+ },
+ { &hf_pn_pa_profile_status_substatus_good,
+ { "Substatus", "pn_io.pa.status.substatus",
+ FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_substatus_good), 0x3C,
+ NULL, HFILL }
+ },
+ { &hf_pn_pa_profile_status_update_event,
+ { "Update Event", "pn_io.pa.status.update",
+ FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_update_event), 0x02,
+ NULL, HFILL }
+ },
+ { &hf_pn_pa_profile_status_simulate,
+ { "Simulate", "pn_io.pa.status.simulate",
+ FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_simulate), 0x01,
+ NULL, HFILL }
+ },
+ { &hf_pn_pa_profile_value_8bit,
+ { "Value", "pn_io.pa.value",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_pn_pa_profile_value_16bit,
+ { "Value", "pn_io.pa.value",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_pn_pa_profile_value_float,
+ { "Value", "pn_io.pa.value",
+ FT_FLOAT, BASE_FLOAT, NULL, 0x0,
+ NULL, HFILL }
+ },
};
static gint *ett[] = {
&ett_pn_io_rtc,
&ett_pn_io_ioxs,
- &ett_pn_io_io_data_object
+ &ett_pn_io_io_data_object,
+ &ett_pn_pa_profile_status
};
static ei_register_info ei[] = {
diff --git a/plugins/epan/profinet/packet-pn.h b/plugins/epan/profinet/packet-pn.h
index d8b93d857f..f2c0743d6f 100644
--- a/plugins/epan/profinet/packet-pn.h
+++ b/plugins/epan/profinet/packet-pn.h
@@ -150,6 +150,9 @@ extern int dissect_pn_undecoded(tvbuff_t *tvb, int offset, packet_info *pinfo,
extern int dissect_pn_user_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree, guint32 length, const char *text);
+extern int dissect_pn_pa_profile_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint32 length, const char *text);
+
extern int dissect_blocks(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, guint8 *drep);