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