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