PROFINET: Rsi dissection errors are fixed.

According to specification, size of PROFINETIOServiceResPDU
is calculated and checked under dissect_RSI_RSP_block
function. Moreover, dissect_rsi_blocks function is added and
type of PDU and operation number (Opnum) are checked before
dissection starts.
This commit is contained in:
Basak Kalfa 2021-04-07 23:44:07 -07:00 committed by Wireshark GitLab Utility
parent dbdfe53538
commit e04ea5c108
3 changed files with 97 additions and 22 deletions

View File

@ -11311,6 +11311,68 @@ dissect_IPNIO_Write_resp(tvbuff_t *tvb, int offset,
}
/* dissect any number of PN-RSI blocks */
int
dissect_rsi_blocks(tvbuff_t* tvb, int offset,
packet_info* pinfo, proto_tree* tree, guint8* drep, guint32 u32FOpnumOffsetOpnum, int type)
{
pnio_ar_t* ar = NULL;
guint recursion_count = 0;
guint16 u16Index = 0;
guint32 u32RecDataLen = 0;
switch (u32FOpnumOffsetOpnum) {
case(0x0): // Connect request or response
offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
break;
case(0x2): // Read request or response
offset = dissect_RecordDataRead(tvb, offset, pinfo, tree, drep, u16Index, u32RecDataLen);
break;
case(0x3): // Write request or response
if (type == PDU_TYPE_REQ)
offset = dissect_IODWriteReq(tvb, offset, pinfo, tree, drep, &ar, recursion_count);
else if (type == PDU_TYPE_RSP)
offset = dissect_IODWriteRes(tvb, offset, pinfo, tree, drep);
break;
case(0x4): // Control request or response
offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
break;
case(0x5): // ReadImplicit request or response
offset = dissect_RecordDataRead(tvb, offset, pinfo, tree, drep, u16Index, u32RecDataLen);
break;
case(0x6): // ReadConnectionless request or response
offset = dissect_RecordDataRead(tvb, offset, pinfo, tree, drep, u16Index, u32RecDataLen);
break;
case(0x7): // ReadNotification request or response
offset = dissect_RecordDataRead(tvb, offset, pinfo, tree, drep, u16Index, u32RecDataLen);
break;
case(0x8): // PrmWriteMore request or response
if (type == PDU_TYPE_REQ)
offset = dissect_IODWriteReq(tvb, offset, pinfo, tree, drep, &ar, recursion_count);
else if (type == PDU_TYPE_RSP)
offset = dissect_IODWriteRes(tvb, offset, pinfo, tree, drep);
break;
case(0x9): // PrmWriteEnd request or response
if (type == PDU_TYPE_REQ)
offset = dissect_IODWriteReq(tvb, offset, pinfo, tree, drep, &ar, recursion_count);
else if (type == PDU_TYPE_RSP)
offset = dissect_IODWriteRes(tvb, offset, pinfo, tree, drep);
break;
default:
col_append_str(pinfo->cinfo, COL_INFO, "Reserved");
offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length(tvb));
break;
}
if (ar != NULL) {
pnio_ar_info(tvb, pinfo, tree, ar);
}
return offset;
}
/* dissect the IOxS (IOCS, IOPS) field */
static int
dissect_PNIO_IOxS(tvbuff_t *tvb, int offset,

View File

@ -295,7 +295,7 @@ static const fragment_items pn_rsi_frag_items = {
static int
dissect_pn_rta_remaining_user_data_bytes(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
proto_tree *tree, guint8 *drep, guint32 length, guint8 u8MoreFrag)
proto_tree *tree, guint8 *drep, guint32 length, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOpnum, int type)
{
fragment_head *fd_frag;
fragment_head *fd_reass;
@ -366,7 +366,7 @@ dissect_pn_rta_remaining_user_data_bytes(tvbuff_t *tvb, int offset, packet_info
payload_item = proto_tree_add_item(tree, hf_pn_rsi_data_payload, next_tvb, 0, tvb_captured_length(next_tvb), ENC_NA);
payload_tree = proto_item_add_subtree(payload_item, ett_pn_rsi_data_payload);
offset = dissect_blocks(next_tvb, 0, pinfo, payload_tree, drep);
offset = dissect_rsi_blocks(next_tvb, 0, pinfo, payload_tree, drep, u32FOpnumOffsetOpnum, type);
/* the toplevel fragment subtree is now behind all desegmented data,
* move it right behind the DE2 tree item */
@ -390,7 +390,7 @@ dissect_pn_rta_remaining_user_data_bytes(tvbuff_t *tvb, int offset, packet_info
/* dissect a PN-IO RSI SVCS block (on top of PN-RT protocol) */
static int
dissect_RSI_SVCS_block(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, guint8 *drep, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOffset)
packet_info *pinfo, proto_tree *tree, guint8 *drep, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOffset, guint32 u32FOpnumOffsetOpnum)
{
proto_item *sub_item;
proto_tree *sub_tree;
@ -410,14 +410,14 @@ dissect_RSI_SVCS_block(tvbuff_t *tvb, int offset,
}
offset = dissect_pn_rta_remaining_user_data_bytes(tvb, offset, pinfo, sub_tree, drep,
tvb_captured_length_remaining(tvb, offset), u8MoreFrag);
tvb_captured_length_remaining(tvb, offset), u8MoreFrag, u32FOpnumOffsetOpnum, PDU_TYPE_REQ);
return offset;
}
/* dissect a PN-IO RSI CONN block (on top of PN-RT protocol) */
static int
dissect_RSI_CONN_block(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, guint8 *drep, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOffset)
packet_info *pinfo, proto_tree *tree, guint8 *drep, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOffset, guint32 u32FOpnumOffsetOpnum)
{
proto_item *sub_item;
proto_tree *sub_tree;
@ -452,7 +452,7 @@ dissect_RSI_CONN_block(tvbuff_t *tvb, int offset,
}
offset = dissect_pn_rta_remaining_user_data_bytes(tvb, offset, pinfo, sub_tree, drep,
tvb_captured_length_remaining(tvb, offset), u8MoreFrag);
tvb_captured_length_remaining(tvb, offset), u8MoreFrag, u32FOpnumOffsetOpnum, PDU_TYPE_REQ);
return offset;
}
@ -471,7 +471,7 @@ dissect_FREQ_RTA_block(tvbuff_t *tvb, int offset,
switch (u32FOpnumOffsetOpnum) {
case(0x0): /* RSI-CONN-PDU */
col_append_str(pinfo->cinfo, COL_INFO, "Connect request");
offset = dissect_RSI_CONN_block(tvb, offset, pinfo, tree, drep, u8MoreFrag,u32FOpnumOffsetOffset);
offset = dissect_RSI_CONN_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
break;
case(0x1): /* Reserved */
col_append_str(pinfo->cinfo, COL_INFO, "Reserved");
@ -479,35 +479,35 @@ dissect_FREQ_RTA_block(tvbuff_t *tvb, int offset,
break;
case(0x2): /* RSI-SVCS-PDU (Only valid with ARUUID<>0) */
col_append_str(pinfo->cinfo, COL_INFO, "Read request");
offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset);
offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
break;
case(0x3): /* RSI-SVCS-PDU */
col_append_str(pinfo->cinfo, COL_INFO, "Write request");
offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset);
offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
break;
case(0x4): /* RSI-SVCS-PDU */
col_append_str(pinfo->cinfo, COL_INFO, "Control request");
offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset);
offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
break;
case(0x5): /* RSI-CONN-PDU (Only valid with ARUUID=0) */
col_append_str(pinfo->cinfo, COL_INFO, "ReadImplicit request");
offset = dissect_RSI_CONN_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset);
offset = dissect_RSI_CONN_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
break;
case(0x6): /* RSI-CONN-PDU (Only valid with ARUUID<>0) */
col_append_str(pinfo->cinfo, COL_INFO, "ReadConnectionless request");
offset = dissect_RSI_CONN_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset);
offset = dissect_RSI_CONN_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
break;
case(0x7): /* RSI-SVCS-PDU */
col_append_str(pinfo->cinfo, COL_INFO, "ReadNotification request");
offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset);
offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
break;
case(0x8): /* RSI-SVCS-PDU */
col_append_str(pinfo->cinfo, COL_INFO, "PrmWriteMore request");
offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset);
offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
break;
case(0x9) : /* RSI-SVCS-PDU */
col_append_str(pinfo->cinfo, COL_INFO, "PrmWriteEnd request");
offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset);
offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
break;
default:
col_append_str(pinfo->cinfo, COL_INFO, "Reserved");
@ -520,8 +520,13 @@ dissect_FREQ_RTA_block(tvbuff_t *tvb, int offset,
/* dissect a PN-IO RSI RSP block (on top of PN-RT protocol) */
static int
dissect_RSI_RSP_block(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, guint8 *drep, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOffset)
packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 u16VarPartLen, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOffset, guint32 u32FOpnumOffsetOpnum)
{
guint32 u32RsiHeaderSize = 4;
// PDU.FOpnumOffset.Offset + PDU.VarPartLen - 4 - RsiHeaderSize
gint32 length = u32FOpnumOffsetOffset + u16VarPartLen - 4 - u32RsiHeaderSize;
if (u32FOpnumOffsetOffset == 0)
{
offset = dissect_PNIO_status(tvb, offset, pinfo, tree, drep);
@ -532,15 +537,18 @@ dissect_RSI_RSP_block(tvbuff_t *tvb, int offset,
proto_item_append_text(tree, ", RSI Header of RSP is at first fragmented frame");
}
offset = dissect_pn_rta_remaining_user_data_bytes(tvb, offset, pinfo, tree, drep,
tvb_captured_length_remaining(tvb, offset), u8MoreFrag);
if (length > 0) {
offset = dissect_pn_rta_remaining_user_data_bytes(tvb, offset, pinfo, tree, drep,
tvb_captured_length_remaining(tvb, offset), u8MoreFrag, u32FOpnumOffsetOpnum, PDU_TYPE_RSP);
}
return offset;
}
/* dissect a PN-IO RSI FRSP RTA PDU (on top of PN-RT protocol) */
static int
dissect_FRSP_RTA_block(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, guint8 *drep, guint8 u8MoreFrag)
packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 u16VarPartLen, guint8 u8MoreFrag)
{
guint32 u32FOpnumOffset;
guint32 u32FOpnumOffsetOpnum;
@ -583,7 +591,7 @@ dissect_FRSP_RTA_block(tvbuff_t *tvb, int offset,
col_append_str(pinfo->cinfo, COL_INFO, "Reserved");
break;
}
offset = dissect_RSI_RSP_block(tvb, offset, pinfo, tree, drep, u8MoreFrag, u32FOpnumOffsetOffset);
offset = dissect_RSI_RSP_block(tvb, offset, pinfo, tree, drep, u16VarPartLen, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum);
return offset;
}
@ -705,7 +713,7 @@ dissect_PNIO_RSI(tvbuff_t *tvb, int offset,
offset = dissect_FREQ_RTA_block(tvb, offset, pinfo, rta_tree, drep, u8MoreFrag);
break;
case(6): /* FRSP-RTA */
offset = dissect_FRSP_RTA_block(tvb, offset, pinfo, rta_tree, drep, u8MoreFrag);
offset = dissect_FRSP_RTA_block(tvb, offset, pinfo, rta_tree, drep, u16VarPartLen, u8MoreFrag);
break;
default:
offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length(tvb));

View File

@ -148,6 +148,11 @@ extern int dissect_pn_user_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U
extern int dissect_blocks(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, guint8 *drep);
#define PDU_TYPE_REQ 0x05
#define PDU_TYPE_RSP 0x06
extern int dissect_rsi_blocks(tvbuff_t* tvb, int offset, packet_info* pinfo, proto_tree* tree, guint8* drep, guint32 u32FOpnumOffsetOpnum, int type);
#define SUBST_DATA 1
#define FRAG_DATA 2
@ -170,7 +175,7 @@ extern int dissect_PNIO_C_SDU_RTC1(tvbuff_t* tvb, int offset, packet_info* pinfo
extern int dissect_PNIO_RSI(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, guint8 *drep);
extern int dissect_PDRsiInstances_block(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow);