2 * Routines for IBM WebSphere MQ PCF packet dissection
4 * metatech <metatech@flashmail.com>
5 * robionekenobi <robionekenobi@bluewin.ch>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 /* MQ PCF in a nutshell
28 * The MQ Programmable Command Formats API allows remotely configuring a queue manager.
30 * MQ PCF documentation is called "WebSphere MQ Programmable Command Formats and Administration Interface"
37 #include <epan/packet.h>
38 #include <epan/expert.h>
39 #include <epan/prefs.h>
40 #include <epan/strutil.h>
42 #include "packet-mq.h"
44 void proto_register_mqpcf(void);
45 void proto_reg_handoff_mqpcf(void);
47 #define PCF_MAX_PARM 999
48 #define PCF_MAX_LIST 20000
50 guint mq_pcf_maxprm = PCF_MAX_PARM;
51 guint mq_pcf_maxlst = PCF_MAX_LIST;
53 static int proto_mqpcf = -1;
55 static int hf_mqpcf_cfh_type = -1;
56 static int hf_mqpcf_cfh_length = -1;
57 static int hf_mqpcf_cfh_version = -1;
58 static int hf_mqpcf_cfh_command = -1;
59 static int hf_mqpcf_cfh_MsgSeqNbr = -1;
60 static int hf_mqpcf_cfh_control = -1;
61 static int hf_mqpcf_cfh_compcode = -1;
62 static int hf_mqpcf_cfh_reason = -1;
63 static int hf_mqpcf_cfh_ParmCount = -1;
65 static int hf_mq_pcf_prmtyp = -1;
66 static int hf_mq_pcf_prmlen = -1;
67 static int hf_mq_pcf_prmid = -1;
68 static int hf_mq_pcf_prmidnovals = -1;
69 static int hf_mq_pcf_filterop = -1;
70 static int hf_mq_pcf_prmccsid = -1;
71 static int hf_mq_pcf_prmstrlen = -1;
72 static int hf_mq_pcf_prmcount = -1;
73 static int hf_mq_pcf_prmunused = -1;
75 static int hf_mq_pcf_string = -1;
76 static int hf_mq_pcf_stringlist = -1;
77 static int hf_mq_pcf_int = -1;
78 static int hf_mq_pcf_intlist = -1;
79 static int hf_mq_pcf_bytestring = -1;
80 static int hf_mq_pcf_int64 = -1;
81 static int hf_mq_pcf_int64list = -1;
83 static expert_field ei_mq_pcf_prmln0 = EI_INIT;
84 static expert_field ei_mq_pcf_MaxInt = EI_INIT;
85 static expert_field ei_mq_pcf_MaxStr = EI_INIT;
86 static expert_field ei_mq_pcf_MaxI64 = EI_INIT;
87 static expert_field ei_mq_pcf_MaxPrm = EI_INIT;
88 static expert_field ei_mq_pcf_PrmCnt = EI_INIT;
90 static gint ett_mqpcf_prm = -1;
91 static gint ett_mqpcf = -1;
92 static gint ett_mqpcf_cfh = -1;
94 #define MQ_TEXT_CFH "MQ Command Format Header"
96 static guint32 dissect_mqpcf_getDigits(guint uCnt)
98 return (guint32)(log10( (double)uCnt ) + 1);
101 * Here we get a special value_string, that return another value_string
102 * pointer instead of string value. This let us use the try_val_to_str
103 * to get val_to_str value from the value of a parameter on a more
104 * easier way than using switch cases
106 static const guint8 *dissect_mqpcf_parm_getintval(guint uPrm, guint uVal)
108 const value_string *pVs;
109 pVs = (const value_string *)try_val_to_str_ext(uPrm, GET_VALS_EXTP(MQCFINT_Parse));
113 return (const guint8 *)try_val_to_str(uVal, pVs);
118 static void dissect_mqpcf_parm_int(tvbuff_t *tvb, proto_tree *tree, guint offset, guint uPrm,
119 guint uVal, int hfindex, guint iCnt, guint iMaxCnt,
120 guint iDigit, gboolean bParse)
122 header_field_info *hfinfo;
123 const guint8 *pVal = NULL;
126 pVal = dissect_mqpcf_parm_getintval(uPrm, uVal);
128 hfinfo = proto_registrar_get_nth(hfindex);
134 proto_tree_add_int_format(tree, hfindex, tvb, offset, 4, uVal,
135 "%s[%*d]: %8x-(%9d)-%s", hfinfo->name, iDigit, iCnt, uVal, uVal, pVal);
139 proto_tree_add_int_format(tree, hfindex, tvb, offset, 4, uVal,
140 "%s[%*d]: %8x-(%9d)", hfinfo->name, iDigit, iCnt, uVal, uVal);
147 proto_tree_add_int_format_value(tree, hfindex, tvb, offset, 4, uVal,
148 "%8x-(%9d)-%s", uVal, uVal, pVal);
152 proto_tree_add_int_format_value(tree, hfindex, tvb, offset, 4, uVal,
153 "%8x-(%9d)", uVal, uVal);
158 void dissect_mqpcf_parm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mq_tree,
159 guint offset, guint32 uCount, guint bLittleEndian, gboolean bParse)
175 const char sMaxLst[] = " Max # of List reached. DECODE interrupted (actual %u of %u)";
176 const char sPrmLn0[] = " MQPrm[%3u] has a zero length. DECODE Failed (MQPrm Count: %u)";
177 const char sMaxPrm[] = " Max # of Parm reached. DECODE interrupted (actual %u of %u)";
178 const char sPrmCnt[] = " Cnt=-1 and Length(%u) < 16. DECODE interrupted for elem %u";
180 proto_item *ti = NULL;
181 proto_tree *tree = NULL;
183 if (uCount == (guint32)-1)
185 guint32 xOfs = offset;
188 while (tvb_reported_length_remaining(tvb, xOfs) >= 16)
190 uLen = tvb_get_guint32(tvb, xOfs + 4, bLittleEndian);
193 proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_PrmCnt, tvb, xOfs, 16, sPrmCnt, uLen, uCnt);
202 uDig = dissect_mqpcf_getDigits(uCount);
204 for (u = 0; u < uCount && u < mq_pcf_maxprm; u++)
207 uTyp = tvb_get_guint32(tvb, offset , bLittleEndian);
208 uLen = tvb_get_guint32(tvb, offset + 4, bLittleEndian);
211 proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_prmln0, tvb, offset, 12, sPrmLn0, u+1, uCount);
215 uPrm = tvb_get_guint32(tvb, offset + 8, bLittleEndian);
219 g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d-%-30.30s",
221 uTyp, val_to_str_ext_const(uTyp, GET_VALS_EXTP(PrmTyp), " Unknown") + 6,
222 uPrm, uPrm, val_to_str_ext_const(uPrm, GET_VALS_EXTP(PrmId), "Unknown"));
224 g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d",
226 uTyp, val_to_str_ext_const(uTyp, GET_VALS_EXTP(PrmTyp), " Unknown") + 6,
233 case MQ_MQCFT_COMMAND:
235 case MQ_MQCFT_RESPONSE:
237 case MQ_MQCFT_INTEGER:
239 const guint8 *pVal = NULL;
240 uVal = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
242 pVal = dissect_mqpcf_parm_getintval(uPrm, uVal);
246 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
247 "%s %8x-(%9d) %s", strPrm, uVal, uVal, pVal);
251 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
252 "%s %8x-(%9d)", strPrm, uVal, uVal);
255 proto_tree_add_item(tree, hf_mq_pcf_prmtyp, tvb, offset , 4, bLittleEndian);
256 proto_tree_add_item(tree, hf_mq_pcf_prmlen, tvb, offset + 4, 4, bLittleEndian);
257 proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
259 dissect_mqpcf_parm_int(tvb, tree, offset+uLenF, uPrm, uVal, hf_mq_pcf_int, 0, 0, 0, bParse);
262 case MQ_MQCFT_STRING:
266 uCCS = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
267 uSLn = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
268 sStr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8,
269 uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
271 strip_trailing_blanks(sStr, uSLn);
273 format_text_chr(sStr, strlen((const char *)sStr), '.');
275 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s", strPrm, sStr);
277 proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
278 proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
279 proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
280 proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 12, 4, bLittleEndian);
281 proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 16, 4, bLittleEndian);
283 proto_tree_add_item(tree, hf_mq_pcf_string, tvb, offset + uLenF + 8, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
286 case MQ_MQCFT_INTEGER_LIST:
291 uCnt = tvb_get_guint32(tvb, offset+uLenF, bLittleEndian);
292 uDigit = dissect_mqpcf_getDigits(uCnt);
294 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, &ti, "%s Cnt(%d)", strPrm, uCnt);
296 proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
297 proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
298 proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
299 proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian);
302 for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++)
304 uVal = tvb_get_guint32(tvb, offset, bLittleEndian);
305 dissect_mqpcf_parm_int(tvb, tree, offset, uPrm, uVal, hf_mq_pcf_intlist, u2+1, uCnt, uDigit, bParse);
310 proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_MaxInt, tvb, offset, (uCnt- u2) * 4, sMaxLst, u2, uCnt);
314 case MQ_MQCFT_STRING_LIST:
319 header_field_info *hfinfo;
321 hfinfo = proto_registrar_get_nth(hf_mq_pcf_stringlist);
323 uCCS = tvb_get_guint32(tvb, offset + uLenF , bLittleEndian);
324 uCnt = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
325 uSLn = tvb_get_guint32(tvb, offset + uLenF + 8, bLittleEndian);
327 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s Cnt(%d)", strPrm, uCnt);
329 proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
330 proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
331 proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
332 proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 12, 4, bLittleEndian);
333 proto_tree_add_item(tree, hf_mq_pcf_prmcount , tvb, offset + 16, 4, bLittleEndian);
334 proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 20, 4, bLittleEndian);
336 uDigit = dissect_mqpcf_getDigits(uCnt);
339 for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++)
341 sStr = tvb_get_string_enc(wmem_packet_scope(), tvb, offset,
342 uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
344 strip_trailing_blanks(sStr, uSLn);
346 format_text_chr(sStr, strlen((const char *)sStr), '.');
348 proto_tree_add_string_format(tree, hf_mq_pcf_stringlist, tvb, offset, uSLn, (const char *)sStr,
349 "%s[%*d]: %s", hfinfo->name, uDigit, u2+1, sStr);
354 proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_MaxStr, tvb, offset,(uCnt - u2) * uSLn, sMaxLst, u2, uCnt);
362 tree = proto_tree_add_subtree(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, strPrm);
364 proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
365 proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
367 proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + 8, uLen - 8, bLittleEndian);
370 case MQ_MQCFT_BYTE_STRING:
372 uSLn = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
375 guint8 *sStrA = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4, uSLn, ENC_ASCII) , uSLn, '.');
376 guint8 *sStrE = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4, uSLn, ENC_EBCDIC), uSLn, '.');
379 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
380 "%s [Truncated] A(%-.35s) E(%-.35s)", strPrm, sStrA, sStrE);
384 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
385 "%s A(%s) E(%s)", strPrm, sStrA, sStrE);
390 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s <MISSING>", strPrm);
393 proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
394 proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
395 proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
396 proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 12, 4, bLittleEndian);
398 proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + uLenF + 4 , uSLn, bLittleEndian);
401 case MQ_MQCFT_TRACE_ROUTE:
403 case MQ_MQCFT_REPORT:
405 case MQ_MQCFT_INTEGER_FILTER:
409 uOpe = tvb_get_guint32(tvb, offset + uLenF , bLittleEndian);
410 uVal = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
412 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s %8x-(%9d)",
413 strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7, uVal, uVal);
415 proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
416 proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
417 proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
418 proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian);
420 proto_tree_add_item(tree, hf_mq_pcf_int, tvb, offset + uLenF + 4, 4, bLittleEndian);
423 case MQ_MQCFT_STRING_FILTER:
428 uOpe = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
429 uCCS = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
430 uSLn = tvb_get_guint32(tvb, offset + uLenF + 8, bLittleEndian);
431 sStr = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 12, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC), uSLn, '.');
432 strip_trailing_blanks(sStr, uSLn);
434 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s %s",
435 strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7, sStr);
437 proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
438 proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
439 proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
440 proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian);
441 proto_tree_add_item(tree, hf_mq_pcf_prmccsid , tvb, offset + 16, 4, bLittleEndian);
442 proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 20, 4, bLittleEndian);
444 proto_tree_add_item(tree, hf_mq_pcf_string, tvb, offset + uLenF + 12, uSLn, (uCCS != 500) ? ENC_ASCII : ENC_EBCDIC);
447 case MQ_MQCFT_BYTE_STRING_FILTER:
450 uOpe = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
451 uSLn = tvb_get_guint32(tvb, offset + uLenF + 4, bLittleEndian);
454 guint8 *sStrA = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, ENC_ASCII), uSLn, '.');
455 guint8 *sStrE = (guint8 *)format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8, uSLn, ENC_EBCDIC), uSLn, '.');
456 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s A(%s) E(%s)",
457 strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7, sStrA, sStrE);
461 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s %s <MISSING>",
462 strPrm, val_to_str(uOpe, GET_VALSV(FilterOP), " Unknown (0x%02x)")+7);
465 proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
466 proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
467 proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
468 proto_tree_add_item(tree, hf_mq_pcf_filterop , tvb, offset + 12, 4, bLittleEndian);
469 proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 16, 4, bLittleEndian);
471 proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + uLenF + 8 , uSLn, bLittleEndian);
474 case MQ_MQCFT_COMMAND_XR:
476 case MQ_MQCFT_XR_MSG:
478 case MQ_MQCFT_XR_ITEM:
480 case MQ_MQCFT_XR_SUMMARY:
484 case MQ_MQCFT_STATISTICS:
486 case MQ_MQCFT_ACCOUNTING:
488 case MQ_MQCFT_INTEGER64:
490 uVal64 = tvb_get_guint64(tvb, offset + uLenF + 4, bLittleEndian);
491 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL,
492 "%s %" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)", strPrm, uVal64, uVal64);
494 proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
495 proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
496 proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
497 proto_tree_add_item(tree, hf_mq_pcf_prmunused, tvb, offset + 12, 4, bLittleEndian);
499 proto_tree_add_item(tree, hf_mq_pcf_int64, tvb, offset + uLenF + 4, 8, bLittleEndian);
502 case MQ_MQCFT_INTEGER64_LIST:
506 header_field_info *hfinfo;
508 hfinfo = proto_registrar_get_nth(hf_mq_pcf_int64list);
510 uCnt = tvb_get_guint32(tvb, offset + uLenF, bLittleEndian);
511 tree = proto_tree_add_subtree_format(mq_tree, tvb, offset, uLen, ett_mqpcf_prm, NULL, "%s Cnt(%d)", strPrm, uCnt);
512 uDigit = dissect_mqpcf_getDigits(uCnt);
514 proto_tree_add_item(tree, hf_mq_pcf_prmtyp , tvb, offset , 4, bLittleEndian);
515 proto_tree_add_item(tree, hf_mq_pcf_prmlen , tvb, offset + 4, 4, bLittleEndian);
516 proto_tree_add_item(tree, (bParse) ? hf_mq_pcf_prmid : hf_mq_pcf_prmidnovals, tvb, offset + 8, 4, bLittleEndian);
517 proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian);
520 for (u2 = 0; u2 < uCnt && u2 < mq_pcf_maxlst; u2++)
522 uVal64 = tvb_get_guint64(tvb, offset, bLittleEndian);
523 proto_tree_add_int64_format(tree, hf_mq_pcf_int64list, tvb, offset, 8, uVal64,
524 "%s[%*d]: %" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)",
525 hfinfo->name, uDigit, u2+1, uVal64, uVal64);
530 proto_tree_add_expert_format(tree, pinfo, &ei_mq_pcf_MaxI64, tvb, offset, (uCnt - u2) * 8, sMaxLst, u2, uCnt);
539 proto_tree_add_expert_format(mq_tree, pinfo, &ei_mq_pcf_MaxPrm, tvb, offset, tvb_reported_length_remaining(tvb, offset), sMaxPrm, u, uCount);
543 static void dissect_mqpcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, mq_parm_t* p_mq_parm)
546 gboolean bLittleEndian;
548 bLittleEndian = ((p_mq_parm->mq_cur_ccsid.encod & MQ_MQENC_INTEGER_MASK) == MQ_MQENC_INTEGER_REVERSED) ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN;
550 if (tvb_reported_length(tvb) >= 36)
552 gint iSizeMQCFH = 36;
553 guint32 iCommand = tvb_get_guint32(tvb, offset + 12, bLittleEndian);
559 proto_tree *mqroot_tree;
567 uTyp = tvb_get_guint32(tvb, offset , bLittleEndian);
568 uCmd = tvb_get_guint32(tvb, offset + 12, bLittleEndian);
569 uCC = tvb_get_guint32(tvb, offset + 24, bLittleEndian);
570 uRC = tvb_get_guint32(tvb, offset + 28, bLittleEndian);
571 uCnt = tvb_get_guint32(tvb, offset + 32, bLittleEndian);
575 g_snprintf(sTmp, (gulong)sizeof(sTmp)-1, " %-s [%d-%s] {%d-%s} PrmCnt(%d) CC(%d-%s) RC(%d-%s)",
577 uTyp, val_to_str_const(uTyp, GET_VALSV(mqcft), "Unknown"),
578 uCmd, val_to_str_ext_const(uCmd, GET_VALS_EXTP(mqcmd), "Unknown"),
580 uCC, val_to_str_const(uCC, GET_VALSV(mqcc), "Unknown"),
581 uRC, val_to_str_ext_const(uRC, GET_VALS_EXTP(mqrc), "Unknown"));
585 g_snprintf(sTmp, (gulong)sizeof(sTmp)-1, " %-s [%d-%s] {%d-%s} PrmCnt(%d)",
587 uTyp, val_to_str_const(uTyp, GET_VALSV(mqcft), "Unknown"),
588 uCmd, val_to_str_ext_const(uCmd, GET_VALS_EXTP(mqcmd), "Unknown"),
592 ti = proto_tree_add_item(tree, proto_mqpcf, tvb, offset, -1, ENC_NA);
594 proto_item_append_text(ti, " (%s)", val_to_str_ext_const(iCommand, GET_VALS_EXTP(mqcmd), "Unknown (0x%02x)"));
595 mqroot_tree = proto_item_add_subtree(ti, ett_mqpcf);
597 mq_tree = proto_tree_add_subtree(mqroot_tree, tvb, offset, iSizeMQCFH, ett_mqpcf_cfh, NULL, sTmp);
599 proto_tree_add_item(mq_tree, hf_mqpcf_cfh_type , tvb, offset + 0, 4, bLittleEndian);
600 proto_tree_add_item(mq_tree, hf_mqpcf_cfh_length , tvb, offset + 4, 4, bLittleEndian);
601 proto_tree_add_item(mq_tree, hf_mqpcf_cfh_version , tvb, offset + 8, 4, bLittleEndian);
602 proto_tree_add_item(mq_tree, hf_mqpcf_cfh_command , tvb, offset + 12, 4, bLittleEndian);
603 proto_tree_add_item(mq_tree, hf_mqpcf_cfh_MsgSeqNbr, tvb, offset + 16, 4, bLittleEndian);
604 proto_tree_add_item(mq_tree, hf_mqpcf_cfh_control , tvb, offset + 20, 4, bLittleEndian);
605 proto_tree_add_item(mq_tree, hf_mqpcf_cfh_compcode , tvb, offset + 24, 4, bLittleEndian);
606 proto_tree_add_item(mq_tree, hf_mqpcf_cfh_reason , tvb, offset + 28, 4, bLittleEndian);
607 proto_tree_add_item(mq_tree, hf_mqpcf_cfh_ParmCount, tvb, offset + 32, 4, bLittleEndian);
608 dissect_mqpcf_parm(tvb, pinfo, mqroot_tree, offset + iSizeMQCFH, uCnt, bLittleEndian, TRUE);
613 static gboolean dissect_mqpcf_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
615 if (data && tvb_reported_length(tvb) >= 36)
617 mq_parm_t *p_mq_parm = (mq_parm_t *)data;
618 if (strncmp((const char*)p_mq_parm->mq_format, MQ_MQFMT_ADMIN, 8) == 0
619 || strncmp((const char*)p_mq_parm->mq_format, MQ_MQFMT_EVENT, 8) == 0
620 || strncmp((const char*)p_mq_parm->mq_format, MQ_MQFMT_PCF, 8) == 0)
622 /* Dissect the packet */
623 dissect_mqpcf(tvb, pinfo, tree, p_mq_parm);
626 if (strncmp((const char *)p_mq_parm->mq_format, "LPOO", 4) == 0)
628 gboolean bLittleEndian;
629 bLittleEndian = ((p_mq_parm->mq_cur_ccsid.encod & MQ_MQENC_INTEGER_MASK) == MQ_MQENC_INTEGER_REVERSED) ? ENC_LITTLE_ENDIAN:ENC_BIG_ENDIAN;
630 dissect_mqpcf_parm(tvb, pinfo, tree, 0, (guint32)-1, bLittleEndian, FALSE);
637 void proto_register_mqpcf(void)
639 expert_module_t *expert_mqpcf;
641 static hf_register_info hf[] =
643 { &hf_mqpcf_cfh_type , { "Type.....", "mqpcf.cfh.type" , FT_UINT32, BASE_DEC, VALS(mq_mqcft_vals), 0x0, "CFH type", HFILL }},
644 { &hf_mqpcf_cfh_length , { "Length...", "mqpcf.cfh.length" , FT_UINT32, BASE_DEC, NULL, 0x0, "CFH length", HFILL }},
645 { &hf_mqpcf_cfh_version , { "Version..", "mqpcf.cfh.version" , FT_UINT32, BASE_DEC, NULL, 0x0, "CFH version", HFILL }},
646 { &hf_mqpcf_cfh_command , { "Command..", "mqpcf.cfh.command" , FT_UINT32, BASE_DEC | BASE_EXT_STRING, &mq_mqcmd_xvals, 0x0, "CFH command", HFILL }},
647 { &hf_mqpcf_cfh_MsgSeqNbr, { "MsgSeqNbr", "mqpcf.cfh.MsgSeqNbr" , FT_UINT32, BASE_DEC, NULL, 0x0, "CFH message sequence number", HFILL }},
648 { &hf_mqpcf_cfh_control , { "Control..", "mqpcf.cfh.control" , FT_UINT32, BASE_DEC, VALS(mq_CtlOpt_vals), 0x0, "CFH control", HFILL }},
649 { &hf_mqpcf_cfh_compcode , { "CompCode.", "mqpcf.cfh.compcode" , FT_UINT32, BASE_DEC, VALS(mq_mqcc_vals), 0x0, "CFH completion code", HFILL }},
650 { &hf_mqpcf_cfh_reason , { "ReasCode.", "mqpcf.cfh.reasoncode", FT_UINT32, BASE_DEC | BASE_EXT_STRING, &mq_mqrc_xvals, 0x0, "CFH reason code", HFILL }},
651 { &hf_mqpcf_cfh_ParmCount, { "ParmCount", "mqpcf.cfh.ParmCount" , FT_UINT32, BASE_DEC, NULL, 0x0, "CFH parameter count", HFILL }},
653 { &hf_mq_pcf_prmtyp , { "ParmTyp..", "mqpcf.parm.type" , FT_UINT32 , BASE_DEC | BASE_EXT_STRING, &mq_PrmTyp_xvals, 0x0, "MQPCF parameter type", HFILL }},
654 { &hf_mq_pcf_prmlen , { "ParmLen..", "mqpcf.parm.len" , FT_UINT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter length", HFILL }},
655 { &hf_mq_pcf_prmid , { "ParmID...", "mqpcf.parm.id" , FT_UINT32 , BASE_DEC | BASE_EXT_STRING, &mq_PrmId_xvals, 0x0, "MQPCF parameter id", HFILL }},
656 { &hf_mq_pcf_prmidnovals , { "ParmID...", "mqpcf.parm.idNoVals" , FT_UINT32 , BASE_HEX_DEC, NULL, 0x0, "MQPCF parameter id No Vals", HFILL }},
657 { &hf_mq_pcf_filterop , { "FilterOP.", "mqpcf.filter.op" , FT_UINT32 , BASE_DEC, VALS(mq_FilterOP_vals), 0x0, "MQPCF Filter operator", HFILL }},
658 { &hf_mq_pcf_prmccsid , { "ParmCCSID", "mqpcf.parm.ccsid" , FT_UINT32 , BASE_DEC | BASE_RANGE_STRING, RVALS(mq_ccsid_rvals), 0x0, "MQPCF parameter ccsid", HFILL }},
659 { &hf_mq_pcf_prmstrlen , { "ParmStrLn", "mqpcf.parm.strlen" , FT_UINT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter strlen", HFILL }},
660 { &hf_mq_pcf_prmcount , { "ParmCount", "mqpcf.parm.count" , FT_UINT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter count", HFILL }},
661 { &hf_mq_pcf_prmunused , { "ParmUnuse", "mqpcf.parm.unused" , FT_UINT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter unused", HFILL }},
662 { &hf_mq_pcf_string , { "String...", "mqpcf.parm.string" , FT_STRINGZ, BASE_NONE, NULL, 0x0, "MQPCF parameter string", HFILL }},
663 { &hf_mq_pcf_stringlist , { "StrList..", "mqpcf.parm.stringlist", FT_STRINGZ, BASE_NONE, NULL, 0x0, "MQPCF parameter string list", HFILL }},
664 { &hf_mq_pcf_int , { "Integer..", "mqpcf.parm.int" , FT_INT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter int", HFILL }},
665 { &hf_mq_pcf_intlist , { "IntList..", "mqpcf.parm.intlist" , FT_INT32 , BASE_DEC, NULL, 0x0, "MQPCF parameter int list", HFILL }},
666 { &hf_mq_pcf_bytestring , { "ByteStr..", "mqpcf.parm.bytestring", FT_BYTES , BASE_NONE, NULL, 0x0, "MQPCF parameter byte string", HFILL }},
667 { &hf_mq_pcf_int64 , { "Int64....", "mqpcf.parm.int64" , FT_INT64 , BASE_DEC, NULL, 0x0, "MQPCF parameter int64", HFILL }},
668 { &hf_mq_pcf_int64list , { "Int64List", "mqpcf.parm.int64list" , FT_INT64 , BASE_DEC, NULL, 0x0, "MQPCF parameter int64 list", HFILL }},
676 static ei_register_info ei[] =
678 { &ei_mq_pcf_prmln0, { "mqpcf.parm.len0" , PI_MALFORMED, PI_ERROR, "MQPCF Parameter length is 0", EXPFILL }},
679 { &ei_mq_pcf_MaxInt, { "mqpcf.parm.IntList" , PI_UNDECODED, PI_WARN , "MQPCF Parameter Integer list exhausted", EXPFILL }},
680 { &ei_mq_pcf_MaxStr, { "mqpcf.parm.StrList" , PI_UNDECODED, PI_WARN , "MQPCF Parameter String list exhausted", EXPFILL }},
681 { &ei_mq_pcf_MaxI64, { "mqpcf.parm.Int64List", PI_UNDECODED, PI_WARN , "MQPCF Parameter Int64 list exhausted", EXPFILL }},
682 { &ei_mq_pcf_MaxPrm, { "mqpcf.parm.MaxPrm" , PI_UNDECODED, PI_WARN , "MQPCF Max number of parameter exhausted", EXPFILL }},
683 { &ei_mq_pcf_PrmCnt, { "mqpcf.parm.PrmCnt" , PI_UNDECODED, PI_WARN , "MQPCF Unkn Parm Cnt Length invalid", EXPFILL }},
686 module_t *mq_pcf_module;
688 proto_mqpcf = proto_register_protocol("WebSphere MQ Programmable Command Formats", "MQ PCF", "mqpcf");
689 proto_register_field_array(proto_mqpcf, hf, array_length(hf));
690 proto_register_subtree_array(ett, array_length(ett));
692 expert_mqpcf = expert_register_protocol(proto_mqpcf);
693 expert_register_field_array(expert_mqpcf, ei, array_length(ei));
695 mq_pcf_module = prefs_register_protocol(proto_mqpcf, NULL);
696 prefs_register_uint_preference(mq_pcf_module, "maxprm",
697 "Set the maximun number of parameter in the PCF to decode",
698 "When dissecting PCF there can be a lot of parameters."
699 " You can limit the number of parameter decoded, before it continue with the next PCF.",
701 prefs_register_uint_preference(mq_pcf_module, "maxlst",
702 "Set the maximun number of Parameter List that are displayed",
703 "When dissecting a parameter of a PCFm, if it is a StringList, IntegerList or Integer64 List, "
704 " You can limit the number of element displayed, before it continue with the next Parameter.",
709 void proto_reg_handoff_mqpcf(void)
711 heur_dissector_add("mq", dissect_mqpcf_heur, "WebSphere MQ PCF", "mqpcf_mq", proto_mqpcf, HEURISTIC_ENABLE);
715 * Editor modelines - http://www.wireshark.org/tools/modelines.html
720 * indent-tabs-mode: nil
723 * vi: set shiftwidth=4 tabstop=8 expandtab:
724 * :indentSize=4:tabSize=8:noTabs=true: