diff options
Diffstat (limited to 'epan/dissectors/packet-mq.c')
-rw-r--r-- | epan/dissectors/packet-mq.c | 328 |
1 files changed, 165 insertions, 163 deletions
diff --git a/epan/dissectors/packet-mq.c b/epan/dissectors/packet-mq.c index 8fc793d889..db39d3d834 100644 --- a/epan/dissectors/packet-mq.c +++ b/epan/dissectors/packet-mq.c @@ -3574,191 +3574,192 @@ static void dissect_mq_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) } } -static void reassemble_mq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +static int reassemble_mq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { + mq_parm_t mq_parm; + /* Reassembly of the MQ messages that span several PDU (several TSH) */ /* Typically a TCP PDU is 1460 bytes and a MQ PDU is 32766 bytes */ - if (tvb_length(tvb) >= 28) - { - mq_parm_t mq_parm; + if (tvb_length(tvb) < 28) + return 0; - memset(&mq_parm,0,sizeof(mq_parm_t)); - mq_parm.mq_strucID = tvb_get_ntohl(tvb, 0); + memset(&mq_parm,0,sizeof(mq_parm_t)); + mq_parm.mq_strucID = tvb_get_ntohl(tvb, 0); - if ( (mq_parm.mq_strucID & MQ_MASK_TSHx) == MQ_STRUCTID_TSHx || (mq_parm.mq_strucID & MQ_MASK_TSHx) == MQ_STRUCTID_TSHx_EBCDIC ) + if ( (mq_parm.mq_strucID & MQ_MASK_TSHx) == MQ_STRUCTID_TSHx || (mq_parm.mq_strucID & MQ_MASK_TSHx) == MQ_STRUCTID_TSHx_EBCDIC ) + { + guint8 iCtlF = 0; + gint32 iSegL = 0; + gint32 iBegL = 0; + gint32 iEnco = 0; + gint32 iMulS = 0; + gint32 iHdrL = 0; + gint32 iNxtP = 0; + guint8 iOpcd = 0; + gboolean bSeg1st = FALSE; + gboolean bSegLst = FALSE; + gboolean bMore = FALSE; + + gint32 iHdl = 0; + gint32 iGlbMsgIdx = 0; + gint32 iSegLength = 0; + gint16 iSegmIndex = 0; + + guint32 uStrL = 0; + guint32 uPadL = 0; + + /* TSHM structure as 8 bytes more after the length (convid/requestid) */ + if (mq_parm.mq_strucID == MQ_STRUCTID_TSHM || mq_parm.mq_strucID == MQ_STRUCTID_TSHM_EBCDIC) + iMulS=8; + + /* Get the Encoding scheme */ + iEnco = (tvb_get_guint8(tvb, 8+iMulS) == MQ_LITTLE_ENDIAN ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN); + /* Get the Operation Code */ + iOpcd = tvb_get_guint8(tvb, 9+iMulS); + /* Get the Control Flag */ + iCtlF = tvb_get_guint8(tvb, 10+iMulS); + /* Get the Semgnet Length */ + iSegL = tvb_get_ntohl (tvb, 4); + /* First Segment ? */ + bSeg1st = ((iCtlF & MQ_TCF_FIRST) != 0); + /* Last Segment */ + bSegLst = ((iCtlF & MQ_TCF_LAST) != 0); + + mq_in_reassembly=FALSE; + + if ((iOpcd > 0x80 && !(bSeg1st && bSegLst)) || iOpcd==MQ_TST_ASYNC_MESSAGE) { - guint8 iCtlF = 0; - gint32 iSegL = 0; - gint32 iBegL = 0; - gint32 iEnco = 0; - gint32 iMulS = 0; - gint32 iHdrL = 0; - gint32 iNxtP = 0; - guint8 iOpcd = 0; - gboolean bSeg1st = FALSE; - gboolean bSegLst = FALSE; - gboolean bMore = FALSE; - - gint32 iHdl = 0; - gint32 iGlbMsgIdx = 0; - gint32 iSegLength = 0; - gint16 iSegmIndex = 0; - - guint32 uStrL = 0; - guint32 uPadL = 0; - - /* TSHM structure as 8 bytes more after the length (convid/requestid) */ - if (mq_parm.mq_strucID == MQ_STRUCTID_TSHM || mq_parm.mq_strucID == MQ_STRUCTID_TSHM_EBCDIC) - iMulS=8; - - /* Get the Encoding scheme */ - iEnco = (tvb_get_guint8(tvb, 8+iMulS) == MQ_LITTLE_ENDIAN ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN); - /* Get the Operation Code */ - iOpcd = tvb_get_guint8(tvb, 9+iMulS); - /* Get the Control Flag */ - iCtlF = tvb_get_guint8(tvb, 10+iMulS); - /* Get the Semgnet Length */ - iSegL = tvb_get_ntohl (tvb, 4); - /* First Segment ? */ - bSeg1st = ((iCtlF & MQ_TCF_FIRST) != 0); - /* Last Segment */ - bSegLst = ((iCtlF & MQ_TCF_LAST) != 0); - - mq_in_reassembly=FALSE; - - if ((iOpcd > 0x80 && !(bSeg1st && bSegLst)) || iOpcd==MQ_TST_ASYNC_MESSAGE) + proto_tree* mq_tree = NULL; + + /* Optimisation : only fragmented segments go through the reassembly process */ + /* + It seems that after a PUT on a Queue, when doing a GET, MQ first get + a small part of the response (4096 bytes) + The response contain the number of bytes returned for this request (ActMsgLen) + and the total number of bytes of this reply (TotMsgLen) + + this mean the flow seems to be : + + PUT + REQUEST_MSG (MaxLen=4096) + ASYNC_MSG (1st/Lst Segment, ActMsgLen=4096, TotMsgLen=279420) + as ActMsgLen!=TotMsgLen, this mean the MSG is not complete, we only receive some of 279420 bytes + REQUEST_MSG (MaxLen=279420) + ASYNC_MSG (1st Segment, SegIndex=0 ActMsgLen=279420, TotMsgLen=279420) + ASYNC_MSG (Mid Segment, SegIndex=1) + ASYNC_MSG (Mid Segment, SegIndex=2) + . + ASYNC_MSG (Lst Segment, SegIndex=n) + End of reassembling (we have 279420 bytes to decode) + */ + + if (mq_reassembly) { - proto_tree* mq_tree = NULL; + fragment_head* fd_head; + guint32 iConnectionId = (pinfo->srcport + pinfo->destport); + iHdrL=28+iMulS; + + /* Get the MQ Handle of the Object */ + iHdl = tvb_get_guint32_endian(tvb, iHdrL + 4, iEnco); + /* Get the Global Message Index */ + iGlbMsgIdx = tvb_get_guint32_endian(tvb, iHdrL + 12, iEnco); + /* Get the Segment Length */ + iSegLength = tvb_get_guint32_endian(tvb, iHdrL + 16, iEnco); + /* Get the Segment Index */ + iSegmIndex = tvb_get_guint16_endian(tvb, iHdrL +20, iEnco); + + /* + if SegmIndex==0, it has 54 bytes + the length and padding + of a variable string at the end of the Header + */ + if (iSegmIndex==0) + { + uStrL = tvb_get_guint8(tvb,iHdrL+54); + uPadL = ((((2+1+uStrL)/4)+1)*4)-(2+1+uStrL); + } + bMore=!bSegLst; + /* + First segment has a longer header + */ + iNxtP = iHdrL + ((bSeg1st)?(54 + 1 + uStrL + uPadL):(24)); + iNxtP += dissect_mq_md(tvb, NULL, iNxtP, &mq_parm, FALSE); - /* Optimisation : only fragmented segments go through the reassembly process */ /* - It seems that after a PUT on a Queue, when doing a GET, MQ first get - a small part of the response (4096 bytes) - The response contain the number of bytes returned for this request (ActMsgLen) - and the total number of bytes of this reply (TotMsgLen) - - this mean the flow seems to be : - - PUT - REQUEST_MSG (MaxLen=4096) - ASYNC_MSG (1st/Lst Segment, ActMsgLen=4096, TotMsgLen=279420) - as ActMsgLen!=TotMsgLen, this mean the MSG is not complete, we only receive some of 279420 bytes - REQUEST_MSG (MaxLen=279420) - ASYNC_MSG (1st Segment, SegIndex=0 ActMsgLen=279420, TotMsgLen=279420) - ASYNC_MSG (Mid Segment, SegIndex=1) - ASYNC_MSG (Mid Segment, SegIndex=2) - . - ASYNC_MSG (Lst Segment, SegIndex=n) - End of reassembling (we have 279420 bytes to decode) + if it is the 1st Segment, it means we are + of the beginning of a reassembling. We must take the whole segment (with tSHM, and headers) */ + iBegL = (bSeg1st)?0:iNxtP; + + fd_head = fragment_add_seq_next(&mq_reassembly_table, + tvb, iBegL, + pinfo, iConnectionId, NULL, + iSegL - iBegL, bMore); - if (mq_reassembly) + if (tree) { - fragment_head* fd_head; - guint32 iConnectionId = (pinfo->srcport + pinfo->destport); - iHdrL=28+iMulS; - - /* Get the MQ Handle of the Object */ - iHdl = tvb_get_guint32_endian(tvb, iHdrL + 4, iEnco); - /* Get the Global Message Index */ - iGlbMsgIdx = tvb_get_guint32_endian(tvb, iHdrL + 12, iEnco); - /* Get the Segment Length */ - iSegLength = tvb_get_guint32_endian(tvb, iHdrL + 16, iEnco); - /* Get the Segment Index */ - iSegmIndex = tvb_get_guint16_endian(tvb, iHdrL +20, iEnco); - - /* - if SegmIndex==0, it has 54 bytes + the length and padding - of a variable string at the end of the Header - */ - if (iSegmIndex==0) - { - uStrL = tvb_get_guint8(tvb,iHdrL+54); - uPadL = ((((2+1+uStrL)/4)+1)*4)-(2+1+uStrL); - } - bMore=!bSegLst; - /* - First segment has a longer header - */ - iNxtP = iHdrL + ((bSeg1st)?(54 + 1 + uStrL + uPadL):(24)); - iNxtP += dissect_mq_md(tvb, NULL, iNxtP, &mq_parm, FALSE); - - /* - if it is the 1st Segment, it means we are - of the beginning of a reassembling. We must take the whole segment (with tSHM, and headers) - */ - iBegL = (bSeg1st)?0:iNxtP; - - fd_head = fragment_add_seq_next(&mq_reassembly_table, - tvb, iBegL, - pinfo, iConnectionId, NULL, - iSegL - iBegL, bMore); - - if (tree) - { - proto_item* ti = proto_tree_add_item(tree, proto_mq, tvb, 0, -1, ENC_NA); - if (bMore) - proto_item_append_text(ti, " [%s of a Reassembled MQ Segment] Hdl=0x%08x GlbMsgIdx=%d, SegIdx=%d, SegLen=%d", - val_to_str(iOpcd, mq_opcode_vals, "Unknown (0x%02x)"), - iHdl, iGlbMsgIdx, iSegmIndex, iSegLength); - else - proto_item_append_text(ti, " %s Hdl=0x%08x GlbMsgIdx=%d, SegIdx=%d, SegLen=%d", - val_to_str(iOpcd, mq_opcode_vals, "Unknown (0x%02x)"), - iHdl, iGlbMsgIdx, iSegmIndex, iSegLength); - mq_tree = proto_item_add_subtree(ti, ett_mq_reaasemb); - } + proto_item* ti = proto_tree_add_item(tree, proto_mq, tvb, 0, -1, ENC_NA); + if (bMore) + proto_item_append_text(ti, " [%s of a Reassembled MQ Segment] Hdl=0x%08x GlbMsgIdx=%d, SegIdx=%d, SegLen=%d", + val_to_str(iOpcd, mq_opcode_vals, "Unknown (0x%02x)"), + iHdl, iGlbMsgIdx, iSegmIndex, iSegLength); else - { - mq_tree=tree; - } + proto_item_append_text(ti, " %s Hdl=0x%08x GlbMsgIdx=%d, SegIdx=%d, SegLen=%d", + val_to_str(iOpcd, mq_opcode_vals, "Unknown (0x%02x)"), + iHdl, iGlbMsgIdx, iSegmIndex, iSegLength); + mq_tree = proto_item_add_subtree(ti, ett_mq_reaasemb); + } + else + { + mq_tree=tree; + } - if (fd_head != NULL && pinfo->fd->num == fd_head->reassembled_in) - { - tvbuff_t* next_tvb; + if (fd_head != NULL && pinfo->fd->num == fd_head->reassembled_in) + { + tvbuff_t* next_tvb; - /* Reassembly finished */ - if (fd_head->next != NULL) - { - /* 2 or more fragments */ - next_tvb = tvb_new_chain(tvb, fd_head->tvb_data); - add_new_data_source(pinfo, next_tvb, "Reassembled MQ"); - } - else - { - /* Only 1 fragment */ - next_tvb = tvb; - } - dissect_mq_pdu(next_tvb, pinfo, mq_tree); - return; + /* Reassembly finished */ + if (fd_head->next != NULL) + { + /* 2 or more fragments */ + next_tvb = tvb_new_chain(tvb, fd_head->tvb_data); + add_new_data_source(pinfo, next_tvb, "Reassembled MQ"); } else { - mq_in_reassembly=TRUE; - /* Reassembly in progress */ - col_set_str(pinfo->cinfo, COL_PROTOCOL, "MQ"); - col_add_fstr(pinfo->cinfo, COL_INFO, "[%s of a Reassembled MQ Segment] Hdl=0x%08x GlbMsgIdx=%d, SegIdx=%d, SegLen=%d", - val_to_str(iOpcd, mq_opcode_vals, "Unknown (0x%02x)"), - iHdl, iGlbMsgIdx, iSegmIndex, iSegLength); - dissect_mq_pdu(tvb, pinfo, mq_tree); - return; + /* Only 1 fragment */ + next_tvb = tvb; } + dissect_mq_pdu(next_tvb, pinfo, mq_tree); + return tvb_length(tvb); } else { + mq_in_reassembly=TRUE; + /* Reassembly in progress */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "MQ"); + col_add_fstr(pinfo->cinfo, COL_INFO, "[%s of a Reassembled MQ Segment] Hdl=0x%08x GlbMsgIdx=%d, SegIdx=%d, SegLen=%d", + val_to_str(iOpcd, mq_opcode_vals, "Unknown (0x%02x)"), + iHdl, iGlbMsgIdx, iSegmIndex, iSegLength); dissect_mq_pdu(tvb, pinfo, mq_tree); - if (bSeg1st) - { - /* MQ segment is the first of a unreassembled series */ - col_append_str(pinfo->cinfo, COL_INFO, " [Unreassembled MQ]"); - } - return; + return tvb_length(tvb); } } - /* Reassembly not enabled or non-fragmented message */ - dissect_mq_pdu(tvb, pinfo, tree); - return; + else + { + dissect_mq_pdu(tvb, pinfo, mq_tree); + if (bSeg1st) + { + /* MQ segment is the first of a unreassembled series */ + col_append_str(pinfo->cinfo, COL_INFO, " [Unreassembled MQ]"); + } + return tvb_length(tvb); + } } + /* Reassembly not enabled or non-fragmented message */ + dissect_mq_pdu(tvb, pinfo, tree); } + + return tvb_length(tvb); } static guint get_mq_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset) @@ -3774,9 +3775,10 @@ static guint get_mq_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset) return 0; } -static void dissect_mq_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +static int dissect_mq_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { - tcp_dissect_pdus(tvb, pinfo, tree, mq_desegment, 28, get_mq_pdu_len, reassemble_mq); + tcp_dissect_pdus(tvb, pinfo, tree, mq_desegment, 28, get_mq_pdu_len, reassemble_mq, data); + return tvb_length(tvb); } static void dissect_mq_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) @@ -3785,7 +3787,7 @@ static void dissect_mq_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) dissect_mq_pdu(tvb, pinfo, tree); } -static gboolean dissect_mq_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint iProto, void *data _U_) +static gboolean dissect_mq_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint iProto, void *data) { if (tvb_length(tvb) >= 28) { @@ -3799,7 +3801,7 @@ static gboolean dissect_mq_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t if (iProto == MQ_XPT_TCP) conversation_set_dissector(conversation, mq_tcp_handle); /* Dissect the packet */ - reassemble_mq(tvb, pinfo, tree); + reassemble_mq(tvb, pinfo, tree, data); return TRUE; } } @@ -4428,7 +4430,7 @@ void proto_reg_handoff_mq(void) * class of applications (web browser, e-mail client, ...) and have a very well * known port number, the MQ applications are most often specific to a business application */ - mq_tcp_handle = create_dissector_handle(dissect_mq_tcp, proto_mq); + mq_tcp_handle = new_create_dissector_handle(dissect_mq_tcp, proto_mq); mq_spx_handle = create_dissector_handle(dissect_mq_spx, proto_mq); dissector_add_handle("tcp.port", mq_tcp_handle); |