diff options
author | Matthias Dietrich <matthias.dietrich@gmx.fr> | 2022-05-15 20:54:35 +0200 |
---|---|---|
committer | A Wireshark GitLab Utility <gerald+gitlab-utility@wireshark.org> | 2022-05-21 07:52:07 +0000 |
commit | 225e90564d1b52fc99ddc88acdca87fe7858628d (patch) | |
tree | 08ca0b555eb906981a3f79298c746c8354b54252 /plugins | |
parent | c552665fd332543f7e6175c4d6a213ad2c6266df (diff) |
Resolve PA Profile 4.02 submodule names
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/epan/profinet/packet-dcerpc-pn-io.c | 353 | ||||
-rw-r--r-- | plugins/epan/profinet/packet-pn.h | 1 |
2 files changed, 354 insertions, 0 deletions
diff --git a/plugins/epan/profinet/packet-dcerpc-pn-io.c b/plugins/epan/profinet/packet-dcerpc-pn-io.c index b11faa8cc3..1fca9ab2ba 100644 --- a/plugins/epan/profinet/packet-dcerpc-pn-io.c +++ b/plugins/epan/profinet/packet-dcerpc-pn-io.c @@ -82,6 +82,27 @@ void proto_reg_handoff_pn_io(void); #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 +#define PA_PROFILE_DAP_MASK 0xFFFF0000u +#define PA_PROFILE_DAP_IDENT 0x00FD0000u + +#define PA_PROFILE_BLOCK_DAP 0u +#define PA_PROFILE_BLOCK_PB 1u +#define PA_PROFILE_BLOCK_FB 2u +#define PA_PROFILE_BLOCK_TB 3u + +#define PA_PROFILE_TB_PARENT_PRESSURE 1u +#define PA_PROFILE_TB_PARENT_TEMPERATURE 2u +#define PA_PROFILE_TB_PARENT_FLOW 3u +#define PA_PROFILE_TB_PARENT_LEVEL 1u +#define PA_PROFILE_TB_PARENT_ACTUATOR 1u +#define PA_PROFILE_TB_PARENT_DISCRETE_IO 1u +#define PA_PROFILE_TB_PARENT_LIQUID_ANALYZER 1u +#define PA_PROFILE_TB_PARENT_GAS_ANALYZER 1u +#define PA_PROFILE_TB_PARENT_ENUMERATED_IO 1u +#define PA_PROFILE_TB_PARENT_BINARY_IO 1u + + static int proto_pn_io = -1; static int proto_pn_io_device = -1; @@ -3110,6 +3131,227 @@ static const value_string pn_io_tsn_port_capabilities_queue_masking_vals[] = { { 0, NULL } }; +/* Format of submodule ident number as per PA Profile 4.02 specification: + [VariantOfSubmodule, Block_object, Parent_Class, Class] */ +static const value_string pn_io_pa_profile_block_object_vals[] = { + { 0, "DAP" }, + { 1, "PB" }, + { 2, "FB" }, + { 3, "TB" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_dap_submodule_vals[] = { + { 1, "DAP" }, + { 2, "Device Management" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_physical_block_parent_class_vals[] = { + { 1, "Transmitter" }, + { 2, "Actuator" }, + { 3, "Discrete I/O" }, + { 4, "Controller" }, + { 5, "Analyzer" }, + { 6, "Lab Device" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_function_block_class_vals[] = { + { 1, "Input" }, + { 2, "Output" }, + { 3, "Further Inputs" }, + { 4, "Further Outputs" }, + { 128, "Manuf. specific Input" }, + { 129, "Manuf. specific Output" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_function_block_parent_class_vals[] = { + {0, "Analog Temperature" }, + {1, "Analog Temperature Difference"}, + {2, "Analog Average Temperature"}, + {3, "Analog Electronics Temperature"}, + {4, "Analog Transmitter Temperature"}, + {5, "Analog Sensor Temperature"}, + {6, "Analog Frame Temperature"}, + {7, "Analog Auxiliary Temperature"}, + {8, "Analog Energy Supply Temperature"}, + {9, "Analog Energy Return Temperature"}, + {20, "Analog Pressure"}, + {21, "Analog Absolute Pressure"}, + {22, "Analog Gauge Pressure"}, + {23, "Analog Differential Pressure"}, + {30, "Analog Level"}, + {31, "Analog Distance"}, + {32, "Analog Interface Level"}, + {33, "Analog Interface Distance"}, + {40, "Analog Volume"}, + {41, "Analog Ullage"}, + {42, "Analog Interface Volume"}, + {43, "Analog Standard Volume"}, + {44, "Analog Fraction Substance 1 Volume"}, + {45, "Analog Fraction Substance 2 Volume"}, + {46, "Analog Fraction Substance 1 Std Volume"}, + {47, "Analog Fraction Substance 2 Std Volume"}, + {50, "Analog Mass"}, + {51, "Analog Net Mass"}, + {52, "Analog Fraction Substance 1 Mass"}, + {53, "Analog Fraction Substance 2 Mass"}, + {60, "Analog Volume Flow"}, + {61, "Analog Standard Volume Flow"}, + {62, "Analog Fraction Substance 1 Volume Flow"}, + {63, "Analog Fraction Substance 2 Volume Flow"}, + {70, "Analog Mass Flow"}, + {71, "Analog Fraction Substance 1 Mass Flow"}, + {72, "Analog Fraction Substance 2 Mass Flow"}, + {80, "Analog Density"}, + {81, "Analog Standard Density"}, + {82, "Analog Analog Api Gravity"}, + {83, "Analog Standard Api Gravity"}, + {84, "Analog Specific Gravity"}, + {85, "Analog Standard Specific Gravity"}, + {90, "Analog Flow Velocity"}, + {91, "Analog Sound Velocity"}, + {92, "Analog Rate Of Change"}, + {100, "Analog Kinematic Viscosity"}, + {101, "Analog Dynamic Viscosity"}, + {110, "Analog Energy"}, + {111, "Analog Power"}, + {120, "Analog Vortex Frequency"}, + {130, "Analog Concentration"}, + {131, "Analog Energy Efficiency Rating"}, + {132, "Analog Coefficient Of Performance"}, + {133, "Analog Fraction Substance 1%"}, + {134, "Analog Fraction Substance 2%"}, + {140, "Analog pH"}, + {141, "Analog Conductivity"}, + {142, "Analog Resistivity"}, + {143, "Analog Gas Concentration"}, + {149, "Flexible AI"}, + {150, "Totalizer"}, + {160, "Actuator"}, + {170, "Discrete"}, + {180, "Enumerated"}, + {190, "Binary(8 Bit)"}, + {191, "Binary(16 Bit)"}, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_parent_class_vals[] = { + { 1, "Pressure" }, + { 2, "Temperature" }, + { 3, "Flow" }, + { 4, "Level" }, + { 5, "Actuator" }, + { 6, "Discrete I/O" }, + { 7, "Liquid analyzer" }, + { 8, "Gas analyzer" }, + { 10, "Enumerated I/O" }, + { 11, "Binary I/O" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_pressure_class_vals[] = { + { 1, "Pressure" }, + { 2, "Pressure + level" }, + { 3, "Pressure + flow" }, + { 4, "Pressure + level + flow" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_temperature_class_vals[] = { + { 1, "Thermocouple (TC)" }, + { 2, "Resistance thermometer (RTD)" }, + { 3, "Pyrometer" }, + { 16, "TC + DC U (DC Voltage)" }, + { 17, "RTD + R (R-Resistance)" }, + { 18, "TC+RTD+r+DC U" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_flow_class_vals[] = { + { 1, "Electromagnetic" }, + { 2, "Vortex" }, + { 3, "Coriolis" }, + { 4, "Thermal mass" }, + { 5, "Ultrasonic" }, + { 6, "Variable area" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_level_class_vals[] = { + { 1, "Hydrostatic" }, + { 2, "Ultrasonic" }, + { 3, "Radiometric" }, + { 4, "Capacitance" }, + { 5, "Displacer" }, + { 6, "Float" }, + { 7, "Radar" }, + { 8, "Buoyancy" }, + { 9, "Air bubble system" }, + { 10, "Gravimetric" }, + { 11, "Optical" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_actuator_class_vals[] = { + { 1, "Electric" }, + { 2, "Electro-pneumatic" }, + { 3, "Electro-hydraulic" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_discrete_io_class_vals[] = { + { 1, "Input" }, + { 2, "Output" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_liquid_analyzer_class_vals[] = { + { 1, "pH" }, + { 2, "Conductivity" }, + { 3, "Oxygen" }, + { 4, "Chlorine" }, + { 5, "Resistivity" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_gas_analyzer_class_vals[] = { + { 1, "Standard" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_enumerated_io_class_vals[] = { + { 1, "Input" }, + { 2, "Output" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_binary_io_class_vals[] = { + { 2, "8 Bit output" }, + { 3, "8 Bit input" }, + { 4, "16 Bit output" }, + { 5, "16 Bit input" }, + { 0, NULL } +}; + +static const value_string* pn_io_pa_profile_transducer_block_class_vals[] = { + NULL, + pn_io_pa_profile_transducer_block_pressure_class_vals, + pn_io_pa_profile_transducer_block_temperature_class_vals, + pn_io_pa_profile_transducer_block_flow_class_vals, + pn_io_pa_profile_transducer_block_level_class_vals, + pn_io_pa_profile_transducer_block_actuator_class_vals, + pn_io_pa_profile_transducer_block_discrete_io_class_vals, + pn_io_pa_profile_transducer_block_liquid_analyzer_class_vals, + pn_io_pa_profile_transducer_block_gas_analyzer_class_vals, + NULL, + pn_io_pa_profile_transducer_block_enumerated_io_class_vals, + pn_io_pa_profile_transducer_block_binary_io_class_vals +}; + + static int dissect_profidrive_value(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, guint8 format_val) @@ -10713,6 +10955,100 @@ dissect_DataDescription(tvbuff_t *tvb, int offset, } +static int +resolve_pa_profile_submodule_name(ioDataObject *io_data_object) +{ + const uint32_t u32SubmoduleIdentNumber = io_data_object->subModuleIdentNr; + /* split components of submodule ident number */ + const uint8_t variant = (u32SubmoduleIdentNumber >> 24u) & 0xFFu; + const uint8_t block_object = (u32SubmoduleIdentNumber >> 16u) & 0xFFu; + const uint8_t parent_class = (u32SubmoduleIdentNumber >> 8u) & 0xFFu; + const uint8_t class = (u32SubmoduleIdentNumber) & 0xFFu; + + const gchar* parent_class_name = NULL; + const gchar* class_name = NULL; + + const gchar* block_object_name = try_val_to_str(block_object, pn_io_pa_profile_block_object_vals); + + if (block_object_name != NULL) + { + switch (block_object) + { + case PA_PROFILE_BLOCK_DAP: + if (parent_class == 0u) + { + class_name = try_val_to_str(class, pn_io_pa_profile_dap_submodule_vals); + if (class_name != NULL) + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - %s", block_object_name, class_name); + } + } + else + { + /* we have an interface or a port */ + if (class == 0u) + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "Interface %d", parent_class); + } + else + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "Port %d Interface %d", class, parent_class); + } + } + break; + + case PA_PROFILE_BLOCK_PB: + parent_class_name = try_val_to_str(parent_class, pn_io_pa_profile_physical_block_parent_class_vals); + if (parent_class_name != NULL) + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - %s", block_object_name, parent_class_name); + } + else + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - Unknown", block_object_name); + } + 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 ((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); + } + else + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - Unknown", block_object_name); + } + break; + + case PA_PROFILE_BLOCK_TB: + parent_class_name = try_val_to_str(parent_class, pn_io_pa_profile_transducer_block_parent_class_vals); + if (parent_class_name != NULL) + { + class_name = try_val_to_str(class, pn_io_pa_profile_transducer_block_class_vals[parent_class]); + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - %s (%s)", block_object_name, parent_class_name, class_name); + } + else + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - Unknown", block_object_name); + } + break; + } + + if (variant != 0u) + { + g_strlcat (io_data_object->moduleNameStr, " (VARIANT)", MAX_NAMELENGTH); + } + + return 1; + } + else + { + return 0; + } +} + /* dissect the ExpectedSubmoduleBlockReq */ static int dissect_ExpectedSubmoduleBlockReq_block(tvbuff_t *tvb, int offset, @@ -10966,12 +11302,29 @@ dissect_ExpectedSubmoduleBlockReq_block(tvbuff_t *tvb, int offset, offset = dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, hf_pn_io_submodule_properties_type, &u16SubmoduleProperties); + io_data_object->api = u32Api; io_data_object->slotNr = u16SlotNr; io_data_object->subSlotNr = u16SubslotNr; io_data_object->moduleIdentNr = u32ModuleIdentNumber; io_data_object->subModuleIdentNr = u32SubmoduleIdentNumber; io_data_object->discardIOXS = u16SubmoduleProperties & 0x0020; + /* Before searching the GSD, check if we have a PA Profile 4.02 submodule. If yes + then the submodule's name is defined in the specification and can be resolved + without the GSD. + We still read the GSD afterwards, in case the user wants to override the specification's + names with a GSD. + Most PA Profile submodules are located in API 0x9700, but the DAP and the interfaces/ports + are located in API 0 per PROFINET specification, so we need to filter also on the DAP module + ident number. + */ + if ((io_data_object->api == PA_PROFILE_API) || + ((io_data_object->moduleIdentNr & PA_PROFILE_DAP_MASK) == PA_PROFILE_DAP_IDENT)) + { + resolve_pa_profile_submodule_name(io_data_object); + } + + /* Search the moduleID and subModuleID, find if PROFIsafe and also search for F-Par. Indexnumber * --------------------------------------------------------------------------------------------- * Speical case: Module has several ModuleIdentNr. in one GSD-file diff --git a/plugins/epan/profinet/packet-pn.h b/plugins/epan/profinet/packet-pn.h index 4833cd76f6..d8b93d857f 100644 --- a/plugins/epan/profinet/packet-pn.h +++ b/plugins/epan/profinet/packet-pn.h @@ -74,6 +74,7 @@ typedef struct tagIocsObject { typedef struct tagIoDataObject { guint16 slotNr; guint16 subSlotNr; + guint32 api; guint32 moduleIdentNr; guint32 subModuleIdentNr; guint16 frameOffset; |