"const"ifty some function arguments and structure members, and "#if 0"
[obnox/wireshark/wip.git] / packet-nbns.c
1 /* packet-nbns.c
2  * Routines for NetBIOS Name Service, Datagram Service, and Session Service
3  * packet disassembly (the name dates back 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.22 1999/07/07 22:51:47 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 #include "packet.h"
41 #include "packet-dns.h"
42 #include "util.h"
43
44 /* Packet structure taken from RFC 1002. See also RFC 1001.
45  * Opcode, flags, and rcode treated as "flags", similarly to DNS,
46  * to make it easier to lift the dissection code from "packet-dns.c". */
47
48 /* Offsets of fields in the NBNS header. */
49 #define NBNS_ID         0
50 #define NBNS_FLAGS      2
51 #define NBNS_QUEST      4
52 #define NBNS_ANS        6
53 #define NBNS_AUTH       8
54 #define NBNS_ADD        10
55
56 /* Length of NBNS header. */
57 #define NBNS_HDRLEN     12
58
59 /* type values  */
60 #define T_NB            32              /* NetBIOS name service RR */
61 #define T_NBSTAT        33              /* NetBIOS node status RR */
62
63 /* Bit fields in the flags */
64 #define F_RESPONSE      (1<<15)         /* packet is response */
65 #define F_OPCODE        (0xF<<11)       /* query opcode */
66 #define F_AUTHORITATIVE (1<<10)         /* response is authoritative */
67 #define F_TRUNCATED     (1<<9)          /* response is truncated */
68 #define F_RECDESIRED    (1<<8)          /* recursion desired */
69 #define F_RECAVAIL      (1<<7)          /* recursion available */
70 #define F_BROADCAST     (1<<4)          /* broadcast/multicast packet */
71 #define F_RCODE         (0xF<<0)        /* reply code */
72
73 /* Opcodes */
74 #define OPCODE_QUERY          (0<<11)    /* standard query */
75 #define OPCODE_REGISTRATION   (5<<11)    /* registration */
76 #define OPCODE_RELEASE        (6<<11)    /* release name */
77 #define OPCODE_WACK           (7<<11)    /* wait for acknowledgement */
78 #define OPCODE_REFRESH        (8<<11)    /* refresh registration */
79 #define OPCODE_REFRESHALT     (9<<11)    /* refresh registration (alternate opcode) */
80 #define OPCODE_MHREGISTRATION (15<<11)   /* multi-homed registration */
81
82 /* Reply codes */
83 #define RCODE_NOERROR   (0<<0)
84 #define RCODE_FMTERROR  (1<<0)
85 #define RCODE_SERVFAIL  (2<<0)
86 #define RCODE_NAMEERROR (3<<0)
87 #define RCODE_NOTIMPL   (4<<0)
88 #define RCODE_REFUSED   (5<<0)
89 #define RCODE_ACTIVE    (6<<0)
90 #define RCODE_CONFLICT  (7<<0)
91
92 /* Values for the "NB_FLAGS" field of RR data.  From RFC 1001 and 1002,
93  * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
94  * packet traces. */
95 #define NB_FLAGS_ONT            (3<<(15-2))     /* bits for node type */
96 #define NB_FLAGS_ONT_B_NODE     (0<<(15-2))     /* B-mode node */
97 #define NB_FLAGS_ONT_P_NODE     (1<<(15-2))     /* P-mode node */
98 #define NB_FLAGS_ONT_M_NODE     (2<<(15-2))     /* M-mode node */
99 #define NB_FLAGS_ONT_H_NODE     (3<<(15-2))     /* H-mode node */
100
101 #define NB_FLAGS_G              (1<<(15-0))     /* group name */
102
103 /* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
104  * RR data.  From RFC 1001 and 1002, except for NAME_FLAGS_ONT_H_NODE,
105  * which was discovered by looking at packet traces. */
106 #define NAME_FLAGS_PRM          (1<<(15-6))     /* name is permanent node name */
107
108 #define NAME_FLAGS_ACT          (1<<(15-5))     /* name is active */
109
110 #define NAME_FLAGS_CNF          (1<<(15-4))     /* name is in conflict */
111
112 #define NAME_FLAGS_DRG          (1<<(15-3))     /* name is being deregistered */
113
114 #define NAME_FLAGS_ONT          (3<<(15-2))     /* bits for node type */
115 #define NAME_FLAGS_ONT_B_NODE   (0<<(15-2))     /* B-mode node */
116 #define NAME_FLAGS_ONT_P_NODE   (1<<(15-2))     /* P-mode node */
117 #define NAME_FLAGS_ONT_M_NODE   (2<<(15-2))     /* M-mode node */
118
119 #define NAME_FLAGS_G            (1<<(15-0))     /* group name */
120
121 static const value_string opcode_vals[] = {
122           { OPCODE_QUERY,          "Name query"                 },
123           { OPCODE_REGISTRATION,   "Registration"               },
124           { OPCODE_RELEASE,        "Release"                    },
125           { OPCODE_WACK,           "Wait for acknowledgment"    },
126           { OPCODE_REFRESH,        "Refresh"                    },
127           { OPCODE_REFRESHALT,     "Refresh (alternate opcode)" },
128           { OPCODE_MHREGISTRATION, "Multi-homed registration"   },
129           { 0,                     NULL                         }
130 };
131
132 static char *
133 nbns_type_name (int type)
134 {
135         switch (type) {
136         case T_NB:
137                 return "NB";
138         case T_NBSTAT:
139                 return "NBSTAT";
140         }
141         
142         return "unknown";
143 }
144
145 /* "Canonicalize" a 16-character NetBIOS name by:
146  *
147  *      removing and saving the last byte;
148  *
149  *      stripping trailing blanks;
150  *
151  *      appending the trailing byte, as a hex number, in square brackets. */
152 static char *
153 canonicalize_netbios_name(char *nbname)
154 {
155         char *pnbname;
156         u_char lastchar;
157
158         /* Get the last character of the name, as it's a special number
159          * indicating the type of the name, rather than part of the name
160          * *per se*. */
161         pnbname = nbname + 15;  /* point to the 16th character */
162         lastchar = *(unsigned char *)pnbname;
163
164         /* Now strip off any trailing blanks used to pad it to
165          * 16 bytes. */
166         while (pnbname > &nbname[0]) {
167                 if (*(pnbname - 1) != ' ')
168                         break;          /* found non-blank character */
169                 pnbname--;              /* blank - skip over it */
170         }
171
172         /* Replace the last character with its hex value, in square
173          * brackets, to make it easier to tell what it is. */
174         sprintf(pnbname, "[%02X]", lastchar);
175         pnbname += 4;
176         return pnbname;
177 }
178
179 static int
180 get_nbns_name(const u_char *nbns_data_ptr, const u_char *pd,
181     int offset, char *name_ret)
182 {
183         int name_len;
184         char name[MAXDNAME];
185         char nbname[MAXDNAME+4];        /* 4 for [<last char>] */
186         char *pname, *pnbname, cname, cnbname;
187
188         name_len = get_dns_name(nbns_data_ptr, pd + offset, name, sizeof(name));
189         
190         /* OK, now undo the first-level encoding. */
191         pname = &name[0];
192         pnbname = &nbname[0];
193         for (;;) {
194                 /* Every two characters of the first level-encoded name
195                  * turn into one character in the decoded name. */
196                 cname = *pname;
197                 if (cname == '\0')
198                         break;          /* no more characters */
199                 if (cname == '.')
200                         break;          /* scope ID follows */
201                 if (cname < 'A' || cname > 'Z') {
202                         /* Not legal. */
203                         strcpy(nbname,
204                             "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
205                         goto bad;
206                 }
207                 cname -= 'A';
208                 cnbname = cname << 4;
209                 pname++;
210
211                 cname = *pname;
212                 if (cname == '\0' || cname == '.') {
213                         /* No more characters in the name - but we're in
214                          * the middle of a pair.  Not legal. */
215                         strcpy(nbname,
216                             "Illegal NetBIOS name (odd number of bytes)");
217                         goto bad;
218                 }
219                 if (cname < 'A' || cname > 'Z') {
220                         /* Not legal. */
221                         strcpy(nbname,
222                             "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
223                         goto bad;
224                 }
225                 cname -= 'A';
226                 cnbname |= cname;
227                 pname++;
228
229                 /* Store the character. */
230                 *pnbname++ = cnbname;
231         }
232
233         /* NetBIOS names are supposed to be exactly 16 bytes long. */
234         if (pnbname - nbname == 16) {
235                 /* This one is; canonicalize its name. */
236                 pnbname = canonicalize_netbios_name(nbname);
237         } else {
238                 sprintf(nbname, "Illegal NetBIOS name (%ld bytes long)",
239                     (long)(pnbname - nbname));
240                 goto bad;
241         }
242         if (cname == '.') {
243                 /* We have a scope ID, starting at "pname"; append that to
244                  * the decoded host name. */
245                 strcpy(pnbname, pname);
246         } else {
247                 /* Terminate the decoded host name. */
248                 *pnbname = '\0';
249         }
250
251 bad:
252         strcpy (name_ret, nbname);
253         return name_len;
254 }
255
256
257 static int
258 get_nbns_name_type_class(const u_char *nbns_data_ptr, const u_char *pd,
259     int offset, char *name_ret, int *name_len_ret, int *type_ret,
260     int *class_ret)
261 {
262         int name_len;
263         int type;
264         int class;
265
266         name_len = get_nbns_name(nbns_data_ptr, pd, offset, name_ret);
267         offset += name_len;
268         
269         type = pntohs(&pd[offset]);
270         offset += 2;
271         class = pntohs(&pd[offset]);
272
273         *type_ret = type;
274         *class_ret = class;
275         *name_len_ret = name_len;
276
277         return name_len + 4;
278 }
279
280
281 static int
282 dissect_nbns_query(const u_char *nbns_data_ptr, const u_char *pd, int offset,
283     proto_tree *nbns_tree)
284 {
285         int len;
286         char name[MAXDNAME];
287         int name_len;
288         int type;
289         int class;
290         char *class_name;
291         char *type_name;
292         const u_char *dptr;
293         const u_char *data_start;
294         proto_tree *q_tree;
295         proto_item *tq;
296
297         data_start = dptr = pd + offset;
298
299         len = get_nbns_name_type_class(nbns_data_ptr, pd, offset, name,
300             &name_len, &type, &class);
301         dptr += len;
302
303         type_name = nbns_type_name(type);
304         class_name = dns_class_name(class);
305
306         tq = proto_tree_add_text(nbns_tree, offset, len, "%s: type %s, class %s", 
307             name, type_name, class_name);
308         q_tree = proto_item_add_subtree(tq, ETT_NBNS_QD);
309
310         proto_tree_add_text(q_tree, offset, name_len, "Name: %s", name);
311         offset += name_len;
312
313         proto_tree_add_text(q_tree, offset, 2, "Type: %s", type_name);
314         offset += 2;
315
316         proto_tree_add_text(q_tree, offset, 2, "Class: %s", class_name);
317         offset += 2;
318         
319         return dptr - data_start;
320 }
321
322 static void
323 nbns_add_nbns_flags(proto_tree *nbns_tree, int offset, u_short flags,
324     int is_wack)
325 {
326         char buf[128+1];
327         proto_tree *field_tree;
328         proto_item *tf;
329         static const value_string rcode_vals[] = {
330                   { RCODE_NOERROR,   "No error"                        },
331                   { RCODE_FMTERROR,  "Request was invalidly formatted" },
332                   { RCODE_SERVFAIL,  "Server failure"                  },
333                   { RCODE_NAMEERROR, "Requested name does not exist"   },
334                   { RCODE_NOTIMPL,   "Request is not implemented"      },
335                   { RCODE_REFUSED,   "Request was refused"             },
336                   { RCODE_ACTIVE,    "Name is owned by another node"   },
337                   { RCODE_CONFLICT,  "Name is in conflict"             },
338                   { 0,               NULL                              }
339         };
340
341         strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals,
342                                 "Unknown operation"));
343         if (flags & F_RESPONSE && !is_wack) {
344                 strcat(buf, " response");
345                 strcat(buf, ", ");
346                 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
347                     "Unknown error"));
348         }
349         tf = proto_tree_add_text(nbns_tree, offset, 2,
350                         "Flags: 0x%04x (%s)", flags, buf);
351         field_tree = proto_item_add_subtree(tf, ETT_NBNS_FLAGS);
352         proto_tree_add_text(field_tree, offset, 2, "%s",
353                         decode_boolean_bitfield(flags, F_RESPONSE,
354                                 2*8, "Response", "Query"));
355         proto_tree_add_text(field_tree, offset, 2, "%s",
356                         decode_enumerated_bitfield(flags, F_OPCODE,
357                                 2*8, opcode_vals, "%s"));
358         if (flags & F_RESPONSE) {
359                 proto_tree_add_text(field_tree, offset, 2,
360                         "%s",
361                         decode_boolean_bitfield(flags, F_AUTHORITATIVE,
362                                 2*8,
363                                 "Server is an authority for domain",
364                                 "Server isn't an authority for domain"));
365         }
366         proto_tree_add_text(field_tree, offset, 2, "%s",
367                         decode_boolean_bitfield(flags, F_TRUNCATED,
368                                 2*8,
369                                 "Message is truncated",
370                                 "Message is not truncated"));
371         proto_tree_add_text(field_tree, offset, 2, "%s",
372                         decode_boolean_bitfield(flags, F_RECDESIRED,
373                                 2*8,
374                                 "Do query recursively",
375                                 "Don't do query recursively"));
376         if (flags & F_RESPONSE) {
377                 proto_tree_add_text(field_tree, offset, 2,
378                         "%s",
379                         decode_boolean_bitfield(flags, F_RECAVAIL,
380                                 2*8,
381                                 "Server can do recursive queries",
382                                 "Server can't do recursive queries"));
383         }
384         proto_tree_add_text(field_tree, offset, 2, "%s",
385                         decode_boolean_bitfield(flags, F_BROADCAST,
386                                 2*8,
387                                 "Broadcast packet",
388                                 "Not a broadcast packet"));
389         if (flags & F_RESPONSE && !is_wack) {
390                 proto_tree_add_text(field_tree, offset, 2,
391                         "%s",
392                         decode_enumerated_bitfield(flags, F_RCODE,
393                                 2*8,
394                                 rcode_vals, "%s"));
395         }
396 }
397
398 static void
399 nbns_add_nb_flags(proto_tree *rr_tree, int offset, u_short flags)
400 {
401         char buf[128+1];
402         proto_tree *field_tree;
403         proto_item *tf;
404         static const value_string nb_flags_ont_vals[] = {
405                   { NB_FLAGS_ONT_B_NODE, "B-node" },
406                   { NB_FLAGS_ONT_P_NODE, "P-node" },
407                   { NB_FLAGS_ONT_M_NODE, "M-node" },
408                   { NB_FLAGS_ONT_H_NODE, "H-node" },
409                   { 0,                   NULL     }
410         };
411
412         strcpy(buf, val_to_str(flags & NB_FLAGS_ONT, nb_flags_ont_vals,
413             "Unknown"));
414         strcat(buf, ", ");
415         if (flags & NB_FLAGS_G)
416                 strcat(buf, "group");
417         else
418                 strcat(buf, "unique");
419         tf = proto_tree_add_text(rr_tree, offset, 2, "Flags: 0x%x (%s)", flags,
420                         buf);
421         field_tree = proto_item_add_subtree(tf, ETT_NBNS_NB_FLAGS);
422         proto_tree_add_text(field_tree, offset, 2, "%s",
423                         decode_boolean_bitfield(flags, NB_FLAGS_G,
424                                 2*8,
425                                 "Group name",
426                                 "Unique name"));
427         proto_tree_add_text(field_tree, offset, 2, "%s",
428                         decode_enumerated_bitfield(flags, NB_FLAGS_ONT,
429                                 2*8, nb_flags_ont_vals, "%s"));
430 }
431
432 static void
433 nbns_add_name_flags(proto_tree *rr_tree, int offset, u_short flags)
434 {
435         char buf[128+1];
436         proto_item *field_tree;
437         proto_item *tf;
438         static const value_string name_flags_ont_vals[] = {
439                   { NAME_FLAGS_ONT_B_NODE, "B-node" },
440                   { NAME_FLAGS_ONT_P_NODE, "P-node" },
441                   { NAME_FLAGS_ONT_M_NODE, "M-node" },
442                   { 0,                     NULL     }
443         };
444
445         strcpy(buf, val_to_str(flags & NAME_FLAGS_ONT, name_flags_ont_vals,
446             "Unknown"));
447         strcat(buf, ", ");
448         if (flags & NAME_FLAGS_G)
449                 strcat(buf, "group");
450         else
451                 strcat(buf, "unique");
452         if (flags & NAME_FLAGS_DRG)
453                 strcat(buf, ", being deregistered");
454         if (flags & NAME_FLAGS_CNF)
455                 strcat(buf, ", in conflict");
456         if (flags & NAME_FLAGS_ACT)
457                 strcat(buf, ", active");
458         if (flags & NAME_FLAGS_PRM)
459                 strcat(buf, ", permanent node name");
460         tf = proto_tree_add_text(rr_tree, offset, 2, "Name flags: 0x%x (%s)",
461                         flags, buf);
462         field_tree = proto_item_add_subtree(tf, ETT_NBNS_NAME_FLAGS);
463         proto_tree_add_text(field_tree, offset, 2, "%s",
464                         decode_boolean_bitfield(flags, NAME_FLAGS_G,
465                                 2*8,
466                                 "Group name",
467                                 "Unique name"));
468         proto_tree_add_text(field_tree, offset, 2, "%s",
469                         decode_enumerated_bitfield(flags, NAME_FLAGS_ONT,
470                                 2*8, name_flags_ont_vals, "%s"));
471         proto_tree_add_text(field_tree, offset, 2, "%s",
472                         decode_boolean_bitfield(flags, NAME_FLAGS_DRG,
473                                 2*8,
474                                 "Name is being deregistered",
475                                 "Name is not being deregistered"));
476         proto_tree_add_text(field_tree, offset, 2, "%s",
477                         decode_boolean_bitfield(flags, NAME_FLAGS_CNF,
478                                 2*8,
479                                 "Name is in conflict",
480                                 "Name is not in conflict"));
481         proto_tree_add_text(field_tree, offset, 2, "%s",
482                         decode_boolean_bitfield(flags, NAME_FLAGS_ACT,
483                                 2*8,
484                                 "Name is active",
485                                 "Name is not active"));
486         proto_tree_add_text(field_tree, offset, 2, "%s",
487                         decode_boolean_bitfield(flags, NAME_FLAGS_PRM,
488                                 2*8,
489                                 "Permanent node name",
490                                 "Not permanent node name"));
491 }
492
493 static int
494 dissect_nbns_answer(const u_char *nbns_data_ptr, const u_char *pd, int offset,
495     proto_tree *nbns_tree, int opcode)
496 {
497         int len;
498         char name[MAXDNAME];
499         int name_len;
500         int type;
501         int class;
502         char *class_name;
503         char *type_name;
504         const u_char *dptr;
505         const u_char *data_start;
506         u_int ttl;
507         u_short data_len;
508         u_short flags;
509         proto_tree *rr_tree;
510         proto_item *trr;
511
512         data_start = dptr = pd + offset;
513
514         len = get_nbns_name_type_class(nbns_data_ptr, pd, offset, name,
515             &name_len, &type, &class);
516         dptr += len;
517
518         type_name = nbns_type_name(type);
519         class_name = dns_class_name(class);
520
521         ttl = pntohl(dptr);
522         dptr += 4;
523
524         data_len = pntohs(dptr);
525         dptr += 2;
526
527         switch (type) {
528         case T_NB:              /* "NB" record */
529                 trr = proto_tree_add_text(nbns_tree, offset,
530                     (dptr - data_start) + data_len,
531                     "%s: type %s, class %s",
532                     name, type_name, class_name);
533                 rr_tree = add_rr_to_tree(trr, ETT_NBNS_RR, offset, name,
534                     name_len, type_name, class_name, ttl, data_len);
535                 offset += (dptr - data_start);
536                 while (data_len > 0) {
537                         if (opcode == OPCODE_WACK) {
538                                 /* WACK response.  This doesn't contain the
539                                  * same type of RR data as other T_NB
540                                  * responses.  */
541                                 if (data_len < 2) {
542                                         proto_tree_add_text(rr_tree, offset,
543                                             data_len, "(incomplete entry)");
544                                         break;
545                                 }
546                                 flags = pntohs(dptr);
547                                 dptr += 2;
548                                 nbns_add_nbns_flags(rr_tree, offset, flags, 1);
549                                 offset += 2;
550                                 data_len -= 2;
551                         } else {
552                                 if (data_len < 2) {
553                                         proto_tree_add_text(rr_tree, offset,
554                                             data_len, "(incomplete entry)");
555                                         break;
556                                 }
557                                 flags = pntohs(dptr);
558                                 dptr += 2;
559                                 nbns_add_nb_flags(rr_tree, offset, flags);
560                                 offset += 2;
561                                 data_len -= 2;
562
563                                 if (data_len < 4) {
564                                         proto_tree_add_text(rr_tree, offset,
565                                             data_len, "(incomplete entry)");
566                                         break;
567                                 }
568                                 proto_tree_add_text(rr_tree, offset, 4,
569                                     "Addr: %s",
570                                     ip_to_str((guint8 *)dptr));
571                                 dptr += 4;
572                                 offset += 4;
573                                 data_len -= 4;
574                         }
575                 }
576                 break;
577
578         case T_NBSTAT:  /* "NBSTAT" record */
579                 {
580                         u_int num_names;
581                         char nbname[16+4+1];    /* 4 for [<last char>] */
582                         u_short name_flags;
583                         
584                         trr = proto_tree_add_text(nbns_tree, offset,
585                             (dptr - data_start) + data_len,
586                             "%s: type %s, class %s",
587                             name, type_name, class_name);
588                         rr_tree = add_rr_to_tree(trr, ETT_NBNS_RR, offset, name,
589                             name_len, type_name, class_name, ttl, data_len);
590                         offset += (dptr - data_start);
591                         if (data_len < 1) {
592                                 proto_tree_add_text(rr_tree, offset,
593                                     data_len, "(incomplete entry)");
594                                 break;
595                         }
596                         num_names = *dptr;
597                         dptr += 1;
598                         proto_tree_add_text(rr_tree, offset, 2,
599                             "Number of names: %u", num_names);
600                         offset += 1;
601
602                         while (num_names != 0) {
603                                 if (data_len < 16) {
604                                         proto_tree_add_text(rr_tree, offset,
605                                             data_len, "(incomplete entry)");
606                                         goto out;
607                                 }
608                                 memcpy(nbname, dptr, 16);
609                                 dptr += 16;
610                                 canonicalize_netbios_name(nbname);
611                                 proto_tree_add_text(rr_tree, offset, 16,
612                                     "Name: %s", nbname);
613                                 offset += 16;
614                                 data_len -= 16;
615
616                                 if (data_len < 2) {
617                                         proto_tree_add_text(rr_tree, offset,
618                                             data_len, "(incomplete entry)");
619                                         goto out;
620                                 }
621                                 name_flags = pntohs(dptr);
622                                 dptr += 2;
623                                 nbns_add_name_flags(rr_tree, offset, name_flags);
624                                 offset += 2;
625                                 data_len -= 2;
626
627                                 num_names--;
628                         }
629
630                         if (data_len < 6) {
631                                 proto_tree_add_text(rr_tree, offset,
632                                     data_len, "(incomplete entry)");
633                                 break;
634                         }
635                         proto_tree_add_text(rr_tree, offset, 6,
636                             "Unit ID: %s",
637                             ether_to_str((guint8 *)dptr));
638                         dptr += 6;
639                         offset += 6;
640                         data_len -= 6;
641
642                         if (data_len < 1) {
643                                 proto_tree_add_text(rr_tree, offset,
644                                     data_len, "(incomplete entry)");
645                                 break;
646                         }
647                         proto_tree_add_text(rr_tree, offset, 1,
648                             "Jumpers: 0x%x", *dptr);
649                         dptr += 1;
650                         offset += 1;
651                         data_len -= 1;
652
653                         if (data_len < 1) {
654                                 proto_tree_add_text(rr_tree, offset,
655                                     data_len, "(incomplete entry)");
656                                 break;
657                         }
658                         proto_tree_add_text(rr_tree, offset, 1,
659                             "Test result: 0x%x", *dptr);
660                         dptr += 1;
661                         offset += 1;
662                         data_len -= 1;
663
664                         if (data_len < 2) {
665                                 proto_tree_add_text(rr_tree, offset,
666                                     data_len, "(incomplete entry)");
667                                 break;
668                         }
669                         proto_tree_add_text(rr_tree, offset, 2,
670                             "Version number: 0x%x", pntohs(dptr));
671                         dptr += 2;
672                         offset += 2;
673                         data_len -= 2;
674
675                         if (data_len < 2) {
676                                 proto_tree_add_text(rr_tree, offset,
677                                     data_len, "(incomplete entry)");
678                                 break;
679                         }
680                         proto_tree_add_text(rr_tree, offset, 2,
681                             "Period of statistics: 0x%x", pntohs(dptr));
682                         dptr += 2;
683                         offset += 2;
684                         data_len -= 2;
685
686                         if (data_len < 2) {
687                                 proto_tree_add_text(rr_tree, offset,
688                                     data_len, "(incomplete entry)");
689                                 break;
690                         }
691                         proto_tree_add_text(rr_tree, offset, 2,
692                             "Number of CRCs: %u", pntohs(dptr));
693                         dptr += 2;
694                         offset += 2;
695                         data_len -= 2;
696
697                         if (data_len < 2) {
698                                 proto_tree_add_text(rr_tree, offset,
699                                     data_len, "(incomplete entry)");
700                                 break;
701                         }
702                         proto_tree_add_text(rr_tree, offset, 2,
703                             "Number of alignment errors: %u", pntohs(dptr));
704                         dptr += 2;
705                         offset += 2;
706                         data_len -= 2;
707
708                         if (data_len < 2) {
709                                 proto_tree_add_text(rr_tree, offset,
710                                     data_len, "(incomplete entry)");
711                                 break;
712                         }
713                         proto_tree_add_text(rr_tree, offset, 2,
714                             "Number of collisions: %u", pntohs(dptr));
715                         dptr += 2;
716                         offset += 2;
717                         data_len -= 2;
718
719                         if (data_len < 2) {
720                                 proto_tree_add_text(rr_tree, offset,
721                                     data_len, "(incomplete entry)");
722                                 break;
723                         }
724                         proto_tree_add_text(rr_tree, offset, 2,
725                             "Number of send aborts: %u", pntohs(dptr));
726                         dptr += 2;
727                         offset += 2;
728                         data_len -= 2;
729
730                         if (data_len < 4) {
731                                 proto_tree_add_text(rr_tree, offset,
732                                     data_len, "(incomplete entry)");
733                                 break;
734                         }
735                         proto_tree_add_text(rr_tree, offset, 4,
736                             "Number of good sends: %u", pntohl(dptr));
737                         dptr += 4;
738                         offset += 4;
739                         data_len -= 4;
740
741                         if (data_len < 4) {
742                                 proto_tree_add_text(rr_tree, offset,
743                                     data_len, "(incomplete entry)");
744                                 break;
745                         }
746                         proto_tree_add_text(rr_tree, offset, 4,
747                             "Number of good receives: %u", pntohl(dptr));
748                         dptr += 4;
749                         offset += 4;
750                         data_len -= 4;
751
752                         if (data_len < 2) {
753                                 proto_tree_add_text(rr_tree, offset,
754                                     data_len, "(incomplete entry)");
755                                 break;
756                         }
757                         proto_tree_add_text(rr_tree, offset, 2,
758                             "Number of retransmits: %u", pntohs(dptr));
759                         dptr += 2;
760                         offset += 2;
761                         data_len -= 2;
762
763                         if (data_len < 2) {
764                                 proto_tree_add_text(rr_tree, offset,
765                                     data_len, "(incomplete entry)");
766                                 break;
767                         }
768                         proto_tree_add_text(rr_tree, offset, 2,
769                             "Number of no resource conditions: %u", pntohs(dptr));
770                         dptr += 2;
771                         offset += 2;
772                         data_len -= 2;
773
774                         if (data_len < 2) {
775                                 proto_tree_add_text(rr_tree, offset,
776                                     data_len, "(incomplete entry)");
777                                 break;
778                         }
779                         proto_tree_add_text(rr_tree, offset, 2,
780                             "Number of command blocks: %u", pntohs(dptr));
781                         dptr += 2;
782                         offset += 2;
783                         data_len -= 2;
784
785                         if (data_len < 2) {
786                                 proto_tree_add_text(rr_tree, offset,
787                                     data_len, "(incomplete entry)");
788                                 break;
789                         }
790                         proto_tree_add_text(rr_tree, offset, 2,
791                             "Number of pending sessions: %u", pntohs(dptr));
792                         dptr += 2;
793                         offset += 2;
794                         data_len -= 2;
795
796                         if (data_len < 2) {
797                                 proto_tree_add_text(rr_tree, offset,
798                                     data_len, "(incomplete entry)");
799                                 break;
800                         }
801                         proto_tree_add_text(rr_tree, offset, 2,
802                             "Max number of pending sessions: %u", pntohs(dptr));
803                         dptr += 2;
804                         offset += 2;
805
806                         proto_tree_add_text(rr_tree, offset, 2,
807                             "Max total sessions possible: %u", pntohs(dptr));
808                         dptr += 2;
809                         offset += 2;
810                         data_len -= 2;
811
812                         if (data_len < 2) {
813                                 proto_tree_add_text(rr_tree, offset,
814                                     data_len, "(incomplete entry)");
815                                 break;
816                         }
817                         proto_tree_add_text(rr_tree, offset, 2,
818                             "Session data packet size: %u", pntohs(dptr));
819                         dptr += 2;
820                         offset += 2;
821                         data_len -= 2;
822                 }
823         out:
824                 break;
825
826         default:
827                 trr = proto_tree_add_text(nbns_tree, offset,
828                     (dptr - data_start) + data_len,
829                     "%s: type %s, class %s",
830                     name, type_name, class_name);
831                 rr_tree = add_rr_to_tree(trr, ETT_NBNS_RR, offset, name,
832                     name_len, type_name, class_name, ttl, data_len);
833                 offset += (dptr - data_start);
834                 proto_tree_add_text(rr_tree, offset, data_len, "Data");
835                 break;
836         }
837         dptr += data_len;
838         
839         return dptr - data_start;
840 }
841
842 static int
843 dissect_query_records(const u_char *nbns_data_ptr, int count, const u_char *pd, 
844     int cur_off, proto_tree *nbns_tree)
845 {
846         int start_off;
847         proto_tree *qatree;
848         proto_item *ti;
849         
850         start_off = cur_off;
851         ti = proto_tree_add_text(nbns_tree, start_off, 0, "Queries");
852         qatree = proto_item_add_subtree(ti, ETT_NBNS_QRY);
853         while (count-- > 0)
854                 cur_off += dissect_nbns_query(nbns_data_ptr, pd, cur_off, qatree);
855         proto_item_set_len(ti, cur_off - start_off);
856
857         return cur_off - start_off;
858 }
859
860
861
862 static int
863 dissect_answer_records(const u_char *nbns_data_ptr, int count,
864     const u_char *pd, int cur_off, proto_tree *nbns_tree, int opcode, char *name)
865 {
866         int start_off;
867         proto_tree *qatree;
868         proto_item *ti;
869         
870         start_off = cur_off;
871         ti = proto_tree_add_text(nbns_tree, start_off, 0, name);
872         qatree = proto_item_add_subtree(ti, ETT_NBNS_ANS);
873         while (count-- > 0)
874                 cur_off += dissect_nbns_answer(nbns_data_ptr, pd, cur_off,
875                                         qatree, opcode);
876         proto_item_set_len(ti, cur_off - start_off);
877         return cur_off - start_off;
878 }
879
880 void
881 dissect_nbns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
882 {
883         const u_char            *nbns_data_ptr;
884         proto_tree              *nbns_tree;
885         proto_item              *ti;
886         guint16                 id, flags, quest, ans, auth, add;
887         int                     cur_off;
888
889         nbns_data_ptr = &pd[offset];
890
891         /* To do: check for runts, errs, etc. */
892         id    = pntohs(&pd[offset + NBNS_ID]);
893         flags = pntohs(&pd[offset + NBNS_FLAGS]);
894         quest = pntohs(&pd[offset + NBNS_QUEST]);
895         ans   = pntohs(&pd[offset + NBNS_ANS]);
896         auth  = pntohs(&pd[offset + NBNS_AUTH]);
897         add   = pntohs(&pd[offset + NBNS_ADD]);
898
899         if (check_col(fd, COL_PROTOCOL))
900                 col_add_str(fd, COL_PROTOCOL, "NBNS (UDP)");
901         if (check_col(fd, COL_INFO)) {
902                 col_add_fstr(fd, COL_INFO, "%s%s",
903                     val_to_str(flags & F_OPCODE, opcode_vals,
904                       "Unknown operation (%x)"),
905                     (flags & F_RESPONSE) ? " response" : "");
906         }
907
908         if (tree) {
909                 ti = proto_tree_add_text(tree, offset, END_OF_FRAME,
910                                 "NetBIOS Name Service");
911                 nbns_tree = proto_item_add_subtree(ti, ETT_NBNS);
912
913                 proto_tree_add_text(nbns_tree, offset + NBNS_ID, 2,
914                                 "Transaction ID: 0x%04X", id);
915
916                 nbns_add_nbns_flags(nbns_tree, offset + NBNS_FLAGS, flags, 0);
917                 proto_tree_add_text(nbns_tree, offset + NBNS_QUEST, 2,
918                                         "Questions: %d",
919                                         quest);
920                 proto_tree_add_text(nbns_tree, offset + NBNS_ANS, 2,
921                                         "Answer RRs: %d",
922                                         ans);
923                 proto_tree_add_text(nbns_tree, offset + NBNS_AUTH, 2,
924                                         "Authority RRs: %d",
925                                         auth);
926                 proto_tree_add_text(nbns_tree, offset + NBNS_ADD, 2,
927                                         "Additional RRs: %d",
928                                         add);
929
930                 cur_off = offset + NBNS_HDRLEN;
931     
932                 if (quest > 0)
933                         cur_off += dissect_query_records(nbns_data_ptr,
934                                         quest, pd, cur_off, nbns_tree);
935
936                 if (ans > 0)
937                         cur_off += dissect_answer_records(nbns_data_ptr,
938                                         ans, pd, cur_off, nbns_tree,
939                                         flags & F_OPCODE,
940                                         "Answers");
941
942                 if (auth > 0)
943                         cur_off += dissect_answer_records(nbns_data_ptr,
944                                         auth, pd, cur_off, nbns_tree, 
945                                         flags & F_OPCODE,
946                                         "Authoritative nameservers");
947
948                 if (add > 0)
949                         cur_off += dissect_answer_records(nbns_data_ptr,
950                                         add, pd, cur_off, nbns_tree, 
951                                         flags & F_OPCODE,
952                                         "Additional records");
953         }
954 }
955
956 /* NetBIOS datagram packet, from RFC 1002, page 32 */
957 struct nbdgm_header {
958         guint8          msg_type;
959         struct {
960                 guint8  more;
961                 guint8  first;
962                 guint8  node_type;
963         } flags;
964         guint16         dgm_id;
965         guint32         src_ip;
966         guint16         src_port;
967
968         /* For packets with data */
969         guint16         dgm_length;
970         guint16         pkt_offset;
971
972         /* For error packets */
973         guint8          error_code;
974 };
975
976 void
977 dissect_nbdgm(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
978     int max_data)
979 {
980         proto_tree              *nbdgm_tree = NULL;
981         proto_item              *ti;
982         struct nbdgm_header     header;
983         int                     flags;
984         int                     message_index;
985
986         char *message[] = {
987                 "Unknown",
988                 "Direct_unique datagram",
989                 "Direct_group datagram",
990                 "Broadcast datagram",
991                 "Datagram error",
992                 "Datagram query request",
993                 "Datagram positive query response",
994                 "Datagram negative query response"
995         };
996
997         char *node[] = {
998                 "B node",
999                 "P node",
1000                 "M node",
1001                 "NBDD"
1002         };
1003
1004         static value_string error_codes[] = {
1005                 { 0x82, "Destination name not present" },
1006                 { 0x83, "Invalid source name format" },
1007                 { 0x84, "Invalid destination name format" },
1008                 { 0x00, NULL }
1009         };
1010
1011         char *yesno[] = { "No", "Yes" };
1012
1013         char name[MAXDNAME+4];
1014         int len;
1015
1016         header.msg_type = pd[offset];
1017         
1018         flags = pd[offset+1];
1019         header.flags.more = flags & 1;
1020         header.flags.first = (flags & 2) >> 1;
1021         header.flags.node_type = (flags & 12) >> 2;
1022
1023         header.dgm_id = pntohs(&pd[offset+2]);
1024         memcpy(&header.src_ip, &pd[offset+4], 4);
1025         header.src_port = pntohs(&pd[offset+8]);
1026
1027         if (header.msg_type == 0x10 ||
1028                         header.msg_type == 0x11 || header.msg_type == 0x12) {
1029                 header.dgm_length = pntohs(&pd[offset+10]);
1030                 header.pkt_offset = pntohs(&pd[offset+12]);
1031         }
1032         else if (header.msg_type == 0x13) {
1033                 header.error_code = pntohs(&pd[offset+10]);
1034         }
1035
1036         message_index = header.msg_type - 0x0f;
1037         if (message_index < 1 || message_index > 8) {
1038                 message_index = 0;
1039         }
1040
1041         if (check_col(fd, COL_PROTOCOL))
1042                 col_add_str(fd, COL_PROTOCOL, "NBDS (UDP)");
1043         if (check_col(fd, COL_INFO)) {
1044                 col_add_fstr(fd, COL_INFO, "%s", message[message_index]);
1045         }
1046
1047         if (tree) {
1048                 ti = proto_tree_add_text(tree, offset, header.dgm_length,
1049                                 "NetBIOS Datagram Service");
1050                 nbdgm_tree = proto_item_add_subtree(ti, ETT_NBDGM);
1051
1052                 proto_tree_add_text(nbdgm_tree, offset, 1, "Message Type: %s",
1053                                 message[message_index]);
1054                 proto_tree_add_text(nbdgm_tree, offset+1, 1, "More fragments follow: %s",
1055                                 yesno[header.flags.more]);
1056                 proto_tree_add_text(nbdgm_tree, offset+1, 1, "This is first fragment: %s",
1057                                 yesno[header.flags.first]);
1058                 proto_tree_add_text(nbdgm_tree, offset+1, 1, "Node Type: %s",
1059                                 node[header.flags.node_type]);
1060
1061                 proto_tree_add_text(nbdgm_tree, offset+2, 2, "Datagram ID: 0x%04X",
1062                                 header.dgm_id);
1063                 proto_tree_add_text(nbdgm_tree, offset+4, 4, "Source IP: %s",
1064                                 ip_to_str((guint8 *)&header.src_ip));
1065                 proto_tree_add_text(nbdgm_tree, offset+8, 2, "Source Port: %d",
1066                                 header.src_port);
1067         }
1068
1069         offset += 10;
1070         max_data -= 10;
1071
1072         if (header.msg_type == 0x10 ||
1073                         header.msg_type == 0x11 || header.msg_type == 0x12) {
1074
1075                 if (tree) {
1076                         proto_tree_add_text(nbdgm_tree, offset, 2,
1077                                         "Datagram length: %d bytes", header.dgm_length);
1078                         proto_tree_add_text(nbdgm_tree, offset+2, 2,
1079                                         "Packet offset: %d bytes", header.pkt_offset);
1080                 }
1081
1082                 offset += 4;
1083                 max_data -= 4;
1084
1085                 /* Source name */
1086                 len = get_nbns_name(&pd[offset], pd, offset, name);
1087
1088                 if (tree) {
1089                         proto_tree_add_text(nbdgm_tree, offset, len, "Source name: %s",
1090                                         name);
1091                 }
1092                 offset += len;
1093                 max_data -= len;
1094
1095                 /* Destination name */
1096                 len = get_nbns_name(&pd[offset], pd, offset, name);
1097
1098                 if (tree) {
1099                         proto_tree_add_text(nbdgm_tree, offset, len, "Destination name: %s",
1100                                         name);
1101                 }
1102                 offset += len;
1103                 max_data -= len;
1104
1105                 /* here we can pass the packet off to the next protocol */
1106                 dissect_smb(pd, offset, fd, tree, max_data);
1107         }
1108         else if (header.msg_type == 0x13) {
1109                 if (tree) {
1110                         proto_tree_add_text(nbdgm_tree, offset, 1, "Error code: %s",
1111                                 val_to_str(header.error_code, error_codes, "Unknown (0x%x)"));
1112                 }
1113         }
1114         else if (header.msg_type == 0x14 ||
1115                         header.msg_type == 0x15 || header.msg_type == 0x16) {
1116                 /* Destination name */
1117                 len = get_nbns_name(&pd[offset], pd, offset, name);
1118
1119                 if (tree) {
1120                         proto_tree_add_text(nbdgm_tree, offset, len, "Destination name: %s",
1121                                         name);
1122                 }
1123         }
1124 }
1125
1126 /*
1127  * NetBIOS Session Service message types.
1128  */
1129 #define SESSION_MESSAGE                 0x00
1130 #define SESSION_REQUEST                 0x81
1131 #define POSITIVE_SESSION_RESPONSE       0x82
1132 #define NEGATIVE_SESSION_RESPONSE       0x83
1133 #define RETARGET_SESSION_RESPONSE       0x84
1134 #define SESSION_KEEP_ALIVE              0x85
1135
1136 static const value_string message_types[] = {
1137         { SESSION_MESSAGE,           "Session message" },
1138         { SESSION_REQUEST,           "Session request" },
1139         { POSITIVE_SESSION_RESPONSE, "Positive session response" },
1140         { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
1141         { RETARGET_SESSION_RESPONSE, "Retarget session response" },
1142         { SESSION_KEEP_ALIVE,        "Session keep-alive" },
1143         { 0x0,                       NULL }
1144 };
1145
1146 /*
1147  * NetBIOS Session Service flags.
1148  */
1149 #define NBSS_FLAGS_E                    0x1
1150
1151 static const value_string error_codes[] = {
1152         { 0x80, "Not listening on called name" },
1153         { 0x81, "Not listening for called name" },
1154         { 0x82, "Called name not present" },
1155         { 0x83, "Called name present, but insufficient resources" },
1156         { 0x8F, "Unspecified error" },
1157         { 0x0,  NULL }
1158 };
1159
1160 /*
1161  * Dissect a single NBSS packet (there may be more than one in a given TCP
1162  * segment). Hmmm, in my experience, I have never seen more than one NBSS
1163  * in a single segment, since they mostly contain SMBs which are essentially
1164  * a request response type protocol (RJS). Also, a single session message 
1165  * may be split over multiple segments.
1166  */
1167 static int
1168 dissect_nbss_packet(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data)
1169 {
1170         proto_tree      *nbss_tree = NULL;
1171         proto_item      *ti;
1172         proto_tree      *field_tree;
1173         proto_item      *tf;
1174         guint8          msg_type;
1175         guint8          flags;
1176         guint16         length;
1177         int             len;
1178         char            name[MAXDNAME+4];
1179
1180         msg_type = pd[offset];
1181         flags = pd[offset + 1];
1182         length = pntohs(&pd[offset + 2]);
1183         if (flags & NBSS_FLAGS_E)
1184                 length += 65536;
1185
1186         if (tree) {
1187           ti = proto_tree_add_text(tree, offset, length + 4,
1188                                    "NetBIOS Session Service");
1189           nbss_tree = proto_item_add_subtree(ti, ETT_NBSS);
1190           
1191           proto_tree_add_text(nbss_tree, offset, 1, "Message Type: %s",
1192                               val_to_str(msg_type, message_types, "Unknown (%x)"));
1193         }
1194
1195         offset += 1;
1196
1197         if (tree) {
1198           tf = proto_tree_add_text(nbss_tree, offset, 1, "Flags: 0x%04x", flags);
1199           field_tree = proto_item_add_subtree(tf, ETT_NBSS_FLAGS);
1200           proto_tree_add_text(field_tree, offset, 1, "%s",
1201                               decode_boolean_bitfield(flags, NBSS_FLAGS_E,
1202                                                       8, "Add 65536 to length", "Add 0 to length"));
1203         }
1204
1205         offset += 1;
1206
1207         if (tree) {
1208           proto_tree_add_text(nbss_tree, offset, 2, "Length: %u", length);
1209         }
1210
1211         offset += 2;
1212
1213         switch (msg_type) {
1214
1215         case SESSION_REQUEST:
1216           len = get_nbns_name(&pd[offset], pd, offset, name);
1217           if (tree)
1218             proto_tree_add_text(nbss_tree, offset, len,
1219                                 "Called name: %s", name);
1220           offset += len;
1221
1222           len = get_nbns_name(&pd[offset], pd, offset, name);
1223           
1224           if (tree)
1225             proto_tree_add_text(nbss_tree, offset, len,
1226                                 "Calling name: %s", name);
1227
1228           break;
1229
1230         case NEGATIVE_SESSION_RESPONSE:
1231           if (tree) 
1232             proto_tree_add_text(nbss_tree, offset, 1,
1233                                 "Error code: %s",
1234                                 val_to_str(pd[offset], error_codes, "Unknown (%x)"));
1235           break;
1236
1237         case RETARGET_SESSION_RESPONSE:
1238           if (tree)
1239             proto_tree_add_text(nbss_tree, offset, 4,
1240                                 "Retarget IP address: %s",
1241                                 ip_to_str((guint8 *)&pd[offset]));
1242           
1243           offset += 4;
1244
1245           if (tree)
1246             proto_tree_add_text(nbss_tree, offset, 2,
1247                                 "Retarget port: %u", pntohs(&pd[offset]));
1248
1249           break;
1250
1251         case SESSION_MESSAGE:
1252           /*
1253            * Here we can pass the packet off to the next protocol.
1254            */
1255
1256           dissect_smb(pd, offset, fd, tree, max_data - 4);
1257
1258           break;
1259
1260         }
1261         return length + 4;
1262 }
1263
1264 void
1265 dissect_nbss(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data)
1266 {
1267         guint8          msg_type;
1268         guint8          flags;
1269         guint16         length;
1270         int             len;
1271
1272         msg_type = pd[offset];
1273         flags = pd[offset + 1];
1274         length = pntohs(&pd[offset + 2]);
1275         if (flags & NBSS_FLAGS_E)
1276                 length += 65536;
1277
1278         if (check_col(fd, COL_PROTOCOL))
1279                 col_add_str(fd, COL_PROTOCOL, "NBSS (TCP)");
1280         if (check_col(fd, COL_INFO)) {
1281                 col_add_fstr(fd, COL_INFO,
1282                     val_to_str(msg_type, message_types, "Unknown (%x)"));
1283         }
1284
1285         while (max_data > 0) { 
1286           len = dissect_nbss_packet(pd, offset, fd, tree, max_data);
1287           offset += len;
1288           max_data -= len;
1289         }
1290
1291 }