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