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