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