Forgot to remove one change only used for local testing from last checkin
[obnox/wireshark/wip.git] / packet-nbns.c
1 /* packet-nbns.c
2  * Routines for NetBIOS-over-TCP packet disassembly (the name dates back
3  * to when it had only NBNS)
4  * Guy Harris <guy@alum.mit.edu>
5  *
6  * $Id: packet-nbns.c,v 1.76 2002/05/15 07:24:20 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 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <glib.h>
38
39 #include <epan/packet.h>
40 #include "packet-dns.h"
41 #include "packet-netbios.h"
42 #include "packet-tcp.h"
43 #include "packet-frame.h"
44 #include "prefs.h"
45
46 static int proto_nbns = -1;
47 static int hf_nbns_flags = -1;
48 static int hf_nbns_flags_response = -1;
49 static int hf_nbns_flags_opcode = -1;
50 static int hf_nbns_flags_authoritative = -1;
51 static int hf_nbns_flags_truncated = -1;
52 static int hf_nbns_flags_recdesired = -1;
53 static int hf_nbns_flags_recavail = -1;
54 static int hf_nbns_flags_broadcast = -1;
55 static int hf_nbns_flags_rcode = -1;
56 static int hf_nbns_transaction_id = -1;
57 static int hf_nbns_count_questions = -1;
58 static int hf_nbns_count_answers = -1;
59 static int hf_nbns_count_auth_rr = -1;
60 static int hf_nbns_count_add_rr = -1;
61
62 static gint ett_nbns = -1;
63 static gint ett_nbns_qd = -1;
64 static gint ett_nbns_flags = -1;
65 static gint ett_nbns_nb_flags = -1;
66 static gint ett_nbns_name_flags = -1;
67 static gint ett_nbns_rr = -1;
68 static gint ett_nbns_qry = -1;
69 static gint ett_nbns_ans = -1;
70
71 static int proto_nbdgm = -1;
72 static int hf_nbdgm_type = -1;
73 static int hf_nbdgm_fragment = -1;
74 static int hf_nbdgm_first = -1;
75 static int hf_nbdgm_node_type = -1;
76 static int hf_nbdgm_datagram_id = -1;
77 static int hf_nbdgm_src_ip = -1;
78 static int hf_nbdgm_src_port = -1;
79
80 static gint ett_nbdgm = -1;
81
82 static int proto_nbss = -1;
83 static int hf_nbss_type = -1;
84 static int hf_nbss_flags = -1;
85
86 static gint ett_nbss = -1;
87 static gint ett_nbss_flags = -1;
88
89 /* desegmentation of NBSS over TCP */
90 static gboolean nbss_desegment = TRUE;
91
92 /* See RFC 1001 and 1002 for information on the first three, and see
93
94         http://www.cifs.com/specs/draft-leach-cifs-v1-spec-01.txt
95
96    Appendix B, and various messages on the CIFS mailing list such as
97
98         http://discuss.microsoft.com/SCRIPTS/WA-MSD.EXE?A2=ind9811A&L=cifs&P=R386
99
100    for information on the fourth. */
101 #define UDP_PORT_NBNS   137
102 #define UDP_PORT_NBDGM  138
103 #define TCP_PORT_NBSS   139
104 #define TCP_PORT_CIFS   445
105
106 /* Packet structure taken from RFC 1002. See also RFC 1001.
107  * Opcode, flags, and rcode treated as "flags", similarly to DNS,
108  * to make it easier to lift the dissection code from "packet-dns.c". */
109
110 /* Offsets of fields in the NBNS header. */
111 #define NBNS_ID         0
112 #define NBNS_FLAGS      2
113 #define NBNS_QUEST      4
114 #define NBNS_ANS        6
115 #define NBNS_AUTH       8
116 #define NBNS_ADD        10
117
118 /* Length of NBNS header. */
119 #define NBNS_HDRLEN     12
120
121 /* type values  */
122 #define T_NB            32              /* NetBIOS name service RR */
123 #define T_NBSTAT        33              /* NetBIOS node status RR */
124
125 /* Bit fields in the flags */
126 #define F_RESPONSE      (1<<15)         /* packet is response */
127 #define F_OPCODE        (0xF<<11)       /* query opcode */
128 #define OPCODE_SHIFT    11
129 #define F_AUTHORITATIVE (1<<10)         /* response is authoritative */
130 #define F_TRUNCATED     (1<<9)          /* response is truncated */
131 #define F_RECDESIRED    (1<<8)          /* recursion desired */
132 #define F_RECAVAIL      (1<<7)          /* recursion available */
133 #define F_BROADCAST     (1<<4)          /* broadcast/multicast packet */
134 #define F_RCODE         (0xF<<0)        /* reply code */
135
136 static const true_false_string tfs_flags_response = {
137         "Message is a response",
138         "Message is a query"
139 };
140
141 static const true_false_string tfs_flags_authoritative = {
142         "Server is an authority for domain",
143         "Server is not an authority for domain"
144 };
145
146 static const true_false_string tfs_flags_truncated = {
147         "Message is truncated",
148         "Message is not truncated"
149 };
150
151 static const true_false_string tfs_flags_recdesired = {
152         "Do query recursively",
153         "Don't do query recursively"
154 };
155
156 static const true_false_string tfs_flags_recavail = {
157         "Server can do recursive queries",
158         "Server can't do recursive queries"
159 };
160
161 static const true_false_string tfs_flags_broadcast = {
162         "Broadcast packet",
163         "Not a broadcast packet"
164 };
165
166 /* Opcodes */
167 #define OPCODE_QUERY          0         /* standard query */
168 #define OPCODE_REGISTRATION   5         /* registration */
169 #define OPCODE_RELEASE        6         /* release name */
170 #define OPCODE_WACK           7         /* wait for acknowledgement */
171 #define OPCODE_REFRESH        8         /* refresh registration */
172 #define OPCODE_REFRESHALT     9         /* refresh registration (alternate opcode) */
173 #define OPCODE_MHREGISTRATION 15        /* multi-homed registration */
174
175 static const value_string opcode_vals[] = {
176           { OPCODE_QUERY,          "Name query"                 },
177           { OPCODE_REGISTRATION,   "Registration"               },
178           { OPCODE_RELEASE,        "Release"                    },
179           { OPCODE_WACK,           "Wait for acknowledgment"    },
180           { OPCODE_REFRESH,        "Refresh"                    },
181           { OPCODE_REFRESHALT,     "Refresh (alternate opcode)" },
182           { OPCODE_MHREGISTRATION, "Multi-homed registration"   },
183           { 0,                     NULL                         }
184 };
185
186 /* Reply codes */
187 #define RCODE_NOERROR   0
188 #define RCODE_FMTERROR  1
189 #define RCODE_SERVFAIL  2
190 #define RCODE_NAMEERROR 3
191 #define RCODE_NOTIMPL   4
192 #define RCODE_REFUSED   5
193 #define RCODE_ACTIVE    6
194 #define RCODE_CONFLICT  7
195
196 static const value_string rcode_vals[] = {
197           { RCODE_NOERROR,   "No error"                        },
198           { RCODE_FMTERROR,  "Request was invalidly formatted" },
199           { RCODE_SERVFAIL,  "Server failure"                  },
200           { RCODE_NAMEERROR, "Requested name does not exist"   },
201           { RCODE_NOTIMPL,   "Request is not implemented"      },
202           { RCODE_REFUSED,   "Request was refused"             },
203           { RCODE_ACTIVE,    "Name is owned by another node"   },
204           { RCODE_CONFLICT,  "Name is in conflict"             },
205           { 0,               NULL                              }
206 };
207
208 /* Values for the "NB_FLAGS" field of RR data.  From RFC 1001 and 1002,
209  * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
210  * packet traces. */
211 #define NB_FLAGS_ONT            (3<<(15-2))     /* bits for node type */
212 #define NB_FLAGS_ONT_B_NODE     (0<<(15-2))     /* B-mode node */
213 #define NB_FLAGS_ONT_P_NODE     (1<<(15-2))     /* P-mode node */
214 #define NB_FLAGS_ONT_M_NODE     (2<<(15-2))     /* M-mode node */
215 #define NB_FLAGS_ONT_H_NODE     (3<<(15-2))     /* H-mode node */
216
217 #define NB_FLAGS_G              (1<<(15-0))     /* group name */
218
219 /* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
220  * RR data.  From RFC 1001 and 1002, except for NAME_FLAGS_ONT_H_NODE,
221  * which was discovered by looking at packet traces. */
222 #define NAME_FLAGS_PRM          (1<<(15-6))     /* name is permanent node name */
223
224 #define NAME_FLAGS_ACT          (1<<(15-5))     /* name is active */
225
226 #define NAME_FLAGS_CNF          (1<<(15-4))     /* name is in conflict */
227
228 #define NAME_FLAGS_DRG          (1<<(15-3))     /* name is being deregistered */
229
230 #define NAME_FLAGS_ONT          (3<<(15-2))     /* bits for node type */
231 #define NAME_FLAGS_ONT_B_NODE   (0<<(15-2))     /* B-mode node */
232 #define NAME_FLAGS_ONT_P_NODE   (1<<(15-2))     /* P-mode node */
233 #define NAME_FLAGS_ONT_M_NODE   (2<<(15-2))     /* M-mode node */
234
235 #define NAME_FLAGS_G            (1<<(15-0))     /* group name */
236
237 static char *
238 nbns_type_name (int type)
239 {
240         switch (type) {
241         case T_NB:
242                 return "NB";
243         case T_NBSTAT:
244                 return "NBSTAT";
245         }
246         
247         return "unknown";
248 }
249
250 #define NBNAME_BUF_LEN 128
251
252 static int
253 get_nbns_name(tvbuff_t *tvb, int offset, int nbns_data_offset,
254     char *name_ret, int *name_type_ret)
255 {
256         int name_len;
257         char name[MAXDNAME];
258         char nbname[NBNAME_BUF_LEN];
259         char *pname, *pnbname, cname, cnbname;
260         int name_type;
261
262         name_len = get_dns_name(tvb, offset, nbns_data_offset, name,
263             sizeof(name));
264
265         /* OK, now undo the first-level encoding. */
266         pname = &name[0];
267         pnbname = &nbname[0];
268         for (;;) {
269                 /* Every two characters of the first level-encoded name
270                  * turn into one character in the decoded name. */
271                 cname = *pname;
272                 if (cname == '\0')
273                         break;          /* no more characters */
274                 if (cname == '.')
275                         break;          /* scope ID follows */
276                 if (cname < 'A' || cname > 'Z') {
277                         /* Not legal. */
278                         strcpy(nbname,
279                             "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
280                         goto bad;
281                 }
282                 cname -= 'A';
283                 cnbname = cname << 4;
284                 pname++;
285
286                 cname = *pname;
287                 if (cname == '\0' || cname == '.') {
288                         /* No more characters in the name - but we're in
289                          * the middle of a pair.  Not legal. */
290                         strcpy(nbname,
291                             "Illegal NetBIOS name (odd number of bytes)");
292                         goto bad;
293                 }
294                 if (cname < 'A' || cname > 'Z') {
295                         /* Not legal. */
296                         strcpy(nbname,
297                             "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
298                         goto bad;
299                 }
300                 cname -= 'A';
301                 cnbname |= cname;
302                 pname++;
303
304                 /* Do we have room to store the character? */
305                 if (pnbname < &nbname[NETBIOS_NAME_LEN]) {
306                         /* Yes - store the character. */
307                         *pnbname = cnbname;
308                 }
309
310                 /* We bump the pointer even if it's past the end of the
311                    name, so we keep track of how long the name is. */
312                 pnbname++;
313         }
314
315         /* NetBIOS names are supposed to be exactly 16 bytes long. */
316         if (pnbname - nbname != NETBIOS_NAME_LEN) {
317                 /* It's not. */
318                 sprintf(nbname, "Illegal NetBIOS name (%ld bytes long)",
319                     (long)(pnbname - nbname));
320                 goto bad;
321         }
322
323         /* This one is; make its name printable. */
324         name_type = process_netbios_name(nbname, name_ret);
325         name_ret += strlen(name_ret);
326         sprintf(name_ret, "<%02x>", name_type);
327         name_ret += 4;
328         if (cname == '.') {
329                 /* We have a scope ID, starting at "pname"; append that to
330                  * the decoded host name. */
331                 strcpy(name_ret, pname);
332         }
333         if (name_type_ret != NULL)
334                 *name_type_ret = name_type;
335         return name_len;
336
337 bad:
338         if (name_type_ret != NULL)
339                 *name_type_ret = -1;
340         strcpy (name_ret, nbname);
341         return name_len;
342 }
343
344
345 static int
346 get_nbns_name_type_class(tvbuff_t *tvb, int offset, int nbns_data_offset,
347     char *name_ret, int *name_len_ret, int *name_type_ret, int *type_ret,
348     int *class_ret)
349 {
350         int name_len;
351         int type;
352         int class;
353
354         name_len = get_nbns_name(tvb, offset, nbns_data_offset, name_ret,
355            name_type_ret);
356         offset += name_len;
357         
358         type = tvb_get_ntohs(tvb, offset);
359         offset += 2;
360
361         class = tvb_get_ntohs(tvb, offset);
362
363         *type_ret = type;
364         *class_ret = class;
365         *name_len_ret = name_len;
366
367         return name_len + 4;
368 }
369
370 static void
371 add_name_and_type(proto_tree *tree, tvbuff_t *tvb, int offset, int len,
372     char *tag, char *name, int name_type)
373 {
374         if (name_type != -1) {
375                 proto_tree_add_text(tree, tvb, offset, len, "%s: %s (%s)",
376                     tag, name, netbios_name_type_descr(name_type));
377         } else {
378                 proto_tree_add_text(tree, tvb, offset, len, "%s: %s",
379                     tag, name);
380         }
381 }
382
383 static int
384 dissect_nbns_query(tvbuff_t *tvb, int offset, int nbns_data_offset,
385     column_info *cinfo, proto_tree *nbns_tree)
386 {
387         int len;
388         char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
389         int name_len;
390         int name_type;
391         int type;
392         int class;
393         char *class_name;
394         char *type_name;
395         int data_offset;
396         int data_start;
397         proto_tree *q_tree;
398         proto_item *tq;
399
400         data_start = data_offset = offset;
401
402         len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
403             &name_len, &name_type, &type, &class);
404         data_offset += len;
405
406         type_name = nbns_type_name(type);
407         class_name = dns_class_name(class);
408
409         if (cinfo != NULL)
410                 col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
411         if (nbns_tree != NULL) {
412                 tq = proto_tree_add_text(nbns_tree, tvb, offset, len,
413                     "%s: type %s, class %s",  name, type_name, class_name);
414                 q_tree = proto_item_add_subtree(tq, ett_nbns_qd);
415
416                 add_name_and_type(q_tree, tvb, offset, name_len, "Name", name,
417                     name_type);
418                 offset += name_len;
419
420                 proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", type_name);
421                 offset += 2;
422
423                 proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
424                 offset += 2;
425         }
426         
427         return data_offset - data_start;
428 }
429
430 static void
431 nbns_add_nbns_flags(proto_tree *nbns_tree, tvbuff_t *tvb, int offset,
432     u_short flags, int is_wack)
433 {
434         char buf[128+1];
435         guint16 opcode;
436         proto_tree *field_tree;
437         proto_item *tf;
438
439         opcode = (flags & F_OPCODE) >> OPCODE_SHIFT;
440         strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation"));
441         if (flags & F_RESPONSE && !is_wack) {
442                 strcat(buf, " response");
443                 strcat(buf, ", ");
444                 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
445                     "Unknown error"));
446         }
447         tf = proto_tree_add_uint_format(nbns_tree, hf_nbns_flags,
448             tvb, offset, 2, flags, "Flags: 0x%04x (%s)", flags, buf);
449         field_tree = proto_item_add_subtree(tf, ett_nbns_flags);
450         proto_tree_add_item(field_tree, hf_nbns_flags_response,
451             tvb, offset, 2, FALSE);
452         proto_tree_add_item(field_tree, hf_nbns_flags_opcode,
453             tvb, offset, 2, FALSE);
454         if (flags & F_RESPONSE) {
455                 proto_tree_add_item(field_tree, hf_nbns_flags_authoritative,
456                           tvb, offset, 2, FALSE);
457         }
458         proto_tree_add_item(field_tree, hf_nbns_flags_truncated,
459             tvb, offset, 2, FALSE);
460         proto_tree_add_item(field_tree, hf_nbns_flags_recdesired,
461             tvb, offset, 2, FALSE);
462         if (flags & F_RESPONSE) {
463                 proto_tree_add_item(field_tree, hf_nbns_flags_recavail,
464                     tvb, offset, 2, FALSE);
465         }
466         proto_tree_add_item(field_tree, hf_nbns_flags_broadcast,
467             tvb, offset, 2, FALSE);
468         if (flags & F_RESPONSE && !is_wack) {
469                 proto_tree_add_item(field_tree, hf_nbns_flags_rcode,
470                     tvb, offset, 2, FALSE);
471         }
472 }
473
474 static void
475 nbns_add_nb_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset, u_short flags)
476 {
477         char buf[128+1];
478         proto_tree *field_tree;
479         proto_item *tf;
480         static const value_string nb_flags_ont_vals[] = {
481                   { NB_FLAGS_ONT_B_NODE, "B-node" },
482                   { NB_FLAGS_ONT_P_NODE, "P-node" },
483                   { NB_FLAGS_ONT_M_NODE, "M-node" },
484                   { NB_FLAGS_ONT_H_NODE, "H-node" },
485                   { 0,                   NULL     }
486         };
487
488         strcpy(buf, val_to_str(flags & NB_FLAGS_ONT, nb_flags_ont_vals,
489             "Unknown"));
490         strcat(buf, ", ");
491         if (flags & NB_FLAGS_G)
492                 strcat(buf, "group");
493         else
494                 strcat(buf, "unique");
495         tf = proto_tree_add_text(rr_tree, tvb, offset, 2, "Flags: 0x%x (%s)", flags,
496                         buf);
497         field_tree = proto_item_add_subtree(tf, ett_nbns_nb_flags);
498         proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
499                         decode_boolean_bitfield(flags, NB_FLAGS_G,
500                                 2*8,
501                                 "Group name",
502                                 "Unique name"));
503         proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
504                         decode_enumerated_bitfield(flags, NB_FLAGS_ONT,
505                                 2*8, nb_flags_ont_vals, "%s"));
506 }
507
508 static void
509 nbns_add_name_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset,
510     u_short flags)
511 {
512         char buf[128+1];
513         proto_item *field_tree;
514         proto_item *tf;
515         static const value_string name_flags_ont_vals[] = {
516                   { NAME_FLAGS_ONT_B_NODE, "B-node" },
517                   { NAME_FLAGS_ONT_P_NODE, "P-node" },
518                   { NAME_FLAGS_ONT_M_NODE, "M-node" },
519                   { 0,                     NULL     }
520         };
521
522         strcpy(buf, val_to_str(flags & NAME_FLAGS_ONT, name_flags_ont_vals,
523             "Unknown"));
524         strcat(buf, ", ");
525         if (flags & NAME_FLAGS_G)
526                 strcat(buf, "group");
527         else
528                 strcat(buf, "unique");
529         if (flags & NAME_FLAGS_DRG)
530                 strcat(buf, ", being deregistered");
531         if (flags & NAME_FLAGS_CNF)
532                 strcat(buf, ", in conflict");
533         if (flags & NAME_FLAGS_ACT)
534                 strcat(buf, ", active");
535         if (flags & NAME_FLAGS_PRM)
536                 strcat(buf, ", permanent node name");
537         tf = proto_tree_add_text(rr_tree, tvb, offset, 2, "Name flags: 0x%x (%s)",
538                         flags, buf);
539         field_tree = proto_item_add_subtree(tf, ett_nbns_name_flags);
540         proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
541                         decode_boolean_bitfield(flags, NAME_FLAGS_G,
542                                 2*8,
543                                 "Group name",
544                                 "Unique name"));
545         proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
546                         decode_enumerated_bitfield(flags, NAME_FLAGS_ONT,
547                                 2*8, name_flags_ont_vals, "%s"));
548         proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
549                         decode_boolean_bitfield(flags, NAME_FLAGS_DRG,
550                                 2*8,
551                                 "Name is being deregistered",
552                                 "Name is not being deregistered"));
553         proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
554                         decode_boolean_bitfield(flags, NAME_FLAGS_CNF,
555                                 2*8,
556                                 "Name is in conflict",
557                                 "Name is not in conflict"));
558         proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
559                         decode_boolean_bitfield(flags, NAME_FLAGS_ACT,
560                                 2*8,
561                                 "Name is active",
562                                 "Name is not active"));
563         proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
564                         decode_boolean_bitfield(flags, NAME_FLAGS_PRM,
565                                 2*8,
566                                 "Permanent node name",
567                                 "Not permanent node name"));
568 }
569
570 static int
571 dissect_nbns_answer(tvbuff_t *tvb, int offset, int nbns_data_offset,
572     column_info *cinfo, proto_tree *nbns_tree, int opcode)
573 {
574         int len;
575         char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME + 64];
576         int name_len;
577         int name_type;
578         int type;
579         int class;
580         char *class_name;
581         char *type_name;
582         int data_offset;
583         int cur_offset;
584         int data_start;
585         u_int ttl;
586         u_short data_len;
587         u_short flags;
588         proto_tree *rr_tree;
589         proto_item *trr;
590         char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
591         u_int num_names;
592         char nbname[16+4+1];    /* 4 for [<last char>] */
593         u_short name_flags;
594
595         data_start = data_offset = offset;
596         cur_offset = offset;
597
598         len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
599             &name_len, &name_type, &type, &class);
600         data_offset += len;
601         cur_offset += len;
602
603         type_name = nbns_type_name(type);
604         class_name = dns_class_name(class);
605
606         ttl = tvb_get_ntohl(tvb, data_offset);
607         data_offset += 4;
608         cur_offset += 4;
609
610         data_len = tvb_get_ntohs(tvb, data_offset);
611         data_offset += 2;
612         cur_offset += 2;
613
614         switch (type) {
615         case T_NB:              /* "NB" record */
616                 if (cinfo != NULL) {
617                         if (opcode != OPCODE_WACK) {
618                                 col_append_fstr(cinfo, COL_INFO, " %s %s",
619                                     type_name,
620                                     ip_to_str(tvb_get_ptr(tvb, data_offset+2, 4)));
621                         }
622                 }
623                 if (nbns_tree == NULL)
624                         break;
625                 trr = proto_tree_add_text(nbns_tree, tvb, offset,
626                     (data_offset - data_start) + data_len,
627                     "%s: type %s, class %s",
628                     name, type_name, class_name);
629                 strcat(name, " (");
630                 strcat(name, netbios_name_type_descr(name_type));
631                 strcat(name, ")");
632                 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
633                     name_len, type_name, class_name, ttl, data_len);
634                 while (data_len > 0) {
635                         if (opcode == OPCODE_WACK) {
636                                 /* WACK response.  This doesn't contain the
637                                  * same type of RR data as other T_NB
638                                  * responses.  */
639                                 if (data_len < 2) {
640                                         proto_tree_add_text(rr_tree, tvb, cur_offset,
641                                             data_len, "(incomplete entry)");
642                                         break;
643                                 }
644                                 flags = tvb_get_ntohs(tvb, cur_offset);
645                                 nbns_add_nbns_flags(rr_tree, tvb, cur_offset,
646                                     flags, 1);
647                                 cur_offset += 2;
648                                 data_len -= 2;
649                         } else {
650                                 if (data_len < 2) {
651                                         proto_tree_add_text(rr_tree, tvb, cur_offset,
652                                             data_len, "(incomplete entry)");
653                                         break;
654                                 }
655                                 flags = tvb_get_ntohs(tvb, cur_offset);
656                                 nbns_add_nb_flags(rr_tree, tvb, cur_offset,
657                                     flags);
658                                 cur_offset += 2;
659                                 data_len -= 2;
660
661                                 if (data_len < 4) {
662                                         proto_tree_add_text(rr_tree, tvb, cur_offset,
663                                             data_len, "(incomplete entry)");
664                                         break;
665                                 }
666                                 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
667                                     "Addr: %s",
668                                     ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
669                                 cur_offset += 4;
670                                 data_len -= 4;
671                         }
672                 }
673                 break;
674
675         case T_NBSTAT:  /* "NBSTAT" record */
676                 if (cinfo != NULL)
677                         col_append_fstr(cinfo, COL_INFO, " %s", type_name);
678                 if (nbns_tree == NULL)
679                         break;
680                 trr = proto_tree_add_text(nbns_tree, tvb, offset,
681                     (data_offset - data_start) + data_len,
682                     "%s: type %s, class %s",
683                     name, type_name, class_name);
684                 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
685                     name_len, type_name, class_name, ttl, data_len);
686                 if (data_len < 1) {
687                         proto_tree_add_text(rr_tree, tvb, cur_offset,
688                             data_len, "(incomplete entry)");
689                         break;
690                 }
691                 num_names = tvb_get_guint8(tvb, cur_offset);
692                 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
693                     "Number of names: %u", num_names);
694                 cur_offset += 1;
695
696                 while (num_names != 0) {
697                         if (data_len < NETBIOS_NAME_LEN) {
698                                 proto_tree_add_text(rr_tree, tvb, cur_offset,
699                                     data_len, "(incomplete entry)");
700                                 goto out;
701                         }
702                         tvb_memcpy(tvb, (guint8 *)nbname, cur_offset,
703                             NETBIOS_NAME_LEN);
704                         name_type = process_netbios_name(nbname,
705                             name_str);
706                         proto_tree_add_text(rr_tree, tvb, cur_offset,
707                             NETBIOS_NAME_LEN, "Name: %s<%02x> (%s)",
708                             name_str, name_type,
709                             netbios_name_type_descr(name_type));
710                         cur_offset += NETBIOS_NAME_LEN;
711                         data_len -= NETBIOS_NAME_LEN;
712
713                         if (data_len < 2) {
714                                 proto_tree_add_text(rr_tree, tvb, cur_offset,
715                                     data_len, "(incomplete entry)");
716                                 goto out;
717                         }
718                         name_flags = tvb_get_ntohs(tvb, cur_offset);
719                         nbns_add_name_flags(rr_tree, tvb, cur_offset,
720                             name_flags);
721                         cur_offset += 2;
722                         data_len -= 2;
723
724                         num_names--;
725                 }
726
727                 if (data_len < 6) {
728                         proto_tree_add_text(rr_tree, tvb, cur_offset,
729                             data_len, "(incomplete entry)");
730                         break;
731                 }
732                 proto_tree_add_text(rr_tree, tvb, cur_offset, 6,
733                     "Unit ID: %s",
734                     ether_to_str(tvb_get_ptr(tvb, cur_offset, 6)));
735                 cur_offset += 6;
736                 data_len -= 6;
737
738                 if (data_len < 1) {
739                         proto_tree_add_text(rr_tree, tvb, cur_offset,
740                             data_len, "(incomplete entry)");
741                         break;
742                 }
743                 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
744                     "Jumpers: 0x%x", tvb_get_guint8(tvb, cur_offset));
745                 cur_offset += 1;
746                 data_len -= 1;
747
748                 if (data_len < 1) {
749                         proto_tree_add_text(rr_tree, tvb, cur_offset,
750                             data_len, "(incomplete entry)");
751                         break;
752                 }
753                 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
754                     "Test result: 0x%x", tvb_get_guint8(tvb, cur_offset));
755                 cur_offset += 1;
756                 data_len -= 1;
757
758                 if (data_len < 2) {
759                         proto_tree_add_text(rr_tree, tvb, cur_offset,
760                             data_len, "(incomplete entry)");
761                         break;
762                 }
763                 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
764                     "Version number: 0x%x", tvb_get_ntohs(tvb, cur_offset));
765                 cur_offset += 2;
766                 data_len -= 2;
767
768                 if (data_len < 2) {
769                         proto_tree_add_text(rr_tree, tvb, cur_offset,
770                             data_len, "(incomplete entry)");
771                         break;
772                 }
773                 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
774                     "Period of statistics: 0x%x",
775                     tvb_get_ntohs(tvb, cur_offset));
776                 cur_offset += 2;
777                 data_len -= 2;
778
779                 if (data_len < 2) {
780                         proto_tree_add_text(rr_tree, tvb, cur_offset,
781                             data_len, "(incomplete entry)");
782                         break;
783                 }
784                 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
785                     "Number of CRCs: %u", tvb_get_ntohs(tvb, cur_offset));
786                 cur_offset += 2;
787                 data_len -= 2;
788
789                 if (data_len < 2) {
790                         proto_tree_add_text(rr_tree, tvb, cur_offset,
791                             data_len, "(incomplete entry)");
792                         break;
793                 }
794                 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
795                     "Number of alignment errors: %u",
796                     tvb_get_ntohs(tvb, cur_offset));
797                 cur_offset += 2;
798                 data_len -= 2;
799
800                 if (data_len < 2) {
801                         proto_tree_add_text(rr_tree, tvb, cur_offset,
802                             data_len, "(incomplete entry)");
803                         break;
804                 }
805                 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
806                     "Number of collisions: %u", tvb_get_ntohs(tvb, cur_offset));
807                 cur_offset += 2;
808                 data_len -= 2;
809
810                 if (data_len < 2) {
811                         proto_tree_add_text(rr_tree, tvb, cur_offset,
812                             data_len, "(incomplete entry)");
813                         break;
814                 }
815                 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
816                     "Number of send aborts: %u", tvb_get_ntohs(tvb, cur_offset));
817                 cur_offset += 2;
818                 data_len -= 2;
819
820                 if (data_len < 4) {
821                         proto_tree_add_text(rr_tree, tvb, cur_offset,
822                             data_len, "(incomplete entry)");
823                         break;
824                 }
825                 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
826                     "Number of good sends: %u", tvb_get_ntohl(tvb, cur_offset));
827                 cur_offset += 4;
828                 data_len -= 4;
829
830                 if (data_len < 4) {
831                         proto_tree_add_text(rr_tree, tvb, cur_offset,
832                             data_len, "(incomplete entry)");
833                         break;
834                 }
835                 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
836                     "Number of good receives: %u",
837                     tvb_get_ntohl(tvb, cur_offset));
838                 cur_offset += 4;
839                 data_len -= 4;
840
841                 if (data_len < 2) {
842                         proto_tree_add_text(rr_tree, tvb, cur_offset,
843                             data_len, "(incomplete entry)");
844                         break;
845                 }
846                 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
847                     "Number of retransmits: %u", tvb_get_ntohs(tvb, cur_offset));
848                 cur_offset += 2;
849                 data_len -= 2;
850
851                 if (data_len < 2) {
852                         proto_tree_add_text(rr_tree, tvb, cur_offset,
853                             data_len, "(incomplete entry)");
854                         break;
855                 }
856                 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
857                     "Number of no resource conditions: %u",
858                     tvb_get_ntohs(tvb, cur_offset));
859                 cur_offset += 2;
860                 data_len -= 2;
861
862                 if (data_len < 2) {
863                         proto_tree_add_text(rr_tree, tvb, cur_offset,
864                             data_len, "(incomplete entry)");
865                         break;
866                 }
867                 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
868                     "Number of command blocks: %u",
869                     tvb_get_ntohs(tvb, cur_offset));
870                 cur_offset += 2;
871                 data_len -= 2;
872
873                 if (data_len < 2) {
874                         proto_tree_add_text(rr_tree, tvb, cur_offset,
875                             data_len, "(incomplete entry)");
876                         break;
877                 }
878                 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
879                     "Number of pending sessions: %u",
880                     tvb_get_ntohs(tvb, cur_offset));
881                 cur_offset += 2;
882                 data_len -= 2;
883
884                 if (data_len < 2) {
885                         proto_tree_add_text(rr_tree, tvb, cur_offset,
886                             data_len, "(incomplete entry)");
887                         break;
888                 }
889                 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
890                     "Max number of pending sessions: %u",
891                     tvb_get_ntohs(tvb, cur_offset));
892                 cur_offset += 2;
893                 data_len -= 2;
894
895                 if (data_len < 2) {
896                         proto_tree_add_text(rr_tree, tvb, cur_offset,
897                             data_len, "(incomplete entry)");
898                         break;
899                 }
900                 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
901                     "Max total sessions possible: %u",
902                     tvb_get_ntohs(tvb, cur_offset));
903                 cur_offset += 2;
904                 data_len -= 2;
905
906                 if (data_len < 2) {
907                         proto_tree_add_text(rr_tree, tvb, cur_offset,
908                             data_len, "(incomplete entry)");
909                         break;
910                 }
911                 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
912                     "Session data packet size: %u",
913                     tvb_get_ntohs(tvb, cur_offset));
914                 cur_offset += 2;
915                 data_len -= 2;
916         out:
917                 break;
918
919         default:
920                 if (cinfo != NULL)
921                         col_append_fstr(cinfo, COL_INFO, " %s", type_name);
922                 if (nbns_tree == NULL)
923                         break;
924                 trr = proto_tree_add_text(nbns_tree, tvb, offset,
925                     (data_offset - data_start) + data_len,
926                     "%s: type %s, class %s",
927                     name, type_name, class_name);
928                 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
929                     name_len, type_name, class_name, ttl, data_len);
930                 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
931                 cur_offset += data_len;
932                 break;
933         }
934         
935         return cur_offset - data_start;
936 }
937
938 static int
939 dissect_query_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
940     int count, column_info *cinfo, proto_tree *nbns_tree)
941 {
942         int start_off, add_off;
943         proto_tree *qatree = NULL;
944         proto_item *ti = NULL;
945         
946         start_off = cur_off;
947         if (nbns_tree != NULL) {
948                 ti = proto_tree_add_text(nbns_tree, tvb, start_off, -1, "Queries");
949                 qatree = proto_item_add_subtree(ti, ett_nbns_qry);
950         }
951         while (count-- > 0) {
952                 add_off = dissect_nbns_query(tvb, cur_off, nbns_data_offset,
953                     cinfo, qatree);
954                 cur_off += add_off;
955         }
956         if (ti != NULL)
957                 proto_item_set_len(ti, cur_off - start_off);
958
959         return cur_off - start_off;
960 }
961
962
963
964 static int
965 dissect_answer_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
966     int count, column_info *cinfo, proto_tree *nbns_tree, int opcode,
967     char *name)
968 {
969         int start_off, add_off;
970         proto_tree *qatree = NULL;
971         proto_item *ti = NULL;
972         
973         start_off = cur_off;
974         if (nbns_tree != NULL) {
975                 ti = proto_tree_add_text(nbns_tree, tvb, start_off, -1, name);
976                 qatree = proto_item_add_subtree(ti, ett_nbns_ans);
977         }
978         while (count-- > 0) {
979                 add_off = dissect_nbns_answer(tvb, cur_off, nbns_data_offset,
980                                         cinfo, qatree, opcode);
981                 cur_off += add_off;
982         }
983         if (ti != NULL)
984                 proto_item_set_len(ti, cur_off - start_off);
985         return cur_off - start_off;
986 }
987
988 static void
989 dissect_nbns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
990 {
991         int                     offset = 0;
992         int                     nbns_data_offset;
993         column_info             *cinfo;
994         proto_tree              *nbns_tree = NULL;
995         proto_item              *ti;
996         guint16                 id, flags, opcode, rcode, quest, ans, auth, add;
997         int                     cur_off;
998
999         nbns_data_offset = offset;
1000
1001         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1002                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBNS");
1003         if (check_col(pinfo->cinfo, COL_INFO))
1004                 col_clear(pinfo->cinfo, COL_INFO);
1005
1006         /* To do: check for runts, errs, etc. */
1007         id    = tvb_get_ntohs(tvb, offset + NBNS_ID);
1008         flags = tvb_get_ntohs(tvb, offset + NBNS_FLAGS);
1009         opcode = (flags & F_OPCODE) >> OPCODE_SHIFT;
1010         rcode = (flags & F_RCODE);
1011
1012         if (check_col(pinfo->cinfo, COL_INFO)) {
1013                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s",
1014                     val_to_str(opcode, opcode_vals, "Unknown operation (%u)"),
1015                     (flags & F_RESPONSE) ? " response" : "");
1016                 cinfo = pinfo->cinfo;
1017         } else {
1018                 /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query
1019                    and answer dissectors, as a way of saying that they
1020                    shouldn't add stuff to the COL_INFO column (a call to
1021                    "check_col(cinfo, COL_INFO)" is more expensive than
1022                    a check that a pointer isn't NULL). */
1023                 cinfo = NULL;
1024         }
1025
1026         if (tree) {
1027                 ti = proto_tree_add_item(tree, proto_nbns, tvb, offset, -1,
1028                     FALSE);
1029                 nbns_tree = proto_item_add_subtree(ti, ett_nbns);
1030
1031                 proto_tree_add_uint(nbns_tree, hf_nbns_transaction_id, tvb,
1032                                     offset + NBNS_ID, 2, id);
1033
1034                 nbns_add_nbns_flags(nbns_tree, tvb, offset + NBNS_FLAGS,
1035                                     flags, 0);
1036         }
1037         quest = tvb_get_ntohs(tvb, offset + NBNS_QUEST);
1038         if (tree) {
1039                 proto_tree_add_uint(nbns_tree, hf_nbns_count_questions, tvb,
1040                                     offset + NBNS_QUEST, 2, quest);
1041         }
1042         ans = tvb_get_ntohs(tvb, offset + NBNS_ANS);
1043         if (tree) {
1044                 proto_tree_add_uint(nbns_tree, hf_nbns_count_answers, tvb,
1045                                     offset + NBNS_ANS, 2, ans);
1046         }
1047         auth = tvb_get_ntohs(tvb, offset + NBNS_AUTH);
1048         if (tree) {
1049                 proto_tree_add_uint(nbns_tree, hf_nbns_count_auth_rr, tvb,
1050                                     offset + NBNS_AUTH, 2, auth);
1051         }
1052         add = tvb_get_ntohs(tvb, offset + NBNS_ADD);
1053         if (tree) {
1054                 proto_tree_add_uint(nbns_tree, hf_nbns_count_add_rr, tvb,
1055                                     offset + NBNS_ADD, 2, add);
1056         }
1057
1058         cur_off = offset + NBNS_HDRLEN;
1059     
1060         if (quest > 0) {
1061                 /* If this is a response, don't add information about the
1062                    queries to the summary, just add information about the
1063                    answers. */
1064                 cur_off += dissect_query_records(tvb, cur_off,
1065                     nbns_data_offset, quest,
1066                     (!(flags & F_RESPONSE) ? cinfo : NULL), nbns_tree);
1067         }
1068
1069         if (ans > 0) {
1070                 /* If this is a request, don't add information about the
1071                    answers to the summary, just add information about the
1072                    queries. */
1073                 cur_off += dissect_answer_records(tvb, cur_off,
1074                         nbns_data_offset, ans,
1075                         ((flags & F_RESPONSE) ? cinfo : NULL), nbns_tree,
1076                         opcode, "Answers");
1077         }
1078
1079         if (tree) {
1080                 /* Don't add information about the authoritative name
1081                    servers, or the additional records, to the summary. */
1082                 if (auth > 0)
1083                         cur_off += dissect_answer_records(tvb, cur_off,
1084                                         nbns_data_offset,
1085                                         auth, NULL, nbns_tree, opcode,
1086                                         "Authoritative nameservers");
1087
1088                 if (add > 0)
1089                         cur_off += dissect_answer_records(tvb, cur_off,
1090                                         nbns_data_offset,
1091                                         add, NULL, nbns_tree, opcode,
1092                                         "Additional records");
1093         }
1094 }
1095
1096 /* NetBIOS datagram packet, from RFC 1002, page 32 */
1097 struct nbdgm_header {
1098         guint8          msg_type;
1099         struct {
1100                 guint8  more;
1101                 guint8  first;
1102                 guint8  node_type;
1103         } flags;
1104         guint16         dgm_id;
1105         guint32         src_ip;
1106         guint16         src_port;
1107
1108         /* For packets with data */
1109         guint16         dgm_length;
1110         guint16         pkt_offset;
1111
1112         /* For error packets */
1113         guint8          error_code;
1114 };
1115
1116 /*
1117  * NBDS message types.
1118  */
1119 #define NBDS_DIRECT_UNIQUE      0x10
1120 #define NBDS_DIRECT_GROUP       0x11
1121 #define NBDS_BROADCAST          0x12
1122 #define NBDS_ERROR              0x13
1123 #define NBDS_QUERY_REQUEST      0x14
1124 #define NBDS_POS_QUERY_RESPONSE 0x15
1125 #define NBDS_NEG_QUERY_RESPONSE 0x16
1126
1127 static const value_string nbds_msgtype_vals[] = {
1128         { NBDS_DIRECT_UNIQUE,      "Direct_unique datagram" },
1129         { NBDS_DIRECT_GROUP,       "Direct_group datagram" },
1130         { NBDS_BROADCAST,          "Broadcast datagram" },
1131         { NBDS_ERROR,              "Datagram error" },
1132         { NBDS_QUERY_REQUEST,      "Datagram query request" },
1133         { NBDS_POS_QUERY_RESPONSE, "Datagram positive query response" },
1134         { NBDS_NEG_QUERY_RESPONSE, "Datagram negative query response" },
1135         { 0,                       NULL }
1136 };
1137
1138 static const true_false_string yesno = {  
1139         "Yes",
1140         "No"
1141 };
1142
1143 static const value_string node_type_vals[] = {
1144         { 0, "B node" },
1145         { 1, "P node" },
1146         { 2, "M node" },
1147         { 3, "NBDD" },
1148         { 0, NULL }
1149 };
1150
1151 static void
1152 dissect_nbdgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1153 {
1154         int                     offset = 0;
1155         proto_tree              *nbdgm_tree = NULL;
1156         proto_item              *ti = NULL;
1157         struct nbdgm_header     header;
1158         int                     flags;
1159         int                     message_index;
1160         tvbuff_t                *next_tvb;
1161
1162         static const value_string error_codes[] = {
1163                 { 0x82, "Destination name not present" },
1164                 { 0x83, "Invalid source name format" },
1165                 { 0x84, "Invalid destination name format" },
1166                 { 0x00, NULL }
1167         };
1168
1169         char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1170         int name_type;
1171         int len;
1172
1173         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1174                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBDS");
1175         if (check_col(pinfo->cinfo, COL_INFO))
1176                 col_clear(pinfo->cinfo, COL_INFO);
1177
1178         header.msg_type = tvb_get_guint8(tvb, offset);
1179         
1180         flags = tvb_get_guint8(tvb, offset+1);
1181         header.flags.more = flags & 1;
1182         header.flags.first = (flags & 2) >> 1;
1183         header.flags.node_type = (flags & 12) >> 2;
1184
1185         header.dgm_id = tvb_get_ntohs(tvb, offset+2);
1186         tvb_memcpy(tvb, (guint8 *)&header.src_ip, offset+4, 4);
1187         header.src_port = tvb_get_ntohs(tvb, offset+8);
1188
1189         switch (header.msg_type) {
1190
1191         case NBDS_DIRECT_UNIQUE:
1192         case NBDS_DIRECT_GROUP:
1193         case NBDS_BROADCAST:
1194                 header.dgm_length = tvb_get_ntohs(tvb, offset+10);
1195                 header.pkt_offset = tvb_get_ntohs(tvb, offset+12);
1196                 break;
1197
1198         case NBDS_ERROR:
1199                 header.error_code = tvb_get_ntohs(tvb, offset+10);
1200                 break;
1201         }
1202
1203         message_index = header.msg_type - 0x0f;
1204         if (message_index < 1 || message_index > 8) {
1205                 message_index = 0;
1206         }
1207
1208         if (check_col(pinfo->cinfo, COL_INFO)) {
1209                 col_add_str(pinfo->cinfo, COL_INFO,
1210                     val_to_str(header.msg_type, nbds_msgtype_vals,
1211                       "Unknown message type (0x%02X)"));
1212         }
1213
1214         if (tree) {
1215                 ti = proto_tree_add_item(tree, proto_nbdgm, tvb, offset, -1,
1216                     FALSE);
1217                 nbdgm_tree = proto_item_add_subtree(ti, ett_nbdgm);
1218
1219                 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_type, tvb,
1220                                      offset, 1, 
1221                                      header.msg_type);
1222                 proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_fragment, tvb,
1223                                        offset+1, 1, 
1224                                        header.flags.more);
1225                 proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_first, tvb,
1226                                        offset+1, 1, 
1227                                        header.flags.first);
1228                 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_node_type, tvb,
1229                                      offset+1, 1, 
1230                                      header.flags.node_type);
1231
1232                 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_datagram_id, tvb,
1233                                     offset+2, 2, header.dgm_id);
1234                 proto_tree_add_ipv4(nbdgm_tree, hf_nbdgm_src_ip, tvb,
1235                                     offset+4, 4, header.src_ip);
1236                 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_src_port, tvb,
1237                                     offset+8, 2, header.src_port);
1238
1239         }
1240
1241         offset += 10;
1242
1243         switch (header.msg_type) {
1244
1245         case NBDS_DIRECT_UNIQUE:
1246         case NBDS_DIRECT_GROUP:
1247         case NBDS_BROADCAST:
1248                 if (tree) {
1249                         proto_tree_add_text(nbdgm_tree, tvb, offset, 2,
1250                                         "Datagram length: %d bytes", header.dgm_length);
1251                         proto_tree_add_text(nbdgm_tree, tvb, offset+2, 2,
1252                                         "Packet offset: %d bytes", header.pkt_offset);
1253                 }
1254
1255                 offset += 4;
1256
1257                 /* Source name */
1258                 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1259
1260                 if (tree) {
1261                         add_name_and_type(nbdgm_tree, tvb, offset, len,
1262                             "Source name", name, name_type);
1263                 }
1264                 offset += len;
1265
1266                 /* Destination name */
1267                 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1268
1269                 if (tree) {
1270                         add_name_and_type(nbdgm_tree, tvb, offset, len,
1271                             "Destination name", name, name_type);
1272                 }
1273                 offset += len;
1274
1275                 /*
1276                  * Here we can pass the packet off to the next protocol.
1277                  * Set the length of our top-level tree item to include
1278                  * only our stuff.
1279                  *
1280                  * XXX - take the datagram length into account?
1281                  */
1282                 proto_item_set_len(ti, offset);
1283                 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1284                 dissect_netbios_payload(next_tvb, pinfo, tree);
1285                 break;
1286
1287         case NBDS_ERROR:
1288                 if (tree) {
1289                         proto_tree_add_text(nbdgm_tree, tvb, offset, 1, "Error code: %s",
1290                                 val_to_str(header.error_code, error_codes, "Unknown (0x%x)"));
1291                 }
1292                 offset += 1;
1293                 proto_item_set_len(ti, offset);
1294                 break;
1295
1296         case NBDS_QUERY_REQUEST:
1297         case NBDS_POS_QUERY_RESPONSE:
1298         case NBDS_NEG_QUERY_RESPONSE:
1299                 /* Destination name */
1300                 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1301
1302                 if (tree) {
1303                         add_name_and_type(nbdgm_tree, tvb, offset, len,
1304                             "Destination name", name, name_type);
1305                 }
1306                 offset += len;
1307                 proto_item_set_len(ti, offset);
1308                 break;
1309         }
1310 }
1311
1312 /*
1313  * NetBIOS Session Service message types.
1314  */
1315 #define SESSION_MESSAGE                 0x00
1316 #define SESSION_REQUEST                 0x81
1317 #define POSITIVE_SESSION_RESPONSE       0x82
1318 #define NEGATIVE_SESSION_RESPONSE       0x83
1319 #define RETARGET_SESSION_RESPONSE       0x84
1320 #define SESSION_KEEP_ALIVE              0x85
1321
1322 static const value_string message_types[] = {
1323         { SESSION_MESSAGE,           "Session message" },
1324         { SESSION_REQUEST,           "Session request" },
1325         { POSITIVE_SESSION_RESPONSE, "Positive session response" },
1326         { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
1327         { RETARGET_SESSION_RESPONSE, "Retarget session response" },
1328         { SESSION_KEEP_ALIVE,        "Session keep-alive" },
1329         { 0x0,                       NULL }
1330 };
1331
1332 /*
1333  * NetBIOS Session Service flags.
1334  */
1335 #define NBSS_FLAGS_E                    0x1
1336
1337 static const value_string error_codes[] = {
1338         { 0x80, "Not listening on called name" },
1339         { 0x81, "Not listening for called name" },
1340         { 0x82, "Called name not present" },
1341         { 0x83, "Called name present, but insufficient resources" },
1342         { 0x8F, "Unspecified error" },
1343         { 0x0,  NULL }
1344 };
1345
1346 /*
1347  * Dissect a single NBSS packet (there may be more than one in a given
1348  * TCP segment).
1349  *
1350  * [ Hmmm, in my experience, I have never seen more than one NBSS in a
1351  * single segment, since they mostly contain SMBs which are essentially
1352  * a request response type protocol (RJS). ]
1353  *
1354  * [ However, under heavy load with many requests multiplexed on one
1355  * session it is not unusual to see multiple requests in one TCP
1356  * segment. Unfortunately, in this case a single session message is
1357  * frequently split over multiple segments, which frustrates decoding
1358  * (MMM). ]
1359  */
1360 static int
1361 dissect_nbss_packet(tvbuff_t *tvb, int offset, packet_info *pinfo,
1362     proto_tree *tree, int is_cifs)
1363 {
1364         proto_tree      *nbss_tree = NULL;
1365         proto_item      *ti = NULL;
1366         proto_tree      *field_tree;
1367         proto_item      *tf;
1368         guint8          msg_type;
1369         guint8          flags;
1370         volatile int    length;
1371         int             length_remaining;
1372         int             len;
1373         char            name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1374         int             name_type;
1375         gint            reported_len;
1376         tvbuff_t        *next_tvb;
1377         const char      *saved_proto;
1378
1379         /* Desegmentation */
1380         length_remaining = tvb_length_remaining(tvb, offset);
1381
1382         /*
1383          * Can we do reassembly?
1384          */
1385         if (nbss_desegment && pinfo->can_desegment) {
1386                 /*
1387                  * Yes - is the NBSS header split across segment boundaries?
1388                  */
1389                 if (length_remaining < 4) {
1390                         /*
1391                          * Yes.  Tell our caller how many more bytes
1392                          * we need.
1393                          */
1394                         return -(4 - length_remaining);
1395                 }
1396         }
1397
1398         /*
1399          * Get the length of the NBSS message.
1400          */
1401         if (is_cifs) {
1402                 flags = 0;
1403                 length = tvb_get_ntoh24(tvb, offset + 1);
1404         } else {
1405                 flags = tvb_get_guint8(tvb, offset + 1);
1406                 length = tvb_get_ntohs(tvb, offset + 2);
1407                 if (flags & NBSS_FLAGS_E)
1408                         length += 65536;
1409         }
1410
1411         /*
1412          * Can we do reassembly?
1413          */
1414         if (nbss_desegment && pinfo->can_desegment) {
1415                 /*
1416                  * Yes - is the NBSS message split across segment boundaries?
1417                  */
1418                 if (length_remaining < length + 4) {
1419                         /*
1420                          * Yes.  Tell our caller how many more bytes
1421                          * we need.
1422                          */
1423                         return -((length + 4) - length_remaining);
1424                 }
1425         }
1426
1427         msg_type = tvb_get_guint8(tvb, offset);
1428
1429         if (tree) {
1430           ti = proto_tree_add_item(tree, proto_nbss, tvb, offset, length + 4, FALSE);
1431           nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1432           
1433           proto_tree_add_uint_format(nbss_tree, hf_nbss_type, tvb,
1434                                      offset, 1, 
1435                                      msg_type,
1436                                      "Message Type: %s",
1437                                      val_to_str(msg_type, message_types, 
1438                                                 "Unknown (%x)"));
1439         }
1440
1441         offset += 1;
1442
1443         if (is_cifs) {
1444                 if (tree) {
1445                   proto_tree_add_text(nbss_tree, tvb, offset, 3, "Length: %u", length);
1446                 }
1447                 offset += 3;
1448         } else {
1449                 if (tree) {
1450                   tf = proto_tree_add_uint(nbss_tree, hf_nbss_flags, tvb, offset, 1, flags);
1451                   field_tree = proto_item_add_subtree(tf, ett_nbss_flags);
1452                   proto_tree_add_text(field_tree, tvb, offset, 1, "%s",
1453                               decode_boolean_bitfield(flags, NBSS_FLAGS_E,
1454                                                               8, "Add 65536 to length", "Add 0 to length"));
1455                 }
1456                 offset += 1;
1457
1458                 if (tree) {
1459                   proto_tree_add_text(nbss_tree, tvb, offset, 2, "Length: %u", length);
1460                 }
1461
1462                 offset += 2;
1463         }
1464
1465         switch (msg_type) {
1466
1467         case SESSION_REQUEST:
1468           len = get_nbns_name(tvb, offset, offset, name, &name_type);
1469           if (tree)
1470             add_name_and_type(nbss_tree, tvb, offset, len,
1471                                 "Called name", name, name_type);
1472           offset += len;
1473
1474           len = get_nbns_name(tvb, offset, offset, name, &name_type);
1475           
1476           if (tree)
1477             add_name_and_type(nbss_tree, tvb, offset, len,
1478                                 "Calling name", name, name_type);
1479
1480           break;
1481
1482         case NEGATIVE_SESSION_RESPONSE:
1483           if (tree) 
1484             proto_tree_add_text(nbss_tree, tvb, offset, 1,
1485                                 "Error code: %s",
1486                                 val_to_str(tvb_get_guint8(tvb, offset),
1487                                            error_codes, "Unknown (%x)"));
1488           break;
1489
1490         case RETARGET_SESSION_RESPONSE:
1491           if (tree)
1492             proto_tree_add_text(nbss_tree, tvb, offset, 4,
1493                                 "Retarget IP address: %s",
1494                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1495           
1496           offset += 4;
1497
1498           if (tree)
1499             proto_tree_add_text(nbss_tree, tvb, offset, 2,
1500                                 "Retarget port: %u",
1501                                 tvb_get_ntohs(tvb, offset));
1502
1503           break;
1504
1505         case SESSION_MESSAGE:
1506           /*
1507            * Here we can pass the message off to the next protocol.
1508            * Set the length of our top-level tree item to include
1509            * only our stuff.
1510            */
1511           proto_item_set_len(ti, offset);
1512           len = tvb_length_remaining(tvb, offset);
1513           reported_len = tvb_reported_length_remaining(tvb, offset);
1514           if (len > length)
1515             len = length;
1516           if (reported_len > length)
1517             reported_len = length;
1518
1519           next_tvb = tvb_new_subset(tvb, offset, len, reported_len);
1520
1521           /*
1522            * Catch the ReportedBoundsError exception; if this
1523            * particular message happens to get a ReportedBoundsError
1524            * exception, that doesn't mean that we should stop
1525            * dissecting NetBIOS messages within this frame or chunk
1526            * of reassembled data.
1527            *
1528            * If it gets a BoundsError, we can stop, as there's nothing
1529            * more to see, so we just re-throw it.
1530            */
1531           saved_proto = pinfo->current_proto;
1532           TRY {
1533             dissect_netbios_payload(next_tvb, pinfo, tree);
1534           }
1535           CATCH(BoundsError) {
1536             RETHROW;
1537           }
1538           CATCH(ReportedBoundsError) {
1539             show_reported_bounds_error(tvb, pinfo, tree);
1540             pinfo->current_proto = saved_proto;
1541           }
1542           ENDTRY;
1543           break;
1544
1545         }
1546         return length + 4;
1547 }
1548
1549 static void
1550 dissect_nbss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1551 {
1552         struct tcpinfo  *tcpinfo = pinfo->private_data;
1553         int             offset = 0;
1554         int             max_data;
1555         guint8          msg_type;
1556         guint8          flags;
1557         guint32         length;
1558         int             len;
1559         gboolean        is_cifs;
1560         proto_tree      *nbss_tree;
1561         proto_item      *ti;
1562
1563         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1564                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBSS");
1565         if (check_col(pinfo->cinfo, COL_INFO))
1566                 col_clear(pinfo->cinfo, COL_INFO);
1567
1568         max_data = tvb_length(tvb);
1569
1570         msg_type = tvb_get_guint8(tvb, offset);
1571
1572         if (pinfo->match_port == TCP_PORT_CIFS) {
1573                 /*
1574                  * Windows 2000 CIFS clients can dispense completely
1575                  * with the NETBIOS encapsulation and directly use CIFS
1576                  * over TCP. As would be expected, the framing is
1577                  * identical, except that the length is 24 bits instead
1578                  * of 17. The only message types used are
1579                  * SESSION_MESSAGE and SESSION_KEEP_ALIVE.
1580                  */
1581                 is_cifs = TRUE;
1582         } else {
1583                 is_cifs = FALSE;
1584         }
1585
1586         /*
1587          * This might be a continuation of an earlier message.
1588          * (Yes, that might be true even if we're doing TCP reassembly,
1589          * as the first TCP segment in the capture might start in the
1590          * middle of an NBNS message.)
1591          */
1592
1593         /*
1594          * If this isn't reassembled data, check to see whether it
1595          * looks like a continuation of a message.
1596          * (If it is reassembled data, it shouldn't be a continuation,
1597          * as reassembly should've gathered the continuations together
1598          * into a message.)
1599          */
1600         if (!tcpinfo->is_reassembled) {
1601                 if (max_data < 4) {
1602                         /*
1603                          * Not enough data for an NBSS header; assume
1604                          * it's a continuation of a message.
1605                          *
1606                          * XXX - if there's not enough data, we should
1607                          * attempt to reassemble the data, if the first byte
1608                          * is a valid message type.
1609                          */
1610                         goto continuation;
1611                 }
1612
1613                 /*
1614                  * We have enough data for an NBSS header.
1615                  * Get the flags and length of the message,
1616                  * and see if they're sane.
1617                  */
1618                 if (is_cifs) {
1619                         flags = 0;
1620                         length = tvb_get_ntoh24(tvb, offset + 1);
1621                 } else {
1622                         flags = tvb_get_guint8(tvb, offset + 1);
1623                         length = tvb_get_ntohs(tvb, offset + 2);
1624                         if (flags & NBSS_FLAGS_E)
1625                                 length += 65536;
1626                 }
1627                 if ((flags & (~NBSS_FLAGS_E)) != 0) {
1628                         /*
1629                          * A bogus flag was set; assume it's a continuation.
1630                          */
1631                         goto continuation;
1632                 }
1633
1634                 switch (msg_type) {
1635
1636                 case SESSION_MESSAGE:
1637                         /*
1638                          * This is variable-length.
1639                          * All we know is that it shouldn't be zero.
1640                          * (XXX - can we get zero-length messages?
1641                          * Not with SMB, but perhaps other NetBIOS-based
1642                          * protocols have them.)
1643                          */
1644                         if (length == 0)
1645                                 goto continuation;
1646                         break;
1647
1648                 case SESSION_REQUEST:
1649                         /*
1650                          * This is variable-length.
1651                          * The names are DNS-encoded 32-byte values;
1652                          * we need at least 2 bytes (one for each name;
1653                          * actually, we should have more for the first
1654                          * name, as there's no name preceding it so
1655                          * there should be no compression), and we
1656                          * shouldn't have more than 128 bytes (actually,
1657                          * we shouldn't have that many).
1658                          *
1659                          * XXX - actually, MacOS X 10.1 (yes, that's
1660                          * redundant, but that's what Apple calls it,
1661                          * not MacOS X.1) puts names longer than 16
1662                          * characters into session request messages,
1663                          * so we can have more than 32 bytes of
1664                          * name value, so we can have more than 128
1665                          * bytes of data.
1666                          */
1667                         if (length < 2 || length > 256)
1668                                 goto continuation;
1669                         break;
1670
1671                 case POSITIVE_SESSION_RESPONSE:
1672                         /*
1673                          * This has no data, so the length must be zero.
1674                          */
1675                         if (length != 0)
1676                                 goto continuation;
1677                         break;
1678
1679                 case NEGATIVE_SESSION_RESPONSE:
1680                         /*
1681                          * This has 1 byte of data.
1682                          */
1683                         if (length != 1)
1684                                 goto continuation;
1685                         break;
1686
1687                 case RETARGET_SESSION_RESPONSE:
1688                         /*
1689                          * This has 6 bytes of data.
1690                          */
1691                         if (length != 6)
1692                                 goto continuation;
1693                         break;
1694
1695                 case SESSION_KEEP_ALIVE:
1696                         /*
1697                          * This has no data, so the length must be zero.
1698                          */
1699                         if (length != 0)
1700                                 goto continuation;
1701                         break;
1702
1703                 default:
1704                         /*
1705                          * Unknown message type; assume it's a continuation.
1706                          */
1707                         goto continuation;
1708                 }
1709         }
1710  
1711         if (check_col(pinfo->cinfo, COL_INFO)) {
1712                 col_add_fstr(pinfo->cinfo, COL_INFO,
1713                     val_to_str(msg_type, message_types, "Unknown (%02x)"));
1714         }
1715
1716         while (tvb_reported_length_remaining(tvb, offset) > 0) {
1717                 len = dissect_nbss_packet(tvb, offset, pinfo, tree, is_cifs);
1718                 if (len < 0) {
1719                         /*
1720                          * We need more data to dissect this, and
1721                          * desegmentation is enabled.  "-len" is the
1722                          * number of additional bytes of data we need.
1723                          *
1724                          * Tell the TCP dissector where the data for this
1725                          * message starts in the data it handed us, and
1726                          * how many more bytes we need, and return.
1727                          */
1728                         pinfo->desegment_offset = offset;
1729                         pinfo->desegment_len = -len;
1730                         return;
1731                 }
1732                 offset += len;
1733         }
1734
1735         return;
1736
1737 continuation:
1738         /*
1739          * It looks like a continuation.
1740          */
1741         if (check_col(pinfo->cinfo, COL_INFO))
1742                 col_add_fstr(pinfo->cinfo, COL_INFO, "NBSS Continuation Message");
1743
1744         if (tree) {
1745                 ti = proto_tree_add_item(tree, proto_nbss, tvb, 0, -1, FALSE);
1746                 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1747                 proto_tree_add_text(nbss_tree, tvb, 0, -1, "Continuation data");
1748         }
1749 }
1750
1751 void
1752 proto_register_nbt(void)
1753 {
1754
1755   static hf_register_info hf_nbns[] = {
1756     { &hf_nbns_flags,
1757       { "Flags",                "nbns.flags",
1758         FT_UINT16, BASE_HEX, NULL, 0x0,
1759         "", HFILL }},
1760     { &hf_nbns_flags_response,
1761       { "Response",             "nbns.flags.response",
1762         FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
1763         "Is the message a response?", HFILL }},
1764     { &hf_nbns_flags_opcode,
1765       { "Opcode",               "nbns.flags.opcode",
1766         FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
1767         "Operation code", HFILL }},
1768     { &hf_nbns_flags_authoritative,
1769       { "Authoritative",        "nbns.flags.authoritative",
1770         FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
1771         "Is the server is an authority for the domain?", HFILL }},
1772     { &hf_nbns_flags_truncated,
1773       { "Truncated",    "nbns.flags.truncated",
1774         FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
1775         "Is the message truncated?", HFILL }},
1776     { &hf_nbns_flags_recdesired,
1777       { "Recursion desired",    "nbns.flags.recdesired",
1778         FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
1779         "Do query recursively?", HFILL }},
1780     { &hf_nbns_flags_recavail,
1781       { "Recursion available",  "nbns.flags.recavail",
1782         FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
1783         "Can the server do recursive queries?", HFILL }},
1784     { &hf_nbns_flags_broadcast,
1785       { "Broadcast",            "nbns.flags.broadcast",
1786         FT_BOOLEAN, 16, TFS(&tfs_flags_broadcast), F_BROADCAST,
1787         "Is this a broadcast packet?", HFILL }},
1788     { &hf_nbns_flags_rcode,
1789       { "Reply code",           "nbns.flags.rcode",
1790         FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
1791         "Reply code", HFILL }},
1792     { &hf_nbns_transaction_id,
1793       { "Transaction ID",       "nbns.id",  
1794         FT_UINT16, BASE_HEX, NULL, 0x0,
1795         "Identification of transaction", HFILL }},
1796     { &hf_nbns_count_questions,
1797       { "Questions",            "nbns.count.queries",  
1798         FT_UINT16, BASE_DEC, NULL, 0x0,
1799         "Number of queries in packet", HFILL }},
1800     { &hf_nbns_count_answers,
1801       { "Answer RRs",           "nbns.count.answers",  
1802         FT_UINT16, BASE_DEC, NULL, 0x0,
1803         "Number of answers in packet", HFILL }},
1804     { &hf_nbns_count_auth_rr,
1805       { "Authority RRs",        "nbns.count.auth_rr",  
1806         FT_UINT16, BASE_DEC, NULL, 0x0,
1807         "Number of authoritative records in packet", HFILL }},
1808     { &hf_nbns_count_add_rr,
1809       { "Additional RRs",       "nbns.count.add_rr",  
1810         FT_UINT16, BASE_DEC, NULL, 0x0,
1811         "Number of additional records in packet", HFILL }}
1812   };
1813
1814   static hf_register_info hf_nbdgm[] = {
1815     { &hf_nbdgm_type,
1816       { "Message Type",         "nbdgm.type",  
1817         FT_UINT8, BASE_DEC, VALS(nbds_msgtype_vals), 0x0,
1818         "NBDGM message type", HFILL }},
1819     { &hf_nbdgm_fragment,
1820       { "More fragments follow",        "nbdgm.next",  
1821         FT_BOOLEAN, BASE_NONE, TFS(&yesno), 0x0,
1822         "TRUE if more fragments follow", HFILL }},
1823     { &hf_nbdgm_first,
1824       { "This is first fragment",       "nbdgm.first",  
1825         FT_BOOLEAN, BASE_NONE, TFS(&yesno), 0x0,
1826         "TRUE if first fragment", HFILL }},
1827     { &hf_nbdgm_node_type,
1828       { "Node Type",            "nbdgm.node_type",  
1829         FT_UINT8, BASE_DEC, VALS(node_type_vals), 0x0,
1830         "Node type", HFILL }},
1831     { &hf_nbdgm_datagram_id,
1832       { "Datagram ID",          "nbdgm.dgram_id",  
1833         FT_UINT16, BASE_HEX, NULL, 0x0,
1834         "Datagram identifier", HFILL }},
1835     { &hf_nbdgm_src_ip,
1836       { "Source IP",            "nbdgm.src.ip",  
1837         FT_IPv4, BASE_NONE, NULL, 0x0,
1838         "Source IPv4 address", HFILL }},
1839     { &hf_nbdgm_src_port,
1840       { "Source Port",          "nbdgm.src.port",
1841         FT_UINT16, BASE_DEC, NULL, 0x0,
1842         "Source port", HFILL }}
1843   };
1844
1845   static hf_register_info hf_nbss[] = {
1846     { &hf_nbss_type,
1847       { "Message Type",         "nbss.type",  
1848         FT_UINT8, BASE_DEC, NULL, 0x0,
1849         "NBSS message type", HFILL }},
1850     { &hf_nbss_flags,
1851       { "Flags",                "nbss.flags",  
1852         FT_UINT8, BASE_HEX, NULL, 0x0,
1853         "NBSS message flags", HFILL }}
1854   };
1855   static gint *ett[] = {
1856     &ett_nbns,
1857     &ett_nbns_qd,
1858     &ett_nbns_flags,
1859     &ett_nbns_nb_flags,
1860     &ett_nbns_name_flags,
1861     &ett_nbns_rr,
1862     &ett_nbns_qry,
1863     &ett_nbns_ans,
1864     &ett_nbdgm,
1865     &ett_nbss,
1866     &ett_nbss_flags,
1867   };
1868   module_t *nbss_module;
1869
1870   proto_nbns = proto_register_protocol("NetBIOS Name Service", "NBNS", "nbns");
1871   proto_register_field_array(proto_nbns, hf_nbns, array_length(hf_nbns));
1872   
1873   proto_nbdgm = proto_register_protocol("NetBIOS Datagram Service",
1874                                         "NBDS", "nbdgm");
1875   proto_register_field_array(proto_nbdgm, hf_nbdgm, array_length(hf_nbdgm));
1876
1877   proto_nbss = proto_register_protocol("NetBIOS Session Service",
1878                                        "NBSS", "nbss");
1879   proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));
1880
1881   proto_register_subtree_array(ett, array_length(ett));
1882
1883   nbss_module = prefs_register_protocol(proto_nbss, NULL);
1884   prefs_register_bool_preference(nbss_module, "desegment_nbss_commands",
1885     "Desegment all NBSS packets spanning multiple TCP segments",
1886     "Whether NBSS dissector should desegment all packets spanning multiple TCP segments",
1887     &nbss_desegment);
1888 }
1889
1890 void
1891 proto_reg_handoff_nbt(void)
1892 {
1893   dissector_handle_t nbns_handle, nbdgm_handle, nbss_handle;
1894
1895   nbns_handle = create_dissector_handle(dissect_nbns, proto_nbns);
1896   dissector_add("udp.port", UDP_PORT_NBNS, nbns_handle);
1897   nbdgm_handle = create_dissector_handle(dissect_nbdgm, proto_nbdgm);
1898   dissector_add("udp.port", UDP_PORT_NBDGM, nbdgm_handle);
1899   nbss_handle = create_dissector_handle(dissect_nbss, proto_nbss);
1900   dissector_add("tcp.port", TCP_PORT_NBSS, nbss_handle);
1901   dissector_add("tcp.port", TCP_PORT_CIFS, nbss_handle);
1902 }