2 * Routines for IBM WebSphere MQ PCF packet dissection
4 * metatech <metatech@flashmail.com>
5 * Robert Grange <robionekenobi@bluewin.ch>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
14 /* MQ PCF in a nutshell
16 * The MQ Programmable Command Formats API allows remotely configuring a queue manager.
18 * MQ PCF documentation is called "WebSphere MQ Programmable Command Formats and Administration Interface"
19 * Formats and Administration Interface"
23 * ftp://public.dhe.ibm.com/software/integration/wmq/docs/V7.0/PDFs/V7.0_2008/csqzak11.pdf
30 #include <epan/packet.h>
31 #include <epan/expert.h>
32 #include <epan/prefs.h>
33 #include <epan/strutil.h>
35 #include "packet-mq.h"
37 void proto_register_mqpcf(void);
38 void proto_reg_handoff_mqpcf(void);
40 #define PCF_MAX_PARM 999
41 #define PCF_MAX_LIST 20000
43 static unsigned mq_pcf_maxprm
= PCF_MAX_PARM
;
44 static unsigned mq_pcf_maxlst
= PCF_MAX_LIST
;
46 static int proto_mqpcf
;
48 static int hf_mqpcf_cfh_type
;
49 static int hf_mqpcf_cfh_length
;
50 static int hf_mqpcf_cfh_version
;
51 static int hf_mqpcf_cfh_command
;
52 static int hf_mqpcf_cfh_MsgSeqNbr
;
53 static int hf_mqpcf_cfh_control
;
54 static int hf_mqpcf_cfh_compcode
;
55 static int hf_mqpcf_cfh_reason
;
56 static int hf_mqpcf_cfh_ParmCount
;
58 static int hf_mq_pcf_prmtyp
;
59 static int hf_mq_pcf_prmlen
;
60 static int hf_mq_pcf_prmid
;
61 static int hf_mq_pcf_prmidnovals
;
62 static int hf_mq_pcf_filterop
;
63 static int hf_mq_pcf_prmccsid
;
64 static int hf_mq_pcf_prmstrlen
;
65 static int hf_mq_pcf_prmcount
;
66 static int hf_mq_pcf_prmunused
;
68 static int hf_mq_pcf_string
;
69 static int hf_mq_pcf_stringlist
;
70 static int hf_mq_pcf_int
;
71 static int hf_mq_pcf_intlist
;
72 static int hf_mq_pcf_bytestring
;
73 static int hf_mq_pcf_int64
;
74 static int hf_mq_pcf_int64list
;
76 static expert_field ei_mq_pcf_hdrlne
;
77 static expert_field ei_mq_pcf_prmln0
;
78 static expert_field ei_mq_pcf_MaxInt
;
79 static expert_field ei_mq_pcf_MaxStr
;
80 static expert_field ei_mq_pcf_MaxI64
;
81 static expert_field ei_mq_pcf_MaxPrm
;
82 static expert_field ei_mq_pcf_PrmCnt
;
84 static int ett_mqpcf_prm
;
85 static int ett_mqpcf_grp
;
87 static int ett_mqpcf_cfh
;
89 #define MQ_TEXT_CFH "MQ Command Format Header"
91 static uint32_t dissect_mqpcf_getDigits(unsigned uCnt
)
93 return (uint32_t)(log10((double)uCnt
) + 1);
96 * Here we get a special value_string, that return another value_string
97 * pointer instead of string value. This let us use the try_val_to_str
98 * to get val_to_str value from the value of a parameter on a more
99 * easier way than using switch cases.
101 const uint8_t *dissect_mqpcf_parm_getintval(unsigned uPrm
, unsigned uVal
)
103 const value_string
*pVs
;
104 pVs
= (const value_string
*)try_val_to_str_ext(uPrm
, GET_VALS_EXTP(MQCFINT_Parse
));
108 return (const uint8_t *)try_val_to_str(uVal
, pVs
);
113 static void dissect_mqpcf_parm_int(tvbuff_t
*tvb
, proto_tree
*tree
, unsigned offset
, unsigned uPrm
,
114 unsigned uVal
, int hfindex
, unsigned iCnt
, unsigned iMaxCnt
,
115 unsigned iDigit
, bool bParse
)
117 header_field_info
*hfinfo
;
118 const uint8_t *pVal
= NULL
;
121 pVal
= dissect_mqpcf_parm_getintval(uPrm
, uVal
);
123 hfinfo
= proto_registrar_get_nth(hfindex
);
129 proto_tree_add_int_format(tree
, hfindex
, tvb
, offset
, 4, uVal
,
130 "%s[%*d]: %s (%d)", hfinfo
->name
, iDigit
, iCnt
, pVal
, uVal
);
134 proto_tree_add_int_format(tree
, hfindex
, tvb
, offset
, 4, uVal
,
135 "%s[%*d]: 0x%08x (%d)", hfinfo
->name
, iDigit
, iCnt
, uVal
, uVal
);
142 proto_tree_add_int_format_value(tree
, hfindex
, tvb
, offset
, 4, uVal
,
143 "%s (%d) ", pVal
, uVal
);
147 proto_tree_add_int_format_value(tree
, hfindex
, tvb
, offset
, 4, uVal
,
148 "0x%08x (%d)", uVal
, uVal
);
153 // NOLINTNEXTLINE(misc-no-recursion)
154 int dissect_mqpcf_parm_grp(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* mq_tree
,
155 unsigned offset
, unsigned bLittleEndian
, bool bParse
)
160 uLen
= tvb_get_uint32(tvb
, offset
+ 4, bLittleEndian
);
161 uCnt
= tvb_get_uint32(tvb
, offset
+ 12, bLittleEndian
);
163 dissect_mqpcf_parm(tvb
, pinfo
, mq_tree
, offset
+ uLen
, uCnt
, bLittleEndian
, bParse
);
165 for (uint32_t u
= 0; u
< uCnt
; u
++)
167 offset
+= tvb_get_uint32(tvb
, offset
+ 4, bLittleEndian
);
174 // NOLINTNEXTLINE(misc-no-recursion)
175 uint32_t dissect_mqpcf_parm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*mq_tree
,
176 unsigned offset
, uint32_t uCount
, unsigned bLittleEndian
, bool bParse
)
192 uint32_t _offset
= offset
;
194 static const char *sMaxLst
= " Max # of List reached. DECODE interrupted (actual %u of %u)";
195 static const char *sPrmLn0
= " MQPrm[%3u] has a zero length. DECODE Failed (MQPrm Count: %u)";
196 static const char *sHdrLne
= " MQPrm[%3u] PCF Header not enough remaining bytes in pdu. DECODE Failed (MQPrm Count: %u)";
197 static const char *sMaxPrm
= " Max # of Parm reached. DECODE interrupted (actual %u of %u)";
198 static const char *sPrmCnt
= " Cnt=-1 and Length(%u) < 16. DECODE interrupted for elem %u";
200 proto_item
*ti
= NULL
;
201 proto_tree
*tree
= NULL
;
203 if (uCount
== (uint32_t)-1)
205 uint32_t xOfs
= offset
;
208 while (tvb_reported_length_remaining(tvb
, xOfs
) >= 16)
210 uLen
= tvb_get_uint32(tvb
, xOfs
+ 4, bLittleEndian
);
213 proto_tree_add_expert_format(tree
, pinfo
, &ei_mq_pcf_PrmCnt
, tvb
, xOfs
, 16, sPrmCnt
, uLen
, uCnt
);
222 uDig
= dissect_mqpcf_getDigits(uCount
);
223 for (u
= 0; u
< uCount
&& u
< mq_pcf_maxprm
; u
++)
226 uMax
= (unsigned)tvb_reported_length_remaining(tvb
, tOfs
);
229 proto_tree_add_expert_format(tree
, pinfo
, &ei_mq_pcf_hdrlne
, tvb
, offset
, 12, sHdrLne
, u
+ 1, uCount
);
233 uTyp
= tvb_get_uint32(tvb
, offset
, bLittleEndian
);
234 uLen
= tvb_get_uint32(tvb
, offset
+ 4, bLittleEndian
);
237 proto_tree_add_expert_format(tree
, pinfo
, &ei_mq_pcf_prmln0
, tvb
, offset
, 12, sPrmLn0
, u
+ 1, uCount
);
241 /* Try to decode as much as possible value */
242 uLen
= MIN(uLen
, uMax
);
244 uPrm
= tvb_get_uint32(tvb
, offset
+ 8, bLittleEndian
);
248 snprintf(strPrm
, sizeof(strPrm
) - 1, " %-s[%*u] {%2d-%-4.4s} 0x%08x (%4d) %-30.30s",
249 "MQPrm", uDig
, u
+ 1,
250 uTyp
, val_to_str_ext_const(uTyp
, GET_VALS_EXTP(PrmTyp2
), " Unkn") + 6,
251 uPrm
, uPrm
, val_to_str_ext_const(uPrm
, GET_VALS_EXTP(PrmId
), "Unknown"));
253 snprintf(strPrm
, sizeof(strPrm
) - 1, " %-s[%*u] {%2d-%-4.4s} 0x%08x (%4d)",
254 "XtraD", uDig
, u
+ 1,
255 uTyp
, val_to_str_ext_const(uTyp
, GET_VALS_EXTP(PrmTyp2
), " Unkn") + 6,
258 increment_dissection_depth(pinfo
);
263 case MQ_MQCFT_COMMAND
:
265 case MQ_MQCFT_RESPONSE
:
267 case MQ_MQCFT_INTEGER
:
269 const uint8_t *pVal
= NULL
;
270 uVal
= tvb_get_uint32(tvb
, offset
+ uLenF
, bLittleEndian
);
272 pVal
= dissect_mqpcf_parm_getintval(uPrm
, uVal
);
276 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
,
277 "%s: %s (%d)", strPrm
, pVal
, uVal
);
281 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
,
282 "%s: 0x%08x (%d)", strPrm
, uVal
, uVal
);
285 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
286 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
287 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
289 dissect_mqpcf_parm_int(tvb
, tree
, offset
+ uLenF
, uPrm
, uVal
, hf_mq_pcf_int
, 0, 0, 0, bParse
);
292 case MQ_MQCFT_STRING
:
296 uCCS
= tvb_get_uint32(tvb
, offset
+ uLenF
, bLittleEndian
);
297 uSLn
= tvb_get_uint32(tvb
, offset
+ uLenF
+ 4, bLittleEndian
);
298 sStr
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+ uLenF
+ 8,
299 uSLn
, IS_EBCDIC(uCCS
) ? ENC_EBCDIC
: ENC_ASCII
);
301 strip_trailing_blanks(sStr
, uSLn
);
303 sStr
= (uint8_t*)format_text_chr(pinfo
->pool
, sStr
, strlen((const char *)sStr
), '.');
305 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
, "%s: %s", strPrm
, sStr
);
307 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
308 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
309 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
310 proto_tree_add_item(tree
, hf_mq_pcf_prmccsid
, tvb
, offset
+ 12, 4, bLittleEndian
);
311 proto_tree_add_item(tree
, hf_mq_pcf_prmstrlen
, tvb
, offset
+ 16, 4, bLittleEndian
);
313 proto_tree_add_item(tree
, hf_mq_pcf_string
, tvb
, offset
+ uLenF
+ 8, uSLn
, IS_EBCDIC(uCCS
) ? ENC_EBCDIC
: ENC_ASCII
);
316 case MQ_MQCFT_INTEGER_LIST
:
321 uCnt
= tvb_get_uint32(tvb
, offset
+ uLenF
, bLittleEndian
);
322 uDigit
= dissect_mqpcf_getDigits(uCnt
);
324 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, &ti
, "%s-> contain %d Element(s)", strPrm
, uCnt
);
326 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
327 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
328 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
329 proto_tree_add_item(tree
, hf_mq_pcf_prmcount
, tvb
, offset
+ 12, 4, bLittleEndian
);
332 for (u2
= 0; u2
< uCnt
&& u2
< mq_pcf_maxlst
; u2
++)
334 uVal
= tvb_get_uint32(tvb
, offset
, bLittleEndian
);
335 dissect_mqpcf_parm_int(tvb
, tree
, offset
, uPrm
, uVal
, hf_mq_pcf_intlist
, u2
+ 1, uCnt
, uDigit
, bParse
);
340 proto_tree_add_expert_format(tree
, pinfo
, &ei_mq_pcf_MaxInt
, tvb
, offset
, (uCnt
- u2
) * 4, sMaxLst
, u2
, uCnt
);
344 case MQ_MQCFT_STRING_LIST
:
349 header_field_info
*hfinfo
;
351 hfinfo
= proto_registrar_get_nth(hf_mq_pcf_stringlist
);
353 uCCS
= tvb_get_uint32(tvb
, offset
+ uLenF
, bLittleEndian
);
354 uCnt
= tvb_get_uint32(tvb
, offset
+ uLenF
+ 4, bLittleEndian
);
355 uSLn
= tvb_get_uint32(tvb
, offset
+ uLenF
+ 8, bLittleEndian
);
357 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
, "%s-> contain %d Element(s)", strPrm
, uCnt
);
359 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
360 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
361 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
362 proto_tree_add_item(tree
, hf_mq_pcf_prmccsid
, tvb
, offset
+ 12, 4, bLittleEndian
);
363 proto_tree_add_item(tree
, hf_mq_pcf_prmcount
, tvb
, offset
+ 16, 4, bLittleEndian
);
364 proto_tree_add_item(tree
, hf_mq_pcf_prmstrlen
, tvb
, offset
+ 20, 4, bLittleEndian
);
366 uDigit
= dissect_mqpcf_getDigits(uCnt
);
368 offset
+= uLenF
+ 12;
369 for (u2
= 0; u2
< uCnt
&& u2
< mq_pcf_maxlst
; u2
++)
371 sStr
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
,
372 uSLn
, IS_EBCDIC(uCCS
) ? ENC_EBCDIC
: ENC_ASCII
);
374 strip_trailing_blanks(sStr
, uSLn
);
376 sStr
= (uint8_t*)format_text_chr(pinfo
->pool
, sStr
, strlen((const char *)sStr
), '.');
378 proto_tree_add_string_format(tree
, hf_mq_pcf_stringlist
, tvb
, offset
, uSLn
, (const char *)sStr
,
379 "%s[%*d]: %s", hfinfo
->name
, uDigit
, u2
+ 1, sStr
);
384 proto_tree_add_expert_format(tree
, pinfo
, &ei_mq_pcf_MaxStr
, tvb
, offset
, (uCnt
- u2
) * uSLn
, sMaxLst
, u2
, uCnt
);
390 uCnt
= tvb_get_uint32(tvb
, offset
+ 12, bLittleEndian
);
392 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, &ti
, "%s-> contain %d Element(s)", strPrm
, uCnt
);
394 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
395 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
396 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
397 proto_tree_add_item(tree
, hf_mq_pcf_prmcount
, tvb
, offset
+ 12, 4, bLittleEndian
);
399 tOfs
= dissect_mqpcf_parm_grp(tvb
, pinfo
, tree
, offset
, bLittleEndian
, bParse
);
406 tree
= proto_tree_add_subtree(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
, strPrm
);
408 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
409 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
410 proto_tree_add_item(tree
, hf_mq_pcf_bytestring
, tvb
, offset
+ 8, uLen
- 8, bLittleEndian
);
413 case MQ_MQCFT_BYTE_STRING
:
415 uSLn
= tvb_get_uint32(tvb
, offset
+ uLenF
, bLittleEndian
);
418 uint8_t *sStrA
= (uint8_t *)format_text_chr(pinfo
->pool
, tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+ uLenF
+ 4, uSLn
, ENC_ASCII
), uSLn
, '.');
419 uint8_t *sStrE
= (uint8_t *)format_text_chr(pinfo
->pool
, tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+ uLenF
+ 4, uSLn
, ENC_EBCDIC
), uSLn
, '.');
422 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
,
423 "%s: [Truncated] A(%-.35s) E(%-.35s)", strPrm
, sStrA
, sStrE
);
427 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
,
428 "%s: A(%s) E(%s)", strPrm
, sStrA
, sStrE
);
433 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
, "%s <MISSING>", strPrm
);
436 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
437 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
438 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
439 proto_tree_add_item(tree
, hf_mq_pcf_prmstrlen
, tvb
, offset
+ 12, 4, bLittleEndian
);
441 proto_tree_add_item(tree
, hf_mq_pcf_bytestring
, tvb
, offset
+ uLenF
+ 4, uSLn
, bLittleEndian
);
444 case MQ_MQCFT_TRACE_ROUTE
:
446 case MQ_MQCFT_REPORT
:
448 case MQ_MQCFT_INTEGER_FILTER
:
452 uOpe
= tvb_get_uint32(tvb
, offset
+ uLenF
, bLittleEndian
);
453 uVal
= tvb_get_uint32(tvb
, offset
+ uLenF
+ 4, bLittleEndian
);
455 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
, "%s: %s 0x%08x (%d)",
456 strPrm
, val_to_str(uOpe
, GET_VALSV(FilterOP
), " Unknown (0x%02x)") + 7, uVal
, uVal
);
458 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
459 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
460 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
461 proto_tree_add_item(tree
, hf_mq_pcf_filterop
, tvb
, offset
+ 12, 4, bLittleEndian
);
463 proto_tree_add_item(tree
, hf_mq_pcf_int
, tvb
, offset
+ uLenF
+ 4, 4, bLittleEndian
);
466 case MQ_MQCFT_STRING_FILTER
:
471 uOpe
= tvb_get_uint32(tvb
, offset
+ uLenF
, bLittleEndian
);
472 uCCS
= tvb_get_uint32(tvb
, offset
+ uLenF
+ 4, bLittleEndian
);
473 uSLn
= tvb_get_uint32(tvb
, offset
+ uLenF
+ 8, bLittleEndian
);
474 sStr
= (uint8_t *)format_text_chr(pinfo
->pool
,
475 tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+ uLenF
+ 12, uSLn
, IS_EBCDIC(uCCS
) ? ENC_EBCDIC
: ENC_ASCII
),
477 strip_trailing_blanks(sStr
, uSLn
);
479 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
, "%s: %s %s",
480 strPrm
, val_to_str(uOpe
, GET_VALSV(FilterOP
), " Unknown (0x%02x)") + 7, sStr
);
482 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
483 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
484 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
485 proto_tree_add_item(tree
, hf_mq_pcf_filterop
, tvb
, offset
+ 12, 4, bLittleEndian
);
486 proto_tree_add_item(tree
, hf_mq_pcf_prmccsid
, tvb
, offset
+ 16, 4, bLittleEndian
);
487 proto_tree_add_item(tree
, hf_mq_pcf_prmstrlen
, tvb
, offset
+ 20, 4, bLittleEndian
);
489 proto_tree_add_item(tree
, hf_mq_pcf_string
, tvb
, offset
+ uLenF
+ 12, uSLn
, IS_EBCDIC(uCCS
) ? ENC_EBCDIC
: ENC_ASCII
);
492 case MQ_MQCFT_BYTE_STRING_FILTER
:
495 uOpe
= tvb_get_uint32(tvb
, offset
+ uLenF
, bLittleEndian
);
496 uSLn
= tvb_get_uint32(tvb
, offset
+ uLenF
+ 4, bLittleEndian
);
499 uint8_t *sStrA
= (uint8_t *)format_text_chr(pinfo
->pool
, tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+ uLenF
+ 8, uSLn
, ENC_ASCII
), uSLn
, '.');
500 uint8_t *sStrE
= (uint8_t *)format_text_chr(pinfo
->pool
, tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+ uLenF
+ 8, uSLn
, ENC_EBCDIC
), uSLn
, '.');
501 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
, "%s: %s A(%s) E(%s)",
502 strPrm
, val_to_str(uOpe
, GET_VALSV(FilterOP
), " Unknown (0x%02x)") + 7, sStrA
, sStrE
);
506 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
, "%s: %s <MISSING>",
507 strPrm
, val_to_str(uOpe
, GET_VALSV(FilterOP
), " Unknown (0x%02x)") + 7);
510 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
511 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
512 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
513 proto_tree_add_item(tree
, hf_mq_pcf_filterop
, tvb
, offset
+ 12, 4, bLittleEndian
);
514 proto_tree_add_item(tree
, hf_mq_pcf_prmstrlen
, tvb
, offset
+ 16, 4, bLittleEndian
);
516 proto_tree_add_item(tree
, hf_mq_pcf_bytestring
, tvb
, offset
+ uLenF
+ 8, uSLn
, bLittleEndian
);
519 case MQ_MQCFT_COMMAND_XR
:
521 case MQ_MQCFT_XR_MSG
:
523 case MQ_MQCFT_XR_ITEM
:
525 case MQ_MQCFT_XR_SUMMARY
:
527 case MQ_MQCFT_STATISTICS
:
529 case MQ_MQCFT_ACCOUNTING
:
531 case MQ_MQCFT_INTEGER64
:
533 uVal64
= tvb_get_uint64(tvb
, offset
+ uLenF
+ 4, bLittleEndian
);
534 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
,
535 "%s: 0x%" PRIx64
" (%" PRId64
")", strPrm
, uVal64
, uVal64
);
537 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
538 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
539 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
540 proto_tree_add_item(tree
, hf_mq_pcf_prmunused
, tvb
, offset
+ 12, 4, bLittleEndian
);
542 proto_tree_add_item(tree
, hf_mq_pcf_int64
, tvb
, offset
+ uLenF
+ 4, 8, bLittleEndian
);
545 case MQ_MQCFT_INTEGER64_LIST
:
549 header_field_info
*hfinfo
;
551 hfinfo
= proto_registrar_get_nth(hf_mq_pcf_int64list
);
553 uCnt
= tvb_get_uint32(tvb
, offset
+ uLenF
, bLittleEndian
);
554 tree
= proto_tree_add_subtree_format(mq_tree
, tvb
, offset
, uLen
, ett_mqpcf_prm
, NULL
, "%s-> contain %d Element(s)", strPrm
, uCnt
);
555 uDigit
= dissect_mqpcf_getDigits(uCnt
);
557 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
558 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
559 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
560 proto_tree_add_item(tree
, hf_mq_pcf_prmcount
, tvb
, offset
+ 12, 4, bLittleEndian
);
563 for (u2
= 0; u2
< uCnt
&& u2
< mq_pcf_maxlst
; u2
++)
565 uVal64
= tvb_get_uint64(tvb
, offset
, bLittleEndian
);
566 proto_tree_add_int64_format(tree
, hf_mq_pcf_int64list
, tvb
, offset
, 8, uVal64
,
567 "%s[%*d]: 0x%" PRIx64
" (%" PRId64
")",
568 hfinfo
->name
, uDigit
, u2
+ 1, uVal64
, uVal64
);
573 proto_tree_add_expert_format(tree
, pinfo
, &ei_mq_pcf_MaxI64
, tvb
, offset
, (uCnt
- u2
) * 8, sMaxLst
, u2
, uCnt
);
578 decrement_dissection_depth(pinfo
);
579 offset
= tOfs
+ uLen
;
583 proto_tree_add_expert_format(mq_tree
, pinfo
, &ei_mq_pcf_MaxPrm
, tvb
, offset
, tvb_reported_length_remaining(tvb
, offset
), sMaxPrm
, u
, uCount
);
585 return offset
- _offset
;
588 static void dissect_mqpcf(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, mq_parm_t
* p_mq_parm
)
591 unsigned bLittleEndian
;
593 bLittleEndian
= ((p_mq_parm
->mq_cur_ccsid
.encod
& MQ_MQENC_INTEGER_MASK
) == MQ_MQENC_INTEGER_REVERSED
) ? ENC_LITTLE_ENDIAN
: ENC_BIG_ENDIAN
;
595 if (tvb_reported_length(tvb
) >= 36)
598 uint32_t iCommand
= tvb_get_uint32(tvb
, offset
+ 12, bLittleEndian
);
604 proto_tree
*mqroot_tree
;
612 uTyp
= tvb_get_uint32(tvb
, offset
, bLittleEndian
);
613 uCmd
= tvb_get_uint32(tvb
, offset
+ 12, bLittleEndian
);
614 uCC
= tvb_get_uint32(tvb
, offset
+ 24, bLittleEndian
);
615 uRC
= tvb_get_uint32(tvb
, offset
+ 28, bLittleEndian
);
616 uCnt
= tvb_get_uint32(tvb
, offset
+ 32, bLittleEndian
);
620 snprintf(sTmp
, sizeof(sTmp
) - 1, " %-s [%d-%s] {%d-%s} PrmCnt(%d) CC(%d-%s) RC(%d-%s)",
622 uTyp
, val_to_str_const(uTyp
, GET_VALSV(mqcft
), "Unknown"),
623 uCmd
, val_to_str_ext_const(uCmd
, GET_VALS_EXTP(MQCMD
), "Unknown"),
625 uCC
, val_to_str_const(uCC
, GET_VALSV(mqcc
), "Unknown"),
626 uRC
, val_to_str_ext_const(uRC
, GET_VALS_EXTP(MQRC
), "Unknown"));
630 snprintf(sTmp
, sizeof(sTmp
) - 1, " %-s [%d-%s] {%d-%s} PrmCnt(%d)",
632 uTyp
, val_to_str_const(uTyp
, GET_VALSV(mqcft
), "Unknown"),
633 uCmd
, val_to_str_ext_const(uCmd
, GET_VALS_EXTP(MQCMD
), "Unknown"),
637 ti
= proto_tree_add_item(tree
, proto_mqpcf
, tvb
, offset
, -1, ENC_NA
);
639 proto_item_append_text(ti
, " (%s)", val_to_str_ext(iCommand
, GET_VALS_EXTP(MQCMD
), "Unknown (0x%02x)"));
640 mqroot_tree
= proto_item_add_subtree(ti
, ett_mqpcf
);
642 mq_tree
= proto_tree_add_subtree(mqroot_tree
, tvb
, offset
, iSizeMQCFH
, ett_mqpcf_cfh
, NULL
, sTmp
);
644 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_type
, tvb
, offset
+ 0, 4, bLittleEndian
);
645 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_length
, tvb
, offset
+ 4, 4, bLittleEndian
);
646 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_version
, tvb
, offset
+ 8, 4, bLittleEndian
);
647 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_command
, tvb
, offset
+ 12, 4, bLittleEndian
);
648 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_MsgSeqNbr
, tvb
, offset
+ 16, 4, bLittleEndian
);
649 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_control
, tvb
, offset
+ 20, 4, bLittleEndian
);
650 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_compcode
, tvb
, offset
+ 24, 4, bLittleEndian
);
651 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_reason
, tvb
, offset
+ 28, 4, bLittleEndian
);
652 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_ParmCount
, tvb
, offset
+ 32, 4, bLittleEndian
);
653 dissect_mqpcf_parm(tvb
, pinfo
, mqroot_tree
, offset
+ iSizeMQCFH
, uCnt
, bLittleEndian
, true);
658 static bool dissect_mqpcf_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
660 if (data
&& tvb_reported_length(tvb
) >= 36)
662 mq_parm_t
*p_mq_parm
= (mq_parm_t
*)data
;
663 if (strncmp((const char*)p_mq_parm
->mq_format
, MQ_MQFMT_ADMIN
, 8) == 0
664 || strncmp((const char*)p_mq_parm
->mq_format
, MQ_MQFMT_EVENT
, 8) == 0
665 || strncmp((const char*)p_mq_parm
->mq_format
, MQ_MQFMT_PCF
, 8) == 0)
667 /* Dissect the packet */
668 dissect_mqpcf(tvb
, pinfo
, tree
, p_mq_parm
);
671 if (strncmp((const char *)p_mq_parm
->mq_format
, "LPOO", 4) == 0)
673 unsigned bLittleEndian
;
674 bLittleEndian
= ((p_mq_parm
->mq_cur_ccsid
.encod
& MQ_MQENC_INTEGER_MASK
) == MQ_MQENC_INTEGER_REVERSED
) ? ENC_LITTLE_ENDIAN
: ENC_BIG_ENDIAN
;
675 dissect_mqpcf_parm(tvb
, pinfo
, tree
, 0, (uint32_t)-1, bLittleEndian
, false);
682 void proto_register_mqpcf(void)
684 expert_module_t
*expert_mqpcf
;
686 static hf_register_info hf
[] =
688 { &hf_mqpcf_cfh_type
, { "Type.....", "mqpcf.cfh.type" , FT_UINT32
, BASE_DEC
, VALS(mq_mqcft_vals
), 0x0, "CFH type", HFILL
}},
689 { &hf_mqpcf_cfh_length
, { "Length...", "mqpcf.cfh.length" , FT_UINT32
, BASE_DEC
, NULL
, 0x0, "CFH length", HFILL
}},
690 { &hf_mqpcf_cfh_version
, { "Version..", "mqpcf.cfh.version" , FT_UINT32
, BASE_DEC
, NULL
, 0x0, "CFH version", HFILL
}},
691 { &hf_mqpcf_cfh_command
, { "Command..", "mqpcf.cfh.command" , FT_UINT32
, BASE_DEC
| BASE_EXT_STRING
, GET_VALS_EXTP(MQCMD
), 0x0, "CFH command", HFILL
}},
692 { &hf_mqpcf_cfh_MsgSeqNbr
, { "MsgSeqNbr", "mqpcf.cfh.MsgSeqNbr" , FT_UINT32
, BASE_DEC
, NULL
, 0x0, "CFH message sequence number", HFILL
}},
693 { &hf_mqpcf_cfh_control
, { "Control..", "mqpcf.cfh.control" , FT_UINT32
, BASE_DEC
, VALS(mq_CtlOpt_vals
), 0x0, "CFH control", HFILL
}},
694 { &hf_mqpcf_cfh_compcode
, { "CompCode.", "mqpcf.cfh.compcode" , FT_UINT32
, BASE_DEC
, VALS(mq_mqcc_vals
), 0x0, "CFH completion code", HFILL
}},
695 { &hf_mqpcf_cfh_reason
, { "ReasCode.", "mqpcf.cfh.reasoncode", FT_UINT32
, BASE_DEC
| BASE_EXT_STRING
, GET_VALS_EXTP(MQRC
), 0x0, "CFH reason code", HFILL
}},
696 { &hf_mqpcf_cfh_ParmCount
, { "ParmCount", "mqpcf.cfh.ParmCount" , FT_UINT32
, BASE_DEC
, NULL
, 0x0, "CFH parameter count", HFILL
}},
698 { &hf_mq_pcf_prmtyp
, { "ParmTyp..", "mqpcf.parm.type" , FT_UINT32
, BASE_DEC
| BASE_EXT_STRING
, GET_VALS_EXTP(PrmTyp
), 0x0, "MQPCF parameter type", HFILL
}},
699 { &hf_mq_pcf_prmlen
, { "ParmLen..", "mqpcf.parm.len" , FT_UINT32
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter length", HFILL
}},
700 { &hf_mq_pcf_prmid
, { "ParmID...", "mqpcf.parm.id" , FT_UINT32
, BASE_DEC
| BASE_EXT_STRING
, GET_VALS_EXTP(PrmId
), 0x0, "MQPCF parameter id", HFILL
}},
701 { &hf_mq_pcf_prmidnovals
, { "ParmID...", "mqpcf.parm.idNoVals" , FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, "MQPCF parameter id No Vals", HFILL
}},
702 { &hf_mq_pcf_filterop
, { "FilterOP.", "mqpcf.filter.op" , FT_UINT32
, BASE_DEC
, VALS(mq_FilterOP_vals
), 0x0, "MQPCF Filter operator", HFILL
}},
703 { &hf_mq_pcf_prmccsid
, { "ParmCCSID", "mqpcf.parm.ccsid" , FT_UINT32
, BASE_DEC
| BASE_RANGE_STRING
, RVALS(mq_ccsid_rvals
), 0x0, "MQPCF parameter ccsid", HFILL
}},
704 { &hf_mq_pcf_prmstrlen
, { "ParmStrLn", "mqpcf.parm.strlen" , FT_UINT32
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter strlen", HFILL
}},
705 { &hf_mq_pcf_prmcount
, { "ParmCount", "mqpcf.parm.count" , FT_UINT32
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter count", HFILL
}},
706 { &hf_mq_pcf_prmunused
, { "ParmUnuse", "mqpcf.parm.unused" , FT_UINT32
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter unused", HFILL
}},
707 { &hf_mq_pcf_string
, { "String...", "mqpcf.parm.string" , FT_STRING
, BASE_NONE
, NULL
, 0x0, "MQPCF parameter string", HFILL
}},
708 { &hf_mq_pcf_stringlist
, { "StrList..", "mqpcf.parm.stringlist", FT_STRING
, BASE_NONE
, NULL
, 0x0, "MQPCF parameter string list", HFILL
}},
709 { &hf_mq_pcf_int
, { "Integer..", "mqpcf.parm.int" , FT_INT32
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter int", HFILL
}},
710 { &hf_mq_pcf_intlist
, { "IntList..", "mqpcf.parm.intlist" , FT_INT32
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter int list", HFILL
}},
711 { &hf_mq_pcf_bytestring
, { "ByteStr..", "mqpcf.parm.bytestring", FT_BYTES
, BASE_NONE
, NULL
, 0x0, "MQPCF parameter byte string", HFILL
}},
712 { &hf_mq_pcf_int64
, { "Int64....", "mqpcf.parm.int64" , FT_INT64
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter int64", HFILL
}},
713 { &hf_mq_pcf_int64list
, { "Int64List", "mqpcf.parm.int64list" , FT_INT64
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter int64 list", HFILL
}},
722 static ei_register_info ei
[] =
724 { &ei_mq_pcf_prmln0
, { "mqpcf.parm.len0" , PI_MALFORMED
, PI_ERROR
, "MQPCF Parameter length is 0", EXPFILL
}},
725 { &ei_mq_pcf_hdrlne
, { "mqpcf.parm.hdrlenerr", PI_MALFORMED
, PI_ERROR
, "MQPCF Header not enough bytes in pdu", EXPFILL
}},
726 { &ei_mq_pcf_MaxInt
, { "mqpcf.parm.IntList" , PI_UNDECODED
, PI_WARN
, "MQPCF Parameter Integer list exhausted", EXPFILL
}},
727 { &ei_mq_pcf_MaxStr
, { "mqpcf.parm.StrList" , PI_UNDECODED
, PI_WARN
, "MQPCF Parameter String list exhausted", EXPFILL
}},
728 { &ei_mq_pcf_MaxI64
, { "mqpcf.parm.Int64List", PI_UNDECODED
, PI_WARN
, "MQPCF Parameter Int64 list exhausted", EXPFILL
}},
729 { &ei_mq_pcf_MaxPrm
, { "mqpcf.parm.MaxPrm" , PI_UNDECODED
, PI_WARN
, "MQPCF Max number of parameter exhausted", EXPFILL
}},
730 { &ei_mq_pcf_PrmCnt
, { "mqpcf.parm.PrmCnt" , PI_UNDECODED
, PI_WARN
, "MQPCF Unkn Parm Cnt Length invalid", EXPFILL
}},
733 module_t
*mq_pcf_module
;
735 proto_mqpcf
= proto_register_protocol("WebSphere MQ Programmable Command Formats", "MQ PCF", "mqpcf");
736 proto_register_field_array(proto_mqpcf
, hf
, array_length(hf
));
737 proto_register_subtree_array(ett
, array_length(ett
));
739 expert_mqpcf
= expert_register_protocol(proto_mqpcf
);
740 expert_register_field_array(expert_mqpcf
, ei
, array_length(ei
));
742 mq_pcf_module
= prefs_register_protocol(proto_mqpcf
, NULL
);
743 prefs_register_uint_preference(mq_pcf_module
, "maxprm",
744 "Set the maximum number of parameters in the PCF to decode",
745 "When dissecting PCF there can be a lot of parameters."
746 " You can limit the number of parameter decoded, before it continue with the next PCF.",
748 prefs_register_uint_preference(mq_pcf_module
, "maxlst",
749 "Set the maximum number of Parameter List that are displayed",
750 "When dissecting a parameter of a PCFm, if it is a StringList, IntegerList or Integer64 List, "
751 " You can limit the number of elements displayed, before it continues with the next Parameter.",
756 void proto_reg_handoff_mqpcf(void)
758 heur_dissector_add("mq", dissect_mqpcf_heur
, "WebSphere MQ PCF", "mqpcf_mq", proto_mqpcf
, HEURISTIC_ENABLE
);
762 * Editor modelines - https://www.wireshark.org/tools/modelines.html
767 * indent-tabs-mode: nil
770 * vi: set shiftwidth=4 tabstop=8 expandtab:
771 * :indentSize=4:tabSize=8:noTabs=true: