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