From Todd Sabin: allocate the buffer for the decrypted payload, rather
[obnox/wireshark/wip.git] / 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: packet-tds.c,v 1.11 2003/03/04 06:47:10 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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://download.nai.com/products/media/sniffer/support/sdos/sybase.pdf
76  *
77  * Much of this code was originally developed for the FreeTDS project.
78  * http://www.freetds.org
79  */
80
81 /*
82  * Excerpts from Brian's posting to ethereal-dev:
83  *
84  * The TDS Protocol is actually a protocol within a protocol.  On the outside
85  * there is netlib which is not so much a encapsulation as a blocking of the
86  * data, typically to 512 or 4096 bytes.  Between this are the protocol data
87  * units for TDS.  Netlib packets may be split over real packets, multiple
88  * netlib packets may appear in single real packets.  TDS PDUs may be split
89  * over netlib packets (and real packets) and most certainly can appear
90  * multiple times within a netlib packet.
91  *
92  * Because of this, I abandoned my earlier attempt at making two dissectors,
93  * one for netlib and one for TDS. Counterintuitively, a single dissector
94  * turned out to be simpler than splitting it up.
95  *
96  * Here are some of the (hefty) limitations of the current code
97  *
98  * . We currently do not handle netlib headers that cross packet boundaries.
99  *   This should be an easy fix.
100  * . I probably could have used the packet reassembly stuff, but I started
101  *   this at version 0.8.20, so c'est la vie. It wouldn't have covered the
102  *   netlib stuff anyway, so no big loss.
103  * . The older two layer version of the code dissected the PDU's, but the new
104  *   version does not yet, it only labels the names. I need an elegant way to
105  *   deal with dissecting data crossing (netlib and tcp) packet boundries.  I
106  *   think I have one, but ran out of time to do it.
107  * . It will only work on little endian platforms.  Or rather I should say,
108  *   the client that was captured must be little endian.  TDS 7.0/8.0 is
109  *   always LE; for TDS 4.2/5.0 look in the code for tvb_get_le*() functions,
110  *   there are fields in the login packet which determine byte order.
111  * . result sets that span netlib packets are not working
112  * . TDS 7 and 4.2 result sets are not working yet
113  *
114  * All that said, the code does deal gracefully with different boudary
115  * conditions and what remains are the easier bits, IMHO.
116  *
117  * XXX - "real packets" means "TCP segments", for TCP.
118  *
119  * XXX - is it *REALLY* true that you can have more than one TDS PDU (as
120  * opposed to more than one server response item) per NETLIB packet?  Or is
121  * all the data in a NETLIB packet put into a single TDS PDU?  If so, then
122  * we can reassemble NETLIB packets using the standard TCP desegmentation
123  * code, and can reassemble TDS PDUs using "fragment_add_seq_next()",
124  * and more cleanly separate the NETLIB and TDS dissectors (although the
125  * "is this NETLIB" heuristic would have to look at TDS information past
126  * the NETLIB header, in order to make the heuristic strong enough not
127  * to get too many false positives; note that the heuristic should reject
128  * any putative NETLIB packet with a length field with a value < 8).
129  *
130  * That would substantially clean the dissector up, eliminating most of
131  * the per-packet data (we might still need information to handle
132  * TDS_ROW_TOKEN), getting rid of the stuff to handle data split across
133  * TCP segment boundaries in favor of simple reassembly code, and
134  * fixing some otherwise nasty-looking crashing bugs.
135  */
136
137 #ifdef HAVE_CONFIG_H
138 # include "config.h"
139 #endif
140
141 #include <stdio.h>
142 #include <stdlib.h>
143 #include <string.h>
144 #include <ctype.h>
145
146 #include <glib.h>
147
148 #include <epan/packet.h>
149 #include <epan/conversation.h>
150
151 #include "packet-smb-common.h"
152 #include "packet-frame.h"
153 #include "reassemble.h"
154 #include "prefs.h"
155
156 #define TDS_QUERY_PKT        1
157 #define TDS_LOGIN_PKT        2
158 #define TDS_RPC_PKT          3
159 #define TDS_RESP_PKT         4
160 #define TDS_RAW_PKT          5
161 #define TDS_CANCEL_PKT       6
162 #define TDS_BULK_DATA_PKT    7
163 #define TDS_OPEN_CHN_PKT     8
164 #define TDS_CLOSE_CHN_PKT    9
165 #define TDS_RES_ERROR_PKT   10
166 #define TDS_LOG_CHN_ACK_PKT 11
167 #define TDS_ECHO_PKT        12
168 #define TDS_LOGOUT_CHN_PKT  13
169 #define TDS_QUERY5_PKT      15  /* or "Normal tokenized request or response */
170 #define TDS_LOGIN7_PKT      16  /* or "Urgent tokenized request or response */
171 #define TDS_XXX7_PKT        18  /* seen in one capture */
172
173 #define is_valid_tds_type(x) ((x) >= TDS_QUERY_PKT && (x) <= TDS_XXX7_PKT)
174
175 /* The following constants are imported more or less directly from FreeTDS */
176
177 #define TDS5_DYN_TOKEN      231  /* 0xE7    TDS 5.0 only              */
178 #define TDS5_DYNRES_TOKEN   236  /* 0xEC    TDS 5.0 only              */
179 #define TDS5_DYN3_TOKEN     215  /* 0xD7    TDS 5.0 only              */
180 #define TDS_LANG_TOKEN       33  /* 0x21    TDS 5.0 only              */
181 #define TDS_CLOSE_TOKEN     113  /* 0x71    TDS 5.0 only? ct_close()  */
182 #define TDS_RET_STAT_TOKEN  121  /* 0x79                              */
183 #define TDS_124_TOKEN       124  /* 0x7C    TDS 4.2 only - TDS_PROCID */
184 #define TDS7_RESULT_TOKEN   129  /* 0x81    TDS 7.0 only              */
185 #define TDS_COL_NAME_TOKEN  160  /* 0xA0    TDS 4.2 only              */
186 #define TDS_COL_INFO_TOKEN  161  /* 0xA1    TDS 4.2 only - TDS_COLFMT */
187 /*#define  TDS_TABNAME   164 */
188 /*#define  TDS_COL_INFO   165 */
189 #define TDS_167_TOKEN       167  /* 0xA7                              */
190 #define TDS_168_TOKEN       168  /* 0xA8                              */
191 #define TDS_ORDER_BY_TOKEN  169  /* 0xA9    TDS_ORDER                 */
192 #define TDS_ERR_TOKEN       170  /* 0xAA                              */
193 #define TDS_MSG_TOKEN       171  /* 0xAB                              */
194 #define TDS_PARAM_TOKEN     172  /* 0xAC    RETURNVALUE?              */
195 #define TDS_LOGIN_ACK_TOKEN 173  /* 0xAD                              */
196 #define TDS_174_TOKEN       174  /* 0xAE    TDS_CONTROL               */
197 #define TDS_ROW_TOKEN       209  /* 0xD1                              */
198 #define TDS_CMP_ROW_TOKEN   211  /* 0xD3                              */
199 #define TDS_CAP_TOKEN       226  /* 0xE2                              */
200 #define TDS_ENV_CHG_TOKEN   227  /* 0xE3                              */
201 #define TDS_EED_TOKEN       229  /* 0xE5                              */
202 #define TDS_AUTH_TOKEN      237  /* 0xED                              */
203 #define TDS_RESULT_TOKEN    238  /* 0xEE                              */
204 #define TDS_DONE_TOKEN      253  /* 0xFD    TDS_DONE                  */
205 #define TDS_DONEPROC_TOKEN  254  /* 0xFE    TDS_DONEPROC              */
206 #define TDS_DONEINPROC_TOKEN 255  /* 0xFF    TDS_DONEINPROC            */
207
208 #define SYBCHAR      47   /* 0x2F */
209 #define SYBVARCHAR   39   /* 0x27 */
210 #define SYBINTN      38   /* 0x26 */
211 #define SYBINT1      48   /* 0x30 */
212 #define SYBINT2      52   /* 0x34 */
213 #define SYBINT4      56   /* 0x38 */
214 #define SYBINT8     127   /* 0x7F */
215 #define SYBFLT8      62   /* 0x3E */
216 #define SYBDATETIME  61   /* 0x3D */
217 #define SYBBIT       50   /* 0x32 */
218 #define SYBTEXT      35   /* 0x23 */
219 #define SYBNTEXT     99   /* 0x63 */
220 #define SYBIMAGE     34   /* 0x22 */
221 #define SYBMONEY4    122  /* 0x7A */
222 #define SYBMONEY     60   /* 0x3C */
223 #define SYBDATETIME4 58   /* 0x3A */
224 #define SYBREAL      59   /* 0x3B */
225 #define SYBBINARY    45   /* 0x2D */
226 #define SYBVOID      31   /* 0x1F */
227 #define SYBVARBINARY 37   /* 0x25 */
228 #define SYBNVARCHAR  103  /* 0x67 */
229 #define SYBBITN      104  /* 0x68 */
230 #define SYBNUMERIC   108  /* 0x6C */
231 #define SYBDECIMAL   106  /* 0x6A */
232 #define SYBFLTN      109  /* 0x6D */
233 #define SYBMONEYN    110  /* 0x6E */
234 #define SYBDATETIMN  111  /* 0x6F */
235 #define XSYBCHAR     167  /* 0xA7 */
236 #define XSYBVARCHAR  175  /* 0xAF */
237 #define XSYBNVARCHAR 231  /* 0xE7 */
238 #define XSYBNCHAR    239  /* 0xEF */
239 #define SYBUNIQUE    0x24
240 #define SYBVARIANT   0x62
241
242 #define is_fixed_coltype(x) (x==SYBINT1    || \
243                         x==SYBINT2      || \
244                         x==SYBINT4      || \
245                         x==SYBINT8      || \
246                         x==SYBREAL       || \
247                         x==SYBFLT8      || \
248                         x==SYBDATETIME  || \
249                         x==SYBDATETIME4 || \
250                         x==SYBBIT       || \
251                         x==SYBMONEY     || \
252                         x==SYBMONEY4    || \
253                         x==SYBUNIQUE)
254
255 /* Initialize the protocol and registered fields */
256 static int proto_tds = -1;
257 static int hf_tds_type = -1;
258 static int hf_tds_status = -1;
259 static int hf_tds_size = -1;
260 static int hf_tds_channel = -1;
261 static int hf_tds_packet_number = -1;
262 static int hf_tds_window = -1;
263 static int hf_tds_fragments = -1;
264 static int hf_tds_fragment = -1;
265 static int hf_tds_fragment_overlap = -1;
266 static int hf_tds_fragment_overlap_conflict = -1;
267 static int hf_tds_fragment_multiple_tails = -1;
268 static int hf_tds_fragment_too_long_fragment = -1;
269 static int hf_tds_fragment_error = -1;
270
271 /* Initialize the subtree pointers */
272 static gint ett_tds = -1;
273 static gint ett_tds_fragments = -1;
274 static gint ett_tds_fragment = -1;
275 static gint ett_tds_token = -1;
276 static gint ett_tds7_login = -1;
277 static gint ett_tds7_hdr = -1;
278
279 /* Desegmentation of Netlib buffers crossing TCP segment boundaries. */
280 static gboolean tds_desegment = TRUE;
281
282 static const fragment_items tds_frag_items = {
283         &ett_tds_fragment,
284         &ett_tds_fragments,
285         &hf_tds_fragments,
286         &hf_tds_fragment,
287         &hf_tds_fragment_overlap,
288         &hf_tds_fragment_overlap_conflict,
289         &hf_tds_fragment_multiple_tails,
290         &hf_tds_fragment_too_long_fragment,
291         &hf_tds_fragment_error,
292         "fragments"
293 };
294
295 /* Tables for reassembly of fragments. */
296 static GHashTable *tds_fragment_table = NULL;
297 static GHashTable *tds_reassembled_table = NULL;
298
299 /* defragmentation of multi-buffer TDS PDUs */
300 static gboolean tds_defragment = TRUE;
301
302 static dissector_handle_t tds_tcp_handle;
303 static dissector_handle_t ntlmssp_handle;
304 static dissector_handle_t data_handle;
305
306 /* These correspond to the netlib packet type field */
307 static const value_string packet_type_names[] = {
308         {TDS_QUERY_PKT,  "Query Packet"},
309         {TDS_LOGIN_PKT,  "Login Packet"},
310         {TDS_RESP_PKT,   "Response Packet"},
311         {TDS_CANCEL_PKT, "Cancel Packet"},
312         {TDS_QUERY5_PKT, "TDS5 Query Packet"},
313         {TDS_LOGIN7_PKT, "TDS7/8 Login Packet"},
314         {0, NULL},
315 };
316
317 /* The status field */
318
319 #define is_valid_tds_status(x) ((x) < 5)
320
321 static const value_string status_names[] = {
322         {0x00, "Not last buffer"},
323         {0x01, "Last buffer in request or response"},
324         {0x02, "Acknowledgment of last attention request"},
325         {0x03, "Attention request"},
326         {0x04, "Event notification"},
327         {0, NULL},
328 };
329
330 /* The one byte token at the start of each TDS PDU */
331 static const value_string token_names[] = {
332         {TDS5_DYN_TOKEN, "Dynamic SQL"},
333         {TDS5_DYNRES_TOKEN, "Dynamic Results"},
334         {TDS5_DYN3_TOKEN, "Dynamic (Unknown)"},
335         {TDS_LANG_TOKEN, "Language"},
336         {TDS_CLOSE_TOKEN, "Close Connection"},
337         {TDS_RET_STAT_TOKEN, "Return Status"},
338         {TDS_124_TOKEN, "Proc ID"},
339         {TDS7_RESULT_TOKEN, "Results"},
340         {TDS_COL_NAME_TOKEN, "Column Names"},
341         {TDS_COL_INFO_TOKEN, "Column Info"},
342         {TDS_167_TOKEN, "Unknown (167)"},
343         {TDS_168_TOKEN, "Unknown (168)"},
344         {TDS_ORDER_BY_TOKEN, "Order By"},
345         {TDS_ERR_TOKEN, "Error Message"},
346         {TDS_MSG_TOKEN, "Info Message"},
347         {TDS_PARAM_TOKEN, "Paramater"},
348         {TDS_LOGIN_ACK_TOKEN, "Login Acknowledgement"},
349         {TDS_174_TOKEN, "Unknown (174)"},
350         {TDS_ROW_TOKEN, "Row"},
351         {TDS_CMP_ROW_TOKEN, "Compute Row"},
352         {TDS_CAP_TOKEN, "Capabilities"},
353         {TDS_ENV_CHG_TOKEN, "Environment Change"},
354         {TDS_EED_TOKEN, "Extended Error"},
355         {TDS_AUTH_TOKEN, "Authentication"},
356         {TDS_RESULT_TOKEN, "Results"},
357         {TDS_DONE_TOKEN, "Done"},
358         {TDS_DONEPROC_TOKEN, "Done Proc"},
359         {TDS_DONEINPROC_TOKEN, "Done In Proc"},
360         {0, NULL},
361 };
362
363 static const value_string env_chg_names[] = {
364         {1, "Database"},
365         {2, "Language"},
366         {3, "Sort Order"},
367         {4, "Blocksize"},
368         {5, "Unicode Locale ID"},
369         {6, "Unicode Comparison Style"},
370         {0, NULL},
371 };
372
373 static const value_string login_field_names[] = {
374         {0, "Client Name"},
375         {1, "Username"},
376         {2, "Password"},
377         {3, "App Name"},
378         {4, "Server Name"},
379         {5, "Unknown1"},
380         {6, "Library Name"},
381         {7, "Locale"},
382         {8, "Unknown2"},
383         {0, NULL},
384 };
385
386
387 #define MAX_COLUMNS 256
388
389 /*
390  * This is where we store the column information to be used in decoding the
391  * TDS_ROW_TOKEN tokens.
392  */
393 struct _tds_col {
394      gchar name[256];
395      guint16 utype;
396      guint8 ctype;
397      guint csize;
398 };
399
400 struct _netlib_data {
401         guint num_cols;
402         struct _tds_col *columns[MAX_COLUMNS];
403 };
404
405 /* all the standard memory management stuff */
406 #define tds_column_length (sizeof(struct _tds_col))
407 #define tds_column_init_count 10
408
409 static GMemChunk *tds_column = NULL;
410
411 /* support routines */
412 static void
413 dissect_tds_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
414     guint offset, guint length)
415 {
416         tvbuff_t *ntlmssp_tvb;
417
418         ntlmssp_tvb = tvb_new_subset(tvb, offset, length, length);
419         call_dissector(ntlmssp_handle, ntlmssp_tvb, pinfo, tree);
420 }
421
422 static void
423 dissect_tds7_login(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
424 {
425         guint offset, i, offset2, len;
426         guint16 bc;
427         gboolean is_unicode = TRUE;
428         const char *val;
429
430         proto_item *login_hdr;
431         proto_tree *login_tree;
432         proto_item *header_hdr;
433         proto_tree *header_tree;
434
435         gint length_remaining;
436
437         offset = 8+36;
438
439         /* create display subtree for the protocol */
440         login_hdr = proto_tree_add_text(tree, tvb, 8, -1, "TDS7 Login Packet");
441         login_tree = proto_item_add_subtree(login_hdr, ett_tds7_login);
442
443         header_hdr = proto_tree_add_text(login_tree, tvb, offset, 50,
444             "Login Packet Header");
445         header_tree = proto_item_add_subtree(header_hdr, ett_tds7_hdr);
446         for (i = 0; i < 9; i++) {
447                 offset2 = tvb_get_letohs(tvb, offset + i*4);
448                 len = tvb_get_letohs(tvb, offset + i*4 + 2);
449                 proto_tree_add_text(header_tree, tvb, offset + i*4, 2,
450                     "%s offset: %u",
451                     val_to_str(i, login_field_names, "Unknown"),
452                     offset2);
453                 proto_tree_add_text(header_tree, tvb, offset + i*4 + 2, 2,
454                         "%s length: %u",
455                         val_to_str(i, login_field_names, "Unknown"),
456                         len);
457                 if (len != 0) {
458                         if (is_unicode == TRUE)
459                                 len *= 2;
460                         val = get_unicode_or_ascii_string(tvb, &offset2,
461                                 is_unicode, &len, TRUE, TRUE, &bc);
462                         if (val != NULL)
463                                 proto_tree_add_text(login_tree, tvb, offset2, len,
464                                         "%s: %s",
465                                         val_to_str(i, login_field_names, "Unknown"),
466                                         val);
467                 }
468         }
469
470         length_remaining = tvb_reported_length_remaining(tvb, offset2 + len);
471         if (length_remaining > 0) {
472                 dissect_tds_ntlmssp(tvb, pinfo, login_tree, offset2 + len,
473                     length_remaining);
474         }
475 }
476
477 static int get_size_by_coltype(int servertype)
478 {
479    switch(servertype)
480    {
481       case SYBINT1:        return 1;  break;
482       case SYBINT2:        return 2;  break;
483       case SYBINT4:        return 4;  break;
484       case SYBINT8:        return 8;  break;
485       case SYBREAL:        return 4;  break;
486       case SYBFLT8:        return 8;  break;
487       case SYBDATETIME:    return 8;  break;
488       case SYBDATETIME4:   return 4;  break;
489       case SYBBIT:         return 1;  break;
490       case SYBBITN:        return 1;  break;
491       case SYBMONEY:       return 8;  break;
492       case SYBMONEY4:      return 4;  break;
493       case SYBUNIQUE:      return 16; break;
494       default:             return -1; break;
495    }
496 }
497 static int tds_is_fixed_token(int token)
498 {
499      switch (token) {
500           case TDS_DONE_TOKEN:
501           case TDS_DONEPROC_TOKEN:
502           case TDS_DONEINPROC_TOKEN:
503           case TDS_RET_STAT_TOKEN:
504                return 1;
505           default:
506                return 0;
507      }
508 }
509 static int tds_get_token_size(int token)
510 {
511      switch(token) {
512           case TDS_DONE_TOKEN:
513           case TDS_DONEPROC_TOKEN:
514           case TDS_DONEINPROC_TOKEN:
515                return 8;
516           case TDS_RET_STAT_TOKEN:
517                return 4;
518           case TDS_124_TOKEN:
519                return 8;
520           default:
521                return 0;
522      }
523 }
524
525 # if 0
526 /*
527  * data_to_string should take column data and turn it into something we can
528  * display on the tree.
529  */
530 static char *data_to_string(void *data, guint col_type, guint col_size)
531 {
532    static char  result[256];
533    guint i;
534
535    switch(col_type) {
536       case SYBVARCHAR:
537          /* strncpy(result, (char *)data, col_size); */
538          for (i=0;i<col_size && i<(256-1);i++)
539                 if (!isprint(((char *)data)[i])) result[i]='.';
540                 else result[i]=((char *)data)[i];
541          result[i] = '\0';
542          break;
543       case SYBINT2:
544          sprintf(result, "%d", *(short *)data);
545          break;
546       case SYBINT4:
547          sprintf(result, "%d", *(int *)data);
548          break;
549       default:
550          sprintf(result, "Unexpected column_type %d", col_type);
551          break;
552    }
553    return result;
554 }
555 #endif
556
557 /*
558  * Since rows are special PDUs in that they are not fixed and lack a size field,
559  * the length must be computed using the column information seen in the result
560  * PDU. This function does just that.
561  */
562 static size_t
563 tds_get_row_size(tvbuff_t *tvb, struct _netlib_data *nl_data, guint offset)
564 {
565         guint cur, i, csize;
566
567         cur = offset;
568         for (i = 0; i < nl_data->num_cols; i++) {
569                 if (!is_fixed_coltype(nl_data->columns[i]->ctype)) {
570                         csize = tvb_get_guint8(tvb, cur);
571                         cur++;
572                 } else
573                         csize = get_size_by_coltype(nl_data->columns[i]->ctype);
574                 cur += csize;
575         }
576
577         return (cur - offset + 1);
578 }
579
580 /*
581  * Read the results token and store the relevant information in the
582  * _netlib_data structure for later use (see tds_get_row_size).
583  */
584 static gboolean
585 read_results_tds5(tvbuff_t *tvb, struct _netlib_data *nl_data, guint offset)
586 {
587         guint len, name_len;
588         guint cur;
589         guint i;
590
591         len = tvb_get_letohs(tvb, offset+1);
592         cur = offset + 3;
593
594         /*
595          * This would be the logical place to check for little/big endianess
596          * if we didn't see the login packet.
597          */
598         nl_data->num_cols = tvb_get_letohs(tvb, cur);
599         if (nl_data->num_cols > MAX_COLUMNS) {
600                 nl_data->num_cols = 0;
601                 return FALSE;
602         }
603
604         cur += 2;
605
606         for (i = 0; i < nl_data->num_cols; i++) {
607                 nl_data->columns[i] = g_mem_chunk_alloc(tds_column);
608                 name_len = tvb_get_guint8(tvb,cur);
609                 cur ++;
610                 cur += name_len;
611
612                 cur++; /* unknown */
613
614                 nl_data->columns[i]->utype = tvb_get_letohs(tvb, cur);
615                 cur += 2;
616
617                 cur += 2; /* unknown */
618
619                 nl_data->columns[i]->ctype = tvb_get_guint8(tvb,cur);
620                 cur++;
621
622                 if (!is_fixed_coltype(nl_data->columns[i]->ctype)) {
623                         nl_data->columns[i]->csize = tvb_get_guint8(tvb,cur);
624                         cur ++;
625                 } else {
626                         nl_data->columns[i]->csize =
627                             get_size_by_coltype(nl_data->columns[i]->ctype);
628                 }
629                 cur++; /* unknown */
630         }
631         return TRUE;
632 }
633
634 /*
635  * If the packet type from the netlib header is a login packet, then dig into
636  * the packet to see if this is a supported TDS version and verify the otherwise
637  * weak heuristics of the netlib check.
638  */
639 static gboolean
640 netlib_check_login_pkt(tvbuff_t *tvb, guint offset, packet_info *pinfo, guint8 type)
641 {
642         guint tds_major, bytes_avail;
643
644         bytes_avail = tvb_length(tvb) - offset;
645
646         /*
647          * we have two login packet styles, one for TDS 4.2 and 5.0
648          */
649         if (type==TDS_LOGIN_PKT) {
650                 /* Use major version number to validate TDS 4/5 login
651                  * packet */
652
653                 /* Login packet is first in stream and should not be fragmented...
654                  * if it is we are screwed */
655                 if (bytes_avail < 467) return FALSE;
656                 tds_major = tvb_get_guint8(tvb, 466);
657                 if (tds_major != 4 && tds_major != 5) {
658                         return FALSE;
659                 }
660         /*
661          * and one added by Microsoft in SQL Server 7
662          */
663         } else if (type==TDS_LOGIN7_PKT) {
664                 if (bytes_avail < 16) return FALSE;
665                 tds_major = tvb_get_guint8(tvb, 15);
666                 if (tds_major != 0x70 && tds_major != 0x80) {
667                         return FALSE;
668                 }
669         } else if (type==TDS_QUERY5_PKT) {
670                 if (bytes_avail < 9) return FALSE;
671                 /* if this is a TDS 5.0 query check the token */
672                 if (tvb_get_guint8(tvb, 8) != TDS_LANG_TOKEN) {
673                         return FALSE;
674                 }
675         /* check if it is MS SQL default port */
676         } else if (pinfo->srcport != 1433 &&
677                 pinfo->destport != 1433) {
678                 /* otherwise, we can not ensure this is netlib */
679                 /* beyond a reasonable doubt.                  */
680                         return FALSE;
681         }
682         return TRUE;
683 }
684
685 static void
686 dissect_tds_env_chg(tvbuff_t *tvb, guint offset, guint token_sz,
687     proto_tree *tree)
688 {
689         guint8 env_type;
690         guint old_len, new_len, old_len_offset;
691         const char *new_val = NULL, *old_val = NULL;
692         guint32 string_offset;
693         guint16 bc;
694         gboolean is_unicode = FALSE;
695
696         env_type = tvb_get_guint8(tvb, offset);
697         proto_tree_add_text(tree, tvb, offset, 1, "Type: %u (%s)", env_type,
698                 val_to_str(env_type, env_chg_names, "Unknown"));
699
700         new_len = tvb_get_guint8(tvb, offset+1);
701         old_len_offset = offset + new_len + 2;
702         old_len = tvb_get_guint8(tvb, old_len_offset);
703
704         /*
705          * If our lengths plus the lengths of the type and the lengths
706          * don't add up to the token size, it must be UCS2.
707          */
708         if (old_len + new_len + 3 != token_sz) {
709                 is_unicode = TRUE;
710                 old_len_offset = offset + (new_len * 2) + 2;
711                 old_len = tvb_get_guint8(tvb, old_len_offset);
712         }
713
714         proto_tree_add_text(tree, tvb, offset + 1, 1, "New Value Length: %u",
715             new_len);
716         if (new_len) {
717                 if (is_unicode == TRUE) {
718                         new_len *= 2;
719                 }
720                 string_offset = offset + 2;
721                 new_val = get_unicode_or_ascii_string(tvb, &string_offset,
722                                             is_unicode, &new_len,
723                                             TRUE, TRUE, &bc);
724
725                 proto_tree_add_text(tree, tvb, string_offset, new_len,
726                     "New Value: %s", new_val);
727         }
728
729         proto_tree_add_text(tree, tvb, old_len_offset, 1, "Old Value Length: %u",
730             old_len);
731         if (old_len) {
732                 if (is_unicode == TRUE) {
733                         old_len *= 2;
734                 }
735                 string_offset = old_len_offset + 1;
736                 old_val = get_unicode_or_ascii_string(tvb, &string_offset,
737                                             is_unicode, &old_len,
738                                             TRUE, TRUE, &bc);
739
740                 proto_tree_add_text(tree, tvb, string_offset, old_len,
741                     "Old Value: %s", old_val);
742          }
743 }
744
745 static void
746 dissect_tds_resp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
747 {
748         int offset = 0;
749         proto_item *token_item;
750         proto_tree *token_tree;
751         guint pos, token_sz = 0;
752         guint8 token;
753         struct _netlib_data nl_data;
754         gint length_remaining;
755
756         memset(&nl_data, '\0', sizeof nl_data);
757
758         /*
759          * Until we reach the end of the packet, read tokens.
760          */
761         pos = offset;
762         while (tvb_reported_length_remaining(tvb, pos) > 0) {
763                 /* our token */
764                 token = tvb_get_guint8(tvb, pos);
765
766                 if (tds_is_fixed_token(token)) {
767                         token_sz = tds_get_token_size(token) + 1;
768                 } else if (token == TDS_ROW_TOKEN) {
769                         /*
770                          * Rows are special; they have no size field and
771                          * aren't fixed length.
772                          */
773                         token_sz = tds_get_row_size(tvb, &nl_data, pos + 1);
774                 } else
775                         token_sz = tvb_get_letohs(tvb, pos + 1) + 3;
776
777                 length_remaining = tvb_ensure_length_remaining(tvb, pos);
778                 if (token_sz > (guint)length_remaining)
779                         token_sz = (guint)length_remaining;
780
781                 token_item = proto_tree_add_text(tree, tvb, pos, token_sz,
782                     "Token 0x%02x %s", token,
783                     val_to_str(token, token_names, "Unknown Token Type"));
784                 token_tree = proto_item_add_subtree(token_item, ett_tds_token);
785
786                 /*
787                  * If it's a variable token, put the length field in here
788                  * instead of replicating this for each token subdissector.
789                  */
790                 if (!tds_is_fixed_token(token) && token != TDS_ROW_TOKEN) {
791                         proto_tree_add_text(token_tree, tvb, pos+1, 2,
792                             "Length: %u", tvb_get_letohs(tvb, pos+1));
793                 }
794
795                 switch (token) {
796
797                 case TDS_RESULT_TOKEN:
798                         /*
799                          * If it's a result token, we need to stash the
800                          * column info.
801                          */
802                         read_results_tds5(tvb, &nl_data, pos);
803                         break;
804
805                 case TDS_ENV_CHG_TOKEN:
806                         dissect_tds_env_chg(tvb, pos + 3, token_sz - 3,
807                             token_tree);
808                         break;
809
810                 case TDS_AUTH_TOKEN:
811                         dissect_tds_ntlmssp(tvb, pinfo, token_tree, pos + 3,
812                             token_sz - 3);
813                         break;
814                 }
815
816                 /* and step to the end of the token, rinse, lather, repeat */
817                 pos += token_sz;
818         }
819 }
820
821 static void
822 dissect_netlib_buffer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
823 {
824         int offset = 0;
825         proto_item *tds_item = NULL;
826         proto_tree *tds_tree = NULL;
827         guint8 type;
828         guint8 status;
829         guint16 size;
830         guint16 channel;
831         gboolean save_fragmented;
832         int len;
833         fragment_data *fd_head;
834         tvbuff_t *next_tvb;
835
836         if (tree) {
837                 /* create display subtree for the protocol */
838                 tds_item = proto_tree_add_item(tree, proto_tds, tvb, offset, -1,
839                     FALSE);
840
841                 tds_tree = proto_item_add_subtree(tds_item, ett_tds);
842         }
843         type = tvb_get_guint8(tvb, offset);
844         if (tree) {
845                 proto_tree_add_uint(tds_tree, hf_tds_type, tvb, offset, 1,
846                     type);
847         }
848         status = tvb_get_guint8(tvb, offset + 1);
849         if (tree) {
850                 proto_tree_add_uint(tds_tree, hf_tds_status, tvb, offset + 1, 1,
851                     status);
852         }
853         size = tvb_get_ntohs(tvb, offset + 2);
854         if (tree) {
855                 proto_tree_add_uint(tds_tree, hf_tds_size, tvb, offset + 2, 2,
856                         size);
857         }
858         channel = tvb_get_ntohs(tvb, offset + 4);
859         if (tree) {
860                 proto_tree_add_uint(tds_tree, hf_tds_channel, tvb, offset + 4, 2,
861                         channel);
862                 proto_tree_add_item(tds_tree, hf_tds_packet_number, tvb, offset + 6, 1,
863                         FALSE);
864                 proto_tree_add_item(tds_tree, hf_tds_window, tvb, offset + 7, 1,
865                         FALSE);
866         }
867         offset += 8;    /* skip Netlib header */
868
869         /*
870          * Deal with fragmentation.
871          */
872         save_fragmented = pinfo->fragmented;
873         if (tds_defragment) {
874                 len = tvb_reported_length_remaining(tvb, offset);
875                 fd_head = fragment_add_seq_next(tvb, offset, pinfo, channel,
876                     tds_fragment_table, tds_reassembled_table,
877                     len, status == 0x00);
878                 if (fd_head != NULL) {
879                         if (fd_head->next != NULL) {
880                                 next_tvb = tvb_new_real_data(fd_head->data,
881                                     fd_head->len, fd_head->len);
882                                 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
883                                 add_new_data_source(pinfo, next_tvb,
884                                     "Reassembled TDS");
885                                 /* Show all fragments. */
886                                 if (tree) {
887                                         show_fragment_seq_tree(fd_head,
888                                             &tds_frag_items, tds_tree, pinfo,
889                                             next_tvb);
890                                 }
891                         } else {
892                                 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
893                         }
894                 } else {
895                         next_tvb = NULL;
896                 }
897         } else {
898                 /*
899                  * If this isn't the last buffer,just show it as a fragment.
900                  * (XXX - it'd be nice to dissect it if it's the first
901                  * buffer, but we'd need to do reassembly in order to
902                  * discover that.)
903                  *
904                  * If this is the last buffer, dissect it.
905                  * (XXX - it'd be nice to show it as a fragment if it's part
906                  * of a fragmented message, but we'd need to do reassembly
907                  * in order to discover that.)
908                  */
909                 if (status == 0x00)
910                         next_tvb = NULL;
911                 else {
912                         next_tvb = tvb_new_subset(tvb, offset, -1, -1);
913                 }
914         }
915         if (next_tvb != NULL) {
916                 switch (type) {
917
918                 case TDS_RESP_PKT:
919                         dissect_tds_resp(next_tvb, pinfo, tds_tree);
920                         break;
921
922                 case TDS_LOGIN7_PKT:
923                         dissect_tds7_login(next_tvb, pinfo, tds_tree);
924                         break;
925
926                 default:
927                         proto_tree_add_text(tds_tree, next_tvb, 0, -1,
928                             "TDS Packet");
929                         break;
930                 }
931         } else {
932                 next_tvb = tvb_new_subset (tvb, offset, -1, -1);
933                 call_dissector(data_handle, next_tvb, pinfo, tds_tree);
934         }
935 }
936
937 static void
938 dissect_tds_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
939 {
940         volatile gboolean first_time = TRUE;
941         volatile int offset = 0;
942         guint length_remaining;
943         guint8 type;
944         guint16 plen;
945         guint length;
946         tvbuff_t *next_tvb;
947         proto_item *tds_item = NULL;
948         proto_tree *tds_tree = NULL;
949
950         while (tvb_reported_length_remaining(tvb, offset) != 0) {
951                 length_remaining = tvb_ensure_length_remaining(tvb, offset);
952
953                 /*
954                  * Can we do reassembly?
955                  */
956                 if (tds_desegment && pinfo->can_desegment) {
957                         /*
958                          * Yes - is the fixed-length part of the PDU
959                          * split across segment boundaries?
960                          */
961                         if (length_remaining < 8) {
962                                 /*
963                                  * Yes.  Tell the TCP dissector where the
964                                  * data for this message starts in the data
965                                  * it handed us, and how many more bytes we
966                                  * need, and return.
967                                  */
968                                 pinfo->desegment_offset = offset;
969                                 pinfo->desegment_len = 8 - length_remaining;
970                                 return;
971                         }
972                 }
973
974                 type = tvb_get_guint8(tvb, offset);
975
976                 /*
977                  * Get the length of the PDU.
978                  */
979                 plen = tvb_get_ntohs(tvb, offset + 2);
980                 if (plen < 8) {
981                         /*
982                          * The length is less than the header length.
983                          * Put in the type, status, and length, and
984                          * report the length as bogus.
985                          */
986                         if (tree) {
987                                 /* create display subtree for the protocol */
988                                 tds_item = proto_tree_add_item(tree, proto_tds,
989                                     tvb, offset, -1, FALSE);
990
991                                 tds_tree = proto_item_add_subtree(tds_item,
992                                     ett_tds);
993                                 proto_tree_add_uint(tds_tree, hf_tds_type, tvb,
994                                     offset, 1, type);
995                                 proto_tree_add_item(tds_tree, hf_tds_status,
996                                     tvb, offset + 1, 1, FALSE);
997                                 proto_tree_add_uint_format(tds_tree,
998                                     hf_tds_size, tvb, offset + 2, 2, plen,
999                                     "Size: %u (bogus, should be >= 8)", plen);
1000                         }
1001
1002                         /*
1003                          * Give up - we can't dissect any more of this
1004                          * data.
1005                          */
1006                         break;
1007                 }
1008
1009                 /*
1010                  * Can we do reassembly?
1011                  */
1012                 if (tds_desegment && pinfo->can_desegment) {
1013                         /*
1014                          * Yes - is the PDU split across segment boundaries?
1015                          */
1016                         if (length_remaining < plen) {
1017                                 /*
1018                                  * Yes.  Tell the TCP dissector where the
1019                                  * data for this message starts in the data
1020                                  * it handed us, and how many more bytes we
1021                                  * need, and return.
1022                                  */
1023                                 pinfo->desegment_offset = offset;
1024                                 pinfo->desegment_len = plen - length_remaining;
1025                         }
1026                 }
1027
1028                 if (first_time) {
1029                         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1030                                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TDS");
1031
1032                         /*
1033                          * Set the packet description based on its TDS packet
1034                          * type.
1035                          */
1036                         if (check_col(pinfo->cinfo, COL_INFO)) {
1037                                 col_add_str(pinfo->cinfo, COL_INFO,
1038                                     val_to_str(type, packet_type_names,
1039                                       "Unknown Packet Type: %u"));
1040                         }
1041                         first_time = FALSE;
1042                 }
1043
1044                 /*
1045                  * Construct a tvbuff containing the amount of the payload
1046                  * we have available.  Make its reported length the amount
1047                  * of data in the PDU.
1048                  *
1049                  * XXX - if reassembly isn't enabled. the subdissector will
1050                  * throw a BoundsError exception, rather than a
1051                  * ReportedBoundsError exception.  We really want a tvbuff
1052                  * where the length is "length", the reported length is
1053                  * "plen", and the "if the snapshot length were infinite"
1054                  * length is the minimum of the reported length of the tvbuff
1055                  * handed to us and "plen", with a new type of exception
1056                  * thrown if the offset is within the reported length but
1057                  * beyond that third length, with that exception getting the
1058                  * "Unreassembled Packet" error.
1059                  */
1060                 length = length_remaining;
1061                 if (length > plen)
1062                         length = plen;
1063                 next_tvb = tvb_new_subset(tvb, offset, length, plen);
1064
1065                 /*
1066                  * Dissect the Netlib buffer.
1067                  *
1068                  * Catch the ReportedBoundsError exception; if this
1069                  * particular Netlib buffer happens to get a
1070                  * ReportedBoundsError exception, that doesn't mean
1071                  * that we should stop dissecting PDUs within this frame
1072                  * or chunk of reassembled data.
1073                  *
1074                  * If it gets a BoundsError, we can stop, as there's nothing
1075                  * more to see, so we just re-throw it.
1076                  */
1077                 TRY {
1078                         dissect_netlib_buffer(next_tvb, pinfo, tree);
1079                 }
1080                 CATCH(BoundsError) {
1081                         RETHROW;
1082                 }
1083                 CATCH(ReportedBoundsError) {
1084                         show_reported_bounds_error(tvb, pinfo, tree);
1085                 }
1086                 ENDTRY;
1087
1088                 /*
1089                  * Step to the next Netlib buffer.
1090                  */
1091                 offset += plen;
1092         }
1093 }
1094
1095 static gboolean
1096 dissect_tds_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1097 {
1098         int offset = 0;
1099         guint8 type;
1100         guint8 status;
1101         guint16 plen;
1102         conversation_t *conv;
1103
1104         /*
1105          * If we don't have even enough data for a Netlib header,
1106          * just say it's not TDS.
1107          */
1108         if (!tvb_bytes_exist(tvb, offset, 8))
1109                 return FALSE;
1110
1111         /*
1112          * Quickly scan all the data we have in order to see if
1113          * everything in it looks like Netlib traffic.
1114          */
1115         while (tvb_bytes_exist(tvb, offset, 1)) {
1116                 /*
1117                  * Check the type field.
1118                  */
1119                 type = tvb_get_guint8(tvb, offset);
1120                 if (!is_valid_tds_type(type))
1121                         return FALSE;
1122
1123                 /*
1124                  * Check the status field, if it's present.
1125                  */
1126                 if (!tvb_bytes_exist(tvb, offset + 1, 1))
1127                         break;
1128                 status = tvb_get_guint8(tvb, offset + 1);
1129                 if (!is_valid_tds_status(status))
1130                         return FALSE;
1131
1132                 /*
1133                  * Get the length of the PDU.
1134                  */
1135                 if (!tvb_bytes_exist(tvb, offset + 2, 2))
1136                         break;
1137                 plen = tvb_get_ntohs(tvb, offset + 2);
1138                 if (plen < 8) {
1139                         /*
1140                          * The length is less than the header length.
1141                          * That's bogus.
1142                          */
1143                         return FALSE;
1144                 }
1145
1146                 /*
1147                  * If we're at the beginning of the segment, check the
1148                  * payload if it's a login packet.
1149                  */
1150                 if (offset == 0) {
1151                         if (!netlib_check_login_pkt(tvb, offset, pinfo, type))
1152                                 return FALSE;
1153                 }
1154
1155                 /*
1156                  * Step to the next Netlib buffer.
1157                  */
1158                 offset += plen;
1159         }
1160
1161         /*
1162          * OK, it passes the test; assume the rest of this conversation
1163          * is TDS.
1164          */
1165         conv = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
1166             pinfo->srcport, pinfo->destport, 0);
1167         if (conv == NULL) {
1168                 /*
1169                  * No conversation exists yet - create one.
1170                  */
1171                 conv = conversation_new(&pinfo->src, &pinfo->dst,
1172                     pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
1173         }
1174         conversation_set_dissector(conv, tds_tcp_handle);
1175
1176         /*
1177          * Now dissect it as TDS.
1178          */
1179         dissect_tds_tcp(tvb, pinfo, tree);
1180         return TRUE;
1181 }
1182
1183 static void
1184 tds_init(void)
1185 {
1186         /*
1187          * Initialize the fragment and reassembly tables.
1188          */
1189         fragment_table_init(&tds_fragment_table);
1190         reassembled_table_init(&tds_reassembled_table);
1191
1192         /*
1193          * Reinitialize the chunks of data for remembering row
1194          * information.
1195          */
1196         if (tds_column)
1197                 g_mem_chunk_destroy(tds_column);
1198
1199         tds_column = g_mem_chunk_new("tds_column", tds_column_length,
1200                 tds_column_init_count * tds_column_length,
1201                 G_ALLOC_AND_FREE);
1202 }
1203
1204 /* Register the protocol with Ethereal */
1205
1206 /* this format is required because a script is used to build the C function
1207    that calls all the protocol registration.
1208 */
1209
1210 void
1211 proto_register_netlib(void)
1212 {
1213         static hf_register_info hf[] = {
1214                 { &hf_tds_type,
1215                         { "Type",           "tds.type",
1216                         FT_UINT8, BASE_HEX, VALS(packet_type_names), 0x0,
1217                         "Packet Type", HFILL }
1218                 },
1219                 { &hf_tds_status,
1220                         { "Status",         "tds.status",
1221                         FT_UINT8, BASE_DEC, VALS(status_names), 0x0,
1222                         "Frame status", HFILL }
1223                 },
1224                 { &hf_tds_size,
1225                         { "Size",           "tds.size",
1226                         FT_UINT16, BASE_DEC, NULL, 0x0,
1227                         "Packet Size", HFILL }
1228                 },
1229                 { &hf_tds_channel,
1230                         { "Channel",        "tds.channel",
1231                         FT_UINT16, BASE_DEC, NULL, 0x0,
1232                         "Channel Number", HFILL }
1233                 },
1234                 { &hf_tds_packet_number,
1235                         { "Packet Number",  "tds.packet_number",
1236                         FT_UINT8, BASE_DEC, NULL, 0x0,
1237                         "Packet Number", HFILL }
1238                 },
1239                 { &hf_tds_window,
1240                         { "Window",         "tds.window",
1241                         FT_UINT8, BASE_DEC, NULL, 0x0,
1242                         "Window", HFILL }
1243                 },
1244                 { &hf_tds_fragment_overlap,
1245                         { "Segment overlap",    "tds.fragment.overlap",
1246                         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1247                         "Fragment overlaps with other fragments", HFILL }
1248                 },
1249                 { &hf_tds_fragment_overlap_conflict,
1250                         { "Conflicting data in fragment overlap", "tds.fragment.overlap.conflict",
1251                         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1252                         "Overlapping fragments contained conflicting data", HFILL }
1253                 },
1254                 { &hf_tds_fragment_multiple_tails,
1255                         { "Multiple tail fragments found", "tds.fragment.multipletails",
1256                         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1257                         "Several tails were found when defragmenting the packet", HFILL }
1258                 },
1259                 { &hf_tds_fragment_too_long_fragment,
1260                         { "Segment too long",   "tds.fragment.toolongfragment",
1261                         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1262                         "Segment contained data past end of packet", HFILL }
1263                 },
1264                 { &hf_tds_fragment_error,
1265                         { "Defragmentation error",      "tds.fragment.error",
1266                         FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1267                         "Defragmentation error due to illegal fragments", HFILL }
1268                 },
1269                 { &hf_tds_fragment,
1270                         { "TDS Fragment",       "tds.fragment",
1271                         FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1272                         "TDS Fragment", HFILL }
1273                 },
1274                 { &hf_tds_fragments,
1275                         { "TDS Fragments",      "tds.fragments",
1276                         FT_NONE, BASE_NONE, NULL, 0x0,
1277                         "TDS Fragments", HFILL }
1278                 },
1279         };
1280         static gint *ett[] = {
1281                 &ett_tds,
1282                 &ett_tds_fragments,
1283                 &ett_tds_fragment,
1284                 &ett_tds_token,
1285                 &ett_tds7_login,
1286                 &ett_tds7_hdr,
1287         };
1288         module_t *tds_module;
1289
1290 /* Register the protocol name and description */
1291         proto_tds = proto_register_protocol("Tabular Data Stream",
1292             "TDS", "tds");
1293
1294 /* Required function calls to register the header fields and subtrees used */
1295         proto_register_field_array(proto_tds, hf, array_length(hf));
1296         proto_register_subtree_array(ett, array_length(ett));
1297
1298         tds_tcp_handle = create_dissector_handle(dissect_tds_tcp, proto_tds);
1299
1300         tds_module = prefs_register_protocol(proto_tds, NULL);
1301         prefs_register_bool_preference(tds_module, "desegment_buffers",
1302             "Desegment all TDS buffers spanning multiple TCP segments",
1303             "Whether the TDS dissector should desegment all TDS buffers spanning multiple TCP segments",
1304             &tds_desegment);
1305         prefs_register_bool_preference(tds_module, "defragment",
1306             "Defragment all TDS messages with multiple buffers",
1307             "Whether the TDS dissector should defragment all messages spanning multiple Netlib buffers",
1308             &tds_defragment);
1309
1310         register_init_routine(tds_init);
1311 }
1312
1313 /* If this dissector uses sub-dissector registration add a registration routine.
1314    This format is required because a script is used to find these routines and
1315    create the code that calls these routines.
1316 */
1317 void
1318 proto_reg_handoff_tds(void)
1319 {
1320         /* dissector_add("tcp.port", 1433, dissect_tds,
1321             proto_tds); */
1322         heur_dissector_add("tcp", dissect_tds_tcp_heur, proto_tds);
1323
1324         ntlmssp_handle = find_dissector("ntlmssp");
1325         data_handle = find_dissector("data");
1326 }