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