Move 3 ASN1 dissectors to 'clean' group; move 1 PIDL dissector to 'dirty' group.
[metze/wireshark/wip.git] / epan / dissectors / packet-tds.c
1 /* packet-tds.c
2  * Routines for TDS NetLib dissection
3  * Copyright 2000-2002, Brian Bruns <camber@ais.org>
4  * Copyright 2002, Steve Langasek <vorlon@netexpress.net>
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 /*
28  * The NETLIB protocol is a small blocking protocol designed to allow TDS
29  * to be placed within different transports (TCP, DECNet, IPX/SPX).  A
30  * NETLIB packet starts with an eight byte header containing:
31  *
32  *      a one-byte packet type field;
33  *
34  *      a one-byte status field;
35  *
36  *      a two-byte big-endian size field giving the size of the packet,
37  *      including the header;
38  *
39  *      a two-byte big-endian channel number, used when multiple sessions
40  *      are being multiplexed on a single connection;
41  *
42  *      a one-byte packet number, giving "the frame number of a multiplexed
43  *      message, modulo 256";
44  *
45  *      a one-byte window, which is the number of frames to be sent
46  *      before an acknowledgment message is received.
47  *
48  * followed by payload whose size is the value in the size field minus
49  * 8.
50  *
51  * Microsoft Network Monitor 2.x dissects the 4 byte field (and indicates
52  * that the one-byte last packet indicator also contains other bits).
53  *
54  * The TDS protocol consists of a number of protocol data units (PDUs) that
55  * appear to be assembled from NETLIB packets, in the form of zero or more
56  * NETLIB packets with the last packet indicator clear and a final NETLIB
57  * packet with the last packet indicator set.  The type of the TDS PDU is
58  * specified by the packet type field of the NETLIB header (presumably that
59  * field has the same value for all NETLIB packets that make up a TDS PDU).
60  *
61  * The "server response" PDU consists of a sequence of multiple items, each
62  * one beginning with a one byte type field at the start of the PDU.  Some
63  * items are fixed length, some are variable length with a two byte size
64  * field following the item type, and then there is TDS_ROW_TOKEN in which
65  * size is determined by analyzing the result set returned from the server.
66  * This in effect means that we are hopelessly lost if we haven't seen the
67  * result set.  Also, TDS 4/5 is byte order negotiable, which is specified
68  * in the login packet.  We can attempt to determine it later on, but not
69  * with 100% accuracy.
70  *
71  * Some preliminary documentation on the packet format can be found at
72  * http://www.freetds.org/tds.html
73  *
74  * Some more information can be found in
75  * http://www.sybase.com/content/1013412/tds34.pdf
76  * http://www.sybase.com/content/1040983/Sybase-tds38-102306.pdf
77  * Microsoft's [MS-TDS] protocol specification
78  *
79  * This document is no longer available here:
80  * http://download.nai.com/products/media/sniffer/support/sdos/sybase.pdf
81  *
82  * Much of this code was originally developed for the FreeTDS project.
83  * http://www.freetds.org
84  */
85
86 /*
87  * Excerpts from Brian's posting to wireshark-dev:
88  *
89  * The TDS Protocol is actually a protocol within a protocol.  On the outside
90  * there is netlib which is not so much a encapsulation as a blocking of the
91  * data, typically to 512 or 4096 bytes.  Between this are the protocol data
92  * units for TDS.  Netlib packets may be split over real packets, multiple
93  * netlib packets may appear in single real packets.  TDS PDUs may be split
94  * over netlib packets (and real packets) and most certainly can appear
95  * multiple times within a netlib packet.
96  *
97  * Because of this, I abandoned my earlier attempt at making two dissectors,
98  * one for netlib and one for TDS. Counterintuitively, a single dissector
99  * turned out to be simpler than splitting it up.
100  *
101  * Here are some of the (hefty) limitations of the current code
102  *
103  * . We currently do not handle netlib headers that cross packet boundaries.
104  *   This should be an easy fix.
105  * . I probably could have used the packet reassembly stuff, but I started
106  *   this at version 0.8.20, so c'est la vie. It wouldn't have covered the
107  *   netlib stuff anyway, so no big loss.
108  * . The older two layer version of the code dissected the PDU's, but the new
109  *   version does not yet, it only labels the names. I need an elegant way to
110  *   deal with dissecting data crossing (netlib and tcp) packet boundries.  I
111  *   think I have one, but ran out of time to do it.
112  * . It will only work on little endian platforms.  Or rather I should say,
113  *   the client that was captured must be little endian.  TDS 7.0/8.0 is
114  *   always LE; for TDS 4.2/5.0 look in the code for tvb_get_le*() functions,
115  *   there are fields in the login packet which determine byte order.
116  * . result sets that span netlib packets are not working
117  * . TDS 7 and 4.2 result sets are not working yet
118  *
119  * All that said, the code does deal gracefully with different boudary
120  * conditions and what remains are the easier bits, IMHO.
121  *
122  * XXX - "real packets" means "TCP segments", for TCP.
123  *
124  * XXX - is it *REALLY* true that you can have more than one TDS PDU (as
125  * opposed to more than one server response item) per NETLIB packet?  Or is
126  * all the data in a NETLIB packet put into a single TDS PDU?  If so, then
127  * we can reassemble NETLIB packets using the standard TCP desegmentation
128  * code, and can reassemble TDS PDUs using "fragment_add_seq_check()",
129  * and more cleanly separate the NETLIB and TDS dissectors (although the
130  * "is this NETLIB" heuristic would have to look at TDS information past
131  * the NETLIB header, in order to make the heuristic strong enough not
132  * to get too many false positives; note that the heuristic should reject
133  * any putative NETLIB packet with a length field with a value < 8).
134  *
135  * That would substantially clean the dissector up, eliminating most of
136  * the per-packet data (we might still need information to handle
137  * TDS_ROW_TOKEN), getting rid of the stuff to handle data split across
138  * TCP segment boundaries in favor of simple reassembly code, and
139  * fixing some otherwise nasty-looking crashing bugs.
140  *
141  * NOTE: we assume that all the data in a NETLIB packet *can* be put into
142  * a single TDS PTU, so that we have separate reassembly of NETLIB
143  * packets and TDS PDUs; it seems to work, and it really did clean stuff
144  * up and fix crashes.
145  */
146
147 #include "config.h"
148
149 #include <string.h>
150 #include <ctype.h>
151
152 #include "isprint.h"
153
154 #include <glib.h>
155
156 #include <epan/packet.h>
157 #include <epan/conversation.h>
158 #include <epan/strutil.h>
159
160 #include "packet-frame.h"
161 #include <epan/reassemble.h>
162 #include <epan/prefs.h>
163 #include <epan/emem.h>
164 #include <epan/expert.h>
165
166 #define TDS_QUERY_PKT        1
167 #define TDS_LOGIN_PKT        2
168 #define TDS_RPC_PKT          3
169 #define TDS_RESP_PKT         4
170 #define TDS_RAW_PKT          5
171 #define TDS_ATTENTION_PKT    6
172 #define TDS_BULK_DATA_PKT    7
173 #define TDS_OPEN_CHN_PKT     8
174 #define TDS_CLOSE_CHN_PKT    9
175 #define TDS_RES_ERROR_PKT   10
176 #define TDS_LOG_CHN_ACK_PKT 11
177 #define TDS_ECHO_PKT        12
178 #define TDS_LOGOUT_CHN_PKT  13
179 #define TDS_TRANS_MGR_PKT   14
180 #define TDS_QUERY5_PKT      15  /* or "Normal tokenized request or response */
181 #define TDS_LOGIN7_PKT      16  /* or "Urgent tokenized request or response */
182 #define TDS_SSPI_PKT        17
183 #define TDS_PRELOGIN_PKT    18
184 #define TDS_INVALID_PKT     19
185
186 #define is_valid_tds_type(x) ((x) >= TDS_QUERY_PKT && (x) < TDS_INVALID_PKT)
187
188 /* The following constants are imported more or less directly from FreeTDS */
189 /*      Updated from FreeTDS v0.63 tds.h                                   */
190 /*         "$Id: tds.h,v 1.192 2004/10/28 12:42:12 freddy77]"              */
191 /* Note: [###] below means 'not defined in FreeTDS tds.h'                  */
192
193 #define TDS5_PARAMFMT2_TOKEN       32  /* 0x20    TDS 5.0 only              */
194 #define TDS_LANG_TOKEN             33  /* 0x21    TDS 5.0 only              */
195 #define TDS5_ORDERBY2_TOKEN        34  /* 0x22    TDS 5.0 only              */
196 #define TDS5_CURDECLARE2_TOKEN     35  /* 0x23    TDS 5.0 only        [###] */
197 #define TDS5_ROWFMT2_TOKEN         97  /* 0x61    TDS 5.0 only              */
198 #define TDS5_MSG_TOKEN            101  /* 0x65    TDS 5.0 only        [###] */
199 #define TDS_LOGOUT_TOKEN          113  /* 0x71    TDS 5.0 only? ct_close()  */
200 #define TDS_RET_STAT_TOKEN        121  /* 0x79                              */
201 #define TDS_PROCID_TOKEN          124  /* 0x7C    TDS 4.2 only - TDS_PROCID */
202 #define TDS_CURCLOSE_TOKEN        128  /* 0x80    TDS 5.0 only              */
203 #define TDS7_RESULT_TOKEN         129  /* 0x81    TDS 7.0 only              */
204 #define TDS_CURFETCH_TOKEN        130  /* 0x82    TDS 5.0 only              */
205 #define TDS_CURINFO_TOKEN         131  /* 0x83    TDS 5.0 only              */
206 #define TDS_CUROPEN_TOKEN         132  /* 0x84    TDS 5.0 only              */
207 #define TDS_CURDECLARE_TOKEN      134  /* 0x86    TDS 5.0 only              */
208 #define TDS7_COMPUTE_RESULT_TOKEN 136  /* 0x88    TDS 7.0 only              */
209 #define TDS_COL_NAME_TOKEN        160  /* 0xA0    TDS 4.2 only              */
210 #define TDS_COL_INFO_TOKEN        161  /* 0xA1    TDS 4.2 only - TDS_COLFMT */
211 #define TDS5_DYNAMIC2_TOKEN       163  /* 0xA3    TDS 5.0 only              */
212 #if 0 /* XX: Why commented out ? These are 'live' in FreeTDS tds.h */
213 #define TDS_TABNAME               164  /* 0xA4                              */
214 #define TDS_COL_INFO              165  /* 0xA5                              */
215 #endif
216 #define TDS_OPTIONCMD_TOKEN       166  /* 0xA6 */
217 #define TDS_COMPUTE_NAMES_TOKEN   167  /* 0xA7 */
218 #define TDS_COMPUTE_RESULT_TOKEN  168  /* 0xA8 */
219 #define TDS_ORDER_BY_TOKEN        169  /* 0xA9    TDS_ORDER                 */
220 #define TDS_ERR_TOKEN             170  /* 0xAA                              */
221 #define TDS_MSG_TOKEN             171  /* 0xAB                              */
222 #define TDS_PARAM_TOKEN           172  /* 0xAC    RETURNVALUE?              */
223 #define TDS_LOGIN_ACK_TOKEN       173  /* 0xAD                              */
224 #define TDS_CONTROL_TOKEN         174  /* 0xAE    TDS_CONTROL               */
225 #define TDS_KEY_TOKEN             202  /* 0xCA                        [###] */
226 #define TDS_ROW_TOKEN             209  /* 0xD1                              */
227 #define TDS_CMP_ROW_TOKEN         211  /* 0xD3                              */
228 #define TDS5_PARAMS_TOKEN         215  /* 0xD7    TDS 5.0 only              */
229 #define TDS_CAP_TOKEN             226  /* 0xE2                              */
230 #define TDS_ENV_CHG_TOKEN         227  /* 0xE3                              */
231 #define TDS_EED_TOKEN             229  /* 0xE5                              */
232 #define TDS_DBRPC_TOKEN           230  /* 0xE6                              */
233 #define TDS5_DYNAMIC_TOKEN        231  /* 0xE7    TDS 5.0 only              */
234 #define TDS5_PARAMFMT_TOKEN       236  /* 0xEC    TDS 5.0 only              */
235 #define TDS_AUTH_TOKEN            237  /* 0xED                              */
236 #define TDS_RESULT_TOKEN          238  /* 0xEE                              */
237 #define TDS_DONE_TOKEN            253  /* 0xFD    TDS_DONE                  */
238 #define TDS_DONEPROC_TOKEN        254  /* 0xFE    TDS_DONEPROC              */
239 #define TDS_DONEINPROC_TOKEN      255  /* 0xFF    TDS_DONEINPROC            */
240
241 /* Microsoft internal stored procedure id's */
242
243 #define TDS_SP_CURSOR           1
244 #define TDS_SP_CURSOROPEN       2
245 #define TDS_SP_CURSORPREPARE    3
246 #define TDS_SP_CURSOREXECUTE    4
247 #define TDS_SP_CURSORPREPEXEC   5
248 #define TDS_SP_CURSORUNPREPARE  6
249 #define TDS_SP_CURSORFETCH      7
250 #define TDS_SP_CURSOROPTION     8
251 #define TDS_SP_CURSORCLOSE      9
252 #define TDS_SP_EXECUTESQL      10
253 #define TDS_SP_PREPARE         11
254 #define TDS_SP_EXECUTE         12
255 #define TDS_SP_PREPEXEC        13
256 #define TDS_SP_PREPEXECRPC     14
257 #define TDS_SP_UNPREPARE       15
258
259
260 #define TDS_RPC_OPT_WITH_RECOMP    0x01
261 #define TDS_RPC_OPT_NO_METADATA    0x02
262 #define TDS_RPC_OPT_REUSE_METADATA 0x04
263
264 #define TDS_RPC_PARAMETER_STATUS_BY_REF  0x01
265 #define TDS_RPC_PARAMETER_STATUS_DEFAULT 0x02
266
267 /* Sybase Data Types */
268
269 #define SYBCHAR        47  /* 0x2F */
270 #define SYBVARCHAR     39  /* 0x27 */
271 #define SYBINTN        38  /* 0x26 */
272 #define SYBINT1        48  /* 0x30 */
273 #define SYBINT2        52  /* 0x34 */
274 #define SYBINT4        56  /* 0x38 */
275 #define SYBINT8       127  /* 0x7F */
276 #define SYBFLT8        62  /* 0x3E */
277 #define SYBDATETIME    61  /* 0x3D */
278 #define SYBBIT         50  /* 0x32 */
279 #define SYBTEXT        35  /* 0x23 */
280 #define SYBNTEXT       99  /* 0x63 */
281 #define SYBIMAGE       34  /* 0x22 */
282 #define SYBMONEY4     122  /* 0x7A */
283 #define SYBMONEY       60  /* 0x3C */
284 #define SYBDATETIME4   58  /* 0x3A */
285 #define SYBREAL        59  /* 0x3B */
286 #define SYBBINARY      45  /* 0x2D */
287 #define SYBVOID        31  /* 0x1F */
288 #define SYBVARBINARY   37  /* 0x25 */
289 #define SYBNVARCHAR   103  /* 0x67 */
290 #define SYBBITN       104  /* 0x68 */
291 #define SYBNUMERIC    108  /* 0x6C */
292 #define SYBDECIMAL    106  /* 0x6A */
293 #define SYBFLTN       109  /* 0x6D */
294 #define SYBMONEYN     110  /* 0x6E */
295 #define SYBDATETIMN   111  /* 0x6F */
296 #define XSYBCHAR      175  /* 0xA7 */
297 #define XSYBVARCHAR   167  /* 0xAF */
298 #define XSYBNVARCHAR  231  /* 0xE7 */
299 #define XSYBNCHAR     239  /* 0xEF */
300 #define XSYBVARBINARY 165  /* 0xA5 */
301 #define XSYBBINARY    173  /* 0xAD */
302 #define SYBLONGBINARY 225  /* 0xE1 */
303 #define SYBSINT1       64  /* 0x40 */
304 #define SYBUINT2       65  /* 0x41 */
305 #define SYBUINT4       66  /* 0x42 */
306 #define SYBUINT8       67  /* 0x43 */
307 #define SYBUNIQUE      36  /* 0x24 */
308 #define SYBVARIANT     98  /* 0x62 */
309
310 #define is_fixed_coltype(x) (x==SYBINT1    ||           \
311                              x==SYBINT2      ||         \
312                              x==SYBINT4      ||         \
313                              x==SYBINT8      ||         \
314                              x==SYBREAL       ||        \
315                              x==SYBFLT8      ||         \
316                              x==SYBDATETIME  ||         \
317                              x==SYBDATETIME4 ||         \
318                              x==SYBBIT       ||         \
319                              x==SYBMONEY     ||         \
320                              x==SYBMONEY4    ||         \
321                              x==SYBUNIQUE)
322
323 /* FIXEDLENTYPE */
324 #define TDS_DATA_TYPE_NULL            0x1F  /* Null (no data associated with this type) */
325 #define TDS_DATA_TYPE_INT1            0x30  /* TinyInt (1 byte data representation) */
326 #define TDS_DATA_TYPE_BIT             0x32  /* Bit (1 byte data representation) */
327 #define TDS_DATA_TYPE_INT2            0x34  /* SmallInt (2 byte data representation) */
328 #define TDS_DATA_TYPE_INT4            0x38  /* Int (4 byte data representation) */
329 #define TDS_DATA_TYPE_DATETIM4        0x3A  /* SmallDateTime (4 byte data representation) */
330 #define TDS_DATA_TYPE_FLT4            0x3B  /* Real (4 byte data representation) */
331 #define TDS_DATA_TYPE_MONEY           0x3C  /* Money (8 byte data representation) */
332 #define TDS_DATA_TYPE_DATETIME        0x3D  /* DateTime (8 byte data representation) */
333 #define TDS_DATA_TYPE_FLT8            0x3E  /* Float (8 byte data representation) */
334 #define TDS_DATA_TYPE_MONEY4          0x7A  /* SmallMoney (4 byte data representation) */
335 #define TDS_DATA_TYPE_INT8            0x7F  /* BigInt (8 byte data representation) */
336 /* BYTELEN_TYPE */
337 #define TDS_DATA_TYPE_GUID            0x24  /* UniqueIdentifier */
338 #define TDS_DATA_TYPE_INTN            0x26
339 #define TDS_DATA_TYPE_DECIMAL         0x37  /* Decimal (legacy support) */
340 #define TDS_DATA_TYPE_NUMERIC         0x3F  /* Numeric (legacy support) */
341 #define TDS_DATA_TYPE_BITN            0x68
342 #define TDS_DATA_TYPE_DECIMALN        0x6A  /* Decimal */
343 #define TDS_DATA_TYPE_NUMERICN        0x6C  /* Numeric */
344 #define TDS_DATA_TYPE_FLTN            0x6D
345 #define TDS_DATA_TYPE_MONEYN          0x6E
346 #define TDS_DATA_TYPE_DATETIMN        0x6F
347 #define TDS_DATA_TYPE_DATEN           0x28  /* (introduced in TDS 7.3) */
348 #define TDS_DATA_TYPE_TIMEN           0x29  /* (introduced in TDS 7.3) */
349 #define TDS_DATA_TYPE_DATETIME2N      0x2A  /* (introduced in TDS 7.3) */
350 #define TDS_DATA_TYPE_DATETIMEOFFSETN 0x2B  /* (introduced in TDS 7.3) */
351 #define TDS_DATA_TYPE_CHAR            0x2F  /* Char (legacy support) */
352 #define TDS_DATA_TYPE_VARCHAR         0x27  /* VarChar (legacy support) */
353 #define TDS_DATA_TYPE_BINARY          0x2D  /* Binary (legacy support) */
354 #define TDS_DATA_TYPE_VARBINARY       0x25  /* VarBinary (legacy support) */
355 /* USHORTLEN_TYPE */
356 #define TDS_DATA_TYPE_BIGVARBIN       0xA5  /* VarBinary */
357 #define TDS_DATA_TYPE_BIGVARCHR       0xA7  /* VarChar */
358 #define TDS_DATA_TYPE_BIGBINARY       0xAD  /* Binary */
359 #define TDS_DATA_TYPE_BIGCHAR         0xAF  /* Char */
360 #define TDS_DATA_TYPE_NVARCHAR        0xE7  /* NVarChar */
361 #define TDS_DATA_TYPE_NCHAR           0xEF  /* NChar */
362 /* LONGLEN_TYPE */
363 #define TDS_DATA_TYPE_XML             0xF1  /* XML (introduced in TDS 7.2) */
364 #define TDS_DATA_TYPE_UDT             0xF0  /* CLR-UDT (introduced in TDS 7.2) */
365 #define TDS_DATA_TYPE_TEXT            0x23  /* Text */
366 #define TDS_DATA_TYPE_IMAGE           0x22  /* Image */
367 #define TDS_DATA_TYPE_NTEXT           0x63  /* NText */
368 #define TDS_DATA_TYPE_SSVARIANT       0x62  /* Sql_Variant (introduced in TDS 7.2) */
369
370 static const value_string tds_data_type_names[] = {
371     /* FIXEDLENTYPE */
372     {TDS_DATA_TYPE_NULL,            "NULLTYPE - Null (no data associated with this type)"},
373     {TDS_DATA_TYPE_INT1,            "INT1TYPE - TinyInt (1 byte data representation)"},
374     {TDS_DATA_TYPE_BIT,             "BITTYPE - Bit (1 byte data representation)"},
375     {TDS_DATA_TYPE_INT2,            "INT2TYPE - SmallInt (2 byte data representation)"},
376     {TDS_DATA_TYPE_INT4,            "INT4TYPE - Int (4 byte data representation)"},
377     {TDS_DATA_TYPE_DATETIM4,        "DATETIM4TYPE - SmallDateTime (4 byte data representation)"},
378     {TDS_DATA_TYPE_FLT4,            "FLT4TYPE - Real (4 byte data representation)"},
379     {TDS_DATA_TYPE_MONEY,           "MONEYTYPE - Money (8 byte data representation)"},
380     {TDS_DATA_TYPE_DATETIME,        "DATETIMETYPE - DateTime (8 byte data representation)"},
381     {TDS_DATA_TYPE_FLT8,            "FLT8TYPE - Float (8 byte data representation)"},
382     {TDS_DATA_TYPE_MONEY4,          "MONEY4TYPE - SmallMoney (4 byte data representation)"},
383     {TDS_DATA_TYPE_INT8,            "INT8TYPE - BigInt (8 byte data representation)"},
384     /* BYTELEN_TYPE */
385     {TDS_DATA_TYPE_GUID,            "GUIDTYPE - UniqueIdentifier"},
386     {TDS_DATA_TYPE_INTN,            "INTNTYPE"},
387     {TDS_DATA_TYPE_DECIMAL,         "DECIMALTYPE - Decimal (legacy support)"},
388     {TDS_DATA_TYPE_NUMERIC,         "NUMERICTYPE - Numeric (legacy support)"},
389     {TDS_DATA_TYPE_BITN,            "BITNTYPE"},
390     {TDS_DATA_TYPE_DECIMALN,        "DECIMALNTYPE - Decimal"},
391     {TDS_DATA_TYPE_NUMERICN,        "NUMERICNTYPE - Numeric"},
392     {TDS_DATA_TYPE_FLTN,            "FLTNTYPE"},
393     {TDS_DATA_TYPE_MONEYN,          "MONEYNTYPE"},
394     {TDS_DATA_TYPE_DATETIMN,        "DATETIMNTYPE"},
395     {TDS_DATA_TYPE_DATEN,           "DATENTYPE - (introduced in TDS 7.3)"},
396     {TDS_DATA_TYPE_TIMEN,           "TIMENTYPE - (introduced in TDS 7.3)"},
397     {TDS_DATA_TYPE_DATETIME2N,      "DATETIME2NTYPE - (introduced in TDS 7.3)"},
398     {TDS_DATA_TYPE_DATETIMEOFFSETN, "DATETIMEOFFSETNTYPE - (introduced in TDS 7.3)"},
399     {TDS_DATA_TYPE_CHAR,            "CHARTYPE - Char (legacy support)"},
400     {TDS_DATA_TYPE_VARCHAR,         "VARCHARTYPE - VarChar (legacy support)"},
401     {TDS_DATA_TYPE_BINARY,          "BINARYTYPE - Binary (legacy support)"},
402     {TDS_DATA_TYPE_VARBINARY,       "VARBINARYTYPE - VarBinary (legacy support)"},
403     /* USHORTLEN_TYPE */
404     {TDS_DATA_TYPE_BIGVARBIN,       "BIGVARBINTYPE - VarBinary"},
405     {TDS_DATA_TYPE_BIGVARCHR,       "BIGVARCHRTYPE - VarChar"},
406     {TDS_DATA_TYPE_BIGBINARY,       "BIGBINARYTYPE - Binary"},
407     {TDS_DATA_TYPE_BIGCHAR,         "BIGCHARTYPE - Char"},
408     {TDS_DATA_TYPE_NVARCHAR,        "NVARCHARTYPE - NVarChar"},
409     {TDS_DATA_TYPE_NCHAR,           "NCHARTYPE - NChar"},
410     /* LONGLEN_TYPE */
411     {TDS_DATA_TYPE_XML,             "XMLTYPE - XML (introduced in TDS 7.2)"},
412     {TDS_DATA_TYPE_UDT,             "UDTTYPE - CLR-UDT (introduced in TDS 7.2)"},
413     {TDS_DATA_TYPE_TEXT,            "TEXTTYPE - Text"},
414     {TDS_DATA_TYPE_IMAGE,           "IMAGETYPE - Image"},
415     {TDS_DATA_TYPE_NTEXT,           "NTEXTTYPE - NText"},
416     {TDS_DATA_TYPE_SSVARIANT,       "SSVARIANTTYPE - Sql_Variant (introduced in TDS 7.2)"},
417     {0, NULL }
418 };
419
420 /* Initialize the protocol and registered fields */
421 static int proto_tds = -1;
422 static int hf_tds_type = -1;
423 static int hf_tds_status = -1;
424 static int hf_tds_status_eom = -1;
425 static int hf_tds_status_ignore = -1;
426 static int hf_tds_status_event_notif = -1;
427 static int hf_tds_status_reset_conn = -1;
428 static int hf_tds_status_reset_conn_skip_tran = -1;
429 static int hf_tds_length = -1;
430 static int hf_tds_channel = -1;
431 static int hf_tds_packet_number = -1;
432 static int hf_tds_window = -1;
433 static int hf_tds_reassembled_in = -1;
434 static int hf_tds_reassembled_length = -1;
435 static int hf_tds_fragments = -1;
436 static int hf_tds_fragment = -1;
437 static int hf_tds_fragment_overlap = -1;
438 static int hf_tds_fragment_overlap_conflict = -1;
439 static int hf_tds_fragment_multiple_tails = -1;
440 static int hf_tds_fragment_too_long_fragment = -1;
441 static int hf_tds_fragment_error = -1;
442 static int hf_tds_fragment_count = -1;
443
444 static int hf_tds7_login_total_size = -1;
445 static int hf_tds7_version = -1;
446 static int hf_tds7_packet_size = -1;
447 static int hf_tds7_client_version = -1;
448 static int hf_tds7_client_pid = -1;
449 static int hf_tds7_connection_id = -1;
450 static int hf_tds7_option_flags1 = -1;
451 static int hf_tds7_option_flags2 = -1;
452 static int hf_tds7_sql_type_flags = -1;
453 static int hf_tds7_reserved_flags = -1;
454 static int hf_tds7_time_zone = -1;
455 static int hf_tds7_collation = -1;
456 static int hf_tds7_loginack_version = -1;
457
458 static int hf_tds_all_headers = -1;
459 static int hf_tds_all_headers_total_length = -1;
460 static int hf_tds_all_headers_header_length = -1;
461 static int hf_tds_all_headers_header_type = -1;
462 static int hf_tds_all_headers_trans_descr = -1;
463 static int hf_tds_all_headers_request_cnt = -1;
464
465 static int hf_tds_type_info = -1;
466 static int hf_tds_type_info_type = -1;
467 static int hf_tds_type_info_varlen = -1;
468 static int hf_tds_type_info_precision = -1;
469 static int hf_tds_type_info_scale = -1;
470 static int hf_tds_type_info_collation = -1;
471 static int hf_tds_type_info_collation_lcid = -1;
472 static int hf_tds_type_info_collation_ign_case = -1;
473 static int hf_tds_type_info_collation_ign_accent = -1;
474 static int hf_tds_type_info_collation_ign_kana = -1;
475 static int hf_tds_type_info_collation_ign_width = -1;
476 static int hf_tds_type_info_collation_binary = -1;
477 static int hf_tds_type_info_collation_version = -1;
478 static int hf_tds_type_info_collation_sortid = -1;
479 static int hf_tds_type_varbyte_length = -1;
480 static int hf_tds_type_varbyte_data_null = -1;
481 static int hf_tds_type_varbyte_data_boolean = -1;
482 static int hf_tds_type_varbyte_data_int1 = -1;
483 static int hf_tds_type_varbyte_data_int2 = -1;
484 static int hf_tds_type_varbyte_data_int4 = -1;
485 static int hf_tds_type_varbyte_data_int8 = -1;
486 static int hf_tds_type_varbyte_data_float = -1;
487 static int hf_tds_type_varbyte_data_double = -1;
488 static int hf_tds_type_varbyte_data_bytes = -1;
489 static int hf_tds_type_varbyte_data_guid = -1;
490 static int hf_tds_type_varbyte_data_string = -1;
491 static int hf_tds_type_varbyte_plp_len = -1;
492 static int hf_tds_type_varbyte_plp_chunk_len = -1;
493
494 static int hf_tds_rpc = -1;
495 static int hf_tds_rpc_name_length8 = -1;
496 static int hf_tds_rpc_name_length = -1;
497 static int hf_tds_rpc_name = -1;
498 static int hf_tds_rpc_proc_id = -1;
499 static int hf_tds_rpc_options = -1;
500 static int hf_tds_rpc_options_with_recomp = -1;
501 static int hf_tds_rpc_options_no_metadata = -1;
502 static int hf_tds_rpc_options_reuse_metadata = -1;
503 static int hf_tds_rpc_separator = -1;
504 static int hf_tds_rpc_parameter = -1;
505 static int hf_tds_rpc_parameter_name_length = -1;
506 static int hf_tds_rpc_parameter_name = -1;
507 static int hf_tds_rpc_parameter_status = -1;
508 static int hf_tds_rpc_parameter_status_by_ref = -1;
509 static int hf_tds_rpc_parameter_status_default = -1;
510 static int hf_tds_rpc_parameter_value = -1;
511
512 /* Initialize the subtree pointers */
513 static gint ett_tds = -1;
514 static gint ett_tds_status = -1;
515 static gint ett_tds_fragments = -1;
516 static gint ett_tds_fragment = -1;
517 static gint ett_tds_token = -1;
518 static gint ett_tds_all_headers = -1;
519 static gint ett_tds_all_headers_header = -1;
520 static gint ett_tds_type_info = -1;
521 static gint ett_tds_type_info_collation = -1;
522 static gint ett_tds_type_varbyte = -1;
523 static gint ett_tds_message = -1;
524 static gint ett_tds_rpc_options = -1;
525 static gint ett_tds_rpc_parameter = -1;
526 static gint ett_tds_rpc_parameter_status = -1;
527 static gint ett_tds7_query = -1;
528 static gint ett_tds7_login = -1;
529 static gint ett_tds7_hdr = -1;
530
531 /* Desegmentation of Netlib buffers crossing TCP segment boundaries. */
532 static gboolean tds_desegment = TRUE;
533
534 static const fragment_items tds_frag_items = {
535     &ett_tds_fragment,
536     &ett_tds_fragments,
537     &hf_tds_fragments,
538     &hf_tds_fragment,
539     &hf_tds_fragment_overlap,
540     &hf_tds_fragment_overlap_conflict,
541     &hf_tds_fragment_multiple_tails,
542     &hf_tds_fragment_too_long_fragment,
543     &hf_tds_fragment_error,
544     &hf_tds_fragment_count,
545     &hf_tds_reassembled_in,
546     &hf_tds_reassembled_length,
547     /* Reassembled data field */
548     NULL,
549     "fragments"
550 };
551
552 /* Tables for reassembly of fragments. */
553 static GHashTable *tds_fragment_table = NULL;
554 static GHashTable *tds_reassembled_table = NULL;
555
556 /* defragmentation of multi-buffer TDS PDUs */
557 static gboolean tds_defragment = TRUE;
558
559 static dissector_handle_t tds_tcp_handle;
560 static dissector_handle_t ntlmssp_handle;
561 static dissector_handle_t gssapi_handle;
562 static dissector_handle_t data_handle;
563
564 typedef struct {
565     gint tds7_version;
566 } tds_conv_info_t;
567
568 /* TDS protocol type preference */
569 /*   XXX: This preference is used as a 'hint' for cases where interpretation is ambiguous */
570 /*        Currently the hint is global                                                    */
571 /*   TODO: Consider storing protocol type with each conversation                          */
572 /*        (when type is determined and using the preference as a default) ??              */
573
574 #define TDS_PROTOCOL_NOT_SPECIFIED   0
575 #define TDS_PROTOCOL_4      0x40
576 #define TDS_PROTOCOL_5      0x50
577 #define TDS_PROTOCOL_7_0    0x70
578 #define TDS_PROTOCOL_7_1    0x71
579 #define TDS_PROTOCOL_7_2    0x72
580 #define TDS_PROTOCOL_7_3    0x73
581
582 static gint tds_protocol_type = TDS_PROTOCOL_NOT_SPECIFIED;
583
584 static const enum_val_t tds_protocol_type_options[] = {
585     {"not_specified", "Not Specified", TDS_PROTOCOL_NOT_SPECIFIED},
586     {"tds4", "TDS 4", TDS_PROTOCOL_4},  /* TDS 4.2 and TDS 4.6 */
587     {"tds5", "TDS 5", TDS_PROTOCOL_5},
588     {"tds70", "TDS 7.0", TDS_PROTOCOL_7_0},
589     {"tds71", "TDS 7.1", TDS_PROTOCOL_7_1},
590     {"tds72", "TDS 7.2", TDS_PROTOCOL_7_2},
591     {"tds73", "TDS 7.3", TDS_PROTOCOL_7_3},
592     {NULL, NULL, -1}
593 };
594
595 #define TDS_PROTO_PREF_NOT_SPECIFIED (tds_protocol_type == TDS_PROTOCOL_NOT_SPECIFIED)
596 #define TDS_PROTO_PREF_TDS4 (tds_protocol_type == TDS_PROTOCOL_4)
597 #define TDS_PROTO_PREF_TDS5 (tds_protocol_type == TDS_PROTOCOL_5)
598 #define TDS_PROTO_PREF_TDS7_0 (tds_protocol_type == TDS_PROTOCOL_7_0)
599 #define TDS_PROTO_PREF_TDS7_1 (tds_protocol_type == TDS_PROTOCOL_7_1)
600 #define TDS_PROTO_PREF_TDS7_2 (tds_protocol_type == TDS_PROTOCOL_7_2)
601 #define TDS_PROTO_PREF_TDS7_3 (tds_protocol_type == TDS_PROTOCOL_7_3)
602 #define TDS_PROTO_PREF_TDS7 (tds_protocol_type >= TDS_PROTOCOL_7_0 && tds_protocol_type <= TDS_PROTOCOL_7_3)
603
604 #define TDS_PROTO_TDS4 TDS_PROTO_PREF_TDS4
605 #define TDS_PROTO_TDS7 (TDS_PROTO_PREF_TDS7 || \
606                         (TDS_PROTO_PREF_NOT_SPECIFIED && (tds_info->tds7_version != TDS_PROTOCOL_NOT_SPECIFIED)))
607 #define TDS_PROTO_TDS7_2_OR_GREATER ((tds_protocol_type >= TDS_PROTOCOL_7_2) || \
608                                      (TDS_PROTO_PREF_NOT_SPECIFIED && (tds_info->tds7_version >= TDS_PROTOCOL_7_2)))
609
610 /* TDS "endian type" */
611 /*   XXX: Assumption is that all TDS conversations being decoded in a particular capture */
612 /*        have the same endian type                                                      */
613 /*   TODO: consider storing endian type with each conversation                           */
614 /*         (using pref as the default)                                                   */
615
616 static gboolean tds_little_endian = TRUE;
617
618 static const enum_val_t tds_endian_type_options[] = {
619     {"little_endian", "Little Endian", TRUE},
620     {"big_endian"   , "Big Endian"   , FALSE},
621     {NULL, NULL, -1}
622 };
623
624 /* TCP port preferences for TDS decode */
625
626 static range_t *tds_tcp_ports = NULL;
627
628 /* These correspond to the netlib packet type field */
629 static const value_string packet_type_names[] = {
630     {TDS_QUERY_PKT,     "SQL batch"},
631     {TDS_LOGIN_PKT,     "Pre-TDS7 login"},
632     {TDS_RPC_PKT,       "Remote Procedure Call"},
633     {TDS_RESP_PKT,      "Response"},
634     {TDS_RAW_PKT,       "Unused"},
635     {TDS_ATTENTION_PKT, "Attention"},
636     {TDS_BULK_DATA_PKT, "Bulk load data"},
637     {TDS_QUERY5_PKT,    "TDS5 query"},
638     {TDS_LOGIN7_PKT,    "TDS7 login"},
639     {TDS_SSPI_PKT,      "SSPI message"},
640     {TDS_PRELOGIN_PKT,  "TDS7 pre-login message"},
641     {0, NULL}
642 };
643
644 enum {
645     TDS_HEADER_QUERY_NOTIF = 0x0001,
646     TDS_HEADER_TRANS_DESCR = 0x0002
647 };
648
649 static const value_string header_type_names[] = {
650     {TDS_HEADER_QUERY_NOTIF, "Query notifications"},
651     {TDS_HEADER_TRANS_DESCR, "Transaction descriptor"},
652     {0, NULL}
653 };
654
655 /* The status field */
656
657 #define is_valid_tds_status(x) ((x) <= STATUS_EVENT_NOTIFICATION)
658
659 #define STATUS_LAST_BUFFER              0x01
660 #define STATUS_IGNORE_EVENT             0x02
661 #define STATUS_EVENT_NOTIFICATION       0x04
662 #define STATUS_RESETCONNECTION          0x08
663 #define STATUS_RESETCONNECTIONSKIPTRAN  0x10
664
665 /* The one byte token at the start of each TDS PDU */
666 static const value_string token_names[] = {
667     {TDS5_DYNAMIC_TOKEN,        "TDS5 Dynamic SQL"},
668     {TDS5_PARAMFMT_TOKEN,       "TDS5 Parameter Format"},
669     {TDS5_PARAMFMT2_TOKEN,      "TDS5 Parameter2 Format"},
670     {TDS5_PARAMS_TOKEN,         "TDS5 Parameters"},
671     {TDS_LANG_TOKEN,            "Language"},
672     {TDS_LOGOUT_TOKEN,          "Logout"},
673     {TDS_RET_STAT_TOKEN,        "Return Status"},
674     {TDS_PROCID_TOKEN,          "Proc ID"},
675     {TDS7_RESULT_TOKEN,         "TDS7+ Results"},
676     {TDS_COL_NAME_TOKEN,        "Column Names"},
677     {TDS_COL_INFO_TOKEN,        "Column Info"},
678     {TDS_COMPUTE_NAMES_TOKEN,   "Compute Names"},
679     {TDS_COMPUTE_RESULT_TOKEN,  "Compute Results"},
680     {TDS_ORDER_BY_TOKEN,        "Order By"},
681     {TDS_ERR_TOKEN,             "Error Message"},
682     {TDS_MSG_TOKEN,             "Info Message"},
683     {TDS_PARAM_TOKEN,           "Parameter"},
684     {TDS_LOGIN_ACK_TOKEN,       "Login Acknowledgement"},
685     {TDS_CONTROL_TOKEN,         "TDS Control"},
686     {TDS_KEY_TOKEN,             "TDS Key"},
687     {TDS_ROW_TOKEN,             "Row"},
688     {TDS_CMP_ROW_TOKEN,         "Compute Row"},
689     {TDS_CAP_TOKEN,             "Capabilities"},
690     {TDS_ENV_CHG_TOKEN,         "Environment Change"},
691     {TDS_EED_TOKEN,             "Extended Error"},
692     {TDS_AUTH_TOKEN,            "Authentication"},
693     {TDS_RESULT_TOKEN,          "Results"},
694     {TDS_DONE_TOKEN,            "Done"},
695     {TDS_DONEPROC_TOKEN,        "Done Proc"},
696     {TDS_DONEINPROC_TOKEN,      "Done In Proc"},
697     {TDS5_DYNAMIC2_TOKEN,       "TDS5 Dynamic2"},
698     {TDS5_ORDERBY2_TOKEN,       "TDS5 OrderBy2"},
699     {TDS5_CURDECLARE2_TOKEN,    "TDS5 CurDeclare2"},
700     {TDS5_ROWFMT2_TOKEN,        "TDS5 RowFmt2"},
701     {TDS5_MSG_TOKEN,            "TDS5 Msg"},
702     {0, NULL}
703 };
704
705 #define TDS_RPC_SEPARATOR_BATCH_FLAG            0x80
706 #define TDS_RPC_SEPARATOR_BATCH_FLAG_7_2        0xFF
707 #define TDS_RPC_SEPARATOR_NO_EXEC_FLAG          0xFE
708
709 static const value_string tds_rpc_separators[] = {
710     {TDS_RPC_SEPARATOR_BATCH_FLAG,     "Batch flag"},
711     {TDS_RPC_SEPARATOR_BATCH_FLAG_7_2, "Batch flag 7.2"},
712     {TDS_RPC_SEPARATOR_NO_EXEC_FLAG,   "No exec flag"},
713     {0, NULL }
714 };
715
716 static const value_string internal_stored_proc_id_names[] = {
717     {TDS_SP_CURSOR,          "sp_cursor"         },
718     {TDS_SP_CURSOROPEN,      "sp_cursoropen"     },
719     {TDS_SP_CURSORPREPARE,   "sp_cursorprepare"  },
720     {TDS_SP_CURSOREXECUTE,   "sp_cursorexecute"  },
721     {TDS_SP_CURSORPREPEXEC,  "sp_cursorprepexec" },
722     {TDS_SP_CURSORUNPREPARE, "sp_cursorunprepare"},
723     {TDS_SP_CURSORFETCH,     "sp_cursorfetch"    },
724     {TDS_SP_CURSOROPTION,    "sp_cursoroption"   },
725     {TDS_SP_CURSORCLOSE,     "sp_cursorclose"    },
726     {TDS_SP_EXECUTESQL,      "sp_executesql"     },
727     {TDS_SP_PREPARE,         "sp_prepare"        },
728     {TDS_SP_EXECUTE,         "sp_execute"        },
729     {TDS_SP_PREPEXEC,        "sp_prepexec"       },
730     {TDS_SP_PREPEXECRPC,     "sp_prepexecrpc"    },
731     {TDS_SP_UNPREPARE,       "sp_unprepare"      },
732     {0,                      NULL                },
733 };
734
735 static const value_string env_chg_names[] = {
736     {1, "Database"},
737     {2, "Language"},
738     {3, "Sort Order"},
739     {4, "Blocksize"},
740     {5, "Unicode Locale ID"},
741     {6, "Unicode Comparison Style"},
742     {7, "Collation Info"},
743     {0, NULL},
744 };
745
746 static const value_string login_field_names[] = {
747     {0, "Client Name"},
748     {1, "Username"},
749     {2, "Password"},
750     {3, "App Name"},
751     {4, "Server Name"},
752     {5, "Unknown1"},
753     {6, "Library Name"},
754     {7, "Locale"},
755     {8, "Database Name"},
756     {0, NULL},
757 };
758
759
760 #define MAX_COLUMNS 256
761
762 /*
763  * This is where we store the column information to be used in decoding the
764  * TDS_ROW_TOKEN tokens.
765  */
766 struct _tds_col {
767     gchar name[256];
768     guint16 utype;
769     guint8 ctype;
770     guint csize;
771 };
772
773 struct _netlib_data {
774     guint num_cols;
775     struct _tds_col *columns[MAX_COLUMNS];
776 };
777
778 struct tds7_login_packet_hdr {
779     guint32 total_packet_size;
780     guint32 tds_version;
781     guint32 packet_size;
782     guint32 client_version;
783     guint32 client_pid;
784     guint32 connection_id;
785     guint8  option_flags1;
786     guint8  option_flags2;
787     guint8  sql_type_flags;
788     guint8  reserved_flags;
789     guint32 time_zone;
790     guint32 collation;
791 };
792
793 /* support routines */
794
795 static void
796 dissect_tds_nt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
797                guint offset, guint length)
798 {
799     tvbuff_t *nt_tvb;
800
801     nt_tvb = tvb_new_subset(tvb, offset, -1, length);
802     if(tvb_strneql(tvb, offset, "NTLMSSP", 7) == 0)
803         call_dissector(ntlmssp_handle, nt_tvb, pinfo, tree);
804     else
805         call_dissector(gssapi_handle, nt_tvb, pinfo, tree);
806 }
807
808 /*  */
809
810 static guint16
811 tds_tvb_get_xxtohs(tvbuff_t *tvb, gint offset, gboolean tds_little_endian_flag) {
812     if (tds_little_endian_flag)
813         return tvb_get_letohs(tvb, offset);
814     else
815         return tvb_get_ntohs(tvb, offset);
816 }
817
818 static guint32
819 tds_tvb_get_xxtohl(tvbuff_t *tvb, gint offset, gboolean tds_little_endian_flag) {
820     if (tds_little_endian_flag)
821         return tvb_get_letohl(tvb, offset);
822     else
823         return tvb_get_ntohl(tvb, offset);
824 }
825
826 static guint64
827 tds_tvb_get_xxtoh64(tvbuff_t *tvb, gint offset, gboolean tds_little_endian_flag) {
828     if (tds_little_endian_flag)
829         return tvb_get_letoh64(tvb, offset);
830     else
831         return tvb_get_ntoh64(tvb, offset);
832 }
833
834 static int
835 tds_token_is_fixed_size(guint8 token)
836 {
837     switch (token) {
838         case TDS_DONE_TOKEN:
839         case TDS_DONEPROC_TOKEN:
840         case TDS_DONEINPROC_TOKEN:
841         case TDS_RET_STAT_TOKEN:
842         case TDS7_RESULT_TOKEN:
843         case TDS_PROCID_TOKEN:
844         case TDS_LOGOUT_TOKEN:
845             return 1;
846         default:
847             return 0;
848     }
849 }
850
851
852 static int
853 tds_get_fixed_token_size(guint8 token, tds_conv_info_t *tds_info)
854 {
855     switch(token) {
856         case TDS_DONE_TOKEN:
857         case TDS_DONEPROC_TOKEN:
858         case TDS_DONEINPROC_TOKEN:
859             if (TDS_PROTO_TDS7_2_OR_GREATER) {
860                 return 12;
861             } else {
862                 return 8;
863             }
864         case TDS_PROCID_TOKEN:
865             return 8;
866         case TDS_RET_STAT_TOKEN:
867             return 4;
868         case TDS_LOGOUT_TOKEN:
869             return 1;
870         case TDS7_RESULT_TOKEN:
871         default:
872             return 0;
873     }
874 }
875
876 static guint
877 tds_get_variable_token_size(tvbuff_t *tvb, gint offset, guint8 token,
878                             guint *len_field_size_p, guint *len_field_val_p)
879 {
880     switch(token) {
881         /* some tokens have a 4 byte length field */
882         case TDS5_PARAMFMT2_TOKEN:
883         case TDS_LANG_TOKEN:
884         case TDS5_ORDERBY2_TOKEN:
885         case TDS5_CURDECLARE2_TOKEN:
886         case TDS5_ROWFMT2_TOKEN:
887         case TDS5_DYNAMIC2_TOKEN:
888             *len_field_size_p = 4;
889             *len_field_val_p = tds_tvb_get_xxtohl(tvb, offset, tds_little_endian);
890             break;
891             /* some have a 1 byte length field */
892         case TDS5_MSG_TOKEN:
893             *len_field_size_p = 1;
894             *len_field_val_p = tvb_get_guint8(tvb, offset);
895             break;
896             /* and most have a 2 byte length field */
897         default:
898             *len_field_size_p = 2;
899             *len_field_val_p = tds_tvb_get_xxtohs(tvb, offset, tds_little_endian);
900             break;
901     }
902     return *len_field_val_p + *len_field_size_p + 1;
903 }
904
905
906 static void
907 dissect_tds_all_headers(tvbuff_t *tvb, guint *offset, packet_info *pinfo, proto_tree *tree)
908 {
909     proto_item *item = NULL, *total_length_item = NULL;
910     proto_tree *sub_tree = NULL;
911     guint32 total_length;
912     guint final_offset;
913
914     total_length = tvb_get_letohl(tvb, *offset);
915     /* Try to find out heuristically whether the ALL_HEADERS rule is actually present.
916      * In practice total_length is a single byte value, so if the extracted value exceeds 1 byte,
917      * then the headers are most likely absent. */
918     if(total_length >= 0x100)
919         return;
920     item = proto_tree_add_item(tree, hf_tds_all_headers, tvb, *offset, total_length, ENC_NA);
921     sub_tree = proto_item_add_subtree(item, ett_tds_all_headers);
922     total_length_item = proto_tree_add_item(sub_tree, hf_tds_all_headers_total_length, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
923
924     final_offset = *offset + total_length;
925     *offset += 4;
926     do {
927         /* dissect a stream header */
928         proto_tree *header_sub_tree = NULL;
929         proto_item *length_item = NULL, *type_item = NULL;
930         guint32 header_length;
931         guint16 header_type;
932
933         header_length = tvb_get_letohl(tvb, *offset);
934         item = proto_tree_add_text(sub_tree, tvb, *offset, header_length, "Header");
935         header_sub_tree = proto_item_add_subtree(item, ett_tds_all_headers_header);
936         length_item = proto_tree_add_item(header_sub_tree, hf_tds_all_headers_header_length, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
937         if(header_length == 0 ) {
938             expert_add_info_format(pinfo, length_item, PI_MALFORMED, PI_ERROR, "Empty header");
939             break;
940         }
941
942         header_type = tvb_get_letohs(tvb, *offset + 4);
943         type_item = proto_tree_add_item(header_sub_tree, hf_tds_all_headers_header_type, tvb, *offset + 4, 2, ENC_LITTLE_ENDIAN);
944
945         switch(header_type) {
946             case TDS_HEADER_QUERY_NOTIF:
947                 break;
948             case TDS_HEADER_TRANS_DESCR:
949                 if(header_length != 18)
950                     expert_add_info_format(pinfo, length_item, PI_MALFORMED, PI_ERROR, "Length should equal 18");
951                 proto_tree_add_item(header_sub_tree, hf_tds_all_headers_trans_descr, tvb, *offset + 6, 8, ENC_LITTLE_ENDIAN);
952                 proto_tree_add_item(header_sub_tree, hf_tds_all_headers_request_cnt, tvb, *offset + 14, 4, ENC_LITTLE_ENDIAN);
953                 break;
954             default:
955                 expert_add_info_format(pinfo, type_item, PI_MALFORMED, PI_ERROR, "Invalid header type");
956         }
957
958         *offset += header_length;
959     } while(*offset < final_offset);
960     if(*offset != final_offset) {
961         expert_add_info_format(pinfo, total_length_item, PI_MALFORMED, PI_ERROR,
962                                "Sum of headers' lengths (%d) differs from total headers length (%d)",
963                                total_length + *offset - final_offset, total_length);
964         return;
965     }
966 }
967
968
969 static void
970 dissect_tds_query_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, tds_conv_info_t *tds_info)
971 {
972     guint offset, len;
973     gboolean is_unicode = TRUE;
974     char *msg;
975
976     proto_item *query_hdr;
977     proto_tree *query_tree;
978
979     offset = 0;
980     query_hdr = proto_tree_add_text(tree, tvb, offset, -1, "TDS Query Packet");
981     query_tree = proto_item_add_subtree(query_hdr, ett_tds7_query);
982     dissect_tds_all_headers(tvb, &offset, pinfo, query_tree);
983     len = tvb_reported_length_remaining(tvb, offset);
984
985     if (TDS_PROTO_TDS4 ||
986         (!TDS_PROTO_TDS7 &&
987          ((len < 2) || tvb_get_guint8(tvb, offset+1) != 0)))
988         is_unicode = FALSE;
989
990     if (is_unicode)
991         msg = tvb_get_ephemeral_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN);
992     else
993         msg = (gchar*)tvb_get_ephemeral_string(tvb, offset, len);
994
995     proto_tree_add_text(query_tree, tvb, offset, len, "Query: %s", msg);
996     offset += len;
997 }
998
999
1000 static void
1001 dissect_tds5_lang_token(tvbuff_t *tvb, guint offset, guint len, proto_tree *tree) {
1002     gboolean is_unicode = FALSE;
1003     char *msg;
1004
1005     proto_tree_add_text(tree, tvb, offset, 1 , "Status: %u", tvb_get_guint8(tvb, offset));
1006     offset += 1;
1007     len    -= 1;
1008
1009     if (is_unicode)
1010         msg = tvb_get_ephemeral_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN);
1011     else
1012         msg = (gchar*)tvb_get_ephemeral_string(tvb, offset, len);
1013
1014     proto_tree_add_text(tree, tvb, offset, len, "Language text: %s", msg);
1015 }
1016
1017 static void
1018 dissect_tds_query5_packet(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, tds_conv_info_t *tds_info)
1019 {
1020     guint offset;
1021     guint pos;
1022     guint token_len_field_size = 2;
1023     guint token_len_field_val = 0;
1024     guint8 token;
1025     guint token_sz;
1026     proto_item *query_hdr;
1027     proto_tree *query_tree;
1028     proto_item *token_item;
1029     proto_tree *token_tree;
1030
1031     offset = 0;
1032     query_hdr = proto_tree_add_text(tree, tvb, offset, -1, "TDS5 Query Packet");
1033     query_tree = proto_item_add_subtree(query_hdr, ett_tds7_query);
1034
1035     /*
1036      * Until we reach the end of the packet, read tokens.
1037      */
1038     pos = offset;
1039     while (tvb_reported_length_remaining(tvb, pos) > 0) {
1040
1041         /* our token */
1042         token = tvb_get_guint8(tvb, pos);
1043         if (tds_token_is_fixed_size(token))
1044             token_sz = tds_get_fixed_token_size(token, tds_info) + 1;
1045         else
1046             token_sz = tds_get_variable_token_size(tvb, pos+1, token, &token_len_field_size,
1047                                                    &token_len_field_val);
1048
1049         /* XXX - Should this check be done in tds_get_variable_token_size()
1050          * instead? */
1051         if ((int) token_sz < 0) {
1052             proto_tree_add_text(query_tree, tvb, 0, 0, "Bogus token size: %u",
1053                                 token_sz);
1054             break;
1055         }
1056
1057         token_item = proto_tree_add_text(query_tree, tvb, pos, token_sz,
1058                                          "Token 0x%02x %s", token,
1059                                          val_to_str_const(token, token_names, "Unknown Token Type"));
1060         token_tree = proto_item_add_subtree(token_item, ett_tds_token);
1061
1062         /*
1063          * If it's a variable token, put the length field in here
1064          * instead of replicating this for each token subdissector.
1065          */
1066         if (!tds_token_is_fixed_size(token))
1067             proto_tree_add_text(token_tree, tvb, pos+1, token_len_field_size, "Length: %u", token_len_field_val);
1068
1069         switch (token) {
1070             case TDS_LANG_TOKEN:
1071                 dissect_tds5_lang_token(tvb, pos + 5, token_sz -5, token_tree);
1072                 break;
1073             default:
1074                 break;
1075         }
1076
1077         pos += token_sz;
1078
1079     }  /* while */
1080 }
1081
1082
1083 static void
1084 dissect_tds7_login(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1085 {
1086     guint offset, i, j, k, offset2, len;
1087     char *val, *val2;
1088
1089     proto_item *login_hdr;
1090     proto_tree *login_tree;
1091     proto_item *header_hdr;
1092     proto_tree *header_tree;
1093     proto_item *length_hdr;
1094     proto_tree *length_tree;
1095
1096     struct tds7_login_packet_hdr td7hdr;
1097     gint length_remaining;
1098
1099
1100     /* create display subtree for the protocol */
1101     offset = 0;
1102     login_hdr = proto_tree_add_text(tree, tvb, offset, -1, "TDS7 Login Packet");
1103     login_tree = proto_item_add_subtree(login_hdr, ett_tds7_login);
1104     header_hdr = proto_tree_add_text(login_tree, tvb, offset, 36, "Login Packet Header");
1105     header_tree = proto_item_add_subtree(header_hdr, ett_tds7_hdr);
1106
1107     td7hdr.total_packet_size = tvb_get_letohl(tvb, offset);
1108     proto_tree_add_uint(header_tree, hf_tds7_login_total_size, tvb, offset,
1109                         sizeof(td7hdr.total_packet_size), td7hdr.total_packet_size);
1110     offset += (int)sizeof(td7hdr.total_packet_size);
1111
1112     td7hdr.tds_version = tvb_get_ntohl(tvb, offset);
1113     proto_tree_add_uint(header_tree, hf_tds7_version, tvb, offset, sizeof(td7hdr.tds_version), td7hdr.tds_version);
1114     offset += (int)sizeof(td7hdr.tds_version);
1115
1116     td7hdr.packet_size = tvb_get_ntohl(tvb, offset);
1117     proto_tree_add_uint(header_tree, hf_tds7_packet_size, tvb, offset, sizeof(td7hdr.packet_size), td7hdr.packet_size);
1118     offset += (int)sizeof(td7hdr.packet_size);
1119
1120     td7hdr.client_version = tvb_get_ntohl(tvb, offset);
1121     proto_tree_add_uint(header_tree, hf_tds7_client_version, tvb, offset, sizeof(td7hdr.client_version), td7hdr.client_version);
1122     offset += (int)sizeof(td7hdr.client_version);
1123
1124     td7hdr.client_pid = tvb_get_letohl(tvb, offset);
1125     proto_tree_add_uint(header_tree, hf_tds7_client_pid, tvb, offset, sizeof(td7hdr.client_pid), td7hdr.client_pid);
1126     offset += (int)sizeof(td7hdr.client_pid);
1127
1128     td7hdr.connection_id= tvb_get_letohl(tvb, offset);
1129     proto_tree_add_uint(header_tree, hf_tds7_connection_id, tvb, offset, sizeof(td7hdr.connection_id), td7hdr.connection_id);
1130     offset += (int)sizeof(td7hdr.connection_id);
1131
1132     td7hdr.option_flags1 = tvb_get_guint8(tvb, offset);
1133     proto_tree_add_uint(header_tree, hf_tds7_option_flags1, tvb, offset, sizeof(td7hdr.option_flags1), td7hdr.option_flags1);
1134     offset += (int)sizeof(td7hdr.option_flags1);
1135
1136     td7hdr.option_flags2 = tvb_get_guint8(tvb, offset);
1137     proto_tree_add_uint(header_tree, hf_tds7_option_flags2, tvb, offset, sizeof(td7hdr.option_flags2), td7hdr.option_flags2);
1138     offset += (int)sizeof(td7hdr.option_flags2);
1139
1140     td7hdr.sql_type_flags = tvb_get_guint8(tvb, offset);
1141     proto_tree_add_uint(header_tree, hf_tds7_sql_type_flags, tvb, offset, sizeof(td7hdr.sql_type_flags), td7hdr.sql_type_flags);
1142     offset += (int)sizeof(td7hdr.sql_type_flags);
1143
1144     td7hdr.reserved_flags = tvb_get_guint8(tvb, offset);
1145     proto_tree_add_uint(header_tree, hf_tds7_reserved_flags, tvb, offset, sizeof(td7hdr.reserved_flags), td7hdr.reserved_flags);
1146     offset += (int)sizeof(td7hdr.reserved_flags);
1147
1148     td7hdr.time_zone = tvb_get_ntohl(tvb, offset);
1149     proto_tree_add_uint(header_tree, hf_tds7_time_zone, tvb, offset, sizeof(td7hdr.time_zone), td7hdr.time_zone);
1150     offset += (int)sizeof(td7hdr.time_zone);
1151
1152     td7hdr.collation = tvb_get_ntohl(tvb, offset);
1153     proto_tree_add_uint(header_tree, hf_tds7_collation, tvb, offset, sizeof(td7hdr.collation), td7hdr.collation);
1154     offset += (int)sizeof(td7hdr.collation);
1155
1156     length_hdr = proto_tree_add_text(login_tree, tvb, offset, 50, "Lengths and offsets");
1157     length_tree = proto_item_add_subtree(length_hdr, ett_tds7_hdr);
1158
1159     for (i = 0; i < 9; i++) {
1160         offset2 = tvb_get_letohs(tvb, offset + i*4);
1161         len = tvb_get_letohs(tvb, offset + i*4 + 2);
1162         proto_tree_add_text(length_tree, tvb, offset + i*4, 2,
1163                             "%s offset: %u",
1164                             val_to_str_const(i, login_field_names, "Unknown"),
1165                             offset2);
1166         proto_tree_add_text(length_tree, tvb, offset + i*4 + 2, 2,
1167                             "%s length: %u",
1168                             val_to_str_const(i, login_field_names, "Unknown"),
1169                             len);
1170         if (len != 0) {
1171             if( i != 2) {
1172                 /* tds 7 is always unicode */
1173                 len *= 2;
1174                 val = tvb_get_ephemeral_unicode_string(tvb, offset2, len, ENC_LITTLE_ENDIAN);
1175                 proto_tree_add_text(login_tree, tvb, offset2, len, "%s: %s", val_to_str_const(i, login_field_names, "Unknown"), val);
1176             } else {
1177                 /* This field is the password.  We retrieve it from the packet
1178                  * as a non-unicode string and then perform two operations on it
1179                  * to "decrypt" it.  Finally, we create a new string that consists
1180                  * of ASCII characters instead of unicode by skipping every other
1181                  * byte in the original string.
1182                  */
1183
1184                 len *= 2;
1185                 val = (gchar*)tvb_get_ephemeral_string(tvb, offset2, len);
1186                 val2 = ep_alloc((len/2)+1);
1187
1188                 for(j = 0, k = 0; j < len; j += 2, k++) {
1189                     val[j] ^= 0xA5;
1190
1191                     /* Swap the most and least significant bits */
1192                     val[j] = ((val[j] & 0x0F) << 4) | ((val[j] & 0xF0) >> 4);
1193
1194                     val2[k] = val[j];
1195                 }
1196                 val2[k] = '\0'; /* Null terminate our new string */
1197
1198                 proto_tree_add_text(login_tree, tvb, offset2, len, "%s: %s", val_to_str_const(i, login_field_names, "Unknown"), val2);
1199             }
1200         }
1201     }
1202
1203     /*
1204      * XXX - what about the client MAC address, etc.?
1205      */
1206     length_remaining = tvb_reported_length_remaining(tvb, offset2 + len);
1207     if (length_remaining > 0) {
1208         dissect_tds_nt(tvb, pinfo, login_tree, offset2 + len,
1209                        length_remaining);
1210     }
1211 }
1212
1213 static int
1214 get_size_by_coltype(int servertype)
1215 {
1216     switch(servertype)
1217     {
1218         case SYBINT1:        return 1;
1219         case SYBINT2:        return 2;
1220         case SYBINT4:        return 4;
1221         case SYBINT8:        return 8;
1222         case SYBREAL:        return 4;
1223         case SYBFLT8:        return 8;
1224         case SYBDATETIME:    return 8;
1225         case SYBDATETIME4:   return 4;
1226         case SYBBIT:         return 1;
1227         case SYBBITN:        return 1;
1228         case SYBMONEY:       return 8;
1229         case SYBMONEY4:      return 4;
1230         case SYBUNIQUE:      return 16;
1231         default:             return -1;
1232     }
1233 }
1234 # if 0
1235 /*
1236  * data_to_string should take column data and turn it into something we can
1237  * display on the tree.
1238  */
1239 static char *data_to_string(void *data, guint col_type, guint col_size)
1240 {
1241     char *result;
1242     guint i;
1243
1244     result=ep_alloc(256);
1245     switch(col_type) {
1246         case SYBVARCHAR:
1247             /* strncpy(result, (char *)data, col_size); */
1248             for (i=0;i<col_size && i<(256-1);i++)
1249                 if (!isprint(((char *)data)[i])) result[i]='.';
1250                 else result[i]=((char *)data)[i];
1251             result[i] = '\0';
1252             break;
1253         case SYBINT2:
1254             g_snprintf(result, 256, "%d", *(short *)data);
1255             break;
1256         case SYBINT4:
1257             g_snprintf(result, 256, "%d", *(int *)data);
1258             break;
1259         default:
1260             g_snprintf(result, 256, "Unexpected column_type %d", col_type);
1261             break;
1262     }
1263     return result;
1264 }
1265 #endif
1266
1267 /*
1268  * Since rows are special PDUs in that they are not fixed and lack a size field,
1269  * the length must be computed using the column information seen in the result
1270  * PDU. This function does just that.
1271  */
1272 static guint
1273 tds_get_row_size(tvbuff_t *tvb, struct _netlib_data *nl_data, guint offset)
1274 {
1275     guint cur, i, csize;
1276
1277     cur = offset;
1278     for (i = 0; i < nl_data->num_cols; i++) {
1279         if (!is_fixed_coltype(nl_data->columns[i]->ctype)) {
1280             csize = tvb_get_guint8(tvb, cur);
1281             cur++;
1282         } else
1283             csize = get_size_by_coltype(nl_data->columns[i]->ctype);
1284         cur += csize;
1285     }
1286
1287     return (cur - offset + 1);
1288 }
1289
1290 /*
1291  * Process TDS 4 "COL_INFO" token and store relevant information in the
1292  * _netlib_data structure for later use (see tds_get_row_size)
1293  *
1294  * XXX Can TDS 4 be "big-endian" ? we'll assume yes.
1295  *
1296  */
1297 static gboolean
1298 dissect_tds_col_info_token(tvbuff_t *tvb, struct _netlib_data *nl_data, guint offset)
1299 {
1300     guint next, cur;
1301     guint col;
1302
1303     next = offset + tds_tvb_get_xxtohs(tvb, offset+1, tds_little_endian) + 3;
1304     cur = offset + 3;
1305
1306     col = 0;
1307     while (cur < next) {
1308
1309         if (col >= MAX_COLUMNS) {
1310             nl_data->num_cols = 0;
1311             return FALSE;
1312         }
1313
1314         nl_data->columns[col] = ep_alloc(sizeof(struct _tds_col));
1315
1316         nl_data->columns[col]->name[0] ='\0';
1317
1318         nl_data->columns[col]->utype = tds_tvb_get_xxtohs(tvb, cur, tds_little_endian);
1319         cur += 2;
1320
1321         cur += 2; /* unknown */
1322
1323         nl_data->columns[col]->ctype = tvb_get_guint8(tvb,cur);
1324         cur++;
1325
1326         if (!is_fixed_coltype(nl_data->columns[col]->ctype)) {
1327             nl_data->columns[col]->csize = tvb_get_guint8(tvb,cur);
1328             cur ++;
1329         } else {
1330             nl_data->columns[col]->csize =
1331                 get_size_by_coltype(nl_data->columns[col]->ctype);
1332         }
1333
1334         col += 1;
1335
1336     } /* while */
1337
1338     nl_data->num_cols = col;
1339     return TRUE;
1340 }
1341
1342
1343 /*
1344  * Read the results token and store the relevant information in the
1345  * _netlib_data structure for later use (see tds_get_row_size).
1346  *
1347  * TODO: check we don't go past end of the token
1348  */
1349 static gboolean
1350 read_results_tds5(tvbuff_t *tvb, struct _netlib_data *nl_data, guint offset, guint len _U_)
1351 {
1352     guint name_len;
1353     guint cur;
1354     guint i;
1355
1356     cur = offset;
1357
1358     /*
1359      * This would be the logical place to check for little/big endianess
1360      * if we didn't see the login packet.
1361      * XXX: We'll take a hint
1362      */
1363     nl_data->num_cols = tds_tvb_get_xxtohs(tvb, cur, tds_little_endian);
1364     if (nl_data->num_cols > MAX_COLUMNS) {
1365         nl_data->num_cols = 0;
1366         return FALSE;
1367     }
1368
1369     cur += 2;
1370
1371     for (i = 0; i < nl_data->num_cols; i++) {
1372         nl_data->columns[i] = ep_alloc(sizeof(struct _tds_col));
1373         name_len = tvb_get_guint8(tvb,cur);
1374         cur ++;
1375         cur += name_len;
1376
1377         cur++; /* unknown */
1378
1379         nl_data->columns[i]->utype = tds_tvb_get_xxtohs(tvb, cur, tds_little_endian);
1380         cur += 2;
1381
1382         cur += 2; /* unknown */
1383
1384         nl_data->columns[i]->ctype = tvb_get_guint8(tvb,cur);
1385         cur++;
1386
1387         if (!is_fixed_coltype(nl_data->columns[i]->ctype)) {
1388             nl_data->columns[i]->csize = tvb_get_guint8(tvb,cur);
1389             cur ++;
1390         } else {
1391             nl_data->columns[i]->csize =
1392                 get_size_by_coltype(nl_data->columns[i]->ctype);
1393         }
1394         cur++; /* unknown */
1395     }
1396     return TRUE;
1397 }
1398
1399 /*
1400  * If the packet type from the netlib header is a login packet, then dig into
1401  * the packet to see if this is a supported TDS version and verify the otherwise
1402  * weak heuristics of the netlib check.
1403  */
1404 static gboolean
1405 netlib_check_login_pkt(tvbuff_t *tvb, guint offset, packet_info *pinfo, guint8 type)
1406 {
1407     guint tds_major, bytes_avail;
1408
1409     bytes_avail = tvb_length(tvb) - offset;
1410     /*
1411      * we have two login packet styles, one for TDS 4.2 and 5.0
1412      */
1413     if (type==TDS_LOGIN_PKT) {
1414         /* Use major version number to validate TDS 4/5 login
1415          * packet */
1416
1417         /* Login packet is first in stream and should not be fragmented...
1418          * if it is we are screwed */
1419         if (bytes_avail < 467) return FALSE;
1420         tds_major = tvb_get_guint8(tvb, 466);
1421         if (tds_major != 4 && tds_major != 5) {
1422             return FALSE;
1423         }
1424         /*
1425          * and one added by Microsoft in SQL Server 7
1426          */
1427     } else if (type==TDS_LOGIN7_PKT) {
1428         if (bytes_avail < 16) return FALSE;
1429         tds_major = tvb_get_guint8(tvb, 15);
1430         if (tds_major != 0x70 && tds_major != 0x80) {
1431             return FALSE;
1432         }
1433     } else if (type==TDS_QUERY5_PKT) {
1434         if (bytes_avail < 9) return FALSE;
1435         /* if this is a TDS 5.0 query check the token */
1436         if (tvb_get_guint8(tvb, 8) != TDS_LANG_TOKEN) {
1437             return FALSE;
1438         }
1439     }
1440     /*
1441      * See if either tcp.destport or tcp.srcport is specified
1442      * in the preferences as being a TDS port.
1443      */
1444     else if (!value_is_in_range(tds_tcp_ports, pinfo->srcport) &&
1445              !value_is_in_range(tds_tcp_ports, pinfo->destport)) {
1446         return FALSE;
1447     }
1448
1449     return TRUE;
1450 }
1451
1452 static void
1453 dissect_tds_env_chg(tvbuff_t *tvb, guint offset, guint token_sz,
1454                     proto_tree *tree)
1455 {
1456     guint8 env_type;
1457     guint old_len, new_len, old_len_offset;
1458     char *new_val = NULL, *old_val = NULL;
1459     guint32 string_offset;
1460     gboolean is_unicode = FALSE;
1461     guint16 collate_codepage, collate_flags;
1462     guint8 collate_charset_id;
1463
1464     env_type = tvb_get_guint8(tvb, offset);
1465     proto_tree_add_text(tree, tvb, offset, 1, "Type: %u (%s)", env_type,
1466                         val_to_str_const(env_type, env_chg_names, "Unknown"));
1467
1468     new_len = tvb_get_guint8(tvb, offset+1);
1469     old_len_offset = offset + new_len + 2;
1470     old_len = tvb_get_guint8(tvb, old_len_offset);
1471
1472     /*
1473      * If our lengths plus the lengths of the type and the lengths
1474      * don't add up to the token size, it must be UCS2.
1475      */
1476     if (old_len + new_len + 3 != token_sz) {
1477         is_unicode = TRUE;
1478         old_len_offset = offset + (new_len * 2) + 2;
1479         old_len = tvb_get_guint8(tvb, old_len_offset);
1480     }
1481
1482     proto_tree_add_text(tree, tvb, offset + 1, 1, "New Value Length: %u",
1483                         new_len);
1484     if (new_len) {
1485         if (env_type != 7) { /* if it's not 'Collation Info - which is not textual! */
1486             string_offset = offset + 2;
1487             if (is_unicode == TRUE) {
1488                 new_len *= 2;
1489                 new_val = tvb_get_ephemeral_unicode_string(tvb, string_offset,
1490                                                           new_len, ENC_LITTLE_ENDIAN);
1491             } else
1492                 new_val = (gchar*)tvb_get_ephemeral_string(tvb, string_offset, new_len);
1493             proto_tree_add_text(tree, tvb, string_offset, new_len,
1494                                 "New Value: %s", new_val);
1495         }
1496         else { /* parse collation info structure. From http://www.freetds.org/tds.html#collate */
1497             offset +=2;
1498             collate_codepage = tvb_get_letohs(tvb, offset);
1499             proto_tree_add_text(tree, tvb, offset, 2, "Codepage: %u" , collate_codepage);
1500             offset += 2;
1501             collate_flags = tvb_get_letohs(tvb, offset);
1502             proto_tree_add_text(tree, tvb, offset, 2, "Flags: 0x%x", collate_flags);
1503             offset += 2;
1504             collate_charset_id = tvb_get_guint8(tvb, offset);
1505             proto_tree_add_text(tree, tvb, offset, 1, "Charset ID: %u", collate_charset_id);
1506             offset +=1;
1507         }
1508     }
1509
1510     proto_tree_add_text(tree, tvb, old_len_offset, 1, "Old Value Length: %u",
1511                         old_len);
1512     if (old_len) {
1513         string_offset = old_len_offset + 1;
1514         if (is_unicode == TRUE) {
1515             old_len *= 2;
1516             old_val = tvb_get_ephemeral_unicode_string(tvb, string_offset,
1517                                                       old_len, ENC_LITTLE_ENDIAN);
1518         } else
1519             old_val = (gchar*)tvb_get_ephemeral_string(tvb, string_offset, old_len);
1520         proto_tree_add_text(tree, tvb, string_offset, old_len,
1521                             "Old Value: %s", old_val);
1522     }
1523 }
1524
1525 static void
1526 dissect_tds_err_token(tvbuff_t *tvb, guint offset, guint token_sz _U_, proto_tree *tree, tds_conv_info_t *tds_info)
1527 {
1528     guint16 msg_len;
1529     guint8 srvr_len, proc_len;
1530     char *msg;
1531     gboolean is_unicode = FALSE;
1532
1533     proto_tree_add_text(tree, tvb, offset, 4, "SQL Error Number: %d", tds_tvb_get_xxtohl(tvb, offset, tds_little_endian));
1534     offset += 4;
1535     proto_tree_add_text(tree, tvb, offset, 1, "State: %u", tvb_get_guint8(tvb, offset));
1536     offset +=1;
1537     proto_tree_add_text(tree, tvb, offset, 1, "Severity Level: %u", tvb_get_guint8(tvb, offset));
1538     offset +=1;
1539
1540     msg_len = tds_tvb_get_xxtohs(tvb, offset, tds_little_endian);
1541     proto_tree_add_text(tree, tvb, offset, 1, "Error message length: %u characters", msg_len);
1542     offset +=2;
1543
1544     if(tvb_get_guint8(tvb, offset+1) == 0) /* FIXME: It's probably unicode, if the 2nd byte of the message is zero. It's not a good detection method, but it works */
1545         is_unicode = TRUE;
1546
1547     if(is_unicode) {
1548         msg_len *= 2;
1549         msg = tvb_get_ephemeral_unicode_string(tvb, offset, msg_len, ENC_LITTLE_ENDIAN);
1550     } else {
1551         msg = (gchar*)tvb_get_ephemeral_string(tvb, offset, msg_len);
1552     }
1553     proto_tree_add_text(tree, tvb, offset, msg_len, "Error: %s", format_text((guchar*)msg, strlen(msg)));
1554     offset += msg_len;
1555
1556     srvr_len = tvb_get_guint8(tvb, offset);
1557
1558     proto_tree_add_text(tree, tvb, offset, 1, "Server name length: %u characters", srvr_len);
1559     offset +=1;
1560     if(srvr_len) {
1561         if (is_unicode) {
1562             srvr_len *=2;
1563             msg = tvb_get_ephemeral_unicode_string(tvb, offset, srvr_len, ENC_LITTLE_ENDIAN);
1564         } else {
1565             msg = (gchar*)tvb_get_ephemeral_string(tvb, offset, srvr_len);
1566         }
1567         proto_tree_add_text(tree, tvb, offset, srvr_len, "Server name: %s", msg);
1568         offset += srvr_len;
1569     }
1570
1571     proc_len = tvb_get_guint8(tvb, offset);
1572
1573     proto_tree_add_text(tree, tvb, offset, 1, "Process name length: %u characters", proc_len);
1574     offset +=1;
1575     if(proc_len) {
1576         if (is_unicode) {
1577             proc_len *=2;
1578             msg = tvb_get_ephemeral_unicode_string(tvb, offset, proc_len, ENC_LITTLE_ENDIAN);
1579         } else {
1580             msg = (gchar*)tvb_get_ephemeral_string(tvb, offset, proc_len);
1581         }
1582         proto_tree_add_text(tree, tvb, offset, proc_len, "Process name: %s", msg);
1583         offset += proc_len;
1584     }
1585
1586     if (TDS_PROTO_TDS7_2_OR_GREATER) {
1587         proto_tree_add_text(tree, tvb, offset, 4, "line number: %d", tds_tvb_get_xxtohl(tvb, offset, tds_little_endian));
1588     } else {
1589         proto_tree_add_text(tree, tvb, offset, 2, "line number: %d", tds_tvb_get_xxtohs(tvb, offset, tds_little_endian));
1590     }
1591 }
1592
1593 static void
1594 dissect_tds_login_ack_token(tvbuff_t *tvb, guint offset, guint token_sz, proto_tree *tree, tds_conv_info_t *tds_info)
1595 {
1596     guint8 msg_len;
1597     guint32 tds_version;
1598     char *msg;
1599     gboolean is_unicode = FALSE;
1600
1601     proto_tree_add_text(tree, tvb, offset, 1, "Ack: %u", tvb_get_guint8(tvb, offset));
1602     offset +=1;
1603     tds_version = tvb_get_ntohl(tvb, offset);
1604     switch (tds_version) {
1605         case 0x07000000:
1606             tds_info->tds7_version = TDS_PROTOCOL_7_0;
1607             break;
1608         case 0x07010000:
1609         case 0x71000001:
1610             tds_info->tds7_version = TDS_PROTOCOL_7_1;
1611             break;
1612         case 0x72090002:
1613             tds_info->tds7_version = TDS_PROTOCOL_7_2;
1614             break;
1615         case 0x730A0003:
1616         case 0x730B0003:
1617         default:
1618             tds_info->tds7_version = TDS_PROTOCOL_7_3;
1619             break;
1620     }
1621     proto_tree_add_uint(tree, hf_tds7_loginack_version, tvb, offset, 4, tds_version);
1622     offset += 4;
1623
1624     msg_len = tvb_get_guint8(tvb, offset);
1625     proto_tree_add_text(tree, tvb, offset, 1, "Text length: %u characters", msg_len);
1626     offset +=1;
1627
1628     if(msg_len + 6U + 3U != token_sz - 1) /* 6 is the length of ack(1), version (4), text length (1) fields */
1629         is_unicode = TRUE;
1630     proto_tree_add_text(tree, tvb, offset, 0, "msg_len: %d, token_sz: %d, total: %d",msg_len, token_sz, msg_len + 6U + 3U);
1631     if(is_unicode) {
1632         msg_len *= 2;
1633         msg = tvb_get_ephemeral_unicode_string(tvb, offset, msg_len, ENC_LITTLE_ENDIAN);
1634     } else {
1635         msg = (gchar*)tvb_get_ephemeral_string(tvb, offset, msg_len);
1636     }
1637     proto_tree_add_text(tree, tvb, offset, msg_len, "Text: %s", format_text((guchar*)msg, strlen(msg)));
1638     offset += msg_len;
1639
1640     proto_tree_add_text(tree, tvb, offset, 4, "Server Version");
1641     offset += 4;
1642 }
1643
1644 static int
1645 dissect_tds7_results_token(tvbuff_t *tvb, guint offset, proto_tree *tree, tds_conv_info_t *tds_info)
1646 {
1647     guint16 num_columns, table_len;
1648     guint8 type, msg_len;
1649     int i;
1650     char *msg;
1651     guint16 collate_codepage, collate_flags;
1652     guint8 collate_charset_id;
1653
1654     num_columns = tvb_get_letohs(tvb, offset);
1655     proto_tree_add_text(tree, tvb, offset, 2, "Columns: %u", tvb_get_letohs(tvb, offset));
1656     offset +=2;
1657     for(i=0; i != num_columns; i++) {
1658         proto_tree_add_text(tree, tvb, offset, 0, "Column %d", i + 1);
1659         if (TDS_PROTO_TDS7_2_OR_GREATER) {
1660             proto_tree_add_text(tree, tvb, offset, 4, "usertype: %d", tvb_get_letohl(tvb, offset));
1661             offset +=4;
1662         } else {
1663             proto_tree_add_text(tree, tvb, offset, 2, "usertype: %d", tvb_get_letohs(tvb, offset));
1664             offset +=2;
1665         }
1666         proto_tree_add_text(tree, tvb, offset, 2, "flags: %d", tvb_get_letohs(tvb, offset));
1667         offset +=2;
1668         type  = tvb_get_guint8(tvb, offset);
1669         proto_tree_add_text(tree, tvb, offset, 1, "Type: %d", type);
1670         offset +=1;
1671         if(type == 38 || type == 104 || type == 109 || type == 111) { /* ugly, ugly hack. Wish I knew what it really means!*/
1672             proto_tree_add_text(tree, tvb, offset, 1, "unknown 1 byte (%x)", tvb_get_guint8(tvb, offset));
1673             offset +=1;
1674         }
1675         else if (type == 35) {
1676             proto_tree_add_text(tree, tvb, offset, 4, "unknown 4 bytes (%x)", tvb_get_letohl(tvb, offset));
1677             offset += 4;
1678             collate_codepage = tvb_get_letohs(tvb, offset);
1679             proto_tree_add_text(tree, tvb, offset, 2, "Codepage: %u" , collate_codepage);
1680             offset += 2;
1681             collate_flags = tvb_get_letohs(tvb, offset);
1682             proto_tree_add_text(tree, tvb, offset, 2, "Flags: 0x%x", collate_flags);
1683             offset += 2;
1684             collate_charset_id = tvb_get_guint8(tvb, offset);
1685             proto_tree_add_text(tree, tvb, offset, 1, "Charset ID: %u", collate_charset_id);
1686             offset +=1;
1687             table_len = tvb_get_letohs(tvb, offset);
1688             offset +=2;
1689             if(table_len != 0) {
1690                 table_len *= 2;
1691                 msg = tvb_get_ephemeral_unicode_string(tvb, offset, table_len, ENC_LITTLE_ENDIAN);
1692                 proto_tree_add_text(tree, tvb, offset, table_len, "Table name: %s", msg);
1693                 offset += table_len;
1694             }
1695         }
1696         else if (type == 106 || type == 108) {
1697             proto_tree_add_text(tree, tvb, offset, 3, "unknown 3 bytes");
1698             offset +=3;
1699         }
1700         else if(type > 128) {
1701             proto_tree_add_text(tree, tvb, offset, 2, "Large type size: 0x%x", tvb_get_letohs(tvb, offset));
1702             offset += 2;
1703             if (type != 165) {
1704                 collate_codepage = tvb_get_letohs(tvb, offset);
1705                 proto_tree_add_text(tree, tvb, offset, 2, "Codepage: %u" , collate_codepage);
1706                 offset += 2;
1707                 collate_flags = tvb_get_letohs(tvb, offset);
1708                 proto_tree_add_text(tree, tvb, offset, 2, "Flags: 0x%x", collate_flags);
1709                 offset += 2;
1710                 collate_charset_id = tvb_get_guint8(tvb, offset);
1711                 proto_tree_add_text(tree, tvb, offset, 1, "Charset ID: %u", collate_charset_id);
1712                 offset +=1;
1713             }
1714         }
1715         msg_len = tvb_get_guint8(tvb, offset);
1716         proto_tree_add_text(tree, tvb, offset, 1, "message length: %d",msg_len);
1717         offset += 1;
1718         if(msg_len != 0) {
1719             msg_len *= 2;
1720             msg = tvb_get_ephemeral_unicode_string(tvb, offset, msg_len, ENC_LITTLE_ENDIAN);
1721             proto_tree_add_text(tree, tvb, offset, msg_len, "Text: %s", msg);
1722             offset += msg_len;
1723         }
1724     }
1725     return offset;
1726 }
1727
1728 static void
1729 dissect_tds_done_token(tvbuff_t *tvb, guint offset, proto_tree *tree, tds_conv_info_t *tds_info)
1730 {
1731     proto_tree_add_text(tree, tvb, offset, 2, "Status flags");
1732     offset += 2;
1733     proto_tree_add_text(tree, tvb, offset, 2, "Operation");
1734     offset += 2;
1735     if (TDS_PROTO_TDS7_2_OR_GREATER) {
1736         proto_tree_add_text(tree, tvb, offset, 8, "row count: %" G_GINT64_MODIFIER "u",
1737                             tds_tvb_get_xxtoh64(tvb, offset, tds_little_endian));
1738     } else {
1739         proto_tree_add_text(tree, tvb, offset, 4, "row count: %u",
1740                             tds_tvb_get_xxtohl(tvb, offset, tds_little_endian));
1741     }
1742 }
1743
1744 static guint8
1745 dissect_tds_type_info(tvbuff_t *tvb, guint *offset, packet_info *pinfo, proto_tree *tree, gboolean *plp)
1746 {
1747     proto_item *item = NULL, *item1 = NULL, *data_type_item = NULL;
1748     proto_tree *sub_tree = NULL, *collation_tree;
1749     guint32 varlen, varlen_len = 0;
1750     guint8 data_type;
1751
1752     *plp = FALSE; /* most types are not Partially Length-Prefixed */
1753     item = proto_tree_add_item(tree, hf_tds_type_info, tvb, *offset, 0, ENC_NA);
1754     data_type = tvb_get_guint8(tvb, *offset);
1755     proto_item_append_text(item, " (%s)", val_to_str(data_type, tds_data_type_names, "Invalid data type: %02X"));
1756     sub_tree = proto_item_add_subtree(item, ett_tds_type_info);
1757     data_type_item = proto_tree_add_item(sub_tree, hf_tds_type_info_type, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
1758     *offset += 1;
1759
1760     /* optional TYPE_VARLEN for variable length types */
1761     switch(data_type) {
1762         /* FIXEDLENTYPE */
1763         case TDS_DATA_TYPE_NULL:            /* Null (no data associated with this type) */
1764         case TDS_DATA_TYPE_INT1:            /* TinyInt (1 byte data representation) */
1765         case TDS_DATA_TYPE_BIT:             /* Bit (1 byte data representation) */
1766         case TDS_DATA_TYPE_INT2:            /* SmallInt (2 byte data representation) */
1767         case TDS_DATA_TYPE_INT4:            /* Int (4 byte data representation) */
1768         case TDS_DATA_TYPE_FLT4:            /* Real (4 byte data representation) */
1769         case TDS_DATA_TYPE_DATETIM4:        /* SmallDateTime (4 byte data representation) */
1770         case TDS_DATA_TYPE_MONEY4:          /* SmallMoney (4 byte data representation) */
1771         case TDS_DATA_TYPE_INT8:            /* BigInt (8 byte data representation) */
1772         case TDS_DATA_TYPE_FLT8:            /* Float (8 byte data representation) */
1773         case TDS_DATA_TYPE_MONEY:           /* Money (8 byte data representation) */
1774         case TDS_DATA_TYPE_DATETIME:        /* DateTime (8 byte data representation) */
1775         /* BYTELEN_TYPE with length determined by SCALE */
1776         case TDS_DATA_TYPE_TIMEN:           /* (introduced in TDS 7.3) */
1777         case TDS_DATA_TYPE_DATETIME2N:      /* (introduced in TDS 7.3) */
1778         case TDS_DATA_TYPE_DATETIMEOFFSETN: /* (introduced in TDS 7.3) */
1779             varlen_len = 0;
1780             break;
1781         /* BYTELEN_TYPE */
1782         case TDS_DATA_TYPE_GUID:            /* UniqueIdentifier */
1783         case TDS_DATA_TYPE_INTN:
1784         case TDS_DATA_TYPE_DECIMAL:         /* Decimal (legacy support) */
1785         case TDS_DATA_TYPE_NUMERIC:         /* Numeric (legacy support) */
1786         case TDS_DATA_TYPE_BITN:
1787         case TDS_DATA_TYPE_DECIMALN:        /* Decimal */
1788         case TDS_DATA_TYPE_NUMERICN:        /* Numeric */
1789         case TDS_DATA_TYPE_FLTN:
1790         case TDS_DATA_TYPE_MONEYN:
1791         case TDS_DATA_TYPE_DATETIMN:
1792         case TDS_DATA_TYPE_DATEN:           /* (introduced in TDS 7.3) */
1793         case TDS_DATA_TYPE_CHAR:            /* Char (legacy support) */
1794         case TDS_DATA_TYPE_VARCHAR:         /* VarChar (legacy support) */
1795         case TDS_DATA_TYPE_BINARY:          /* Binary (legacy support) */
1796         case TDS_DATA_TYPE_VARBINARY:       /* VarBinary (legacy support) */
1797             varlen_len = 1;
1798             varlen = tvb_get_guint8(tvb, *offset);
1799             break;
1800         /* USHORTLEN_TYPE */
1801         case TDS_DATA_TYPE_BIGVARCHR:       /* VarChar */
1802         case TDS_DATA_TYPE_BIGVARBIN:       /* VarBinary */
1803         case TDS_DATA_TYPE_NVARCHAR:        /* NVarChar */
1804             varlen_len = 2;
1805             varlen = tvb_get_letohs(tvb, *offset);
1806             /* A type with unlimited max size, known as varchar(max), varbinary(max) and nvarchar(max),
1807                which has a max size of 0xFFFF, defined by PARTLENTYPE. This class of types was introduced in TDS 7.2. */
1808             if(varlen == 0xFFFF)
1809                 *plp = TRUE;
1810             break;
1811         case TDS_DATA_TYPE_BIGBINARY:       /* Binary */
1812         case TDS_DATA_TYPE_BIGCHAR:         /* Char */
1813         case TDS_DATA_TYPE_NCHAR:           /* NChar */
1814             varlen_len = 2;
1815             varlen = tvb_get_letohs(tvb, *offset);
1816             break;
1817         /* LONGLEN_TYPE */
1818         case TDS_DATA_TYPE_XML:             /* XML (introduced in TDS 7.2) */
1819         case TDS_DATA_TYPE_UDT:             /* CLR-UDT (introduced in TDS 7.2) */
1820             *plp = TRUE;
1821         case TDS_DATA_TYPE_TEXT:            /* Text */
1822         case TDS_DATA_TYPE_IMAGE:           /* Image */
1823         case TDS_DATA_TYPE_NTEXT:           /* NText */
1824         case TDS_DATA_TYPE_SSVARIANT:       /* Sql_Variant (introduced in TDS 7.2) */
1825             varlen_len = 4;
1826             varlen = tvb_get_letohl(tvb, *offset);
1827             break;
1828         default:
1829             expert_add_info_format(pinfo, data_type_item, PI_MALFORMED, PI_ERROR, "Invalid data type");
1830             THROW(ReportedBoundsError); /* No point in continuing */
1831     }
1832
1833     if(varlen_len)
1834         item1 = proto_tree_add_uint(sub_tree, hf_tds_type_info_varlen, tvb, *offset, varlen_len, varlen);
1835     if(*plp)
1836         proto_item_append_text(item1, " (PLP - Partially Length-Prefixed data type)");
1837     *offset += varlen_len;
1838
1839     /* Optional data dependent on type */
1840     switch(data_type) {
1841         /* PRECISION and SCALE */
1842         case TDS_DATA_TYPE_DECIMAL:         /* Decimal (legacy support) */
1843         case TDS_DATA_TYPE_NUMERIC:         /* Numeric (legacy support) */
1844         case TDS_DATA_TYPE_DECIMALN:        /* Decimal */
1845         case TDS_DATA_TYPE_NUMERICN:        /* Numeric */
1846             proto_tree_add_item(sub_tree, hf_tds_type_info_precision, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
1847             *offset += 1;
1848         /* SCALE */
1849         case TDS_DATA_TYPE_TIMEN:           /* (introduced in TDS 7.3) */
1850         case TDS_DATA_TYPE_DATETIME2N:      /* (introduced in TDS 7.3) */
1851         case TDS_DATA_TYPE_DATETIMEOFFSETN: /* (introduced in TDS 7.3) */
1852             proto_tree_add_item(sub_tree, hf_tds_type_info_scale, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
1853             *offset += 1;
1854             break;
1855         /* COLLATION */
1856         case TDS_DATA_TYPE_BIGCHAR:         /* Char */
1857         case TDS_DATA_TYPE_BIGVARCHR:       /* VarChar */
1858         case TDS_DATA_TYPE_TEXT:            /* Text */
1859         case TDS_DATA_TYPE_NTEXT:           /* NText */
1860         case TDS_DATA_TYPE_NCHAR:           /* NChar */
1861         case TDS_DATA_TYPE_NVARCHAR:        /* NVarChar */
1862             item1 = proto_tree_add_item(sub_tree, hf_tds_type_info_collation, tvb, *offset, 5, ENC_NA);
1863             collation_tree = proto_item_add_subtree(item1, ett_tds_type_info_collation);
1864             proto_tree_add_item(collation_tree, hf_tds_type_info_collation_lcid, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
1865             proto_tree_add_item(collation_tree, hf_tds_type_info_collation_ign_case, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
1866             proto_tree_add_item(collation_tree, hf_tds_type_info_collation_ign_accent, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
1867             proto_tree_add_item(collation_tree, hf_tds_type_info_collation_ign_kana, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
1868             proto_tree_add_item(collation_tree, hf_tds_type_info_collation_ign_width, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
1869             proto_tree_add_item(collation_tree, hf_tds_type_info_collation_binary, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
1870             proto_tree_add_item(collation_tree, hf_tds_type_info_collation_version, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
1871             proto_tree_add_item(collation_tree, hf_tds_type_info_collation_sortid, tvb, *offset + 4, 1, ENC_LITTLE_ENDIAN);
1872             *offset += 5;
1873             break;
1874     }
1875
1876     proto_item_set_end(item, tvb, *offset);
1877     return data_type;
1878 }
1879
1880 static void
1881 dissect_tds_type_varbyte(tvbuff_t *tvb, guint *offset, packet_info *pinfo, proto_tree *tree, int hf, guint8 data_type, gboolean plp)
1882 {
1883     enum { GEN_NULL = 0x00U, CHARBIN_NULL = 0xFFFFU, CHARBIN_NULL32 = 0xFFFFFFFFUL };
1884     guint32 length;
1885     char *string_value;
1886     proto_tree *sub_tree = NULL;
1887     proto_item *item = NULL, *length_item = NULL;
1888
1889     item = proto_tree_add_item(tree, hf, tvb, *offset, 0, ENC_NA);
1890     sub_tree = proto_item_add_subtree(item, ett_tds_type_varbyte);
1891
1892     if(plp) {
1893         enum { PLP_TERMINATOR = 0x00000000UL, UNKNOWN_PLP_LEN = 0xFFFFFFFFFFFFFFFEULL, PLP_NULL = 0xFFFFFFFFFFFFFFFFULL };
1894         guint64 plp_length = tvb_get_letoh64(tvb, *offset);
1895         length_item = proto_tree_add_item(sub_tree, hf_tds_type_varbyte_plp_len, tvb, *offset, 8, ENC_LITTLE_ENDIAN);
1896         *offset += 8;
1897         if(plp_length == PLP_NULL)
1898             proto_item_append_text(length_item, " (PLP_NULL)");
1899         else {
1900             if(plp_length == UNKNOWN_PLP_LEN)
1901                 proto_item_append_text(length_item, " (UNKNOWN_PLP_LEN)");
1902             while(TRUE) {
1903                 length = tvb_get_letohl(tvb, *offset);
1904                 length_item = proto_tree_add_item(sub_tree, hf_tds_type_varbyte_plp_chunk_len, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
1905                 *offset += 4;
1906                 if(length == PLP_TERMINATOR) {
1907                     proto_item_append_text(length_item, " (PLP_TERMINATOR)");
1908                     break;
1909                 }
1910                 switch(data_type) {
1911                     case TDS_DATA_TYPE_BIGVARBIN: /* VarBinary */
1912                         proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_bytes, tvb, *offset, length, ENC_NA);
1913                         break;
1914                     case TDS_DATA_TYPE_BIGVARCHR: /* VarChar */
1915                         proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_string, tvb, *offset, length, ENC_ASCII|ENC_NA);
1916                         break;
1917                     case TDS_DATA_TYPE_NVARCHAR:  /* NVarChar */
1918                         string_value = tvb_get_ephemeral_unicode_string(tvb, *offset, length, ENC_LITTLE_ENDIAN);
1919                         proto_tree_add_string(sub_tree, hf_tds_type_varbyte_data_string, tvb, *offset, length, string_value);
1920                         break;
1921                     case TDS_DATA_TYPE_XML:       /* XML (introduced in TDS 7.2) */
1922                     case TDS_DATA_TYPE_UDT:       /* CLR-UDT (introduced in TDS 7.2) */
1923                         expert_add_info_format(pinfo, length_item, PI_UNDECODED, PI_ERROR, "Data type %d not supported yet", data_type);
1924                         /* No point in continuing: we need to parse the full data_type to know where it ends */
1925                         THROW(ReportedBoundsError);
1926                     default:
1927                         /* no other data type sets plp = TRUE */
1928                         DISSECTOR_ASSERT_NOT_REACHED();
1929                 }
1930                 *offset += length;
1931             }
1932         }
1933     }
1934     else switch(data_type) {
1935         /* FIXEDLENTYPE */
1936         case TDS_DATA_TYPE_NULL:            /* Null (no data associated with this type) */
1937             break;
1938         case TDS_DATA_TYPE_BIT:             /* Bit (1 byte data representation) */
1939             proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_boolean, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
1940             *offset += 1;
1941             break;
1942         case TDS_DATA_TYPE_INT1:            /* TinyInt (1 byte data representation) */
1943             proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_int1, tvb, *offset, 1, ENC_LITTLE_ENDIAN);
1944             *offset += 1;
1945             break;
1946         case TDS_DATA_TYPE_INT2:            /* SmallInt (2 byte data representation) */
1947             proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_int2, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
1948             *offset += 2;
1949             break;
1950         case TDS_DATA_TYPE_INT4:            /* Int (4 byte data representation) */
1951             proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_int4, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
1952             *offset += 4;
1953             break;
1954         case TDS_DATA_TYPE_INT8:            /* BigInt (8 byte data representation) */
1955             proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_int8, tvb, *offset, 8, ENC_LITTLE_ENDIAN);
1956             *offset += 8;
1957             break;
1958         case TDS_DATA_TYPE_FLT4:            /* Real (4 byte data representation) */
1959             proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_float, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
1960             *offset += 4;
1961             break;
1962         case TDS_DATA_TYPE_FLT8:            /* Float (8 byte data representation) */
1963             proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_double, tvb, *offset, 8, ENC_LITTLE_ENDIAN);
1964             *offset += 8;
1965             break;
1966         case TDS_DATA_TYPE_MONEY4:          /* SmallMoney (4 byte data representation) */
1967         case TDS_DATA_TYPE_DATETIM4:        /* SmallDateTime (4 byte data representation) */
1968             /*TODO*/
1969             *offset += 4;
1970             break;
1971         case TDS_DATA_TYPE_MONEY:           /* Money (8 byte data representation) */
1972         case TDS_DATA_TYPE_DATETIME:        /* DateTime (8 byte data representation) */
1973             /*TODO*/
1974             *offset += 8;
1975             break;
1976
1977
1978         /* BYTELEN_TYPE - types prefixed with 1-byte length */
1979         case TDS_DATA_TYPE_GUID:            /* UniqueIdentifier */
1980             length = tvb_get_guint8(tvb, *offset);
1981             length_item = proto_tree_add_uint(sub_tree, hf_tds_type_varbyte_length, tvb, *offset, 1, length);
1982             switch(length) {
1983                 case GEN_NULL: proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_null, tvb, *offset, 0, ENC_NA); break;
1984                 case 16: proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_guid, tvb, *offset + 1, length, ENC_LITTLE_ENDIAN); break;
1985                 default: expert_add_info_format(pinfo, length_item, PI_MALFORMED, PI_ERROR, "Invalid length");
1986             }
1987             *offset += 1 + length;
1988             break;
1989         case TDS_DATA_TYPE_BITN:
1990             length = tvb_get_guint8(tvb, *offset);
1991             length_item = proto_tree_add_uint(sub_tree, hf_tds_type_varbyte_length, tvb, *offset, 1, length);
1992             switch(length) {
1993                 case GEN_NULL: proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_null, tvb, *offset, 0, ENC_NA); break;
1994                 case 1: proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_boolean, tvb, *offset + 1, 1, ENC_LITTLE_ENDIAN); break;
1995                 default: expert_add_info_format(pinfo, length_item, PI_MALFORMED, PI_ERROR, "Invalid length");
1996             }
1997             *offset += 1 + length;
1998             break;
1999         case TDS_DATA_TYPE_INTN:
2000             length = tvb_get_guint8(tvb, *offset);
2001             length_item = proto_tree_add_uint(sub_tree, hf_tds_type_varbyte_length, tvb, *offset, 1, length);
2002             switch(length) {
2003                 case GEN_NULL: proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_null, tvb, *offset, 0, ENC_NA); break;
2004                 case 1: proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_int1, tvb, *offset + 1, 1, ENC_LITTLE_ENDIAN); break;
2005                 case 2: proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_int2, tvb, *offset + 1, 2, ENC_LITTLE_ENDIAN); break;
2006                 case 4: proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_int4, tvb, *offset + 1, 4, ENC_LITTLE_ENDIAN); break;
2007                 case 8: proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_int8, tvb, *offset + 1, 8, ENC_LITTLE_ENDIAN); break;
2008                 default: expert_add_info_format(pinfo, length_item, PI_MALFORMED, PI_ERROR, "Invalid length");
2009             }
2010             *offset += 1 + length;
2011             break;
2012         case TDS_DATA_TYPE_FLTN:
2013             length = tvb_get_guint8(tvb, *offset);
2014             length_item = proto_tree_add_uint(sub_tree, hf_tds_type_varbyte_length, tvb, *offset, 1, length);
2015             switch(length) {
2016                 case GEN_NULL: proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_null, tvb, *offset, 0, ENC_NA); break;
2017                 case 4: proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_float, tvb, *offset + 1, 4, ENC_LITTLE_ENDIAN); break;
2018                 case 8: proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_double, tvb, *offset + 1, 8, ENC_LITTLE_ENDIAN); break;
2019                 default: expert_add_info_format(pinfo, length_item, PI_MALFORMED, PI_ERROR, "Invalid length");
2020             }
2021             *offset += 1 + length;
2022             break;
2023         case TDS_DATA_TYPE_DECIMAL:         /* Decimal (legacy support) */
2024         case TDS_DATA_TYPE_NUMERIC:         /* Numeric (legacy support) */
2025         case TDS_DATA_TYPE_DECIMALN:        /* Decimal */
2026         case TDS_DATA_TYPE_NUMERICN:        /* Numeric */
2027         case TDS_DATA_TYPE_MONEYN:
2028         case TDS_DATA_TYPE_DATETIMN:
2029         case TDS_DATA_TYPE_DATEN:           /* (introduced in TDS 7.3) */
2030         case TDS_DATA_TYPE_TIMEN:           /* (introduced in TDS 7.3) */
2031         case TDS_DATA_TYPE_DATETIME2N:      /* (introduced in TDS 7.3) */
2032         case TDS_DATA_TYPE_DATETIMEOFFSETN: /* (introduced in TDS 7.3) */
2033         case TDS_DATA_TYPE_CHAR:            /* Char (legacy support) */
2034         case TDS_DATA_TYPE_VARCHAR:         /* VarChar (legacy support) */
2035         case TDS_DATA_TYPE_BINARY:          /* Binary (legacy support) */
2036         case TDS_DATA_TYPE_VARBINARY:       /* VarBinary (legacy support) */
2037             length = tvb_get_guint8(tvb, *offset);
2038             proto_tree_add_uint(sub_tree, hf_tds_type_varbyte_length, tvb, *offset, 1, length);
2039             *offset += 1;
2040             if(length > 0) {
2041                 proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_bytes, tvb, *offset, length, ENC_NA);
2042                 *offset += length;
2043             }
2044             break;
2045
2046         /* USHORTLEN_TYPE - types prefixed with 2-byte length */
2047         case TDS_DATA_TYPE_BIGVARBIN:       /* VarBinary */
2048         case TDS_DATA_TYPE_BIGBINARY:       /* Binary */
2049         case TDS_DATA_TYPE_BIGVARCHR:       /* VarChar */
2050         case TDS_DATA_TYPE_BIGCHAR:         /* Char */
2051         case TDS_DATA_TYPE_NVARCHAR:        /* NVarChar */
2052         case TDS_DATA_TYPE_NCHAR:           /* NChar */
2053             length = tvb_get_letohs(tvb, *offset);
2054             length_item = proto_tree_add_uint(sub_tree, hf_tds_type_varbyte_length, tvb, *offset, 2, length);
2055             *offset += 2;
2056             if(length == CHARBIN_NULL) {
2057                 proto_item_append_text(length_item, " (CHARBIN_NULL)");
2058                 proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_null, tvb, *offset, 0, ENC_NA);
2059             }
2060             else {
2061                 switch(data_type) {
2062                     case TDS_DATA_TYPE_BIGVARBIN: /* VarBinary */
2063                     case TDS_DATA_TYPE_BIGBINARY: /* Binary */
2064                         proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_bytes, tvb, *offset, length, ENC_NA);
2065                         break;
2066                     case TDS_DATA_TYPE_BIGVARCHR: /* VarChar */
2067                     case TDS_DATA_TYPE_BIGCHAR:   /* Char */
2068                         proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_string, tvb, *offset, length, ENC_ASCII|ENC_NA);
2069                         break;
2070                     case TDS_DATA_TYPE_NVARCHAR:  /* NVarChar */
2071                     case TDS_DATA_TYPE_NCHAR:     /* NChar */
2072                         string_value = tvb_get_ephemeral_unicode_string(tvb, *offset, length, ENC_LITTLE_ENDIAN);
2073                         proto_tree_add_string(sub_tree, hf_tds_type_varbyte_data_string, tvb, *offset, length, string_value);
2074                         break;
2075                     default:
2076                         DISSECTOR_ASSERT_NOT_REACHED();
2077                 }
2078                 *offset += length;
2079             }
2080             break;
2081
2082         /* LONGLEN_TYPE - types prefixed with 2-byte length */
2083         case TDS_DATA_TYPE_NTEXT:           /* NText */
2084         case TDS_DATA_TYPE_XML:             /* XML (introduced in TDS 7.2) */
2085         case TDS_DATA_TYPE_UDT:             /* CLR-UDT (introduced in TDS 7.2) */
2086         case TDS_DATA_TYPE_TEXT:            /* Text */
2087         case TDS_DATA_TYPE_IMAGE:           /* Image */
2088         case TDS_DATA_TYPE_SSVARIANT:       /* Sql_Variant (introduced in TDS 7.2) */
2089             length = tvb_get_letohl(tvb, *offset);
2090             length_item = proto_tree_add_uint(sub_tree, hf_tds_type_varbyte_length, tvb, *offset, 4, length);
2091             *offset += 4;
2092             if(length == CHARBIN_NULL32) {
2093                 proto_item_append_text(length_item, " (CHARBIN_NULL)");
2094                 proto_tree_add_item(sub_tree, hf_tds_type_varbyte_data_null, tvb, *offset, 0, ENC_NA);
2095             }
2096             else {
2097                 switch(data_type) {
2098                     case TDS_DATA_TYPE_NTEXT: /* NText */
2099                         string_value = tvb_get_ephemeral_unicode_string(tvb, *offset, length, ENC_LITTLE_ENDIAN);
2100                         proto_tree_add_string(sub_tree, hf_tds_type_varbyte_data_string, tvb, *offset, length, string_value);
2101                         break;
2102                     default: /*TODO*/
2103                         expert_add_info_format(pinfo, length_item, PI_UNDECODED, PI_ERROR, "Data type %d not supported yet", data_type);
2104                         /* No point in continuing: we need to parse the full data_type to know where it ends */
2105                         THROW(ReportedBoundsError);
2106                 }
2107                 *offset += length;
2108             }
2109             break;
2110     }
2111     proto_item_set_end(item, tvb, *offset);
2112 }
2113
2114 static void
2115 dissect_tds_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2116 {
2117     proto_item *item = NULL, *param_item = NULL;
2118     proto_tree *sub_tree = NULL, *status_sub_tree = NULL;
2119     int offset = 0;
2120     guint len;
2121     char *val;
2122     guint8 data_type;
2123
2124     item = proto_tree_add_item(tree, hf_tds_rpc, tvb, 0, -1, ENC_NA);
2125     tree = proto_item_add_subtree(item, ett_tds_message);
2126
2127     dissect_tds_all_headers(tvb, &offset, pinfo, tree);
2128     while(tvb_length_remaining(tvb, offset) > 0) {
2129         /*
2130          * RPC name.
2131          */
2132         switch(tds_protocol_type) {
2133             case TDS_PROTOCOL_4:
2134                 len = tvb_get_guint8(tvb, offset);
2135                 proto_tree_add_item(tree, hf_tds_rpc_name_length8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2136                 proto_tree_add_item(tree, hf_tds_rpc_name, tvb, offset + 1, len, ENC_ASCII|ENC_NA);
2137                 offset += 1 + len;
2138                 break;
2139
2140             case TDS_PROTOCOL_7_0:
2141             case TDS_PROTOCOL_7_1:
2142             case TDS_PROTOCOL_7_2:
2143             case TDS_PROTOCOL_7_3:
2144             default: /* unspecified: try as if TDS7 */
2145                 len = tvb_get_letohs(tvb, offset);
2146                 proto_tree_add_item(tree, hf_tds_rpc_name_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2147                 offset += 2;
2148                 if (len == 0xFFFF) {
2149                     proto_tree_add_item(tree, hf_tds_rpc_proc_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2150                     offset += 2;
2151                 }
2152                 else if (len != 0) {
2153                     len *= 2;
2154                     val = tvb_get_ephemeral_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN);
2155                     proto_tree_add_string(tree, hf_tds_rpc_name, tvb, offset, len, val);
2156                     offset += len;
2157                 }
2158                 break;
2159         }
2160         item = proto_tree_add_item(tree, hf_tds_rpc_options, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2161         sub_tree = proto_item_add_subtree(item, ett_tds_rpc_options);
2162         proto_tree_add_item(sub_tree, hf_tds_rpc_options_with_recomp, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2163         proto_tree_add_item(sub_tree, hf_tds_rpc_options_no_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2164         proto_tree_add_item(sub_tree, hf_tds_rpc_options_reuse_metadata, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2165         offset += 2;
2166
2167         /* dissect parameters */
2168         while(tvb_length_remaining(tvb, offset) > 0) {
2169             gboolean plp;
2170
2171             len = tvb_get_guint8(tvb, offset);
2172             /* check for BatchFlag or NoExecFlag */
2173             if((gint8)len < 0) {
2174                 proto_tree_add_item(tree, hf_tds_rpc_separator, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2175                 ++offset;
2176                 break;
2177             }
2178             param_item = proto_tree_add_item(tree, hf_tds_rpc_parameter, tvb, offset, 0, ENC_NA);
2179             sub_tree = proto_item_add_subtree(param_item, ett_tds_rpc_parameter);
2180             proto_tree_add_item(sub_tree, hf_tds_rpc_parameter_name_length, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2181             ++offset;
2182             if(len) {
2183                 len *= 2;
2184                 val = tvb_get_ephemeral_unicode_string(tvb, offset, len, ENC_LITTLE_ENDIAN);
2185                 proto_tree_add_string(sub_tree, hf_tds_rpc_parameter_name, tvb, offset, len, val);
2186                 offset += len;
2187             }
2188             item = proto_tree_add_item(sub_tree, hf_tds_rpc_parameter_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2189             status_sub_tree = proto_item_add_subtree(item, ett_tds_rpc_parameter_status);
2190             proto_tree_add_item(status_sub_tree, hf_tds_rpc_parameter_status_by_ref, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2191             proto_tree_add_item(status_sub_tree, hf_tds_rpc_parameter_status_default, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2192             ++offset;
2193             data_type = dissect_tds_type_info(tvb, &offset, pinfo, sub_tree, &plp);
2194             dissect_tds_type_varbyte(tvb, &offset, pinfo, sub_tree, hf_tds_rpc_parameter_value, data_type, plp);
2195             proto_item_set_end(param_item, tvb, offset);
2196         }
2197     }
2198 }
2199
2200 static void
2201 dissect_tds_resp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, tds_conv_info_t *tds_info)
2202 {
2203     int offset = 0;
2204     proto_item *token_item;
2205     proto_tree *token_tree;
2206     guint pos, token_sz = 0;
2207     guint token_len_field_size = 2;
2208     guint token_len_field_val = 0;
2209     guint8 token;
2210     struct _netlib_data nl_data;
2211     gint length_remaining;
2212
2213     memset(&nl_data, '\0', sizeof nl_data);
2214
2215     /*
2216      * Until we reach the end of the packet, read tokens.
2217      */
2218     pos = offset;
2219     while (tvb_reported_length_remaining(tvb, pos) > 0) {
2220         /* our token */
2221         token = tvb_get_guint8(tvb, pos);
2222
2223         /* TODO Handle TDS_PARAMFMT, TDS_PARAMS [similar to TDS_RESULTS, TDS_ROW] */
2224         if (tds_token_is_fixed_size(token)) {
2225             token_sz = tds_get_fixed_token_size(token, tds_info) + 1;
2226         } else if (token == TDS_ROW_TOKEN) {
2227             /*
2228              * Rows are special; they have no size field and
2229              * aren't fixed length.
2230              */
2231             token_sz = tds_get_row_size(tvb, &nl_data, pos + 1);
2232         } else
2233             token_sz = tds_get_variable_token_size(tvb, pos + 1,
2234                                                    token, &token_len_field_size, &token_len_field_val);
2235
2236         length_remaining = tvb_ensure_length_remaining(tvb, pos);
2237
2238         if ((int) token_sz < 0) {
2239             proto_tree_add_text(tree, tvb, pos, 0, "Bogus token size: %u",
2240                                 token_sz);
2241             break;
2242         }
2243         if ((int) token_len_field_size < 0) {
2244             proto_tree_add_text(tree, tvb, pos, 0, "Bogus token length field size: %u",
2245                                 token_len_field_size);
2246             break;
2247         }
2248         token_item = proto_tree_add_text(tree, tvb, pos, token_sz,
2249                                          "Token 0x%02x %s", token,
2250                                          val_to_str_const(token, token_names, "Unknown Token Type"));
2251         token_tree = proto_item_add_subtree(token_item, ett_tds_token);
2252
2253         /*
2254          * If it's a variable token, put the length field in here
2255          * instead of replicating this for each token subdissector.
2256          */
2257         if (!tds_token_is_fixed_size(token) && token != TDS_ROW_TOKEN) {
2258             proto_tree_add_text(token_tree, tvb, pos + 1,
2259                                 token_len_field_size, "Length: %u",
2260                                 token_len_field_val);
2261         }
2262
2263         if (token_sz > (guint)length_remaining)
2264             token_sz = (guint)length_remaining;
2265
2266         switch (token) {
2267
2268             case TDS_COL_NAME_TOKEN:
2269                 /*
2270                  * TDS 4.2
2271                  * TODO dissect token to get "column names" to fill in _netlib_data
2272                  */
2273                 break;
2274
2275             case TDS_COL_INFO_TOKEN:
2276                 /*
2277                  * TDS 4.2: get the column info
2278                  */
2279                 dissect_tds_col_info_token(tvb, &nl_data, pos);
2280                 break;
2281
2282             case TDS_RESULT_TOKEN:
2283                 /*
2284                  * If it's a result token, we need to stash the
2285                  * column info.
2286                  */
2287                 read_results_tds5(tvb, &nl_data, pos + 3, token_sz - 3);
2288                 break;
2289
2290             case TDS_ENV_CHG_TOKEN:
2291                 dissect_tds_env_chg(tvb, pos + 3, token_sz - 3, token_tree);
2292                 break;
2293
2294             case TDS_AUTH_TOKEN:
2295                 dissect_tds_nt(tvb, pinfo, token_tree, pos + 3, token_sz - 3);
2296                 break;
2297             case TDS_ERR_TOKEN:
2298             case TDS_MSG_TOKEN:
2299                 dissect_tds_err_token(tvb, pos + 3, token_sz - 3, token_tree, tds_info);
2300                 break;
2301
2302             case TDS_DONE_TOKEN:
2303             case TDS_DONEPROC_TOKEN:
2304             case TDS_DONEINPROC_TOKEN:
2305                 dissect_tds_done_token(tvb, pos + 1, token_tree, tds_info);
2306                 break;
2307             case TDS_LOGIN_ACK_TOKEN:
2308                 dissect_tds_login_ack_token(tvb, pos + 3, token_sz - 3, token_tree, tds_info);
2309                 break;
2310             case TDS7_RESULT_TOKEN:
2311                 pos = (dissect_tds7_results_token(tvb, pos + 1, token_tree, tds_info)-1);
2312                 break;
2313         }
2314
2315         /* and step to the end of the token, rinse, lather, repeat */
2316         pos += token_sz;
2317     }
2318 }
2319
2320 static void
2321 dissect_netlib_buffer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2322 {
2323     int offset = 0;
2324     proto_item *tds_item = NULL;
2325     proto_tree *tds_tree = NULL;
2326     proto_tree *tds_status_tree = NULL;
2327     guint8 type;
2328     guint8 status;
2329     guint16 channel;
2330     guint8 packet_number;
2331     gboolean save_fragmented;
2332     int len;
2333     fragment_data *fd_head;
2334     tvbuff_t *next_tvb;
2335     conversation_t *conv;
2336     tds_conv_info_t *tds_info;
2337
2338     conv = find_or_create_conversation(pinfo);
2339     tds_info = (tds_conv_info_t*)conversation_get_proto_data(conv, proto_tds);
2340     if (!tds_info) {
2341         tds_info = se_new(tds_conv_info_t);
2342         tds_info->tds7_version = TDS_PROTOCOL_NOT_SPECIFIED;
2343         conversation_add_proto_data(conv, proto_tds, tds_info);
2344     }
2345
2346     type = tvb_get_guint8(tvb, offset);
2347     status = tvb_get_guint8(tvb, offset + 1);
2348     channel = tvb_get_ntohs(tvb, offset + 4);
2349     packet_number = tvb_get_guint8(tvb, offset + 6);
2350
2351     /* create display subtree for the protocol */
2352     tds_item = proto_tree_add_item(tree, proto_tds, tvb, offset, -1, ENC_NA);
2353     tds_tree = proto_item_add_subtree(tds_item, ett_tds);
2354     proto_tree_add_item(tds_tree, hf_tds_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2355     tds_item = proto_tree_add_item(tds_tree, hf_tds_status, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
2356     tds_status_tree = proto_item_add_subtree(tds_item, ett_tds_status);
2357     proto_tree_add_item(tds_status_tree, hf_tds_status_eom, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
2358     proto_tree_add_item(tds_status_tree, hf_tds_status_ignore, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
2359     proto_tree_add_item(tds_status_tree, hf_tds_status_event_notif, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
2360     proto_tree_add_item(tds_status_tree, hf_tds_status_reset_conn, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
2361     proto_tree_add_item(tds_status_tree, hf_tds_status_reset_conn_skip_tran,tvb, offset + 1, 1, ENC_BIG_ENDIAN);
2362     proto_tree_add_item(tds_tree, hf_tds_length, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2363     proto_tree_add_item(tds_tree, hf_tds_channel, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
2364     proto_tree_add_item(tds_tree, hf_tds_packet_number, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
2365     proto_tree_add_item(tds_tree, hf_tds_window, tvb, offset + 7, 1, ENC_LITTLE_ENDIAN);
2366     offset += 8;        /* skip Netlib header */
2367
2368     /*
2369      * Deal with fragmentation.
2370      *
2371      * TODO: handle case where netlib headers 'packet-number'.is always 0
2372      *       use fragment_add_seq_next in this case ?
2373      *
2374      */
2375     save_fragmented = pinfo->fragmented;
2376     if (tds_defragment &&
2377         (packet_number > 1 || (status & STATUS_LAST_BUFFER) == 0)) {
2378         if ((status & STATUS_LAST_BUFFER) == 0) {
2379             col_append_str(pinfo->cinfo, COL_INFO,
2380                            " (Not last buffer)");
2381         }
2382         len = tvb_reported_length_remaining(tvb, offset);
2383         /*
2384          * XXX - I've seen captures that start with a login
2385          * packet with a sequence number of 2.
2386          */
2387         fd_head = fragment_add_seq_check(tvb, offset, pinfo, channel,
2388                                          tds_fragment_table, tds_reassembled_table,
2389                                          packet_number - 1, len, (status & STATUS_LAST_BUFFER) == 0);
2390         next_tvb = process_reassembled_data(tvb, offset, pinfo,
2391                                             "Reassembled TDS", fd_head, &tds_frag_items, NULL,
2392                                             tds_tree);
2393     } else {
2394         /*
2395          * If this isn't the last buffer, just show it as a fragment.
2396          * (XXX - it'd be nice to dissect it if it's the first
2397          * buffer, but we'd need to do reassembly in order to
2398          * discover that.)
2399          *
2400          * If this is the last buffer, dissect it.
2401          * (XXX - it'd be nice to show it as a fragment if it's part
2402          * of a fragmented message, but we'd need to do reassembly
2403          * in order to discover that.)
2404          */
2405         if ((status & STATUS_LAST_BUFFER) == 0)
2406             next_tvb = NULL;
2407         else {
2408             next_tvb = tvb_new_subset_remaining(tvb, offset);
2409         }
2410     }
2411
2412     if (next_tvb != NULL) {
2413
2414         switch (type) {
2415
2416             case TDS_RPC_PKT:
2417                 dissect_tds_rpc(next_tvb, pinfo, tds_tree);
2418                 break;
2419
2420             case TDS_RESP_PKT:
2421                 dissect_tds_resp(next_tvb, pinfo, tds_tree, tds_info);
2422                 break;
2423
2424             case TDS_LOGIN7_PKT:
2425                 dissect_tds7_login(next_tvb, pinfo, tds_tree);
2426                 break;
2427             case TDS_QUERY_PKT:
2428                 dissect_tds_query_packet(next_tvb, pinfo, tds_tree, tds_info);
2429                 break;
2430             case TDS_QUERY5_PKT:
2431                 dissect_tds_query5_packet(next_tvb, pinfo, tds_tree, tds_info);
2432                 break;
2433             case TDS_SSPI_PKT:
2434                 dissect_tds_nt(next_tvb, pinfo, tds_tree, offset - 8, -1);
2435                 break;
2436             default:
2437                 proto_tree_add_text(tds_tree, next_tvb, 0, -1,
2438                                     "TDS Packet");
2439                 break;
2440         }
2441     } else {
2442         next_tvb = tvb_new_subset_remaining (tvb, offset);
2443         call_dissector(data_handle, next_tvb, pinfo, tds_tree);
2444     }
2445     pinfo->fragmented = save_fragmented;
2446 }
2447
2448 static void
2449 dissect_tds_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2450 {
2451     volatile gboolean first_time = TRUE;
2452     volatile int offset = 0;
2453     guint length_remaining;
2454     guint8 type;
2455     guint16 plen;
2456     guint length;
2457     tvbuff_t *volatile next_tvb;
2458     proto_item *tds_item = NULL;
2459     proto_tree *tds_tree = NULL;
2460     void *pd_save;
2461
2462     while (tvb_reported_length_remaining(tvb, offset) != 0) {
2463         length_remaining = tvb_ensure_length_remaining(tvb, offset);
2464
2465         /*
2466          * Can we do reassembly?
2467          */
2468         if (tds_desegment && pinfo->can_desegment) {
2469             /*
2470              * Yes - is the fixed-length part of the PDU
2471              * split across segment boundaries?
2472              */
2473             if (length_remaining < 8) {
2474                 /*
2475                  * Yes.  Tell the TCP dissector where the data for this message
2476                  * starts in the data it handed us and that we need "some more
2477                  * data."  Don't tell it exactly how many bytes we need because
2478                  * if/when we ask for even more (after the header) that will
2479                  * break reassembly.
2480                  */
2481                 pinfo->desegment_offset = offset;
2482                 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
2483                 return;
2484             }
2485         }
2486
2487         type = tvb_get_guint8(tvb, offset);
2488
2489         /*
2490          * Get the length of the PDU.
2491          */
2492         plen = tvb_get_ntohs(tvb, offset + 2);
2493         if (plen < 8) {
2494             /*
2495              * The length is less than the header length.
2496              * Put in the type, status, and length, and
2497              * report the length as bogus.
2498              */
2499             if (tree) {
2500                 /* create display subtree for the protocol */
2501                 tds_item = proto_tree_add_item(tree, proto_tds,
2502                                                tvb, offset, -1, ENC_NA);
2503
2504                 tds_tree = proto_item_add_subtree(tds_item,
2505                                                   ett_tds);
2506                 proto_tree_add_uint(tds_tree, hf_tds_type, tvb,
2507                                     offset, 1, type);
2508                 proto_tree_add_item(tds_tree, hf_tds_status,
2509                                     tvb, offset + 1, 1, ENC_BIG_ENDIAN);
2510                 proto_tree_add_uint_format(tds_tree,
2511                                            hf_tds_length, tvb, offset + 2, 2, plen,
2512                                            "Size: %u (bogus, should be >= 8)", plen);
2513             }
2514
2515             /*
2516              * Give up - we can't dissect any more of this
2517              * data.
2518              */
2519             break;
2520         }
2521
2522         /*
2523          * Can we do reassembly?
2524          */
2525         if (tds_desegment && pinfo->can_desegment) {
2526             /*
2527              * Yes - is the PDU split across segment boundaries?
2528              */
2529             if (length_remaining < plen) {
2530                 /*
2531                  * Yes.  Tell the TCP dissector where the
2532                  * data for this message starts in the data
2533                  * it handed us, and how many more bytes we
2534                  * need, and return.
2535                  */
2536                 pinfo->desegment_offset = offset;
2537                 pinfo->desegment_len = plen - length_remaining;
2538                 return;
2539             }
2540         }
2541
2542         if (first_time) {
2543             col_set_str(pinfo->cinfo, COL_PROTOCOL, "TDS");
2544
2545             /*
2546              * Set the packet description based on its TDS packet
2547              * type.
2548              */
2549             col_add_str(pinfo->cinfo, COL_INFO,
2550                         val_to_str(type, packet_type_names,
2551                                    "Unknown Packet Type: %u"));
2552             first_time = FALSE;
2553         }
2554
2555         /*
2556          * Construct a tvbuff containing the amount of the payload
2557          * we have available.  Make its reported length the amount
2558          * of data in the PDU.
2559          *
2560          * XXX - if reassembly isn't enabled. the subdissector will
2561          * throw a BoundsError exception, rather than a
2562          * ReportedBoundsError exception.  We really want a tvbuff
2563          * where the length is "length", the reported length is
2564          * "plen", and the "if the snapshot length were infinite"
2565          * length is the minimum of the reported length of the tvbuff
2566          * handed to us and "plen", with a new type of exception
2567          * thrown if the offset is within the reported length but
2568          * beyond that third length, with that exception getting the
2569          * "Unreassembled Packet" error.
2570          */
2571         length = length_remaining;
2572         if (length > plen)
2573             length = plen;
2574         next_tvb = tvb_new_subset(tvb, offset, length, plen);
2575
2576         /*
2577          * Dissect the Netlib buffer.
2578          *
2579          * Catch the ReportedBoundsError exception; if this
2580          * particular Netlib buffer happens to get a
2581          * ReportedBoundsError exception, that doesn't mean
2582          * that we should stop dissecting PDUs within this frame
2583          * or chunk of reassembled data.
2584          *
2585          * If it gets a BoundsError, we can stop, as there's nothing
2586          * more to see, so we just re-throw it.
2587          */
2588         pd_save = pinfo->private_data;
2589         TRY {
2590             dissect_netlib_buffer(next_tvb, pinfo, tree);
2591         }
2592         CATCH(BoundsError) {
2593             RETHROW;
2594         }
2595         CATCH(ReportedBoundsError) {
2596             /*  Restore the private_data structure in case one of the
2597              *  called dissectors modified it (and, due to the exception,
2598              *  was unable to restore it).
2599              */
2600             pinfo->private_data = pd_save;
2601
2602             show_reported_bounds_error(tvb, pinfo, tree);
2603         }
2604         ENDTRY;
2605
2606         /*
2607          * Step to the next Netlib buffer.
2608          */
2609         offset += plen;
2610     }
2611 }
2612
2613 static gboolean
2614 dissect_tds_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2615 {
2616     int offset = 0;
2617     guint8 type;
2618     guint8 status;
2619     guint16 plen;
2620     conversation_t *conv;
2621
2622     /*
2623      * If we don't have even enough data for a Netlib header,
2624      * just say it's not TDS.
2625      */
2626     if (tvb_length(tvb) < 8)
2627         return FALSE;
2628
2629     /*
2630      * Quickly scan all the data we have in order to see if
2631      * everything in it looks like Netlib traffic.
2632      */
2633     while (tvb_bytes_exist(tvb, offset, 1)) {
2634         /*
2635          * Check the type field.
2636          */
2637         type = tvb_get_guint8(tvb, offset);
2638         if (!is_valid_tds_type(type))
2639             return FALSE;
2640
2641         /*
2642          * Check the status field, if it's present.
2643          */
2644         if (!tvb_bytes_exist(tvb, offset + 1, 1))
2645             break;
2646         status = tvb_get_guint8(tvb, offset + 1);
2647         if (!is_valid_tds_status(status))
2648             return FALSE;
2649
2650         /*
2651          * Get the length of the PDU.
2652          */
2653         if (!tvb_bytes_exist(tvb, offset + 2, 2))
2654             break;
2655         plen = tvb_get_ntohs(tvb, offset + 2);
2656         if (plen < 8) {
2657             /*
2658              * The length is less than the header length.
2659              * That's bogus.
2660              */
2661             return FALSE;
2662         }
2663
2664         /*
2665          * If we're at the beginning of the segment, check the
2666          * payload if it's a login packet.
2667          */
2668         if (offset == 0) {
2669             if (!netlib_check_login_pkt(tvb, offset, pinfo, type))
2670                 return FALSE;
2671         }
2672
2673         /*
2674          * Step to the next Netlib buffer.
2675          */
2676         offset += plen;
2677     }
2678
2679     /*
2680      * OK, it passes the test; assume the rest of this conversation
2681      * is TDS.
2682      */
2683     conv = find_or_create_conversation(pinfo);
2684     conversation_set_dissector(conv, tds_tcp_handle);
2685
2686     /*
2687      * Now dissect it as TDS.
2688      */
2689     dissect_tds_tcp(tvb, pinfo, tree);
2690     return TRUE;
2691 }
2692
2693 static void
2694 tds_init(void)
2695 {
2696     /*
2697      * Initialize the fragment and reassembly tables.
2698      */
2699     fragment_table_init(&tds_fragment_table);
2700     reassembled_table_init(&tds_reassembled_table);
2701
2702 }
2703
2704 /* Register the protocol with Wireshark */
2705
2706 /* this format is required because a script is used to build the C function
2707    that calls all the protocol registration.
2708 */
2709
2710 void
2711 proto_register_tds(void)
2712 {
2713     static hf_register_info hf[] = {
2714         { &hf_tds_type,
2715           { "Type",             "tds.type",
2716             FT_UINT8, BASE_DEC, VALS(packet_type_names), 0x0,
2717             "Packet type", HFILL }
2718         },
2719         { &hf_tds_status,
2720           { "Status",           "tds.status",
2721             FT_UINT8, BASE_HEX, NULL, 0x0,
2722             "Packet status", HFILL }
2723         },
2724         { &hf_tds_status_eom,
2725           { "End of message",   "tds.status.eom",
2726             FT_BOOLEAN, 8, NULL, STATUS_LAST_BUFFER,
2727             "The packet is the last packet in the whole request", HFILL }
2728         },
2729         { &hf_tds_status_ignore,
2730           { "Ignore this event", "tds.status.ignore",
2731             FT_BOOLEAN, 8, NULL, STATUS_IGNORE_EVENT,
2732             "(From client to server) Ignore this event (EOM MUST also be set)", HFILL }
2733         },
2734         { &hf_tds_status_event_notif,
2735           { "Event notification", "tds.status.event_notif",
2736             FT_BOOLEAN, 8, NULL, STATUS_EVENT_NOTIFICATION,
2737             NULL, HFILL }
2738         },
2739         { &hf_tds_status_reset_conn,
2740           { "Reset connection", "tds.status.reset_conn",
2741             FT_BOOLEAN, 8, NULL, STATUS_RESETCONNECTION,
2742             "(From client to server) Reset this connection before processing event", HFILL }
2743         },
2744         { &hf_tds_status_reset_conn_skip_tran,
2745           { "Reset connection keeping transaction state", "tds.status.reset_conn_skip_tran",
2746             FT_BOOLEAN, 8, NULL, STATUS_RESETCONNECTIONSKIPTRAN,
2747             "(From client to server) Reset the connection before processing event but do not modify the transaction state", HFILL }
2748         },
2749         { &hf_tds_length,
2750           { "Length",           "tds.length",
2751             FT_UINT16, BASE_DEC, NULL, 0x0,
2752             "Packet length", HFILL }
2753         },
2754         { &hf_tds_channel,
2755           { "Channel",          "tds.channel",
2756             FT_UINT16, BASE_DEC, NULL, 0x0,
2757             "Channel Number", HFILL }
2758         },
2759         { &hf_tds_packet_number,
2760           { "Packet Number",    "tds.packet_number",
2761             FT_UINT8, BASE_DEC, NULL, 0x0,
2762             NULL, HFILL }
2763         },
2764         { &hf_tds_window,
2765           { "Window",           "tds.window",
2766             FT_UINT8, BASE_DEC, NULL, 0x0,
2767             NULL, HFILL }
2768         },
2769         { &hf_tds_fragment_overlap,
2770           { "Segment overlap",  "tds.fragment.overlap",
2771             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2772             "Fragment overlaps with other fragments", HFILL }
2773         },
2774         { &hf_tds_fragment_overlap_conflict,
2775           { "Conflicting data in fragment overlap", "tds.fragment.overlap.conflict",
2776             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2777             "Overlapping fragments contained conflicting data", HFILL }
2778         },
2779         { &hf_tds_fragment_multiple_tails,
2780           { "Multiple tail fragments found", "tds.fragment.multipletails",
2781             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2782             "Several tails were found when defragmenting the packet", HFILL }
2783         },
2784         { &hf_tds_fragment_too_long_fragment,
2785           { "Segment too long", "tds.fragment.toolongfragment",
2786             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2787             "Segment contained data past end of packet", HFILL }
2788         },
2789         { &hf_tds_fragment_error,
2790           { "Defragmentation error",    "tds.fragment.error",
2791             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2792             "Defragmentation error due to illegal fragments", HFILL }
2793         },
2794         { &hf_tds_fragment_count,
2795           { "Segment count", "tds.fragment.count",
2796             FT_UINT32, BASE_DEC, NULL, 0x0,
2797             NULL, HFILL }
2798         },
2799         { &hf_tds_fragment,
2800           { "TDS Fragment",     "tds.fragment",
2801             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2802             NULL, HFILL }
2803         },
2804         { &hf_tds_fragments,
2805           { "TDS Fragments",    "tds.fragments",
2806             FT_NONE, BASE_NONE, NULL, 0x0,
2807             NULL, HFILL }
2808         },
2809         { &hf_tds_reassembled_in,
2810           { "Reassembled TDS in frame", "tds.reassembled_in",
2811             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2812             "This TDS packet is reassembled in this frame", HFILL }
2813         },
2814         { &hf_tds_reassembled_length,
2815           { "Reassembled TDS length", "tds.reassembled.length",
2816             FT_UINT32, BASE_DEC, NULL, 0x0,
2817             "The total length of the reassembled payload", HFILL }
2818         },
2819         { &hf_tds7_login_total_size,
2820           { "Total Packet Length", "tds.7login.total_len",
2821             FT_UINT32, BASE_DEC, NULL, 0x0,
2822             "TDS7 Login Packet total packet length", HFILL }
2823         },
2824         { &hf_tds7_version,
2825           { "TDS version", "tds.7login.version",
2826             FT_UINT32, BASE_HEX, NULL, 0x0,
2827             NULL, HFILL }
2828         },
2829         { &hf_tds7_packet_size,
2830           { "Packet Size", "tds.7login.packet_size",
2831             FT_UINT32, BASE_DEC, NULL, 0x0,
2832             NULL, HFILL }
2833         },
2834         { &hf_tds7_client_version,
2835           { "Client version", "tds.7login.client_version",
2836             FT_UINT32, BASE_DEC, NULL, 0x0,
2837             NULL, HFILL }
2838         },
2839         { &hf_tds7_client_pid,
2840           { "Client PID", "tds.7login.client_pid",
2841             FT_UINT32, BASE_DEC, NULL, 0x0,
2842             NULL, HFILL }
2843         },
2844         { &hf_tds7_connection_id,
2845           { "Connection ID", "tds.7login.connection_id",
2846             FT_UINT32, BASE_DEC, NULL, 0x0,
2847             NULL, HFILL }
2848         },
2849         { &hf_tds7_option_flags1,
2850           { "Option Flags 1", "tds.7login.option_flags1",
2851             FT_UINT8, BASE_HEX, NULL, 0x0,
2852             NULL, HFILL }
2853         },
2854         { &hf_tds7_option_flags2,
2855           { "Option Flags 2", "tds.7login.option_flags2",
2856             FT_UINT8, BASE_HEX, NULL, 0x0,
2857             NULL, HFILL }
2858         },
2859         { &hf_tds7_sql_type_flags,
2860           { "SQL Type Flags", "tds.7login.sql_type_flags",
2861             FT_UINT8, BASE_HEX, NULL, 0x0,
2862             NULL, HFILL }
2863         },
2864         { &hf_tds7_reserved_flags,
2865           { "Reserved Flags", "tds.7login.reserved_flags",
2866             FT_UINT8, BASE_HEX, NULL, 0x0,
2867             NULL, HFILL }
2868         },
2869         { &hf_tds7_time_zone,
2870           { "Time Zone", "tds.7login.time_zone",
2871             FT_UINT32, BASE_HEX, NULL, 0x0,
2872             NULL, HFILL }
2873         },
2874         { &hf_tds7_collation,
2875           { "Collation", "tds.7login.collation",
2876             FT_UINT32, BASE_HEX, NULL, 0x0,
2877             NULL, HFILL }
2878         },
2879         { &hf_tds7_loginack_version,
2880           { "TDS version", "tds.7loginack.version",
2881             FT_UINT32, BASE_HEX, NULL, 0x0,
2882             NULL, HFILL }
2883         },
2884         { &hf_tds_all_headers,
2885           { "Packet data stream headers", "tds.all_headers",
2886             FT_NONE, BASE_NONE, NULL, 0x0,
2887             "The ALL_HEADERS rule", HFILL }
2888         },
2889         { &hf_tds_all_headers_total_length,
2890           { "Total length",     "tds.all_headers.total_length",
2891             FT_UINT32, BASE_DEC, NULL, 0x0,
2892             "Total length of ALL_HEADERS stream", HFILL }
2893         },
2894         { &hf_tds_all_headers_header_length,
2895           { "Length",           "tds.all_headers.header.length",
2896             FT_UINT32, BASE_DEC, NULL, 0x0,
2897             "Total length of an individual header", HFILL }
2898         },
2899         { &hf_tds_all_headers_header_type,
2900           { "Type",             "tds.all_headers.header.type",
2901             FT_UINT16, BASE_HEX, VALS(header_type_names), 0x0,
2902             NULL, HFILL }
2903         },
2904         { &hf_tds_all_headers_trans_descr,
2905           { "Transaction descriptor", "tds.all_headers.header.trans_descr",
2906             FT_UINT64, BASE_DEC, NULL, 0x0,
2907             "For each connection, a number that uniquely identifies the transaction the request is associated with. Initially generated by the server when a new transaction is created and returned to the client as part of the ENVCHANGE token stream.", HFILL }
2908         },
2909         { &hf_tds_all_headers_request_cnt,
2910           { "Outstanding request count", "tds.all_headers.header.request_cnt",
2911             FT_UINT32, BASE_DEC, NULL, 0x0,
2912             "Number of requests currently active on the connection", HFILL }
2913         },
2914         { &hf_tds_type_info,
2915           { "Type info",        "tds.type_info",
2916             FT_NONE, BASE_NONE, NULL, 0x0,
2917             "The TYPE_INFO rule applies to several messages used to describe column information", HFILL }
2918         },
2919         { &hf_tds_type_info_type,
2920           { "Type",             "tds.type_info.type",
2921             FT_UINT8, BASE_HEX, VALS(tds_data_type_names), 0x0,
2922             NULL, HFILL }
2923         },
2924         { &hf_tds_type_info_varlen,
2925           { "Maximal length",   "tds.type_info.varlen",
2926             FT_UINT32, BASE_DEC, NULL, 0x0,
2927             "Defines the length of the data contained within the column", HFILL }
2928         },
2929         { &hf_tds_type_info_precision,
2930           { "Precision",        "tds.type_info.precision",
2931             FT_UINT8, BASE_DEC, NULL, 0x0,
2932             NULL, HFILL }
2933         },
2934         { &hf_tds_type_info_scale,
2935           { "Scale",            "tds.type_info.scale",
2936             FT_UINT8, BASE_DEC, NULL, 0x0,
2937             NULL, HFILL }
2938         },
2939         { &hf_tds_type_info_collation,
2940           { "Collation",        "tds.type_info.collation",
2941             FT_NONE, BASE_NONE, NULL, 0x0,
2942             "Specifies collation information for character data or metadata describing character data", HFILL }
2943         },
2944         { &hf_tds_type_info_collation_lcid,
2945           { "LCID",             "tds.type_info.collation.lcid",
2946             FT_UINT32, BASE_HEX, NULL, 0x000FFFFF,
2947             "For a SortId==0 collation, the LCID bits correspond to a LocaleId as defined by the National Language Support (NLS) functions", HFILL }
2948         },
2949         { &hf_tds_type_info_collation_ign_case,
2950           { "Ignore case",      "tds.type_info.collation.ignore_case",
2951             FT_BOOLEAN, 32, NULL, 0x00100000,
2952             NULL, HFILL }
2953         },
2954         { &hf_tds_type_info_collation_ign_accent,
2955           { "Ignore accent",    "tds.type_info.collation.ignore_accent",
2956             FT_BOOLEAN, 32, NULL, 0x00200000,
2957             NULL, HFILL }
2958         },
2959         { &hf_tds_type_info_collation_ign_kana,
2960           { "Ignore kana",      "tds.type_info.collation.ignore_kana",
2961             FT_BOOLEAN, 32, NULL, 0x00400000,
2962             NULL, HFILL }
2963         },
2964         { &hf_tds_type_info_collation_ign_width,
2965           { "Ignore width",     "tds.type_info.collation.ignore_width",
2966             FT_BOOLEAN, 32, NULL, 0x00800000,
2967             NULL, HFILL }
2968         },
2969         { &hf_tds_type_info_collation_binary,
2970           { "Binary",           "tds.type_info.collation.binary",
2971             FT_BOOLEAN, 32, NULL, 0x01000000,
2972             NULL, HFILL }
2973         },
2974         { &hf_tds_type_info_collation_version,
2975           { "Version",          "tds.type_info.collation.version",
2976             FT_UINT32, BASE_DEC, NULL, 0xF0000000,
2977             NULL, HFILL }
2978         },
2979         { &hf_tds_type_info_collation_sortid,
2980           { "SortId",           "tds.type_info.collation.sortid",
2981             FT_UINT8, BASE_DEC, NULL, 0x0,
2982             NULL, HFILL }
2983         },
2984         { &hf_tds_type_varbyte_length,
2985           { "Length",           "tds.type_varbyte.length",
2986             FT_UINT32, BASE_DEC, NULL, 0x0,
2987             NULL, HFILL }
2988         },
2989         { &hf_tds_type_varbyte_data_null,
2990           { "Data: NULL",       "tds.type_varbyte.data.null",
2991             FT_NONE, BASE_NONE, NULL, 0x0,
2992             NULL, HFILL }
2993         },
2994         { &hf_tds_type_varbyte_data_boolean,
2995           { "Data",             "tds.type_varbyte.data.bool",
2996             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2997             NULL, HFILL }
2998         },
2999         { &hf_tds_type_varbyte_data_int1,
3000           { "Data",             "tds.type_varbyte.data.int",
3001             FT_INT8, BASE_DEC, NULL, 0x0,
3002             NULL, HFILL }
3003         },
3004         { &hf_tds_type_varbyte_data_int2,
3005           { "Data",             "tds.type_varbyte.data.int",
3006             FT_INT16, BASE_DEC, NULL, 0x0,
3007             NULL, HFILL }
3008         },
3009         { &hf_tds_type_varbyte_data_int4,
3010           { "Data",             "tds.type_varbyte.data.int",
3011             FT_INT32, BASE_DEC, NULL, 0x0,
3012             NULL, HFILL }
3013         },
3014         { &hf_tds_type_varbyte_data_int8,
3015           { "Data",             "tds.type_varbyte.data.int64",
3016             FT_INT64, BASE_DEC, NULL, 0x0,
3017             NULL, HFILL }
3018         },
3019         { &hf_tds_type_varbyte_data_float,
3020           { "Data",             "tds.type_varbyte.data.float",
3021             FT_FLOAT, BASE_NONE, NULL, 0x0,
3022             NULL, HFILL }
3023         },
3024         { &hf_tds_type_varbyte_data_double,
3025           { "Data",             "tds.type_varbyte.data.float",
3026             FT_DOUBLE, BASE_NONE, NULL, 0x0,
3027             NULL, HFILL }
3028         },
3029         { &hf_tds_type_varbyte_data_bytes,
3030           { "Data",             "tds.type_varbyte.data.bytes",
3031             FT_BYTES, BASE_NONE, NULL, 0x0,
3032             NULL, HFILL }
3033         },
3034         { &hf_tds_type_varbyte_data_guid,
3035           { "Data",             "tds.type_varbyte.data.guid",
3036             FT_GUID, BASE_NONE, NULL, 0x0,
3037             NULL, HFILL }
3038         },
3039         { &hf_tds_type_varbyte_data_string,
3040           { "Data",             "tds.type_varbyte.data.string",
3041             FT_STRING, BASE_NONE, NULL, 0x0,
3042             NULL, HFILL }
3043         },
3044         { &hf_tds_type_varbyte_plp_len,
3045           { "PLP length",       "tds.type_varbyte.plp_len",
3046             FT_INT64, BASE_DEC, NULL, 0x0,
3047             NULL, HFILL }
3048         },
3049         { &hf_tds_type_varbyte_plp_chunk_len,
3050           { "PLP chunk length", "tds.type_varbyte.plp_chunk_len",
3051             FT_INT32, BASE_DEC, NULL, 0x0,
3052             NULL, HFILL }
3053         },
3054         { &hf_tds_rpc,
3055           { "Remote Procedure Call", "tds.rpc",
3056             FT_NONE, BASE_NONE, NULL, 0x0,
3057             NULL, HFILL }
3058         },
3059         { &hf_tds_rpc_name_length8,
3060           { "Procedure name length", "tds.rpc.name_length",
3061             FT_UINT8, BASE_DEC, NULL, 0x0,
3062             NULL, HFILL }
3063         },
3064         { &hf_tds_rpc_name_length,
3065           { "Procedure name length", "tds.rpc.name_length",
3066             FT_UINT16, BASE_DEC, NULL, 0x0,
3067             NULL, HFILL }
3068         },
3069         { &hf_tds_rpc_name,
3070           { "Procedure name",   "tds.rpc.name",
3071             FT_STRING, BASE_NONE, NULL, 0x0,
3072             NULL, HFILL }
3073         },
3074         { &hf_tds_rpc_proc_id,
3075           { "Stored procedure ID", "tds.rpc.proc_id",
3076             FT_UINT16, BASE_DEC, VALS(internal_stored_proc_id_names), 0x0,
3077             "The number identifying the special stored procedure to be executed", HFILL }
3078         },
3079         { &hf_tds_rpc_options,
3080           { "Option flags",     "tds.rpc.options",
3081             FT_UINT16, BASE_HEX, NULL, 0x0,
3082             "The number identifying the special stored procedure to be executed", HFILL }
3083         },
3084         { &hf_tds_rpc_options_with_recomp,
3085           { "With recompile",   "tds.rpc.options.with_recomp",
3086             FT_BOOLEAN, 16, NULL, TDS_RPC_OPT_WITH_RECOMP,
3087             "The number identifying the special stored procedure to be executed", HFILL }
3088         },
3089         { &hf_tds_rpc_options_no_metadata,
3090           { "No metadata",      "tds.rpc.options.no_metadata",
3091             FT_BOOLEAN, 16, NULL, TDS_RPC_OPT_NO_METADATA,
3092             "The number identifying the special stored procedure to be executed", HFILL }
3093         },
3094         { &hf_tds_rpc_options_reuse_metadata,
3095           { "Reuse metadata",   "tds.rpc.options.reuse_metadata",
3096             FT_BOOLEAN, 16, NULL, TDS_RPC_OPT_REUSE_METADATA,
3097             "The number identifying the special stored procedure to be executed", HFILL }
3098         },
3099         { &hf_tds_rpc_separator,
3100           { "RPC batch separator", "tds.rpc.separator",
3101             FT_UINT8, BASE_DEC, VALS(tds_rpc_separators), 0x0,
3102             NULL, HFILL }
3103         },
3104         { &hf_tds_rpc_parameter,
3105           { "Parameter",        "tds.rpc.parameter",
3106             FT_NONE, BASE_NONE, NULL, 0x0,
3107             NULL, HFILL }
3108         },
3109         { &hf_tds_rpc_parameter_name_length,
3110           { "Name length",      "tds.rpc.parameter.name_length",
3111             FT_UINT8, BASE_DEC, NULL, 0x0,
3112             NULL, HFILL }
3113         },
3114         { &hf_tds_rpc_parameter_name,
3115           { "Name",             "tds.rpc.parameter.name",
3116             FT_STRING, BASE_NONE, NULL, 0x0,
3117             NULL, HFILL }
3118         },
3119         { &hf_tds_rpc_parameter_status,
3120           { "Status flags",     "tds.rpc.parameter.status",
3121             FT_UINT8, BASE_HEX, NULL, 0x0,
3122             "Information on how the parameter is passed", HFILL }
3123         },
3124         { &hf_tds_rpc_parameter_status_by_ref,
3125           { "By reference",     "tds.rpc.parameter.status.by_ref",
3126             FT_BOOLEAN, 16, NULL, TDS_RPC_PARAMETER_STATUS_BY_REF,
3127             NULL, HFILL }
3128         },
3129         { &hf_tds_rpc_parameter_status_default,
3130           { "Default value",    "tds.rpc.parameter.status.default",
3131             FT_BOOLEAN, 16, NULL, TDS_RPC_PARAMETER_STATUS_DEFAULT,
3132             NULL, HFILL }
3133         },
3134         { &hf_tds_rpc_parameter_value,
3135           { "Value",            "tds.rpc.parameter.value",
3136             FT_NONE, BASE_NONE, NULL, 0x0,
3137             NULL, HFILL }
3138         },
3139     };
3140
3141     static gint *ett[] = {
3142         &ett_tds,
3143         &ett_tds_status,
3144         &ett_tds_fragments,
3145         &ett_tds_fragment,
3146         &ett_tds_all_headers,
3147         &ett_tds_all_headers_header,
3148         &ett_tds_type_info,
3149         &ett_tds_type_info_collation,
3150         &ett_tds_type_varbyte,
3151         &ett_tds_message,
3152         &ett_tds_rpc_options,
3153         &ett_tds_rpc_parameter,
3154         &ett_tds_rpc_parameter_status,
3155         &ett_tds_token,
3156         &ett_tds7_query,
3157         &ett_tds7_login,
3158         &ett_tds7_hdr,
3159     };
3160     module_t *tds_module;
3161
3162 /* Register the protocol name and description */
3163     proto_tds = proto_register_protocol("Tabular Data Stream",
3164                                         "TDS", "tds");
3165
3166 /* Required function calls to register the header fields and subtrees used */
3167     proto_register_field_array(proto_tds, hf, array_length(hf));
3168     proto_register_subtree_array(ett, array_length(ett));
3169
3170 /* Allow dissector to be found by name. */
3171     register_dissector("tds", dissect_tds_tcp, proto_tds);
3172
3173     tds_module = prefs_register_protocol(proto_tds, NULL);
3174     prefs_register_bool_preference(tds_module, "desegment_buffers",
3175                                    "Reassemble TDS buffers spanning multiple TCP segments",
3176                                    "Whether the TDS dissector should reassemble TDS buffers spanning multiple TCP segments. "
3177                                    "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
3178                                    &tds_desegment);
3179     prefs_register_bool_preference(tds_module, "defragment",
3180                                    "Reassemble fragmented TDS messages with multiple buffers",
3181                                    "Whether the TDS dissector should defragment messages spanning multiple Netlib buffers",
3182                                    &tds_defragment);
3183     prefs_register_enum_preference(tds_module, "protocol_type",
3184                                    "TDS Protocol Type",
3185                                    "Hint as to version of TDS protocol being decoded",
3186                                    &tds_protocol_type, tds_protocol_type_options, FALSE);
3187     prefs_register_enum_preference(tds_module, "endian_type",
3188                                    "TDS decode as",
3189                                    "Hint as to whether to decode TDS protocol as little-endian or big-endian. (TDS7/8 always decoded as little-endian)",
3190                                    &tds_little_endian, tds_endian_type_options, FALSE);
3191     prefs_register_range_preference(tds_module, "tcp_ports",
3192                                     "TDS TCP ports",
3193                                     "Additional TCP ports to decode as TDS",
3194                                     &tds_tcp_ports, 0xFFFF);
3195
3196     register_init_routine(tds_init);
3197 }
3198
3199 /* If this dissector uses sub-dissector registration add a registration routine.
3200    This format is required because a script is used to find these routines and
3201    create the code that calls these routines.
3202 */
3203 void
3204 proto_reg_handoff_tds(void)
3205 {
3206     tds_tcp_handle = create_dissector_handle(dissect_tds_tcp, proto_tds);
3207
3208     /* Initial TDS ports: MS SQL default ports */
3209     dissector_add_uint("tcp.port", 1433, tds_tcp_handle);
3210     dissector_add_uint("tcp.port", 2433, tds_tcp_handle);
3211
3212     heur_dissector_add("tcp", dissect_tds_tcp_heur, proto_tds);
3213
3214     ntlmssp_handle = find_dissector("ntlmssp");
3215     gssapi_handle = find_dissector("gssapi");
3216     data_handle = find_dissector("data");
3217 }