MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-mq-pcf.c
blob3be5ae118ed9acc27ec919076e5d5d1148d81ce6
1 /* packet-mq-pcf.c
2 * Routines for IBM WebSphere MQ PCF packet dissection
4 * metatech <metatech@flashmail.com>
5 * robionekenobi <robionekenobi@bluewin.ch>
7 * $Id$
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"
35 #include "config.h"
37 #include <string.h>
38 #include <math.h>
40 #include <glib.h>
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)
106 value_string *pVs;
107 pVs = (value_string *)try_val_to_str(uPrm, GET_VALSV(MQCFINT_Parse));
109 if (pVs)
111 return (guint8 *)try_val_to_str(uVal, pVs);
113 return NULL;
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;
120 guint8 *pVal = NULL;
122 if (bParse)
123 pVal = dissect_mqpcf_parm_getintval(uPrm, uVal);
125 hfinfo = proto_registrar_get_nth(hfindex);
127 if (iMaxCnt > 1)
129 if (pVal)
131 proto_tree_add_int_format(tree, hfindex, tvb, offset, 4, uVal,
132 "%s[%*d]: %8d-%s", hfinfo->name, iDigit, iCnt, uVal, pVal);
134 else
136 proto_tree_add_int_format(tree, hfindex, tvb, offset, 4, uVal,
137 "%s[%*d]: %8x-%d", hfinfo->name, iDigit, iCnt, uVal, uVal);
140 else
142 if (pVal)
144 proto_tree_add_int_format_value(tree, hfindex, tvb, offset, 4, uVal,
145 "%8d-%s", uVal, pVal);
147 else
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)
158 guint32 u = 0;
159 guint32 tOfs = 0;
160 guint32 uLenF;
161 char strPrm[256];
162 guint32 uTyp;
163 guint32 uLen = 0;
164 guint32 uPrm;
165 guint32 uCnt;
166 guint32 uCCS;
167 guint32 uSLn;
168 guint32 uVal;
169 guint64 uVal64;
170 guint32 uDig;
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;
184 uCnt = 0;
185 while (tvb_length_remaining(tvb, xOfs) >= 16)
187 uLen = tvb_get_guint32_endian(tvb, xOfs + 4, bLittleEndian);
188 if (uLen < 16)
190 ti = proto_tree_add_text(mq_tree, tvb, xOfs, 16, sPrmCnt, uLen, uCnt);
191 expert_add_info(pinfo, ti, &ei_mq_pcf_PrmCnt);
192 break;
194 uCnt++;
195 xOfs += uLen;
197 uCount = uCnt;
200 uDig = dissect_mqpcf_getDigits(uCount);
202 for (u = 0; u < uCount && u < mq_pcf_maxprm; u++)
204 tOfs = offset;
205 uTyp = tvb_get_guint32_endian(tvb, offset , bLittleEndian);
206 uLen = tvb_get_guint32_endian(tvb, offset + 4, bLittleEndian);
207 if (uLen == 0)
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);
211 u = uCount;
212 break;
214 uPrm = tvb_get_guint32_endian(tvb, offset + 8, bLittleEndian);
215 uLenF = 12;
217 if (bParse)
218 g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d-%-30.30s",
219 "MQPrm", uDig, u+1,
220 uTyp, val_to_str_const(uTyp, GET_VALSV(PrmTyp), " Unknown") + 6,
221 uPrm, uPrm, val_to_str_const(uPrm, GET_VALSV(PrmId), "Unknown"));
222 else
223 g_snprintf(strPrm, (gulong)sizeof(strPrm) - 1, " %-s[%*u] {%2d-%-15.15s} %8x/%5d",
224 "XtraD", uDig, u+1,
225 uTyp, val_to_str_const(uTyp, GET_VALSV(PrmTyp), " Unknown") + 6,
226 uPrm, uPrm);
228 switch (uTyp)
230 case MQ_MQCFT_NONE:
231 break;
232 case MQ_MQCFT_COMMAND:
233 break;
234 case MQ_MQCFT_RESPONSE:
235 break;
236 case MQ_MQCFT_INTEGER:
238 guint8 *pVal = NULL;
239 uVal = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian);
240 if (bParse)
241 pVal = dissect_mqpcf_parm_getintval(uPrm, uVal);
242 if (pVal)
244 ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %d-%s",
245 strPrm, uVal, pVal);
247 else
249 ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %8x-%d",
250 strPrm, uVal, uVal);
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);
259 break;
260 case MQ_MQCFT_STRING:
262 guint8 *sStr;
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);
268 if (*sStr)
269 strip_trailing_blanks(sStr, uSLn);
270 if (*sStr)
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);
284 break;
285 case MQ_MQCFT_INTEGER_LIST:
287 guint32 u2;
288 guint32 uDigit = 0;
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);
301 offset += uLenF+4;
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);
306 offset += 4;
308 if (u2 != uCnt)
310 ti = proto_tree_add_text(tree, tvb, offset, uLen, sMaxLst, u2, uCnt);
311 expert_add_info(pinfo, ti, &ei_mq_pcf_MaxInt);
314 break;
315 case MQ_MQCFT_STRING_LIST:
317 guint32 u2;
318 guint32 uDigit;
319 guint8 *sStr;
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);
340 offset += uLenF+12;
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);
345 if (*sStr)
346 strip_trailing_blanks(sStr, uSLn);
347 if (*sStr)
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);
352 offset += uSLn;
354 if (u2 != uCnt)
356 ti = proto_tree_add_text(tree, tvb, offset, uLen, sMaxLst, u2, uCnt);
357 expert_add_info(pinfo, ti, &ei_mq_pcf_MaxStr);
360 break;
361 case MQ_MQCFT_EVENT:
362 break;
363 case MQ_MQCFT_USER:
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);
373 break;
374 case MQ_MQCFT_BYTE_STRING:
376 uSLn = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian);
377 if (uSLn)
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, '.');
381 if (uSLn > 35)
383 ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s [Truncated] A(%-.35s) E(%-.35s)", strPrm, sStrA, sStrE);
385 else
387 ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s A(%s) E(%s)", strPrm, sStrA, sStrE);
390 else
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);
403 break;
404 case MQ_MQCFT_TRACE_ROUTE:
405 break;
406 case MQ_MQCFT_REPORT:
407 break;
408 case MQ_MQCFT_INTEGER_FILTER:
410 guint32 uOpe;
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);
426 break;
427 case MQ_MQCFT_STRING_FILTER:
429 guint8 *sStr;
430 guint32 uOpe;
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);
451 break;
452 case MQ_MQCFT_BYTE_STRING_FILTER:
454 guint32 uOpe;
455 uOpe = tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian);
456 uSLn = tvb_get_guint32_endian(tvb, offset + uLenF + 4, bLittleEndian);
457 if (uSLn)
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);
464 else
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);
479 break;
480 case MQ_MQCFT_COMMAND_XR:
481 break;
482 case MQ_MQCFT_XR_MSG:
483 break;
484 case MQ_MQCFT_XR_ITEM:
485 break;
486 case MQ_MQCFT_XR_SUMMARY:
487 break;
488 case MQ_MQCFT_GROUP:
489 break;
490 case MQ_MQCFT_STATISTICS:
491 break;
492 case MQ_MQCFT_ACCOUNTING:
493 break;
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);
508 break;
509 case MQ_MQCFT_INTEGER64_LIST:
511 guint32 u2;
512 guint32 uDigit;
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);
527 offset += uLenF + 4;
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);
533 offset += 8;
535 if (u2 != uCnt)
537 ti = proto_tree_add_text(tree, tvb, offset, uLen, sMaxLst, u2, uCnt);
538 expert_add_info(pinfo, ti, &ei_mq_pcf_MaxI64);
541 break;
543 offset = tOfs+uLen;
545 if (u != uCount)
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)
554 gint offset = 0;
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);
564 if (tree)
566 proto_item *ti;
567 proto_tree *mq_tree;
568 proto_tree *mqroot_tree;
569 char sTmp[256];
570 guint32 uCnt;
571 guint32 uTyp;
572 guint32 uCmd;
573 guint32 uCC;
574 guint32 uRC;
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);
582 if (uCC || uRC)
584 g_snprintf(sTmp, (gulong)sizeof(sTmp)-1, " %-s [%d-%s] {%d-%s} PrmCnt(%d) CC(%d-%s) RC(%d-%s)",
585 MQ_TEXT_CFH,
586 uTyp, val_to_str_const(uTyp, GET_VALSV(mqcft), "Unknown"),
587 uCmd, val_to_str_const(uCmd, GET_VALSV(mqcmd), "Unknown"),
588 uCnt,
589 uCC, val_to_str_const(uCC, GET_VALSV(mqcc), "Unknown"),
590 uRC, val_to_str_const(uRC, GET_VALSV(mqrc), "Unknown"));
592 else
594 g_snprintf(sTmp, (gulong)sizeof(sTmp)-1, " %-s [%d-%s] {%d-%s} PrmCnt(%d)",
595 MQ_TEXT_CFH,
596 uTyp, val_to_str_const(uTyp, GET_VALSV(mqcft), "Unknown"),
597 uCmd, val_to_str_const(uCmd, GET_VALSV(mqcmd), "Unknown"),
598 uCnt);
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);
634 return TRUE;
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);
641 return TRUE;
644 return 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 }},
680 static gint *ett[] =
682 &ett_mqpcf,
683 &ett_mqpcf_prm,
684 &ett_mqpcf_cfh,
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.",
710 10, &mq_pcf_maxprm);
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.",
715 10, &mq_pcf_maxlst);
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
727 * Local variables:
728 * c-basic-offset: 4
729 * tab-width: 4
730 * indent-tabs-mode: t
731 * End:
733 * vi: set shiftwidth=4 tabstop=4 noexpandtab:
734 * :indentSize=4:tabSize=4:noTabs=false: