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