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>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
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 <epan/emem.h>
37 #include "packet-dns.h"
38 #include "packet-netbios.h"
39 #include "packet-tcp.h"
40 #include "packet-frame.h"
41 #include <epan/prefs.h>
42 #include <epan/strutil.h>
44 static int proto_nbns = -1;
45 static int hf_nbns_flags = -1;
46 static int hf_nbns_flags_response = -1;
47 static int hf_nbns_flags_opcode = -1;
48 static int hf_nbns_flags_authoritative = -1;
49 static int hf_nbns_flags_truncated = -1;
50 static int hf_nbns_flags_recdesired = -1;
51 static int hf_nbns_flags_recavail = -1;
52 static int hf_nbns_flags_broadcast = -1;
53 static int hf_nbns_flags_rcode = -1;
54 static int hf_nbns_transaction_id = -1;
55 static int hf_nbns_count_questions = -1;
56 static int hf_nbns_count_answers = -1;
57 static int hf_nbns_count_auth_rr = -1;
58 static int hf_nbns_count_add_rr = -1;
60 static gint ett_nbns = -1;
61 static gint ett_nbns_qd = -1;
62 static gint ett_nbns_flags = -1;
63 static gint ett_nbns_nb_flags = -1;
64 static gint ett_nbns_name_flags = -1;
65 static gint ett_nbns_rr = -1;
66 static gint ett_nbns_qry = -1;
67 static gint ett_nbns_ans = -1;
69 static int proto_nbdgm = -1;
70 static int hf_nbdgm_type = -1;
71 static int hf_nbdgm_fragment = -1;
72 static int hf_nbdgm_first = -1;
73 static int hf_nbdgm_node_type = -1;
74 static int hf_nbdgm_datagram_id = -1;
75 static int hf_nbdgm_src_ip = -1;
76 static int hf_nbdgm_src_port = -1;
78 static gint ett_nbdgm = -1;
80 static int proto_nbss = -1;
81 static int hf_nbss_type = -1;
82 static int hf_nbss_flags = -1;
84 static gint ett_nbss = -1;
85 static gint ett_nbss_flags = -1;
87 /* desegmentation of NBSS over TCP */
88 static gboolean nbss_desegment = TRUE;
90 /* See RFC 1001 and 1002 for information on the first three, and see
92 http://www.cifs.com/specs/draft-leach-cifs-v1-spec-01.txt
94 Appendix B, and various messages on the CIFS mailing list such as
96 http://discuss.microsoft.com/SCRIPTS/WA-MSD.EXE?A2=ind9811A&L=cifs&P=R386
98 for information on the fourth. */
99 #define UDP_PORT_NBNS 137
100 #define UDP_PORT_NBDGM 138
101 #define TCP_PORT_NBSS 139
102 #define TCP_PORT_CIFS 445
104 /* Packet structure taken from RFC 1002. See also RFC 1001.
105 * Opcode, flags, and rcode treated as "flags", similarly to DNS,
106 * to make it easier to lift the dissection code from "packet-dns.c". */
108 /* Offsets of fields in the NBNS header. */
116 /* Length of NBNS header. */
117 #define NBNS_HDRLEN 12
120 #define T_NB 32 /* NetBIOS name service RR */
121 #define T_NBSTAT 33 /* NetBIOS node status RR */
123 /* Bit fields in the flags */
124 #define F_RESPONSE (1<<15) /* packet is response */
125 #define F_OPCODE (0xF<<11) /* query opcode */
126 #define OPCODE_SHIFT 11
127 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
128 #define F_TRUNCATED (1<<9) /* response is truncated */
129 #define F_RECDESIRED (1<<8) /* recursion desired */
130 #define F_RECAVAIL (1<<7) /* recursion available */
131 #define F_BROADCAST (1<<4) /* broadcast/multicast packet */
132 #define F_RCODE (0xF<<0) /* reply code */
134 static const true_false_string tfs_flags_response = {
135 "Message is a response",
139 static const true_false_string tfs_flags_authoritative = {
140 "Server is an authority for domain",
141 "Server is not an authority for domain"
144 static const true_false_string tfs_flags_truncated = {
145 "Message is truncated",
146 "Message is not truncated"
149 static const true_false_string tfs_flags_recdesired = {
150 "Do query recursively",
151 "Don't do query recursively"
154 static const true_false_string tfs_flags_recavail = {
155 "Server can do recursive queries",
156 "Server can't do recursive queries"
159 static const true_false_string tfs_flags_broadcast = {
161 "Not a broadcast packet"
165 #define OPCODE_QUERY 0 /* standard query */
166 #define OPCODE_REGISTRATION 5 /* registration */
167 #define OPCODE_RELEASE 6 /* release name */
168 #define OPCODE_WACK 7 /* wait for acknowledgement */
169 #define OPCODE_REFRESH 8 /* refresh registration */
170 #define OPCODE_REFRESHALT 9 /* refresh registration (alternate opcode) */
171 #define OPCODE_MHREGISTRATION 15 /* multi-homed registration */
173 static const value_string opcode_vals[] = {
174 { OPCODE_QUERY, "Name query" },
175 { OPCODE_REGISTRATION, "Registration" },
176 { OPCODE_RELEASE, "Release" },
177 { OPCODE_WACK, "Wait for acknowledgment" },
178 { OPCODE_REFRESH, "Refresh" },
179 { OPCODE_REFRESHALT, "Refresh (alternate opcode)" },
180 { OPCODE_MHREGISTRATION, "Multi-homed registration" },
185 #define RCODE_NOERROR 0
186 #define RCODE_FMTERROR 1
187 #define RCODE_SERVFAIL 2
188 #define RCODE_NAMEERROR 3
189 #define RCODE_NOTIMPL 4
190 #define RCODE_REFUSED 5
191 #define RCODE_ACTIVE 6
192 #define RCODE_CONFLICT 7
194 static const value_string rcode_vals[] = {
195 { RCODE_NOERROR, "No error" },
196 { RCODE_FMTERROR, "Request was invalidly formatted" },
197 { RCODE_SERVFAIL, "Server failure" },
198 { RCODE_NAMEERROR, "Requested name does not exist" },
199 { RCODE_NOTIMPL, "Request is not implemented" },
200 { RCODE_REFUSED, "Request was refused" },
201 { RCODE_ACTIVE, "Name is owned by another node" },
202 { RCODE_CONFLICT, "Name is in conflict" },
206 /* Values for the "NB_FLAGS" field of RR data. From RFC 1001 and 1002,
207 * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
209 #define NB_FLAGS_ONT (3<<(15-2)) /* bits for node type */
210 #define NB_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
211 #define NB_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
212 #define NB_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
213 #define NB_FLAGS_ONT_H_NODE (3<<(15-2)) /* H-mode node */
215 #define NB_FLAGS_G (1<<(15-0)) /* group name */
217 /* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
218 * RR data. From RFC 1001 and 1002; as I remember, the "NAME_FLAGS"
219 * field doesn't include any special values for H-mode nodes, even
220 * though one can register them (if so, perhaps that was done to
221 * avoid surprising clients that don't know about H-mode nodes). */
222 #define NAME_FLAGS_PRM (1<<(15-6)) /* name is permanent node name */
224 #define NAME_FLAGS_ACT (1<<(15-5)) /* name is active */
226 #define NAME_FLAGS_CNF (1<<(15-4)) /* name is in conflict */
228 #define NAME_FLAGS_DRG (1<<(15-3)) /* name is being deregistered */
230 #define NAME_FLAGS_ONT (3<<(15-2)) /* bits for node type */
231 #define NAME_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
232 #define NAME_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
233 #define NAME_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
235 #define NAME_FLAGS_G (1<<(15-0)) /* group name */
238 nbns_type_name (int type)
250 #define NBNAME_BUF_LEN 128
253 add_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
254 const char *name, int namelen,
255 const char *type_name, const char *class_description,
256 guint ttl, gushort data_len)
260 rr_tree = proto_item_add_subtree(trr, rr_type);
261 proto_tree_add_text(rr_tree, tvb, offset+1, namelen-1, "Name: %s", name);
263 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
265 proto_tree_add_text(rr_tree, tvb, offset, 2, "Class: %s", class_description);
267 proto_tree_add_text(rr_tree, tvb, offset, 4, "Time to live: %s",
268 time_secs_to_str(ttl));
270 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
275 get_nbns_name(tvbuff_t *tvb, int offset, int nbns_data_offset,
276 char *name_ret, int name_ret_len, int *name_type_ret)
280 const guchar *nbname;
288 nbname_buf=ep_alloc(NBNAME_BUF_LEN);
290 /* XXX Fix data len */
291 name_len = get_dns_name(tvb, offset, 0, nbns_data_offset, &name);
293 /* OK, now undo the first-level encoding. */
298 /* Every two characters of the first level-encoded name
299 * turn into one character in the decoded name. */
302 break; /* no more characters */
304 break; /* scope ID follows */
305 if (cname < 'A' || cname > 'Z') {
307 nbname="Illegal NetBIOS name (1st character not between A and Z in first-level encoding)";
311 cnbname = cname << 4;
315 if (cname == '\0' || cname == '.') {
316 /* No more characters in the name - but we're in
317 * the middle of a pair. Not legal. */
318 nbname="Illegal NetBIOS name (odd number of bytes)";
321 if (cname < 'A' || cname > 'Z') {
323 nbname="Illegal NetBIOS name (2nd character not between A and Z in first-level encoding)";
330 /* Do we have room to store the character? */
331 if (index < NETBIOS_NAME_LEN) {
332 /* Yes - store the character. */
333 nbname_buf[index++] = cnbname;
337 /* NetBIOS names are supposed to be exactly 16 bytes long. */
338 if (index != NETBIOS_NAME_LEN) {
340 g_snprintf(nbname_buf, NBNAME_BUF_LEN, "Illegal NetBIOS name (%lu bytes long)",
341 (unsigned long)index);
345 /* This one is; make its name printable. */
346 name_type = process_netbios_name(nbname, name_ret, name_ret_len);
347 pname_ret += MIN(strlen(name_ret), (size_t) name_ret_len);
348 pname_ret += MIN(name_ret_len-(pname_ret-name_ret),
349 g_snprintf(pname_ret, name_ret_len-(gulong)(pname_ret-name_ret), "<%02x>", name_type));
351 /* We have a scope ID, starting at "pname"; append that to
352 * the decoded host name. */
353 g_snprintf(pname_ret, name_ret_len-(gulong)(pname_ret-name_ret), "%s", pname);
355 if (name_type_ret != NULL)
356 *name_type_ret = name_type;
360 if (name_type_ret != NULL)
362 /* This is only valid because nbname is always assigned an error string
363 * before jumping to bad: Otherwise nbname wouldn't be \0 terminated */
364 g_snprintf(pname_ret, name_ret_len-(gulong)(pname_ret-name_ret), "%s", nbname);
370 get_nbns_name_type_class(tvbuff_t *tvb, int offset, int nbns_data_offset,
371 char *name_ret, int *name_len_ret, int *name_type_ret, int *type_ret,
378 name_len = get_nbns_name(tvb, offset, nbns_data_offset, name_ret,
379 *name_len_ret, name_type_ret);
382 type = tvb_get_ntohs(tvb, offset);
385 class = tvb_get_ntohs(tvb, offset);
389 *name_len_ret = name_len;
395 add_name_and_type(proto_tree *tree, tvbuff_t *tvb, int offset, int len,
396 const char *tag, const char *name, int name_type)
398 if (name_type != -1) {
399 proto_tree_add_text(tree, tvb, offset, len, "%s: %s (%s)",
400 tag, name, netbios_name_type_descr(name_type));
402 proto_tree_add_text(tree, tvb, offset, len, "%s: %s",
407 #define MAX_NAME_LEN (NETBIOS_NAME_LEN - 1)*4 + MAXDNAME + 64
410 dissect_nbns_query(tvbuff_t *tvb, int offset, int nbns_data_offset,
411 column_info *cinfo, proto_tree *nbns_tree)
419 const char *type_name;
425 name=ep_alloc(MAX_NAME_LEN);
426 data_start = data_offset = offset;
428 name_len=MAX_NAME_LEN;
429 len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
430 &name_len, &name_type, &type, &class);
433 type_name = nbns_type_name(type);
436 col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
437 if (nbns_tree != NULL) {
438 tq = proto_tree_add_text(nbns_tree, tvb, offset, len,
439 "%s: type %s, class %s", name, type_name,
440 dns_class_name(class));
441 q_tree = proto_item_add_subtree(tq, ett_nbns_qd);
443 add_name_and_type(q_tree, tvb, offset, name_len, "Name", name,
447 proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", type_name);
450 proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s",
451 dns_class_name(class));
455 return data_offset - data_start;
459 nbns_add_nbns_flags(column_info *cinfo, proto_tree *nbns_tree, tvbuff_t *tvb, int offset,
460 gushort flags, int is_wack)
464 proto_tree *field_tree;
467 #define MAX_BUF_SIZE (128+1)
468 buf=ep_alloc(MAX_BUF_SIZE);
469 opcode = (guint16) ((flags & F_OPCODE) >> OPCODE_SHIFT);
470 g_snprintf(buf, MAX_BUF_SIZE, "%s", val_to_str(opcode, opcode_vals, "Unknown operation"));
471 if (flags & F_RESPONSE && !is_wack) {
472 g_strlcat(buf, " response", MAX_BUF_SIZE);
473 g_strlcat(buf, ", ", MAX_BUF_SIZE);
474 g_strlcat(buf, val_to_str(flags & F_RCODE, rcode_vals, "Unknown error"), MAX_BUF_SIZE);
475 buf[MAX_BUF_SIZE-1] = '\0';
476 if ((flags & F_RCODE) && check_col(cinfo, COL_INFO))
477 col_append_fstr(cinfo, COL_INFO, ", %s",
478 val_to_str(flags & F_RCODE, rcode_vals,
481 tf = proto_tree_add_uint_format(nbns_tree, hf_nbns_flags,
482 tvb, offset, 2, flags, "Flags: 0x%04x (%s)", flags, buf);
483 field_tree = proto_item_add_subtree(tf, ett_nbns_flags);
484 proto_tree_add_item(field_tree, hf_nbns_flags_response,
485 tvb, offset, 2, FALSE);
486 proto_tree_add_item(field_tree, hf_nbns_flags_opcode,
487 tvb, offset, 2, FALSE);
488 if (flags & F_RESPONSE) {
489 proto_tree_add_item(field_tree, hf_nbns_flags_authoritative,
490 tvb, offset, 2, FALSE);
492 proto_tree_add_item(field_tree, hf_nbns_flags_truncated,
493 tvb, offset, 2, FALSE);
494 proto_tree_add_item(field_tree, hf_nbns_flags_recdesired,
495 tvb, offset, 2, FALSE);
496 if (flags & F_RESPONSE) {
497 proto_tree_add_item(field_tree, hf_nbns_flags_recavail,
498 tvb, offset, 2, FALSE);
500 proto_tree_add_item(field_tree, hf_nbns_flags_broadcast,
501 tvb, offset, 2, FALSE);
502 if (flags & F_RESPONSE && !is_wack) {
503 proto_tree_add_item(field_tree, hf_nbns_flags_rcode,
504 tvb, offset, 2, FALSE);
509 nbns_add_nb_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset, gushort flags)
512 proto_tree *field_tree;
514 static const value_string nb_flags_ont_vals[] = {
515 { NB_FLAGS_ONT_B_NODE, "B-node" },
516 { NB_FLAGS_ONT_P_NODE, "P-node" },
517 { NB_FLAGS_ONT_M_NODE, "M-node" },
518 { NB_FLAGS_ONT_H_NODE, "H-node" },
522 buf=ep_alloc(MAX_BUF_SIZE);
523 g_snprintf(buf, MAX_BUF_SIZE, "%s", val_to_str(flags & NB_FLAGS_ONT, nb_flags_ont_vals,
525 g_strlcat(buf, ", ", MAX_BUF_SIZE);
526 if (flags & NB_FLAGS_G)
527 g_strlcat(buf, "group", MAX_BUF_SIZE);
529 g_strlcat(buf, "unique", MAX_BUF_SIZE);
530 buf[MAX_BUF_SIZE-1] = '\0';
531 tf = proto_tree_add_text(rr_tree, tvb, offset, 2, "Flags: 0x%x (%s)", flags,
533 field_tree = proto_item_add_subtree(tf, ett_nbns_nb_flags);
534 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
535 decode_boolean_bitfield(flags, NB_FLAGS_G,
539 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
540 decode_enumerated_bitfield(flags, NB_FLAGS_ONT,
541 2*8, nb_flags_ont_vals, "%s"));
545 nbns_add_name_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset,
549 proto_item *field_tree;
551 static const value_string name_flags_ont_vals[] = {
552 { NAME_FLAGS_ONT_B_NODE, "B-node" },
553 { NAME_FLAGS_ONT_P_NODE, "P-node" },
554 { NAME_FLAGS_ONT_M_NODE, "M-node" },
558 buf=ep_alloc(MAX_BUF_SIZE);
559 g_snprintf(buf, MAX_BUF_SIZE, "%s", val_to_str(flags & NAME_FLAGS_ONT, name_flags_ont_vals,
561 g_strlcat(buf, ", ", MAX_BUF_SIZE);
562 if (flags & NAME_FLAGS_G)
563 g_strlcat(buf, "group", MAX_BUF_SIZE);
565 g_strlcat(buf, "unique", MAX_BUF_SIZE);
566 if (flags & NAME_FLAGS_DRG)
567 g_strlcat(buf, ", being deregistered", MAX_BUF_SIZE);
568 if (flags & NAME_FLAGS_CNF)
569 g_strlcat(buf, ", in conflict", MAX_BUF_SIZE);
570 if (flags & NAME_FLAGS_ACT)
571 g_strlcat(buf, ", active", MAX_BUF_SIZE);
572 if (flags & NAME_FLAGS_PRM)
573 g_strlcat(buf, ", permanent node name", MAX_BUF_SIZE);
574 buf[MAX_BUF_SIZE-1] = '\0';
575 tf = proto_tree_add_text(rr_tree, tvb, offset, 2, "Name flags: 0x%x (%s)",
577 field_tree = proto_item_add_subtree(tf, ett_nbns_name_flags);
578 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
579 decode_boolean_bitfield(flags, NAME_FLAGS_G,
583 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
584 decode_enumerated_bitfield(flags, NAME_FLAGS_ONT,
585 2*8, name_flags_ont_vals, "%s"));
586 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
587 decode_boolean_bitfield(flags, NAME_FLAGS_DRG,
589 "Name is being deregistered",
590 "Name is not being deregistered"));
591 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
592 decode_boolean_bitfield(flags, NAME_FLAGS_CNF,
594 "Name is in conflict",
595 "Name is not in conflict"));
596 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
597 decode_boolean_bitfield(flags, NAME_FLAGS_ACT,
600 "Name is not active"));
601 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
602 decode_boolean_bitfield(flags, NAME_FLAGS_PRM,
604 "Permanent node name",
605 "Not permanent node name"));
609 dissect_nbns_answer(tvbuff_t *tvb, int offset, int nbns_data_offset,
610 column_info *cinfo, proto_tree *nbns_tree, int opcode)
618 const char *class_name;
619 const char *type_name;
633 data_start = data_offset = offset;
636 name=ep_alloc(MAX_NAME_LEN);
637 name_str=ep_alloc(MAX_NAME_LEN);
638 nbname=ep_alloc(16+4+1); /* 4 for [<last char>] */
640 name_len=MAX_NAME_LEN;
641 len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
642 &name_len, &name_type, &type, &class);
646 type_name = nbns_type_name(type);
647 class_name = dns_class_name(class);
649 ttl = tvb_get_ntohl(tvb, data_offset);
653 data_len = tvb_get_ntohs(tvb, data_offset);
658 case T_NB: /* "NB" record */
660 if (opcode != OPCODE_WACK) {
661 col_append_fstr(cinfo, COL_INFO, " %s %s",
663 ip_to_str(tvb_get_ptr(tvb, data_offset+2, 4)));
666 if (nbns_tree == NULL)
668 trr = proto_tree_add_text(nbns_tree, tvb, offset,
669 (data_offset - data_start) + data_len,
670 "%s: type %s, class %s",
671 name, type_name, class_name);
672 g_strlcat(name, " (", MAX_NAME_LEN);
673 g_strlcat(name, netbios_name_type_descr(name_type), MAX_NAME_LEN);
674 g_strlcat(name, ")", MAX_NAME_LEN);
675 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
676 name_len, type_name, dns_class_name(class), ttl, data_len);
677 while (data_len > 0) {
678 if (opcode == OPCODE_WACK) {
679 /* WACK response. This doesn't contain the
680 * same type of RR data as other T_NB
683 proto_tree_add_text(rr_tree, tvb, cur_offset,
684 data_len, "(incomplete entry)");
687 flags = tvb_get_ntohs(tvb, cur_offset);
688 nbns_add_nbns_flags(cinfo, rr_tree, tvb, cur_offset,
694 proto_tree_add_text(rr_tree, tvb, cur_offset,
695 data_len, "(incomplete entry)");
698 flags = tvb_get_ntohs(tvb, cur_offset);
699 nbns_add_nb_flags(rr_tree, tvb, cur_offset,
705 proto_tree_add_text(rr_tree, tvb, cur_offset,
706 data_len, "(incomplete entry)");
709 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
711 ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
718 case T_NBSTAT: /* "NBSTAT" record */
720 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
721 if (nbns_tree == NULL)
723 trr = proto_tree_add_text(nbns_tree, tvb, offset,
724 (data_offset - data_start) + data_len,
725 "%s: type %s, class %s",
726 name, type_name, class_name);
727 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
728 name_len, type_name, dns_class_name(class), ttl, data_len);
730 proto_tree_add_text(rr_tree, tvb, cur_offset,
731 data_len, "(incomplete entry)");
734 num_names = tvb_get_guint8(tvb, cur_offset);
735 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
736 "Number of names: %u", num_names);
739 while (num_names != 0) {
740 if (data_len < NETBIOS_NAME_LEN) {
741 proto_tree_add_text(rr_tree, tvb, cur_offset,
742 data_len, "(incomplete entry)");
745 tvb_memcpy(tvb, (guint8 *)nbname, cur_offset,
747 name_type = process_netbios_name(nbname,
749 proto_tree_add_text(rr_tree, tvb, cur_offset,
750 NETBIOS_NAME_LEN, "Name: %s<%02x> (%s)",
752 netbios_name_type_descr(name_type));
753 cur_offset += NETBIOS_NAME_LEN;
754 data_len -= NETBIOS_NAME_LEN;
757 proto_tree_add_text(rr_tree, tvb, cur_offset,
758 data_len, "(incomplete entry)");
761 name_flags = tvb_get_ntohs(tvb, cur_offset);
762 nbns_add_name_flags(rr_tree, tvb, cur_offset,
771 proto_tree_add_text(rr_tree, tvb, cur_offset,
772 data_len, "(incomplete entry)");
775 proto_tree_add_text(rr_tree, tvb, cur_offset, 6,
777 ether_to_str(tvb_get_ptr(tvb, cur_offset, 6)));
782 proto_tree_add_text(rr_tree, tvb, cur_offset,
783 data_len, "(incomplete entry)");
786 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
787 "Jumpers: 0x%x", tvb_get_guint8(tvb, cur_offset));
792 proto_tree_add_text(rr_tree, tvb, cur_offset,
793 data_len, "(incomplete entry)");
796 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
797 "Test result: 0x%x", tvb_get_guint8(tvb, cur_offset));
802 proto_tree_add_text(rr_tree, tvb, cur_offset,
803 data_len, "(incomplete entry)");
806 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
807 "Version number: 0x%x", tvb_get_ntohs(tvb, cur_offset));
812 proto_tree_add_text(rr_tree, tvb, cur_offset,
813 data_len, "(incomplete entry)");
816 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
817 "Period of statistics: 0x%x",
818 tvb_get_ntohs(tvb, cur_offset));
823 proto_tree_add_text(rr_tree, tvb, cur_offset,
824 data_len, "(incomplete entry)");
827 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
828 "Number of CRCs: %u", tvb_get_ntohs(tvb, cur_offset));
833 proto_tree_add_text(rr_tree, tvb, cur_offset,
834 data_len, "(incomplete entry)");
837 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
838 "Number of alignment errors: %u",
839 tvb_get_ntohs(tvb, cur_offset));
844 proto_tree_add_text(rr_tree, tvb, cur_offset,
845 data_len, "(incomplete entry)");
848 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
849 "Number of collisions: %u", tvb_get_ntohs(tvb, cur_offset));
854 proto_tree_add_text(rr_tree, tvb, cur_offset,
855 data_len, "(incomplete entry)");
858 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
859 "Number of send aborts: %u", tvb_get_ntohs(tvb, cur_offset));
864 proto_tree_add_text(rr_tree, tvb, cur_offset,
865 data_len, "(incomplete entry)");
868 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
869 "Number of good sends: %u", tvb_get_ntohl(tvb, cur_offset));
874 proto_tree_add_text(rr_tree, tvb, cur_offset,
875 data_len, "(incomplete entry)");
878 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
879 "Number of good receives: %u",
880 tvb_get_ntohl(tvb, cur_offset));
885 proto_tree_add_text(rr_tree, tvb, cur_offset,
886 data_len, "(incomplete entry)");
889 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
890 "Number of retransmits: %u", tvb_get_ntohs(tvb, cur_offset));
895 proto_tree_add_text(rr_tree, tvb, cur_offset,
896 data_len, "(incomplete entry)");
899 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
900 "Number of no resource conditions: %u",
901 tvb_get_ntohs(tvb, cur_offset));
906 proto_tree_add_text(rr_tree, tvb, cur_offset,
907 data_len, "(incomplete entry)");
910 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
911 "Number of command blocks: %u",
912 tvb_get_ntohs(tvb, cur_offset));
917 proto_tree_add_text(rr_tree, tvb, cur_offset,
918 data_len, "(incomplete entry)");
921 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
922 "Number of pending sessions: %u",
923 tvb_get_ntohs(tvb, cur_offset));
928 proto_tree_add_text(rr_tree, tvb, cur_offset,
929 data_len, "(incomplete entry)");
932 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
933 "Max number of pending sessions: %u",
934 tvb_get_ntohs(tvb, cur_offset));
939 proto_tree_add_text(rr_tree, tvb, cur_offset,
940 data_len, "(incomplete entry)");
943 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
944 "Max total sessions possible: %u",
945 tvb_get_ntohs(tvb, cur_offset));
950 proto_tree_add_text(rr_tree, tvb, cur_offset,
951 data_len, "(incomplete entry)");
954 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
955 "Session data packet size: %u",
956 tvb_get_ntohs(tvb, cur_offset));
964 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
965 if (nbns_tree == NULL)
967 trr = proto_tree_add_text(nbns_tree, tvb, offset,
968 (data_offset - data_start) + data_len,
969 "%s: type %s, class %s",
970 name, type_name, class_name);
971 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
972 name_len, type_name, dns_class_name(class), ttl, data_len);
973 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
974 cur_offset += data_len;
978 return cur_offset - data_start;
982 dissect_query_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
983 int count, column_info *cinfo, proto_tree *nbns_tree)
985 int start_off, add_off;
986 proto_tree *qatree = NULL;
987 proto_item *ti = NULL;
990 if (nbns_tree != NULL) {
991 ti = proto_tree_add_text(nbns_tree, tvb, start_off, -1, "Queries");
992 qatree = proto_item_add_subtree(ti, ett_nbns_qry);
994 while (count-- > 0) {
995 add_off = dissect_nbns_query(tvb, cur_off, nbns_data_offset,
1000 proto_item_set_len(ti, cur_off - start_off);
1002 return cur_off - start_off;
1008 dissect_answer_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
1009 int count, column_info *cinfo, proto_tree *nbns_tree, int opcode,
1012 int start_off, add_off;
1013 proto_tree *qatree = NULL;
1014 proto_item *ti = NULL;
1016 start_off = cur_off;
1017 if (nbns_tree != NULL) {
1018 ti = proto_tree_add_text(nbns_tree, tvb, start_off, -1, "%s", name);
1019 qatree = proto_item_add_subtree(ti, ett_nbns_ans);
1021 while (count-- > 0) {
1022 add_off = dissect_nbns_answer(tvb, cur_off, nbns_data_offset,
1023 cinfo, qatree, opcode);
1027 proto_item_set_len(ti, cur_off - start_off);
1028 return cur_off - start_off;
1032 dissect_nbns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1035 int nbns_data_offset;
1037 proto_tree *nbns_tree = NULL;
1039 guint16 id, flags, opcode, rcode, quest, ans, auth, add;
1042 nbns_data_offset = offset;
1044 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1045 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBNS");
1046 if (check_col(pinfo->cinfo, COL_INFO))
1047 col_clear(pinfo->cinfo, COL_INFO);
1049 /* To do: check for runts, errs, etc. */
1050 id = tvb_get_ntohs(tvb, offset + NBNS_ID);
1051 flags = tvb_get_ntohs(tvb, offset + NBNS_FLAGS);
1052 opcode = (guint16) ((flags & F_OPCODE) >> OPCODE_SHIFT);
1053 rcode = (guint16) (flags & F_RCODE);
1055 if (check_col(pinfo->cinfo, COL_INFO)) {
1056 col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s",
1057 val_to_str(opcode, opcode_vals, "Unknown operation (%u)"),
1058 (flags & F_RESPONSE) ? " response" : "");
1059 cinfo = pinfo->cinfo;
1061 /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query
1062 and answer dissectors, as a way of saying that they
1063 shouldn't add stuff to the COL_INFO column (a call to
1064 "check_col(cinfo, COL_INFO)" is more expensive than
1065 a check that a pointer isn't NULL). */
1070 ti = proto_tree_add_item(tree, proto_nbns, tvb, offset, -1,
1072 nbns_tree = proto_item_add_subtree(ti, ett_nbns);
1074 proto_tree_add_uint(nbns_tree, hf_nbns_transaction_id, tvb,
1075 offset + NBNS_ID, 2, id);
1077 nbns_add_nbns_flags(pinfo->cinfo, nbns_tree, tvb, offset + NBNS_FLAGS,
1080 quest = tvb_get_ntohs(tvb, offset + NBNS_QUEST);
1082 proto_tree_add_uint(nbns_tree, hf_nbns_count_questions, tvb,
1083 offset + NBNS_QUEST, 2, quest);
1085 ans = tvb_get_ntohs(tvb, offset + NBNS_ANS);
1087 proto_tree_add_uint(nbns_tree, hf_nbns_count_answers, tvb,
1088 offset + NBNS_ANS, 2, ans);
1090 auth = tvb_get_ntohs(tvb, offset + NBNS_AUTH);
1092 proto_tree_add_uint(nbns_tree, hf_nbns_count_auth_rr, tvb,
1093 offset + NBNS_AUTH, 2, auth);
1095 add = tvb_get_ntohs(tvb, offset + NBNS_ADD);
1097 proto_tree_add_uint(nbns_tree, hf_nbns_count_add_rr, tvb,
1098 offset + NBNS_ADD, 2, add);
1101 cur_off = offset + NBNS_HDRLEN;
1104 /* If this is a response, don't add information about the
1105 queries to the summary, just add information about the
1107 cur_off += dissect_query_records(tvb, cur_off,
1108 nbns_data_offset, quest,
1109 (!(flags & F_RESPONSE) ? cinfo : NULL), nbns_tree);
1113 /* If this is a request, don't add information about the
1114 answers to the summary, just add information about the
1116 cur_off += dissect_answer_records(tvb, cur_off,
1117 nbns_data_offset, ans,
1118 ((flags & F_RESPONSE) ? cinfo : NULL), nbns_tree,
1123 /* Don't add information about the authoritative name
1124 servers, or the additional records, to the summary. */
1126 cur_off += dissect_answer_records(tvb, cur_off,
1128 auth, NULL, nbns_tree, opcode,
1129 "Authoritative nameservers");
1132 cur_off += dissect_answer_records(tvb, cur_off,
1134 add, NULL, nbns_tree, opcode,
1135 "Additional records");
1139 /* NetBIOS datagram packet, from RFC 1002, page 32 */
1140 struct nbdgm_header {
1151 /* For packets with data */
1155 /* For error packets */
1160 * NBDS message types.
1162 #define NBDS_DIRECT_UNIQUE 0x10
1163 #define NBDS_DIRECT_GROUP 0x11
1164 #define NBDS_BROADCAST 0x12
1165 #define NBDS_ERROR 0x13
1166 #define NBDS_QUERY_REQUEST 0x14
1167 #define NBDS_POS_QUERY_RESPONSE 0x15
1168 #define NBDS_NEG_QUERY_RESPONSE 0x16
1170 static const value_string nbds_msgtype_vals[] = {
1171 { NBDS_DIRECT_UNIQUE, "Direct_unique datagram" },
1172 { NBDS_DIRECT_GROUP, "Direct_group datagram" },
1173 { NBDS_BROADCAST, "Broadcast datagram" },
1174 { NBDS_ERROR, "Datagram error" },
1175 { NBDS_QUERY_REQUEST, "Datagram query request" },
1176 { NBDS_POS_QUERY_RESPONSE, "Datagram positive query response" },
1177 { NBDS_NEG_QUERY_RESPONSE, "Datagram negative query response" },
1181 static const value_string node_type_vals[] = {
1190 dissect_nbdgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1193 proto_tree *nbdgm_tree = NULL;
1194 proto_item *ti = NULL;
1195 struct nbdgm_header header;
1200 static const value_string error_codes[] = {
1201 { 0x82, "Destination name not present" },
1202 { 0x83, "Invalid source name format" },
1203 { 0x84, "Invalid destination name format" },
1211 name=ep_alloc(MAX_NAME_LEN);
1213 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1214 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBDS");
1215 if (check_col(pinfo->cinfo, COL_INFO))
1216 col_clear(pinfo->cinfo, COL_INFO);
1218 header.msg_type = tvb_get_guint8(tvb, offset);
1220 flags = tvb_get_guint8(tvb, offset+1);
1221 header.flags.more = flags & 1;
1222 header.flags.first = (flags & 2) >> 1;
1223 header.flags.node_type = (flags & 12) >> 2;
1225 header.dgm_id = tvb_get_ntohs(tvb, offset+2);
1226 header.src_ip = tvb_get_ipv4(tvb, offset+4);
1227 header.src_port = tvb_get_ntohs(tvb, offset+8);
1229 /* avoid gcc warnings */
1230 header.dgm_length = 0;
1231 header.pkt_offset = 0;
1232 header.error_code = 0;
1233 switch (header.msg_type) {
1235 case NBDS_DIRECT_UNIQUE:
1236 case NBDS_DIRECT_GROUP:
1237 case NBDS_BROADCAST:
1238 header.dgm_length = tvb_get_ntohs(tvb, offset+10);
1239 header.pkt_offset = tvb_get_ntohs(tvb, offset+12);
1243 header.error_code = tvb_get_guint8(tvb, offset+10);
1247 message_index = header.msg_type - 0x0f;
1248 if (message_index < 1 || message_index > 8) {
1252 if (check_col(pinfo->cinfo, COL_INFO)) {
1253 col_add_str(pinfo->cinfo, COL_INFO,
1254 val_to_str(header.msg_type, nbds_msgtype_vals,
1255 "Unknown message type (0x%02X)"));
1259 ti = proto_tree_add_item(tree, proto_nbdgm, tvb, offset, -1,
1261 nbdgm_tree = proto_item_add_subtree(ti, ett_nbdgm);
1263 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_type, tvb,
1266 proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_fragment, tvb,
1269 proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_first, tvb,
1271 header.flags.first);
1272 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_node_type, tvb,
1274 header.flags.node_type);
1276 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_datagram_id, tvb,
1277 offset+2, 2, header.dgm_id);
1278 proto_tree_add_ipv4(nbdgm_tree, hf_nbdgm_src_ip, tvb,
1279 offset+4, 4, header.src_ip);
1280 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_src_port, tvb,
1281 offset+8, 2, header.src_port);
1287 switch (header.msg_type) {
1289 case NBDS_DIRECT_UNIQUE:
1290 case NBDS_DIRECT_GROUP:
1291 case NBDS_BROADCAST:
1293 proto_tree_add_text(nbdgm_tree, tvb, offset, 2,
1294 "Datagram length: %d bytes", header.dgm_length);
1295 proto_tree_add_text(nbdgm_tree, tvb, offset+2, 2,
1296 "Packet offset: %d bytes", header.pkt_offset);
1302 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1305 add_name_and_type(nbdgm_tree, tvb, offset, len,
1306 "Source name", name, name_type);
1310 /* Destination name */
1311 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1314 add_name_and_type(nbdgm_tree, tvb, offset, len,
1315 "Destination name", name, name_type);
1320 * Here we can pass the packet off to the next protocol.
1321 * Set the length of our top-level tree item to include
1324 * XXX - take the datagram length into account?
1326 proto_item_set_len(ti, offset);
1327 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1328 dissect_netbios_payload(next_tvb, pinfo, tree);
1333 proto_tree_add_text(nbdgm_tree, tvb, offset, 1, "Error code: %s",
1334 val_to_str(header.error_code, error_codes, "Unknown (0x%x)"));
1337 proto_item_set_len(ti, offset);
1340 case NBDS_QUERY_REQUEST:
1341 case NBDS_POS_QUERY_RESPONSE:
1342 case NBDS_NEG_QUERY_RESPONSE:
1343 /* Destination name */
1344 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1347 add_name_and_type(nbdgm_tree, tvb, offset, len,
1348 "Destination name", name, name_type);
1351 proto_item_set_len(ti, offset);
1357 * NetBIOS Session Service message types.
1359 #define SESSION_MESSAGE 0x00
1360 #define SESSION_REQUEST 0x81
1361 #define POSITIVE_SESSION_RESPONSE 0x82
1362 #define NEGATIVE_SESSION_RESPONSE 0x83
1363 #define RETARGET_SESSION_RESPONSE 0x84
1364 #define SESSION_KEEP_ALIVE 0x85
1366 static const value_string message_types[] = {
1367 { SESSION_MESSAGE, "Session message" },
1368 { SESSION_REQUEST, "Session request" },
1369 { POSITIVE_SESSION_RESPONSE, "Positive session response" },
1370 { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
1371 { RETARGET_SESSION_RESPONSE, "Retarget session response" },
1372 { SESSION_KEEP_ALIVE, "Session keep-alive" },
1377 * NetBIOS Session Service flags.
1379 #define NBSS_FLAGS_E 0x1
1381 static const value_string error_codes[] = {
1382 { 0x80, "Not listening on called name" },
1383 { 0x81, "Not listening for called name" },
1384 { 0x82, "Called name not present" },
1385 { 0x83, "Called name present, but insufficient resources" },
1386 { 0x8F, "Unspecified error" },
1391 * Dissect a single NBSS packet (there may be more than one in a given
1394 * [ Hmmm, in my experience, I have never seen more than one NBSS in a
1395 * single segment, since they mostly contain SMBs which are essentially
1396 * a request response type protocol (RJS). ]
1398 * [ However, under heavy load with many requests multiplexed on one
1399 * session it is not unusual to see multiple requests in one TCP
1400 * segment. Unfortunately, in this case a single session message is
1401 * frequently split over multiple segments, which frustrates decoding
1405 dissect_nbss_packet(tvbuff_t *tvb, int offset, packet_info *pinfo,
1406 proto_tree *tree, int is_cifs)
1408 proto_tree *nbss_tree = NULL;
1409 proto_item *ti = NULL;
1410 proto_tree *field_tree;
1414 volatile int length;
1415 int length_remaining;
1421 const char *saved_proto;
1423 name=ep_alloc(MAX_NAME_LEN);
1425 /* Desegmentation */
1426 length_remaining = tvb_length_remaining(tvb, offset);
1429 * Can we do reassembly?
1431 if (nbss_desegment && pinfo->can_desegment) {
1433 * Yes - is the NBSS header split across segment boundaries?
1435 if (length_remaining < 4) {
1437 * Yes. Tell our caller how many more bytes
1440 return -(4 - length_remaining);
1445 * Get the length of the NBSS message.
1449 length = tvb_get_ntoh24(tvb, offset + 1);
1451 flags = tvb_get_guint8(tvb, offset + 1);
1452 length = tvb_get_ntohs(tvb, offset + 2);
1453 if (flags & NBSS_FLAGS_E)
1457 /* give a hint to TCP where the next PDU starts
1458 * so that it can attempt to find it in case it starts
1459 * somewhere in the middle of a segment.
1461 if(!pinfo->fd->flags.visited){
1462 /* 'Only' SMB is transported ontop of this so make sure
1463 * there is an SMB header there ...
1465 if( ((length+4)>tvb_reported_length_remaining(tvb, offset))
1466 &&(tvb_length_remaining(tvb, offset)>=8)
1467 &&(tvb_get_guint8(tvb,offset+5)=='S')
1468 &&(tvb_get_guint8(tvb,offset+6)=='M')
1469 &&(tvb_get_guint8(tvb,offset+7)=='B') ){
1470 pinfo->want_pdu_tracking=2;
1471 pinfo->bytes_until_next_pdu=(length+4)-tvb_reported_length_remaining(tvb, offset);
1476 * Can we do reassembly?
1478 if (nbss_desegment && pinfo->can_desegment) {
1480 * Yes - is the NBSS message split across segment boundaries?
1482 if (length_remaining < length + 4) {
1484 * Yes. Tell our caller how many more bytes
1487 return -((length + 4) - length_remaining);
1491 msg_type = tvb_get_guint8(tvb, offset);
1494 ti = proto_tree_add_item(tree, proto_nbss, tvb, offset, length + 4, FALSE);
1495 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1497 proto_tree_add_uint_format(nbss_tree, hf_nbss_type, tvb,
1501 val_to_str(msg_type, message_types,
1509 proto_tree_add_text(nbss_tree, tvb, offset, 3, "Length: %u", length);
1514 tf = proto_tree_add_uint(nbss_tree, hf_nbss_flags, tvb, offset, 1, flags);
1515 field_tree = proto_item_add_subtree(tf, ett_nbss_flags);
1516 proto_tree_add_text(field_tree, tvb, offset, 1, "%s",
1517 decode_boolean_bitfield(flags, NBSS_FLAGS_E,
1518 8, "Add 65536 to length", "Add 0 to length"));
1523 proto_tree_add_text(nbss_tree, tvb, offset, 2, "Length: %u", length);
1531 case SESSION_REQUEST:
1532 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1534 add_name_and_type(nbss_tree, tvb, offset, len,
1535 "Called name", name, name_type);
1538 if (check_col(pinfo->cinfo, COL_INFO))
1539 col_append_fstr(pinfo->cinfo, COL_INFO, ", to %s ", name);
1541 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1544 add_name_and_type(nbss_tree, tvb, offset, len,
1545 "Calling name", name, name_type);
1547 if (check_col(pinfo->cinfo, COL_INFO))
1548 col_append_fstr(pinfo->cinfo, COL_INFO, "from %s", name);
1552 case NEGATIVE_SESSION_RESPONSE:
1554 proto_tree_add_text(nbss_tree, tvb, offset, 1,
1556 val_to_str(tvb_get_guint8(tvb, offset),
1557 error_codes, "Unknown (%x)"));
1559 if (check_col(pinfo->cinfo, COL_INFO))
1560 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1561 val_to_str(tvb_get_guint8(tvb, offset),
1562 error_codes, "Unknown (%x)"));
1566 case RETARGET_SESSION_RESPONSE:
1568 proto_tree_add_text(nbss_tree, tvb, offset, 4,
1569 "Retarget IP address: %s",
1570 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1575 proto_tree_add_text(nbss_tree, tvb, offset, 2,
1576 "Retarget port: %u",
1577 tvb_get_ntohs(tvb, offset));
1581 case SESSION_MESSAGE:
1583 * Here we can pass the message off to the next protocol.
1584 * Set the length of our top-level tree item to include
1587 proto_item_set_len(ti, offset);
1588 len = tvb_length_remaining(tvb, offset);
1589 reported_len = tvb_reported_length_remaining(tvb, offset);
1592 if (reported_len > length)
1593 reported_len = length;
1595 next_tvb = tvb_new_subset(tvb, offset, len, reported_len);
1598 * Catch the ReportedBoundsError exception; if this
1599 * particular message happens to get a ReportedBoundsError
1600 * exception, that doesn't mean that we should stop
1601 * dissecting NetBIOS messages within this frame or chunk
1602 * of reassembled data.
1604 * If it gets a BoundsError, we can stop, as there's nothing
1605 * more to see, so we just re-throw it.
1607 saved_proto = pinfo->current_proto;
1609 dissect_netbios_payload(next_tvb, pinfo, tree);
1611 CATCH(BoundsError) {
1614 CATCH(ReportedBoundsError) {
1615 show_reported_bounds_error(tvb, pinfo, tree);
1616 pinfo->current_proto = saved_proto;
1626 dissect_nbss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1628 struct tcpinfo *tcpinfo = pinfo->private_data;
1636 proto_tree *nbss_tree;
1639 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1640 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBSS");
1641 if (check_col(pinfo->cinfo, COL_INFO))
1642 col_clear(pinfo->cinfo, COL_INFO);
1644 max_data = tvb_length(tvb);
1646 msg_type = tvb_get_guint8(tvb, offset);
1648 if (pinfo->match_port == TCP_PORT_CIFS) {
1650 * Windows 2000 CIFS clients can dispense completely
1651 * with the NETBIOS encapsulation and directly use CIFS
1652 * over TCP. As would be expected, the framing is
1653 * identical, except that the length is 24 bits instead
1654 * of 17. The only message types used are
1655 * SESSION_MESSAGE and SESSION_KEEP_ALIVE.
1663 * This might be a continuation of an earlier message.
1664 * (Yes, that might be true even if we're doing TCP reassembly,
1665 * as the first TCP segment in the capture might start in the
1666 * middle of an NBNS message.)
1670 * If this isn't reassembled data, check to see whether it
1671 * looks like a continuation of a message.
1672 * (If it is reassembled data, it shouldn't be a continuation,
1673 * as reassembly should've gathered the continuations together
1676 if (!tcpinfo->is_reassembled) {
1679 * Not enough data for an NBSS header; assume
1680 * it's a continuation of a message.
1682 * XXX - if there's not enough data, we should
1683 * attempt to reassemble the data, if the first byte
1684 * is a valid message type.
1690 * We have enough data for an NBSS header.
1691 * Get the flags and length of the message,
1692 * and see if they're sane.
1696 length = tvb_get_ntoh24(tvb, offset + 1);
1698 flags = tvb_get_guint8(tvb, offset + 1);
1699 length = tvb_get_ntohs(tvb, offset + 2);
1700 if (flags & NBSS_FLAGS_E)
1703 if ((flags & (~NBSS_FLAGS_E)) != 0) {
1705 * A bogus flag was set; assume it's a continuation.
1712 case SESSION_MESSAGE:
1714 * This is variable-length.
1715 * All we know is that it shouldn't be zero.
1716 * (XXX - can we get zero-length messages?
1717 * Not with SMB, but perhaps other NetBIOS-based
1718 * protocols have them.)
1724 case SESSION_REQUEST:
1726 * This is variable-length.
1727 * The names are DNS-encoded 32-byte values;
1728 * we need at least 2 bytes (one for each name;
1729 * actually, we should have more for the first
1730 * name, as there's no name preceding it so
1731 * there should be no compression), and we
1732 * shouldn't have more than 128 bytes (actually,
1733 * we shouldn't have that many).
1735 * XXX - actually, MacOS X 10.1 (yes, that's
1736 * redundant, but that's what Apple calls it,
1737 * not MacOS X.1) puts names longer than 16
1738 * characters into session request messages,
1739 * so we can have more than 32 bytes of
1740 * name value, so we can have more than 128
1743 if (length < 2 || length > 256)
1747 case POSITIVE_SESSION_RESPONSE:
1749 * This has no data, so the length must be zero.
1755 case NEGATIVE_SESSION_RESPONSE:
1757 * This has 1 byte of data.
1763 case RETARGET_SESSION_RESPONSE:
1765 * This has 6 bytes of data.
1771 case SESSION_KEEP_ALIVE:
1773 * This has no data, so the length must be zero.
1781 * Unknown message type; assume it's a continuation.
1787 if (check_col(pinfo->cinfo, COL_INFO)) {
1788 col_add_str(pinfo->cinfo, COL_INFO,
1789 val_to_str(msg_type, message_types, "Unknown (%02x)"));
1792 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1793 len = dissect_nbss_packet(tvb, offset, pinfo, tree, is_cifs);
1796 * We need more data to dissect this, and
1797 * desegmentation is enabled. "-len" is the
1798 * number of additional bytes of data we need.
1800 * Tell the TCP dissector where the data for this
1801 * message starts in the data it handed us, and
1802 * how many more bytes we need, and return.
1804 pinfo->desegment_offset = offset;
1805 pinfo->desegment_len = -len;
1815 * It looks like a continuation.
1817 if (check_col(pinfo->cinfo, COL_INFO))
1818 col_set_str(pinfo->cinfo, COL_INFO, "NBSS Continuation Message");
1821 ti = proto_tree_add_item(tree, proto_nbss, tvb, 0, -1, FALSE);
1822 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1823 proto_tree_add_text(nbss_tree, tvb, 0, -1, "Continuation data");
1828 proto_register_nbt(void)
1831 static hf_register_info hf_nbns[] = {
1833 { "Flags", "nbns.flags",
1834 FT_UINT16, BASE_HEX, NULL, 0x0,
1836 { &hf_nbns_flags_response,
1837 { "Response", "nbns.flags.response",
1838 FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
1839 "Is the message a response?", HFILL }},
1840 { &hf_nbns_flags_opcode,
1841 { "Opcode", "nbns.flags.opcode",
1842 FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
1843 "Operation code", HFILL }},
1844 { &hf_nbns_flags_authoritative,
1845 { "Authoritative", "nbns.flags.authoritative",
1846 FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
1847 "Is the server is an authority for the domain?", HFILL }},
1848 { &hf_nbns_flags_truncated,
1849 { "Truncated", "nbns.flags.truncated",
1850 FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
1851 "Is the message truncated?", HFILL }},
1852 { &hf_nbns_flags_recdesired,
1853 { "Recursion desired", "nbns.flags.recdesired",
1854 FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
1855 "Do query recursively?", HFILL }},
1856 { &hf_nbns_flags_recavail,
1857 { "Recursion available", "nbns.flags.recavail",
1858 FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
1859 "Can the server do recursive queries?", HFILL }},
1860 { &hf_nbns_flags_broadcast,
1861 { "Broadcast", "nbns.flags.broadcast",
1862 FT_BOOLEAN, 16, TFS(&tfs_flags_broadcast), F_BROADCAST,
1863 "Is this a broadcast packet?", HFILL }},
1864 { &hf_nbns_flags_rcode,
1865 { "Reply code", "nbns.flags.rcode",
1866 FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
1868 { &hf_nbns_transaction_id,
1869 { "Transaction ID", "nbns.id",
1870 FT_UINT16, BASE_HEX, NULL, 0x0,
1871 "Identification of transaction", HFILL }},
1872 { &hf_nbns_count_questions,
1873 { "Questions", "nbns.count.queries",
1874 FT_UINT16, BASE_DEC, NULL, 0x0,
1875 "Number of queries in packet", HFILL }},
1876 { &hf_nbns_count_answers,
1877 { "Answer RRs", "nbns.count.answers",
1878 FT_UINT16, BASE_DEC, NULL, 0x0,
1879 "Number of answers in packet", HFILL }},
1880 { &hf_nbns_count_auth_rr,
1881 { "Authority RRs", "nbns.count.auth_rr",
1882 FT_UINT16, BASE_DEC, NULL, 0x0,
1883 "Number of authoritative records in packet", HFILL }},
1884 { &hf_nbns_count_add_rr,
1885 { "Additional RRs", "nbns.count.add_rr",
1886 FT_UINT16, BASE_DEC, NULL, 0x0,
1887 "Number of additional records in packet", HFILL }}
1890 static hf_register_info hf_nbdgm[] = {
1892 { "Message Type", "nbdgm.type",
1893 FT_UINT8, BASE_DEC, VALS(nbds_msgtype_vals), 0x0,
1894 "NBDGM message type", HFILL }},
1895 { &hf_nbdgm_fragment,
1896 { "More fragments follow", "nbdgm.next",
1897 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
1898 "TRUE if more fragments follow", HFILL }},
1900 { "This is first fragment", "nbdgm.first",
1901 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
1902 "TRUE if first fragment", HFILL }},
1903 { &hf_nbdgm_node_type,
1904 { "Node Type", "nbdgm.node_type",
1905 FT_UINT8, BASE_DEC, VALS(node_type_vals), 0x0,
1906 "Node type", HFILL }},
1907 { &hf_nbdgm_datagram_id,
1908 { "Datagram ID", "nbdgm.dgram_id",
1909 FT_UINT16, BASE_HEX, NULL, 0x0,
1910 "Datagram identifier", HFILL }},
1912 { "Source IP", "nbdgm.src.ip",
1913 FT_IPv4, BASE_NONE, NULL, 0x0,
1914 "Source IPv4 address", HFILL }},
1915 { &hf_nbdgm_src_port,
1916 { "Source Port", "nbdgm.src.port",
1917 FT_UINT16, BASE_DEC, NULL, 0x0,
1918 "Source port", HFILL }}
1921 static hf_register_info hf_nbss[] = {
1923 { "Message Type", "nbss.type",
1924 FT_UINT8, BASE_DEC, NULL, 0x0,
1925 "NBSS message type", HFILL }},
1927 { "Flags", "nbss.flags",
1928 FT_UINT8, BASE_HEX, NULL, 0x0,
1929 "NBSS message flags", HFILL }}
1931 static gint *ett[] = {
1936 &ett_nbns_name_flags,
1944 module_t *nbss_module;
1946 proto_nbns = proto_register_protocol("NetBIOS Name Service", "NBNS", "nbns");
1947 proto_register_field_array(proto_nbns, hf_nbns, array_length(hf_nbns));
1949 proto_nbdgm = proto_register_protocol("NetBIOS Datagram Service",
1951 proto_register_field_array(proto_nbdgm, hf_nbdgm, array_length(hf_nbdgm));
1953 proto_nbss = proto_register_protocol("NetBIOS Session Service",
1955 proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));
1957 proto_register_subtree_array(ett, array_length(ett));
1959 nbss_module = prefs_register_protocol(proto_nbss, NULL);
1960 prefs_register_bool_preference(nbss_module, "desegment_nbss_commands",
1961 "Reassemble NBSS packets spanning multiple TCP segments",
1962 "Whether the NBSS dissector should reassemble packets spanning multiple TCP segments."
1963 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1968 proto_reg_handoff_nbt(void)
1970 dissector_handle_t nbns_handle, nbdgm_handle, nbss_handle;
1972 nbns_handle = create_dissector_handle(dissect_nbns, proto_nbns);
1973 dissector_add("udp.port", UDP_PORT_NBNS, nbns_handle);
1974 nbdgm_handle = create_dissector_handle(dissect_nbdgm, proto_nbdgm);
1975 dissector_add("udp.port", UDP_PORT_NBDGM, nbdgm_handle);
1976 nbss_handle = create_dissector_handle(dissect_nbss, proto_nbss);
1977 dissector_add("tcp.port", TCP_PORT_NBSS, nbss_handle);
1978 dissector_add("tcp.port", TCP_PORT_CIFS, nbss_handle);