2 * Routines for NetBIOS-over-TCP packet disassembly (the name dates back
3 * to when it had only NBNS)
4 * Guy Harris <guy@alum.mit.edu>
6 * $Id: packet-nbns.c,v 1.79 2002/08/28 21:00:22 jmayer Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #include <epan/packet.h>
36 #include "packet-dns.h"
37 #include "packet-netbios.h"
38 #include "packet-tcp.h"
39 #include "packet-frame.h"
42 static int proto_nbns = -1;
43 static int hf_nbns_flags = -1;
44 static int hf_nbns_flags_response = -1;
45 static int hf_nbns_flags_opcode = -1;
46 static int hf_nbns_flags_authoritative = -1;
47 static int hf_nbns_flags_truncated = -1;
48 static int hf_nbns_flags_recdesired = -1;
49 static int hf_nbns_flags_recavail = -1;
50 static int hf_nbns_flags_broadcast = -1;
51 static int hf_nbns_flags_rcode = -1;
52 static int hf_nbns_transaction_id = -1;
53 static int hf_nbns_count_questions = -1;
54 static int hf_nbns_count_answers = -1;
55 static int hf_nbns_count_auth_rr = -1;
56 static int hf_nbns_count_add_rr = -1;
58 static gint ett_nbns = -1;
59 static gint ett_nbns_qd = -1;
60 static gint ett_nbns_flags = -1;
61 static gint ett_nbns_nb_flags = -1;
62 static gint ett_nbns_name_flags = -1;
63 static gint ett_nbns_rr = -1;
64 static gint ett_nbns_qry = -1;
65 static gint ett_nbns_ans = -1;
67 static int proto_nbdgm = -1;
68 static int hf_nbdgm_type = -1;
69 static int hf_nbdgm_fragment = -1;
70 static int hf_nbdgm_first = -1;
71 static int hf_nbdgm_node_type = -1;
72 static int hf_nbdgm_datagram_id = -1;
73 static int hf_nbdgm_src_ip = -1;
74 static int hf_nbdgm_src_port = -1;
76 static gint ett_nbdgm = -1;
78 static int proto_nbss = -1;
79 static int hf_nbss_type = -1;
80 static int hf_nbss_flags = -1;
82 static gint ett_nbss = -1;
83 static gint ett_nbss_flags = -1;
85 /* desegmentation of NBSS over TCP */
86 static gboolean nbss_desegment = TRUE;
88 /* See RFC 1001 and 1002 for information on the first three, and see
90 http://www.cifs.com/specs/draft-leach-cifs-v1-spec-01.txt
92 Appendix B, and various messages on the CIFS mailing list such as
94 http://discuss.microsoft.com/SCRIPTS/WA-MSD.EXE?A2=ind9811A&L=cifs&P=R386
96 for information on the fourth. */
97 #define UDP_PORT_NBNS 137
98 #define UDP_PORT_NBDGM 138
99 #define TCP_PORT_NBSS 139
100 #define TCP_PORT_CIFS 445
102 /* Packet structure taken from RFC 1002. See also RFC 1001.
103 * Opcode, flags, and rcode treated as "flags", similarly to DNS,
104 * to make it easier to lift the dissection code from "packet-dns.c". */
106 /* Offsets of fields in the NBNS header. */
114 /* Length of NBNS header. */
115 #define NBNS_HDRLEN 12
118 #define T_NB 32 /* NetBIOS name service RR */
119 #define T_NBSTAT 33 /* NetBIOS node status RR */
121 /* Bit fields in the flags */
122 #define F_RESPONSE (1<<15) /* packet is response */
123 #define F_OPCODE (0xF<<11) /* query opcode */
124 #define OPCODE_SHIFT 11
125 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
126 #define F_TRUNCATED (1<<9) /* response is truncated */
127 #define F_RECDESIRED (1<<8) /* recursion desired */
128 #define F_RECAVAIL (1<<7) /* recursion available */
129 #define F_BROADCAST (1<<4) /* broadcast/multicast packet */
130 #define F_RCODE (0xF<<0) /* reply code */
132 static const true_false_string tfs_flags_response = {
133 "Message is a response",
137 static const true_false_string tfs_flags_authoritative = {
138 "Server is an authority for domain",
139 "Server is not an authority for domain"
142 static const true_false_string tfs_flags_truncated = {
143 "Message is truncated",
144 "Message is not truncated"
147 static const true_false_string tfs_flags_recdesired = {
148 "Do query recursively",
149 "Don't do query recursively"
152 static const true_false_string tfs_flags_recavail = {
153 "Server can do recursive queries",
154 "Server can't do recursive queries"
157 static const true_false_string tfs_flags_broadcast = {
159 "Not a broadcast packet"
163 #define OPCODE_QUERY 0 /* standard query */
164 #define OPCODE_REGISTRATION 5 /* registration */
165 #define OPCODE_RELEASE 6 /* release name */
166 #define OPCODE_WACK 7 /* wait for acknowledgement */
167 #define OPCODE_REFRESH 8 /* refresh registration */
168 #define OPCODE_REFRESHALT 9 /* refresh registration (alternate opcode) */
169 #define OPCODE_MHREGISTRATION 15 /* multi-homed registration */
171 static const value_string opcode_vals[] = {
172 { OPCODE_QUERY, "Name query" },
173 { OPCODE_REGISTRATION, "Registration" },
174 { OPCODE_RELEASE, "Release" },
175 { OPCODE_WACK, "Wait for acknowledgment" },
176 { OPCODE_REFRESH, "Refresh" },
177 { OPCODE_REFRESHALT, "Refresh (alternate opcode)" },
178 { OPCODE_MHREGISTRATION, "Multi-homed registration" },
183 #define RCODE_NOERROR 0
184 #define RCODE_FMTERROR 1
185 #define RCODE_SERVFAIL 2
186 #define RCODE_NAMEERROR 3
187 #define RCODE_NOTIMPL 4
188 #define RCODE_REFUSED 5
189 #define RCODE_ACTIVE 6
190 #define RCODE_CONFLICT 7
192 static const value_string rcode_vals[] = {
193 { RCODE_NOERROR, "No error" },
194 { RCODE_FMTERROR, "Request was invalidly formatted" },
195 { RCODE_SERVFAIL, "Server failure" },
196 { RCODE_NAMEERROR, "Requested name does not exist" },
197 { RCODE_NOTIMPL, "Request is not implemented" },
198 { RCODE_REFUSED, "Request was refused" },
199 { RCODE_ACTIVE, "Name is owned by another node" },
200 { RCODE_CONFLICT, "Name is in conflict" },
204 /* Values for the "NB_FLAGS" field of RR data. From RFC 1001 and 1002,
205 * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
207 #define NB_FLAGS_ONT (3<<(15-2)) /* bits for node type */
208 #define NB_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
209 #define NB_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
210 #define NB_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
211 #define NB_FLAGS_ONT_H_NODE (3<<(15-2)) /* H-mode node */
213 #define NB_FLAGS_G (1<<(15-0)) /* group name */
215 /* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
216 * RR data. From RFC 1001 and 1002, except for NAME_FLAGS_ONT_H_NODE,
217 * which was discovered by looking at packet traces. */
218 #define NAME_FLAGS_PRM (1<<(15-6)) /* name is permanent node name */
220 #define NAME_FLAGS_ACT (1<<(15-5)) /* name is active */
222 #define NAME_FLAGS_CNF (1<<(15-4)) /* name is in conflict */
224 #define NAME_FLAGS_DRG (1<<(15-3)) /* name is being deregistered */
226 #define NAME_FLAGS_ONT (3<<(15-2)) /* bits for node type */
227 #define NAME_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
228 #define NAME_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
229 #define NAME_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
231 #define NAME_FLAGS_G (1<<(15-0)) /* group name */
234 nbns_type_name (int type)
246 #define NBNAME_BUF_LEN 128
249 get_nbns_name(tvbuff_t *tvb, int offset, int nbns_data_offset,
250 char *name_ret, int *name_type_ret)
254 char nbname[NBNAME_BUF_LEN];
255 char *pname, *pnbname, cname, cnbname;
258 name_len = get_dns_name(tvb, offset, nbns_data_offset, name,
261 /* OK, now undo the first-level encoding. */
263 pnbname = &nbname[0];
265 /* Every two characters of the first level-encoded name
266 * turn into one character in the decoded name. */
269 break; /* no more characters */
271 break; /* scope ID follows */
272 if (cname < 'A' || cname > 'Z') {
275 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
279 cnbname = cname << 4;
283 if (cname == '\0' || cname == '.') {
284 /* No more characters in the name - but we're in
285 * the middle of a pair. Not legal. */
287 "Illegal NetBIOS name (odd number of bytes)");
290 if (cname < 'A' || cname > 'Z') {
293 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
300 /* Do we have room to store the character? */
301 if (pnbname < &nbname[NETBIOS_NAME_LEN]) {
302 /* Yes - store the character. */
306 /* We bump the pointer even if it's past the end of the
307 name, so we keep track of how long the name is. */
311 /* NetBIOS names are supposed to be exactly 16 bytes long. */
312 if (pnbname - nbname != NETBIOS_NAME_LEN) {
314 sprintf(nbname, "Illegal NetBIOS name (%ld bytes long)",
315 (long)(pnbname - nbname));
319 /* This one is; make its name printable. */
320 name_type = process_netbios_name(nbname, name_ret);
321 name_ret += strlen(name_ret);
322 sprintf(name_ret, "<%02x>", name_type);
325 /* We have a scope ID, starting at "pname"; append that to
326 * the decoded host name. */
327 strcpy(name_ret, pname);
329 if (name_type_ret != NULL)
330 *name_type_ret = name_type;
334 if (name_type_ret != NULL)
336 strcpy (name_ret, nbname);
342 get_nbns_name_type_class(tvbuff_t *tvb, int offset, int nbns_data_offset,
343 char *name_ret, int *name_len_ret, int *name_type_ret, int *type_ret,
350 name_len = get_nbns_name(tvb, offset, nbns_data_offset, name_ret,
354 type = tvb_get_ntohs(tvb, offset);
357 class = tvb_get_ntohs(tvb, offset);
361 *name_len_ret = name_len;
367 add_name_and_type(proto_tree *tree, tvbuff_t *tvb, int offset, int len,
368 char *tag, char *name, int name_type)
370 if (name_type != -1) {
371 proto_tree_add_text(tree, tvb, offset, len, "%s: %s (%s)",
372 tag, name, netbios_name_type_descr(name_type));
374 proto_tree_add_text(tree, tvb, offset, len, "%s: %s",
380 dissect_nbns_query(tvbuff_t *tvb, int offset, int nbns_data_offset,
381 column_info *cinfo, proto_tree *nbns_tree)
384 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
396 data_start = data_offset = offset;
398 len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
399 &name_len, &name_type, &type, &class);
402 type_name = nbns_type_name(type);
403 class_name = dns_class_name(class);
406 col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
407 if (nbns_tree != NULL) {
408 tq = proto_tree_add_text(nbns_tree, tvb, offset, len,
409 "%s: type %s, class %s", name, type_name, class_name);
410 q_tree = proto_item_add_subtree(tq, ett_nbns_qd);
412 add_name_and_type(q_tree, tvb, offset, name_len, "Name", name,
416 proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", type_name);
419 proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
423 return data_offset - data_start;
427 nbns_add_nbns_flags(proto_tree *nbns_tree, tvbuff_t *tvb, int offset,
428 gushort flags, int is_wack)
432 proto_tree *field_tree;
435 opcode = (flags & F_OPCODE) >> OPCODE_SHIFT;
436 strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation"));
437 if (flags & F_RESPONSE && !is_wack) {
438 strcat(buf, " response");
440 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
443 tf = proto_tree_add_uint_format(nbns_tree, hf_nbns_flags,
444 tvb, offset, 2, flags, "Flags: 0x%04x (%s)", flags, buf);
445 field_tree = proto_item_add_subtree(tf, ett_nbns_flags);
446 proto_tree_add_item(field_tree, hf_nbns_flags_response,
447 tvb, offset, 2, FALSE);
448 proto_tree_add_item(field_tree, hf_nbns_flags_opcode,
449 tvb, offset, 2, FALSE);
450 if (flags & F_RESPONSE) {
451 proto_tree_add_item(field_tree, hf_nbns_flags_authoritative,
452 tvb, offset, 2, FALSE);
454 proto_tree_add_item(field_tree, hf_nbns_flags_truncated,
455 tvb, offset, 2, FALSE);
456 proto_tree_add_item(field_tree, hf_nbns_flags_recdesired,
457 tvb, offset, 2, FALSE);
458 if (flags & F_RESPONSE) {
459 proto_tree_add_item(field_tree, hf_nbns_flags_recavail,
460 tvb, offset, 2, FALSE);
462 proto_tree_add_item(field_tree, hf_nbns_flags_broadcast,
463 tvb, offset, 2, FALSE);
464 if (flags & F_RESPONSE && !is_wack) {
465 proto_tree_add_item(field_tree, hf_nbns_flags_rcode,
466 tvb, offset, 2, FALSE);
471 nbns_add_nb_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset, gushort flags)
474 proto_tree *field_tree;
476 static const value_string nb_flags_ont_vals[] = {
477 { NB_FLAGS_ONT_B_NODE, "B-node" },
478 { NB_FLAGS_ONT_P_NODE, "P-node" },
479 { NB_FLAGS_ONT_M_NODE, "M-node" },
480 { NB_FLAGS_ONT_H_NODE, "H-node" },
484 strcpy(buf, val_to_str(flags & NB_FLAGS_ONT, nb_flags_ont_vals,
487 if (flags & NB_FLAGS_G)
488 strcat(buf, "group");
490 strcat(buf, "unique");
491 tf = proto_tree_add_text(rr_tree, tvb, offset, 2, "Flags: 0x%x (%s)", flags,
493 field_tree = proto_item_add_subtree(tf, ett_nbns_nb_flags);
494 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
495 decode_boolean_bitfield(flags, NB_FLAGS_G,
499 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
500 decode_enumerated_bitfield(flags, NB_FLAGS_ONT,
501 2*8, nb_flags_ont_vals, "%s"));
505 nbns_add_name_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset,
509 proto_item *field_tree;
511 static const value_string name_flags_ont_vals[] = {
512 { NAME_FLAGS_ONT_B_NODE, "B-node" },
513 { NAME_FLAGS_ONT_P_NODE, "P-node" },
514 { NAME_FLAGS_ONT_M_NODE, "M-node" },
518 strcpy(buf, val_to_str(flags & NAME_FLAGS_ONT, name_flags_ont_vals,
521 if (flags & NAME_FLAGS_G)
522 strcat(buf, "group");
524 strcat(buf, "unique");
525 if (flags & NAME_FLAGS_DRG)
526 strcat(buf, ", being deregistered");
527 if (flags & NAME_FLAGS_CNF)
528 strcat(buf, ", in conflict");
529 if (flags & NAME_FLAGS_ACT)
530 strcat(buf, ", active");
531 if (flags & NAME_FLAGS_PRM)
532 strcat(buf, ", permanent node name");
533 tf = proto_tree_add_text(rr_tree, tvb, offset, 2, "Name flags: 0x%x (%s)",
535 field_tree = proto_item_add_subtree(tf, ett_nbns_name_flags);
536 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
537 decode_boolean_bitfield(flags, NAME_FLAGS_G,
541 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
542 decode_enumerated_bitfield(flags, NAME_FLAGS_ONT,
543 2*8, name_flags_ont_vals, "%s"));
544 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
545 decode_boolean_bitfield(flags, NAME_FLAGS_DRG,
547 "Name is being deregistered",
548 "Name is not being deregistered"));
549 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
550 decode_boolean_bitfield(flags, NAME_FLAGS_CNF,
552 "Name is in conflict",
553 "Name is not in conflict"));
554 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
555 decode_boolean_bitfield(flags, NAME_FLAGS_ACT,
558 "Name is not active"));
559 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
560 decode_boolean_bitfield(flags, NAME_FLAGS_PRM,
562 "Permanent node name",
563 "Not permanent node name"));
567 dissect_nbns_answer(tvbuff_t *tvb, int offset, int nbns_data_offset,
568 column_info *cinfo, proto_tree *nbns_tree, int opcode)
571 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME + 64];
586 char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
588 char nbname[16+4+1]; /* 4 for [<last char>] */
591 data_start = data_offset = offset;
594 len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
595 &name_len, &name_type, &type, &class);
599 type_name = nbns_type_name(type);
600 class_name = dns_class_name(class);
602 ttl = tvb_get_ntohl(tvb, data_offset);
606 data_len = tvb_get_ntohs(tvb, data_offset);
611 case T_NB: /* "NB" record */
613 if (opcode != OPCODE_WACK) {
614 col_append_fstr(cinfo, COL_INFO, " %s %s",
616 ip_to_str(tvb_get_ptr(tvb, data_offset+2, 4)));
619 if (nbns_tree == NULL)
621 trr = proto_tree_add_text(nbns_tree, tvb, offset,
622 (data_offset - data_start) + data_len,
623 "%s: type %s, class %s",
624 name, type_name, class_name);
626 strcat(name, netbios_name_type_descr(name_type));
628 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
629 name_len, type_name, class_name, ttl, data_len);
630 while (data_len > 0) {
631 if (opcode == OPCODE_WACK) {
632 /* WACK response. This doesn't contain the
633 * same type of RR data as other T_NB
636 proto_tree_add_text(rr_tree, tvb, cur_offset,
637 data_len, "(incomplete entry)");
640 flags = tvb_get_ntohs(tvb, cur_offset);
641 nbns_add_nbns_flags(rr_tree, tvb, cur_offset,
647 proto_tree_add_text(rr_tree, tvb, cur_offset,
648 data_len, "(incomplete entry)");
651 flags = tvb_get_ntohs(tvb, cur_offset);
652 nbns_add_nb_flags(rr_tree, tvb, cur_offset,
658 proto_tree_add_text(rr_tree, tvb, cur_offset,
659 data_len, "(incomplete entry)");
662 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
664 ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
671 case T_NBSTAT: /* "NBSTAT" record */
673 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
674 if (nbns_tree == NULL)
676 trr = proto_tree_add_text(nbns_tree, tvb, offset,
677 (data_offset - data_start) + data_len,
678 "%s: type %s, class %s",
679 name, type_name, class_name);
680 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
681 name_len, type_name, class_name, ttl, data_len);
683 proto_tree_add_text(rr_tree, tvb, cur_offset,
684 data_len, "(incomplete entry)");
687 num_names = tvb_get_guint8(tvb, cur_offset);
688 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
689 "Number of names: %u", num_names);
692 while (num_names != 0) {
693 if (data_len < NETBIOS_NAME_LEN) {
694 proto_tree_add_text(rr_tree, tvb, cur_offset,
695 data_len, "(incomplete entry)");
698 tvb_memcpy(tvb, (guint8 *)nbname, cur_offset,
700 name_type = process_netbios_name(nbname,
702 proto_tree_add_text(rr_tree, tvb, cur_offset,
703 NETBIOS_NAME_LEN, "Name: %s<%02x> (%s)",
705 netbios_name_type_descr(name_type));
706 cur_offset += NETBIOS_NAME_LEN;
707 data_len -= NETBIOS_NAME_LEN;
710 proto_tree_add_text(rr_tree, tvb, cur_offset,
711 data_len, "(incomplete entry)");
714 name_flags = tvb_get_ntohs(tvb, cur_offset);
715 nbns_add_name_flags(rr_tree, tvb, cur_offset,
724 proto_tree_add_text(rr_tree, tvb, cur_offset,
725 data_len, "(incomplete entry)");
728 proto_tree_add_text(rr_tree, tvb, cur_offset, 6,
730 ether_to_str(tvb_get_ptr(tvb, cur_offset, 6)));
735 proto_tree_add_text(rr_tree, tvb, cur_offset,
736 data_len, "(incomplete entry)");
739 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
740 "Jumpers: 0x%x", tvb_get_guint8(tvb, cur_offset));
745 proto_tree_add_text(rr_tree, tvb, cur_offset,
746 data_len, "(incomplete entry)");
749 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
750 "Test result: 0x%x", tvb_get_guint8(tvb, cur_offset));
755 proto_tree_add_text(rr_tree, tvb, cur_offset,
756 data_len, "(incomplete entry)");
759 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
760 "Version number: 0x%x", tvb_get_ntohs(tvb, cur_offset));
765 proto_tree_add_text(rr_tree, tvb, cur_offset,
766 data_len, "(incomplete entry)");
769 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
770 "Period of statistics: 0x%x",
771 tvb_get_ntohs(tvb, cur_offset));
776 proto_tree_add_text(rr_tree, tvb, cur_offset,
777 data_len, "(incomplete entry)");
780 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
781 "Number of CRCs: %u", tvb_get_ntohs(tvb, cur_offset));
786 proto_tree_add_text(rr_tree, tvb, cur_offset,
787 data_len, "(incomplete entry)");
790 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
791 "Number of alignment errors: %u",
792 tvb_get_ntohs(tvb, cur_offset));
797 proto_tree_add_text(rr_tree, tvb, cur_offset,
798 data_len, "(incomplete entry)");
801 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
802 "Number of collisions: %u", tvb_get_ntohs(tvb, cur_offset));
807 proto_tree_add_text(rr_tree, tvb, cur_offset,
808 data_len, "(incomplete entry)");
811 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
812 "Number of send aborts: %u", tvb_get_ntohs(tvb, cur_offset));
817 proto_tree_add_text(rr_tree, tvb, cur_offset,
818 data_len, "(incomplete entry)");
821 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
822 "Number of good sends: %u", tvb_get_ntohl(tvb, cur_offset));
827 proto_tree_add_text(rr_tree, tvb, cur_offset,
828 data_len, "(incomplete entry)");
831 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
832 "Number of good receives: %u",
833 tvb_get_ntohl(tvb, cur_offset));
838 proto_tree_add_text(rr_tree, tvb, cur_offset,
839 data_len, "(incomplete entry)");
842 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
843 "Number of retransmits: %u", tvb_get_ntohs(tvb, cur_offset));
848 proto_tree_add_text(rr_tree, tvb, cur_offset,
849 data_len, "(incomplete entry)");
852 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
853 "Number of no resource conditions: %u",
854 tvb_get_ntohs(tvb, cur_offset));
859 proto_tree_add_text(rr_tree, tvb, cur_offset,
860 data_len, "(incomplete entry)");
863 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
864 "Number of command blocks: %u",
865 tvb_get_ntohs(tvb, cur_offset));
870 proto_tree_add_text(rr_tree, tvb, cur_offset,
871 data_len, "(incomplete entry)");
874 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
875 "Number of pending sessions: %u",
876 tvb_get_ntohs(tvb, cur_offset));
881 proto_tree_add_text(rr_tree, tvb, cur_offset,
882 data_len, "(incomplete entry)");
885 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
886 "Max number of pending sessions: %u",
887 tvb_get_ntohs(tvb, cur_offset));
892 proto_tree_add_text(rr_tree, tvb, cur_offset,
893 data_len, "(incomplete entry)");
896 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
897 "Max total sessions possible: %u",
898 tvb_get_ntohs(tvb, cur_offset));
903 proto_tree_add_text(rr_tree, tvb, cur_offset,
904 data_len, "(incomplete entry)");
907 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
908 "Session data packet size: %u",
909 tvb_get_ntohs(tvb, cur_offset));
917 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
918 if (nbns_tree == NULL)
920 trr = proto_tree_add_text(nbns_tree, tvb, offset,
921 (data_offset - data_start) + data_len,
922 "%s: type %s, class %s",
923 name, type_name, class_name);
924 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
925 name_len, type_name, class_name, ttl, data_len);
926 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
927 cur_offset += data_len;
931 return cur_offset - data_start;
935 dissect_query_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
936 int count, column_info *cinfo, proto_tree *nbns_tree)
938 int start_off, add_off;
939 proto_tree *qatree = NULL;
940 proto_item *ti = NULL;
943 if (nbns_tree != NULL) {
944 ti = proto_tree_add_text(nbns_tree, tvb, start_off, -1, "Queries");
945 qatree = proto_item_add_subtree(ti, ett_nbns_qry);
947 while (count-- > 0) {
948 add_off = dissect_nbns_query(tvb, cur_off, nbns_data_offset,
953 proto_item_set_len(ti, cur_off - start_off);
955 return cur_off - start_off;
961 dissect_answer_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
962 int count, column_info *cinfo, proto_tree *nbns_tree, int opcode,
965 int start_off, add_off;
966 proto_tree *qatree = NULL;
967 proto_item *ti = NULL;
970 if (nbns_tree != NULL) {
971 ti = proto_tree_add_text(nbns_tree, tvb, start_off, -1, name);
972 qatree = proto_item_add_subtree(ti, ett_nbns_ans);
974 while (count-- > 0) {
975 add_off = dissect_nbns_answer(tvb, cur_off, nbns_data_offset,
976 cinfo, qatree, opcode);
980 proto_item_set_len(ti, cur_off - start_off);
981 return cur_off - start_off;
985 dissect_nbns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
988 int nbns_data_offset;
990 proto_tree *nbns_tree = NULL;
992 guint16 id, flags, opcode, rcode, quest, ans, auth, add;
995 nbns_data_offset = offset;
997 if (check_col(pinfo->cinfo, COL_PROTOCOL))
998 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBNS");
999 if (check_col(pinfo->cinfo, COL_INFO))
1000 col_clear(pinfo->cinfo, COL_INFO);
1002 /* To do: check for runts, errs, etc. */
1003 id = tvb_get_ntohs(tvb, offset + NBNS_ID);
1004 flags = tvb_get_ntohs(tvb, offset + NBNS_FLAGS);
1005 opcode = (flags & F_OPCODE) >> OPCODE_SHIFT;
1006 rcode = (flags & F_RCODE);
1008 if (check_col(pinfo->cinfo, COL_INFO)) {
1009 col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s",
1010 val_to_str(opcode, opcode_vals, "Unknown operation (%u)"),
1011 (flags & F_RESPONSE) ? " response" : "");
1012 cinfo = pinfo->cinfo;
1014 /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query
1015 and answer dissectors, as a way of saying that they
1016 shouldn't add stuff to the COL_INFO column (a call to
1017 "check_col(cinfo, COL_INFO)" is more expensive than
1018 a check that a pointer isn't NULL). */
1023 ti = proto_tree_add_item(tree, proto_nbns, tvb, offset, -1,
1025 nbns_tree = proto_item_add_subtree(ti, ett_nbns);
1027 proto_tree_add_uint(nbns_tree, hf_nbns_transaction_id, tvb,
1028 offset + NBNS_ID, 2, id);
1030 nbns_add_nbns_flags(nbns_tree, tvb, offset + NBNS_FLAGS,
1033 quest = tvb_get_ntohs(tvb, offset + NBNS_QUEST);
1035 proto_tree_add_uint(nbns_tree, hf_nbns_count_questions, tvb,
1036 offset + NBNS_QUEST, 2, quest);
1038 ans = tvb_get_ntohs(tvb, offset + NBNS_ANS);
1040 proto_tree_add_uint(nbns_tree, hf_nbns_count_answers, tvb,
1041 offset + NBNS_ANS, 2, ans);
1043 auth = tvb_get_ntohs(tvb, offset + NBNS_AUTH);
1045 proto_tree_add_uint(nbns_tree, hf_nbns_count_auth_rr, tvb,
1046 offset + NBNS_AUTH, 2, auth);
1048 add = tvb_get_ntohs(tvb, offset + NBNS_ADD);
1050 proto_tree_add_uint(nbns_tree, hf_nbns_count_add_rr, tvb,
1051 offset + NBNS_ADD, 2, add);
1054 cur_off = offset + NBNS_HDRLEN;
1057 /* If this is a response, don't add information about the
1058 queries to the summary, just add information about the
1060 cur_off += dissect_query_records(tvb, cur_off,
1061 nbns_data_offset, quest,
1062 (!(flags & F_RESPONSE) ? cinfo : NULL), nbns_tree);
1066 /* If this is a request, don't add information about the
1067 answers to the summary, just add information about the
1069 cur_off += dissect_answer_records(tvb, cur_off,
1070 nbns_data_offset, ans,
1071 ((flags & F_RESPONSE) ? cinfo : NULL), nbns_tree,
1076 /* Don't add information about the authoritative name
1077 servers, or the additional records, to the summary. */
1079 cur_off += dissect_answer_records(tvb, cur_off,
1081 auth, NULL, nbns_tree, opcode,
1082 "Authoritative nameservers");
1085 cur_off += dissect_answer_records(tvb, cur_off,
1087 add, NULL, nbns_tree, opcode,
1088 "Additional records");
1092 /* NetBIOS datagram packet, from RFC 1002, page 32 */
1093 struct nbdgm_header {
1104 /* For packets with data */
1108 /* For error packets */
1113 * NBDS message types.
1115 #define NBDS_DIRECT_UNIQUE 0x10
1116 #define NBDS_DIRECT_GROUP 0x11
1117 #define NBDS_BROADCAST 0x12
1118 #define NBDS_ERROR 0x13
1119 #define NBDS_QUERY_REQUEST 0x14
1120 #define NBDS_POS_QUERY_RESPONSE 0x15
1121 #define NBDS_NEG_QUERY_RESPONSE 0x16
1123 static const value_string nbds_msgtype_vals[] = {
1124 { NBDS_DIRECT_UNIQUE, "Direct_unique datagram" },
1125 { NBDS_DIRECT_GROUP, "Direct_group datagram" },
1126 { NBDS_BROADCAST, "Broadcast datagram" },
1127 { NBDS_ERROR, "Datagram error" },
1128 { NBDS_QUERY_REQUEST, "Datagram query request" },
1129 { NBDS_POS_QUERY_RESPONSE, "Datagram positive query response" },
1130 { NBDS_NEG_QUERY_RESPONSE, "Datagram negative query response" },
1134 static const true_false_string yesno = {
1139 static const value_string node_type_vals[] = {
1148 dissect_nbdgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1151 proto_tree *nbdgm_tree = NULL;
1152 proto_item *ti = NULL;
1153 struct nbdgm_header header;
1158 static const value_string error_codes[] = {
1159 { 0x82, "Destination name not present" },
1160 { 0x83, "Invalid source name format" },
1161 { 0x84, "Invalid destination name format" },
1165 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1169 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1170 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBDS");
1171 if (check_col(pinfo->cinfo, COL_INFO))
1172 col_clear(pinfo->cinfo, COL_INFO);
1174 header.msg_type = tvb_get_guint8(tvb, offset);
1176 flags = tvb_get_guint8(tvb, offset+1);
1177 header.flags.more = flags & 1;
1178 header.flags.first = (flags & 2) >> 1;
1179 header.flags.node_type = (flags & 12) >> 2;
1181 header.dgm_id = tvb_get_ntohs(tvb, offset+2);
1182 tvb_memcpy(tvb, (guint8 *)&header.src_ip, offset+4, 4);
1183 header.src_port = tvb_get_ntohs(tvb, offset+8);
1185 switch (header.msg_type) {
1187 case NBDS_DIRECT_UNIQUE:
1188 case NBDS_DIRECT_GROUP:
1189 case NBDS_BROADCAST:
1190 header.dgm_length = tvb_get_ntohs(tvb, offset+10);
1191 header.pkt_offset = tvb_get_ntohs(tvb, offset+12);
1195 header.error_code = tvb_get_ntohs(tvb, offset+10);
1199 message_index = header.msg_type - 0x0f;
1200 if (message_index < 1 || message_index > 8) {
1204 if (check_col(pinfo->cinfo, COL_INFO)) {
1205 col_add_str(pinfo->cinfo, COL_INFO,
1206 val_to_str(header.msg_type, nbds_msgtype_vals,
1207 "Unknown message type (0x%02X)"));
1211 ti = proto_tree_add_item(tree, proto_nbdgm, tvb, offset, -1,
1213 nbdgm_tree = proto_item_add_subtree(ti, ett_nbdgm);
1215 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_type, tvb,
1218 proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_fragment, tvb,
1221 proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_first, tvb,
1223 header.flags.first);
1224 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_node_type, tvb,
1226 header.flags.node_type);
1228 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_datagram_id, tvb,
1229 offset+2, 2, header.dgm_id);
1230 proto_tree_add_ipv4(nbdgm_tree, hf_nbdgm_src_ip, tvb,
1231 offset+4, 4, header.src_ip);
1232 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_src_port, tvb,
1233 offset+8, 2, header.src_port);
1239 switch (header.msg_type) {
1241 case NBDS_DIRECT_UNIQUE:
1242 case NBDS_DIRECT_GROUP:
1243 case NBDS_BROADCAST:
1245 proto_tree_add_text(nbdgm_tree, tvb, offset, 2,
1246 "Datagram length: %d bytes", header.dgm_length);
1247 proto_tree_add_text(nbdgm_tree, tvb, offset+2, 2,
1248 "Packet offset: %d bytes", header.pkt_offset);
1254 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1257 add_name_and_type(nbdgm_tree, tvb, offset, len,
1258 "Source name", name, name_type);
1262 /* Destination name */
1263 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1266 add_name_and_type(nbdgm_tree, tvb, offset, len,
1267 "Destination name", name, name_type);
1272 * Here we can pass the packet off to the next protocol.
1273 * Set the length of our top-level tree item to include
1276 * XXX - take the datagram length into account?
1278 proto_item_set_len(ti, offset);
1279 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1280 dissect_netbios_payload(next_tvb, pinfo, tree);
1285 proto_tree_add_text(nbdgm_tree, tvb, offset, 1, "Error code: %s",
1286 val_to_str(header.error_code, error_codes, "Unknown (0x%x)"));
1289 proto_item_set_len(ti, offset);
1292 case NBDS_QUERY_REQUEST:
1293 case NBDS_POS_QUERY_RESPONSE:
1294 case NBDS_NEG_QUERY_RESPONSE:
1295 /* Destination name */
1296 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1299 add_name_and_type(nbdgm_tree, tvb, offset, len,
1300 "Destination name", name, name_type);
1303 proto_item_set_len(ti, offset);
1309 * NetBIOS Session Service message types.
1311 #define SESSION_MESSAGE 0x00
1312 #define SESSION_REQUEST 0x81
1313 #define POSITIVE_SESSION_RESPONSE 0x82
1314 #define NEGATIVE_SESSION_RESPONSE 0x83
1315 #define RETARGET_SESSION_RESPONSE 0x84
1316 #define SESSION_KEEP_ALIVE 0x85
1318 static const value_string message_types[] = {
1319 { SESSION_MESSAGE, "Session message" },
1320 { SESSION_REQUEST, "Session request" },
1321 { POSITIVE_SESSION_RESPONSE, "Positive session response" },
1322 { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
1323 { RETARGET_SESSION_RESPONSE, "Retarget session response" },
1324 { SESSION_KEEP_ALIVE, "Session keep-alive" },
1329 * NetBIOS Session Service flags.
1331 #define NBSS_FLAGS_E 0x1
1333 static const value_string error_codes[] = {
1334 { 0x80, "Not listening on called name" },
1335 { 0x81, "Not listening for called name" },
1336 { 0x82, "Called name not present" },
1337 { 0x83, "Called name present, but insufficient resources" },
1338 { 0x8F, "Unspecified error" },
1343 * Dissect a single NBSS packet (there may be more than one in a given
1346 * [ Hmmm, in my experience, I have never seen more than one NBSS in a
1347 * single segment, since they mostly contain SMBs which are essentially
1348 * a request response type protocol (RJS). ]
1350 * [ However, under heavy load with many requests multiplexed on one
1351 * session it is not unusual to see multiple requests in one TCP
1352 * segment. Unfortunately, in this case a single session message is
1353 * frequently split over multiple segments, which frustrates decoding
1357 dissect_nbss_packet(tvbuff_t *tvb, int offset, packet_info *pinfo,
1358 proto_tree *tree, int is_cifs)
1360 proto_tree *nbss_tree = NULL;
1361 proto_item *ti = NULL;
1362 proto_tree *field_tree;
1366 volatile int length;
1367 int length_remaining;
1369 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1373 const char *saved_proto;
1375 /* Desegmentation */
1376 length_remaining = tvb_length_remaining(tvb, offset);
1379 * Can we do reassembly?
1381 if (nbss_desegment && pinfo->can_desegment) {
1383 * Yes - is the NBSS header split across segment boundaries?
1385 if (length_remaining < 4) {
1387 * Yes. Tell our caller how many more bytes
1390 return -(4 - length_remaining);
1395 * Get the length of the NBSS message.
1399 length = tvb_get_ntoh24(tvb, offset + 1);
1401 flags = tvb_get_guint8(tvb, offset + 1);
1402 length = tvb_get_ntohs(tvb, offset + 2);
1403 if (flags & NBSS_FLAGS_E)
1408 * Can we do reassembly?
1410 if (nbss_desegment && pinfo->can_desegment) {
1412 * Yes - is the NBSS message split across segment boundaries?
1414 if (length_remaining < length + 4) {
1416 * Yes. Tell our caller how many more bytes
1419 return -((length + 4) - length_remaining);
1423 msg_type = tvb_get_guint8(tvb, offset);
1426 ti = proto_tree_add_item(tree, proto_nbss, tvb, offset, length + 4, FALSE);
1427 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1429 proto_tree_add_uint_format(nbss_tree, hf_nbss_type, tvb,
1433 val_to_str(msg_type, message_types,
1441 proto_tree_add_text(nbss_tree, tvb, offset, 3, "Length: %u", length);
1446 tf = proto_tree_add_uint(nbss_tree, hf_nbss_flags, tvb, offset, 1, flags);
1447 field_tree = proto_item_add_subtree(tf, ett_nbss_flags);
1448 proto_tree_add_text(field_tree, tvb, offset, 1, "%s",
1449 decode_boolean_bitfield(flags, NBSS_FLAGS_E,
1450 8, "Add 65536 to length", "Add 0 to length"));
1455 proto_tree_add_text(nbss_tree, tvb, offset, 2, "Length: %u", length);
1463 case SESSION_REQUEST:
1464 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1466 add_name_and_type(nbss_tree, tvb, offset, len,
1467 "Called name", name, name_type);
1470 if (check_col(pinfo->cinfo, COL_INFO))
1471 col_append_fstr(pinfo->cinfo, COL_INFO, ", to %s ", name);
1473 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1476 add_name_and_type(nbss_tree, tvb, offset, len,
1477 "Calling name", name, name_type);
1479 if (check_col(pinfo->cinfo, COL_INFO))
1480 col_append_fstr(pinfo->cinfo, COL_INFO, "from %s", name);
1484 case NEGATIVE_SESSION_RESPONSE:
1486 proto_tree_add_text(nbss_tree, tvb, offset, 1,
1488 val_to_str(tvb_get_guint8(tvb, offset),
1489 error_codes, "Unknown (%x)"));
1491 if (check_col(pinfo->cinfo, COL_INFO))
1492 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1493 val_to_str(tvb_get_guint8(tvb, offset),
1494 error_codes, "Unknown (%x)"));
1498 case RETARGET_SESSION_RESPONSE:
1500 proto_tree_add_text(nbss_tree, tvb, offset, 4,
1501 "Retarget IP address: %s",
1502 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1507 proto_tree_add_text(nbss_tree, tvb, offset, 2,
1508 "Retarget port: %u",
1509 tvb_get_ntohs(tvb, offset));
1513 case SESSION_MESSAGE:
1515 * Here we can pass the message off to the next protocol.
1516 * Set the length of our top-level tree item to include
1519 proto_item_set_len(ti, offset);
1520 len = tvb_length_remaining(tvb, offset);
1521 reported_len = tvb_reported_length_remaining(tvb, offset);
1524 if (reported_len > length)
1525 reported_len = length;
1527 next_tvb = tvb_new_subset(tvb, offset, len, reported_len);
1530 * Catch the ReportedBoundsError exception; if this
1531 * particular message happens to get a ReportedBoundsError
1532 * exception, that doesn't mean that we should stop
1533 * dissecting NetBIOS messages within this frame or chunk
1534 * of reassembled data.
1536 * If it gets a BoundsError, we can stop, as there's nothing
1537 * more to see, so we just re-throw it.
1539 saved_proto = pinfo->current_proto;
1541 dissect_netbios_payload(next_tvb, pinfo, tree);
1543 CATCH(BoundsError) {
1546 CATCH(ReportedBoundsError) {
1547 show_reported_bounds_error(tvb, pinfo, tree);
1548 pinfo->current_proto = saved_proto;
1558 dissect_nbss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1560 struct tcpinfo *tcpinfo = pinfo->private_data;
1568 proto_tree *nbss_tree;
1571 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1572 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBSS");
1573 if (check_col(pinfo->cinfo, COL_INFO))
1574 col_clear(pinfo->cinfo, COL_INFO);
1576 max_data = tvb_length(tvb);
1578 msg_type = tvb_get_guint8(tvb, offset);
1580 if (pinfo->match_port == TCP_PORT_CIFS) {
1582 * Windows 2000 CIFS clients can dispense completely
1583 * with the NETBIOS encapsulation and directly use CIFS
1584 * over TCP. As would be expected, the framing is
1585 * identical, except that the length is 24 bits instead
1586 * of 17. The only message types used are
1587 * SESSION_MESSAGE and SESSION_KEEP_ALIVE.
1595 * This might be a continuation of an earlier message.
1596 * (Yes, that might be true even if we're doing TCP reassembly,
1597 * as the first TCP segment in the capture might start in the
1598 * middle of an NBNS message.)
1602 * If this isn't reassembled data, check to see whether it
1603 * looks like a continuation of a message.
1604 * (If it is reassembled data, it shouldn't be a continuation,
1605 * as reassembly should've gathered the continuations together
1608 if (!tcpinfo->is_reassembled) {
1611 * Not enough data for an NBSS header; assume
1612 * it's a continuation of a message.
1614 * XXX - if there's not enough data, we should
1615 * attempt to reassemble the data, if the first byte
1616 * is a valid message type.
1622 * We have enough data for an NBSS header.
1623 * Get the flags and length of the message,
1624 * and see if they're sane.
1628 length = tvb_get_ntoh24(tvb, offset + 1);
1630 flags = tvb_get_guint8(tvb, offset + 1);
1631 length = tvb_get_ntohs(tvb, offset + 2);
1632 if (flags & NBSS_FLAGS_E)
1635 if ((flags & (~NBSS_FLAGS_E)) != 0) {
1637 * A bogus flag was set; assume it's a continuation.
1644 case SESSION_MESSAGE:
1646 * This is variable-length.
1647 * All we know is that it shouldn't be zero.
1648 * (XXX - can we get zero-length messages?
1649 * Not with SMB, but perhaps other NetBIOS-based
1650 * protocols have them.)
1656 case SESSION_REQUEST:
1658 * This is variable-length.
1659 * The names are DNS-encoded 32-byte values;
1660 * we need at least 2 bytes (one for each name;
1661 * actually, we should have more for the first
1662 * name, as there's no name preceding it so
1663 * there should be no compression), and we
1664 * shouldn't have more than 128 bytes (actually,
1665 * we shouldn't have that many).
1667 * XXX - actually, MacOS X 10.1 (yes, that's
1668 * redundant, but that's what Apple calls it,
1669 * not MacOS X.1) puts names longer than 16
1670 * characters into session request messages,
1671 * so we can have more than 32 bytes of
1672 * name value, so we can have more than 128
1675 if (length < 2 || length > 256)
1679 case POSITIVE_SESSION_RESPONSE:
1681 * This has no data, so the length must be zero.
1687 case NEGATIVE_SESSION_RESPONSE:
1689 * This has 1 byte of data.
1695 case RETARGET_SESSION_RESPONSE:
1697 * This has 6 bytes of data.
1703 case SESSION_KEEP_ALIVE:
1705 * This has no data, so the length must be zero.
1713 * Unknown message type; assume it's a continuation.
1719 if (check_col(pinfo->cinfo, COL_INFO)) {
1720 col_add_fstr(pinfo->cinfo, COL_INFO,
1721 val_to_str(msg_type, message_types, "Unknown (%02x)"));
1724 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1725 len = dissect_nbss_packet(tvb, offset, pinfo, tree, is_cifs);
1728 * We need more data to dissect this, and
1729 * desegmentation is enabled. "-len" is the
1730 * number of additional bytes of data we need.
1732 * Tell the TCP dissector where the data for this
1733 * message starts in the data it handed us, and
1734 * how many more bytes we need, and return.
1736 pinfo->desegment_offset = offset;
1737 pinfo->desegment_len = -len;
1747 * It looks like a continuation.
1749 if (check_col(pinfo->cinfo, COL_INFO))
1750 col_add_fstr(pinfo->cinfo, COL_INFO, "NBSS Continuation Message");
1753 ti = proto_tree_add_item(tree, proto_nbss, tvb, 0, -1, FALSE);
1754 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1755 proto_tree_add_text(nbss_tree, tvb, 0, -1, "Continuation data");
1760 proto_register_nbt(void)
1763 static hf_register_info hf_nbns[] = {
1765 { "Flags", "nbns.flags",
1766 FT_UINT16, BASE_HEX, NULL, 0x0,
1768 { &hf_nbns_flags_response,
1769 { "Response", "nbns.flags.response",
1770 FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
1771 "Is the message a response?", HFILL }},
1772 { &hf_nbns_flags_opcode,
1773 { "Opcode", "nbns.flags.opcode",
1774 FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
1775 "Operation code", HFILL }},
1776 { &hf_nbns_flags_authoritative,
1777 { "Authoritative", "nbns.flags.authoritative",
1778 FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
1779 "Is the server is an authority for the domain?", HFILL }},
1780 { &hf_nbns_flags_truncated,
1781 { "Truncated", "nbns.flags.truncated",
1782 FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
1783 "Is the message truncated?", HFILL }},
1784 { &hf_nbns_flags_recdesired,
1785 { "Recursion desired", "nbns.flags.recdesired",
1786 FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
1787 "Do query recursively?", HFILL }},
1788 { &hf_nbns_flags_recavail,
1789 { "Recursion available", "nbns.flags.recavail",
1790 FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
1791 "Can the server do recursive queries?", HFILL }},
1792 { &hf_nbns_flags_broadcast,
1793 { "Broadcast", "nbns.flags.broadcast",
1794 FT_BOOLEAN, 16, TFS(&tfs_flags_broadcast), F_BROADCAST,
1795 "Is this a broadcast packet?", HFILL }},
1796 { &hf_nbns_flags_rcode,
1797 { "Reply code", "nbns.flags.rcode",
1798 FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
1799 "Reply code", HFILL }},
1800 { &hf_nbns_transaction_id,
1801 { "Transaction ID", "nbns.id",
1802 FT_UINT16, BASE_HEX, NULL, 0x0,
1803 "Identification of transaction", HFILL }},
1804 { &hf_nbns_count_questions,
1805 { "Questions", "nbns.count.queries",
1806 FT_UINT16, BASE_DEC, NULL, 0x0,
1807 "Number of queries in packet", HFILL }},
1808 { &hf_nbns_count_answers,
1809 { "Answer RRs", "nbns.count.answers",
1810 FT_UINT16, BASE_DEC, NULL, 0x0,
1811 "Number of answers in packet", HFILL }},
1812 { &hf_nbns_count_auth_rr,
1813 { "Authority RRs", "nbns.count.auth_rr",
1814 FT_UINT16, BASE_DEC, NULL, 0x0,
1815 "Number of authoritative records in packet", HFILL }},
1816 { &hf_nbns_count_add_rr,
1817 { "Additional RRs", "nbns.count.add_rr",
1818 FT_UINT16, BASE_DEC, NULL, 0x0,
1819 "Number of additional records in packet", HFILL }}
1822 static hf_register_info hf_nbdgm[] = {
1824 { "Message Type", "nbdgm.type",
1825 FT_UINT8, BASE_DEC, VALS(nbds_msgtype_vals), 0x0,
1826 "NBDGM message type", HFILL }},
1827 { &hf_nbdgm_fragment,
1828 { "More fragments follow", "nbdgm.next",
1829 FT_BOOLEAN, BASE_NONE, TFS(&yesno), 0x0,
1830 "TRUE if more fragments follow", HFILL }},
1832 { "This is first fragment", "nbdgm.first",
1833 FT_BOOLEAN, BASE_NONE, TFS(&yesno), 0x0,
1834 "TRUE if first fragment", HFILL }},
1835 { &hf_nbdgm_node_type,
1836 { "Node Type", "nbdgm.node_type",
1837 FT_UINT8, BASE_DEC, VALS(node_type_vals), 0x0,
1838 "Node type", HFILL }},
1839 { &hf_nbdgm_datagram_id,
1840 { "Datagram ID", "nbdgm.dgram_id",
1841 FT_UINT16, BASE_HEX, NULL, 0x0,
1842 "Datagram identifier", HFILL }},
1844 { "Source IP", "nbdgm.src.ip",
1845 FT_IPv4, BASE_NONE, NULL, 0x0,
1846 "Source IPv4 address", HFILL }},
1847 { &hf_nbdgm_src_port,
1848 { "Source Port", "nbdgm.src.port",
1849 FT_UINT16, BASE_DEC, NULL, 0x0,
1850 "Source port", HFILL }}
1853 static hf_register_info hf_nbss[] = {
1855 { "Message Type", "nbss.type",
1856 FT_UINT8, BASE_DEC, NULL, 0x0,
1857 "NBSS message type", HFILL }},
1859 { "Flags", "nbss.flags",
1860 FT_UINT8, BASE_HEX, NULL, 0x0,
1861 "NBSS message flags", HFILL }}
1863 static gint *ett[] = {
1868 &ett_nbns_name_flags,
1876 module_t *nbss_module;
1878 proto_nbns = proto_register_protocol("NetBIOS Name Service", "NBNS", "nbns");
1879 proto_register_field_array(proto_nbns, hf_nbns, array_length(hf_nbns));
1881 proto_nbdgm = proto_register_protocol("NetBIOS Datagram Service",
1883 proto_register_field_array(proto_nbdgm, hf_nbdgm, array_length(hf_nbdgm));
1885 proto_nbss = proto_register_protocol("NetBIOS Session Service",
1887 proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));
1889 proto_register_subtree_array(ett, array_length(ett));
1891 nbss_module = prefs_register_protocol(proto_nbss, NULL);
1892 prefs_register_bool_preference(nbss_module, "desegment_nbss_commands",
1893 "Desegment all NBSS packets spanning multiple TCP segments",
1894 "Whether NBSS dissector should desegment all packets spanning multiple TCP segments",
1899 proto_reg_handoff_nbt(void)
1901 dissector_handle_t nbns_handle, nbdgm_handle, nbss_handle;
1903 nbns_handle = create_dissector_handle(dissect_nbns, proto_nbns);
1904 dissector_add("udp.port", UDP_PORT_NBNS, nbns_handle);
1905 nbdgm_handle = create_dissector_handle(dissect_nbdgm, proto_nbdgm);
1906 dissector_add("udp.port", UDP_PORT_NBDGM, nbdgm_handle);
1907 nbss_handle = create_dissector_handle(dissect_nbss, proto_nbss);
1908 dissector_add("tcp.port", TCP_PORT_NBSS, nbss_handle);
1909 dissector_add("tcp.port", TCP_PORT_CIFS, nbss_handle);