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