Put the "-s" option in the SYNOPSIS section.
[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.69 2002/01/07 00:57:46 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 "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, 0, "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                 if (add_off <= 0) {
937                         /* We ran past the end of the captured data in the
938                            packet. */
939                         break;
940                 }
941                 cur_off += add_off;
942         }
943         if (ti != NULL)
944                 proto_item_set_len(ti, cur_off - start_off);
945
946         return cur_off - start_off;
947 }
948
949
950
951 static int
952 dissect_answer_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
953     int count, column_info *cinfo, proto_tree *nbns_tree, int opcode,
954     char *name)
955 {
956         int start_off, add_off;
957         proto_tree *qatree = NULL;
958         proto_item *ti = NULL;
959         
960         start_off = cur_off;
961         if (nbns_tree != NULL) {
962                 ti = proto_tree_add_text(nbns_tree, tvb, start_off, 0, name);
963                 qatree = proto_item_add_subtree(ti, ett_nbns_ans);
964         }
965         while (count-- > 0) {
966                 add_off = dissect_nbns_answer(tvb, cur_off, nbns_data_offset,
967                                         cinfo, qatree, opcode);
968                 if (add_off <= 0) {
969                         /* We ran past the end of the captured data in the
970                            packet. */
971                         break;
972                 }
973                 cur_off += add_off;
974         }
975         if (ti != NULL)
976                 proto_item_set_len(ti, cur_off - start_off);
977         return cur_off - start_off;
978 }
979
980 static void
981 dissect_nbns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
982 {
983         int                     offset = 0;
984         int                     nbns_data_offset;
985         column_info             *cinfo;
986         proto_tree              *nbns_tree = NULL;
987         proto_item              *ti;
988         guint16                 id, flags, quest, ans, auth, add;
989         int                     cur_off;
990
991         nbns_data_offset = offset;
992
993         if (check_col(pinfo->cinfo, COL_PROTOCOL))
994                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBNS");
995         if (check_col(pinfo->cinfo, COL_INFO))
996                 col_clear(pinfo->cinfo, COL_INFO);
997
998         /* To do: check for runts, errs, etc. */
999         id    = tvb_get_ntohs(tvb, offset + NBNS_ID);
1000         flags = tvb_get_ntohs(tvb, offset + NBNS_FLAGS);
1001
1002         if (check_col(pinfo->cinfo, COL_INFO)) {
1003                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s",
1004                     val_to_str(flags & F_OPCODE, opcode_vals,
1005                       "Unknown operation (%x)"),
1006                     (flags & F_RESPONSE) ? " response" : "");
1007                 cinfo = pinfo->cinfo;
1008         } else {
1009                 /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query
1010                    and answer dissectors, as a way of saying that they
1011                    shouldn't add stuff to the COL_INFO column (a call to
1012                    "check_col(cinfo, COL_INFO)" is more expensive than
1013                    a check that a pointer isn't NULL). */
1014                 cinfo = NULL;
1015         }
1016
1017         if (tree) {
1018                 ti = proto_tree_add_item(tree, proto_nbns, tvb, offset,
1019                     tvb_length(tvb), FALSE);
1020                 nbns_tree = proto_item_add_subtree(ti, ett_nbns);
1021
1022                 if (flags & F_RESPONSE) {
1023                         proto_tree_add_boolean_hidden(nbns_tree, hf_nbns_response, tvb, 
1024                                              0, 0, TRUE);
1025                 } else {
1026                         proto_tree_add_boolean_hidden(nbns_tree, hf_nbns_query, tvb, 
1027                                              0, 0, TRUE);
1028                 }
1029
1030                 proto_tree_add_uint(nbns_tree, hf_nbns_transaction_id, tvb,
1031                                     offset + NBNS_ID, 2, id);
1032
1033                 nbns_add_nbns_flags(nbns_tree, tvb, offset + NBNS_FLAGS,
1034                                     flags, 0);
1035         }
1036         quest = tvb_get_ntohs(tvb, offset + NBNS_QUEST);
1037         if (tree) {
1038                 proto_tree_add_uint(nbns_tree, hf_nbns_count_questions, tvb,
1039                                     offset + NBNS_QUEST, 2, quest);
1040         }
1041         ans = tvb_get_ntohs(tvb, offset + NBNS_ANS);
1042         if (tree) {
1043                 proto_tree_add_uint(nbns_tree, hf_nbns_count_answers, tvb,
1044                                     offset + NBNS_ANS, 2, ans);
1045         }
1046         auth = tvb_get_ntohs(tvb, offset + NBNS_AUTH);
1047         if (tree) {
1048                 proto_tree_add_uint(nbns_tree, hf_nbns_count_auth_rr, tvb,
1049                                     offset + NBNS_AUTH, 2, auth);
1050         }
1051         add = tvb_get_ntohs(tvb, offset + NBNS_ADD);
1052         if (tree) {
1053                 proto_tree_add_uint(nbns_tree, hf_nbns_count_add_rr, tvb,
1054                                     offset + NBNS_ADD, 2, add);
1055         }
1056
1057         cur_off = offset + NBNS_HDRLEN;
1058     
1059         if (quest > 0) {
1060                 /* If this is a response, don't add information about the
1061                    queries to the summary, just add information about the
1062                    answers. */
1063                 cur_off += dissect_query_records(tvb, cur_off,
1064                     nbns_data_offset, quest,
1065                     (!(flags & F_RESPONSE) ? cinfo : NULL), nbns_tree);
1066         }
1067
1068         if (ans > 0) {
1069                 /* If this is a request, don't add information about the
1070                    answers to the summary, just add information about the
1071                    queries. */
1072                 cur_off += dissect_answer_records(tvb, cur_off,
1073                         nbns_data_offset, ans,
1074                         ((flags & F_RESPONSE) ? cinfo : NULL), nbns_tree,
1075                         flags & F_OPCODE, "Answers");
1076         }
1077
1078         if (tree) {
1079                 /* Don't add information about the authoritative name
1080                    servers, or the additional records, to the summary. */
1081                 if (auth > 0)
1082                         cur_off += dissect_answer_records(tvb, cur_off,
1083                                         nbns_data_offset,
1084                                         auth, NULL, nbns_tree,
1085                                         flags & F_OPCODE,
1086                                         "Authoritative nameservers");
1087
1088                 if (add > 0)
1089                         cur_off += dissect_answer_records(tvb, cur_off,
1090                                         nbns_data_offset,
1091                                         add, NULL, nbns_tree,
1092                                         flags & F_OPCODE,
1093                                         "Additional records");
1094         }
1095 }
1096
1097 /* NetBIOS datagram packet, from RFC 1002, page 32 */
1098 struct nbdgm_header {
1099         guint8          msg_type;
1100         struct {
1101                 guint8  more;
1102                 guint8  first;
1103                 guint8  node_type;
1104         } flags;
1105         guint16         dgm_id;
1106         guint32         src_ip;
1107         guint16         src_port;
1108
1109         /* For packets with data */
1110         guint16         dgm_length;
1111         guint16         pkt_offset;
1112
1113         /* For error packets */
1114         guint8          error_code;
1115 };
1116
1117 /*
1118  * NBDS message types.
1119  */
1120 #define NBDS_DIRECT_UNIQUE      0x10
1121 #define NBDS_DIRECT_GROUP       0x11
1122 #define NBDS_BROADCAST          0x12
1123 #define NBDS_ERROR              0x13
1124 #define NBDS_QUERY_REQUEST      0x14
1125 #define NBDS_POS_QUERY_RESPONSE 0x15
1126 #define NBDS_NEG_QUERY_RESPONSE 0x16
1127
1128 static const value_string nbds_msgtype_vals[] = {
1129         { NBDS_DIRECT_UNIQUE,      "Direct_unique datagram" },
1130         { NBDS_DIRECT_GROUP,       "Direct_group datagram" },
1131         { NBDS_BROADCAST,          "Broadcast datagram" },
1132         { NBDS_ERROR,              "Datagram error" },
1133         { NBDS_QUERY_REQUEST,      "Datagram query request" },
1134         { NBDS_POS_QUERY_RESPONSE, "Datagram positive query response" },
1135         { NBDS_NEG_QUERY_RESPONSE, "Datagram negative query response" },
1136         { 0,                       NULL }
1137 };
1138
1139 static const true_false_string yesno = {  
1140         "Yes",
1141         "No"
1142 };
1143
1144 static const value_string node_type_vals[] = {
1145         { 0, "B node" },
1146         { 1, "P node" },
1147         { 2, "M node" },
1148         { 3, "NBDD" },
1149         { 0, NULL }
1150 };
1151
1152 static void
1153 dissect_nbdgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1154 {
1155         int                     offset = 0;
1156         proto_tree              *nbdgm_tree = NULL;
1157         proto_item              *ti = NULL;
1158         struct nbdgm_header     header;
1159         int                     flags;
1160         int                     message_index;
1161         tvbuff_t                *next_tvb;
1162
1163         static const value_string error_codes[] = {
1164                 { 0x82, "Destination name not present" },
1165                 { 0x83, "Invalid source name format" },
1166                 { 0x84, "Invalid destination name format" },
1167                 { 0x00, NULL }
1168         };
1169
1170         char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1171         int name_type;
1172         int len;
1173
1174         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1175                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBDS");
1176         if (check_col(pinfo->cinfo, COL_INFO))
1177                 col_clear(pinfo->cinfo, COL_INFO);
1178
1179         header.msg_type = tvb_get_guint8(tvb, offset);
1180         
1181         flags = tvb_get_guint8(tvb, offset+1);
1182         header.flags.more = flags & 1;
1183         header.flags.first = (flags & 2) >> 1;
1184         header.flags.node_type = (flags & 12) >> 2;
1185
1186         header.dgm_id = tvb_get_ntohs(tvb, offset+2);
1187         tvb_memcpy(tvb, (guint8 *)&header.src_ip, offset+4, 4);
1188         header.src_port = tvb_get_ntohs(tvb, offset+8);
1189
1190         switch (header.msg_type) {
1191
1192         case NBDS_DIRECT_UNIQUE:
1193         case NBDS_DIRECT_GROUP:
1194         case NBDS_BROADCAST:
1195                 header.dgm_length = tvb_get_ntohs(tvb, offset+10);
1196                 header.pkt_offset = tvb_get_ntohs(tvb, offset+12);
1197                 break;
1198
1199         case NBDS_ERROR:
1200                 header.error_code = tvb_get_ntohs(tvb, offset+10);
1201                 break;
1202         }
1203
1204         message_index = header.msg_type - 0x0f;
1205         if (message_index < 1 || message_index > 8) {
1206                 message_index = 0;
1207         }
1208
1209         if (check_col(pinfo->cinfo, COL_INFO)) {
1210                 col_add_str(pinfo->cinfo, COL_INFO,
1211                     val_to_str(header.msg_type, nbds_msgtype_vals,
1212                       "Unknown message type (0x%02X)"));
1213         }
1214
1215         if (tree) {
1216                 ti = proto_tree_add_item(tree, proto_nbdgm, tvb, offset,
1217                     tvb_length_remaining(tvb, offset), FALSE);
1218                 nbdgm_tree = proto_item_add_subtree(ti, ett_nbdgm);
1219
1220                 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_type, tvb,
1221                                      offset, 1, 
1222                                      header.msg_type);
1223                 proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_fragment, tvb,
1224                                        offset+1, 1, 
1225                                        header.flags.more);
1226                 proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_first, tvb,
1227                                        offset+1, 1, 
1228                                        header.flags.first);
1229                 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_node_type, tvb,
1230                                      offset+1, 1, 
1231                                      header.flags.node_type);
1232
1233                 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_datagram_id, tvb,
1234                                     offset+2, 2, header.dgm_id);
1235                 proto_tree_add_ipv4(nbdgm_tree, hf_nbdgm_src_ip, tvb,
1236                                     offset+4, 4, header.src_ip);
1237                 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_src_port, tvb,
1238                                     offset+8, 2, header.src_port);
1239
1240         }
1241
1242         offset += 10;
1243
1244         switch (header.msg_type) {
1245
1246         case NBDS_DIRECT_UNIQUE:
1247         case NBDS_DIRECT_GROUP:
1248         case NBDS_BROADCAST:
1249                 if (tree) {
1250                         proto_tree_add_text(nbdgm_tree, tvb, offset, 2,
1251                                         "Datagram length: %d bytes", header.dgm_length);
1252                         proto_tree_add_text(nbdgm_tree, tvb, offset+2, 2,
1253                                         "Packet offset: %d bytes", header.pkt_offset);
1254                 }
1255
1256                 offset += 4;
1257
1258                 /* Source name */
1259                 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1260
1261                 if (tree) {
1262                         add_name_and_type(nbdgm_tree, tvb, offset, len,
1263                             "Source name", name, name_type);
1264                 }
1265                 offset += len;
1266
1267                 /* Destination name */
1268                 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1269
1270                 if (tree) {
1271                         add_name_and_type(nbdgm_tree, tvb, offset, len,
1272                             "Destination name", name, name_type);
1273                 }
1274                 offset += len;
1275
1276                 /*
1277                  * Here we can pass the packet off to the next protocol.
1278                  * Set the length of our top-level tree item to include
1279                  * only our stuff.
1280                  *
1281                  * XXX - take the datagram length into account?
1282                  */
1283                 proto_item_set_len(ti, offset);
1284                 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1285                 dissect_netbios_payload(next_tvb, pinfo, tree);
1286                 break;
1287
1288         case NBDS_ERROR:
1289                 if (tree) {
1290                         proto_tree_add_text(nbdgm_tree, tvb, offset, 1, "Error code: %s",
1291                                 val_to_str(header.error_code, error_codes, "Unknown (0x%x)"));
1292                 }
1293                 offset += 1;
1294                 proto_item_set_len(ti, offset);
1295                 break;
1296
1297         case NBDS_QUERY_REQUEST:
1298         case NBDS_POS_QUERY_RESPONSE:
1299         case NBDS_NEG_QUERY_RESPONSE:
1300                 /* Destination name */
1301                 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1302
1303                 if (tree) {
1304                         add_name_and_type(nbdgm_tree, tvb, offset, len,
1305                             "Destination name", name, name_type);
1306                 }
1307                 offset += len;
1308                 proto_item_set_len(ti, offset);
1309                 break;
1310         }
1311 }
1312
1313 /*
1314  * NetBIOS Session Service message types.
1315  */
1316 #define SESSION_MESSAGE                 0x00
1317 #define SESSION_REQUEST                 0x81
1318 #define POSITIVE_SESSION_RESPONSE       0x82
1319 #define NEGATIVE_SESSION_RESPONSE       0x83
1320 #define RETARGET_SESSION_RESPONSE       0x84
1321 #define SESSION_KEEP_ALIVE              0x85
1322
1323 static const value_string message_types[] = {
1324         { SESSION_MESSAGE,           "Session message" },
1325         { SESSION_REQUEST,           "Session request" },
1326         { POSITIVE_SESSION_RESPONSE, "Positive session response" },
1327         { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
1328         { RETARGET_SESSION_RESPONSE, "Retarget session response" },
1329         { SESSION_KEEP_ALIVE,        "Session keep-alive" },
1330         { 0x0,                       NULL }
1331 };
1332
1333 /*
1334  * NetBIOS Session Service flags.
1335  */
1336 #define NBSS_FLAGS_E                    0x1
1337
1338 static const value_string error_codes[] = {
1339         { 0x80, "Not listening on called name" },
1340         { 0x81, "Not listening for called name" },
1341         { 0x82, "Called name not present" },
1342         { 0x83, "Called name present, but insufficient resources" },
1343         { 0x8F, "Unspecified error" },
1344         { 0x0,  NULL }
1345 };
1346
1347 /*
1348  * Dissect a single NBSS packet (there may be more than one in a given
1349  * TCP segment).
1350  *
1351  * [ Hmmm, in my experience, I have never seen more than one NBSS in a
1352  * single segment, since they mostly contain SMBs which are essentially
1353  * a request response type protocol (RJS). ]
1354  *
1355  * [ However, under heavy load with many requests multiplexed on one
1356  * session it is not unusual to see multiple requests in one TCP
1357  * segment. Unfortunately, in this case a single session message is
1358  * frequently split over multiple segments, which frustrates decoding
1359  * (MMM). ]
1360  */
1361 static int
1362 dissect_nbss_packet(tvbuff_t *tvb, int offset, packet_info *pinfo,
1363     proto_tree *tree, int max_data, int is_cifs)
1364 {
1365         proto_tree      *nbss_tree = NULL;
1366         proto_item      *ti = NULL;
1367         proto_tree      *field_tree;
1368         proto_item      *tf;
1369         guint8          msg_type;
1370         guint8          flags;
1371         volatile int    length;
1372         int             len;
1373         char            name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1374         int             name_type;
1375         gint            reported_len;
1376         tvbuff_t        *next_tvb;
1377         const char      *saved_proto;
1378
1379         msg_type = tvb_get_guint8(tvb, offset);
1380
1381         if (is_cifs) {
1382                 flags = 0;
1383                 length = tvb_get_ntoh24(tvb, offset + 1);
1384         } else {
1385                 flags = tvb_get_guint8(tvb, offset + 1);
1386                 length = tvb_get_ntohs(tvb, offset + 2);
1387                 if (flags & NBSS_FLAGS_E)
1388                         length += 65536;
1389         }
1390
1391         /*Desegmentation */
1392         if (nbss_desegment) {
1393                 if (pinfo->can_desegment
1394                     && length > tvb_length_remaining(tvb, offset+4)) {
1395                         /*
1396                          * This frame doesn't have all of the data for
1397                          * this message, but we can do reassembly on it.
1398                          *
1399                          * Tell the TCP dissector where the data for this
1400                          * message starts in the data it handed us, and
1401                          * how many more bytes we need, and return.
1402                          */
1403                         pinfo->desegment_offset = offset;
1404                         pinfo->desegment_len =
1405                             length - tvb_length_remaining(tvb, offset+4);
1406                         return max_data;
1407                 }
1408         }
1409
1410         if (tree) {
1411           ti = proto_tree_add_item(tree, proto_nbss, tvb, offset, length + 4, FALSE);
1412           nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1413           
1414           proto_tree_add_uint_format(nbss_tree, hf_nbss_type, tvb,
1415                                      offset, 1, 
1416                                      msg_type,
1417                                      "Message Type: %s",
1418                                      val_to_str(msg_type, message_types, 
1419                                                 "Unknown (%x)"));
1420         }
1421
1422         offset += 1;
1423
1424         if (is_cifs) {
1425                 if (tree) {
1426                   proto_tree_add_text(nbss_tree, tvb, offset, 3, "Length: %u", length);
1427                 }
1428                 offset += 3;
1429         } else {
1430                 if (tree) {
1431                   tf = proto_tree_add_uint(nbss_tree, hf_nbss_flags, tvb, offset, 1, flags);
1432                   field_tree = proto_item_add_subtree(tf, ett_nbss_flags);
1433                   proto_tree_add_text(field_tree, tvb, offset, 1, "%s",
1434                               decode_boolean_bitfield(flags, NBSS_FLAGS_E,
1435                                                               8, "Add 65536 to length", "Add 0 to length"));
1436                 }
1437                 offset += 1;
1438
1439                 if (tree) {
1440                   proto_tree_add_text(nbss_tree, tvb, offset, 2, "Length: %u", length);
1441                 }
1442
1443                 offset += 2;
1444         }
1445
1446         switch (msg_type) {
1447
1448         case SESSION_REQUEST:
1449           len = get_nbns_name(tvb, offset, offset, name, &name_type);
1450           if (tree)
1451             add_name_and_type(nbss_tree, tvb, offset, len,
1452                                 "Called name", name, name_type);
1453           offset += len;
1454
1455           len = get_nbns_name(tvb, offset, offset, name, &name_type);
1456           
1457           if (tree)
1458             add_name_and_type(nbss_tree, tvb, offset, len,
1459                                 "Calling name", name, name_type);
1460
1461           break;
1462
1463         case NEGATIVE_SESSION_RESPONSE:
1464           if (tree) 
1465             proto_tree_add_text(nbss_tree, tvb, offset, 1,
1466                                 "Error code: %s",
1467                                 val_to_str(tvb_get_guint8(tvb, offset),
1468                                            error_codes, "Unknown (%x)"));
1469           break;
1470
1471         case RETARGET_SESSION_RESPONSE:
1472           if (tree)
1473             proto_tree_add_text(nbss_tree, tvb, offset, 4,
1474                                 "Retarget IP address: %s",
1475                                 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1476           
1477           offset += 4;
1478
1479           if (tree)
1480             proto_tree_add_text(nbss_tree, tvb, offset, 2,
1481                                 "Retarget port: %u",
1482                                 tvb_get_ntohs(tvb, offset));
1483
1484           break;
1485
1486         case SESSION_MESSAGE:
1487           /*
1488            * Here we can pass the message off to the next protocol.
1489            * Set the length of our top-level tree item to include
1490            * only our stuff.
1491            */
1492           proto_item_set_len(ti, offset);
1493           len = tvb_length_remaining(tvb, offset);
1494           reported_len = tvb_reported_length_remaining(tvb, offset);
1495           if (len > length)
1496             len = length;
1497           if (reported_len > length)
1498             reported_len = length;
1499
1500           next_tvb = tvb_new_subset(tvb, offset, len, reported_len);
1501
1502           /*
1503            * Catch the ReportedBoundsError exception; if this
1504            * particular message happens to get a ReportedBoundsError
1505            * exception, that doesn't mean that we should stop
1506            * dissecting NetBIOS messages within this frame or chunk
1507            * of reassembled data.
1508            *
1509            * If it gets a BoundsError, we can stop, as there's nothing
1510            * more to see, so we just re-throw it.
1511            */
1512           saved_proto = pinfo->current_proto;
1513           TRY {
1514             dissect_netbios_payload(next_tvb, pinfo, tree);
1515           }
1516           CATCH(BoundsError) {
1517             RETHROW;
1518           }
1519           CATCH(ReportedBoundsError) {
1520             if (check_col(pinfo->cinfo, COL_INFO))
1521               col_append_str(pinfo->cinfo, COL_INFO, "[Malformed Packet]");
1522             proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0,
1523                                 "[Malformed Packet: %s]", pinfo->current_proto );
1524             pinfo->current_proto = saved_proto;
1525           }
1526           ENDTRY;
1527           break;
1528
1529         }
1530         return length + 4;
1531 }
1532
1533 static void
1534 dissect_nbss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1535 {
1536         struct tcpinfo  *tcpinfo = pinfo->private_data;
1537         int             offset = 0;
1538         int             max_data;
1539         guint8          msg_type;
1540         guint8          flags;
1541         guint32         length;
1542         int             len;
1543         gboolean        is_cifs;
1544         proto_tree      *nbss_tree;
1545         proto_item      *ti;
1546
1547         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1548                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBSS");
1549         if (check_col(pinfo->cinfo, COL_INFO))
1550                 col_clear(pinfo->cinfo, COL_INFO);
1551
1552         max_data = tvb_length(tvb);
1553
1554         msg_type = tvb_get_guint8(tvb, offset);
1555
1556         if (pinfo->match_port == TCP_PORT_CIFS) {
1557                 /*
1558                  * Windows 2000 CIFS clients can dispense completely
1559                  * with the NETBIOS encapsulation and directly use CIFS
1560                  * over TCP. As would be expected, the framing is
1561                  * identical, except that the length is 24 bits instead
1562                  * of 17. The only message types used are
1563                  * SESSION_MESSAGE and SESSION_KEEP_ALIVE.
1564                  */
1565                 is_cifs = TRUE;
1566         } else {
1567                 is_cifs = FALSE;
1568         }
1569
1570         /*
1571          * This might be a continuation of an earlier message.
1572          * (Yes, that might be true even if we're doing TCP reassembly,
1573          * as the first TCP segment in the capture might start in the
1574          * middle of an NBNS message.)
1575          */
1576
1577         /*
1578          * If this isn't reassembled data, check to see whether it
1579          * looks like a continuation of a message.
1580          * (If it is reassembled data, it shouldn't be a continuation,
1581          * as reassembly should've gathered the continuations together
1582          * into a message.)
1583          */
1584         if (!tcpinfo->is_reassembled) {
1585                 if (max_data < 4) {
1586                         /*
1587                          * Not enough data for an NBSS header; assume
1588                          * it's a continuation of a message.
1589                          *
1590                          * XXX - if there's not enough data, we should
1591                          * attempt to reassemble the data, if the first byte
1592                          * is a valid message type.
1593                          */
1594                         goto continuation;
1595                 }
1596
1597                 /*
1598                  * We have enough data for an NBSS header.
1599                  * Get the flags and length of the message,
1600                  * and see if they're sane.
1601                  */
1602                 if (is_cifs) {
1603                         flags = 0;
1604                         length = tvb_get_ntoh24(tvb, offset + 1);
1605                 } else {
1606                         flags = tvb_get_guint8(tvb, offset + 1);
1607                         length = tvb_get_ntohs(tvb, offset + 2);
1608                         if (flags & NBSS_FLAGS_E)
1609                                 length += 65536;
1610                 }
1611                 if ((flags & (~NBSS_FLAGS_E)) != 0) {
1612                         /*
1613                          * A bogus flag was set; assume it's a continuation.
1614                          */
1615                         goto continuation;
1616                 }
1617
1618                 switch (msg_type) {
1619
1620                 case SESSION_MESSAGE:
1621                         /*
1622                          * This is variable-length.
1623                          * All we know is that it shouldn't be zero.
1624                          * (XXX - can we get zero-length messages?
1625                          * Not with SMB, but perhaps other NetBIOS-based
1626                          * protocols have them.)
1627                          */
1628                         if (length == 0)
1629                                 goto continuation;
1630                         break;
1631
1632                 case SESSION_REQUEST:
1633                         /*
1634                          * This is variable-length.
1635                          * The names are DNS-encoded 32-byte values;
1636                          * we need at least 2 bytes (one for each name;
1637                          * actually, we should have more for the first
1638                          * name, as there's no name preceding it so
1639                          * there should be no compression), and we
1640                          * shouldn't have more than 128 bytes (actually,
1641                          * we shouldn't have that many).
1642                          *
1643                          * XXX - actually, MacOS X 10.1 (yes, that's
1644                          * redundant, but that's what Apple calls it,
1645                          * not MacOS X.1) puts names longer than 16
1646                          * characters into session request messages,
1647                          * so we can have more than 32 bytes of
1648                          * name value, so we can have more than 128
1649                          * bytes of data.
1650                          */
1651                         if (length < 2 || length > 256)
1652                                 goto continuation;
1653                         break;
1654
1655                 case POSITIVE_SESSION_RESPONSE:
1656                         /*
1657                          * This has no data, so the length must be zero.
1658                          */
1659                         if (length != 0)
1660                                 goto continuation;
1661                         break;
1662
1663                 case NEGATIVE_SESSION_RESPONSE:
1664                         /*
1665                          * This has 1 byte of data.
1666                          */
1667                         if (length != 1)
1668                                 goto continuation;
1669                         break;
1670
1671                 case RETARGET_SESSION_RESPONSE:
1672                         /*
1673                          * This has 6 bytes of data.
1674                          */
1675                         if (length != 6)
1676                                 goto continuation;
1677                         break;
1678
1679                 case SESSION_KEEP_ALIVE:
1680                         /*
1681                          * This has no data, so the length must be zero.
1682                          */
1683                         if (length != 0)
1684                                 goto continuation;
1685                         break;
1686
1687                 default:
1688                         /*
1689                          * Unknown message type; assume it's a continuation.
1690                          */
1691                         goto continuation;
1692                 }
1693         }
1694  
1695         if (check_col(pinfo->cinfo, COL_INFO)) {
1696                 col_add_fstr(pinfo->cinfo, COL_INFO,
1697                     val_to_str(msg_type, message_types, "Unknown (%02x)"));
1698         }
1699
1700         while (max_data > 0) {
1701                 len = dissect_nbss_packet(tvb, offset, pinfo, tree, max_data,
1702                     is_cifs);
1703                 offset += len;
1704                 max_data -= len;
1705         }
1706
1707         return;
1708
1709 continuation:
1710         /*
1711          * It looks like a continuation.
1712          */
1713         if (check_col(pinfo->cinfo, COL_INFO))
1714                 col_add_fstr(pinfo->cinfo, COL_INFO, "NBSS Continuation Message");
1715
1716         if (tree) {
1717                 ti = proto_tree_add_item(tree, proto_nbss, tvb, 0,
1718                     max_data, FALSE);
1719                 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1720                 proto_tree_add_text(nbss_tree, tvb, 0, max_data,
1721                     "Continuation data");
1722         }
1723 }
1724
1725 void
1726 proto_register_nbt(void)
1727 {
1728
1729   static hf_register_info hf_nbns[] = {
1730     { &hf_nbns_response,
1731       { "Response",             "nbns.response",  
1732         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1733         "TRUE if NBNS response", HFILL }},
1734     { &hf_nbns_query,
1735       { "Query",                "nbns.query",  
1736         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1737         "TRUE if NBNS query", HFILL }},
1738     { &hf_nbns_transaction_id,
1739       { "Transaction ID",       "nbns.id",  
1740         FT_UINT16, BASE_HEX, NULL, 0x0,
1741         "Identification of transaction", HFILL }},
1742     { &hf_nbns_count_questions,
1743       { "Questions",            "nbns.count.queries",  
1744         FT_UINT16, BASE_DEC, NULL, 0x0,
1745         "Number of queries in packet", HFILL }},
1746     { &hf_nbns_count_answers,
1747       { "Answer RRs",           "nbns.count.answers",  
1748         FT_UINT16, BASE_DEC, NULL, 0x0,
1749         "Number of answers in packet", HFILL }},
1750     { &hf_nbns_count_auth_rr,
1751       { "Authority RRs",        "nbns.count.auth_rr",  
1752         FT_UINT16, BASE_DEC, NULL, 0x0,
1753         "Number of authoritative records in packet", HFILL }},
1754     { &hf_nbns_count_add_rr,
1755       { "Additional RRs",       "nbns.count.add_rr",  
1756         FT_UINT16, BASE_DEC, NULL, 0x0,
1757         "Number of additional records in packet", HFILL }}
1758   };
1759
1760   static hf_register_info hf_nbdgm[] = {
1761     { &hf_nbdgm_type,
1762       { "Message Type",         "nbdgm.type",  
1763         FT_UINT8, BASE_DEC, VALS(nbds_msgtype_vals), 0x0,
1764         "NBDGM message type", HFILL }},
1765     { &hf_nbdgm_fragment,
1766       { "More fragments follow",        "nbdgm.next",  
1767         FT_BOOLEAN, BASE_NONE, TFS(&yesno), 0x0,
1768         "TRUE if more fragments follow", HFILL }},
1769     { &hf_nbdgm_first,
1770       { "This is first fragment",       "nbdgm.first",  
1771         FT_BOOLEAN, BASE_NONE, TFS(&yesno), 0x0,
1772         "TRUE if first fragment", HFILL }},
1773     { &hf_nbdgm_node_type,
1774       { "Node Type",            "nbdgm.node_type",  
1775         FT_UINT8, BASE_DEC, VALS(node_type_vals), 0x0,
1776         "Node type", HFILL }},
1777     { &hf_nbdgm_datagram_id,
1778       { "Datagram ID",          "nbdgm.dgram_id",  
1779         FT_UINT16, BASE_HEX, NULL, 0x0,
1780         "Datagram identifier", HFILL }},
1781     { &hf_nbdgm_src_ip,
1782       { "Source IP",            "nbdgm.src.ip",  
1783         FT_IPv4, BASE_NONE, NULL, 0x0,
1784         "Source IPv4 address", HFILL }},
1785     { &hf_nbdgm_src_port,
1786       { "Source Port",          "nbdgm.src.port",
1787         FT_UINT16, BASE_DEC, NULL, 0x0,
1788         "Source port", HFILL }}
1789   };
1790
1791   static hf_register_info hf_nbss[] = {
1792     { &hf_nbss_type,
1793       { "Message Type",         "nbss.type",  
1794         FT_UINT8, BASE_DEC, NULL, 0x0,
1795         "NBSS message type", HFILL }},
1796     { &hf_nbss_flags,
1797       { "Flags",                "nbss.flags",  
1798         FT_UINT8, BASE_HEX, NULL, 0x0,
1799         "NBSS message flags", HFILL }}
1800   };
1801   static gint *ett[] = {
1802     &ett_nbns,
1803     &ett_nbns_qd,
1804     &ett_nbns_flags,
1805     &ett_nbns_nb_flags,
1806     &ett_nbns_name_flags,
1807     &ett_nbns_rr,
1808     &ett_nbns_qry,
1809     &ett_nbns_ans,
1810     &ett_nbdgm,
1811     &ett_nbss,
1812     &ett_nbss_flags,
1813   };
1814   module_t *nbss_module;
1815
1816   proto_nbns = proto_register_protocol("NetBIOS Name Service", "NBNS", "nbns");
1817   proto_register_field_array(proto_nbns, hf_nbns, array_length(hf_nbns));
1818   
1819   proto_nbdgm = proto_register_protocol("NetBIOS Datagram Service",
1820                                         "NBDS", "nbdgm");
1821   proto_register_field_array(proto_nbdgm, hf_nbdgm, array_length(hf_nbdgm));
1822
1823   proto_nbss = proto_register_protocol("NetBIOS Session Service",
1824                                        "NBSS", "nbss");
1825   proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));
1826
1827   proto_register_subtree_array(ett, array_length(ett));
1828
1829   nbss_module = prefs_register_protocol(proto_nbss, NULL);
1830   prefs_register_bool_preference(nbss_module, "desegment_nbss_commands",
1831     "Desegment all NBSS packets spanning multiple TCP segments",
1832     "Whether NBSS dissector should desegment all packets spanning multiple TCP segments",
1833     &nbss_desegment);
1834 }
1835
1836 void
1837 proto_reg_handoff_nbt(void)
1838 {
1839   dissector_handle_t nbns_handle, nbdgm_handle, nbss_handle;
1840
1841   nbns_handle = create_dissector_handle(dissect_nbns, proto_nbns);
1842   dissector_add("udp.port", UDP_PORT_NBNS, nbns_handle);
1843   nbdgm_handle = create_dissector_handle(dissect_nbdgm, proto_nbdgm);
1844   dissector_add("udp.port", UDP_PORT_NBDGM, nbdgm_handle);
1845   nbss_handle = create_dissector_handle(dissect_nbss, proto_nbss);
1846   dissector_add("tcp.port", TCP_PORT_NBSS, nbss_handle);
1847   dissector_add("tcp.port", TCP_PORT_CIFS, nbss_handle);
1848 }