emem -> wmem conversion:
[metze/wireshark/wip.git] / epan / dissectors / packet-mq-pcf.c
1 /* packet-mq-pcf.c
2  * Routines for IBM WebSphere MQ PCF packet dissection
3  *
4  * metatech <metatech@flashmail.com>
5  * robionekenobi <robionekenobi@bluewin.ch>
6  *
7  * $Id$
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
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.
17  *
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.
22  *
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.
26  */
27
28 /*  MQ PCF in a nutshell
29 *
30 *   The MQ Programmable Command Formats API allows remotely configuring a queue manager.
31 *
32 *   MQ PCF documentation is called "WebSphere MQ Programmable Command Formats and Administration Interface"
33 */
34
35 #include "config.h"
36
37 #include <string.h>
38
39 #include <glib.h>
40 #include <epan/packet.h>
41 #include <epan/proto.h>
42 #include <epan/expert.h>
43 #include <epan/prefs.h>
44 #include <epan/value_string.h>
45 #include "packet-mq.h"
46 #include "wmem/wmem.h"
47
48 #define PCF_MAX_PARM 999
49 #define PCF_MAX_LIST 20000
50
51 guint mq_pcf_maxprm = PCF_MAX_PARM;
52 guint mq_pcf_maxlst = PCF_MAX_LIST;
53
54 static int proto_mqpcf = -1;
55
56 static int hf_mqpcf_cfh_type = -1;
57 static int hf_mqpcf_cfh_length = -1;
58 static int hf_mqpcf_cfh_version = -1;
59 static int hf_mqpcf_cfh_command = -1;
60 static int hf_mqpcf_cfh_msgseqnumber = -1;
61 static int hf_mqpcf_cfh_control = -1;
62 static int hf_mqpcf_cfh_compcode = -1;
63 static int hf_mqpcf_cfh_reason = -1;
64 static int hf_mqpcf_cfh_paramcount = -1;
65
66 static int hf_mq_pcf_prmtyp = -1;
67 static int hf_mq_pcf_prmlen = -1;
68 static int hf_mq_pcf_prmid = -1;
69 static int hf_mq_pcf_prmccsid = -1;
70 static int hf_mq_pcf_prmstrlen = -1;
71 static int hf_mq_pcf_prmcount = -1;
72 static int hf_mq_pcf_prmunused = -1;
73
74 static int hf_mq_pcf_string = -1;
75 static int hf_mq_pcf_stringlist = -1;
76 static int hf_mq_pcf_int = -1;
77 static int hf_mq_pcf_intlist = -1;
78 static int hf_mq_pcf_bytestring = -1;
79 static int hf_mq_pcf_int64 = -1;
80 static int hf_mq_pcf_int64list = -1;
81
82 static expert_field ei_mq_pcf_prmln0 = EI_INIT;
83 static expert_field ei_mq_pcf_MaxInt = EI_INIT;
84 static expert_field ei_mq_pcf_MaxStr = EI_INIT;
85 static expert_field ei_mq_pcf_MaxI64 = EI_INIT;
86 static expert_field ei_mq_pcf_MaxPrm = EI_INIT;
87
88 static gint ett_mqpcf_prm = -1;
89 static gint ett_mqpcf = -1;
90 static gint ett_mqpcf_cfh = -1;
91
92 #define MQ_TEXT_CFH   "MQ Command Format Header"
93
94 guint8 *dissect_mqpcf_parm_getintval(guint uPrm,guint uVal)
95 {
96         value_string *pVs=NULL;
97         pVs=(value_string *)try_val_to_str(uPrm,GET_VALSV(MQCFINT_Parse));
98
99         if (pVs)
100         {
101                 return (guint8 *)try_val_to_str(uVal,pVs);
102         }
103         return NULL;
104 }
105
106 void dissect_mqpcf_parm_int(tvbuff_t *tvb, proto_tree *tree, guint offset,guint uPrm,guint uVal,int hfindex)
107 {
108         header_field_info *hfinfo;
109         guint8 *pVal;
110
111         pVal=dissect_mqpcf_parm_getintval(uPrm,uVal);
112         hfinfo=proto_registrar_get_nth(hfindex);
113
114         if (pVal)
115         {
116                 proto_tree_add_none_format(tree, hfindex, tvb, offset , 4, "%s:%d-%s",
117                         hfinfo->name, uVal, pVal);
118         }
119         else
120         {
121                 proto_tree_add_none_format(tree, hfindex, tvb, offset , 4, "%s:%8x-%d",
122                         hfinfo->name, uVal, uVal);
123         }
124 }
125
126 static void dissect_mqpcf_parm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mq_tree, guint offset,guint32 uCount,guint bLittleEndian)
127 {
128         guint32 u=0;
129         guint32 tOfs=0;
130         guint32 uLenF;
131         char strPrm[256];
132         guint32 uTyp;
133         guint32 uLen = 0;
134         guint32 uPrm;
135         guint32 uCnt;
136         guint32 uCCS;
137         guint32 uSLn;
138         guint32 uVal;
139         guint64 uVal64;
140
141         const char sMaxLst[] = " Max # of List reached. DECODE interrupted   (actual %u of %u)";
142         const char sPrmLn0[] = " MQPrm[%3u] has a zero length. DECODE Failed (MQPrm Count: %u)";
143         const char sMaxPrm[] = " Max # of Parm reached. DECODE interrupted   (actual %u of %u)";
144
145         proto_item *ti=NULL;
146         proto_tree *tree=NULL;
147
148         for (u=0;u<uCount && u<mq_pcf_maxprm;u++)
149         {
150                 tOfs=offset;
151                 uTyp=tvb_get_guint32_endian(tvb, offset, bLittleEndian);
152                 uLen=tvb_get_guint32_endian(tvb, offset + 4, bLittleEndian);
153                 if (uLen==0)
154                 {
155                         ti = proto_tree_add_text(mq_tree, tvb, offset, 12, sPrmLn0, u+1, uCount);
156                         expert_add_info(pinfo, ti, &ei_mq_pcf_prmln0);
157                         u=uCount;
158                         break;
159                 }
160                 uPrm=tvb_get_guint32_endian(tvb, offset + 8, bLittleEndian);
161                 uLenF=12;
162
163                 g_snprintf(strPrm,(gulong)sizeof(strPrm)-1," %-s[%3u] {%1d-%-15.15s} %8x/%5d-%-30.30s",
164                         "MQPrm",u+1,
165                         uTyp,val_to_str_const(uTyp,GET_VALSV(PrmTyp),"      Unknown")+6,
166                         uPrm,uPrm,val_to_str_const(uPrm,GET_VALSV(PrmId),"Unknown"));
167
168                 switch (uTyp)
169                 {
170                 case MQ_MQCFT_NONE:
171                         break;
172                 case MQ_MQCFT_COMMAND:
173                         break;
174                 case MQ_MQCFT_RESPONSE:
175                         break;
176                 case MQ_MQCFT_INTEGER:
177                         {
178                                 guint8 *pVal;
179                                 uVal=tvb_get_guint32_endian(tvb, offset+uLenF, bLittleEndian);
180                                 pVal=dissect_mqpcf_parm_getintval(uPrm,uVal);
181                                 if (pVal)
182                                 {
183                                         ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %d-%s",
184                                                 strPrm,uVal,pVal);
185                                 }
186                                 else
187                                 {
188                                         ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %8x-%d",
189                                                 strPrm,uVal,uVal);
190                                 }
191                                 tree = proto_item_add_subtree(ti, ett_mqpcf_prm);
192                                 proto_tree_add_item(tree, hf_mq_pcf_prmtyp, tvb, offset, 4, bLittleEndian);
193                                 proto_tree_add_item(tree, hf_mq_pcf_prmlen, tvb, offset + 4, 4, bLittleEndian);
194                                 proto_tree_add_item(tree, hf_mq_pcf_prmid, tvb, offset + 8, 4, bLittleEndian);
195
196                                 dissect_mqpcf_parm_int(tvb, tree, offset+uLenF, uPrm, uVal, hf_mq_pcf_int);
197
198                                 offset+=uLenF+4;
199                         }
200                         break;
201                 case MQ_MQCFT_STRING:
202                         {
203                                 guint8 *sStr;
204
205                                 uCCS=tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian);
206                                 uSLn=tvb_get_guint32_endian(tvb, offset + uLenF + 4, bLittleEndian);
207                                 sStr=tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 8,uSLn,(uCCS!=500)?ENC_ASCII:ENC_EBCDIC);
208                                 strip_trailing_blanks(sStr,uSLn);
209
210                                 ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %s", strPrm, sStr);
211                                 tree = proto_item_add_subtree(ti, ett_mqpcf_prm);
212
213                                 proto_tree_add_item(tree, hf_mq_pcf_prmtyp, tvb, offset, 4, bLittleEndian);
214                                 proto_tree_add_item(tree, hf_mq_pcf_prmlen, tvb, offset + 4, 4, bLittleEndian);
215                                 proto_tree_add_item(tree, hf_mq_pcf_prmid, tvb, offset + 8, 4, bLittleEndian);
216                                 proto_tree_add_item(tree, hf_mq_pcf_prmccsid, tvb, offset + 12, 4, bLittleEndian);
217                                 proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 16, 4, bLittleEndian);
218
219                                 proto_tree_add_item(tree, hf_mq_pcf_string, tvb, offset + uLenF + 8, uSLn, (uCCS!=500)?ENC_ASCII:ENC_EBCDIC);
220
221                                 offset+=uLenF+8+uSLn;
222                         }
223                         break;
224                 case MQ_MQCFT_INTEGER_LIST:
225                         {
226                                 guint32 u2;
227
228                                 uCnt=tvb_get_guint32_endian(tvb, offset+uLenF, bLittleEndian);
229                                 ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s Cnt(%d)",strPrm,uCnt);
230                                 tree = proto_item_add_subtree(ti, ett_mqpcf_prm);
231
232                                 proto_tree_add_item(tree, hf_mq_pcf_prmtyp, tvb, offset, 4, bLittleEndian);
233                                 proto_tree_add_item(tree, hf_mq_pcf_prmlen, tvb, offset + 4, 4, bLittleEndian);
234                                 proto_tree_add_item(tree, hf_mq_pcf_prmid, tvb, offset + 8, 4, bLittleEndian);
235                                 proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian);
236
237                                 offset+=uLenF+4;
238                                 for (u2=0;u2<uCnt && u2<mq_pcf_maxlst;u2++)
239                                 {
240                                         uVal=tvb_get_guint32_endian(tvb, offset, bLittleEndian);
241                                         dissect_mqpcf_parm_int(tvb, tree, offset, uPrm, uVal, hf_mq_pcf_intlist);
242                                         offset+=4;
243                                 }
244                                 if (u2!=uCnt)
245                                 {
246                                         ti = proto_tree_add_text(tree, tvb, offset, uLen, sMaxLst, u2, uCnt);
247                                         expert_add_info(pinfo, ti, &ei_mq_pcf_MaxInt);
248                                 }
249                         }
250                         break;
251                 case MQ_MQCFT_STRING_LIST:
252                         {
253                                 guint32 u2;
254
255                                 uCCS=tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian);
256                                 uCnt=tvb_get_guint32_endian(tvb, offset + uLenF + 4, bLittleEndian);
257                                 uSLn=tvb_get_guint32_endian(tvb, offset + uLenF + 8, bLittleEndian);
258
259                                 ti = proto_tree_add_text(mq_tree, tvb, offset, uLen,"%s Cnt(%d)",strPrm,uCnt);
260
261                                 tree = proto_item_add_subtree(ti, ett_mqpcf_prm);
262                                 proto_tree_add_item(tree, hf_mq_pcf_prmtyp, tvb, offset, 4, bLittleEndian);
263                                 proto_tree_add_item(tree, hf_mq_pcf_prmlen, tvb, offset + 4, 4, bLittleEndian);
264                                 proto_tree_add_item(tree, hf_mq_pcf_prmid, tvb, offset + 8, 4, bLittleEndian);
265                                 proto_tree_add_item(tree, hf_mq_pcf_prmccsid, tvb, offset + 12, 4, bLittleEndian);
266                                 proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 16, 4, bLittleEndian);
267                                 proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 20, 4, bLittleEndian);
268
269                                 offset+=uLenF+12;
270                                 for (u2=0;u2<uCnt && u2<mq_pcf_maxlst;u2++)
271                                 {
272                                         proto_tree_add_item(tree, hf_mq_pcf_stringlist, tvb, offset , uSLn, (uCCS!=500)?ENC_ASCII:ENC_EBCDIC);
273                                         offset+=uSLn;
274                                 }
275                                 if (u2!=uCnt)
276                                 {
277                                         ti = proto_tree_add_text(tree, tvb, offset, uLen, sMaxLst, u2, uCnt);
278                                         expert_add_info(pinfo, ti, &ei_mq_pcf_MaxStr);
279                                 }
280                         }
281                         break;
282                 case MQ_MQCFT_EVENT:
283                         break;
284                 case MQ_MQCFT_USER:
285                         break;
286                 case MQ_MQCFT_BYTE_STRING:
287                         {
288                                 uSLn=tvb_get_guint32_endian(tvb, offset + uLenF, bLittleEndian);
289                                 if (uSLn)
290                                 {
291                                         guint8 *sStrA=tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4,uSLn,ENC_ASCII);
292                                         guint8 *sStrE=tvb_get_string_enc(wmem_packet_scope(), tvb, offset + uLenF + 4,uSLn,ENC_EBCDIC);
293                                         ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s A(%s) E(%s)", strPrm, sStrA,sStrE);
294                                 }
295                                 else
296                                 {
297                                         ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s <MISSING>", strPrm);
298                                 }
299                                 tree = proto_item_add_subtree(ti, ett_mqpcf_prm);
300
301                                 proto_tree_add_item(tree, hf_mq_pcf_prmtyp, tvb, offset, 4, bLittleEndian);
302                                 proto_tree_add_item(tree, hf_mq_pcf_prmlen, tvb, offset + 4, 4, bLittleEndian);
303                                 proto_tree_add_item(tree, hf_mq_pcf_prmid, tvb, offset + 8, 4, bLittleEndian);
304                                 proto_tree_add_item(tree, hf_mq_pcf_prmstrlen, tvb, offset + 12, 4, bLittleEndian);
305
306                                 proto_tree_add_item(tree, hf_mq_pcf_bytestring, tvb, offset + uLenF + 4 , uSLn,bLittleEndian);
307
308                                 offset+=uLenF+4+uSLn;
309                         }
310                         break;
311                 case MQ_MQCFT_TRACE_ROUTE:
312                         break;
313                 case MQ_MQCFT_REPORT:
314                         break;
315                 case MQ_MQCFT_INTEGER_FILTER:
316                         break;
317                 case MQ_MQCFT_STRING_FILTER:
318                         break;
319                 case MQ_MQCFT_BYTE_STRING_FILTER:
320                         break;
321                 case MQ_MQCFT_COMMAND_XR:
322                         break;
323                 case MQ_MQCFT_XR_MSG:
324                         break;
325                 case MQ_MQCFT_XR_ITEM:
326                         break;
327                 case MQ_MQCFT_XR_SUMMARY:
328                         break;
329                 case MQ_MQCFT_GROUP:
330                         break;
331                 case MQ_MQCFT_STATISTICS:
332                         break;
333                 case MQ_MQCFT_ACCOUNTING:
334                         break;
335                 case MQ_MQCFT_INTEGER64:
336                         {
337                                 uVal64=tvb_get_guint64_endian(tvb, offset+4, bLittleEndian);
338                                 ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s %" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)",
339                                         strPrm, uVal64, uVal64);
340                                 tree = proto_item_add_subtree(ti, ett_mqpcf_prm);
341
342                                 proto_tree_add_item(tree, hf_mq_pcf_prmtyp, tvb, offset, 4, bLittleEndian);
343                                 proto_tree_add_item(tree, hf_mq_pcf_prmlen, tvb, offset + 4, 4, bLittleEndian);
344                                 proto_tree_add_item(tree, hf_mq_pcf_prmid, tvb, offset + 8, 4, bLittleEndian);
345                                 proto_tree_add_item(tree, hf_mq_pcf_prmunused, tvb, offset + 12, 4, bLittleEndian);
346
347                                 proto_tree_add_item(tree, hf_mq_pcf_int64, tvb, offset + uLenF + 4, 8, bLittleEndian);
348
349                                 offset+=uLenF+4+8;
350                         }
351                         break;
352                 case MQ_MQCFT_INTEGER64_LIST:
353                         {
354                                 guint32 u2;
355                                 uCnt=tvb_get_guint32_endian(tvb, offset, bLittleEndian);
356                                 ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, "%s Cnt(%d)",strPrm,uCnt);
357                                 tree = proto_item_add_subtree(ti, ett_mqpcf_prm);
358
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, hf_mq_pcf_prmid, tvb, offset + 8, 4, bLittleEndian);
362                                 proto_tree_add_item(tree, hf_mq_pcf_prmcount, tvb, offset + 12, 4, bLittleEndian);
363
364                                 offset+=uLenF+4;
365                                 for (u2=0;u2<uCnt && u2<mq_pcf_maxlst;u2++)
366                                 {
367                                         proto_tree_add_item(tree, hf_mq_pcf_int64list, tvb, offset, 8, bLittleEndian);
368                                         offset+=8;
369                                 }
370                                 if (u2!=uCnt)
371                                 {
372                                         ti = proto_tree_add_text(tree, tvb, offset, uLen, sMaxLst, u2, uCnt);
373                                         expert_add_info(pinfo, ti, &ei_mq_pcf_MaxI64);
374                                 }
375                         }
376                         break;
377                 }
378                 offset=tOfs+uLen;
379         }
380         if (u!=uCount)
381         {
382                 ti = proto_tree_add_text(mq_tree, tvb, offset, uLen, sMaxPrm, u, uCount);
383                 expert_add_info(pinfo, ti, &ei_mq_pcf_MaxPrm);
384         }
385 }
386 static void dissect_mqpcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
387 {
388         gint offset = 0;
389         struct mqinfo* mqinfo = (struct mqinfo *)pinfo->private_data;
390         gboolean bLittleEndian;
391
392         bLittleEndian = ((mqinfo->encoding & MQ_MQENC_INTEGER_MASK)==MQ_MQENC_INTEGER_REVERSED)?ENC_LITTLE_ENDIAN:ENC_BIG_ENDIAN;
393
394         if (tvb_length(tvb) >= 36)
395         {
396                 gint iSizeMQCFH = 36;
397                 guint32 iCommand = tvb_get_guint32_endian(tvb, offset + 12, bLittleEndian);
398
399                 if (tree)
400                 {
401                         proto_item      *ti = NULL;
402                         proto_tree      *mq_tree = NULL;
403                         proto_tree      *mqroot_tree = NULL;
404                         guint32 uCount;
405
406                         ti = proto_tree_add_item(tree, proto_mqpcf, tvb, offset, -1, ENC_NA);
407                         proto_item_append_text(ti, " (%s)", val_to_str(iCommand, mq_mqcmd_vals, "Unknown (0x%02x)"));
408                         mqroot_tree = proto_item_add_subtree(ti, ett_mqpcf);
409
410                         ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeMQCFH, MQ_TEXT_CFH);
411                         mq_tree = proto_item_add_subtree(ti, ett_mqpcf_cfh);
412
413                         uCount=tvb_get_guint32_endian(tvb, offset+32, bLittleEndian);     /* Count of parameter structures */
414
415                         proto_tree_add_item(mq_tree, hf_mqpcf_cfh_type, tvb, offset + 0, 4, bLittleEndian);
416                         proto_tree_add_item(mq_tree, hf_mqpcf_cfh_length, tvb, offset + 4, 4, bLittleEndian);
417                         proto_tree_add_item(mq_tree, hf_mqpcf_cfh_version, tvb, offset + 8, 4, bLittleEndian);
418                         proto_tree_add_item(mq_tree, hf_mqpcf_cfh_command, tvb, offset + 12, 4, bLittleEndian);
419                         proto_tree_add_item(mq_tree, hf_mqpcf_cfh_msgseqnumber, tvb, offset + 16, 4, bLittleEndian);
420                         proto_tree_add_item(mq_tree, hf_mqpcf_cfh_control, tvb, offset + 20, 4, bLittleEndian);
421                         proto_tree_add_item(mq_tree, hf_mqpcf_cfh_compcode, tvb, offset + 24, 4, bLittleEndian);
422                         proto_tree_add_item(mq_tree, hf_mqpcf_cfh_reason, tvb, offset + 28, 4, bLittleEndian);
423                         proto_tree_add_item(mq_tree, hf_mqpcf_cfh_paramcount, tvb, offset + 32, 4, bLittleEndian);
424                         dissect_mqpcf_parm(tvb, pinfo, mqroot_tree, offset + iSizeMQCFH, uCount, bLittleEndian);
425                 }
426         }
427 }
428
429 static gboolean dissect_mqpcf_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
430 {
431         if (tvb_length(tvb) >= 36)
432         {
433                 struct mqinfo* mqinfo = (struct mqinfo *)pinfo->private_data;
434                 if (strncmp((const char*)mqinfo->format, MQ_MQFMT_ADMIN, 8) == 0
435                         || strncmp((const char*)mqinfo->format, MQ_MQFMT_EVENT, 8) == 0
436                         || strncmp((const char*)mqinfo->format, MQ_MQFMT_PCF, 8) == 0)
437                 {
438                         /* Dissect the packet */
439                         dissect_mqpcf(tvb, pinfo, tree);
440                         return TRUE;
441                 }
442         }
443         return FALSE;
444 }
445
446 void proto_register_mqpcf(void)
447 {
448         expert_module_t* expert_mqpcf;
449
450         static hf_register_info hf[] = {
451                 { &hf_mqpcf_cfh_type    , { "Type....", "mqpcf.cfh.type", FT_UINT32, BASE_DEC, VALS(&GET_VALSV(mqcft)), 0x0, "CFH type", HFILL }},
452                 { &hf_mqpcf_cfh_length  , { "Length..", "mqpcf.cfh.length", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH length", HFILL }},
453                 { &hf_mqpcf_cfh_version , { "Version.", "mqpcf.cfh.version", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH version", HFILL }},
454                 { &hf_mqpcf_cfh_command , { "Command.", "mqpcf.cfh.command", FT_UINT32, BASE_DEC, VALS(&GET_VALSV(mqcmd)), 0x0, "CFH command", HFILL }},
455                 { &hf_mqpcf_cfh_msgseqnumber, { "MsgSeqNr", "mqpcf.cfh.msgseqnumber", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH message sequence number", HFILL }},
456                 { &hf_mqpcf_cfh_control , { "Control.", "mqpcf.cfh.control", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH control", HFILL }},
457                 { &hf_mqpcf_cfh_compcode, { "CompCode", "mqpcf.cfh.compcode", FT_UINT32, BASE_DEC, VALS(&GET_VALSV(mqcc)), 0x0, "CFH completion code", HFILL }},
458                 { &hf_mqpcf_cfh_reason  , { "ReasCode", "mqpcf.cfh.reasoncode", FT_UINT32, BASE_DEC, VALS(&GET_VALSV(mqrc)), 0x0, "CFH reason code", HFILL }},
459                 { &hf_mqpcf_cfh_paramcount, { "ParmCnt.", "mqpcf.cfh.paramcount", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH parameter count", HFILL }},
460                 { &hf_mq_pcf_prmtyp     , { "PrmTyp..", "mqpcf.parm.type", FT_UINT32, BASE_DEC, VALS(&GET_VALSV(PrmTyp)), 0x0, "MQPCF parameter type", HFILL }},
461                 { &hf_mq_pcf_prmlen     , { "PrmLen..", "mqpcf.parm.len", FT_UINT32, BASE_DEC, NULL, 0x0, "MQPCF parameter length", HFILL }},
462                 { &hf_mq_pcf_prmid      , { "PrmID...", "mqpcf.parm.id", FT_UINT32, BASE_DEC, VALS(&GET_VALSV(PrmId)), 0x0, "MQPCF parameter id", HFILL }},
463                 { &hf_mq_pcf_prmccsid   , { "PrmCCSID", "mqpcf.parm.ccsid", FT_UINT32, BASE_DEC, NULL, 0x0, "MQPCF parameter ccsid", HFILL }},
464                 { &hf_mq_pcf_prmstrlen  , { "PrmStrLn", "mqpcf.parm.strlen", FT_UINT32, BASE_DEC, NULL, 0x0, "MQPCF parameter strlen", HFILL }},
465                 { &hf_mq_pcf_prmcount   , { "PrmCount", "mqpcf.parm.count", FT_UINT32, BASE_DEC, NULL, 0x0, "MQPCF parameter count", HFILL }},
466                 { &hf_mq_pcf_prmunused  , { "PrmUnuse", "mqpcf.parm.unused", FT_UINT32, BASE_DEC, NULL, 0x0, "MQPCF parameter unused", HFILL }},
467                 { &hf_mq_pcf_string     , { "String..", "mqpcf.parm.string", FT_STRINGZ, BASE_NONE, NULL, 0x0, "MQPCF parameter string", HFILL }},
468                 { &hf_mq_pcf_stringlist , { "StrList..", "mqpcf.parm.stringlist", FT_STRINGZ, BASE_NONE, NULL, 0x0, "MQPCF parameter string list", HFILL }},
469                 { &hf_mq_pcf_int        , { "Integer.", "mqpcf.parm.int", FT_NONE, BASE_NONE, NULL, 0x0, "MQPCF parameter int", HFILL }},
470                 { &hf_mq_pcf_intlist    , { "IntList.", "mqpcf.parm.intlist", FT_NONE, BASE_NONE, NULL, 0x0, "MQPCF parameter int list", HFILL }},
471                 { &hf_mq_pcf_bytestring , { "ByteStr..", "mqpcf.parm.bytestring", FT_BYTES, BASE_NONE, NULL, 0x0, "MQPCF parameter byte string", HFILL }},
472                 { &hf_mq_pcf_int64      , { "Int64...", "mqpcf.parm.int64", FT_UINT64, BASE_HEX | BASE_DEC, NULL, 0x0, "MQPCF parameter int64", HFILL }},
473                 { &hf_mq_pcf_int64list  , { "Int64Lst", "mqpcf.parm.int64list", FT_UINT64, BASE_HEX | BASE_DEC, NULL, 0x0, "MQPCF parameter int64 list", HFILL }},
474         };
475         static gint *ett[] = {
476                 &ett_mqpcf,
477                 &ett_mqpcf_prm,
478                 &ett_mqpcf_cfh,
479         };
480         static ei_register_info ei[] = 
481         {
482         { &ei_mq_pcf_prmln0, { "mqpcf.parm.len0", PI_MALFORMED, PI_ERROR, "MQPCF Parameter length is 0", EXPFILL }},
483                 { &ei_mq_pcf_MaxInt, { "mqpcf.parm.IntList", PI_UNDECODED, PI_WARN, "MQPCF Parameter Integer list exhausted", EXPFILL }},
484                 { &ei_mq_pcf_MaxStr, { "mqpcf.parm.StrList", PI_UNDECODED, PI_WARN, "MQPCF Parameter String list exhausted", EXPFILL }},
485                 { &ei_mq_pcf_MaxI64, { "mqpcf.parm.Int64List", PI_UNDECODED, PI_WARN, "MQPCF Parameter Int64 list exhausted", EXPFILL }},
486                 { &ei_mq_pcf_MaxPrm, { "mqpcf.parm.MaxPrm", PI_UNDECODED, PI_WARN, "MQPCF Max number of parameter exhausted", EXPFILL }},
487     };
488
489         module_t *mq_pcf_module;
490
491         proto_mqpcf = proto_register_protocol("WebSphere MQ Programmable Command Formats", "MQ PCF", "mqpcf");
492         proto_register_field_array(proto_mqpcf, hf, array_length(hf));
493         proto_register_subtree_array(ett, array_length(ett));
494
495         expert_mqpcf = expert_register_protocol(proto_mqpcf);
496     expert_register_field_array(expert_mqpcf, ei, array_length(ei));
497
498         mq_pcf_module = prefs_register_protocol(proto_mqpcf, NULL);
499         prefs_register_uint_preference(mq_pcf_module,"maxprm",
500                 "Set the maximun number of parameter in the PCF to decode",
501                 "When dissecting PCF there can be a lot of parameters."
502                 " You can limit the number of parameter decoded, before it continue with the next PCF.",
503                 10, &mq_pcf_maxprm);
504         prefs_register_uint_preference(mq_pcf_module,"maxlst",
505                 "Set the maximun number of Parameter List that are displayed",
506                 "When dissecting a parameter of a PCFm, if it is a StringList, IntegerList or Integer64 List, "
507                 " You can limit the number of element displayed, before it continue with the next Parameter.",
508                 10, &mq_pcf_maxlst);
509
510 }
511
512 void proto_reg_handoff_mqpcf(void)
513 {
514         heur_dissector_add("mq", dissect_mqpcf_heur, proto_mqpcf);
515 }
516
517 /*
518  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
519  *
520  * Local variables:
521  * c-basic-offset: 4
522  * tab-width: 4
523  * indent-tabs-mode: t
524  * End:
525  *
526  * vi: set shiftwidth=4 tabstop=4 noexpandtab:
527  * :indentSize=4:tabSize=4:noTabs=false:
528  */