* Routines for IBM WebSphere MQ PCF packet dissection
*
* metatech <metatech@flashmail.com>
- *
- * $Id$
+ * robionekenobi <robionekenobi@bluewin.ch>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* MQ PCF in a nutshell
-*
-* The MQ Programmable Command Formats API allows remotely configuring a queue manager.
-*
-* MQ PCF documentation is called "WebSphere MQ Programmable Command Formats and Administration Interface"
+ *
+ * The MQ Programmable Command Formats API allows remotely configuring a queue manager.
+ *
+ * MQ PCF documentation is called "WebSphere MQ Programmable Command Formats and Administration Interface"
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
-#include <string.h>
+#include <math.h>
-#include <glib.h>
#include <epan/packet.h>
+#include <epan/expert.h>
+#include <epan/prefs.h>
+#include <epan/strutil.h>
+
#include "packet-mq.h"
+void proto_register_mqpcf(void);
+void proto_reg_handoff_mqpcf(void);
+
+#define PCF_MAX_PARM 999
+#define PCF_MAX_LIST 20000
+
+guint mq_pcf_maxprm = PCF_MAX_PARM;
+guint mq_pcf_maxlst = PCF_MAX_LIST;
+
static int proto_mqpcf = -1;
+
static int hf_mqpcf_cfh_type = -1;
static int hf_mqpcf_cfh_length = -1;
static int hf_mqpcf_cfh_version = -1;
static int hf_mqpcf_cfh_command = -1;
-static int hf_mqpcf_cfh_msgseqnumber = -1;
+static int hf_mqpcf_cfh_MsgSeqNbr = -1;
static int hf_mqpcf_cfh_control = -1;
static int hf_mqpcf_cfh_compcode = -1;
static int hf_mqpcf_cfh_reason = -1;
-static int hf_mqpcf_cfh_paramcount = -1;
+static int hf_mqpcf_cfh_ParmCount = -1;
+
+static int hf_mq_pcf_prmtyp = -1;
+static int hf_mq_pcf_prmlen = -1;
+static int hf_mq_pcf_prmid = -1;
+static int hf_mq_pcf_prmidnovals = -1;
+static int hf_mq_pcf_filterop = -1;
+static int hf_mq_pcf_prmccsid = -1;
+static int hf_mq_pcf_prmstrlen = -1;
+static int hf_mq_pcf_prmcount = -1;
+static int hf_mq_pcf_prmunused = -1;
+
+static int hf_mq_pcf_string = -1;
+static int hf_mq_pcf_stringlist = -1;
+static int hf_mq_pcf_int = -1;
+static int hf_mq_pcf_intlist = -1;
+static int hf_mq_pcf_bytestring = -1;
+static int hf_mq_pcf_int64 = -1;
+static int hf_mq_pcf_int64list = -1;
+
+static expert_field ei_mq_pcf_prmln0 = EI_INIT;
+static expert_field ei_mq_pcf_MaxInt = EI_INIT;
+static expert_field ei_mq_pcf_MaxStr = EI_INIT;
+static expert_field ei_mq_pcf_MaxI64 = EI_INIT;
+static expert_field ei_mq_pcf_MaxPrm = EI_INIT;
+static expert_field ei_mq_pcf_PrmCnt = EI_INIT;
+static gint ett_mqpcf_prm = -1;
static gint ett_mqpcf = -1;
static gint ett_mqpcf_cfh = -1;
-#define MQ_FMT_ADMIN "MQADMIN "
-#define MQ_FMT_EVENT "MQEVENT "
-#define MQ_FMT_PCF "MQPCF "
-
-#define MQ_ENC_INTEGER_NORMAL 0x00000001
-#define MQ_ENC_INTEGER_REVERSED 0x00000002
-
-#define MQ_CMD_NONE 0
-#define MQ_CMD_CHANGE_Q_MGR 1
-#define MQ_CMD_INQUIRE_Q_MGR 2
-#define MQ_CMD_CHANGE_PROCESS 3
-#define MQ_CMD_COPY_PROCESS 4
-#define MQ_CMD_CREATE_PROCESS 5
-#define MQ_CMD_DELETE_PROCESS 6
-#define MQ_CMD_INQUIRE_PROCESS 7
-#define MQ_CMD_CHANGE_Q 8
-#define MQ_CMD_CLEAR_Q 9
-#define MQ_CMD_COPY_Q 10
-#define MQ_CMD_CREATE_Q 11
-#define MQ_CMD_DELETE_Q 12
-#define MQ_CMD_INQUIRE_Q 13
-#define MQ_CMD_RESET_Q_STATS 17
-#define MQ_CMD_INQUIRE_Q_NAMES 18
-#define MQ_CMD_INQUIRE_PROCESS_NAMES 19
-#define MQ_CMD_INQUIRE_CHANNEL_NAMES 20
-#define MQ_CMD_CHANGE_CHANNEL 21
-#define MQ_CMD_COPY_CHANNEL 22
-#define MQ_CMD_CREATE_CHANNEL 23
-#define MQ_CMD_DELETE_CHANNEL 24
-#define MQ_CMD_INQUIRE_CHANNEL 25
-#define MQ_CMD_PING_CHANNEL 26
-#define MQ_CMD_RESET_CHANNEL 27
-#define MQ_CMD_START_CHANNEL 28
-#define MQ_CMD_STOP_CHANNEL 29
-#define MQ_CMD_START_CHANNEL_INIT 30
-#define MQ_CMD_START_CHANNEL_LISTENER 31
-#define MQ_CMD_CHANGE_NAMELIST 32
-#define MQ_CMD_COPY_NAMELIST 33
-#define MQ_CMD_CREATE_NAMELIST 34
-#define MQ_CMD_DELETE_NAMELIST 35
-#define MQ_CMD_INQUIRE_NAMELIST 36
-#define MQ_CMD_INQUIRE_NAMELIST_NAMES 37
-#define MQ_CMD_ESCAPE 38
-#define MQ_CMD_RESOLVE_CHANNEL 39
-#define MQ_CMD_PING_Q_MGR 40
-#define MQ_CMD_INQUIRE_Q_STATUS 41
-#define MQ_CMD_INQUIRE_CHANNEL_STATUS 42
-#define MQ_CMD_CONFIG_EVENT 43
-#define MQ_CMD_Q_MGR_EVENT 44
-#define MQ_CMD_PERFM_EVENT 45
-#define MQ_CMD_CHANNEL_EVENT 46
-#define MQ_CMD_DELETE_PUBLICATION 60
-#define MQ_CMD_DEREGISTER_PUBLISHER 61
-#define MQ_CMD_DEREGISTER_SUBSCRIBER 62
-#define MQ_CMD_PUBLISH 63
-#define MQ_CMD_REGISTER_PUBLISHER 64
-#define MQ_CMD_REGISTER_SUBSCRIBER 65
-#define MQ_CMD_REQUEST_UPDATE 66
-#define MQ_CMD_BROKER_INTERNAL 67
-#define MQ_CMD_INQUIRE_CLUSTER_Q_MGR 70
-#define MQ_CMD_RESUME_Q_MGR_CLUSTER 71
-#define MQ_CMD_SUSPEND_Q_MGR_CLUSTER 72
-#define MQ_CMD_REFRESH_CLUSTER 73
-#define MQ_CMD_RESET_CLUSTER 74
-#define MQ_CMD_REFRESH_SECURITY 78
-#define MQ_CMD_CHANGE_AUTH_INFO 79
-#define MQ_CMD_COPY_AUTH_INFO 80
-#define MQ_CMD_CREATE_AUTH_INFO 81
-#define MQ_CMD_DELETE_AUTH_INFO 82
-#define MQ_CMD_INQUIRE_AUTH_INFO 83
-#define MQ_CMD_INQUIRE_AUTH_INFO_NAMES 84
-
#define MQ_TEXT_CFH "MQ Command Format Header"
-static const value_string mqpcf_opcode_vals[] = {
- { MQ_CMD_NONE, "NONE" },
- { MQ_CMD_CHANGE_Q_MGR, "CHANGE_Q_MGR" },
- { MQ_CMD_INQUIRE_Q_MGR, "INQUIRE_Q_MGR" },
- { MQ_CMD_CHANGE_PROCESS, "CHANGE_PROCESS" },
- { MQ_CMD_COPY_PROCESS, "COPY_PROCESS" },
- { MQ_CMD_CREATE_PROCESS, "CREATE_PROCESS" },
- { MQ_CMD_DELETE_PROCESS, "DELETE_PROCESS" },
- { MQ_CMD_INQUIRE_PROCESS, "INQUIRE_PROCESS" },
- { MQ_CMD_CHANGE_Q, "CHANGE_Q" },
- { MQ_CMD_CLEAR_Q, "CLEAR_Q" },
- { MQ_CMD_COPY_Q, "COPY_Q" },
- { MQ_CMD_CREATE_Q, "CREATE_Q" },
- { MQ_CMD_DELETE_Q, "DELETE_Q" },
- { MQ_CMD_INQUIRE_Q, "INQUIRE_Q" },
- { MQ_CMD_RESET_Q_STATS, "RESET_Q_STATS" },
- { MQ_CMD_INQUIRE_Q_NAMES, "INQUIRE_Q_NAMES" },
- { MQ_CMD_INQUIRE_PROCESS_NAMES, "INQUIRE_PROCESS_NAMES" },
- { MQ_CMD_INQUIRE_CHANNEL_NAMES, "INQUIRE_CHANNEL_NAMES" },
- { MQ_CMD_CHANGE_CHANNEL, "CHANGE_CHANNEL" },
- { MQ_CMD_COPY_CHANNEL, "COPY_CHANNEL" },
- { MQ_CMD_CREATE_CHANNEL, "CREATE_CHANNEL" },
- { MQ_CMD_DELETE_CHANNEL, "DELETE_CHANNEL" },
- { MQ_CMD_INQUIRE_CHANNEL, "INQUIRE_CHANNEL" },
- { MQ_CMD_PING_CHANNEL, "PING_CHANNEL" },
- { MQ_CMD_RESET_CHANNEL, "RESET_CHANNEL" },
- { MQ_CMD_START_CHANNEL, "START_CHANNEL" },
- { MQ_CMD_STOP_CHANNEL, "STOP_CHANNEL" },
- { MQ_CMD_START_CHANNEL_INIT, "START_CHANNEL_INIT" },
- { MQ_CMD_START_CHANNEL_LISTENER, "START_CHANNEL_LISTENER" },
- { MQ_CMD_CHANGE_NAMELIST, "CHANGE_NAMELIST" },
- { MQ_CMD_CREATE_NAMELIST, "CREATE_NAMELIST" },
- { MQ_CMD_DELETE_NAMELIST, "DELETE_NAMELIST" },
- { MQ_CMD_INQUIRE_NAMELIST, "INQUIRE_NAMELIST" },
- { MQ_CMD_INQUIRE_NAMELIST_NAMES, "INQUIRE_NAMELIST_NAMES" },
- { MQ_CMD_ESCAPE, "ESCAPE" },
- { MQ_CMD_RESOLVE_CHANNEL, "RESOLVE_CHANNEL" },
- { MQ_CMD_PING_Q_MGR, "PING_Q_MGR" },
- { MQ_CMD_INQUIRE_Q_STATUS, "INQUIRE_Q_STATUS" },
- { MQ_CMD_INQUIRE_CHANNEL_STATUS, "INQUIRE_CHANNEL_STATUS" },
- { MQ_CMD_CONFIG_EVENT, "CONFIG_EVENT" },
- { MQ_CMD_Q_MGR_EVENT, "Q_MGR_EVENT" },
- { MQ_CMD_PERFM_EVENT, "PERFM_EVENT" },
- { MQ_CMD_CHANNEL_EVENT, "CHANNEL_EVENT" },
- { MQ_CMD_DELETE_PUBLICATION, "DELETE_PUBLICATION" },
- { MQ_CMD_DEREGISTER_PUBLISHER, "DEREGISTER_PUBLISHER" },
- { MQ_CMD_DEREGISTER_SUBSCRIBER, "DEREGISTER_SUBSCRIBER" },
- { MQ_CMD_PUBLISH, "PUBLISH" },
- { MQ_CMD_REGISTER_PUBLISHER, "REGISTER_PUBLISHER" },
- { MQ_CMD_REGISTER_SUBSCRIBER, "REGISTER_SUBSCRIBER" },
- { MQ_CMD_REQUEST_UPDATE, "REQUEST_UPDATE" },
- { MQ_CMD_BROKER_INTERNAL, "BROKER_INTERNAL" },
- { MQ_CMD_INQUIRE_CLUSTER_Q_MGR, "INQUIRE_CLUSTER_Q_MGR" },
- { MQ_CMD_RESUME_Q_MGR_CLUSTER, "RESUME_Q_MGR_CLUSTER" },
- { MQ_CMD_SUSPEND_Q_MGR_CLUSTER, "SUSPEND_Q_MGR_CLUSTER" },
- { MQ_CMD_REFRESH_CLUSTER, "REFRESH_CLUSTER" },
- { MQ_CMD_REFRESH_SECURITY, "REFRESH_SECURITY" },
- { MQ_CMD_CHANGE_AUTH_INFO, "CHANGE_AUTH_INFO" },
- { MQ_CMD_COPY_AUTH_INFO, "COPY_AUTH_INFO" },
- { MQ_CMD_CREATE_AUTH_INFO, "CREATE_AUTH_INFO" },
- { MQ_CMD_DELETE_AUTH_INFO, "DELETE_AUTH_INFO" },
- { MQ_CMD_INQUIRE_AUTH_INFO, "INQUIRE_AUTH_INFO" },
- { MQ_CMD_INQUIRE_AUTH_INFO_NAMES, "INQUIRE_AUTH_INFO_NAMES" },
- { 0, NULL }
-};
-
-static guint32 tvb_get_guint32_endian(tvbuff_t *a_tvb, gint a_iOffset, gboolean a_bLittleEndian)
+static guint32 dissect_mqpcf_getDigits(guint uCnt)
{
- guint32 iResult;
- if (a_bLittleEndian)
- iResult = tvb_get_letohl(a_tvb, a_iOffset);
- else
- iResult = tvb_get_ntohl(a_tvb, a_iOffset);
- return iResult;
+ return (guint32)(log10( (double)uCnt ) + 1);
+}
+/*
+* Here we get a special value_string, that return another value_string
+* pointer instead of string value. This let us use the try_val_to_str
+* to get val_to_str value from the value of a parameter on a more
+* easier way than using switch cases
+*/
+static const guint8 *dissect_mqpcf_parm_getintval(guint uPrm, guint uVal)
+{
+ const value_string *pVs;
+ pVs = (const value_string *)try_val_to_str_ext(uPrm, GET_VALS_EXTP(MQCFINT_Parse));
+
+ if (pVs)
+ {
+ return (const guint8 *)try_val_to_str(uVal, pVs);
+ }
+ return NULL;
}
-static void
-dissect_mqpcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static void dissect_mqpcf_parm_int(tvbuff_t *tvb, proto_tree *tree, guint offset, guint uPrm,
+ guint uVal, int hfindex, guint iCnt, guint iMaxCnt,
+ guint iDigit, gboolean bParse)
{
- proto_tree *mq_tree = NULL;
- proto_tree *mqroot_tree = NULL;
- proto_item *ti = NULL;
- gint offset = 0;
- struct mqinfo* mqinfo = pinfo->private_data;
- gboolean bLittleEndian;
- bLittleEndian = ((mqinfo->encoding & MQ_ENC_INTEGER_REVERSED) != 0) ? TRUE : FALSE;
-
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "MQ PCF");
- col_clear(pinfo->cinfo, COL_INFO);
- if (tvb_length(tvb) >= 36)
- {
- gint iSizeMQCFH = 36;
- guint32 iCommand = tvb_get_guint32_endian(tvb, offset + 12, bLittleEndian);
-
- if (check_col(pinfo->cinfo, COL_INFO))
- {
- col_append_str(pinfo->cinfo, COL_INFO, val_to_str(iCommand, mqpcf_opcode_vals, "Unknown (0x%02x)"));
- }
-
- if (tree)
- {
- ti = proto_tree_add_item(tree, proto_mqpcf, tvb, offset, -1, FALSE);
- proto_item_append_text(ti, " (%s)", val_to_str(iCommand, mqpcf_opcode_vals, "Unknown (0x%02x)"));
- mqroot_tree = proto_item_add_subtree(ti, ett_mqpcf);
-
- ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeMQCFH, MQ_TEXT_CFH);
- mq_tree = proto_item_add_subtree(ti, ett_mqpcf_cfh);
-
- proto_tree_add_item(mq_tree, hf_mqpcf_cfh_type, tvb, offset + 0, 4, bLittleEndian);
- proto_tree_add_item(mq_tree, hf_mqpcf_cfh_length, tvb, offset + 4, 4, bLittleEndian);
- proto_tree_add_item(mq_tree, hf_mqpcf_cfh_version, tvb, offset + 8, 4, bLittleEndian);
- proto_tree_add_item(mq_tree, hf_mqpcf_cfh_command, tvb, offset + 12, 4, bLittleEndian);
- proto_tree_add_item(mq_tree, hf_mqpcf_cfh_msgseqnumber, tvb, offset + 16, 4, bLittleEndian);
- proto_tree_add_item(mq_tree, hf_mqpcf_cfh_control, tvb, offset + 20, 4, bLittleEndian);
- proto_tree_add_item(mq_tree, hf_mqpcf_cfh_compcode, tvb, offset + 24, 4, bLittleEndian);
- proto_tree_add_item(mq_tree, hf_mqpcf_cfh_reason, tvb, offset + 28, 4, bLittleEndian);
- proto_tree_add_item(mq_tree, hf_mqpcf_cfh_paramcount, tvb, offset + 32, 4, bLittleEndian);
- }
- offset += iSizeMQCFH;
- }
+ header_field_info *hfinfo;
+ const guint8 *pVal = NULL;
+
+ if (bParse)
+ pVal = dissect_mqpcf_parm_getintval(uPrm, uVal);
+
+ hfinfo = proto_registrar_get_nth(hfindex);
+
+ if (iMaxCnt > 1)
+ {
+ if (pVal)
+ {
+ proto_tree_add_int_format(tree, hfindex, tvb, offset, 4, uVal,
+ "%s[%*d]: %8x-(%9d)-%s", hfinfo->name, iDigit, iCnt, uVal, uVal, pVal);
+ }
+ else
+ {
+ proto_tree_add_int_format(tree, hfindex, tvb, offset, 4, uVal,
+ "%s[%*d]: %8x-(%9d)", hfinfo->name, iDigit, iCnt, uVal, uVal);
+ }
+ }
+ else
+ {
+ if (pVal)
+ {
+ proto_tree_add_int_format_value(tree, hfindex, tvb, offset, 4, uVal,
+ "%8x-(%9d)-%s", uVal, uVal, pVal);
+ }
+ else
+ {
+ proto_tree_add_int_format_value(tree, hfindex, tvb, offset, 4, uVal,
+ "%8x-(%9d)", uVal, uVal);
+ }
+ }
}
-static gboolean
-dissect_mqpcf_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+void dissect_mqpcf_parm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mq_tree,
+ guint offset, guint32 uCount, guint bLittleEndian, gboolean bParse)
{
- if (tvb_length(tvb) >= 36)
- {
- struct mqinfo* mqinfo = pinfo->private_data;
- if (strncmp((const char*)mqinfo->format, MQ_FMT_ADMIN, 8) == 0
- || strncmp((const char*)mqinfo->format, MQ_FMT_EVENT, 8) == 0
- || strncmp((const char*)mqinfo->format, MQ_FMT_PCF, 8) == 0)
- {
- /* Dissect the packet */
- dissect_mqpcf(tvb, pinfo, tree);
- return TRUE;
- }
- }
- return FALSE;
+ guint32 u = 0;
+ guint32 tOfs = 0;
+ guint32 uLenF;
+ char strPrm[256];
+ guint32 uTyp;
+ guint32 uLen = 0;
+ guint32 uPrm;
+ guint32 uCnt;
+ guint32 uCCS;
+ guint32 uSLn;
+ guint32 uVal;
+ guint64 uVal64;
+ guint32 uDig;
+
+ const char sMaxLst[] = " Max # of List reached. DECODE interrupted (actual %u of %u)";
+ const char sPrmLn0[] = " MQPrm[%3u] has a zero length. DECODE Failed (MQPrm Count: %u)";
+ const char sMaxPrm[] = " Max # of Parm reached. DECODE interrupted (actual %u of %u)";
+ const char sPrmCnt[] = " Cnt=-1 and Length(%u) < 16. DECODE interrupted for elem %u";
+
+ proto_item *ti = NULL;
+ proto_tree *tree = NULL;
+
+ if (uCount == (guint32)-1)
+ {
+ guint32 xOfs = offset;
+
+ uCnt = 0;
+ while (tvb_reported_length_remaining(tvb, xOfs) >= 16)
+ {
+ uLen = tvb_get_guint32(tvb, xOfs + 4, bLittleEndian);
+ if (uLen < 16)
+ {
+ proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_PrmCnt, tvb, xOfs, 16, sPrmCnt, uLen, uCnt);
+ break;
+ }
+ uCnt++;
+ xOfs += uLen;
+ }
+ uCount = uCnt;
+ }
+
+ uDig = dissect_mqpcf_getDigits(uCount);
+
+ for (u = 0; u < uCount && u < mq_pcf_maxprm; u++)
+ {
+ tOfs = offset;
+ uTyp = tvb_get_guint32(tvb, offset , bLittleEndian);
+ uLen = tvb_get_guint32(tvb, offset + 4, bLittleEndian);
+ if (uLen == 0)
+ {
+ proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_prmln0, tvb, offset, 12, sPrmLn0, u+1, uCount);
+ u = uCount;
+ break;
+ }
+ uPrm = tvb_get_guint32(tvb, offset + 8, bLittleEndian);
+ uLenF = 12;
+
+ if (bParse)
+ g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d-%-30.30s",
+ "MQPrm", uDig, u+1,
+ uTyp, val_to_str_ext_const(uTyp, GET_VALS_EXTP(PrmTyp), " Unknown") + 6,
+ uPrm, uPrm, val_to_str_ext_const(uPrm, GET_VALS_EXTP(PrmId), "Unknown"));
+ else
+ g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d",
+ "XtraD", uDig, u+1,
+ uTyp, val_to_str_ext_const(uTyp, GET_VALS_EXTP(PrmTyp), " Unknown") + 6,
+ uPrm, uPrm);
+
+ switch (uTyp)
+ {
+ case MQ_MQCFT_NONE:
+ break;
+ case MQ_MQCFT_COMMAND:
+ break;
+ case MQ_MQCFT_RESPONSE:
+ break;
+ case MQ_MQCFT_INTEGER:
+ {
+ const guint8 *pVal = NULL;
+ uVal = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
+ if (bParse)
+ pVal = dissect_mqpcf_parm_getintval(uPrm, uVal);
+
+ if (pVal)
+ {
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
+ "%s %8x-(%9d) %s", strPrm, uVal, uVal, pVal);
+ }
+ else
+ {
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
+ "%s %8x-(%9d)", strPrm, uVal, uVal);
+ }
+
+ proto_tree_add_item(tree, hf_mq_pcf_prmtyp, tvb, offset , 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmlen, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
+
+ dissect_mqpcf_parm_int(tvb, tree, offset+uLenF, uPrm, uVal, hf_mq_pcf_int, 0, 0, 0, bParse);
+ }
+ break;
+ case MQ_MQCFT_STRING:
+ {
+ guint8 *sStr;
+
+ uCCS = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
+ uSLn = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
+ sStr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8,
+ uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
+ if (*sStr)
+ strip_trailing_blanks(sStr, uSLn);
+ if (*sStr)
+ format_text_chr(sStr, strlen((const char *)sStr), '.');
+
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s", strPrm, sStr);
+
+ proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 16, 4, bLittleEndian);
+
+ proto_tree_add_item(tree, hf_mq_pcf_string, tvb, offset + uLenF + 8, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
+ }
+ break;
+ case MQ_MQCFT_INTEGER_LIST:
+ {
+ guint32 u2;
+ guint32 uDigit = 0;
+
+ uCnt = tvb_get_guint32(tvb, offset+uLenF, bLittleEndian);
+ uDigit = dissect_mqpcf_getDigits(uCnt);
+
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, &ti, "%s Cnt(%d)", strPrm, uCnt);
+
+ proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian);
+
+ offset += uLenF+4;
+ for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++)
+ {
+ uVal = tvb_get_guint32(tvb, offset, bLittleEndian);
+ dissect_mqpcf_parm_int(tvb, tree, offset, uPrm, uVal, hf_mq_pcf_intlist, u2+1, uCnt, uDigit, bParse);
+ offset += 4;
+ }
+ if (u2 != uCnt)
+ {
+ proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_MaxInt, tvb, offset, (uCnt- u2) * 4, sMaxLst, u2, uCnt);
+ }
+ }
+ break;
+ case MQ_MQCFT_STRING_LIST:
+ {
+ guint32 u2;
+ guint32 uDigit;
+ guint8 *sStr;
+ header_field_info *hfinfo;
+
+ hfinfo = proto_registrar_get_nth(hf_mq_pcf_stringlist);
+
+ uCCS = tvb_get_guint32(tvb, offset + uLenF , bLittleEndian);
+ uCnt = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
+ uSLn = tvb_get_guint32(tvb, offset + uLenF + 8, bLittleEndian);
+
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s Cnt(%d)", strPrm, uCnt);
+
+ proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmcount , tvb, offset + 16, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 20, 4, bLittleEndian);
+
+ uDigit = dissect_mqpcf_getDigits(uCnt);
+
+ offset += uLenF+12;
+ for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++)
+ {
+ sStr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset,
+ uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
+ if (*sStr)
+ strip_trailing_blanks(sStr, uSLn);
+ if (*sStr)
+ format_text_chr(sStr, strlen((const char *)sStr), '.');
+
+ proto_tree_add_string_format(tree, hf_mq_pcf_stringlist, tvb, offset, uSLn, (const char *)sStr,
+ "%s[%*d]: %s", hfinfo->name, uDigit, u2+1, sStr);
+ offset += uSLn;
+ }
+ if (u2 != uCnt)
+ {
+ proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_MaxStr, tvb, offset,(uCnt - u2) * uSLn, sMaxLst, u2, uCnt);
+ }
+ }
+ break;
+ case MQ_MQCFT_EVENT:
+ break;
+ case MQ_MQCFT_USER:
+ {
+ tree = proto_tree_add_subtree(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, strPrm);
+
+ proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
+
+ proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + 8, uLen - 8, bLittleEndian);
+ }
+ break;
+ case MQ_MQCFT_BYTE_STRING:
+ {
+ uSLn = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
+ if (uSLn)
+ {
+ guint8 *sStrA = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4, uSLn, ENC_ASCII) , uSLn, '.');
+ guint8 *sStrE = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4, uSLn, ENC_EBCDIC), uSLn, '.');
+ if (uSLn > 35)
+ {
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
+ "%s [Truncated] A(%-.35s) E(%-.35s)", strPrm, sStrA, sStrE);
+ }
+ else
+ {
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
+ "%s A(%s) E(%s)", strPrm, sStrA, sStrE);
+ }
+ }
+ else
+ {
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s <MISSING>", strPrm);
+ }
+
+ proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 12, 4, bLittleEndian);
+
+ proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + uLenF + 4 , uSLn, bLittleEndian);
+ }
+ break;
+ case MQ_MQCFT_TRACE_ROUTE:
+ break;
+ case MQ_MQCFT_REPORT:
+ break;
+ case MQ_MQCFT_INTEGER_FILTER:
+ {
+ guint32 uOpe;
+
+ uOpe = tvb_get_guint32(tvb, offset + uLenF , bLittleEndian);
+ uVal = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
+
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s %8x-(%9d)",
+ strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7, uVal, uVal);
+
+ proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian);
+
+ proto_tree_add_item(tree, hf_mq_pcf_int, tvb, offset + uLenF + 4, 4, bLittleEndian);
+ }
+ break;
+ case MQ_MQCFT_STRING_FILTER:
+ {
+ guint8 *sStr;
+ guint32 uOpe;
+
+ uOpe = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
+ uCCS = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
+ uSLn = tvb_get_guint32(tvb, offset + uLenF + 8, bLittleEndian);
+ sStr = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 12, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC), uSLn, '.');
+ strip_trailing_blanks(sStr, uSLn);
+
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s %s",
+ strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7, sStr);
+
+ proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 16, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 20, 4, bLittleEndian);
+
+ proto_tree_add_item(tree, hf_mq_pcf_string, tvb, offset + uLenF + 12, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
+ }
+ break;
+ case MQ_MQCFT_BYTE_STRING_FILTER:
+ {
+ guint32 uOpe;
+ uOpe = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
+ uSLn = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
+ if (uSLn)
+ {
+ guint8 *sStrA = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, ENC_ASCII), uSLn, '.');
+ guint8 *sStrE = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, ENC_EBCDIC), uSLn, '.');
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s A(%s) E(%s)",
+ strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7, sStrA, sStrE);
+ }
+ else
+ {
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s <MISSING>",
+ strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7);
+ }
+
+ proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 16, 4, bLittleEndian);
+
+ proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + uLenF + 8 , uSLn, bLittleEndian);
+ }
+ break;
+ case MQ_MQCFT_COMMAND_XR:
+ break;
+ case MQ_MQCFT_XR_MSG:
+ break;
+ case MQ_MQCFT_XR_ITEM:
+ break;
+ case MQ_MQCFT_XR_SUMMARY:
+ break;
+ case MQ_MQCFT_GROUP:
+ break;
+ case MQ_MQCFT_STATISTICS:
+ break;
+ case MQ_MQCFT_ACCOUNTING:
+ break;
+ case MQ_MQCFT_INTEGER64:
+ {
+ uVal64 = tvb_get_guint64(tvb, offset + uLenF + 4, bLittleEndian);
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
+ "%s %" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)", strPrm, uVal64, uVal64);
+
+ proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmunused, tvb, offset + 12, 4, bLittleEndian);
+
+ proto_tree_add_item(tree, hf_mq_pcf_int64, tvb, offset + uLenF + 4, 8, bLittleEndian);
+ }
+ break;
+ case MQ_MQCFT_INTEGER64_LIST:
+ {
+ guint32 u2;
+ guint32 uDigit;
+ header_field_info *hfinfo;
+
+ hfinfo = proto_registrar_get_nth(hf_mq_pcf_int64list);
+
+ uCnt = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
+ tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s Cnt(%d)", strPrm, uCnt);
+ uDigit = dissect_mqpcf_getDigits(uCnt);
+
+ proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian);
+
+ offset += uLenF + 4;
+ for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++)
+ {
+ uVal64 = tvb_get_guint64(tvb, offset, bLittleEndian);
+ proto_tree_add_int64_format(tree, hf_mq_pcf_int64list, tvb, offset, 8, uVal64,
+ "%s[%*d]: %" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)",
+ hfinfo->name, uDigit, u2+1, uVal64, uVal64);
+ offset += 8;
+ }
+ if (u2 != uCnt)
+ {
+ proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_MaxI64, tvb, offset, (uCnt - u2) * 8, sMaxLst, u2, uCnt);
+ }
+ }
+ break;
+ }
+ offset = tOfs+uLen;
+ }
+ if (u != uCount)
+ {
+ proto_tree_add_expert_format(mq_tree, pinfo, &ei_mq_pcf_MaxPrm, tvb, offset, tvb_reported_length_remaining(tvb, offset), sMaxPrm, u, uCount);
+ }
}
-void
-proto_register_mqpcf(void)
+static void dissect_mqpcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, mq_parm_t* p_mq_parm)
{
- static hf_register_info hf[] = {
- { &hf_mqpcf_cfh_type,
- { "Type", "mqpcf.cfh.type", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH type", HFILL }},
+ gint offset = 0;
+ gboolean bLittleEndian;
+
+ bLittleEndian = ((p_mq_parm->mq_cur_ccsid.encod & MQ_MQENC_INTEGER_MASK) == MQ_MQENC_INTEGER_REVERSED) ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN;
+
+ if (tvb_reported_length(tvb) >= 36)
+ {
+ gint iSizeMQCFH = 36;
+ guint32 iCommand = tvb_get_guint32(tvb, offset + 12, bLittleEndian);
+
+ if (tree)
+ {
+ proto_item *ti;
+ proto_tree *mq_tree;
+ proto_tree *mqroot_tree;
+ char sTmp[256];
+ guint32 uCnt;
+ guint32 uTyp;
+ guint32 uCmd;
+ guint32 uCC;
+ guint32 uRC;
+
+ uTyp = tvb_get_guint32(tvb, offset , bLittleEndian);
+ uCmd = tvb_get_guint32(tvb, offset + 12, bLittleEndian);
+ uCC = tvb_get_guint32(tvb, offset + 24, bLittleEndian);
+ uRC = tvb_get_guint32(tvb, offset + 28, bLittleEndian);
+ uCnt = tvb_get_guint32(tvb, offset + 32, bLittleEndian);
+
+ if (uCC || uRC)
+ {
+ g_snprintf(sTmp, (gulong)sizeof(sTmp)-1, " %-s [%d-%s] {%d-%s} PrmCnt(%d) CC(%d-%s) RC(%d-%s)",
+ MQ_TEXT_CFH,
+ uTyp, val_to_str_const(uTyp, GET_VALSV(mqcft), "Unknown"),
+ uCmd, val_to_str_ext_const(uCmd, GET_VALS_EXTP(mqcmd), "Unknown"),
+ uCnt,
+ uCC, val_to_str_const(uCC, GET_VALSV(mqcc), "Unknown"),
+ uRC, val_to_str_ext_const(uRC, GET_VALS_EXTP(mqrc), "Unknown"));
+ }
+ else
+ {
+ g_snprintf(sTmp, (gulong)sizeof(sTmp)-1, " %-s [%d-%s] {%d-%s} PrmCnt(%d)",
+ MQ_TEXT_CFH,
+ uTyp, val_to_str_const(uTyp, GET_VALSV(mqcft), "Unknown"),
+ uCmd, val_to_str_ext_const(uCmd, GET_VALS_EXTP(mqcmd), "Unknown"),
+ uCnt);
+ }
+
+ ti = proto_tree_add_item(tree, proto_mqpcf, tvb, offset, -1, ENC_NA);
+
+ proto_item_append_text(ti, " (%s)", val_to_str_ext_const(iCommand, GET_VALS_EXTP(mqcmd), "Unknown (0x%02x)"));
+ mqroot_tree = proto_item_add_subtree(ti, ett_mqpcf);
- { &hf_mqpcf_cfh_length,
- { "Length", "mqpcf.cfh.length", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH length", HFILL }},
+ mq_tree = proto_tree_add_subtree(mqroot_tree, tvb, offset, iSizeMQCFH, ett_mqpcf_cfh, NULL, sTmp);
- { &hf_mqpcf_cfh_version,
- { "Version", "mqpcf.cfh.version", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH version", HFILL }},
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_type , tvb, offset + 0, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_length , tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_version , tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_command , tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_MsgSeqNbr, tvb, offset + 16, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_control , tvb, offset + 20, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_compcode , tvb, offset + 24, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_reason , tvb, offset + 28, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_ParmCount, tvb, offset + 32, 4, bLittleEndian);
+ dissect_mqpcf_parm(tvb, pinfo, mqroot_tree, offset + iSizeMQCFH, uCnt, bLittleEndian, TRUE);
+ }
+ }
+}
+
+static gboolean dissect_mqpcf_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ if (data && tvb_reported_length(tvb) >= 36)
+ {
+ mq_parm_t *p_mq_parm = (mq_parm_t *)data;
+ if (strncmp((const char*)p_mq_parm->mq_format, MQ_MQFMT_ADMIN, 8) == 0
+ || strncmp((const char*)p_mq_parm->mq_format, MQ_MQFMT_EVENT, 8) == 0
+ || strncmp((const char*)p_mq_parm->mq_format, MQ_MQFMT_PCF, 8) == 0)
+ {
+ /* Dissect the packet */
+ dissect_mqpcf(tvb, pinfo, tree, p_mq_parm);
+ return TRUE;
+ }
+ if (strncmp((const char *)p_mq_parm->mq_format, "LPOO", 4) == 0)
+ {
+ gboolean bLittleEndian;
+ bLittleEndian = ((p_mq_parm->mq_cur_ccsid.encod & MQ_MQENC_INTEGER_MASK) == MQ_MQENC_INTEGER_REVERSED) ? ENC_LITTLE_ENDIAN:ENC_BIG_ENDIAN;
+ dissect_mqpcf_parm(tvb, pinfo, tree, 0, (guint32)-1, bLittleEndian, FALSE);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void proto_register_mqpcf(void)
+{
+ expert_module_t *expert_mqpcf;
- { &hf_mqpcf_cfh_command,
- { "Command", "mqpcf.cfh.command", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH command", HFILL }},
+ static hf_register_info hf[] =
+ {
+ { &hf_mqpcf_cfh_type , { "Type.....", "mqpcf.cfh.type" , FT_UINT32, BASE_DEC, VALS(mq_mqcft_vals), 0x0, "CFH type", HFILL }},
+ { &hf_mqpcf_cfh_length , { "Length...", "mqpcf.cfh.length" , FT_UINT32, BASE_DEC, NULL, 0x0, "CFH length", HFILL }},
+ { &hf_mqpcf_cfh_version , { "Version..", "mqpcf.cfh.version" , FT_UINT32, BASE_DEC, NULL, 0x0, "CFH version", HFILL }},
+ { &hf_mqpcf_cfh_command , { "Command..", "mqpcf.cfh.command" , FT_UINT32, BASE_DEC | BASE_EXT_STRING, &mq_mqcmd_xvals, 0x0, "CFH command", HFILL }},
+ { &hf_mqpcf_cfh_MsgSeqNbr, { "MsgSeqNbr", "mqpcf.cfh.MsgSeqNbr" , FT_UINT32, BASE_DEC, NULL, 0x0, "CFH message sequence number", HFILL }},
+ { &hf_mqpcf_cfh_control , { "Control..", "mqpcf.cfh.control" , FT_UINT32, BASE_DEC, VALS(mq_CtlOpt_vals), 0x0, "CFH control", HFILL }},
+ { &hf_mqpcf_cfh_compcode , { "CompCode.", "mqpcf.cfh.compcode" , FT_UINT32, BASE_DEC, VALS(mq_mqcc_vals), 0x0, "CFH completion code", HFILL }},
+ { &hf_mqpcf_cfh_reason , { "ReasCode.", "mqpcf.cfh.reasoncode", FT_UINT32, BASE_DEC | BASE_EXT_STRING, &mq_mqrc_xvals, 0x0, "CFH reason code", HFILL }},
+ { &hf_mqpcf_cfh_ParmCount, { "ParmCount", "mqpcf.cfh.ParmCount" , FT_UINT32, BASE_DEC, NULL, 0x0, "CFH parameter count", HFILL }},
- { &hf_mqpcf_cfh_msgseqnumber,
- { "Message sequence number", "mqpcf.cfh.msgseqnumber", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH message sequence number", HFILL }},
+ { &hf_mq_pcf_prmtyp , { "ParmTyp..", "mqpcf.parm.type" , FT_UINT32 , BASE_DEC | BASE_EXT_STRING, &mq_PrmTyp_xvals, 0x0, "MQPCF parameter type", HFILL }},
+ { &hf_mq_pcf_prmlen , { "ParmLen..", "mqpcf.parm.len" , FT_UINT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter length", HFILL }},
+ { &hf_mq_pcf_prmid , { "ParmID...", "mqpcf.parm.id" , FT_UINT32 , BASE_DEC | BASE_EXT_STRING, &mq_PrmId_xvals, 0x0, "MQPCF parameter id", HFILL }},
+ { &hf_mq_pcf_prmidnovals , { "ParmID...", "mqpcf.parm.idNoVals" , FT_UINT32 , BASE_HEX_DEC, NULL, 0x0, "MQPCF parameter id No Vals", HFILL }},
+ { &hf_mq_pcf_filterop , { "FilterOP.", "mqpcf.filter.op" , FT_UINT32 , BASE_DEC, VALS(mq_FilterOP_vals), 0x0, "MQPCF Filter operator", HFILL }},
+ { &hf_mq_pcf_prmccsid , { "ParmCCSID", "mqpcf.parm.ccsid" , FT_UINT32 , BASE_DEC | BASE_RANGE_STRING, RVALS(mq_ccsid_rvals), 0x0, "MQPCF parameter ccsid", HFILL }},
+ { &hf_mq_pcf_prmstrlen , { "ParmStrLn", "mqpcf.parm.strlen" , FT_UINT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter strlen", HFILL }},
+ { &hf_mq_pcf_prmcount , { "ParmCount", "mqpcf.parm.count" , FT_UINT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter count", HFILL }},
+ { &hf_mq_pcf_prmunused , { "ParmUnuse", "mqpcf.parm.unused" , FT_UINT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter unused", HFILL }},
+ { &hf_mq_pcf_string , { "String...", "mqpcf.parm.string" , FT_STRINGZ, BASE_NONE, NULL, 0x0, "MQPCF parameter string", HFILL }},
+ { &hf_mq_pcf_stringlist , { "StrList..", "mqpcf.parm.stringlist", FT_STRINGZ, BASE_NONE, NULL, 0x0, "MQPCF parameter string list", HFILL }},
+ { &hf_mq_pcf_int , { "Integer..", "mqpcf.parm.int" , FT_INT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter int", HFILL }},
+ { &hf_mq_pcf_intlist , { "IntList..", "mqpcf.parm.intlist" , FT_INT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter int list", HFILL }},
+ { &hf_mq_pcf_bytestring , { "ByteStr..", "mqpcf.parm.bytestring", FT_BYTES , BASE_NONE, NULL, 0x0, "MQPCF parameter byte string", HFILL }},
+ { &hf_mq_pcf_int64 , { "Int64....", "mqpcf.parm.int64" , FT_INT64 , BASE_DEC, NULL, 0x0, "MQPCF parameter int64", HFILL }},
+ { &hf_mq_pcf_int64list , { "Int64List", "mqpcf.parm.int64list" , FT_INT64 , BASE_DEC, NULL, 0x0, "MQPCF parameter int64 list", HFILL }},
+ };
+ static gint *ett[] =
+ {
+ &ett_mqpcf,
+ &ett_mqpcf_prm,
+ &ett_mqpcf_cfh,
+ };
+ static ei_register_info ei[] =
+ {
+ { &ei_mq_pcf_prmln0, { "mqpcf.parm.len0" , PI_MALFORMED, PI_ERROR, "MQPCF Parameter length is 0", EXPFILL }},
+ { &ei_mq_pcf_MaxInt, { "mqpcf.parm.IntList" , PI_UNDECODED, PI_WARN , "MQPCF Parameter Integer list exhausted", EXPFILL }},
+ { &ei_mq_pcf_MaxStr, { "mqpcf.parm.StrList" , PI_UNDECODED, PI_WARN , "MQPCF Parameter String list exhausted", EXPFILL }},
+ { &ei_mq_pcf_MaxI64, { "mqpcf.parm.Int64List", PI_UNDECODED, PI_WARN , "MQPCF Parameter Int64 list exhausted", EXPFILL }},
+ { &ei_mq_pcf_MaxPrm, { "mqpcf.parm.MaxPrm" , PI_UNDECODED, PI_WARN , "MQPCF Max number of parameter exhausted", EXPFILL }},
+ { &ei_mq_pcf_PrmCnt, { "mqpcf.parm.PrmCnt" , PI_UNDECODED, PI_WARN , "MQPCF Unkn Parm Cnt Length invalid", EXPFILL }},
+ };
- { &hf_mqpcf_cfh_control,
- { "Control", "mqpcf.cfh.control", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH control", HFILL }},
+ module_t *mq_pcf_module;
- { &hf_mqpcf_cfh_compcode,
- { "Completion code", "mqpcf.cfh.compcode", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH completion code", HFILL }},
+ proto_mqpcf = proto_register_protocol("WebSphere MQ Programmable Command Formats", "MQ PCF", "mqpcf");
+ proto_register_field_array(proto_mqpcf, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
- { &hf_mqpcf_cfh_reason,
- { "Reason code", "mqpcf.cfh.reasoncode", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH reason code", HFILL }},
+ expert_mqpcf = expert_register_protocol(proto_mqpcf);
+ expert_register_field_array(expert_mqpcf, ei, array_length(ei));
- { &hf_mqpcf_cfh_paramcount,
- { "Parameter count", "mqpcf.cfh.paramcount", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH parameter count", HFILL }}
- };
- static gint *ett[] = {
- &ett_mqpcf,
- &ett_mqpcf_cfh,
- };
+ mq_pcf_module = prefs_register_protocol(proto_mqpcf, NULL);
+ prefs_register_uint_preference(mq_pcf_module, "maxprm",
+ "Set the maximun number of parameter in the PCF to decode",
+ "When dissecting PCF there can be a lot of parameters."
+ " You can limit the number of parameter decoded, before it continue with the next PCF.",
+ 10, &mq_pcf_maxprm);
+ prefs_register_uint_preference(mq_pcf_module, "maxlst",
+ "Set the maximun number of Parameter List that are displayed",
+ "When dissecting a parameter of a PCFm, if it is a StringList, IntegerList or Integer64 List, "
+ " You can limit the number of element displayed, before it continue with the next Parameter.",
+ 10, &mq_pcf_maxlst);
- proto_mqpcf = proto_register_protocol("WebSphere MQ Programmable Command Formats", "MQ PCF", "mqpcf");
- proto_register_field_array(proto_mqpcf, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
}
-void
-proto_reg_handoff_mqpcf(void)
+void proto_reg_handoff_mqpcf(void)
{
- heur_dissector_add("mq", dissect_mqpcf_heur, proto_mqpcf);
+ heur_dissector_add("mq", dissect_mqpcf_heur, "WebSphere MQ PCF", "mqpcf_mq", proto_mqpcf, HEURISTIC_ENABLE);
}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */