2 * Routines for IBM WebSphere MQ PCF packet dissection
4 * metatech <metatech@flashmail.com>
5 * robionekenobi <robionekenobi@bluewin.ch>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 /* MQ PCF in a nutshell
30 * The MQ Programmable Command Formats API allows remotely configuring a queue manager.
32 * MQ PCF documentation is called "WebSphere MQ Programmable Command Formats and Administration Interface"
41 #include <epan/packet.h>
42 #include <epan/proto.h>
43 #include <epan/expert.h>
44 #include <epan/prefs.h>
45 #include <epan/value_string.h>
46 #include <epan/strutil.h>
47 #include "packet-mq.h"
48 #include "wmem/wmem.h"
50 #define PCF_MAX_PARM 999
51 #define PCF_MAX_LIST 20000
53 guint mq_pcf_maxprm
= PCF_MAX_PARM
;
54 guint mq_pcf_maxlst
= PCF_MAX_LIST
;
56 static int proto_mqpcf
= -1;
58 static int hf_mqpcf_cfh_type
= -1;
59 static int hf_mqpcf_cfh_length
= -1;
60 static int hf_mqpcf_cfh_version
= -1;
61 static int hf_mqpcf_cfh_command
= -1;
62 static int hf_mqpcf_cfh_MsgSeqNbr
= -1;
63 static int hf_mqpcf_cfh_control
= -1;
64 static int hf_mqpcf_cfh_compcode
= -1;
65 static int hf_mqpcf_cfh_reason
= -1;
66 static int hf_mqpcf_cfh_ParmCount
= -1;
68 static int hf_mq_pcf_prmtyp
= -1;
69 static int hf_mq_pcf_prmlen
= -1;
70 static int hf_mq_pcf_prmid
= -1;
71 static int hf_mq_pcf_prmidnovals
= -1;
72 static int hf_mq_pcf_filterop
= -1;
73 static int hf_mq_pcf_prmccsid
= -1;
74 static int hf_mq_pcf_prmstrlen
= -1;
75 static int hf_mq_pcf_prmcount
= -1;
76 static int hf_mq_pcf_prmunused
= -1;
78 static int hf_mq_pcf_string
= -1;
79 static int hf_mq_pcf_stringlist
= -1;
80 static int hf_mq_pcf_int
= -1;
81 static int hf_mq_pcf_intlist
= -1;
82 static int hf_mq_pcf_bytestring
= -1;
83 static int hf_mq_pcf_int64
= -1;
84 static int hf_mq_pcf_int64list
= -1;
86 static expert_field ei_mq_pcf_prmln0
= EI_INIT
;
87 static expert_field ei_mq_pcf_MaxInt
= EI_INIT
;
88 static expert_field ei_mq_pcf_MaxStr
= EI_INIT
;
89 static expert_field ei_mq_pcf_MaxI64
= EI_INIT
;
90 static expert_field ei_mq_pcf_MaxPrm
= EI_INIT
;
91 static expert_field ei_mq_pcf_PrmCnt
= EI_INIT
;
93 static gint ett_mqpcf_prm
= -1;
94 static gint ett_mqpcf
= -1;
95 static gint ett_mqpcf_cfh
= -1;
97 #define MQ_TEXT_CFH "MQ Command Format Header"
99 guint32
dissect_mqpcf_getDigits(guint uCnt
)
101 return (guint
) log10(uCnt
) + 1;
104 guint8
*dissect_mqpcf_parm_getintval(guint uPrm
, guint uVal
)
107 pVs
= (value_string
*)try_val_to_str(uPrm
, GET_VALSV(MQCFINT_Parse
));
111 return (guint8
*)try_val_to_str(uVal
, pVs
);
116 void dissect_mqpcf_parm_int(tvbuff_t
*tvb
, proto_tree
*tree
, guint offset
, guint uPrm
,
117 guint uVal
, int hfindex
, guint iCnt
, guint iMaxCnt
, guint iDigit
, gboolean bParse
)
119 header_field_info
*hfinfo
;
123 pVal
= dissect_mqpcf_parm_getintval(uPrm
, uVal
);
125 hfinfo
= proto_registrar_get_nth(hfindex
);
131 proto_tree_add_int_format(tree
, hfindex
, tvb
, offset
, 4, uVal
,
132 "%s[%*d]: %8d-%s", hfinfo
->name
, iDigit
, iCnt
, uVal
, pVal
);
136 proto_tree_add_int_format(tree
, hfindex
, tvb
, offset
, 4, uVal
,
137 "%s[%*d]: %8x-%d", hfinfo
->name
, iDigit
, iCnt
, uVal
, uVal
);
144 proto_tree_add_int_format_value(tree
, hfindex
, tvb
, offset
, 4, uVal
,
145 "%8d-%s", uVal
, pVal
);
149 proto_tree_add_int_format_value(tree
, hfindex
, tvb
, offset
, 4, uVal
,
150 "%8x-%d", uVal
, uVal
);
155 static void dissect_mqpcf_parm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*mq_tree
,
156 guint offset
, guint32 uCount
, guint bLittleEndian
, gboolean bParse
)
172 const char sMaxLst
[] = " Max # of List reached. DECODE interrupted (actual %u of %u)";
173 const char sPrmLn0
[] = " MQPrm[%3u] has a zero length. DECODE Failed (MQPrm Count: %u)";
174 const char sMaxPrm
[] = " Max # of Parm reached. DECODE interrupted (actual %u of %u)";
175 const char sPrmCnt
[] = " Cnt=-1 and Length(%u) < 16. DECODE interrupted for elem %u";
177 proto_item
*ti
= NULL
;
178 proto_tree
*tree
= NULL
;
180 if (uCount
== (guint32
)-1)
182 guint32 xOfs
= offset
;
185 while (tvb_length_remaining(tvb
, xOfs
) >= 16)
187 uLen
= tvb_get_guint32_endian(tvb
, xOfs
+ 4, bLittleEndian
);
190 ti
= proto_tree_add_text(mq_tree
, tvb
, xOfs
, 16, sPrmCnt
, uLen
, uCnt
);
191 expert_add_info(pinfo
, ti
, &ei_mq_pcf_PrmCnt
);
200 uDig
= dissect_mqpcf_getDigits(uCount
);
202 for (u
= 0; u
< uCount
&& u
< mq_pcf_maxprm
; u
++)
205 uTyp
= tvb_get_guint32_endian(tvb
, offset
, bLittleEndian
);
206 uLen
= tvb_get_guint32_endian(tvb
, offset
+ 4, bLittleEndian
);
209 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, 12, sPrmLn0
, u
+1, uCount
);
210 expert_add_info(pinfo
, ti
, &ei_mq_pcf_prmln0
);
214 uPrm
= tvb_get_guint32_endian(tvb
, offset
+ 8, bLittleEndian
);
218 g_snprintf(strPrm
, (gulong
)sizeof(strPrm
) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d-%-30.30s",
220 uTyp
, val_to_str_const(uTyp
, GET_VALSV(PrmTyp
), " Unknown") + 6,
221 uPrm
, uPrm
, val_to_str_const(uPrm
, GET_VALSV(PrmId
), "Unknown"));
223 g_snprintf(strPrm
, (gulong
)sizeof(strPrm
) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d",
225 uTyp
, val_to_str_const(uTyp
, GET_VALSV(PrmTyp
), " Unknown") + 6,
232 case MQ_MQCFT_COMMAND
:
234 case MQ_MQCFT_RESPONSE
:
236 case MQ_MQCFT_INTEGER
:
239 uVal
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
, bLittleEndian
);
241 pVal
= dissect_mqpcf_parm_getintval(uPrm
, uVal
);
244 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s %d-%s",
249 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s %8x-%d",
252 tree
= proto_item_add_subtree(ti
, ett_mqpcf_prm
);
253 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
254 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
255 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
257 dissect_mqpcf_parm_int(tvb
, tree
, offset
+uLenF
, uPrm
, uVal
, hf_mq_pcf_int
, 0, 0, 0, bParse
);
260 case MQ_MQCFT_STRING
:
264 uCCS
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
, bLittleEndian
);
265 uSLn
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
+ 4, bLittleEndian
);
266 sStr
= tvb_get_string_enc(wmem_packet_scope(), tvb
, offset
+ uLenF
+ 8,
267 uSLn
, (uCCS
!= 500) ? ENC_ASCII
: ENC_EBCDIC
);
269 strip_trailing_blanks(sStr
, uSLn
);
271 format_text_chr(sStr
, strlen(sStr
), '.');
273 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s %s", strPrm
, sStr
);
274 tree
= proto_item_add_subtree(ti
, ett_mqpcf_prm
);
276 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
277 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
278 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
279 proto_tree_add_item(tree
, hf_mq_pcf_prmccsid
, tvb
, offset
+ 12, 4, bLittleEndian
);
280 proto_tree_add_item(tree
, hf_mq_pcf_prmstrlen
, tvb
, offset
+ 16, 4, bLittleEndian
);
282 proto_tree_add_item(tree
, hf_mq_pcf_string
, tvb
, offset
+ uLenF
+ 8, uSLn
, (uCCS
!= 500) ? ENC_ASCII
: ENC_EBCDIC
);
285 case MQ_MQCFT_INTEGER_LIST
:
290 uCnt
= tvb_get_guint32_endian(tvb
, offset
+uLenF
, bLittleEndian
);
291 uDigit
= dissect_mqpcf_getDigits(uCnt
);
293 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s Cnt(%d)", strPrm
, uCnt
);
294 tree
= proto_item_add_subtree(ti
, ett_mqpcf_prm
);
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_endian(tvb
, offset
, bLittleEndian
);
305 dissect_mqpcf_parm_int(tvb
, tree
, offset
, uPrm
, uVal
, hf_mq_pcf_intlist
, u2
+1, uCnt
, uDigit
, bParse
);
310 ti
= proto_tree_add_text(tree
, tvb
, offset
, uLen
, sMaxLst
, u2
, uCnt
);
311 expert_add_info(pinfo
, ti
, &ei_mq_pcf_MaxInt
);
315 case MQ_MQCFT_STRING_LIST
:
320 header_field_info
*hfinfo
;
322 hfinfo
= proto_registrar_get_nth(hf_mq_pcf_stringlist
);
324 uCCS
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
, bLittleEndian
);
325 uCnt
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
+ 4, bLittleEndian
);
326 uSLn
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
+ 8, bLittleEndian
);
328 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s Cnt(%d)", strPrm
, uCnt
);
330 tree
= proto_item_add_subtree(ti
, ett_mqpcf_prm
);
331 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
332 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
333 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
334 proto_tree_add_item(tree
, hf_mq_pcf_prmccsid
, tvb
, offset
+ 12, 4, bLittleEndian
);
335 proto_tree_add_item(tree
, hf_mq_pcf_prmcount
, tvb
, offset
+ 16, 4, bLittleEndian
);
336 proto_tree_add_item(tree
, hf_mq_pcf_prmstrlen
, tvb
, offset
+ 20, 4, bLittleEndian
);
338 uDigit
= dissect_mqpcf_getDigits(uCnt
);
341 for (u2
= 0; u2
< uCnt
&& u2
< mq_pcf_maxlst
; u2
++)
343 sStr
= tvb_get_string_enc(wmem_packet_scope(), tvb
, offset
,
344 uSLn
, (uCCS
!= 500) ? ENC_ASCII
: ENC_EBCDIC
);
346 strip_trailing_blanks(sStr
, uSLn
);
348 format_text_chr(sStr
, strlen(sStr
), '.');
350 proto_tree_add_string_format(tree
, hf_mq_pcf_stringlist
, tvb
, offset
, uSLn
, sStr
,
351 "%s[%*d]: %s", hfinfo
->name
, uDigit
, u2
+1, sStr
);
356 ti
= proto_tree_add_text(tree
, tvb
, offset
, uLen
, sMaxLst
, u2
, uCnt
);
357 expert_add_info(pinfo
, ti
, &ei_mq_pcf_MaxStr
);
365 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s", strPrm
);
366 tree
= proto_item_add_subtree(ti
, ett_mqpcf_prm
);
368 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
369 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
371 proto_tree_add_item(tree
, hf_mq_pcf_bytestring
, tvb
, offset
+ 8, uLen
- 8, bLittleEndian
);
374 case MQ_MQCFT_BYTE_STRING
:
376 uSLn
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
, bLittleEndian
);
379 guint8
*sStrA
= format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb
, offset
+ uLenF
+ 4, uSLn
, ENC_ASCII
) , uSLn
, '.');
380 guint8
*sStrE
= format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb
, offset
+ uLenF
+ 4, uSLn
, ENC_EBCDIC
), uSLn
, '.');
383 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s [Truncated] A(%-.35s) E(%-.35s)", strPrm
, sStrA
, sStrE
);
387 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s A(%s) E(%s)", strPrm
, sStrA
, sStrE
);
392 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s <MISSING>", strPrm
);
394 tree
= proto_item_add_subtree(ti
, ett_mqpcf_prm
);
396 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
397 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
398 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
399 proto_tree_add_item(tree
, hf_mq_pcf_prmstrlen
, tvb
, offset
+ 12, 4, bLittleEndian
);
401 proto_tree_add_item(tree
, hf_mq_pcf_bytestring
, tvb
, offset
+ uLenF
+ 4 , uSLn
, bLittleEndian
);
404 case MQ_MQCFT_TRACE_ROUTE
:
406 case MQ_MQCFT_REPORT
:
408 case MQ_MQCFT_INTEGER_FILTER
:
412 uOpe
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
, bLittleEndian
);
413 uVal
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
+ 4, bLittleEndian
);
415 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s %s %d",
416 strPrm
, val_to_str(uOpe
, GET_VALSV(FilterOP
), " Unknown (0x%02x)")+7, uVal
);
417 tree
= proto_item_add_subtree(ti
, ett_mqpcf_prm
);
419 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
420 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
421 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
422 proto_tree_add_item(tree
, hf_mq_pcf_filterop
, tvb
, offset
+ 12, 4, bLittleEndian
);
424 proto_tree_add_item(tree
, hf_mq_pcf_int
, tvb
, offset
+ uLenF
+ 4, 4, bLittleEndian
);
427 case MQ_MQCFT_STRING_FILTER
:
432 uOpe
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
, bLittleEndian
);
433 uCCS
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
+ 4, bLittleEndian
);
434 uSLn
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
+ 8, bLittleEndian
);
435 sStr
= format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb
, offset
+ uLenF
+ 12, uSLn
, (uCCS
!= 500) ? ENC_ASCII
: ENC_EBCDIC
), uSLn
, '.');
436 strip_trailing_blanks(sStr
, uSLn
);
438 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s %s %s",
439 strPrm
, val_to_str(uOpe
, GET_VALSV(FilterOP
), " Unknown (0x%02x)")+7, sStr
);
440 tree
= proto_item_add_subtree(ti
, ett_mqpcf_prm
);
442 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
443 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
444 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
445 proto_tree_add_item(tree
, hf_mq_pcf_filterop
, tvb
, offset
+ 12, 4, bLittleEndian
);
446 proto_tree_add_item(tree
, hf_mq_pcf_prmccsid
, tvb
, offset
+ 16, 4, bLittleEndian
);
447 proto_tree_add_item(tree
, hf_mq_pcf_prmstrlen
, tvb
, offset
+ 20, 4, bLittleEndian
);
449 proto_tree_add_item(tree
, hf_mq_pcf_string
, tvb
, offset
+ uLenF
+ 12, uSLn
, (uCCS
!= 500) ? ENC_ASCII
: ENC_EBCDIC
);
452 case MQ_MQCFT_BYTE_STRING_FILTER
:
455 uOpe
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
, bLittleEndian
);
456 uSLn
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
+ 4, bLittleEndian
);
459 guint8
*sStrA
= format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb
, offset
+ uLenF
+ 8, uSLn
, ENC_ASCII
), uSLn
, '.');
460 guint8
*sStrE
= format_text_chr(tvb_get_string_enc(wmem_packet_scope(), tvb
, offset
+ uLenF
+ 8, uSLn
, ENC_EBCDIC
), uSLn
, '.');
461 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s %s A(%s) E(%s)",
462 strPrm
, val_to_str(uOpe
, GET_VALSV(FilterOP
), " Unknown (0x%02x)")+7, sStrA
, sStrE
);
466 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s %s <MISSING>",
467 strPrm
, val_to_str(uOpe
, GET_VALSV(FilterOP
), " Unknown (0x%02x)")+7);
469 tree
= proto_item_add_subtree(ti
, ett_mqpcf_prm
);
471 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
472 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
473 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
474 proto_tree_add_item(tree
, hf_mq_pcf_filterop
, tvb
, offset
+ 12, 4, bLittleEndian
);
475 proto_tree_add_item(tree
, hf_mq_pcf_prmstrlen
, tvb
, offset
+ 16, 4, bLittleEndian
);
477 proto_tree_add_item(tree
, hf_mq_pcf_bytestring
, tvb
, offset
+ uLenF
+ 8 , uSLn
, bLittleEndian
);
480 case MQ_MQCFT_COMMAND_XR
:
482 case MQ_MQCFT_XR_MSG
:
484 case MQ_MQCFT_XR_ITEM
:
486 case MQ_MQCFT_XR_SUMMARY
:
490 case MQ_MQCFT_STATISTICS
:
492 case MQ_MQCFT_ACCOUNTING
:
494 case MQ_MQCFT_INTEGER64
:
496 uVal64
= tvb_get_guint64_endian(tvb
, offset
+ uLenF
+ 4, bLittleEndian
);
497 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s %" G_GINT64_MODIFIER
"x (%" G_GINT64_MODIFIER
"d)",
498 strPrm
, uVal64
, uVal64
);
499 tree
= proto_item_add_subtree(ti
, ett_mqpcf_prm
);
501 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
502 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
503 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
504 proto_tree_add_item(tree
, hf_mq_pcf_prmunused
, tvb
, offset
+ 12, 4, bLittleEndian
);
506 proto_tree_add_item(tree
, hf_mq_pcf_int64
, tvb
, offset
+ uLenF
+ 4, 8, bLittleEndian
);
509 case MQ_MQCFT_INTEGER64_LIST
:
513 header_field_info
*hfinfo
;
515 hfinfo
= proto_registrar_get_nth(hf_mq_pcf_int64list
);
517 uCnt
= tvb_get_guint32_endian(tvb
, offset
+ uLenF
, bLittleEndian
);
518 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, "%s Cnt(%d)", strPrm
, uCnt
);
519 tree
= proto_item_add_subtree(ti
, ett_mqpcf_prm
);
520 uDigit
= dissect_mqpcf_getDigits(uCnt
);
522 proto_tree_add_item(tree
, hf_mq_pcf_prmtyp
, tvb
, offset
, 4, bLittleEndian
);
523 proto_tree_add_item(tree
, hf_mq_pcf_prmlen
, tvb
, offset
+ 4, 4, bLittleEndian
);
524 proto_tree_add_item(tree
, (bParse
) ? hf_mq_pcf_prmid
: hf_mq_pcf_prmidnovals
, tvb
, offset
+ 8, 4, bLittleEndian
);
525 proto_tree_add_item(tree
, hf_mq_pcf_prmcount
, tvb
, offset
+ 12, 4, bLittleEndian
);
528 for (u2
= 0; u2
< uCnt
&& u2
< mq_pcf_maxlst
; u2
++)
530 uVal64
= tvb_get_guint64_endian(tvb
, offset
, bLittleEndian
);
531 proto_tree_add_int64_format(tree
, hf_mq_pcf_int64list
, tvb
, offset
, 8, uVal64
,
532 "%s[%*d]: %" G_GINT64_MODIFIER
"d", hfinfo
->name
, uDigit
, u2
+1, uVal64
);
537 ti
= proto_tree_add_text(tree
, tvb
, offset
, uLen
, sMaxLst
, u2
, uCnt
);
538 expert_add_info(pinfo
, ti
, &ei_mq_pcf_MaxI64
);
547 ti
= proto_tree_add_text(mq_tree
, tvb
, offset
, uLen
, sMaxPrm
, u
, uCount
);
548 expert_add_info(pinfo
, ti
, &ei_mq_pcf_MaxPrm
);
552 static void dissect_mqpcf(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, mq_parm_t
* p_mq_parm
)
555 gboolean bLittleEndian
;
557 bLittleEndian
= ((p_mq_parm
->mq_cur_ccsid
.encod
& MQ_MQENC_INTEGER_MASK
) == MQ_MQENC_INTEGER_REVERSED
) ? ENC_LITTLE_ENDIAN
: ENC_BIG_ENDIAN
;
559 if (tvb_length(tvb
) >= 36)
561 gint iSizeMQCFH
= 36;
562 guint32 iCommand
= tvb_get_guint32_endian(tvb
, offset
+ 12, bLittleEndian
);
568 proto_tree
*mqroot_tree
;
576 uTyp
= tvb_get_guint32_endian(tvb
, offset
, bLittleEndian
);
577 uCmd
= tvb_get_guint32_endian(tvb
, offset
+ 12, bLittleEndian
);
578 uCC
= tvb_get_guint32_endian(tvb
, offset
+ 24, bLittleEndian
);
579 uRC
= tvb_get_guint32_endian(tvb
, offset
+ 28, bLittleEndian
);
580 uCnt
= tvb_get_guint32_endian(tvb
, offset
+ 32, bLittleEndian
);
584 g_snprintf(sTmp
, (gulong
)sizeof(sTmp
)-1, " %-s [%d-%s] {%d-%s} PrmCnt(%d) CC(%d-%s) RC(%d-%s)",
586 uTyp
, val_to_str_const(uTyp
, GET_VALSV(mqcft
), "Unknown"),
587 uCmd
, val_to_str_const(uCmd
, GET_VALSV(mqcmd
), "Unknown"),
589 uCC
, val_to_str_const(uCC
, GET_VALSV(mqcc
), "Unknown"),
590 uRC
, val_to_str_const(uRC
, GET_VALSV(mqrc
), "Unknown"));
594 g_snprintf(sTmp
, (gulong
)sizeof(sTmp
)-1, " %-s [%d-%s] {%d-%s} PrmCnt(%d)",
596 uTyp
, val_to_str_const(uTyp
, GET_VALSV(mqcft
), "Unknown"),
597 uCmd
, val_to_str_const(uCmd
, GET_VALSV(mqcmd
), "Unknown"),
601 ti
= proto_tree_add_item(tree
, proto_mqpcf
, tvb
, offset
, -1, ENC_NA
);
603 proto_item_append_text(ti
, " (%s)", val_to_str(iCommand
, GET_VALSV(mqcmd
), "Unknown (0x%02x)"));
604 mqroot_tree
= proto_item_add_subtree(ti
, ett_mqpcf
);
606 ti
= proto_tree_add_text(mqroot_tree
, tvb
, offset
, iSizeMQCFH
, "%s", sTmp
);
607 mq_tree
= proto_item_add_subtree(ti
, ett_mqpcf_cfh
);
609 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_type
, tvb
, offset
+ 0, 4, bLittleEndian
);
610 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_length
, tvb
, offset
+ 4, 4, bLittleEndian
);
611 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_version
, tvb
, offset
+ 8, 4, bLittleEndian
);
612 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_command
, tvb
, offset
+ 12, 4, bLittleEndian
);
613 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_MsgSeqNbr
, tvb
, offset
+ 16, 4, bLittleEndian
);
614 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_control
, tvb
, offset
+ 20, 4, bLittleEndian
);
615 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_compcode
, tvb
, offset
+ 24, 4, bLittleEndian
);
616 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_reason
, tvb
, offset
+ 28, 4, bLittleEndian
);
617 proto_tree_add_item(mq_tree
, hf_mqpcf_cfh_ParmCount
, tvb
, offset
+ 32, 4, bLittleEndian
);
618 dissect_mqpcf_parm(tvb
, pinfo
, mqroot_tree
, offset
+ iSizeMQCFH
, uCnt
, bLittleEndian
, TRUE
);
623 static gboolean
dissect_mqpcf_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
625 if (tvb_length(tvb
) >= 36)
627 mq_parm_t
*p_mq_parm
= (mq_parm_t
*)data
;
628 if (strncmp((const char*)p_mq_parm
->mq_format
, MQ_MQFMT_ADMIN
, 8) == 0
629 || strncmp((const char*)p_mq_parm
->mq_format
, MQ_MQFMT_EVENT
, 8) == 0
630 || strncmp((const char*)p_mq_parm
->mq_format
, MQ_MQFMT_PCF
, 8) == 0)
632 /* Dissect the packet */
633 dissect_mqpcf(tvb
, pinfo
, tree
, p_mq_parm
);
636 if (strncmp((const char *)p_mq_parm
->mq_format
, "LPOO", 4) == 0)
638 gboolean bLittleEndian
;
639 bLittleEndian
= ((p_mq_parm
->mq_cur_ccsid
.encod
& MQ_MQENC_INTEGER_MASK
) == MQ_MQENC_INTEGER_REVERSED
) ? ENC_LITTLE_ENDIAN
:ENC_BIG_ENDIAN
;
640 dissect_mqpcf_parm(tvb
, pinfo
, tree
, 0, (guint32
)-1, bLittleEndian
, FALSE
);
647 void proto_register_mqpcf(void)
649 expert_module_t
*expert_mqpcf
;
651 static hf_register_info hf
[] =
653 { &hf_mqpcf_cfh_type
, { "Type.....", "mqpcf.cfh.type", FT_UINT32
, BASE_DEC
, VALS(&GET_VALSV(mqcft
)), 0x0, "CFH type", HFILL
}},
654 { &hf_mqpcf_cfh_length
, { "Length...", "mqpcf.cfh.length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "CFH length", HFILL
}},
655 { &hf_mqpcf_cfh_version
, { "Version..", "mqpcf.cfh.version", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "CFH version", HFILL
}},
656 { &hf_mqpcf_cfh_command
, { "Command..", "mqpcf.cfh.command", FT_UINT32
, BASE_DEC
, VALS(&GET_VALSV(mqcmd
)), 0x0, "CFH command", HFILL
}},
657 { &hf_mqpcf_cfh_MsgSeqNbr
, { "MsgSeqNbr", "mqpcf.cfh.MsgSeqNbr", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "CFH message sequence number", HFILL
}},
658 { &hf_mqpcf_cfh_control
, { "Control..", "mqpcf.cfh.control", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "CFH control", HFILL
}},
659 { &hf_mqpcf_cfh_compcode
, { "CompCode.", "mqpcf.cfh.compcode", FT_UINT32
, BASE_DEC
, VALS(&GET_VALSV(mqcc
)), 0x0, "CFH completion code", HFILL
}},
660 { &hf_mqpcf_cfh_reason
, { "ReasCode.", "mqpcf.cfh.reasoncode", FT_UINT32
, BASE_DEC
, VALS(&GET_VALSV(mqrc
)), 0x0, "CFH reason code", HFILL
}},
661 { &hf_mqpcf_cfh_ParmCount
, { "ParmCount", "mqpcf.cfh.ParmCount", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "CFH parameter count", HFILL
}},
663 { &hf_mq_pcf_prmtyp
, { "ParmTyp..", "mqpcf.parm.type", FT_UINT32
, BASE_DEC
, VALS(&GET_VALSV(PrmTyp
)), 0x0, "MQPCF parameter type", HFILL
}},
664 { &hf_mq_pcf_prmlen
, { "ParmLen..", "mqpcf.parm.len", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter length", HFILL
}},
665 { &hf_mq_pcf_prmid
, { "ParmID...", "mqpcf.parm.id", FT_UINT32
, BASE_DEC
, VALS(&GET_VALSV(PrmId
)), 0x0, "MQPCF parameter id", HFILL
}},
666 { &hf_mq_pcf_prmidnovals
, { "ParmID...", "mqpcf.parm.idNoVals", FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, "MQPCF parameter id No Vals", HFILL
}},
667 { &hf_mq_pcf_filterop
, { "FilterOP.", "mqpcf.filter.op", FT_UINT32
, BASE_DEC
, VALS(&GET_VALSV(FilterOP
)), 0x0, "MQPCF Filter operator", HFILL
}},
668 { &hf_mq_pcf_prmccsid
, { "ParmCCSID", "mqpcf.parm.ccsid", FT_UINT32
, BASE_DEC
| BASE_RANGE_STRING
, RVALS(&GET_VALRV(ccsid
)), 0x0, "MQPCF parameter ccsid", HFILL
}},
669 { &hf_mq_pcf_prmstrlen
, { "ParmStrLn", "mqpcf.parm.strlen", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter strlen", HFILL
}},
670 { &hf_mq_pcf_prmcount
, { "ParmCount", "mqpcf.parm.count", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter count", HFILL
}},
671 { &hf_mq_pcf_prmunused
, { "ParmUnuse", "mqpcf.parm.unused", FT_UINT32
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter unused", HFILL
}},
672 { &hf_mq_pcf_string
, { "String...", "mqpcf.parm.string", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, "MQPCF parameter string", HFILL
}},
673 { &hf_mq_pcf_stringlist
, { "StrList..", "mqpcf.parm.stringlist", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, "MQPCF parameter string list", HFILL
}},
674 { &hf_mq_pcf_int
, { "Integer..", "mqpcf.parm.int", FT_INT32
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter int", HFILL
}},
675 { &hf_mq_pcf_intlist
, { "IntList..", "mqpcf.parm.intlist", FT_INT32
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter int list", HFILL
}},
676 { &hf_mq_pcf_bytestring
, { "ByteStr..", "mqpcf.parm.bytestring", FT_BYTES
, BASE_NONE
, NULL
, 0x0, "MQPCF parameter byte string", HFILL
}},
677 { &hf_mq_pcf_int64
, { "Int64....", "mqpcf.parm.int64", FT_INT64
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter int64", HFILL
}},
678 { &hf_mq_pcf_int64list
, { "Int64List", "mqpcf.parm.int64list", FT_INT64
, BASE_DEC
, NULL
, 0x0, "MQPCF parameter int64 list", HFILL
}},
686 static ei_register_info ei
[] =
688 { &ei_mq_pcf_prmln0
, { "mqpcf.parm.len0", PI_MALFORMED
, PI_ERROR
, "MQPCF Parameter length is 0", EXPFILL
}},
689 { &ei_mq_pcf_MaxInt
, { "mqpcf.parm.IntList", PI_UNDECODED
, PI_WARN
, "MQPCF Parameter Integer list exhausted", EXPFILL
}},
690 { &ei_mq_pcf_MaxStr
, { "mqpcf.parm.StrList", PI_UNDECODED
, PI_WARN
, "MQPCF Parameter String list exhausted", EXPFILL
}},
691 { &ei_mq_pcf_MaxI64
, { "mqpcf.parm.Int64List", PI_UNDECODED
, PI_WARN
, "MQPCF Parameter Int64 list exhausted", EXPFILL
}},
692 { &ei_mq_pcf_MaxPrm
, { "mqpcf.parm.MaxPrm", PI_UNDECODED
, PI_WARN
, "MQPCF Max number of parameter exhausted", EXPFILL
}},
693 { &ei_mq_pcf_PrmCnt
, { "mqpcf.parm.PrmCnt", PI_UNDECODED
, PI_WARN
, "MQPCF Unkn Parm Cnt Length invalid", EXPFILL
}},
696 module_t
*mq_pcf_module
;
698 proto_mqpcf
= proto_register_protocol("WebSphere MQ Programmable Command Formats", "MQ PCF", "mqpcf");
699 proto_register_field_array(proto_mqpcf
, hf
, array_length(hf
));
700 proto_register_subtree_array(ett
, array_length(ett
));
702 expert_mqpcf
= expert_register_protocol(proto_mqpcf
);
703 expert_register_field_array(expert_mqpcf
, ei
, array_length(ei
));
705 mq_pcf_module
= prefs_register_protocol(proto_mqpcf
, NULL
);
706 prefs_register_uint_preference(mq_pcf_module
, "maxprm",
707 "Set the maximun number of parameter in the PCF to decode",
708 "When dissecting PCF there can be a lot of parameters."
709 " You can limit the number of parameter decoded, before it continue with the next PCF.",
711 prefs_register_uint_preference(mq_pcf_module
, "maxlst",
712 "Set the maximun number of Parameter List that are displayed",
713 "When dissecting a parameter of a PCFm, if it is a StringList, IntegerList or Integer64 List, "
714 " You can limit the number of element displayed, before it continue with the next Parameter.",
719 void proto_reg_handoff_mqpcf(void)
721 heur_dissector_add("mq", dissect_mqpcf_heur
, proto_mqpcf
);
725 * Editor modelines - http://www.wireshark.org/tools/modelines.html
730 * indent-tabs-mode: t
733 * vi: set shiftwidth=4 tabstop=4 noexpandtab:
734 * :indentSize=4:tabSize=4:noTabs=false: