2 * Routines for NetBIOS-over-TCP packet disassembly (the name dates back
3 * to when it had only NBNS)
4 * Gilbert Ramirez <gram@verdict.uthscsa.edu>
5 * Much stuff added by Guy Harris <guy@netapp.com>
7 * $Id: packet-nbns.c,v 1.35 2000/01/16 02:54:47 guy Exp $
9 * Ethereal - Network traffic analyzer
10 * By Gerald Combs <gerald@zing.org>
11 * Copyright 1998 Gerald Combs
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.
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.
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.
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
41 #include "packet-dns.h"
42 #include "packet-netbios.h"
44 static int proto_nbns = -1;
45 static int hf_nbns_response = -1;
46 static int hf_nbns_query = -1;
47 static int hf_nbns_transaction_id = -1;
48 static int hf_nbns_count_questions = -1;
49 static int hf_nbns_count_answers = -1;
50 static int hf_nbns_count_auth_rr = -1;
51 static int hf_nbns_count_add_rr = -1;
53 static gint ett_nbns = -1;
54 static gint ett_nbns_qd = -1;
55 static gint ett_nbns_flags = -1;
56 static gint ett_nbns_nb_flags = -1;
57 static gint ett_nbns_name_flags = -1;
58 static gint ett_nbns_rr = -1;
59 static gint ett_nbns_qry = -1;
60 static gint ett_nbns_ans = -1;
62 static int proto_nbdgm = -1;
63 static int hf_nbdgm_type = -1;
64 static int hf_nbdgm_fragment = -1;
65 static int hf_nbdgm_first = -1;
66 static int hf_nbdgm_node_type = -1;
67 static int hf_nbdgm_datagram_id = -1;
68 static int hf_nbdgm_src_ip = -1;
69 static int hf_nbdgm_src_port = -1;
71 static gint ett_nbdgm = -1;
73 static int proto_nbss = -1;
74 static int hf_nbss_type = -1;
75 static int hf_nbss_flags = -1;
77 static gint ett_nbss = -1;
78 static gint ett_nbss_flags = -1;
80 /* Packet structure taken from RFC 1002. See also RFC 1001.
81 * Opcode, flags, and rcode treated as "flags", similarly to DNS,
82 * to make it easier to lift the dissection code from "packet-dns.c". */
84 /* Offsets of fields in the NBNS header. */
92 /* Length of NBNS header. */
93 #define NBNS_HDRLEN 12
96 #define T_NB 32 /* NetBIOS name service RR */
97 #define T_NBSTAT 33 /* NetBIOS node status RR */
99 /* Bit fields in the flags */
100 #define F_RESPONSE (1<<15) /* packet is response */
101 #define F_OPCODE (0xF<<11) /* query opcode */
102 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
103 #define F_TRUNCATED (1<<9) /* response is truncated */
104 #define F_RECDESIRED (1<<8) /* recursion desired */
105 #define F_RECAVAIL (1<<7) /* recursion available */
106 #define F_BROADCAST (1<<4) /* broadcast/multicast packet */
107 #define F_RCODE (0xF<<0) /* reply code */
110 #define OPCODE_QUERY (0<<11) /* standard query */
111 #define OPCODE_REGISTRATION (5<<11) /* registration */
112 #define OPCODE_RELEASE (6<<11) /* release name */
113 #define OPCODE_WACK (7<<11) /* wait for acknowledgement */
114 #define OPCODE_REFRESH (8<<11) /* refresh registration */
115 #define OPCODE_REFRESHALT (9<<11) /* refresh registration (alternate opcode) */
116 #define OPCODE_MHREGISTRATION (15<<11) /* multi-homed registration */
119 #define RCODE_NOERROR (0<<0)
120 #define RCODE_FMTERROR (1<<0)
121 #define RCODE_SERVFAIL (2<<0)
122 #define RCODE_NAMEERROR (3<<0)
123 #define RCODE_NOTIMPL (4<<0)
124 #define RCODE_REFUSED (5<<0)
125 #define RCODE_ACTIVE (6<<0)
126 #define RCODE_CONFLICT (7<<0)
128 /* Values for the "NB_FLAGS" field of RR data. From RFC 1001 and 1002,
129 * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
131 #define NB_FLAGS_ONT (3<<(15-2)) /* bits for node type */
132 #define NB_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
133 #define NB_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
134 #define NB_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
135 #define NB_FLAGS_ONT_H_NODE (3<<(15-2)) /* H-mode node */
137 #define NB_FLAGS_G (1<<(15-0)) /* group name */
139 /* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
140 * RR data. From RFC 1001 and 1002, except for NAME_FLAGS_ONT_H_NODE,
141 * which was discovered by looking at packet traces. */
142 #define NAME_FLAGS_PRM (1<<(15-6)) /* name is permanent node name */
144 #define NAME_FLAGS_ACT (1<<(15-5)) /* name is active */
146 #define NAME_FLAGS_CNF (1<<(15-4)) /* name is in conflict */
148 #define NAME_FLAGS_DRG (1<<(15-3)) /* name is being deregistered */
150 #define NAME_FLAGS_ONT (3<<(15-2)) /* bits for node type */
151 #define NAME_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
152 #define NAME_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
153 #define NAME_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
155 #define NAME_FLAGS_G (1<<(15-0)) /* group name */
157 static const value_string opcode_vals[] = {
158 { OPCODE_QUERY, "Name query" },
159 { OPCODE_REGISTRATION, "Registration" },
160 { OPCODE_RELEASE, "Release" },
161 { OPCODE_WACK, "Wait for acknowledgment" },
162 { OPCODE_REFRESH, "Refresh" },
163 { OPCODE_REFRESHALT, "Refresh (alternate opcode)" },
164 { OPCODE_MHREGISTRATION, "Multi-homed registration" },
169 nbns_type_name (int type)
182 get_nbns_name(const u_char *pd, int offset, int nbns_data_offset,
183 char *name_ret, int *name_type_ret)
187 char nbname[NETBIOS_NAME_LEN];
188 char *pname, *pnbname, cname, cnbname;
191 name_len = get_dns_name(pd, offset, nbns_data_offset, name,
194 /* OK, now undo the first-level encoding. */
196 pnbname = &nbname[0];
198 /* Every two characters of the first level-encoded name
199 * turn into one character in the decoded name. */
202 break; /* no more characters */
204 break; /* scope ID follows */
205 if (cname < 'A' || cname > 'Z') {
208 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
212 cnbname = cname << 4;
216 if (cname == '\0' || cname == '.') {
217 /* No more characters in the name - but we're in
218 * the middle of a pair. Not legal. */
220 "Illegal NetBIOS name (odd number of bytes)");
223 if (cname < 'A' || cname > 'Z') {
226 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
233 /* Do we have room to store the character? */
234 if (pnbname < &nbname[NETBIOS_NAME_LEN]) {
235 /* Yes - store the character. */
239 /* We bump the pointer even if it's past the end of the
240 name, so we keep track of how long the name is. */
244 /* NetBIOS names are supposed to be exactly 16 bytes long. */
245 if (pnbname - nbname != NETBIOS_NAME_LEN) {
247 sprintf(nbname, "Illegal NetBIOS name (%ld bytes long)",
248 (long)(pnbname - nbname));
252 /* This one is; make its name printable. */
253 name_type = process_netbios_name(nbname, name_ret);
254 name_ret += strlen(name_ret);
255 sprintf(name_ret, "<%02x>", name_type);
258 /* We have a scope ID, starting at "pname"; append that to
259 * the decoded host name. */
260 strcpy(name_ret, pname);
262 if (name_type_ret != NULL)
263 *name_type_ret = name_type;
267 if (name_type_ret != NULL)
269 strcpy (name_ret, nbname);
275 get_nbns_name_type_class(const u_char *pd, int offset, int nbns_data_offset,
276 char *name_ret, int *name_len_ret, int *name_type_ret, int *type_ret,
283 name_len = get_nbns_name(pd, offset, nbns_data_offset, name_ret,
287 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
288 /* We ran past the end of the captured data in the packet. */
291 type = pntohs(&pd[offset]);
294 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
295 /* We ran past the end of the captured data in the packet. */
298 class = pntohs(&pd[offset]);
302 *name_len_ret = name_len;
308 add_name_and_type(proto_tree *tree, int offset, int len, char *tag,
309 char *name, int name_type)
311 if (name_type != -1) {
312 proto_tree_add_text(tree, offset, len, "%s: %s (%s)",
313 tag, name, netbios_name_type_descr(name_type));
315 proto_tree_add_text(tree, offset, len, "%s: %s",
321 dissect_nbns_query(const u_char *pd, int offset, int nbns_data_offset,
322 frame_data *fd, proto_tree *nbns_tree)
325 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
333 const u_char *data_start;
337 data_start = dptr = pd + offset;
339 len = get_nbns_name_type_class(pd, offset, nbns_data_offset, name,
340 &name_len, &name_type, &type, &class);
342 /* We ran past the end of the data in the packet. */
347 type_name = nbns_type_name(type);
348 class_name = dns_class_name(class);
351 col_append_fstr(fd, COL_INFO, " %s %s", type_name, name);
352 if (nbns_tree != NULL) {
353 tq = proto_tree_add_text(nbns_tree, offset, len,
354 "%s: type %s, class %s", name, type_name, class_name);
355 q_tree = proto_item_add_subtree(tq, ett_nbns_qd);
357 add_name_and_type(q_tree, offset, name_len, "Name", name,
361 proto_tree_add_text(q_tree, offset, 2, "Type: %s", type_name);
364 proto_tree_add_text(q_tree, offset, 2, "Class: %s", class_name);
368 return dptr - data_start;
372 nbns_add_nbns_flags(proto_tree *nbns_tree, int offset, u_short flags,
376 proto_tree *field_tree;
378 static const value_string rcode_vals[] = {
379 { RCODE_NOERROR, "No error" },
380 { RCODE_FMTERROR, "Request was invalidly formatted" },
381 { RCODE_SERVFAIL, "Server failure" },
382 { RCODE_NAMEERROR, "Requested name does not exist" },
383 { RCODE_NOTIMPL, "Request is not implemented" },
384 { RCODE_REFUSED, "Request was refused" },
385 { RCODE_ACTIVE, "Name is owned by another node" },
386 { RCODE_CONFLICT, "Name is in conflict" },
390 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals,
391 "Unknown operation"));
392 if (flags & F_RESPONSE && !is_wack) {
393 strcat(buf, " response");
395 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
398 tf = proto_tree_add_text(nbns_tree, offset, 2,
399 "Flags: 0x%04x (%s)", flags, buf);
400 field_tree = proto_item_add_subtree(tf, ett_nbns_flags);
401 proto_tree_add_text(field_tree, offset, 2, "%s",
402 decode_boolean_bitfield(flags, F_RESPONSE,
403 2*8, "Response", "Query"));
404 proto_tree_add_text(field_tree, offset, 2, "%s",
405 decode_enumerated_bitfield(flags, F_OPCODE,
406 2*8, opcode_vals, "%s"));
407 if (flags & F_RESPONSE) {
408 proto_tree_add_text(field_tree, offset, 2,
410 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
412 "Server is an authority for domain",
413 "Server isn't an authority for domain"));
415 proto_tree_add_text(field_tree, offset, 2, "%s",
416 decode_boolean_bitfield(flags, F_TRUNCATED,
418 "Message is truncated",
419 "Message is not truncated"));
420 proto_tree_add_text(field_tree, offset, 2, "%s",
421 decode_boolean_bitfield(flags, F_RECDESIRED,
423 "Do query recursively",
424 "Don't do query recursively"));
425 if (flags & F_RESPONSE) {
426 proto_tree_add_text(field_tree, offset, 2,
428 decode_boolean_bitfield(flags, F_RECAVAIL,
430 "Server can do recursive queries",
431 "Server can't do recursive queries"));
433 proto_tree_add_text(field_tree, offset, 2, "%s",
434 decode_boolean_bitfield(flags, F_BROADCAST,
437 "Not a broadcast packet"));
438 if (flags & F_RESPONSE && !is_wack) {
439 proto_tree_add_text(field_tree, offset, 2,
441 decode_enumerated_bitfield(flags, F_RCODE,
448 nbns_add_nb_flags(proto_tree *rr_tree, int offset, u_short flags)
451 proto_tree *field_tree;
453 static const value_string nb_flags_ont_vals[] = {
454 { NB_FLAGS_ONT_B_NODE, "B-node" },
455 { NB_FLAGS_ONT_P_NODE, "P-node" },
456 { NB_FLAGS_ONT_M_NODE, "M-node" },
457 { NB_FLAGS_ONT_H_NODE, "H-node" },
461 strcpy(buf, val_to_str(flags & NB_FLAGS_ONT, nb_flags_ont_vals,
464 if (flags & NB_FLAGS_G)
465 strcat(buf, "group");
467 strcat(buf, "unique");
468 tf = proto_tree_add_text(rr_tree, offset, 2, "Flags: 0x%x (%s)", flags,
470 field_tree = proto_item_add_subtree(tf, ett_nbns_nb_flags);
471 proto_tree_add_text(field_tree, offset, 2, "%s",
472 decode_boolean_bitfield(flags, NB_FLAGS_G,
476 proto_tree_add_text(field_tree, offset, 2, "%s",
477 decode_enumerated_bitfield(flags, NB_FLAGS_ONT,
478 2*8, nb_flags_ont_vals, "%s"));
482 nbns_add_name_flags(proto_tree *rr_tree, int offset, u_short flags)
485 proto_item *field_tree;
487 static const value_string name_flags_ont_vals[] = {
488 { NAME_FLAGS_ONT_B_NODE, "B-node" },
489 { NAME_FLAGS_ONT_P_NODE, "P-node" },
490 { NAME_FLAGS_ONT_M_NODE, "M-node" },
494 strcpy(buf, val_to_str(flags & NAME_FLAGS_ONT, name_flags_ont_vals,
497 if (flags & NAME_FLAGS_G)
498 strcat(buf, "group");
500 strcat(buf, "unique");
501 if (flags & NAME_FLAGS_DRG)
502 strcat(buf, ", being deregistered");
503 if (flags & NAME_FLAGS_CNF)
504 strcat(buf, ", in conflict");
505 if (flags & NAME_FLAGS_ACT)
506 strcat(buf, ", active");
507 if (flags & NAME_FLAGS_PRM)
508 strcat(buf, ", permanent node name");
509 tf = proto_tree_add_text(rr_tree, offset, 2, "Name flags: 0x%x (%s)",
511 field_tree = proto_item_add_subtree(tf, ett_nbns_name_flags);
512 proto_tree_add_text(field_tree, offset, 2, "%s",
513 decode_boolean_bitfield(flags, NAME_FLAGS_G,
517 proto_tree_add_text(field_tree, offset, 2, "%s",
518 decode_enumerated_bitfield(flags, NAME_FLAGS_ONT,
519 2*8, name_flags_ont_vals, "%s"));
520 proto_tree_add_text(field_tree, offset, 2, "%s",
521 decode_boolean_bitfield(flags, NAME_FLAGS_DRG,
523 "Name is being deregistered",
524 "Name is not being deregistered"));
525 proto_tree_add_text(field_tree, offset, 2, "%s",
526 decode_boolean_bitfield(flags, NAME_FLAGS_CNF,
528 "Name is in conflict",
529 "Name is not in conflict"));
530 proto_tree_add_text(field_tree, offset, 2, "%s",
531 decode_boolean_bitfield(flags, NAME_FLAGS_ACT,
534 "Name is not active"));
535 proto_tree_add_text(field_tree, offset, 2, "%s",
536 decode_boolean_bitfield(flags, NAME_FLAGS_PRM,
538 "Permanent node name",
539 "Not permanent node name"));
543 dissect_nbns_answer(const u_char *pd, int offset, int nbns_data_offset,
544 frame_data *fd, proto_tree *nbns_tree, int opcode)
547 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME + 64];
556 const u_char *data_start;
562 char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
564 char nbname[16+4+1]; /* 4 for [<last char>] */
567 data_start = dptr = pd + offset;
570 len = get_nbns_name_type_class(pd, offset, nbns_data_offset, name,
571 &name_len, &name_type, &type, &class);
573 /* We ran past the end of the data in the packet. */
579 type_name = nbns_type_name(type);
580 class_name = dns_class_name(class);
582 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
583 /* We ran past the end of the captured data in the packet. */
590 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
591 /* We ran past the end of the captured data in the packet. */
594 data_len = pntohs(dptr);
599 case T_NB: /* "NB" record */
601 if (opcode != OPCODE_WACK) {
602 col_append_fstr(fd, COL_INFO, " %s %s",
603 type_name, ip_to_str((guint8 *)(dptr + 2)));
606 if (nbns_tree == NULL)
608 trr = proto_tree_add_text(nbns_tree, offset,
609 (dptr - data_start) + data_len,
610 "%s: type %s, class %s",
611 name, type_name, class_name);
613 strcat(name, netbios_name_type_descr(name_type));
615 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, offset, name,
616 name_len, type_name, class_name, ttl, data_len);
617 while (data_len > 0) {
618 if (opcode == OPCODE_WACK) {
619 /* WACK response. This doesn't contain the
620 * same type of RR data as other T_NB
622 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
623 /* We ran past the end of the captured
624 data in the packet. */
628 proto_tree_add_text(rr_tree, cur_offset,
629 data_len, "(incomplete entry)");
632 flags = pntohs(dptr);
634 nbns_add_nbns_flags(rr_tree, cur_offset,
639 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
640 /* We ran past the end of the captured
641 data in the packet. */
645 proto_tree_add_text(rr_tree, cur_offset,
646 data_len, "(incomplete entry)");
649 flags = pntohs(dptr);
651 nbns_add_nb_flags(rr_tree, cur_offset, flags);
655 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
656 /* We ran past the end of the captured
657 data in the packet. */
661 proto_tree_add_text(rr_tree, cur_offset,
662 data_len, "(incomplete entry)");
665 proto_tree_add_text(rr_tree, cur_offset, 4,
667 ip_to_str((guint8 *)dptr));
675 case T_NBSTAT: /* "NBSTAT" record */
677 col_append_fstr(fd, COL_INFO, " %s", type_name);
678 if (nbns_tree == NULL)
680 trr = proto_tree_add_text(nbns_tree, offset,
681 (dptr - data_start) + data_len,
682 "%s: type %s, class %s",
683 name, type_name, class_name);
684 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, offset, name,
685 name_len, type_name, class_name, ttl, data_len);
686 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
687 /* We ran past the end of the captured
688 data in the packet. */
692 proto_tree_add_text(rr_tree, cur_offset,
693 data_len, "(incomplete entry)");
698 proto_tree_add_text(rr_tree, cur_offset, 2,
699 "Number of names: %u", num_names);
702 while (num_names != 0) {
703 if (!BYTES_ARE_IN_FRAME(cur_offset, NETBIOS_NAME_LEN)) {
704 /* We ran past the end of the captured
705 data in the packet. */
708 if (data_len < NETBIOS_NAME_LEN) {
709 proto_tree_add_text(rr_tree, cur_offset,
710 data_len, "(incomplete entry)");
713 memcpy(nbname, dptr, NETBIOS_NAME_LEN);
714 dptr += NETBIOS_NAME_LEN;
715 name_type = process_netbios_name(nbname,
717 proto_tree_add_text(rr_tree, cur_offset,
718 NETBIOS_NAME_LEN, "Name: %s<%02x> (%s)",
720 netbios_name_type_descr(name_type));
721 cur_offset += NETBIOS_NAME_LEN;
722 data_len -= NETBIOS_NAME_LEN;
724 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
725 /* We ran past the end of the captured
726 data in the packet. */
730 proto_tree_add_text(rr_tree, cur_offset,
731 data_len, "(incomplete entry)");
734 name_flags = pntohs(dptr);
736 nbns_add_name_flags(rr_tree, cur_offset, name_flags);
743 if (!BYTES_ARE_IN_FRAME(cur_offset, 6)) {
744 /* We ran past the end of the captured
745 data in the packet. */
749 proto_tree_add_text(rr_tree, cur_offset,
750 data_len, "(incomplete entry)");
753 proto_tree_add_text(rr_tree, cur_offset, 6,
755 ether_to_str((guint8 *)dptr));
760 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
761 /* We ran past the end of the captured
762 data in the packet. */
766 proto_tree_add_text(rr_tree, cur_offset,
767 data_len, "(incomplete entry)");
770 proto_tree_add_text(rr_tree, cur_offset, 1,
771 "Jumpers: 0x%x", *dptr);
776 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
777 /* We ran past the end of the captured
778 data in the packet. */
782 proto_tree_add_text(rr_tree, cur_offset,
783 data_len, "(incomplete entry)");
786 proto_tree_add_text(rr_tree, cur_offset, 1,
787 "Test result: 0x%x", *dptr);
792 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
793 /* We ran past the end of the captured
794 data in the packet. */
798 proto_tree_add_text(rr_tree, cur_offset,
799 data_len, "(incomplete entry)");
802 proto_tree_add_text(rr_tree, cur_offset, 2,
803 "Version number: 0x%x", pntohs(dptr));
808 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
809 /* We ran past the end of the captured
810 data in the packet. */
814 proto_tree_add_text(rr_tree, cur_offset,
815 data_len, "(incomplete entry)");
818 proto_tree_add_text(rr_tree, cur_offset, 2,
819 "Period of statistics: 0x%x", pntohs(dptr));
824 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
825 /* We ran past the end of the captured
826 data in the packet. */
830 proto_tree_add_text(rr_tree, cur_offset,
831 data_len, "(incomplete entry)");
834 proto_tree_add_text(rr_tree, cur_offset, 2,
835 "Number of CRCs: %u", pntohs(dptr));
840 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
841 /* We ran past the end of the captured
842 data in the packet. */
846 proto_tree_add_text(rr_tree, cur_offset,
847 data_len, "(incomplete entry)");
850 proto_tree_add_text(rr_tree, cur_offset, 2,
851 "Number of alignment errors: %u", pntohs(dptr));
856 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
857 /* We ran past the end of the captured
858 data in the packet. */
862 proto_tree_add_text(rr_tree, cur_offset,
863 data_len, "(incomplete entry)");
866 proto_tree_add_text(rr_tree, cur_offset, 2,
867 "Number of collisions: %u", pntohs(dptr));
872 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
873 /* We ran past the end of the captured
874 data in the packet. */
878 proto_tree_add_text(rr_tree, cur_offset,
879 data_len, "(incomplete entry)");
882 proto_tree_add_text(rr_tree, cur_offset, 2,
883 "Number of send aborts: %u", pntohs(dptr));
888 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
889 /* We ran past the end of the captured
890 data in the packet. */
894 proto_tree_add_text(rr_tree, cur_offset,
895 data_len, "(incomplete entry)");
898 proto_tree_add_text(rr_tree, cur_offset, 4,
899 "Number of good sends: %u", pntohl(dptr));
904 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
905 /* We ran past the end of the captured
906 data in the packet. */
910 proto_tree_add_text(rr_tree, cur_offset,
911 data_len, "(incomplete entry)");
914 proto_tree_add_text(rr_tree, cur_offset, 4,
915 "Number of good receives: %u", pntohl(dptr));
920 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
921 /* We ran past the end of the captured
922 data in the packet. */
926 proto_tree_add_text(rr_tree, cur_offset,
927 data_len, "(incomplete entry)");
930 proto_tree_add_text(rr_tree, cur_offset, 2,
931 "Number of retransmits: %u", pntohs(dptr));
936 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
937 /* We ran past the end of the captured
938 data in the packet. */
942 proto_tree_add_text(rr_tree, cur_offset,
943 data_len, "(incomplete entry)");
946 proto_tree_add_text(rr_tree, cur_offset, 2,
947 "Number of no resource conditions: %u", pntohs(dptr));
952 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
953 /* We ran past the end of the captured
954 data in the packet. */
958 proto_tree_add_text(rr_tree, cur_offset,
959 data_len, "(incomplete entry)");
962 proto_tree_add_text(rr_tree, cur_offset, 2,
963 "Number of command blocks: %u", pntohs(dptr));
968 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
969 /* We ran past the end of the captured
970 data in the packet. */
974 proto_tree_add_text(rr_tree, cur_offset,
975 data_len, "(incomplete entry)");
978 proto_tree_add_text(rr_tree, cur_offset, 2,
979 "Number of pending sessions: %u", pntohs(dptr));
984 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
985 /* We ran past the end of the captured
986 data in the packet. */
990 proto_tree_add_text(rr_tree, cur_offset,
991 data_len, "(incomplete entry)");
994 proto_tree_add_text(rr_tree, cur_offset, 2,
995 "Max number of pending sessions: %u", pntohs(dptr));
999 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1000 /* We ran past the end of the captured
1001 data in the packet. */
1005 proto_tree_add_text(rr_tree, cur_offset,
1006 data_len, "(incomplete entry)");
1009 proto_tree_add_text(rr_tree, cur_offset, 2,
1010 "Max total sessions possible: %u", pntohs(dptr));
1015 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1016 /* We ran past the end of the captured
1017 data in the packet. */
1021 proto_tree_add_text(rr_tree, cur_offset,
1022 data_len, "(incomplete entry)");
1025 proto_tree_add_text(rr_tree, cur_offset, 2,
1026 "Session data packet size: %u", pntohs(dptr));
1035 col_append_fstr(fd, COL_INFO, " %s", type_name);
1036 if (nbns_tree == NULL)
1038 trr = proto_tree_add_text(nbns_tree, offset,
1039 (dptr - data_start) + data_len,
1040 "%s: type %s, class %s",
1041 name, type_name, class_name);
1042 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, offset, name,
1043 name_len, type_name, class_name, ttl, data_len);
1044 proto_tree_add_text(rr_tree, cur_offset, data_len, "Data");
1049 return dptr - data_start;
1053 dissect_query_records(const u_char *pd, int cur_off, int nbns_data_offset,
1054 int count, frame_data *fd, proto_tree *nbns_tree)
1056 int start_off, add_off;
1057 proto_tree *qatree = NULL;
1058 proto_item *ti = NULL;
1060 start_off = cur_off;
1061 if (nbns_tree != NULL) {
1062 ti = proto_tree_add_text(nbns_tree, start_off, 0, "Queries");
1063 qatree = proto_item_add_subtree(ti, ett_nbns_qry);
1065 while (count-- > 0) {
1066 add_off = dissect_nbns_query(pd, cur_off, nbns_data_offset,
1069 /* We ran past the end of the captured data in the
1076 proto_item_set_len(ti, cur_off - start_off);
1078 return cur_off - start_off;
1084 dissect_answer_records(const u_char *pd, int cur_off, int nbns_data_offset,
1085 int count, frame_data *fd, proto_tree *nbns_tree, int opcode, char *name)
1087 int start_off, add_off;
1088 proto_tree *qatree = NULL;
1089 proto_item *ti = NULL;
1091 start_off = cur_off;
1092 if (nbns_tree != NULL) {
1093 ti = proto_tree_add_text(nbns_tree, start_off, 0, name);
1094 qatree = proto_item_add_subtree(ti, ett_nbns_ans);
1096 while (count-- > 0) {
1097 add_off = dissect_nbns_answer(pd, cur_off, nbns_data_offset,
1098 fd, qatree, opcode);
1100 /* We ran past the end of the captured data in the
1107 proto_item_set_len(ti, cur_off - start_off);
1108 return cur_off - start_off;
1112 dissect_nbns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1114 int nbns_data_offset;
1115 proto_tree *nbns_tree = NULL;
1117 guint16 id, flags, quest, ans, auth, add;
1120 nbns_data_offset = offset;
1122 if (check_col(fd, COL_PROTOCOL))
1123 col_add_str(fd, COL_PROTOCOL, "NBNS");
1125 if (pi.captured_len < NBNS_HDRLEN) {
1126 col_add_str(fd, COL_INFO, "Short NBNS packet");
1127 dissect_data(pd, offset, fd, tree);
1131 /* To do: check for runts, errs, etc. */
1132 id = pntohs(&pd[offset + NBNS_ID]);
1133 flags = pntohs(&pd[offset + NBNS_FLAGS]);
1134 quest = pntohs(&pd[offset + NBNS_QUEST]);
1135 ans = pntohs(&pd[offset + NBNS_ANS]);
1136 auth = pntohs(&pd[offset + NBNS_AUTH]);
1137 add = pntohs(&pd[offset + NBNS_ADD]);
1139 if (check_col(fd, COL_INFO)) {
1140 col_add_fstr(fd, COL_INFO, "%s%s",
1141 val_to_str(flags & F_OPCODE, opcode_vals,
1142 "Unknown operation (%x)"),
1143 (flags & F_RESPONSE) ? " response" : "");
1145 /* Set "fd" to NULL; we pass a NULL "fd" to the query and
1146 answer dissectors, as a way of saying that they shouldn't
1147 add stuff to the COL_INFO column (a call to
1148 "check_col(fd, COL_INFO)" is more expensive than a check
1149 that a pointer isn't NULL). */
1154 ti = proto_tree_add_item(tree, proto_nbns, offset, END_OF_FRAME, NULL);
1155 nbns_tree = proto_item_add_subtree(ti, ett_nbns);
1157 if (flags & F_RESPONSE) {
1158 proto_tree_add_item_hidden(nbns_tree, hf_nbns_response,
1161 proto_tree_add_item_hidden(nbns_tree, hf_nbns_query,
1165 proto_tree_add_item(nbns_tree, hf_nbns_transaction_id,
1166 offset + NBNS_ID, 2, id);
1168 nbns_add_nbns_flags(nbns_tree, offset + NBNS_FLAGS, flags, 0);
1169 proto_tree_add_item(nbns_tree, hf_nbns_count_questions,
1170 offset + NBNS_QUEST, 2, quest);
1171 proto_tree_add_item(nbns_tree, hf_nbns_count_answers,
1172 offset + NBNS_ANS, 2, ans);
1173 proto_tree_add_item(nbns_tree, hf_nbns_count_auth_rr,
1174 offset + NBNS_AUTH, 2, auth);
1175 proto_tree_add_item(nbns_tree, hf_nbns_count_add_rr,
1176 offset + NBNS_ADD, 2, add);
1179 cur_off = offset + NBNS_HDRLEN;
1182 /* If this is a response, don't add information about the
1183 queries to the summary, just add information about the
1185 cur_off += dissect_query_records(pd, cur_off,
1186 nbns_data_offset, quest,
1187 (!(flags & F_RESPONSE) ? fd : NULL), nbns_tree);
1191 /* If this is a request, don't add information about the
1192 answers to the summary, just add information about the
1194 cur_off += dissect_answer_records(pd, cur_off,
1195 nbns_data_offset, ans,
1196 ((flags & F_RESPONSE) ? fd : NULL), nbns_tree,
1197 flags & F_OPCODE, "Answers");
1201 /* Don't add information about the authoritative name
1202 servers, or the additional records, to the summary. */
1204 cur_off += dissect_answer_records(pd, cur_off,
1206 auth, NULL, nbns_tree,
1208 "Authoritative nameservers");
1211 cur_off += dissect_answer_records(pd, cur_off,
1213 add, NULL, nbns_tree,
1215 "Additional records");
1219 /* NetBIOS datagram packet, from RFC 1002, page 32 */
1220 struct nbdgm_header {
1231 /* For packets with data */
1235 /* For error packets */
1240 dissect_nbdgm(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1242 proto_tree *nbdgm_tree = NULL;
1244 struct nbdgm_header header;
1247 int max_data = pi.captured_len - offset;
1251 "Direct_unique datagram",
1252 "Direct_group datagram",
1253 "Broadcast datagram",
1255 "Datagram query request",
1256 "Datagram positive query response",
1257 "Datagram negative query response"
1267 static value_string error_codes[] = {
1268 { 0x82, "Destination name not present" },
1269 { 0x83, "Invalid source name format" },
1270 { 0x84, "Invalid destination name format" },
1274 char *yesno[] = { "No", "Yes" };
1276 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1280 header.msg_type = pd[offset];
1282 flags = pd[offset+1];
1283 header.flags.more = flags & 1;
1284 header.flags.first = (flags & 2) >> 1;
1285 header.flags.node_type = (flags & 12) >> 2;
1287 header.dgm_id = pntohs(&pd[offset+2]);
1288 memcpy(&header.src_ip, &pd[offset+4], 4);
1289 header.src_port = pntohs(&pd[offset+8]);
1291 if (header.msg_type == 0x10 ||
1292 header.msg_type == 0x11 || header.msg_type == 0x12) {
1293 header.dgm_length = pntohs(&pd[offset+10]);
1294 header.pkt_offset = pntohs(&pd[offset+12]);
1296 else if (header.msg_type == 0x13) {
1297 header.error_code = pntohs(&pd[offset+10]);
1300 message_index = header.msg_type - 0x0f;
1301 if (message_index < 1 || message_index > 8) {
1305 if (check_col(fd, COL_PROTOCOL))
1306 col_add_str(fd, COL_PROTOCOL, "NBDS");
1307 if (check_col(fd, COL_INFO)) {
1308 col_add_fstr(fd, COL_INFO, "%s", message[message_index]);
1312 ti = proto_tree_add_item(tree, proto_nbdgm, offset, header.dgm_length, NULL);
1313 nbdgm_tree = proto_item_add_subtree(ti, ett_nbdgm);
1315 proto_tree_add_item_format(nbdgm_tree, hf_nbdgm_type,
1319 message[message_index]);
1320 proto_tree_add_item_format(nbdgm_tree, hf_nbdgm_fragment,
1323 "More fragments follow: %s",
1324 yesno[header.flags.more]);
1325 proto_tree_add_item_format(nbdgm_tree, hf_nbdgm_first,
1328 "This is first fragment: %s",
1329 yesno[header.flags.first]);
1330 proto_tree_add_item_format(nbdgm_tree, hf_nbdgm_node_type,
1332 header.flags.node_type,
1334 node[header.flags.node_type]);
1336 proto_tree_add_item(nbdgm_tree, hf_nbdgm_datagram_id,
1337 offset+2, 2, header.dgm_id);
1338 proto_tree_add_item(nbdgm_tree, hf_nbdgm_src_ip,
1339 offset+4, 4, header.src_ip);
1340 proto_tree_add_item(nbdgm_tree, hf_nbdgm_src_port,
1341 offset+8, 2, header.src_port);
1348 if (header.msg_type == 0x10 ||
1349 header.msg_type == 0x11 || header.msg_type == 0x12) {
1352 proto_tree_add_text(nbdgm_tree, offset, 2,
1353 "Datagram length: %d bytes", header.dgm_length);
1354 proto_tree_add_text(nbdgm_tree, offset+2, 2,
1355 "Packet offset: %d bytes", header.pkt_offset);
1362 len = get_nbns_name(pd, offset, offset, name, &name_type);
1365 add_name_and_type(nbdgm_tree, offset, len,
1366 "Source name", name, name_type);
1371 /* Destination name */
1372 len = get_nbns_name(pd, offset, offset, name, &name_type);
1375 add_name_and_type(nbdgm_tree, offset, len,
1376 "Destination name", name, name_type);
1381 /* here we can pass the packet off to the next protocol */
1382 dissect_smb(pd, offset, fd, tree, max_data);
1384 else if (header.msg_type == 0x13) {
1386 proto_tree_add_text(nbdgm_tree, offset, 1, "Error code: %s",
1387 val_to_str(header.error_code, error_codes, "Unknown (0x%x)"));
1390 else if (header.msg_type == 0x14 ||
1391 header.msg_type == 0x15 || header.msg_type == 0x16) {
1392 /* Destination name */
1393 len = get_nbns_name(pd, offset, offset, name, &name_type);
1396 add_name_and_type(nbdgm_tree, offset, len,
1397 "Destination name", name, name_type);
1403 * NetBIOS Session Service message types.
1405 #define SESSION_MESSAGE 0x00
1406 #define SESSION_REQUEST 0x81
1407 #define POSITIVE_SESSION_RESPONSE 0x82
1408 #define NEGATIVE_SESSION_RESPONSE 0x83
1409 #define RETARGET_SESSION_RESPONSE 0x84
1410 #define SESSION_KEEP_ALIVE 0x85
1412 static const value_string message_types[] = {
1413 { SESSION_MESSAGE, "Session message" },
1414 { SESSION_REQUEST, "Session request" },
1415 { POSITIVE_SESSION_RESPONSE, "Positive session response" },
1416 { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
1417 { RETARGET_SESSION_RESPONSE, "Retarget session response" },
1418 { SESSION_KEEP_ALIVE, "Session keep-alive" },
1423 * NetBIOS Session Service flags.
1425 #define NBSS_FLAGS_E 0x1
1427 static const value_string error_codes[] = {
1428 { 0x80, "Not listening on called name" },
1429 { 0x81, "Not listening for called name" },
1430 { 0x82, "Called name not present" },
1431 { 0x83, "Called name present, but insufficient resources" },
1432 { 0x8F, "Unspecified error" },
1437 * Dissect a single NBSS packet (there may be more than one in a given TCP
1438 * segment). Hmmm, in my experience, I have never seen more than one NBSS
1439 * in a single segment, since they mostly contain SMBs which are essentially
1440 * a request response type protocol (RJS). Also, a single session message
1441 * may be split over multiple segments.
1444 dissect_nbss_packet(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data)
1446 proto_tree *nbss_tree = NULL;
1448 proto_tree *field_tree;
1454 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1457 msg_type = pd[offset];
1458 flags = pd[offset + 1];
1459 length = pntohs(&pd[offset + 2]);
1460 if (flags & NBSS_FLAGS_E)
1464 ti = proto_tree_add_item(tree, proto_nbss, offset, length + 4, NULL);
1465 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1467 proto_tree_add_item_format(nbss_tree, hf_nbss_type,
1471 val_to_str(msg_type, message_types,
1478 tf = proto_tree_add_item(nbss_tree, hf_nbss_flags, offset, 1, flags);
1479 field_tree = proto_item_add_subtree(tf, ett_nbss_flags);
1480 proto_tree_add_text(field_tree, offset, 1, "%s",
1481 decode_boolean_bitfield(flags, NBSS_FLAGS_E,
1482 8, "Add 65536 to length", "Add 0 to length"));
1488 proto_tree_add_text(nbss_tree, offset, 2, "Length: %u", length);
1495 case SESSION_REQUEST:
1496 len = get_nbns_name(pd, offset, offset, name, &name_type);
1498 add_name_and_type(nbss_tree, offset, len,
1499 "Called name", name, name_type);
1502 len = get_nbns_name(pd, offset, offset, name, &name_type);
1505 add_name_and_type(nbss_tree, offset, len,
1506 "Calling name", name, name_type);
1510 case NEGATIVE_SESSION_RESPONSE:
1512 proto_tree_add_text(nbss_tree, offset, 1,
1514 val_to_str(pd[offset], error_codes, "Unknown (%x)"));
1517 case RETARGET_SESSION_RESPONSE:
1519 proto_tree_add_text(nbss_tree, offset, 4,
1520 "Retarget IP address: %s",
1521 ip_to_str((guint8 *)&pd[offset]));
1526 proto_tree_add_text(nbss_tree, offset, 2,
1527 "Retarget port: %u", pntohs(&pd[offset]));
1531 case SESSION_MESSAGE:
1533 * Here we can pass the packet off to the next protocol.
1536 dissect_smb(pd, offset, fd, tree, max_data - 4);
1545 dissect_nbss(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1553 msg_type = pd[offset];
1554 flags = pd[offset + 1];
1555 length = pntohs(&pd[offset + 2]);
1556 if (flags & NBSS_FLAGS_E)
1560 * XXX - we should set this based on both "pi.captured_len"
1563 max_data = pi.captured_len - offset;
1565 /* Hmmm, it may be a continuation message ... */
1569 if (((msg_type != SESSION_REQUEST) &&
1570 (msg_type != POSITIVE_SESSION_RESPONSE) &&
1571 (msg_type != NEGATIVE_SESSION_RESPONSE) &&
1572 (msg_type != RETARGET_SESSION_RESPONSE) &&
1573 (msg_type != SESSION_MESSAGE)) ||
1574 ((msg_type == SESSION_MESSAGE) &&
1575 (memcmp(pd + offset + 4, "\377SMB", 4) != 0))) {
1577 if (check_col(fd, COL_PROTOCOL))
1578 col_add_str(fd, COL_PROTOCOL, "NBSS");
1579 if (check_col(fd, COL_INFO)) {
1580 col_add_fstr(fd, COL_INFO, "NBSS Continuation Message");
1584 proto_tree_add_text(tree, offset, max_data, "Continuation data");
1590 if (check_col(fd, COL_PROTOCOL))
1591 col_add_str(fd, COL_PROTOCOL, "NBSS");
1592 if (check_col(fd, COL_INFO)) {
1593 col_add_fstr(fd, COL_INFO,
1594 val_to_str(msg_type, message_types, "Unknown (%x)"));
1597 while (max_data > 0) {
1598 len = dissect_nbss_packet(pd, offset, fd, tree, max_data);
1606 proto_register_nbt(void)
1609 static hf_register_info hf_nbns[] = {
1610 { &hf_nbns_response,
1611 { "Response", "nbns.response",
1612 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1613 "TRUE if NBNS response" }},
1615 { "Query", "nbns.query",
1616 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1617 "TRUE if NBNS query" }},
1618 { &hf_nbns_transaction_id,
1619 { "Transaction ID", "nbns.id",
1620 FT_UINT16, BASE_HEX, NULL, 0x0,
1621 "Identification of transaction" }},
1622 { &hf_nbns_count_questions,
1623 { "Questions", "nbns.count.queries",
1624 FT_UINT16, BASE_DEC, NULL, 0x0,
1625 "Number of queries in packet" }},
1626 { &hf_nbns_count_answers,
1627 { "Answer RRs", "nbns.count.answers",
1628 FT_UINT16, BASE_DEC, NULL, 0x0,
1629 "Number of answers in packet" }},
1630 { &hf_nbns_count_auth_rr,
1631 { "Authority RRs", "nbns.count.auth_rr",
1632 FT_UINT16, BASE_DEC, NULL, 0x0,
1633 "Number of authoritative records in packet" }},
1634 { &hf_nbns_count_add_rr,
1635 { "Additional RRs", "nbns.count.add_rr",
1636 FT_UINT16, BASE_DEC, NULL, 0x0,
1637 "Number of additional records in packet" }}
1640 static hf_register_info hf_nbdgm[] = {
1642 { "Message Type", "nbdgm.type",
1643 FT_UINT8, BASE_DEC, NULL, 0x0,
1644 "NBDGM message type" }},
1645 { &hf_nbdgm_fragment,
1646 { "Fragmented", "nbdgm.next",
1647 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1648 "TRUE if more fragments follow" }},
1650 { "First fragment", "nbdgm.first",
1651 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1652 "TRUE if first fragment" }},
1653 { &hf_nbdgm_node_type,
1654 { "Node Type", "nbdgm.node_type",
1655 FT_UINT8, BASE_DEC, NULL, 0x0,
1657 { &hf_nbdgm_datagram_id,
1658 { "Datagram ID", "nbdgm.dgram_id",
1659 FT_UINT16, BASE_HEX, NULL, 0x0,
1660 "Datagram identifier" }},
1662 { "Source IP", "nbdgm.src.ip",
1663 FT_IPv4, BASE_NONE, NULL, 0x0,
1664 "Source IPv4 address" }},
1665 { &hf_nbdgm_src_port,
1666 { "Source Port", "nbdgm.src.port",
1667 FT_UINT16, BASE_DEC, NULL, 0x0,
1671 static hf_register_info hf_nbss[] = {
1673 { "Message Type", "nbss.type",
1674 FT_UINT8, BASE_DEC, NULL, 0x0,
1675 "NBSS message type" }},
1677 { "Flags", "nbss.flags",
1678 FT_UINT8, BASE_HEX, NULL, 0x0,
1679 "NBSS message flags" }}
1681 static gint *ett[] = {
1686 &ett_nbns_name_flags,
1695 proto_nbns = proto_register_protocol("NetBIOS Name Service", "nbns");
1696 proto_register_field_array(proto_nbns, hf_nbns, array_length(hf_nbns));
1698 proto_nbdgm = proto_register_protocol("NetBIOS Datagram Service", "nbdgm");
1699 proto_register_field_array(proto_nbdgm, hf_nbdgm, array_length(hf_nbdgm));
1701 proto_nbss = proto_register_protocol("NetBIOS Session Service", "nbss");
1702 proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));
1704 proto_register_subtree_array(ett, array_length(ett));