Update Free Software Foundation address.
[metze/wireshark/wip.git] / epan / dissectors / packet-drda.c
1 /* packet-drda.c
2  * Routines for Distributed Relational Database Architecture packet dissection
3  *
4  * metatech <metatech@flashmail.com>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26
27 /*  DRDA in a nutshell
28 *
29 *   DRDA stands for Distributed Relational Database Architecture.
30 *   It is a protocol between database client and database server published by
31 *   the Open Group (www.opengroup.org) DDM (Distributed Data Management) is an
32 *   data management interface which allows to exchange structured data between
33 *   systems.  DRDA is specific to relational databases and uses a subset of DDM
34 *   to transport its data.  The IBM DB2 product uses the DRDA protocol from
35 *   version V8.  Unless negotiated differently during the handshake, the fields
36 *   of the DDM commands and reply messages are in EBCDIC.
37 *
38 *   Documentation:
39 *   DRDA Version 3 Vol. 3: Distributed Relational Database Architecture,
40 *   Open Group.
41 *   Version 3 is no longer available; for the latest version, see
42 *
43 *       http://www.opengroup.org/dbiop/
44 *
45 *   Reference for Remote DRDA Requesters and Servers, IBM.
46 *
47 *       https://www-304.ibm.com/support/docview.wss?uid=pub1sc18985301
48 */
49
50 #ifdef HAVE_CONFIG_H
51 # include "config.h"
52 #endif
53
54 #include <glib.h>
55 #include <epan/packet.h>
56 #include <epan/conversation.h>
57 #include <epan/prefs.h>
58 #include "packet-tcp.h"
59
60 static int proto_drda = -1;
61 static int hf_drda_ddm_length = -1;
62 static int hf_drda_ddm_magic = -1;
63 static int hf_drda_ddm_format = -1;
64 static int hf_drda_ddm_fmt_reserved = -1;
65 static int hf_drda_ddm_fmt_chained = -1;
66 static int hf_drda_ddm_fmt_errcont = -1;
67 static int hf_drda_ddm_fmt_samecorr = -1;
68 static int hf_drda_ddm_fmt_dsstyp = -1;
69 static int hf_drda_ddm_rc = -1;
70 static int hf_drda_ddm_length2 = -1;
71 static int hf_drda_ddm_codepoint = -1;
72 static int hf_drda_param_length = -1;
73 static int hf_drda_param_codepoint = -1;
74 static int hf_drda_param_data = -1;
75 static int hf_drda_param_data_ebcdic = -1;
76 static int hf_drda_sqlstatement = -1;
77 static int hf_drda_sqlstatement_ebcdic = -1;
78
79 static gint ett_drda = -1;
80 static gint ett_drda_ddm = -1;
81 static gint ett_drda_ddm_format = -1;
82 static gint ett_drda_param = -1;
83
84 static dissector_handle_t drda_tcp_handle;
85
86 static gboolean drda_desegment = TRUE;
87
88 #define DRDA_MAGIC  0xD0
89
90 #define DRDA_CP_DATA          0x0000
91 #define DRDA_CP_CODPNT        0x000C
92 #define DRDA_CP_FDODSC        0x0010
93 #define DRDA_CP_TYPDEFNAM     0x002F
94 #define DRDA_CP_TYPDEFOVR     0x0035
95 #define DRDA_CP_CODPNTDR      0x0064
96 #define DRDA_CP_EXCSAT        0x1041
97 #define DRDA_CP_SYNCCTL       0x1055
98 #define DRDA_CP_SYNCRSY       0x1069
99 #define DRDA_CP_ACCSEC        0x106D
100 #define DRDA_CP_SECCHK        0x106E
101 #define DRDA_CP_SYNCLOG       0x106F
102 #define DRDA_CP_RSCTYP        0x111F
103 #define DRDA_CP_RSNCOD        0x1127
104 #define DRDA_CP_RSCNAM        0x112D
105 #define DRDA_CP_PRDID         0x112E
106 #define DRDA_CP_PRCCNVCD      0x113F
107 #define DRDA_CP_VRSNAM        0x1144
108 #define DRDA_CP_SRVCLSNM      0x1147
109 #define DRDA_CP_SVRCOD        0x1149
110 #define DRDA_CP_SYNERRCD      0x114A
111 #define DRDA_CP_SRVDGN        0x1153
112 #define DRDA_CP_SRVRLSLV      0x115A
113 #define DRDA_CP_SPVNAM        0x115D
114 #define DRDA_CP_EXTNAM        0x115E
115 #define DRDA_CP_SRVNAM        0x116D
116 #define DRDA_CP_SECMGRNM      0x1196
117 #define DRDA_CP_DEPERRCD      0x119B
118 #define DRDA_CP_CCSIDSBC      0x119C
119 #define DRDA_CP_CCSIDDBC      0x119D
120 #define DRDA_CP_CCSIDMBC      0x119E
121 #define DRDA_CP_USRID         0x11A0
122 #define DRDA_CP_PASSWORD      0x11A1
123 #define DRDA_CP_SECMEC        0x11A2
124 #define DRDA_CP_SECCHKCD      0x11A4
125 #define DRDA_CP_SVCERRNO      0x11B4
126 #define DRDA_CP_SECTKN        0x11DC
127 #define DRDA_CP_NEWPASSWORD   0x11DE
128 #define DRDA_CP_MGRLVLRM      0x1210
129 #define DRDA_CP_MGRDEPRM      0x1218
130 #define DRDA_CP_SECCHKRM      0x1219
131 #define DRDA_CP_CMDATHRM      0x121C
132 #define DRDA_CP_AGNPRMRM      0x1232
133 #define DRDA_CP_RSCLMTRM      0x1233
134 #define DRDA_CP_PRCCNVRM      0x1245
135 #define DRDA_CP_CMDCMPRM      0x124B
136 #define DRDA_CP_SYNTAXRM      0x124C
137 #define DRDA_CP_CMDNSPRM      0x1250
138 #define DRDA_CP_PRMNSPRM      0x1251
139 #define DRDA_CP_VALNSPRM      0x1252
140 #define DRDA_CP_OBJNSPRM      0x1253
141 #define DRDA_CP_CMDCHKRM      0x1254
142 #define DRDA_CP_TRGNSPRM      0x125F
143 #define DRDA_CP_AGENT         0x1403
144 #define DRDA_CP_MGRLVLLS      0x1404
145 #define DRDA_CP_SUPERVISOR    0x143C
146 #define DRDA_CP_SECMGR        0x1440
147 #define DRDA_CP_EXCSATRD      0x1443
148 #define DRDA_CP_CMNAPPC       0x1444
149 #define DRDA_CP_DICTIONARY    0x1458
150 #define DRDA_CP_MGRLVLN       0x1473
151 #define DRDA_CP_CMNTCPIP      0x1474
152 #define DRDA_CP_FDODTA        0x147A
153 #define DRDA_CP_CMNSYNCPT     0x147C
154 #define DRDA_CP_ACCSECRD      0x14AC
155 #define DRDA_CP_SYNCPTMGR     0x14C0
156 #define DRDA_CP_RSYNCMGR      0x14C1
157 #define DRDA_CP_CCSIDMGR      0x14CC
158 #define DRDA_CP_MONITOR       0x1900
159 #define DRDA_CP_MONITORRD     0x1C00
160 #define DRDA_CP_XAMGR         0x1C01
161 #define DRDA_CP_ACCRDB        0x2001
162 #define DRDA_CP_BGNBND        0x2002
163 #define DRDA_CP_BNDSQLSTT     0x2004
164 #define DRDA_CP_CLSQRY        0x2005
165 #define DRDA_CP_CNTQRY        0x2006
166 #define DRDA_CP_DRPPKG        0x2007
167 #define DRDA_CP_DSCSQLSTT     0x2008
168 #define DRDA_CP_ENDBND        0x2009
169 #define DRDA_CP_EXCSQLIMM     0x200A
170 #define DRDA_CP_EXCSQLSTT     0x200B
171 #define DRDA_CP_OPNQRY        0x200C
172 #define DRDA_CP_PRPSQLSTT     0x200D
173 #define DRDA_CP_RDBCMM        0x200E
174 #define DRDA_CP_RDBRLLBCK     0x200F
175 #define DRDA_CP_REBIND        0x2010
176 #define DRDA_CP_DSCRDBTBL     0x2012
177 #define DRDA_CP_EXCSQLSET     0x2014
178 #define DRDA_CP_DSCERRCD      0x2101
179 #define DRDA_CP_QRYPRCTYP     0x2102
180 #define DRDA_CP_RDBINTTKN     0x2103
181 #define DRDA_CP_PRDDTA        0x2104
182 #define DRDA_CP_RDBCMTOK      0x2105
183 #define DRDA_CP_RDBCOLID      0x2108
184 #define DRDA_CP_PKGID         0x2109
185 #define DRDA_CP_PKGCNSTKN     0x210D
186 #define DRDA_CP_RTNSETSTT     0x210E
187 #define DRDA_CP_RDBACCCL      0x210F
188 #define DRDA_CP_RDBNAM        0x2110
189 #define DRDA_CP_OUTEXP        0x2111
190 #define DRDA_CP_PKGNAMCT      0x2112
191 #define DRDA_CP_PKGNAMCSN     0x2113
192 #define DRDA_CP_QRYBLKSZ      0x2114
193 #define DRDA_CP_UOWDSP        0x2115
194 #define DRDA_CP_RTNSQLDA      0x2116
195 #define DRDA_CP_RDBALWUPD     0x211A
196 #define DRDA_CP_SQLCSRHLD     0x211F
197 #define DRDA_CP_STTSTRDEL     0x2120
198 #define DRDA_CP_STTDECDEL     0x2121
199 #define DRDA_CP_PKGDFTCST     0x2125
200 #define DRDA_CP_QRYBLKCTL     0x2132
201 #define DRDA_CP_CRRTKN        0x2135
202 #define DRDA_CP_PRCNAM        0x2138
203 #define DRDA_CP_PKGSNLST      0x2139
204 #define DRDA_CP_NBRROW        0x213A
205 #define DRDA_CP_TRGDFTRT      0x213B
206 #define DRDA_CP_QRYRELSCR     0x213C
207 #define DRDA_CP_QRYROWNBR     0x213D
208 #define DRDA_CP_QRYRFRTBL     0x213E
209 #define DRDA_CP_MAXRSLCNT     0x2140
210 #define DRDA_CP_MAXBLKEXT     0x2141
211 #define DRDA_CP_RSLSETFLG     0x2142
212 #define DRDA_CP_TYPSQLDA      0x2146
213 #define DRDA_CP_OUTOVROPT     0x2147
214 #define DRDA_CP_RTNEXTDTA     0x2148
215 #define DRDA_CP_QRYATTSCR     0x2149
216 #define DRDA_CP_QRYATTUPD     0x2150
217 #define DRDA_CP_QRYSCRORN     0x2152
218 #define DRDA_CP_QRYROWSNS     0x2153
219 #define DRDA_CP_QRYBLKRST     0x2154
220 #define DRDA_CP_QRYRTNDTA     0x2155
221 #define DRDA_CP_QRYROWSET     0x2156
222 #define DRDA_CP_QRYATTSNS     0x2157
223 #define DRDA_CP_QRYINSID      0x215B
224 #define DRDA_CP_QRYCLSIMP     0x215D
225 #define DRDA_CP_QRYCLSRLS     0x215E
226 #define DRDA_CP_QRYOPTVAL     0x215F
227 #define DRDA_CP_DIAGLVL       0x2160
228 #define DRDA_CP_ACCRDBRM      0x2201
229 #define DRDA_CP_QRYNOPRM      0x2202
230 #define DRDA_CP_RDBNACRM      0x2204
231 #define DRDA_CP_OPNQRYRM      0x2205
232 #define DRDA_CP_PKGBNARM      0x2206
233 #define DRDA_CP_RDBACCRM      0x2207
234 #define DRDA_CP_BGNBNDRM      0x2208
235 #define DRDA_CP_PKGBPARM      0x2209
236 #define DRDA_CP_DSCINVRM      0x220A
237 #define DRDA_CP_ENDQRYRM      0x220B
238 #define DRDA_CP_ENDUOWRM      0x220C
239 #define DRDA_CP_ABNUOWRM      0x220D
240 #define DRDA_CP_DTAMCHRM      0x220E
241 #define DRDA_CP_QRYPOPRM      0x220F
242 #define DRDA_CP_RDBNFNRM      0x2211
243 #define DRDA_CP_OPNQFLRM      0x2212
244 #define DRDA_CP_SQLERRRM      0x2213
245 #define DRDA_CP_RDBUPDRM      0x2218
246 #define DRDA_CP_RSLSETRM      0x2219
247 #define DRDA_CP_RDBAFLRM      0x221A
248 #define DRDA_CP_CMDVLTRM      0x221D
249 #define DRDA_CP_CMMRQSRM      0x2225
250 #define DRDA_CP_RDBATHRM      0x22CB
251 #define DRDA_CP_SQLAM         0x2407
252 #define DRDA_CP_SQLCARD       0x2408
253 #define DRDA_CP_SQLCINRD      0x240B
254 #define DRDA_CP_SQLRSLRD      0x240E
255 #define DRDA_CP_RDB           0x240F
256 #define DRDA_CP_FRCFIXROW     0x2410
257 #define DRDA_CP_SQLDARD       0x2411
258 #define DRDA_CP_SQLDTA        0x2412
259 #define DRDA_CP_SQLDTARD      0x2413
260 #define DRDA_CP_SQLSTT        0x2414
261 #define DRDA_CP_OUTOVR        0x2415
262 #define DRDA_CP_LMTBLKPRC     0x2417
263 #define DRDA_CP_FIXROWPRC     0x2418
264 #define DRDA_CP_SQLSTTVRB     0x2419
265 #define DRDA_CP_QRYDSC        0x241A
266 #define DRDA_CP_QRYDTA        0x241B
267 #define DRDA_CP_CSTMBCS       0x2435
268 #define DRDA_CP_SRVLST        0x244E
269 #define DRDA_CP_SQLATTR       0x2450
270
271 #define DRDA_DSSFMT_SAME_CORR 0x01
272 #define DRDA_DSSFMT_CONTINUE  0x02
273 #define DRDA_DSSFMT_CHAINED   0x04
274 #define DRDA_DSSFMT_RESERVED  0x08
275
276 #define DRDA_DSSFMT_RQSDSS    0x01
277 #define DRDA_DSSFMT_RPYDSS    0x02
278 #define DRDA_DSSFMT_OBJDSS    0x03
279 #define DRDA_DSSFMT_CMNDSS    0x04
280 #define DRDA_DSSFMT_NORPYDSS  0x05
281
282 #define DRDA_TEXT_DDM   "DDM"
283 #define DRDA_TEXT_PARAM "Parameter"
284
285 static const value_string drda_opcode_vals[] = {
286     { DRDA_CP_DATA,         "Data" },
287     { DRDA_CP_CODPNT,       "Code Point" },
288     { DRDA_CP_FDODSC,       "FD:OCA Data Descriptor" },
289     { DRDA_CP_TYPDEFNAM,    "Data Type Definition Name" },
290     { DRDA_CP_TYPDEFOVR,    "TYPDEF Overrides" },
291     { DRDA_CP_CODPNTDR,     "Code Point Data Representation" },
292     { DRDA_CP_EXCSAT,       "Exchange Server Attributes" },
293     { DRDA_CP_SYNCCTL,      "Sync Point Control Request" },
294     { DRDA_CP_SYNCRSY,      "Sync Point Resync Command" },
295     { DRDA_CP_ACCSEC,       "Access Security" },
296     { DRDA_CP_SECCHK,       "Security Check" },
297     { DRDA_CP_SYNCLOG,      "Sync Point Log" },
298     { DRDA_CP_RSCTYP,       "Resource Type Information" },
299     { DRDA_CP_RSNCOD,       "Reason Code Information" },
300     { DRDA_CP_RSCNAM,       "Resource Name Information" },
301     { DRDA_CP_PRDID,        "Product-Specific Identifier" },
302     { DRDA_CP_PRCCNVCD,     "Conversation Protocol Error Code" },
303     { DRDA_CP_VRSNAM,       "Version Name" },
304     { DRDA_CP_SRVCLSNM,     "Server Class Name" },
305     { DRDA_CP_SVRCOD,       "Severity Code" },
306     { DRDA_CP_SYNERRCD,     "Syntax Error Code" },
307     { DRDA_CP_SRVDGN,       "Server Diagnostic Information" },
308     { DRDA_CP_SRVRLSLV,     "Server Product Release Level" },
309     { DRDA_CP_SPVNAM,       "Supervisor Name" },
310     { DRDA_CP_EXTNAM,       "External Name" },
311     { DRDA_CP_SRVNAM,       "Server Name" },
312     { DRDA_CP_SECMGRNM,     "Security Manager Name" },
313     { DRDA_CP_DEPERRCD,     "Manager Dependency Error Code" },
314     { DRDA_CP_CCSIDSBC,     "CCSID for Single-Byte Characters" },
315     { DRDA_CP_CCSIDDBC,     "CCSID for Double-byte Characters" },
316     { DRDA_CP_CCSIDMBC,     "CCSID for Mixed-byte Characters" },
317     { DRDA_CP_USRID,        "User ID at the Target System" },
318     { DRDA_CP_PASSWORD,     "Password" },
319     { DRDA_CP_SECMEC,       "Security Mechanism" },
320     { DRDA_CP_SECCHKCD,     "Security Check Code" },
321     { DRDA_CP_SVCERRNO,     "Security Service ErrorNumber" },
322     { DRDA_CP_SECTKN,       "Security Token" },
323     { DRDA_CP_NEWPASSWORD,  "New Password" },
324     { DRDA_CP_MGRLVLRM,     "Manager-Level Conflict" },
325     { DRDA_CP_MGRDEPRM,     "Manager Dependency Error" },
326     { DRDA_CP_SECCHKRM,     "Security Check" },
327     { DRDA_CP_CMDATHRM,     "Not Authorized to Command" },
328     { DRDA_CP_AGNPRMRM,     "Permanent Agent Error" },
329     { DRDA_CP_RSCLMTRM,     "Resource Limits Reached" },
330     { DRDA_CP_PRCCNVRM,     "Conversational Protocol Error" },
331     { DRDA_CP_CMDCMPRM,     "Command Processing Completed" },
332     { DRDA_CP_SYNTAXRM,     "Data Stream Syntax Error" },
333     { DRDA_CP_CMDNSPRM,     "Command Not Supported" },
334     { DRDA_CP_PRMNSPRM,     "Parameter Not Supported" },
335     { DRDA_CP_VALNSPRM,     "Parameter Value Not Supported" },
336     { DRDA_CP_OBJNSPRM,     "Object Not Supported" },
337     { DRDA_CP_CMDCHKRM,     "Command Check" },
338     { DRDA_CP_TRGNSPRM,     "Target Not Supported" },
339     { DRDA_CP_AGENT,        "Agent" },
340     { DRDA_CP_MGRLVLLS,     "Manager-Level List" },
341     { DRDA_CP_SUPERVISOR,   "Supervisor" },
342     { DRDA_CP_SECMGR,       "Security Manager" },
343     { DRDA_CP_EXCSATRD,     "Server Attributes Reply Data" },
344     { DRDA_CP_CMNAPPC,      "LU 6.2 Conversational Communications Manager" },
345     { DRDA_CP_DICTIONARY,   "Dictionary" },
346     { DRDA_CP_MGRLVLN,      "Manager-Level Number Attribute" },
347     { DRDA_CP_CMNTCPIP,     "TCP/IP CommunicationManager" },
348     { DRDA_CP_FDODTA,       "FD:OCA Data" },
349     { DRDA_CP_CMNSYNCPT,
350       "SNA LU 6.2 Sync Point Conversational Communications Manager" },
351     { DRDA_CP_ACCSECRD,     "Access Security Reply Data" },
352     { DRDA_CP_SYNCPTMGR,    "Sync Point Manager" },
353     { DRDA_CP_RSYNCMGR,     "ResynchronizationManager" },
354     { DRDA_CP_CCSIDMGR,     "CCSID Manager" },
355     { DRDA_CP_MONITOR,      "Monitor Events" },
356     { DRDA_CP_MONITORRD,    "Monitor Reply Data" },
357     { DRDA_CP_XAMGR,        "XAManager" },
358     { DRDA_CP_ACCRDB,       "Access RDB" },
359     { DRDA_CP_BGNBND,       "Begin Binding a Package to an RDB" },
360     { DRDA_CP_BNDSQLSTT,    "Bind SQL Statement to an RDB Package" },
361     { DRDA_CP_CLSQRY,       "Close Query" },
362     { DRDA_CP_CNTQRY,       "Continue Query" },
363     { DRDA_CP_DRPPKG,       "Drop RDB Package" },
364     { DRDA_CP_DSCSQLSTT,    "Describe SQL Statement" },
365     { DRDA_CP_ENDBND,       "End Binding a Package to an RDB" },
366     { DRDA_CP_EXCSQLIMM,    "Execute Immediate SQL Statement" },
367     { DRDA_CP_EXCSQLSTT,    "Execute SQL Statement" },
368     { DRDA_CP_OPNQRY,       "Open Query" },
369     { DRDA_CP_PRPSQLSTT,    "Prepare SQL Statement" },
370     { DRDA_CP_RDBCMM,       "RDB Commit Unit of Work" },
371     { DRDA_CP_RDBRLLBCK,    "RDB Rollback Unit of Work" },
372     { DRDA_CP_REBIND,       "Rebind an Existing RDB Package" },
373     { DRDA_CP_DSCRDBTBL,    "Describe RDB Table" },
374     { DRDA_CP_EXCSQLSET,    "Set SQL Environment" },
375     { DRDA_CP_DSCERRCD,     "Description Error Code" },
376     { DRDA_CP_QRYPRCTYP,    "Query Protocol Type" },
377     { DRDA_CP_RDBINTTKN,    "RDB Interrupt Token" },
378     { DRDA_CP_PRDDTA,       "Product-Specific Data" },
379     { DRDA_CP_RDBCMTOK,     "RDB Commit Allowed" },
380     { DRDA_CP_RDBCOLID,     "RDB Collection Identifier" },
381     { DRDA_CP_PKGID,        "RDB Package Identifier" },
382     { DRDA_CP_PKGCNSTKN,    "RDB Package Consistency Token" },
383     { DRDA_CP_RTNSETSTT,    "Return SET Statement" },
384     { DRDA_CP_RDBACCCL,     "RDB Access Manager Class" },
385     { DRDA_CP_RDBNAM,       "Relational Database Name" },
386     { DRDA_CP_OUTEXP,       "Output Expected" },
387     { DRDA_CP_PKGNAMCT,     "RDB Package Name and Consistency Token" },
388     { DRDA_CP_PKGNAMCSN,
389       "RDB Package Name, Consistency Token, and Section Number" },
390     { DRDA_CP_QRYBLKSZ,     "Query Block Size" },
391     { DRDA_CP_UOWDSP,       "Unit of Work Disposition" },
392     { DRDA_CP_RTNSQLDA,     "Maximum Result Set Count" },
393     { DRDA_CP_RDBALWUPD,    "RDB Allow Updates" },
394     { DRDA_CP_SQLCSRHLD,    "Hold Cursor Position" },
395     { DRDA_CP_STTSTRDEL,    "Statement String Delimiter" },
396     { DRDA_CP_STTDECDEL,    "Statement Decimal Delimiter" },
397     { DRDA_CP_PKGDFTCST,    "Package Default Character Subtype" },
398     { DRDA_CP_QRYBLKCTL,    "Query Block Protocol Control" },
399     { DRDA_CP_CRRTKN,       "Correlation Token" },
400     { DRDA_CP_PRCNAM,       "Procedure Name" },
401     { DRDA_CP_PKGSNLST,     "RDB Result Set Reply Message" },
402     { DRDA_CP_NBRROW,       "Number of Fetch or Insert Rows" },
403     { DRDA_CP_TRGDFTRT,     "Target Default Value Return" },
404     { DRDA_CP_QRYRELSCR,    "Query Relative Scrolling Action" },
405     { DRDA_CP_QRYROWNBR,    "Query Row Number" },
406     { DRDA_CP_QRYRFRTBL,    "Query Refresh Answer Set Table" },
407     { DRDA_CP_MAXRSLCNT,    "Maximum Result Set Count" },
408     { DRDA_CP_MAXBLKEXT,    "Maximum Number of Extra Blocks" },
409     { DRDA_CP_RSLSETFLG,    "Result Set Flags" },
410     { DRDA_CP_TYPSQLDA,     "Type of SQL Descriptor Area" },
411     { DRDA_CP_OUTOVROPT,    "Output Override Option" },
412     { DRDA_CP_RTNEXTDTA,    "Return of EXTDTA Option" },
413     { DRDA_CP_QRYATTSCR,    "Query Attribute for Scrollability" },
414     { DRDA_CP_QRYATTUPD,    "Query Attribute for Updatability" },
415     { DRDA_CP_QRYSCRORN,    "Query Scroll Orientation" },
416     { DRDA_CP_QRYROWSNS,    "Query Row Sensitivity" },
417     { DRDA_CP_QRYBLKRST,    "Query Block Reset" },
418     { DRDA_CP_QRYRTNDTA,    "Query Returns Datat" },
419     { DRDA_CP_QRYROWSET,    "Query Rowset Size" },
420     { DRDA_CP_QRYATTSNS,    "Query Attribute for Sensitivity" },
421     { DRDA_CP_QRYINSID,     "Query Instance Identifier" },
422     { DRDA_CP_QRYCLSIMP,    "Query Close Implicit" },
423     { DRDA_CP_QRYCLSRLS,    "Query Close Lock Release" },
424     { DRDA_CP_QRYOPTVAL,    "QRYOPTVAL" },
425     { DRDA_CP_DIAGLVL,      "SQL Error Diagnostic Level" },
426     { DRDA_CP_ACCRDBRM,     "Access to RDB Completed" },
427     { DRDA_CP_QRYNOPRM,     "Query Not Open" },
428     { DRDA_CP_RDBNACRM,     "RDB Not Accessed" },
429     { DRDA_CP_OPNQRYRM,     "Open Query Complete" },
430     { DRDA_CP_PKGBNARM,     "RDB Package Binding Not Active" },
431     { DRDA_CP_RDBACCRM,     "RDB Currently Accessed" },
432     { DRDA_CP_BGNBNDRM,     "Begin Bind Error" },
433     { DRDA_CP_PKGBPARM,     "RDB Package Binding Process Active" },
434     { DRDA_CP_DSCINVRM,     "Invalid Description" },
435     { DRDA_CP_ENDQRYRM,     "End of Query" },
436     { DRDA_CP_ENDUOWRM,     "End Unit of Work Condition" },
437     { DRDA_CP_ABNUOWRM,     "Abnormal End Unit ofWork Condition" },
438     { DRDA_CP_DTAMCHRM,     "Data Descriptor Mismatch" },
439     { DRDA_CP_QRYPOPRM,     "Query Previously Opened" },
440     { DRDA_CP_RDBNFNRM,     "RDB Not Found" },
441     { DRDA_CP_OPNQFLRM,     "Open Query Failure" },
442     { DRDA_CP_SQLERRRM,     "SQL Error Condition" },
443     { DRDA_CP_RDBUPDRM,     "RDB Update Reply Message" },
444     { DRDA_CP_RSLSETRM,     "RDB Result Set Reply Message" },
445     { DRDA_CP_RDBAFLRM,     "RDB Access Failed Reply Message" },
446     { DRDA_CP_CMDVLTRM,     "Command Violation" },
447     { DRDA_CP_CMMRQSRM,     "Commitment Request" },
448     { DRDA_CP_RDBATHRM,     "Not Authorized to RDB" },
449     { DRDA_CP_SQLAM,        "SQL Application Manager" },
450     { DRDA_CP_SQLCARD,      "SQL Communications Area Reply Data" },
451     { DRDA_CP_SQLCINRD,     "SQL Result Set Column Information Reply Data" },
452     { DRDA_CP_SQLRSLRD,     "SQL Result Set Reply Data" },
453     { DRDA_CP_RDB,          "Relational Database" },
454     { DRDA_CP_FRCFIXROW,    "Force Fixed Row Query Protocol" },
455     { DRDA_CP_SQLDARD,      "SQLDA Reply Data" },
456     { DRDA_CP_SQLDTA,       "SQL Program Variable Data" },
457     { DRDA_CP_SQLDTARD,     "SQL Data Reply Data" },
458     { DRDA_CP_SQLSTT,       "SQL Statement" },
459     { DRDA_CP_OUTOVR,       "Output Override Descriptor" },
460     { DRDA_CP_LMTBLKPRC,    "Limited Block Protocol" },
461     { DRDA_CP_FIXROWPRC,    "Fixed Row Query Protocol" },
462     { DRDA_CP_SQLSTTVRB,    "SQL Statement Variable Descriptions" },
463     { DRDA_CP_QRYDSC,       "Query Answer Set Description" },
464     { DRDA_CP_QRYDTA,       "Query Answer Set Data" },
465     { DRDA_CP_SQLATTR,      "SQL Statement Attributes" },
466     { 0,          NULL }
467 };
468 static value_string_ext drda_opcode_vals_ext = VALUE_STRING_EXT_INIT(drda_opcode_vals);
469
470 static const value_string drda_opcode_abbr[] = {
471     { DRDA_CP_DATA,         "DATA" },
472     { DRDA_CP_CODPNT,       "CODPNT" },
473     { DRDA_CP_FDODSC,       "FDODSC" },
474     { DRDA_CP_TYPDEFNAM,    "TYPDEFNAM" },
475     { DRDA_CP_TYPDEFOVR,    "TYPDEFOVR" },
476     { DRDA_CP_CODPNTDR,     "CODPNTDR" },
477     { DRDA_CP_EXCSAT,       "EXCSAT" },
478     { DRDA_CP_SYNCCTL,      "SYNCCTL" },
479     { DRDA_CP_SYNCRSY,      "SYNCRSY" },
480     { DRDA_CP_ACCSEC,       "ACCSEC" },
481     { DRDA_CP_SECCHK,       "SECCHK" },
482     { DRDA_CP_SYNCLOG,      "SYNCLOG" },
483     { DRDA_CP_RSCTYP,       "RSCTYP" },
484     { DRDA_CP_RSNCOD,       "RSNCOD" },
485     { DRDA_CP_RSCNAM,       "RSCNAM" },
486     { DRDA_CP_PRDID,        "PRDID" },
487     { DRDA_CP_PRCCNVCD,     "PRCCNVCD" },
488     { DRDA_CP_VRSNAM,       "VRSNAM" },
489     { DRDA_CP_SRVCLSNM,     "SRVCLSNM" },
490     { DRDA_CP_SVRCOD,       "SVRCOD" },
491     { DRDA_CP_SYNERRCD,     "SYNERRCD" },
492     { DRDA_CP_SRVDGN,       "SRVDGN" },
493     { DRDA_CP_SRVRLSLV,     "SRVRLSLV" },
494     { DRDA_CP_SPVNAM,       "SPVNAM" },
495     { DRDA_CP_EXTNAM,       "EXTNAM" },
496     { DRDA_CP_SRVNAM,       "SRVNAM" },
497     { DRDA_CP_SECMGRNM,     "SECMGRNM" },
498     { DRDA_CP_DEPERRCD,     "DEPERRCD" },
499     { DRDA_CP_CCSIDSBC,     "CCSIDSBC" },
500     { DRDA_CP_CCSIDDBC,     "CCSIDDBC" },
501     { DRDA_CP_CCSIDMBC,     "CCSIDMBC" },
502     { DRDA_CP_USRID,        "USRID" },
503     { DRDA_CP_PASSWORD,     "PASSWORD" },
504     { DRDA_CP_SECMEC,       "SECMEC" },
505     { DRDA_CP_SECCHKCD,     "SECCHKCD" },
506     { DRDA_CP_SVCERRNO,     "SVCERRNO" },
507     { DRDA_CP_SECTKN,       "SECTKN" },
508     { DRDA_CP_NEWPASSWORD,  "NEWPASSWORD" },
509     { DRDA_CP_MGRLVLRM,     "MGRLVLRM" },
510     { DRDA_CP_MGRDEPRM,     "MGRDEPRM" },
511     { DRDA_CP_SECCHKRM,     "SECCHKRM" },
512     { DRDA_CP_CMDATHRM,     "CMDATHRM" },
513     { DRDA_CP_AGNPRMRM,     "AGNPRMRM" },
514     { DRDA_CP_RSCLMTRM,     "RSCLMTRM" },
515     { DRDA_CP_PRCCNVRM,     "PRCCNVRM" },
516     { DRDA_CP_CMDCMPRM,     "CMDCMPRM" },
517     { DRDA_CP_SYNTAXRM,     "SYNTAXRM" },
518     { DRDA_CP_CMDNSPRM,     "CMDNSPRM" },
519     { DRDA_CP_PRMNSPRM,     "PRMNSPRM" },
520     { DRDA_CP_VALNSPRM,     "VALNSPRM" },
521     { DRDA_CP_OBJNSPRM,     "OBJNSPRM" },
522     { DRDA_CP_CMDCHKRM,     "CMDCHKRM" },
523     { DRDA_CP_TRGNSPRM,     "TRGNSPRM" },
524     { DRDA_CP_AGENT,        "AGENT" },
525     { DRDA_CP_MGRLVLLS,     "MGRLVLLS" },
526     { DRDA_CP_SUPERVISOR,   "SUPERVISOR" },
527     { DRDA_CP_SECMGR,       "SECMGR" },
528     { DRDA_CP_EXCSATRD,     "EXCSATRD" },
529     { DRDA_CP_CMNAPPC,      "CMNAPPC" },
530     { DRDA_CP_DICTIONARY,   "DICTIONARY" },
531     { DRDA_CP_MGRLVLN,      "MGRLVLN" },
532     { DRDA_CP_CMNTCPIP,     "CMNTCPIP" },
533     { DRDA_CP_FDODTA,       "FDODTA" },
534     { DRDA_CP_CMNSYNCPT,    "CMNSYNCPT" },
535     { DRDA_CP_ACCSECRD,     "ACCSECRD" },
536     { DRDA_CP_SYNCPTMGR,    "SYNCPTMGR" },
537     { DRDA_CP_RSYNCMGR,     "RSYNCMGR" },
538     { DRDA_CP_CCSIDMGR,     "CCSIDMGR" },
539     { DRDA_CP_MONITOR,      "MONITOR" },
540     { DRDA_CP_MONITORRD,    "MONITORRD" },
541     { DRDA_CP_XAMGR,        "XAMGR" },
542     { DRDA_CP_ACCRDB,       "ACCRDB" },
543     { DRDA_CP_BGNBND,       "BGNBND" },
544     { DRDA_CP_BNDSQLSTT,    "BNDSQLSTT" },
545     { DRDA_CP_CLSQRY,       "CLSQRY" },
546     { DRDA_CP_CNTQRY,       "CNTQRY" },
547     { DRDA_CP_DRPPKG,       "DRPPKG" },
548     { DRDA_CP_DSCSQLSTT,    "DSCSQLSTT" },
549     { DRDA_CP_ENDBND,       "ENDBND" },
550     { DRDA_CP_EXCSQLIMM,    "EXCSQLIMM" },
551     { DRDA_CP_EXCSQLSTT,    "EXCSQLSTT" },
552     { DRDA_CP_OPNQRY,       "OPNQRY" },
553     { DRDA_CP_PRPSQLSTT,    "PRPSQLSTT" },
554     { DRDA_CP_RDBCMM,       "RDBCMM" },
555     { DRDA_CP_RDBRLLBCK,    "RDBRLLBCK" },
556     { DRDA_CP_REBIND,       "REBIND" },
557     { DRDA_CP_DSCRDBTBL,    "DSCRDBTBL" },
558     { DRDA_CP_EXCSQLSET,    "EXCSQLSET" },
559     { DRDA_CP_DSCERRCD,     "DSCERRCD" },
560     { DRDA_CP_QRYPRCTYP,    "QRYPRCTYP" },
561     { DRDA_CP_RDBINTTKN,    "RDBINTTKN" },
562     { DRDA_CP_PRDDTA,       "PRDDTA" },
563     { DRDA_CP_RDBCMTOK,     "RDBCMTOK" },
564     { DRDA_CP_RDBCOLID,     "RDBCOLID" },
565     { DRDA_CP_PKGID,        "PKGID" },
566     { DRDA_CP_PKGCNSTKN,    "PKGCNSTKN" },
567     { DRDA_CP_RTNSETSTT,    "RTNSETSTT" },
568     { DRDA_CP_RDBACCCL,     "RDBACCCL" },
569     { DRDA_CP_RDBNAM,       "RDBNAM" },
570     { DRDA_CP_OUTEXP,       "OUTEXP" },
571     { DRDA_CP_PKGNAMCT,     "PKGNAMCT" },
572     { DRDA_CP_PKGNAMCSN,    "PKGNAMCSN" },
573     { DRDA_CP_QRYBLKSZ,     "QRYBLKSZ" },
574     { DRDA_CP_UOWDSP,       "UOWDSP" },
575     { DRDA_CP_RTNSQLDA,     "RTNSQLDA" },
576     { DRDA_CP_RDBALWUPD,    "RDBALWUPD" },
577     { DRDA_CP_SQLCSRHLD,    "SQLCSRHLD" },
578     { DRDA_CP_STTSTRDEL,    "STTSTRDEL" },
579     { DRDA_CP_STTDECDEL,    "STTDECDEL" },
580     { DRDA_CP_PKGDFTCST,    "PKGDFTCST" },
581     { DRDA_CP_QRYBLKCTL,    "QRYBLKCTL" },
582     { DRDA_CP_CRRTKN,       "CRRTKN" },
583     { DRDA_CP_PRCNAM,       "PRCNAM" },
584     { DRDA_CP_PKGSNLST,     "PKGSNLST" },
585     { DRDA_CP_NBRROW,       "NBRROW" },
586     { DRDA_CP_TRGDFTRT,     "TRGDFTRT" },
587     { DRDA_CP_QRYRELSCR,    "QRYRELSCR" },
588     { DRDA_CP_QRYROWNBR,    "QRYROWNBR" },
589     { DRDA_CP_QRYRFRTBL,    "QRYRFRTBL" },
590     { DRDA_CP_MAXRSLCNT,    "MAXRSLCNT" },
591     { DRDA_CP_MAXBLKEXT,    "MAXBLKEXT" },
592     { DRDA_CP_RSLSETFLG,    "RSLSETFLG" },
593     { DRDA_CP_TYPSQLDA,     "TYPSQLDA" },
594     { DRDA_CP_OUTOVROPT,    "OUTOVROPT" },
595     { DRDA_CP_RTNEXTDTA,    "RTNEXTDTA" },
596     { DRDA_CP_QRYATTSCR,    "QRYATTSCR" },
597     { DRDA_CP_QRYATTUPD,    "QRYATTUPD" },
598     { DRDA_CP_QRYSCRORN,    "QRYSCRORN" },
599     { DRDA_CP_QRYROWSNS,    "QRYROWSNS" },
600     { DRDA_CP_QRYBLKRST,    "QRYBLKRST" },
601     { DRDA_CP_QRYRTNDTA,    "QRYRTNDTA" },
602     { DRDA_CP_QRYROWSET,    "QRYROWSET" },
603     { DRDA_CP_QRYATTSNS,    "QRYATTSNS" },
604     { DRDA_CP_QRYINSID,     "QRYINSID" },
605     { DRDA_CP_QRYCLSIMP,    "QRYCLSIMP" },
606     { DRDA_CP_QRYCLSRLS,    "QRYCLSRLS" },
607     { DRDA_CP_QRYOPTVAL,    "QRYOPTVAL" },
608     { DRDA_CP_DIAGLVL,      "DIAGLVL" },
609     { DRDA_CP_ACCRDBRM,     "ACCRDBRM" },
610     { DRDA_CP_QRYNOPRM,     "QRYNOPRM" },
611     { DRDA_CP_RDBNACRM,     "RDBNACRM" },
612     { DRDA_CP_OPNQRYRM,     "OPNQRYRM" },
613     { DRDA_CP_PKGBNARM,     "PKGBNARM" },
614     { DRDA_CP_RDBACCRM,     "RDBACCRM" },
615     { DRDA_CP_BGNBNDRM,     "BGNBNDRM" },
616     { DRDA_CP_PKGBPARM,     "PKGBPARM" },
617     { DRDA_CP_DSCINVRM,     "DSCINVRM" },
618     { DRDA_CP_ENDQRYRM,     "ENDQRYRM" },
619     { DRDA_CP_ENDUOWRM,     "ENDUOWRM" },
620     { DRDA_CP_ABNUOWRM,     "ABNUOWRM" },
621     { DRDA_CP_DTAMCHRM,     "DTAMCHRM" },
622     { DRDA_CP_QRYPOPRM,     "QRYPOPRM" },
623     { DRDA_CP_RDBNFNRM,     "RDBNFNRM" },
624     { DRDA_CP_OPNQFLRM,     "OPNQFLRM" },
625     { DRDA_CP_SQLERRRM,     "SQLERRRM" },
626     { DRDA_CP_RDBUPDRM,     "RDBUPDRM" },
627     { DRDA_CP_RSLSETRM,     "RSLSETRM" },
628     { DRDA_CP_RDBAFLRM,     "RDBAFLRM" },
629     { DRDA_CP_CMDVLTRM,     "CMDVLTRM" },
630     { DRDA_CP_CMMRQSRM,     "CMMRQSRM" },
631     { DRDA_CP_RDBATHRM,     "RDBATHRM" },
632     { DRDA_CP_SQLAM,        "SQLAM" },
633     { DRDA_CP_SQLCARD,      "SQLCARD" },
634     { DRDA_CP_SQLCINRD,     "SQLCINRD" },
635     { DRDA_CP_SQLRSLRD,     "SQLRSLRD" },
636     { DRDA_CP_RDB,          "RDB" },
637     { DRDA_CP_FRCFIXROW,    "FRCFIXROW" },
638     { DRDA_CP_SQLDARD,      "SQLDARD" },
639     { DRDA_CP_SQLDTA,       "SQLDTA" },
640     { DRDA_CP_SQLDTARD,     "SQLDTARD" },
641     { DRDA_CP_SQLSTT,       "SQLSTT" },
642     { DRDA_CP_OUTOVR,       "OUTOVR" },
643     { DRDA_CP_LMTBLKPRC,    "LMTBLKPRC" },
644     { DRDA_CP_FIXROWPRC,    "FIXROWPRC" },
645     { DRDA_CP_SQLSTTVRB,    "SQLSTTVRB" },
646     { DRDA_CP_QRYDSC,       "QRYDSC" },
647     { DRDA_CP_QRYDTA,       "QRYDTA" },
648     { DRDA_CP_SQLATTR,      "SQLATTR" },
649     { 0,          NULL }
650 };
651 static value_string_ext drda_opcode_abbr_ext = VALUE_STRING_EXT_INIT(drda_opcode_abbr);
652
653 static const value_string drda_dsstyp_abbr[] = {
654     { DRDA_DSSFMT_RQSDSS,     "RQSDSS" },
655     { DRDA_DSSFMT_RPYDSS,     "RPYDSS" },
656     { DRDA_DSSFMT_OBJDSS,     "OBJDSS" },
657     { DRDA_DSSFMT_CMNDSS,     "CMNDSS" },
658     { DRDA_DSSFMT_NORPYDSS,   "NORPYDSS" },
659     { 0,          NULL }
660 };
661
662 static guint iPreviousFrameNumber = 0;
663
664 static void
665 drda_init(void)
666 {
667     iPreviousFrameNumber = 0;
668 }
669
670 static void
671 dissect_drda(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
672 {
673     gint offset = 0;
674
675     guint16 iCommand;
676     guint16 iLength;
677     guint16 iCommandEnd = 0;
678
679     guint8 iFormatFlags;
680     guint8 iDSSType;
681     guint8 iDSSFlags;
682
683     guint16 iParameterCP;
684     gint iLengthParam;
685
686     col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRDA");
687     /* This is a trick to know whether this is the first PDU in this packet or not */
688     if (iPreviousFrameNumber != pinfo->fd->num)
689         col_clear(pinfo->cinfo, COL_INFO);
690     else
691         col_append_str(pinfo->cinfo, COL_INFO, " | ");
692
693     iPreviousFrameNumber = pinfo->fd->num;
694     /* There may be multiple DRDA commands in one frame */
695     while ((guint) (offset + 10) <= tvb_length(tvb))
696     {
697         iCommand = tvb_get_ntohs(tvb, offset + 8);
698         iLength = tvb_get_ntohs(tvb, offset + 0);
699         /* iCommandEnd is the length of the packet up to the end of the current command */
700         iCommandEnd += iLength;
701
702         if (offset > 0)
703             col_append_str(pinfo->cinfo, COL_INFO, " | ");
704         col_append_str(pinfo->cinfo, COL_INFO, val_to_str_ext(iCommand, &drda_opcode_abbr_ext, "Unknown (0x%02x)"));
705
706         if (tree)
707         {
708             proto_tree  *drda_tree;
709             proto_tree  *drdaroot_tree;
710             proto_tree  *drda_tree_sub;
711             proto_item  *ti;
712
713             ti = proto_tree_add_item(tree, proto_drda, tvb, offset, -1, ENC_NA);
714             proto_item_append_text(ti, " (%s)", val_to_str_ext(iCommand, &drda_opcode_vals_ext, "Unknown (0x%02x)"));
715             drdaroot_tree = proto_item_add_subtree(ti, ett_drda);
716
717             ti = proto_tree_add_text(drdaroot_tree, tvb, offset, 10, DRDA_TEXT_DDM);
718             proto_item_append_text(ti, " (%s)", val_to_str_ext(iCommand, &drda_opcode_abbr_ext, "Unknown (0x%02x)"));
719             drda_tree = proto_item_add_subtree(ti, ett_drda_ddm);
720
721             proto_tree_add_item(drda_tree, hf_drda_ddm_length, tvb, offset + 0, 2, ENC_BIG_ENDIAN);
722             proto_tree_add_item(drda_tree, hf_drda_ddm_magic, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
723
724             iFormatFlags = tvb_get_guint8(tvb, offset + 3);
725             iDSSType = iFormatFlags & 0x0F;
726             iDSSFlags = iFormatFlags >> 4;
727
728             ti = proto_tree_add_item(drda_tree, hf_drda_ddm_format, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
729             drda_tree_sub = proto_item_add_subtree(ti, ett_drda_ddm_format);
730
731             proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_reserved, tvb, offset + 3, 1, iDSSFlags);
732             proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_chained, tvb, offset + 3, 1, iDSSFlags);
733             proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_errcont, tvb, offset + 3, 1, iDSSFlags);
734             proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_samecorr, tvb, offset + 3, 1, iDSSFlags);
735             proto_tree_add_uint(drda_tree_sub, hf_drda_ddm_fmt_dsstyp, tvb, offset + 3, 1, iDSSType);
736
737             proto_tree_add_item(drda_tree, hf_drda_ddm_rc, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
738             proto_tree_add_item(drda_tree, hf_drda_ddm_length2, tvb, offset + 6, 2, ENC_BIG_ENDIAN);
739             proto_tree_add_item(drda_tree, hf_drda_ddm_codepoint, tvb, offset + 8, 2, ENC_BIG_ENDIAN);
740
741             /* The number of attributes is variable */
742             for (offset += 10; offset < iCommandEnd; )
743             {
744                 if (tvb_length_remaining(tvb, offset) >= 2)
745                 {
746                     iLengthParam = tvb_get_ntohs(tvb, offset + 0);
747                     if (iLengthParam == 0 || iLengthParam == 1) iLengthParam = iLength - 10;
748                     if (tvb_length_remaining(tvb, offset) >= iLengthParam)
749                     {
750                         iParameterCP = tvb_get_ntohs(tvb, offset + 2);
751                         ti = proto_tree_add_text(drdaroot_tree, tvb, offset, iLengthParam,
752                                      DRDA_TEXT_PARAM);
753                         proto_item_append_text(ti, " (%s)", val_to_str_ext(iParameterCP, &drda_opcode_vals_ext, "Unknown (0x%02x)"));
754                         drda_tree_sub = proto_item_add_subtree(ti, ett_drda_param);
755                         proto_tree_add_item(drda_tree_sub, hf_drda_param_length, tvb, offset, 2, ENC_BIG_ENDIAN);
756                         proto_tree_add_item(drda_tree_sub, hf_drda_param_codepoint, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
757                         proto_tree_add_item(drda_tree_sub, hf_drda_param_data, tvb, offset + 4, iLengthParam - 4, ENC_UTF_8|ENC_NA);
758                         proto_tree_add_item(drda_tree_sub, hf_drda_param_data_ebcdic, tvb, offset + 4, iLengthParam - 4, ENC_EBCDIC|ENC_NA);
759                         if (iCommand == DRDA_CP_SQLSTT)
760                         {
761                             /* Extract SQL statement from packet */
762                             tvbuff_t* next_tvb = NULL;
763                             next_tvb = tvb_new_subset(tvb, offset + 4, iLengthParam - 4, iLengthParam - 4);
764                             add_new_data_source(pinfo, next_tvb, "SQL statement");
765                             proto_tree_add_item(drdaroot_tree, hf_drda_sqlstatement, next_tvb, 0, iLengthParam - 5, ENC_UTF_8|ENC_NA);
766                             proto_tree_add_item(drdaroot_tree, hf_drda_sqlstatement_ebcdic, next_tvb, 0, iLengthParam - 4, ENC_EBCDIC|ENC_NA);
767                         }
768                     }
769                     offset += iLengthParam;
770                 }
771                 else
772                 {
773                     break;
774                 }
775             }
776         }
777         else
778         {
779             /* No tree, advance directly to next command */
780             offset += iLength;
781         }
782     }
783 }
784
785 static guint
786 get_drda_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
787 {
788     if (tvb_length_remaining(tvb, offset) >= 10)
789     {
790         return (tvb_get_ntohs(tvb, offset));
791     }
792     return 0;
793 }
794
795 static void
796 dissect_drda_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
797 {
798     tcp_dissect_pdus(tvb, pinfo, tree, drda_desegment, 10, get_drda_pdu_len, dissect_drda);
799 }
800
801
802 static gboolean
803 dissect_drda_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
804 {
805     conversation_t * conversation;
806     if (tvb_length(tvb) >= 10)
807     {
808         /* The first header is 6 bytes long, so the length in the second header should 6 bytes less */
809         guint16 cOuterLength, cInnerLength;
810         cOuterLength = tvb_get_ntohs(tvb, 0);
811         cInnerLength = tvb_get_ntohs(tvb, 6);
812         if ((tvb_get_guint8(tvb, 2) == DRDA_MAGIC) && ((cOuterLength - cInnerLength) == 6))
813         {
814             /* Register this dissector for this conversation */
815             conversation = find_or_create_conversation(pinfo);
816             conversation_set_dissector(conversation, drda_tcp_handle);
817
818             /* Dissect the packet */
819             dissect_drda(tvb, pinfo, tree);
820             return TRUE;
821         }
822     }
823     return FALSE;
824 }
825
826 void
827 proto_register_drda(void)
828 {
829     static hf_register_info hf[] = {
830         { &hf_drda_ddm_length,
831           { "Length", "drda.ddm.length",
832             FT_UINT16, BASE_DEC, NULL, 0x0,
833             "DDM length", HFILL }},
834
835         { &hf_drda_ddm_magic,
836           { "Magic", "drda.ddm.ddmid",
837             FT_UINT8, BASE_HEX, NULL, 0x0,
838             "DDM magic", HFILL }},
839
840         { &hf_drda_ddm_format,
841           { "Format", "drda.ddm.format",
842             FT_UINT8, BASE_HEX, NULL, 0x0,
843             "DDM format", HFILL }},
844
845         { &hf_drda_ddm_fmt_reserved,
846           { "Reserved", "drda.ddm.fmt.bit0",
847             FT_BOOLEAN, 4, TFS(&tfs_set_notset), DRDA_DSSFMT_RESERVED,
848             "DSSFMT reserved", HFILL }},
849
850         { &hf_drda_ddm_fmt_chained,
851           { "Chained", "drda.ddm.fmt.bit1",
852             FT_BOOLEAN, 4, TFS(&tfs_set_notset), DRDA_DSSFMT_CHAINED,
853             "DSSFMT chained", HFILL }},
854
855         { &hf_drda_ddm_fmt_errcont,
856           { "Continue", "drda.ddm.fmt.bit2",
857             FT_BOOLEAN, 4, TFS(&tfs_set_notset), DRDA_DSSFMT_CONTINUE,
858             "DSSFMT continue on error", HFILL }},
859
860         { &hf_drda_ddm_fmt_samecorr,
861           { "Same correlation", "drda.ddm.fmt.bit3",
862             FT_BOOLEAN, 4, TFS(&tfs_set_notset), DRDA_DSSFMT_SAME_CORR,
863             "DSSFMT same correlation", HFILL }},
864
865         { &hf_drda_ddm_fmt_dsstyp,
866           { "DSS type", "drda.ddm.fmt.dsstyp",
867             FT_UINT8, BASE_DEC, VALS(drda_dsstyp_abbr), 0x0,
868             "DSSFMT type", HFILL }},
869
870         { &hf_drda_ddm_rc,
871           { "CorrelId", "drda.ddm.rqscrr",
872             FT_UINT16, BASE_DEC, NULL, 0x0,
873             "DDM correlation identifier", HFILL }},
874
875         { &hf_drda_ddm_length2,
876           { "Length2", "drda.ddm.length2",
877             FT_UINT16, BASE_DEC, NULL, 0x0,
878             "DDM length2", HFILL }},
879
880         { &hf_drda_ddm_codepoint,
881           { "Code point", "drda.ddm.codepoint",
882             FT_UINT16, BASE_HEX|BASE_EXT_STRING, &drda_opcode_abbr_ext, 0x0,
883             "DDM code point", HFILL }},
884
885         { &hf_drda_param_length,
886           { "Length", "drda.param.length",
887             FT_UINT16, BASE_DEC, NULL, 0x0,
888             "Param length", HFILL }},
889
890         { &hf_drda_param_codepoint,
891           { "Code point", "drda.param.codepoint",
892             FT_UINT16, BASE_HEX|BASE_EXT_STRING, &drda_opcode_abbr_ext, 0x0,
893             "Param code point", HFILL }},
894
895         { &hf_drda_param_data,
896           { "Data (ASCII)", "drda.param.data",
897             FT_STRING, BASE_NONE, NULL, 0x0,
898             "Param data left as ASCII for display", HFILL }},
899
900         { &hf_drda_param_data_ebcdic,
901           { "Data (EBCDIC)", "drda.param.data.ebcdic",
902             FT_STRING, BASE_NONE, NULL, 0x0,
903             "Param data converted from EBCDIC to ASCII for display", HFILL }},
904
905         { &hf_drda_sqlstatement,
906           { "SQL statement (ASCII)", "drda.sqlstatement",
907             FT_STRING, BASE_NONE, NULL, 0x0,
908             "SQL statement left as ASCII for display", HFILL }},
909
910         { &hf_drda_sqlstatement_ebcdic,
911           { "SQL statement (EBCDIC)", "drda.sqlstatement.ebcdic",
912             FT_STRING, BASE_NONE, NULL, 0x0,
913             "SQL statement converted from EBCDIC to ASCII for display", HFILL }}
914
915     };
916     static gint *ett[] = {
917         &ett_drda,
918         &ett_drda_ddm,
919         &ett_drda_ddm_format,
920         &ett_drda_param
921     };
922
923     module_t *drda_module;
924
925     proto_drda = proto_register_protocol("DRDA", "DRDA", "drda");
926     proto_register_field_array(proto_drda, hf, array_length(hf));
927     proto_register_subtree_array(ett, array_length(ett));
928
929     drda_module = prefs_register_protocol(proto_drda, NULL);
930     prefs_register_bool_preference(drda_module, "desegment",
931                        "Reassemble DRDA messages spanning multiple TCP segments",
932                        "Whether the DRDA dissector should reassemble messages spanning"
933                        " multiple TCP segments."
934                        " To use this option, you must also enable"
935                        " \"Allow subdissectors to reassemble TCP streams\""
936                        " in the TCP protocol settings.",
937                        &drda_desegment);
938     register_init_routine(&drda_init);
939 }
940
941 void
942 proto_reg_handoff_drda(void)
943 {
944     heur_dissector_add("tcp", dissect_drda_heur, proto_drda);
945     drda_tcp_handle = create_dissector_handle(dissect_drda_tcp, proto_drda);
946 }