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