2 * Routines for NetBIOS-over-TCP packet disassembly (the name dates back
3 * to when it had only NBNS)
4 * Gilbert Ramirez <gram@xiexie.org>
5 * Much stuff added by Guy Harris <guy@alum.mit.edu>
7 * $Id: packet-nbns.c,v 1.55 2001/09/13 07:53:51 guy Exp $
9 * Ethereal - Network traffic analyzer
10 * By Gerald Combs <gerald@ethereal.com>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
41 #include "packet-dns.h"
42 #include "packet-netbios.h"
43 #include "packet-smb.h"
46 static int proto_nbns = -1;
47 static int hf_nbns_response = -1;
48 static int hf_nbns_query = -1;
49 static int hf_nbns_transaction_id = -1;
50 static int hf_nbns_count_questions = -1;
51 static int hf_nbns_count_answers = -1;
52 static int hf_nbns_count_auth_rr = -1;
53 static int hf_nbns_count_add_rr = -1;
55 static gint ett_nbns = -1;
56 static gint ett_nbns_qd = -1;
57 static gint ett_nbns_flags = -1;
58 static gint ett_nbns_nb_flags = -1;
59 static gint ett_nbns_name_flags = -1;
60 static gint ett_nbns_rr = -1;
61 static gint ett_nbns_qry = -1;
62 static gint ett_nbns_ans = -1;
64 static int proto_nbdgm = -1;
65 static int hf_nbdgm_type = -1;
66 static int hf_nbdgm_fragment = -1;
67 static int hf_nbdgm_first = -1;
68 static int hf_nbdgm_node_type = -1;
69 static int hf_nbdgm_datagram_id = -1;
70 static int hf_nbdgm_src_ip = -1;
71 static int hf_nbdgm_src_port = -1;
73 static gint ett_nbdgm = -1;
75 static int proto_nbss = -1;
76 static int hf_nbss_type = -1;
77 static int hf_nbss_flags = -1;
79 static gint ett_nbss = -1;
80 static gint ett_nbss_flags = -1;
82 /* desegmentation of NBSS over TCP */
83 static gboolean nbss_desegment = FALSE;
86 /* See RFC 1001 and 1002 for information on the first three, and see
88 http://www.cifs.com/specs/draft-leach-cifs-v1-spec-01.txt
90 Appendix B, and various messages on the CIFS mailing list such as
92 http://discuss.microsoft.com/SCRIPTS/WA-MSD.EXE?A2=ind9811A&L=cifs&P=R386
94 for information on the fourth. */
95 #define UDP_PORT_NBNS 137
96 #define UDP_PORT_NBDGM 138
97 #define TCP_PORT_NBSS 139
98 #define TCP_PORT_CIFS 445
100 /* Packet structure taken from RFC 1002. See also RFC 1001.
101 * Opcode, flags, and rcode treated as "flags", similarly to DNS,
102 * to make it easier to lift the dissection code from "packet-dns.c". */
104 /* Offsets of fields in the NBNS header. */
112 /* Length of NBNS header. */
113 #define NBNS_HDRLEN 12
116 #define T_NB 32 /* NetBIOS name service RR */
117 #define T_NBSTAT 33 /* NetBIOS node status RR */
119 /* Bit fields in the flags */
120 #define F_RESPONSE (1<<15) /* packet is response */
121 #define F_OPCODE (0xF<<11) /* query opcode */
122 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
123 #define F_TRUNCATED (1<<9) /* response is truncated */
124 #define F_RECDESIRED (1<<8) /* recursion desired */
125 #define F_RECAVAIL (1<<7) /* recursion available */
126 #define F_BROADCAST (1<<4) /* broadcast/multicast packet */
127 #define F_RCODE (0xF<<0) /* reply code */
130 #define OPCODE_QUERY (0<<11) /* standard query */
131 #define OPCODE_REGISTRATION (5<<11) /* registration */
132 #define OPCODE_RELEASE (6<<11) /* release name */
133 #define OPCODE_WACK (7<<11) /* wait for acknowledgement */
134 #define OPCODE_REFRESH (8<<11) /* refresh registration */
135 #define OPCODE_REFRESHALT (9<<11) /* refresh registration (alternate opcode) */
136 #define OPCODE_MHREGISTRATION (15<<11) /* multi-homed registration */
139 #define RCODE_NOERROR (0<<0)
140 #define RCODE_FMTERROR (1<<0)
141 #define RCODE_SERVFAIL (2<<0)
142 #define RCODE_NAMEERROR (3<<0)
143 #define RCODE_NOTIMPL (4<<0)
144 #define RCODE_REFUSED (5<<0)
145 #define RCODE_ACTIVE (6<<0)
146 #define RCODE_CONFLICT (7<<0)
148 /* Values for the "NB_FLAGS" field of RR data. From RFC 1001 and 1002,
149 * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
151 #define NB_FLAGS_ONT (3<<(15-2)) /* bits for node type */
152 #define NB_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
153 #define NB_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
154 #define NB_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
155 #define NB_FLAGS_ONT_H_NODE (3<<(15-2)) /* H-mode node */
157 #define NB_FLAGS_G (1<<(15-0)) /* group name */
159 /* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
160 * RR data. From RFC 1001 and 1002, except for NAME_FLAGS_ONT_H_NODE,
161 * which was discovered by looking at packet traces. */
162 #define NAME_FLAGS_PRM (1<<(15-6)) /* name is permanent node name */
164 #define NAME_FLAGS_ACT (1<<(15-5)) /* name is active */
166 #define NAME_FLAGS_CNF (1<<(15-4)) /* name is in conflict */
168 #define NAME_FLAGS_DRG (1<<(15-3)) /* name is being deregistered */
170 #define NAME_FLAGS_ONT (3<<(15-2)) /* bits for node type */
171 #define NAME_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
172 #define NAME_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
173 #define NAME_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
175 #define NAME_FLAGS_G (1<<(15-0)) /* group name */
177 static const value_string opcode_vals[] = {
178 { OPCODE_QUERY, "Name query" },
179 { OPCODE_REGISTRATION, "Registration" },
180 { OPCODE_RELEASE, "Release" },
181 { OPCODE_WACK, "Wait for acknowledgment" },
182 { OPCODE_REFRESH, "Refresh" },
183 { OPCODE_REFRESHALT, "Refresh (alternate opcode)" },
184 { OPCODE_MHREGISTRATION, "Multi-homed registration" },
189 nbns_type_name (int type)
201 #define NBNAME_BUF_LEN 128
204 get_nbns_name(tvbuff_t *tvb, int offset, int nbns_data_offset,
205 char *name_ret, int *name_type_ret)
209 char nbname[NBNAME_BUF_LEN];
210 char *pname, *pnbname, cname, cnbname;
213 name_len = get_dns_name(tvb, offset, nbns_data_offset, name,
216 /* OK, now undo the first-level encoding. */
218 pnbname = &nbname[0];
220 /* Every two characters of the first level-encoded name
221 * turn into one character in the decoded name. */
224 break; /* no more characters */
226 break; /* scope ID follows */
227 if (cname < 'A' || cname > 'Z') {
230 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
234 cnbname = cname << 4;
238 if (cname == '\0' || cname == '.') {
239 /* No more characters in the name - but we're in
240 * the middle of a pair. Not legal. */
242 "Illegal NetBIOS name (odd number of bytes)");
245 if (cname < 'A' || cname > 'Z') {
248 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
255 /* Do we have room to store the character? */
256 if (pnbname < &nbname[NETBIOS_NAME_LEN]) {
257 /* Yes - store the character. */
261 /* We bump the pointer even if it's past the end of the
262 name, so we keep track of how long the name is. */
266 /* NetBIOS names are supposed to be exactly 16 bytes long. */
267 if (pnbname - nbname != NETBIOS_NAME_LEN) {
269 sprintf(nbname, "Illegal NetBIOS name (%ld bytes long)",
270 (long)(pnbname - nbname));
274 /* This one is; make its name printable. */
275 name_type = process_netbios_name(nbname, name_ret);
276 name_ret += strlen(name_ret);
277 sprintf(name_ret, "<%02x>", name_type);
280 /* We have a scope ID, starting at "pname"; append that to
281 * the decoded host name. */
282 strcpy(name_ret, pname);
284 if (name_type_ret != NULL)
285 *name_type_ret = name_type;
289 if (name_type_ret != NULL)
291 strcpy (name_ret, nbname);
297 get_nbns_name_type_class(tvbuff_t *tvb, int offset, int nbns_data_offset,
298 char *name_ret, int *name_len_ret, int *name_type_ret, int *type_ret,
305 name_len = get_nbns_name(tvb, offset, nbns_data_offset, name_ret,
309 type = tvb_get_ntohs(tvb, offset);
312 class = tvb_get_ntohs(tvb, offset);
316 *name_len_ret = name_len;
322 add_name_and_type(proto_tree *tree, tvbuff_t *tvb, int offset, int len,
323 char *tag, char *name, int name_type)
325 if (name_type != -1) {
326 proto_tree_add_text(tree, tvb, offset, len, "%s: %s (%s)",
327 tag, name, netbios_name_type_descr(name_type));
329 proto_tree_add_text(tree, tvb, offset, len, "%s: %s",
335 dissect_nbns_query(tvbuff_t *tvb, int offset, int nbns_data_offset,
336 frame_data *fd, proto_tree *nbns_tree)
339 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
351 data_start = data_offset = offset;
353 len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
354 &name_len, &name_type, &type, &class);
357 type_name = nbns_type_name(type);
358 class_name = dns_class_name(class);
361 col_append_fstr(fd, COL_INFO, " %s %s", type_name, name);
362 if (nbns_tree != NULL) {
363 tq = proto_tree_add_text(nbns_tree, tvb, offset, len,
364 "%s: type %s, class %s", name, type_name, class_name);
365 q_tree = proto_item_add_subtree(tq, ett_nbns_qd);
367 add_name_and_type(q_tree, tvb, offset, name_len, "Name", name,
371 proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", type_name);
374 proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
378 return data_offset - data_start;
382 nbns_add_nbns_flags(proto_tree *nbns_tree, tvbuff_t *tvb, int offset,
383 u_short flags, int is_wack)
386 proto_tree *field_tree;
388 static const value_string rcode_vals[] = {
389 { RCODE_NOERROR, "No error" },
390 { RCODE_FMTERROR, "Request was invalidly formatted" },
391 { RCODE_SERVFAIL, "Server failure" },
392 { RCODE_NAMEERROR, "Requested name does not exist" },
393 { RCODE_NOTIMPL, "Request is not implemented" },
394 { RCODE_REFUSED, "Request was refused" },
395 { RCODE_ACTIVE, "Name is owned by another node" },
396 { RCODE_CONFLICT, "Name is in conflict" },
400 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals,
401 "Unknown operation"));
402 if (flags & F_RESPONSE && !is_wack) {
403 strcat(buf, " response");
405 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
408 tf = proto_tree_add_text(nbns_tree, tvb, offset, 2,
409 "Flags: 0x%04x (%s)", flags, buf);
410 field_tree = proto_item_add_subtree(tf, ett_nbns_flags);
411 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
412 decode_boolean_bitfield(flags, F_RESPONSE,
413 2*8, "Response", "Query"));
414 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
415 decode_enumerated_bitfield(flags, F_OPCODE,
416 2*8, opcode_vals, "%s"));
417 if (flags & F_RESPONSE) {
418 proto_tree_add_text(field_tree, tvb, offset, 2,
420 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
422 "Server is an authority for domain",
423 "Server isn't an authority for domain"));
425 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
426 decode_boolean_bitfield(flags, F_TRUNCATED,
428 "Message is truncated",
429 "Message is not truncated"));
430 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
431 decode_boolean_bitfield(flags, F_RECDESIRED,
433 "Do query recursively",
434 "Don't do query recursively"));
435 if (flags & F_RESPONSE) {
436 proto_tree_add_text(field_tree, tvb, offset, 2,
438 decode_boolean_bitfield(flags, F_RECAVAIL,
440 "Server can do recursive queries",
441 "Server can't do recursive queries"));
443 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
444 decode_boolean_bitfield(flags, F_BROADCAST,
447 "Not a broadcast packet"));
448 if (flags & F_RESPONSE && !is_wack) {
449 proto_tree_add_text(field_tree, tvb, offset, 2,
451 decode_enumerated_bitfield(flags, F_RCODE,
458 nbns_add_nb_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset, u_short flags)
461 proto_tree *field_tree;
463 static const value_string nb_flags_ont_vals[] = {
464 { NB_FLAGS_ONT_B_NODE, "B-node" },
465 { NB_FLAGS_ONT_P_NODE, "P-node" },
466 { NB_FLAGS_ONT_M_NODE, "M-node" },
467 { NB_FLAGS_ONT_H_NODE, "H-node" },
471 strcpy(buf, val_to_str(flags & NB_FLAGS_ONT, nb_flags_ont_vals,
474 if (flags & NB_FLAGS_G)
475 strcat(buf, "group");
477 strcat(buf, "unique");
478 tf = proto_tree_add_text(rr_tree, tvb, offset, 2, "Flags: 0x%x (%s)", flags,
480 field_tree = proto_item_add_subtree(tf, ett_nbns_nb_flags);
481 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
482 decode_boolean_bitfield(flags, NB_FLAGS_G,
486 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
487 decode_enumerated_bitfield(flags, NB_FLAGS_ONT,
488 2*8, nb_flags_ont_vals, "%s"));
492 nbns_add_name_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset,
496 proto_item *field_tree;
498 static const value_string name_flags_ont_vals[] = {
499 { NAME_FLAGS_ONT_B_NODE, "B-node" },
500 { NAME_FLAGS_ONT_P_NODE, "P-node" },
501 { NAME_FLAGS_ONT_M_NODE, "M-node" },
505 strcpy(buf, val_to_str(flags & NAME_FLAGS_ONT, name_flags_ont_vals,
508 if (flags & NAME_FLAGS_G)
509 strcat(buf, "group");
511 strcat(buf, "unique");
512 if (flags & NAME_FLAGS_DRG)
513 strcat(buf, ", being deregistered");
514 if (flags & NAME_FLAGS_CNF)
515 strcat(buf, ", in conflict");
516 if (flags & NAME_FLAGS_ACT)
517 strcat(buf, ", active");
518 if (flags & NAME_FLAGS_PRM)
519 strcat(buf, ", permanent node name");
520 tf = proto_tree_add_text(rr_tree, tvb, offset, 2, "Name flags: 0x%x (%s)",
522 field_tree = proto_item_add_subtree(tf, ett_nbns_name_flags);
523 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
524 decode_boolean_bitfield(flags, NAME_FLAGS_G,
528 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
529 decode_enumerated_bitfield(flags, NAME_FLAGS_ONT,
530 2*8, name_flags_ont_vals, "%s"));
531 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
532 decode_boolean_bitfield(flags, NAME_FLAGS_DRG,
534 "Name is being deregistered",
535 "Name is not being deregistered"));
536 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
537 decode_boolean_bitfield(flags, NAME_FLAGS_CNF,
539 "Name is in conflict",
540 "Name is not in conflict"));
541 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
542 decode_boolean_bitfield(flags, NAME_FLAGS_ACT,
545 "Name is not active"));
546 proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
547 decode_boolean_bitfield(flags, NAME_FLAGS_PRM,
549 "Permanent node name",
550 "Not permanent node name"));
554 dissect_nbns_answer(tvbuff_t *tvb, int offset, int nbns_data_offset,
555 frame_data *fd, proto_tree *nbns_tree, int opcode)
558 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME + 64];
573 char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
575 char nbname[16+4+1]; /* 4 for [<last char>] */
578 data_start = data_offset = offset;
581 len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
582 &name_len, &name_type, &type, &class);
586 type_name = nbns_type_name(type);
587 class_name = dns_class_name(class);
589 ttl = tvb_get_ntohl(tvb, data_offset);
593 data_len = tvb_get_ntohs(tvb, data_offset);
598 case T_NB: /* "NB" record */
600 if (opcode != OPCODE_WACK) {
601 col_append_fstr(fd, COL_INFO, " %s %s",
603 ip_to_str(tvb_get_ptr(tvb, data_offset+2, 4)));
606 if (nbns_tree == NULL)
608 trr = proto_tree_add_text(nbns_tree, tvb, offset,
609 (data_offset - data_start) + data_len,
610 "%s: type %s, class %s",
611 name, type_name, class_name);
613 strcat(name, netbios_name_type_descr(name_type));
615 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
616 name_len, type_name, class_name, ttl, data_len);
617 while (data_len > 0) {
618 if (opcode == OPCODE_WACK) {
619 /* WACK response. This doesn't contain the
620 * same type of RR data as other T_NB
623 proto_tree_add_text(rr_tree, tvb, cur_offset,
624 data_len, "(incomplete entry)");
627 flags = tvb_get_ntohs(tvb, cur_offset);
628 nbns_add_nbns_flags(rr_tree, tvb, cur_offset,
634 proto_tree_add_text(rr_tree, tvb, cur_offset,
635 data_len, "(incomplete entry)");
638 flags = tvb_get_ntohs(tvb, cur_offset);
639 nbns_add_nb_flags(rr_tree, tvb, cur_offset,
645 proto_tree_add_text(rr_tree, tvb, cur_offset,
646 data_len, "(incomplete entry)");
649 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
651 ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
658 case T_NBSTAT: /* "NBSTAT" record */
660 col_append_fstr(fd, COL_INFO, " %s", type_name);
661 if (nbns_tree == NULL)
663 trr = proto_tree_add_text(nbns_tree, tvb, offset,
664 (data_offset - data_start) + data_len,
665 "%s: type %s, class %s",
666 name, type_name, class_name);
667 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
668 name_len, type_name, class_name, ttl, data_len);
670 proto_tree_add_text(rr_tree, tvb, cur_offset,
671 data_len, "(incomplete entry)");
674 num_names = tvb_get_guint8(tvb, cur_offset);
675 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
676 "Number of names: %u", num_names);
679 while (num_names != 0) {
680 if (data_len < NETBIOS_NAME_LEN) {
681 proto_tree_add_text(rr_tree, tvb, cur_offset,
682 data_len, "(incomplete entry)");
685 tvb_memcpy(tvb, (guint8 *)nbname, cur_offset,
687 name_type = process_netbios_name(nbname,
689 proto_tree_add_text(rr_tree, tvb, cur_offset,
690 NETBIOS_NAME_LEN, "Name: %s<%02x> (%s)",
692 netbios_name_type_descr(name_type));
693 cur_offset += NETBIOS_NAME_LEN;
694 data_len -= NETBIOS_NAME_LEN;
697 proto_tree_add_text(rr_tree, tvb, cur_offset,
698 data_len, "(incomplete entry)");
701 name_flags = tvb_get_ntohs(tvb, cur_offset);
702 nbns_add_name_flags(rr_tree, tvb, cur_offset,
711 proto_tree_add_text(rr_tree, tvb, cur_offset,
712 data_len, "(incomplete entry)");
715 proto_tree_add_text(rr_tree, tvb, cur_offset, 6,
717 ether_to_str(tvb_get_ptr(tvb, cur_offset, 6)));
722 proto_tree_add_text(rr_tree, tvb, cur_offset,
723 data_len, "(incomplete entry)");
726 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
727 "Jumpers: 0x%x", tvb_get_guint8(tvb, cur_offset));
732 proto_tree_add_text(rr_tree, tvb, cur_offset,
733 data_len, "(incomplete entry)");
736 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
737 "Test result: 0x%x", tvb_get_guint8(tvb, cur_offset));
742 proto_tree_add_text(rr_tree, tvb, cur_offset,
743 data_len, "(incomplete entry)");
746 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
747 "Version number: 0x%x", tvb_get_ntohs(tvb, cur_offset));
752 proto_tree_add_text(rr_tree, tvb, cur_offset,
753 data_len, "(incomplete entry)");
756 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
757 "Period of statistics: 0x%x",
758 tvb_get_ntohs(tvb, cur_offset));
763 proto_tree_add_text(rr_tree, tvb, cur_offset,
764 data_len, "(incomplete entry)");
767 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
768 "Number of CRCs: %u", tvb_get_ntohs(tvb, cur_offset));
773 proto_tree_add_text(rr_tree, tvb, cur_offset,
774 data_len, "(incomplete entry)");
777 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
778 "Number of alignment errors: %u",
779 tvb_get_ntohs(tvb, cur_offset));
784 proto_tree_add_text(rr_tree, tvb, cur_offset,
785 data_len, "(incomplete entry)");
788 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
789 "Number of collisions: %u", tvb_get_ntohs(tvb, cur_offset));
794 proto_tree_add_text(rr_tree, tvb, cur_offset,
795 data_len, "(incomplete entry)");
798 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
799 "Number of send aborts: %u", tvb_get_ntohs(tvb, cur_offset));
804 proto_tree_add_text(rr_tree, tvb, cur_offset,
805 data_len, "(incomplete entry)");
808 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
809 "Number of good sends: %u", tvb_get_ntohl(tvb, cur_offset));
814 proto_tree_add_text(rr_tree, tvb, cur_offset,
815 data_len, "(incomplete entry)");
818 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
819 "Number of good receives: %u",
820 tvb_get_ntohl(tvb, cur_offset));
825 proto_tree_add_text(rr_tree, tvb, cur_offset,
826 data_len, "(incomplete entry)");
829 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
830 "Number of retransmits: %u", tvb_get_ntohs(tvb, cur_offset));
835 proto_tree_add_text(rr_tree, tvb, cur_offset,
836 data_len, "(incomplete entry)");
839 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
840 "Number of no resource conditions: %u",
841 tvb_get_ntohs(tvb, cur_offset));
846 proto_tree_add_text(rr_tree, tvb, cur_offset,
847 data_len, "(incomplete entry)");
850 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
851 "Number of command blocks: %u",
852 tvb_get_ntohs(tvb, cur_offset));
857 proto_tree_add_text(rr_tree, tvb, cur_offset,
858 data_len, "(incomplete entry)");
861 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
862 "Number of pending sessions: %u",
863 tvb_get_ntohs(tvb, cur_offset));
868 proto_tree_add_text(rr_tree, tvb, cur_offset,
869 data_len, "(incomplete entry)");
872 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
873 "Max number of pending sessions: %u",
874 tvb_get_ntohs(tvb, cur_offset));
879 proto_tree_add_text(rr_tree, tvb, cur_offset,
880 data_len, "(incomplete entry)");
883 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
884 "Max total sessions possible: %u",
885 tvb_get_ntohs(tvb, cur_offset));
890 proto_tree_add_text(rr_tree, tvb, cur_offset,
891 data_len, "(incomplete entry)");
894 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
895 "Session data packet size: %u",
896 tvb_get_ntohs(tvb, cur_offset));
904 col_append_fstr(fd, COL_INFO, " %s", type_name);
905 if (nbns_tree == NULL)
907 trr = proto_tree_add_text(nbns_tree, tvb, offset,
908 (data_offset - data_start) + data_len,
909 "%s: type %s, class %s",
910 name, type_name, class_name);
911 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
912 name_len, type_name, class_name, ttl, data_len);
913 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
914 cur_offset += data_len;
918 return cur_offset - data_start;
922 dissect_query_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
923 int count, frame_data *fd, proto_tree *nbns_tree)
925 int start_off, add_off;
926 proto_tree *qatree = NULL;
927 proto_item *ti = NULL;
930 if (nbns_tree != NULL) {
931 ti = proto_tree_add_text(nbns_tree, tvb, start_off, 0, "Queries");
932 qatree = proto_item_add_subtree(ti, ett_nbns_qry);
934 while (count-- > 0) {
935 add_off = dissect_nbns_query(tvb, cur_off, nbns_data_offset,
938 /* We ran past the end of the captured data in the
945 proto_item_set_len(ti, cur_off - start_off);
947 return cur_off - start_off;
953 dissect_answer_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
954 int count, frame_data *fd, proto_tree *nbns_tree, int opcode, char *name)
956 int start_off, add_off;
957 proto_tree *qatree = NULL;
958 proto_item *ti = NULL;
961 if (nbns_tree != NULL) {
962 ti = proto_tree_add_text(nbns_tree, tvb, start_off, 0, name);
963 qatree = proto_item_add_subtree(ti, ett_nbns_ans);
965 while (count-- > 0) {
966 add_off = dissect_nbns_answer(tvb, cur_off, nbns_data_offset,
969 /* We ran past the end of the captured data in the
976 proto_item_set_len(ti, cur_off - start_off);
977 return cur_off - start_off;
981 dissect_nbns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
984 int nbns_data_offset;
986 proto_tree *nbns_tree = NULL;
988 guint16 id, flags, quest, ans, auth, add;
991 nbns_data_offset = offset;
993 if (check_col(pinfo->fd, COL_PROTOCOL))
994 col_set_str(pinfo->fd, COL_PROTOCOL, "NBNS");
995 if (check_col(pinfo->fd, COL_INFO))
996 col_clear(pinfo->fd, COL_INFO);
998 /* To do: check for runts, errs, etc. */
999 id = tvb_get_ntohs(tvb, offset + NBNS_ID);
1000 flags = tvb_get_ntohs(tvb, offset + NBNS_FLAGS);
1002 if (check_col(pinfo->fd, COL_INFO)) {
1003 col_add_fstr(pinfo->fd, COL_INFO, "%s%s",
1004 val_to_str(flags & F_OPCODE, opcode_vals,
1005 "Unknown operation (%x)"),
1006 (flags & F_RESPONSE) ? " response" : "");
1009 /* Set "fd" to NULL; we pass a NULL "fd" to the query and
1010 answer dissectors, as a way of saying that they shouldn't
1011 add stuff to the COL_INFO column (a call to
1012 "check_col(fd, COL_INFO)" is more expensive than a check
1013 that a pointer isn't NULL). */
1018 ti = proto_tree_add_item(tree, proto_nbns, tvb, offset,
1019 tvb_length(tvb), FALSE);
1020 nbns_tree = proto_item_add_subtree(ti, ett_nbns);
1022 if (flags & F_RESPONSE) {
1023 proto_tree_add_boolean_hidden(nbns_tree, hf_nbns_response, tvb,
1026 proto_tree_add_boolean_hidden(nbns_tree, hf_nbns_query, tvb,
1030 proto_tree_add_uint(nbns_tree, hf_nbns_transaction_id, tvb,
1031 offset + NBNS_ID, 2, id);
1033 nbns_add_nbns_flags(nbns_tree, tvb, offset + NBNS_FLAGS,
1036 quest = tvb_get_ntohs(tvb, offset + NBNS_QUEST);
1038 proto_tree_add_uint(nbns_tree, hf_nbns_count_questions, tvb,
1039 offset + NBNS_QUEST, 2, quest);
1041 ans = tvb_get_ntohs(tvb, offset + NBNS_ANS);
1043 proto_tree_add_uint(nbns_tree, hf_nbns_count_answers, tvb,
1044 offset + NBNS_ANS, 2, ans);
1046 auth = tvb_get_ntohs(tvb, offset + NBNS_AUTH);
1048 proto_tree_add_uint(nbns_tree, hf_nbns_count_auth_rr, tvb,
1049 offset + NBNS_AUTH, 2, auth);
1051 add = tvb_get_ntohs(tvb, offset + NBNS_ADD);
1053 proto_tree_add_uint(nbns_tree, hf_nbns_count_add_rr, tvb,
1054 offset + NBNS_ADD, 2, add);
1057 cur_off = offset + NBNS_HDRLEN;
1060 /* If this is a response, don't add information about the
1061 queries to the summary, just add information about the
1063 cur_off += dissect_query_records(tvb, cur_off,
1064 nbns_data_offset, quest,
1065 (!(flags & F_RESPONSE) ? fd : NULL), nbns_tree);
1069 /* If this is a request, don't add information about the
1070 answers to the summary, just add information about the
1072 cur_off += dissect_answer_records(tvb, cur_off,
1073 nbns_data_offset, ans,
1074 ((flags & F_RESPONSE) ? fd : NULL), nbns_tree,
1075 flags & F_OPCODE, "Answers");
1079 /* Don't add information about the authoritative name
1080 servers, or the additional records, to the summary. */
1082 cur_off += dissect_answer_records(tvb, cur_off,
1084 auth, NULL, nbns_tree,
1086 "Authoritative nameservers");
1089 cur_off += dissect_answer_records(tvb, cur_off,
1091 add, NULL, nbns_tree,
1093 "Additional records");
1097 /* NetBIOS datagram packet, from RFC 1002, page 32 */
1098 struct nbdgm_header {
1109 /* For packets with data */
1113 /* For error packets */
1118 * NBDS message types.
1120 #define NBDS_DIRECT_UNIQUE 0x10
1121 #define NBDS_DIRECT_GROUP 0x11
1122 #define NBDS_BROADCAST 0x12
1123 #define NBDS_ERROR 0x13
1124 #define NBDS_QUERY_REQUEST 0x14
1125 #define NBDS_POS_QUERY_RESPONSE 0x15
1126 #define NBDS_NEG_QUERY_RESPONSE 0x16
1128 static const value_string nbds_msgtype_vals[] = {
1129 { NBDS_DIRECT_UNIQUE, "Direct_unique datagram" },
1130 { NBDS_DIRECT_GROUP, "Direct_group datagram" },
1131 { NBDS_BROADCAST, "Broadcast datagram" },
1132 { NBDS_ERROR, "Datagram error" },
1133 { NBDS_QUERY_REQUEST, "Datagram query request" },
1134 { NBDS_POS_QUERY_RESPONSE, "Datagram positive query response" },
1135 { NBDS_NEG_QUERY_RESPONSE, "Datagram negative query response" },
1139 static const true_false_string yesno = {
1144 static const value_string node_type_vals[] = {
1153 dissect_nbdgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1156 proto_tree *nbdgm_tree = NULL;
1157 proto_item *ti = NULL;
1158 struct nbdgm_header header;
1162 int max_data = tvb_length_remaining(tvb, offset);
1165 static const value_string error_codes[] = {
1166 { 0x82, "Destination name not present" },
1167 { 0x83, "Invalid source name format" },
1168 { 0x84, "Invalid destination name format" },
1172 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1176 if (check_col(pinfo->fd, COL_PROTOCOL))
1177 col_set_str(pinfo->fd, COL_PROTOCOL, "NBDS");
1178 if (check_col(pinfo->fd, COL_INFO))
1179 col_clear(pinfo->fd, COL_INFO);
1181 header.msg_type = tvb_get_guint8(tvb, offset);
1183 flags = tvb_get_guint8(tvb, offset+1);
1184 header.flags.more = flags & 1;
1185 header.flags.first = (flags & 2) >> 1;
1186 header.flags.node_type = (flags & 12) >> 2;
1188 header.dgm_id = tvb_get_ntohs(tvb, offset+2);
1189 tvb_memcpy(tvb, (guint8 *)&header.src_ip, offset+4, 4);
1190 header.src_port = tvb_get_ntohs(tvb, offset+8);
1192 switch (header.msg_type) {
1194 case NBDS_DIRECT_UNIQUE:
1195 case NBDS_DIRECT_GROUP:
1196 case NBDS_BROADCAST:
1197 header.dgm_length = tvb_get_ntohs(tvb, offset+10);
1198 header.pkt_offset = tvb_get_ntohs(tvb, offset+12);
1202 header.error_code = tvb_get_ntohs(tvb, offset+10);
1206 message_index = header.msg_type - 0x0f;
1207 if (message_index < 1 || message_index > 8) {
1211 if (check_col(pinfo->fd, COL_INFO)) {
1212 col_add_str(pinfo->fd, COL_INFO,
1213 val_to_str(header.msg_type, nbds_msgtype_vals,
1214 "Unknown message type (0x%02X)"));
1218 ti = proto_tree_add_item(tree, proto_nbdgm, tvb, offset,
1219 tvb_length_remaining(tvb, offset), FALSE);
1220 nbdgm_tree = proto_item_add_subtree(ti, ett_nbdgm);
1222 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_type, tvb,
1225 proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_fragment, tvb,
1228 proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_first, tvb,
1230 header.flags.first);
1231 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_node_type, tvb,
1233 header.flags.node_type);
1235 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_datagram_id, tvb,
1236 offset+2, 2, header.dgm_id);
1237 proto_tree_add_ipv4(nbdgm_tree, hf_nbdgm_src_ip, tvb,
1238 offset+4, 4, header.src_ip);
1239 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_src_port, tvb,
1240 offset+8, 2, header.src_port);
1247 switch (header.msg_type) {
1249 case NBDS_DIRECT_UNIQUE:
1250 case NBDS_DIRECT_GROUP:
1251 case NBDS_BROADCAST:
1253 proto_tree_add_text(nbdgm_tree, tvb, offset, 2,
1254 "Datagram length: %d bytes", header.dgm_length);
1255 proto_tree_add_text(nbdgm_tree, tvb, offset+2, 2,
1256 "Packet offset: %d bytes", header.pkt_offset);
1263 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1266 add_name_and_type(nbdgm_tree, tvb, offset, len,
1267 "Source name", name, name_type);
1272 /* Destination name */
1273 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1276 add_name_and_type(nbdgm_tree, tvb, offset, len,
1277 "Destination name", name, name_type);
1283 * Here we can pass the packet off to the next protocol.
1284 * Set the length of our top-level tree item to include
1287 proto_item_set_len(ti, offset);
1289 const guint8 *next_pd;
1292 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1293 tvb_compat(next_tvb, &next_pd, &next_offset);
1295 dissect_smb(next_pd, next_offset, pinfo->fd, tree,
1302 proto_tree_add_text(nbdgm_tree, tvb, offset, 1, "Error code: %s",
1303 val_to_str(header.error_code, error_codes, "Unknown (0x%x)"));
1306 proto_item_set_len(ti, offset);
1309 case NBDS_QUERY_REQUEST:
1310 case NBDS_POS_QUERY_RESPONSE:
1311 case NBDS_NEG_QUERY_RESPONSE:
1312 /* Destination name */
1313 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1316 add_name_and_type(nbdgm_tree, tvb, offset, len,
1317 "Destination name", name, name_type);
1320 proto_item_set_len(ti, offset);
1326 * NetBIOS Session Service message types.
1328 #define SESSION_MESSAGE 0x00
1329 #define SESSION_REQUEST 0x81
1330 #define POSITIVE_SESSION_RESPONSE 0x82
1331 #define NEGATIVE_SESSION_RESPONSE 0x83
1332 #define RETARGET_SESSION_RESPONSE 0x84
1333 #define SESSION_KEEP_ALIVE 0x85
1335 static const value_string message_types[] = {
1336 { SESSION_MESSAGE, "Session message" },
1337 { SESSION_REQUEST, "Session request" },
1338 { POSITIVE_SESSION_RESPONSE, "Positive session response" },
1339 { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
1340 { RETARGET_SESSION_RESPONSE, "Retarget session response" },
1341 { SESSION_KEEP_ALIVE, "Session keep-alive" },
1346 * NetBIOS Session Service flags.
1348 #define NBSS_FLAGS_E 0x1
1350 static const value_string error_codes[] = {
1351 { 0x80, "Not listening on called name" },
1352 { 0x81, "Not listening for called name" },
1353 { 0x82, "Called name not present" },
1354 { 0x83, "Called name present, but insufficient resources" },
1355 { 0x8F, "Unspecified error" },
1360 * Dissect a single NBSS packet (there may be more than one in a given
1363 * [ Hmmm, in my experience, I have never seen more than one NBSS in a
1364 * single segment, since they mostly contain SMBs which are essentially
1365 * a request response type protocol (RJS). ]
1367 * [ However, under heavy load with many requests multiplexed on one
1368 * session it is not unusual to see multiple requests in one TCP
1369 * segment. Unfortunately, in this case a single session message is
1370 * frequently split over multiple segments, which frustrates decoding
1374 dissect_nbss_packet(tvbuff_t *tvb, int offset, packet_info *pinfo,
1375 proto_tree *tree, int max_data, int is_cifs)
1377 proto_tree *nbss_tree = NULL;
1378 proto_item *ti = NULL;
1379 proto_tree *field_tree;
1385 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1389 msg_type = tvb_get_guint8(tvb, offset);
1393 length = tvb_get_ntoh24(tvb, offset + 1);
1395 flags = tvb_get_guint8(tvb, offset + 1);
1396 length = tvb_get_ntohs(tvb, offset + 2);
1397 if (flags & NBSS_FLAGS_E)
1402 if (nbss_desegment) {
1403 if (pinfo->can_desegment
1404 && length > tvb_length_remaining(tvb, offset+4)) {
1406 * This frame doesn't have all of the data for
1407 * this message, but we can do reassembly on it.
1409 * Tell the TCP dissector where the data for this
1410 * message starts in the data it handed us, and
1411 * how many more bytes we need, and return.
1413 pinfo->desegment_offset = offset;
1414 pinfo->desegment_len =
1415 length - tvb_length_remaining(tvb, offset+4);
1421 ti = proto_tree_add_item(tree, proto_nbss, tvb, offset, length + 4, FALSE);
1422 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1424 proto_tree_add_uint_format(nbss_tree, hf_nbss_type, tvb,
1428 val_to_str(msg_type, message_types,
1436 proto_tree_add_text(nbss_tree, tvb, offset, 3, "Length: %u", length);
1441 tf = proto_tree_add_uint(nbss_tree, hf_nbss_flags, tvb, offset, 1, flags);
1442 field_tree = proto_item_add_subtree(tf, ett_nbss_flags);
1443 proto_tree_add_text(field_tree, tvb, offset, 1, "%s",
1444 decode_boolean_bitfield(flags, NBSS_FLAGS_E,
1445 8, "Add 65536 to length", "Add 0 to length"));
1450 proto_tree_add_text(nbss_tree, tvb, offset, 2, "Length: %u", length);
1458 case SESSION_REQUEST:
1459 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1461 add_name_and_type(nbss_tree, tvb, offset, len,
1462 "Called name", name, name_type);
1465 len = get_nbns_name(tvb, offset, offset, name, &name_type);
1468 add_name_and_type(nbss_tree, tvb, offset, len,
1469 "Calling name", name, name_type);
1473 case NEGATIVE_SESSION_RESPONSE:
1475 proto_tree_add_text(nbss_tree, tvb, offset, 1,
1477 val_to_str(tvb_get_guint8(tvb, offset),
1478 error_codes, "Unknown (%x)"));
1481 case RETARGET_SESSION_RESPONSE:
1483 proto_tree_add_text(nbss_tree, tvb, offset, 4,
1484 "Retarget IP address: %s",
1485 ip_to_str(tvb_get_ptr(tvb, offset, 4)));
1490 proto_tree_add_text(nbss_tree, tvb, offset, 2,
1491 "Retarget port: %u",
1492 tvb_get_ntohs(tvb, offset));
1496 case SESSION_MESSAGE:
1498 * Here we can pass the packet off to the next protocol.
1499 * Set the length of our top-level tree item to include
1502 proto_item_set_len(ti, offset);
1504 const guint8 *next_pd;
1507 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1508 tvb_compat(next_tvb, &next_pd, &next_offset);
1510 dissect_smb(next_pd, next_offset, pinfo->fd, tree,
1520 dissect_nbss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1528 if (check_col(pinfo->fd, COL_PROTOCOL))
1529 col_set_str(pinfo->fd, COL_PROTOCOL, "NBSS");
1530 if (check_col(pinfo->fd, COL_INFO))
1531 col_clear(pinfo->fd, COL_INFO);
1533 msg_type = tvb_get_guint8(tvb, offset);
1536 * XXX - we should set this based on both the length remaining
1539 max_data = tvb_length_remaining(tvb, offset);
1541 if (pinfo->match_port == TCP_PORT_CIFS) {
1543 * Windows 2000 CIFS clients can dispense completely
1544 * with the NETBIOS encapsulation and directly use CIFS
1545 * over TCP. As would be expected, the framing is
1546 * identical, except that the length is 24 bits instead
1547 * of 17. The only message types used are
1548 * SESSION_MESSAGE and SESSION_KEEP_ALIVE.
1555 /* Hmmm, it may be a continuation message ... */
1559 if (((msg_type != SESSION_REQUEST) &&
1560 (msg_type != POSITIVE_SESSION_RESPONSE) &&
1561 (msg_type != NEGATIVE_SESSION_RESPONSE) &&
1562 (msg_type != RETARGET_SESSION_RESPONSE) &&
1563 (msg_type != SESSION_KEEP_ALIVE) &&
1564 (msg_type != SESSION_MESSAGE)) ||
1565 ((msg_type == SESSION_MESSAGE) &&
1566 (max_data < 8 || tvb_memeql(tvb, offset + 4, "\377SMB", 4) != 0))) {
1569 * Either the first byte isn't one of the known message types,
1570 * or it's a session message but we either don't have enough
1571 * data in the frame for the NBSS/CIFS header plus an SMB header,
1572 * or we do but the message data doesn't begin with 0xFF S M B.
1573 * Assume it's a continuation message.
1575 if (check_col(pinfo->fd, COL_INFO)) {
1576 col_add_fstr(pinfo->fd, COL_INFO, "NBSS Continuation Message");
1580 proto_tree_add_text(tree, tvb, offset, max_data, "Continuation data");
1586 if (check_col(pinfo->fd, COL_INFO)) {
1587 col_add_fstr(pinfo->fd, COL_INFO,
1588 val_to_str(msg_type, message_types, "Unknown (%x)"));
1591 while (max_data > 0) {
1592 len = dissect_nbss_packet(tvb, offset, pinfo, tree, max_data,
1600 proto_register_nbt(void)
1603 static hf_register_info hf_nbns[] = {
1604 { &hf_nbns_response,
1605 { "Response", "nbns.response",
1606 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1607 "TRUE if NBNS response", HFILL }},
1609 { "Query", "nbns.query",
1610 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1611 "TRUE if NBNS query", HFILL }},
1612 { &hf_nbns_transaction_id,
1613 { "Transaction ID", "nbns.id",
1614 FT_UINT16, BASE_HEX, NULL, 0x0,
1615 "Identification of transaction", HFILL }},
1616 { &hf_nbns_count_questions,
1617 { "Questions", "nbns.count.queries",
1618 FT_UINT16, BASE_DEC, NULL, 0x0,
1619 "Number of queries in packet", HFILL }},
1620 { &hf_nbns_count_answers,
1621 { "Answer RRs", "nbns.count.answers",
1622 FT_UINT16, BASE_DEC, NULL, 0x0,
1623 "Number of answers in packet", HFILL }},
1624 { &hf_nbns_count_auth_rr,
1625 { "Authority RRs", "nbns.count.auth_rr",
1626 FT_UINT16, BASE_DEC, NULL, 0x0,
1627 "Number of authoritative records in packet", HFILL }},
1628 { &hf_nbns_count_add_rr,
1629 { "Additional RRs", "nbns.count.add_rr",
1630 FT_UINT16, BASE_DEC, NULL, 0x0,
1631 "Number of additional records in packet", HFILL }}
1634 static hf_register_info hf_nbdgm[] = {
1636 { "Message Type", "nbdgm.type",
1637 FT_UINT8, BASE_DEC, VALS(nbds_msgtype_vals), 0x0,
1638 "NBDGM message type", HFILL }},
1639 { &hf_nbdgm_fragment,
1640 { "More fragments follow", "nbdgm.next",
1641 FT_BOOLEAN, BASE_NONE, TFS(&yesno), 0x0,
1642 "TRUE if more fragments follow", HFILL }},
1644 { "This is first fragment", "nbdgm.first",
1645 FT_BOOLEAN, BASE_NONE, TFS(&yesno), 0x0,
1646 "TRUE if first fragment", HFILL }},
1647 { &hf_nbdgm_node_type,
1648 { "Node Type", "nbdgm.node_type",
1649 FT_UINT8, BASE_DEC, VALS(node_type_vals), 0x0,
1650 "Node type", HFILL }},
1651 { &hf_nbdgm_datagram_id,
1652 { "Datagram ID", "nbdgm.dgram_id",
1653 FT_UINT16, BASE_HEX, NULL, 0x0,
1654 "Datagram identifier", HFILL }},
1656 { "Source IP", "nbdgm.src.ip",
1657 FT_IPv4, BASE_NONE, NULL, 0x0,
1658 "Source IPv4 address", HFILL }},
1659 { &hf_nbdgm_src_port,
1660 { "Source Port", "nbdgm.src.port",
1661 FT_UINT16, BASE_DEC, NULL, 0x0,
1662 "Source port", HFILL }}
1665 static hf_register_info hf_nbss[] = {
1667 { "Message Type", "nbss.type",
1668 FT_UINT8, BASE_DEC, NULL, 0x0,
1669 "NBSS message type", HFILL }},
1671 { "Flags", "nbss.flags",
1672 FT_UINT8, BASE_HEX, NULL, 0x0,
1673 "NBSS message flags", HFILL }}
1675 static gint *ett[] = {
1680 &ett_nbns_name_flags,
1688 module_t *nbss_module;
1690 proto_nbns = proto_register_protocol("NetBIOS Name Service", "NBNS", "nbns");
1691 proto_register_field_array(proto_nbns, hf_nbns, array_length(hf_nbns));
1693 proto_nbdgm = proto_register_protocol("NetBIOS Datagram Service",
1695 proto_register_field_array(proto_nbdgm, hf_nbdgm, array_length(hf_nbdgm));
1697 proto_nbss = proto_register_protocol("NetBIOS Session Service",
1699 proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));
1701 proto_register_subtree_array(ett, array_length(ett));
1703 nbss_module = prefs_register_protocol(proto_nbss, NULL);
1704 prefs_register_bool_preference(nbss_module, "desegment_nbss_commands",
1705 "Desegment all NBSS commands spanning multiple TCP segments",
1706 "Whether NBSS dissector should desegment all commands spanning multiple TCP segments",
1711 proto_reg_handoff_nbt(void)
1713 dissector_add("udp.port", UDP_PORT_NBNS, dissect_nbns, proto_nbns);
1714 dissector_add("udp.port", UDP_PORT_NBDGM, dissect_nbdgm, proto_nbdgm);
1715 dissector_add("tcp.port", TCP_PORT_NBSS, dissect_nbss, proto_nbss);
1716 dissector_add("tcp.port", TCP_PORT_CIFS, dissect_nbss, proto_nbss);