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