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.51 2001/01/22 08:03:45 guy Exp $
9 * Ethereal - Network traffic analyzer
10 * By Gerald Combs <gerald@zing.org>
11 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
42 #include "packet-dns.h"
43 #include "packet-netbios.h"
44 #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 /* See RFC 1001 and 1002 for information on the first three, and see
84 http://www.cifs.com/specs/draft-leach-cifs-v1-spec-01.txt
86 Appendix B, and various messages on the CIFS mailing list such as
88 http://discuss.microsoft.com/SCRIPTS/WA-MSD.EXE?A2=ind9811A&L=cifs&P=R386
90 for information on the fourth. */
91 #define UDP_PORT_NBNS 137
92 #define UDP_PORT_NBDGM 138
93 #define TCP_PORT_NBSS 139
94 #define TCP_PORT_CIFS 445
96 /* Packet structure taken from RFC 1002. See also RFC 1001.
97 * Opcode, flags, and rcode treated as "flags", similarly to DNS,
98 * to make it easier to lift the dissection code from "packet-dns.c". */
100 /* Offsets of fields in the NBNS header. */
108 /* Length of NBNS header. */
109 #define NBNS_HDRLEN 12
112 #define T_NB 32 /* NetBIOS name service RR */
113 #define T_NBSTAT 33 /* NetBIOS node status RR */
115 /* Bit fields in the flags */
116 #define F_RESPONSE (1<<15) /* packet is response */
117 #define F_OPCODE (0xF<<11) /* query opcode */
118 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
119 #define F_TRUNCATED (1<<9) /* response is truncated */
120 #define F_RECDESIRED (1<<8) /* recursion desired */
121 #define F_RECAVAIL (1<<7) /* recursion available */
122 #define F_BROADCAST (1<<4) /* broadcast/multicast packet */
123 #define F_RCODE (0xF<<0) /* reply code */
126 #define OPCODE_QUERY (0<<11) /* standard query */
127 #define OPCODE_REGISTRATION (5<<11) /* registration */
128 #define OPCODE_RELEASE (6<<11) /* release name */
129 #define OPCODE_WACK (7<<11) /* wait for acknowledgement */
130 #define OPCODE_REFRESH (8<<11) /* refresh registration */
131 #define OPCODE_REFRESHALT (9<<11) /* refresh registration (alternate opcode) */
132 #define OPCODE_MHREGISTRATION (15<<11) /* multi-homed registration */
135 #define RCODE_NOERROR (0<<0)
136 #define RCODE_FMTERROR (1<<0)
137 #define RCODE_SERVFAIL (2<<0)
138 #define RCODE_NAMEERROR (3<<0)
139 #define RCODE_NOTIMPL (4<<0)
140 #define RCODE_REFUSED (5<<0)
141 #define RCODE_ACTIVE (6<<0)
142 #define RCODE_CONFLICT (7<<0)
144 /* Values for the "NB_FLAGS" field of RR data. From RFC 1001 and 1002,
145 * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
147 #define NB_FLAGS_ONT (3<<(15-2)) /* bits for node type */
148 #define NB_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
149 #define NB_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
150 #define NB_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
151 #define NB_FLAGS_ONT_H_NODE (3<<(15-2)) /* H-mode node */
153 #define NB_FLAGS_G (1<<(15-0)) /* group name */
155 /* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
156 * RR data. From RFC 1001 and 1002, except for NAME_FLAGS_ONT_H_NODE,
157 * which was discovered by looking at packet traces. */
158 #define NAME_FLAGS_PRM (1<<(15-6)) /* name is permanent node name */
160 #define NAME_FLAGS_ACT (1<<(15-5)) /* name is active */
162 #define NAME_FLAGS_CNF (1<<(15-4)) /* name is in conflict */
164 #define NAME_FLAGS_DRG (1<<(15-3)) /* name is being deregistered */
166 #define NAME_FLAGS_ONT (3<<(15-2)) /* bits for node type */
167 #define NAME_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
168 #define NAME_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
169 #define NAME_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
171 #define NAME_FLAGS_G (1<<(15-0)) /* group name */
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 nbns_type_name (int type)
197 #define NBNAME_BUF_LEN 128
200 get_nbns_name(const u_char *pd, int offset, int nbns_data_offset,
201 char *name_ret, int *name_type_ret)
205 char nbname[NBNAME_BUF_LEN];
206 char *pname, *pnbname, cname, cnbname;
209 name_len = get_dns_name(pd, offset, nbns_data_offset, name,
212 /* OK, now undo the first-level encoding. */
214 pnbname = &nbname[0];
216 /* Every two characters of the first level-encoded name
217 * turn into one character in the decoded name. */
220 break; /* no more characters */
222 break; /* scope ID follows */
223 if (cname < 'A' || cname > 'Z') {
226 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
230 cnbname = cname << 4;
234 if (cname == '\0' || cname == '.') {
235 /* No more characters in the name - but we're in
236 * the middle of a pair. Not legal. */
238 "Illegal NetBIOS name (odd number of bytes)");
241 if (cname < 'A' || cname > 'Z') {
244 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
251 /* Do we have room to store the character? */
252 if (pnbname < &nbname[NETBIOS_NAME_LEN]) {
253 /* Yes - store the character. */
257 /* We bump the pointer even if it's past the end of the
258 name, so we keep track of how long the name is. */
262 /* NetBIOS names are supposed to be exactly 16 bytes long. */
263 if (pnbname - nbname != NETBIOS_NAME_LEN) {
265 sprintf(nbname, "Illegal NetBIOS name (%ld bytes long)",
266 (long)(pnbname - nbname));
270 /* This one is; make its name printable. */
271 name_type = process_netbios_name(nbname, name_ret);
272 name_ret += strlen(name_ret);
273 sprintf(name_ret, "<%02x>", name_type);
276 /* We have a scope ID, starting at "pname"; append that to
277 * the decoded host name. */
278 strcpy(name_ret, pname);
280 if (name_type_ret != NULL)
281 *name_type_ret = name_type;
285 if (name_type_ret != NULL)
287 strcpy (name_ret, nbname);
293 get_nbns_name_type_class(const u_char *pd, int offset, int nbns_data_offset,
294 char *name_ret, int *name_len_ret, int *name_type_ret, int *type_ret,
301 name_len = get_nbns_name(pd, offset, nbns_data_offset, name_ret,
305 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
306 /* We ran past the end of the captured data in the packet. */
309 type = pntohs(&pd[offset]);
312 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
313 /* We ran past the end of the captured data in the packet. */
316 class = pntohs(&pd[offset]);
320 *name_len_ret = name_len;
326 add_name_and_type(proto_tree *tree, int offset, int len, char *tag,
327 char *name, int name_type)
329 if (name_type != -1) {
330 proto_tree_add_text(tree, NullTVB, offset, len, "%s: %s (%s)",
331 tag, name, netbios_name_type_descr(name_type));
333 proto_tree_add_text(tree, NullTVB, offset, len, "%s: %s",
339 dissect_nbns_query(const u_char *pd, int offset, int nbns_data_offset,
340 frame_data *fd, proto_tree *nbns_tree)
343 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
351 const u_char *data_start;
355 data_start = dptr = pd + offset;
357 len = get_nbns_name_type_class(pd, offset, nbns_data_offset, name,
358 &name_len, &name_type, &type, &class);
360 /* We ran past the end of the data in the packet. */
365 type_name = nbns_type_name(type);
366 class_name = dns_class_name(class);
369 col_append_fstr(fd, COL_INFO, " %s %s", type_name, name);
370 if (nbns_tree != NULL) {
371 tq = proto_tree_add_text(nbns_tree, NullTVB, offset, len,
372 "%s: type %s, class %s", name, type_name, class_name);
373 q_tree = proto_item_add_subtree(tq, ett_nbns_qd);
375 add_name_and_type(q_tree, offset, name_len, "Name", name,
379 proto_tree_add_text(q_tree, NullTVB, offset, 2, "Type: %s", type_name);
382 proto_tree_add_text(q_tree, NullTVB, offset, 2, "Class: %s", class_name);
386 return dptr - data_start;
390 nbns_add_nbns_flags(proto_tree *nbns_tree, int offset, u_short flags,
394 proto_tree *field_tree;
396 static const value_string rcode_vals[] = {
397 { RCODE_NOERROR, "No error" },
398 { RCODE_FMTERROR, "Request was invalidly formatted" },
399 { RCODE_SERVFAIL, "Server failure" },
400 { RCODE_NAMEERROR, "Requested name does not exist" },
401 { RCODE_NOTIMPL, "Request is not implemented" },
402 { RCODE_REFUSED, "Request was refused" },
403 { RCODE_ACTIVE, "Name is owned by another node" },
404 { RCODE_CONFLICT, "Name is in conflict" },
408 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals,
409 "Unknown operation"));
410 if (flags & F_RESPONSE && !is_wack) {
411 strcat(buf, " response");
413 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
416 tf = proto_tree_add_text(nbns_tree, NullTVB, offset, 2,
417 "Flags: 0x%04x (%s)", flags, buf);
418 field_tree = proto_item_add_subtree(tf, ett_nbns_flags);
419 proto_tree_add_text(field_tree, NullTVB, offset, 2, "%s",
420 decode_boolean_bitfield(flags, F_RESPONSE,
421 2*8, "Response", "Query"));
422 proto_tree_add_text(field_tree, NullTVB, offset, 2, "%s",
423 decode_enumerated_bitfield(flags, F_OPCODE,
424 2*8, opcode_vals, "%s"));
425 if (flags & F_RESPONSE) {
426 proto_tree_add_text(field_tree, NullTVB, offset, 2,
428 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
430 "Server is an authority for domain",
431 "Server isn't an authority for domain"));
433 proto_tree_add_text(field_tree, NullTVB, offset, 2, "%s",
434 decode_boolean_bitfield(flags, F_TRUNCATED,
436 "Message is truncated",
437 "Message is not truncated"));
438 proto_tree_add_text(field_tree, NullTVB, offset, 2, "%s",
439 decode_boolean_bitfield(flags, F_RECDESIRED,
441 "Do query recursively",
442 "Don't do query recursively"));
443 if (flags & F_RESPONSE) {
444 proto_tree_add_text(field_tree, NullTVB, offset, 2,
446 decode_boolean_bitfield(flags, F_RECAVAIL,
448 "Server can do recursive queries",
449 "Server can't do recursive queries"));
451 proto_tree_add_text(field_tree, NullTVB, offset, 2, "%s",
452 decode_boolean_bitfield(flags, F_BROADCAST,
455 "Not a broadcast packet"));
456 if (flags & F_RESPONSE && !is_wack) {
457 proto_tree_add_text(field_tree, NullTVB, offset, 2,
459 decode_enumerated_bitfield(flags, F_RCODE,
466 nbns_add_nb_flags(proto_tree *rr_tree, int offset, u_short flags)
469 proto_tree *field_tree;
471 static const value_string nb_flags_ont_vals[] = {
472 { NB_FLAGS_ONT_B_NODE, "B-node" },
473 { NB_FLAGS_ONT_P_NODE, "P-node" },
474 { NB_FLAGS_ONT_M_NODE, "M-node" },
475 { NB_FLAGS_ONT_H_NODE, "H-node" },
479 strcpy(buf, val_to_str(flags & NB_FLAGS_ONT, nb_flags_ont_vals,
482 if (flags & NB_FLAGS_G)
483 strcat(buf, "group");
485 strcat(buf, "unique");
486 tf = proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Flags: 0x%x (%s)", flags,
488 field_tree = proto_item_add_subtree(tf, ett_nbns_nb_flags);
489 proto_tree_add_text(field_tree, NullTVB, offset, 2, "%s",
490 decode_boolean_bitfield(flags, NB_FLAGS_G,
494 proto_tree_add_text(field_tree, NullTVB, offset, 2, "%s",
495 decode_enumerated_bitfield(flags, NB_FLAGS_ONT,
496 2*8, nb_flags_ont_vals, "%s"));
500 nbns_add_name_flags(proto_tree *rr_tree, int offset, u_short flags)
503 proto_item *field_tree;
505 static const value_string name_flags_ont_vals[] = {
506 { NAME_FLAGS_ONT_B_NODE, "B-node" },
507 { NAME_FLAGS_ONT_P_NODE, "P-node" },
508 { NAME_FLAGS_ONT_M_NODE, "M-node" },
512 strcpy(buf, val_to_str(flags & NAME_FLAGS_ONT, name_flags_ont_vals,
515 if (flags & NAME_FLAGS_G)
516 strcat(buf, "group");
518 strcat(buf, "unique");
519 if (flags & NAME_FLAGS_DRG)
520 strcat(buf, ", being deregistered");
521 if (flags & NAME_FLAGS_CNF)
522 strcat(buf, ", in conflict");
523 if (flags & NAME_FLAGS_ACT)
524 strcat(buf, ", active");
525 if (flags & NAME_FLAGS_PRM)
526 strcat(buf, ", permanent node name");
527 tf = proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Name flags: 0x%x (%s)",
529 field_tree = proto_item_add_subtree(tf, ett_nbns_name_flags);
530 proto_tree_add_text(field_tree, NullTVB, offset, 2, "%s",
531 decode_boolean_bitfield(flags, NAME_FLAGS_G,
535 proto_tree_add_text(field_tree, NullTVB, offset, 2, "%s",
536 decode_enumerated_bitfield(flags, NAME_FLAGS_ONT,
537 2*8, name_flags_ont_vals, "%s"));
538 proto_tree_add_text(field_tree, NullTVB, offset, 2, "%s",
539 decode_boolean_bitfield(flags, NAME_FLAGS_DRG,
541 "Name is being deregistered",
542 "Name is not being deregistered"));
543 proto_tree_add_text(field_tree, NullTVB, offset, 2, "%s",
544 decode_boolean_bitfield(flags, NAME_FLAGS_CNF,
546 "Name is in conflict",
547 "Name is not in conflict"));
548 proto_tree_add_text(field_tree, NullTVB, offset, 2, "%s",
549 decode_boolean_bitfield(flags, NAME_FLAGS_ACT,
552 "Name is not active"));
553 proto_tree_add_text(field_tree, NullTVB, offset, 2, "%s",
554 decode_boolean_bitfield(flags, NAME_FLAGS_PRM,
556 "Permanent node name",
557 "Not permanent node name"));
561 dissect_nbns_answer(const u_char *pd, int offset, int nbns_data_offset,
562 frame_data *fd, proto_tree *nbns_tree, int opcode)
565 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME + 64];
574 const u_char *data_start;
580 char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
582 char nbname[16+4+1]; /* 4 for [<last char>] */
585 data_start = dptr = pd + offset;
588 len = get_nbns_name_type_class(pd, offset, nbns_data_offset, name,
589 &name_len, &name_type, &type, &class);
591 /* We ran past the end of the data in the packet. */
597 type_name = nbns_type_name(type);
598 class_name = dns_class_name(class);
600 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
601 /* We ran past the end of the captured data in the packet. */
608 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
609 /* We ran past the end of the captured data in the packet. */
612 data_len = pntohs(dptr);
617 case T_NB: /* "NB" record */
619 if (opcode != OPCODE_WACK) {
620 col_append_fstr(fd, COL_INFO, " %s %s",
621 type_name, ip_to_str((guint8 *)(dptr + 2)));
624 if (nbns_tree == NULL)
626 trr = proto_tree_add_text(nbns_tree, NullTVB, offset,
627 (dptr - data_start) + data_len,
628 "%s: type %s, class %s",
629 name, type_name, class_name);
631 strcat(name, netbios_name_type_descr(name_type));
633 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, offset, name,
634 name_len, type_name, class_name, ttl, data_len);
635 while (data_len > 0) {
636 if (opcode == OPCODE_WACK) {
637 /* WACK response. This doesn't contain the
638 * same type of RR data as other T_NB
640 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
641 /* We ran past the end of the captured
642 data in the packet. */
646 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
647 data_len, "(incomplete entry)");
650 flags = pntohs(dptr);
652 nbns_add_nbns_flags(rr_tree, cur_offset,
657 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
658 /* We ran past the end of the captured
659 data in the packet. */
663 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
664 data_len, "(incomplete entry)");
667 flags = pntohs(dptr);
669 nbns_add_nb_flags(rr_tree, cur_offset, flags);
673 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
674 /* We ran past the end of the captured
675 data in the packet. */
679 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
680 data_len, "(incomplete entry)");
683 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4,
685 ip_to_str((guint8 *)dptr));
693 case T_NBSTAT: /* "NBSTAT" record */
695 col_append_fstr(fd, COL_INFO, " %s", type_name);
696 if (nbns_tree == NULL)
698 trr = proto_tree_add_text(nbns_tree, NullTVB, offset,
699 (dptr - data_start) + data_len,
700 "%s: type %s, class %s",
701 name, type_name, class_name);
702 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, offset, name,
703 name_len, type_name, class_name, ttl, data_len);
704 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
705 /* We ran past the end of the captured
706 data in the packet. */
710 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
711 data_len, "(incomplete entry)");
716 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
717 "Number of names: %u", num_names);
720 while (num_names != 0) {
721 if (!BYTES_ARE_IN_FRAME(cur_offset, NETBIOS_NAME_LEN)) {
722 /* We ran past the end of the captured
723 data in the packet. */
726 if (data_len < NETBIOS_NAME_LEN) {
727 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
728 data_len, "(incomplete entry)");
731 memcpy(nbname, dptr, NETBIOS_NAME_LEN);
732 dptr += NETBIOS_NAME_LEN;
733 name_type = process_netbios_name(nbname,
735 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
736 NETBIOS_NAME_LEN, "Name: %s<%02x> (%s)",
738 netbios_name_type_descr(name_type));
739 cur_offset += NETBIOS_NAME_LEN;
740 data_len -= NETBIOS_NAME_LEN;
742 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
743 /* We ran past the end of the captured
744 data in the packet. */
748 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
749 data_len, "(incomplete entry)");
752 name_flags = pntohs(dptr);
754 nbns_add_name_flags(rr_tree, cur_offset, name_flags);
761 if (!BYTES_ARE_IN_FRAME(cur_offset, 6)) {
762 /* We ran past the end of the captured
763 data in the packet. */
767 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
768 data_len, "(incomplete entry)");
771 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 6,
773 ether_to_str((guint8 *)dptr));
778 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
779 /* We ran past the end of the captured
780 data in the packet. */
784 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
785 data_len, "(incomplete entry)");
788 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1,
789 "Jumpers: 0x%x", *dptr);
794 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
795 /* We ran past the end of the captured
796 data in the packet. */
800 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
801 data_len, "(incomplete entry)");
804 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1,
805 "Test result: 0x%x", *dptr);
810 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
811 /* We ran past the end of the captured
812 data in the packet. */
816 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
817 data_len, "(incomplete entry)");
820 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
821 "Version number: 0x%x", pntohs(dptr));
826 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
827 /* We ran past the end of the captured
828 data in the packet. */
832 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
833 data_len, "(incomplete entry)");
836 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
837 "Period of statistics: 0x%x", pntohs(dptr));
842 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
843 /* We ran past the end of the captured
844 data in the packet. */
848 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
849 data_len, "(incomplete entry)");
852 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
853 "Number of CRCs: %u", pntohs(dptr));
858 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
859 /* We ran past the end of the captured
860 data in the packet. */
864 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
865 data_len, "(incomplete entry)");
868 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
869 "Number of alignment errors: %u", pntohs(dptr));
874 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
875 /* We ran past the end of the captured
876 data in the packet. */
880 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
881 data_len, "(incomplete entry)");
884 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
885 "Number of collisions: %u", pntohs(dptr));
890 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
891 /* We ran past the end of the captured
892 data in the packet. */
896 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
897 data_len, "(incomplete entry)");
900 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
901 "Number of send aborts: %u", pntohs(dptr));
906 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
907 /* We ran past the end of the captured
908 data in the packet. */
912 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
913 data_len, "(incomplete entry)");
916 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4,
917 "Number of good sends: %u", pntohl(dptr));
922 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
923 /* We ran past the end of the captured
924 data in the packet. */
928 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
929 data_len, "(incomplete entry)");
932 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4,
933 "Number of good receives: %u", pntohl(dptr));
938 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
939 /* We ran past the end of the captured
940 data in the packet. */
944 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
945 data_len, "(incomplete entry)");
948 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
949 "Number of retransmits: %u", pntohs(dptr));
954 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
955 /* We ran past the end of the captured
956 data in the packet. */
960 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
961 data_len, "(incomplete entry)");
964 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
965 "Number of no resource conditions: %u", pntohs(dptr));
970 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
971 /* We ran past the end of the captured
972 data in the packet. */
976 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
977 data_len, "(incomplete entry)");
980 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
981 "Number of command blocks: %u", pntohs(dptr));
986 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
987 /* We ran past the end of the captured
988 data in the packet. */
992 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
993 data_len, "(incomplete entry)");
996 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
997 "Number of pending sessions: %u", pntohs(dptr));
1002 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1003 /* We ran past the end of the captured
1004 data in the packet. */
1008 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
1009 data_len, "(incomplete entry)");
1012 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
1013 "Max number of pending sessions: %u", pntohs(dptr));
1017 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1018 /* We ran past the end of the captured
1019 data in the packet. */
1023 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
1024 data_len, "(incomplete entry)");
1027 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
1028 "Max total sessions possible: %u", pntohs(dptr));
1033 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1034 /* We ran past the end of the captured
1035 data in the packet. */
1039 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
1040 data_len, "(incomplete entry)");
1043 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2,
1044 "Session data packet size: %u", pntohs(dptr));
1053 col_append_fstr(fd, COL_INFO, " %s", type_name);
1054 if (nbns_tree == NULL)
1056 trr = proto_tree_add_text(nbns_tree, NullTVB, offset,
1057 (dptr - data_start) + data_len,
1058 "%s: type %s, class %s",
1059 name, type_name, class_name);
1060 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, offset, name,
1061 name_len, type_name, class_name, ttl, data_len);
1062 proto_tree_add_text(rr_tree, NullTVB, cur_offset, data_len, "Data");
1067 return dptr - data_start;
1071 dissect_query_records(const u_char *pd, int cur_off, int nbns_data_offset,
1072 int count, frame_data *fd, proto_tree *nbns_tree)
1074 int start_off, add_off;
1075 proto_tree *qatree = NULL;
1076 proto_item *ti = NULL;
1078 start_off = cur_off;
1079 if (nbns_tree != NULL) {
1080 ti = proto_tree_add_text(nbns_tree, NullTVB, start_off, 0, "Queries");
1081 qatree = proto_item_add_subtree(ti, ett_nbns_qry);
1083 while (count-- > 0) {
1084 add_off = dissect_nbns_query(pd, cur_off, nbns_data_offset,
1087 /* We ran past the end of the captured data in the
1094 proto_item_set_len(ti, cur_off - start_off);
1096 return cur_off - start_off;
1102 dissect_answer_records(const u_char *pd, int cur_off, int nbns_data_offset,
1103 int count, frame_data *fd, proto_tree *nbns_tree, int opcode, char *name)
1105 int start_off, add_off;
1106 proto_tree *qatree = NULL;
1107 proto_item *ti = NULL;
1109 start_off = cur_off;
1110 if (nbns_tree != NULL) {
1111 ti = proto_tree_add_text(nbns_tree, NullTVB, start_off, 0, name);
1112 qatree = proto_item_add_subtree(ti, ett_nbns_ans);
1114 while (count-- > 0) {
1115 add_off = dissect_nbns_answer(pd, cur_off, nbns_data_offset,
1116 fd, qatree, opcode);
1118 /* We ran past the end of the captured data in the
1125 proto_item_set_len(ti, cur_off - start_off);
1126 return cur_off - start_off;
1130 dissect_nbns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1132 int nbns_data_offset;
1133 proto_tree *nbns_tree = NULL;
1135 guint16 id, flags, quest, ans, auth, add;
1138 nbns_data_offset = offset;
1140 if (check_col(fd, COL_PROTOCOL))
1141 col_set_str(fd, COL_PROTOCOL, "NBNS");
1142 if (check_col(fd, COL_INFO))
1143 col_clear(fd, COL_INFO);
1145 if (pi.captured_len < NBNS_HDRLEN) {
1146 if (check_col(fd, COL_INFO)) {
1147 col_set_str(fd, COL_INFO, "Short NBNS packet");
1149 old_dissect_data(pd, offset, fd, tree);
1153 /* To do: check for runts, errs, etc. */
1154 id = pntohs(&pd[offset + NBNS_ID]);
1155 flags = pntohs(&pd[offset + NBNS_FLAGS]);
1156 quest = pntohs(&pd[offset + NBNS_QUEST]);
1157 ans = pntohs(&pd[offset + NBNS_ANS]);
1158 auth = pntohs(&pd[offset + NBNS_AUTH]);
1159 add = pntohs(&pd[offset + NBNS_ADD]);
1161 if (check_col(fd, COL_INFO)) {
1162 col_add_fstr(fd, COL_INFO, "%s%s",
1163 val_to_str(flags & F_OPCODE, opcode_vals,
1164 "Unknown operation (%x)"),
1165 (flags & F_RESPONSE) ? " response" : "");
1167 /* Set "fd" to NULL; we pass a NULL "fd" to the query and
1168 answer dissectors, as a way of saying that they shouldn't
1169 add stuff to the COL_INFO column (a call to
1170 "check_col(fd, COL_INFO)" is more expensive than a check
1171 that a pointer isn't NULL). */
1176 ti = proto_tree_add_item(tree, proto_nbns, NullTVB, offset, END_OF_FRAME, FALSE);
1177 nbns_tree = proto_item_add_subtree(ti, ett_nbns);
1179 if (flags & F_RESPONSE) {
1180 proto_tree_add_boolean_hidden(nbns_tree, hf_nbns_response, NullTVB,
1183 proto_tree_add_boolean_hidden(nbns_tree, hf_nbns_query, NullTVB,
1187 proto_tree_add_uint(nbns_tree, hf_nbns_transaction_id, NullTVB,
1188 offset + NBNS_ID, 2, id);
1190 nbns_add_nbns_flags(nbns_tree, offset + NBNS_FLAGS, flags, 0);
1191 proto_tree_add_uint(nbns_tree, hf_nbns_count_questions, NullTVB,
1192 offset + NBNS_QUEST, 2, quest);
1193 proto_tree_add_uint(nbns_tree, hf_nbns_count_answers, NullTVB,
1194 offset + NBNS_ANS, 2, ans);
1195 proto_tree_add_uint(nbns_tree, hf_nbns_count_auth_rr, NullTVB,
1196 offset + NBNS_AUTH, 2, auth);
1197 proto_tree_add_uint(nbns_tree, hf_nbns_count_add_rr, NullTVB,
1198 offset + NBNS_ADD, 2, add);
1201 cur_off = offset + NBNS_HDRLEN;
1204 /* If this is a response, don't add information about the
1205 queries to the summary, just add information about the
1207 cur_off += dissect_query_records(pd, cur_off,
1208 nbns_data_offset, quest,
1209 (!(flags & F_RESPONSE) ? fd : NULL), nbns_tree);
1213 /* If this is a request, don't add information about the
1214 answers to the summary, just add information about the
1216 cur_off += dissect_answer_records(pd, cur_off,
1217 nbns_data_offset, ans,
1218 ((flags & F_RESPONSE) ? fd : NULL), nbns_tree,
1219 flags & F_OPCODE, "Answers");
1223 /* Don't add information about the authoritative name
1224 servers, or the additional records, to the summary. */
1226 cur_off += dissect_answer_records(pd, cur_off,
1228 auth, NULL, nbns_tree,
1230 "Authoritative nameservers");
1233 cur_off += dissect_answer_records(pd, cur_off,
1235 add, NULL, nbns_tree,
1237 "Additional records");
1241 /* NetBIOS datagram packet, from RFC 1002, page 32 */
1242 struct nbdgm_header {
1253 /* For packets with data */
1257 /* For error packets */
1262 dissect_nbdgm(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1264 proto_tree *nbdgm_tree = NULL;
1266 struct nbdgm_header header;
1269 int max_data = pi.captured_len - offset;
1273 "Direct_unique datagram",
1274 "Direct_group datagram",
1275 "Broadcast datagram",
1277 "Datagram query request",
1278 "Datagram positive query response",
1279 "Datagram negative query response"
1289 static value_string error_codes[] = {
1290 { 0x82, "Destination name not present" },
1291 { 0x83, "Invalid source name format" },
1292 { 0x84, "Invalid destination name format" },
1296 char *yesno[] = { "No", "Yes" };
1298 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1302 if (check_col(fd, COL_PROTOCOL))
1303 col_set_str(fd, COL_PROTOCOL, "NBDS");
1304 if (check_col(fd, COL_INFO))
1305 col_clear(fd, COL_INFO);
1307 header.msg_type = pd[offset];
1309 flags = pd[offset+1];
1310 header.flags.more = flags & 1;
1311 header.flags.first = (flags & 2) >> 1;
1312 header.flags.node_type = (flags & 12) >> 2;
1314 header.dgm_id = pntohs(&pd[offset+2]);
1315 memcpy(&header.src_ip, &pd[offset+4], 4);
1316 header.src_port = pntohs(&pd[offset+8]);
1318 if (header.msg_type == 0x10 ||
1319 header.msg_type == 0x11 || header.msg_type == 0x12) {
1320 header.dgm_length = pntohs(&pd[offset+10]);
1321 header.pkt_offset = pntohs(&pd[offset+12]);
1323 else if (header.msg_type == 0x13) {
1324 header.error_code = pntohs(&pd[offset+10]);
1327 message_index = header.msg_type - 0x0f;
1328 if (message_index < 1 || message_index > 8) {
1332 if (check_col(fd, COL_INFO)) {
1333 col_set_str(fd, COL_INFO, message[message_index]);
1337 ti = proto_tree_add_item(tree, proto_nbdgm, NullTVB, offset, header.dgm_length, FALSE);
1338 nbdgm_tree = proto_item_add_subtree(ti, ett_nbdgm);
1340 proto_tree_add_uint_format(nbdgm_tree, hf_nbdgm_type, NullTVB,
1344 message[message_index]);
1345 proto_tree_add_boolean_format(nbdgm_tree, hf_nbdgm_fragment, NullTVB,
1348 "More fragments follow: %s",
1349 yesno[header.flags.more]);
1350 proto_tree_add_boolean_format(nbdgm_tree, hf_nbdgm_first, NullTVB,
1353 "This is first fragment: %s",
1354 yesno[header.flags.first]);
1355 proto_tree_add_uint_format(nbdgm_tree, hf_nbdgm_node_type, NullTVB,
1357 header.flags.node_type,
1359 node[header.flags.node_type]);
1361 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_datagram_id, NullTVB,
1362 offset+2, 2, header.dgm_id);
1363 proto_tree_add_ipv4(nbdgm_tree, hf_nbdgm_src_ip, NullTVB,
1364 offset+4, 4, header.src_ip);
1365 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_src_port, NullTVB,
1366 offset+8, 2, header.src_port);
1373 if (header.msg_type == 0x10 ||
1374 header.msg_type == 0x11 || header.msg_type == 0x12) {
1377 proto_tree_add_text(nbdgm_tree, NullTVB, offset, 2,
1378 "Datagram length: %d bytes", header.dgm_length);
1379 proto_tree_add_text(nbdgm_tree, NullTVB, offset+2, 2,
1380 "Packet offset: %d bytes", header.pkt_offset);
1387 len = get_nbns_name(pd, offset, offset, name, &name_type);
1390 add_name_and_type(nbdgm_tree, offset, len,
1391 "Source name", name, name_type);
1396 /* Destination name */
1397 len = get_nbns_name(pd, offset, offset, name, &name_type);
1400 add_name_and_type(nbdgm_tree, offset, len,
1401 "Destination name", name, name_type);
1406 /* here we can pass the packet off to the next protocol */
1407 dissect_smb(pd, offset, fd, tree, max_data);
1409 else if (header.msg_type == 0x13) {
1411 proto_tree_add_text(nbdgm_tree, NullTVB, offset, 1, "Error code: %s",
1412 val_to_str(header.error_code, error_codes, "Unknown (0x%x)"));
1415 else if (header.msg_type == 0x14 ||
1416 header.msg_type == 0x15 || header.msg_type == 0x16) {
1417 /* Destination name */
1418 len = get_nbns_name(pd, offset, offset, name, &name_type);
1421 add_name_and_type(nbdgm_tree, offset, len,
1422 "Destination name", name, name_type);
1428 * NetBIOS Session Service message types.
1430 #define SESSION_MESSAGE 0x00
1431 #define SESSION_REQUEST 0x81
1432 #define POSITIVE_SESSION_RESPONSE 0x82
1433 #define NEGATIVE_SESSION_RESPONSE 0x83
1434 #define RETARGET_SESSION_RESPONSE 0x84
1435 #define SESSION_KEEP_ALIVE 0x85
1437 static const value_string message_types[] = {
1438 { SESSION_MESSAGE, "Session message" },
1439 { SESSION_REQUEST, "Session request" },
1440 { POSITIVE_SESSION_RESPONSE, "Positive session response" },
1441 { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
1442 { RETARGET_SESSION_RESPONSE, "Retarget session response" },
1443 { SESSION_KEEP_ALIVE, "Session keep-alive" },
1448 * NetBIOS Session Service flags.
1450 #define NBSS_FLAGS_E 0x1
1452 static const value_string error_codes[] = {
1453 { 0x80, "Not listening on called name" },
1454 { 0x81, "Not listening for called name" },
1455 { 0x82, "Called name not present" },
1456 { 0x83, "Called name present, but insufficient resources" },
1457 { 0x8F, "Unspecified error" },
1462 * Dissect a single NBSS packet (there may be more than one in a given
1465 * [ Hmmm, in my experience, I have never seen more than one NBSS in a
1466 * single segment, since they mostly contain SMBs which are essentially
1467 * a request response type protocol (RJS). ]
1469 * [ However, under heavy load with many requests multiplexed on one
1470 * session it is not unusual to see multiple requests in one TCP
1471 * segment. Unfortunately, in this case a single session message is
1472 * frequently split over multiple segments, which frustrates decoding
1476 dissect_nbss_packet(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data, int is_cifs)
1478 proto_tree *nbss_tree = NULL;
1480 proto_tree *field_tree;
1486 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1489 msg_type = pd[offset];
1493 length = pntohl(&pd[offset]) & 0x00FFFFFF;
1495 flags = pd[offset + 1];
1496 length = pntohs(&pd[offset + 2]);
1497 if (flags & NBSS_FLAGS_E)
1502 ti = proto_tree_add_item(tree, proto_nbss, NullTVB, offset, length + 4, FALSE);
1503 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1505 proto_tree_add_uint_format(nbss_tree, hf_nbss_type, NullTVB,
1509 val_to_str(msg_type, message_types,
1517 proto_tree_add_text(nbss_tree, NullTVB, offset, 3, "Length: %u", length);
1522 tf = proto_tree_add_uint(nbss_tree, hf_nbss_flags, NullTVB, offset, 1, flags);
1523 field_tree = proto_item_add_subtree(tf, ett_nbss_flags);
1524 proto_tree_add_text(field_tree, NullTVB, offset, 1, "%s",
1525 decode_boolean_bitfield(flags, NBSS_FLAGS_E,
1526 8, "Add 65536 to length", "Add 0 to length"));
1531 proto_tree_add_text(nbss_tree, NullTVB, offset, 2, "Length: %u", length);
1539 case SESSION_REQUEST:
1540 len = get_nbns_name(pd, offset, offset, name, &name_type);
1542 add_name_and_type(nbss_tree, offset, len,
1543 "Called name", name, name_type);
1546 len = get_nbns_name(pd, offset, offset, name, &name_type);
1549 add_name_and_type(nbss_tree, offset, len,
1550 "Calling name", name, name_type);
1554 case NEGATIVE_SESSION_RESPONSE:
1556 proto_tree_add_text(nbss_tree, NullTVB, offset, 1,
1558 val_to_str(pd[offset], error_codes, "Unknown (%x)"));
1561 case RETARGET_SESSION_RESPONSE:
1563 proto_tree_add_text(nbss_tree, NullTVB, offset, 4,
1564 "Retarget IP address: %s",
1565 ip_to_str((guint8 *)&pd[offset]));
1570 proto_tree_add_text(nbss_tree, NullTVB, offset, 2,
1571 "Retarget port: %u", pntohs(&pd[offset]));
1575 case SESSION_MESSAGE:
1577 * Here we can pass the packet off to the next protocol.
1580 dissect_smb(pd, offset, fd, tree, max_data - 4);
1589 dissect_nbss(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1598 if (check_col(fd, COL_PROTOCOL))
1599 col_set_str(fd, COL_PROTOCOL, "NBSS");
1600 if (check_col(fd, COL_INFO))
1601 col_clear(fd, COL_INFO);
1603 msg_type = pd[offset];
1605 if (pi.match_port == TCP_PORT_CIFS) {
1607 * Windows 2000 CIFS clients can dispense completely
1608 * with the NETBIOS encapsulation and directly use CIFS
1609 * over TCP. As would be expected, the framing is
1610 * identical, except that the length is 24 bits instead
1611 * of 17. The only message types used are
1612 * SESSION_MESSAGE and SESSION_KEEP_ALIVE.
1615 length = pntohl(&pd[offset]) & 0x00FFFFFF;
1618 flags = pd[offset + 1];
1619 length = pntohs(&pd[offset + 2]);
1620 if (flags & NBSS_FLAGS_E)
1626 * XXX - we should set this based on both "pi.captured_len"
1629 max_data = pi.captured_len - offset;
1631 /* Hmmm, it may be a continuation message ... */
1635 if (((msg_type != SESSION_REQUEST) &&
1636 (msg_type != POSITIVE_SESSION_RESPONSE) &&
1637 (msg_type != NEGATIVE_SESSION_RESPONSE) &&
1638 (msg_type != RETARGET_SESSION_RESPONSE) &&
1639 (msg_type != SESSION_MESSAGE)) ||
1640 ((msg_type == SESSION_MESSAGE) &&
1641 (memcmp(pd + offset + 4, "\377SMB", 4) != 0))) {
1643 if (check_col(fd, COL_INFO)) {
1644 col_add_fstr(fd, COL_INFO, "NBSS Continuation Message");
1648 proto_tree_add_text(tree, NullTVB, offset, max_data, "Continuation data");
1654 if (check_col(fd, COL_INFO)) {
1655 col_add_fstr(fd, COL_INFO,
1656 val_to_str(msg_type, message_types, "Unknown (%x)"));
1659 while (max_data > 0) {
1660 len = dissect_nbss_packet(pd, offset, fd, tree, max_data, is_cifs);
1668 proto_register_nbt(void)
1671 static hf_register_info hf_nbns[] = {
1672 { &hf_nbns_response,
1673 { "Response", "nbns.response",
1674 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1675 "TRUE if NBNS response" }},
1677 { "Query", "nbns.query",
1678 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1679 "TRUE if NBNS query" }},
1680 { &hf_nbns_transaction_id,
1681 { "Transaction ID", "nbns.id",
1682 FT_UINT16, BASE_HEX, NULL, 0x0,
1683 "Identification of transaction" }},
1684 { &hf_nbns_count_questions,
1685 { "Questions", "nbns.count.queries",
1686 FT_UINT16, BASE_DEC, NULL, 0x0,
1687 "Number of queries in packet" }},
1688 { &hf_nbns_count_answers,
1689 { "Answer RRs", "nbns.count.answers",
1690 FT_UINT16, BASE_DEC, NULL, 0x0,
1691 "Number of answers in packet" }},
1692 { &hf_nbns_count_auth_rr,
1693 { "Authority RRs", "nbns.count.auth_rr",
1694 FT_UINT16, BASE_DEC, NULL, 0x0,
1695 "Number of authoritative records in packet" }},
1696 { &hf_nbns_count_add_rr,
1697 { "Additional RRs", "nbns.count.add_rr",
1698 FT_UINT16, BASE_DEC, NULL, 0x0,
1699 "Number of additional records in packet" }}
1702 static hf_register_info hf_nbdgm[] = {
1704 { "Message Type", "nbdgm.type",
1705 FT_UINT8, BASE_DEC, NULL, 0x0,
1706 "NBDGM message type" }},
1707 { &hf_nbdgm_fragment,
1708 { "Fragmented", "nbdgm.next",
1709 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1710 "TRUE if more fragments follow" }},
1712 { "First fragment", "nbdgm.first",
1713 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1714 "TRUE if first fragment" }},
1715 { &hf_nbdgm_node_type,
1716 { "Node Type", "nbdgm.node_type",
1717 FT_UINT8, BASE_DEC, NULL, 0x0,
1719 { &hf_nbdgm_datagram_id,
1720 { "Datagram ID", "nbdgm.dgram_id",
1721 FT_UINT16, BASE_HEX, NULL, 0x0,
1722 "Datagram identifier" }},
1724 { "Source IP", "nbdgm.src.ip",
1725 FT_IPv4, BASE_NONE, NULL, 0x0,
1726 "Source IPv4 address" }},
1727 { &hf_nbdgm_src_port,
1728 { "Source Port", "nbdgm.src.port",
1729 FT_UINT16, BASE_DEC, NULL, 0x0,
1733 static hf_register_info hf_nbss[] = {
1735 { "Message Type", "nbss.type",
1736 FT_UINT8, BASE_DEC, NULL, 0x0,
1737 "NBSS message type" }},
1739 { "Flags", "nbss.flags",
1740 FT_UINT8, BASE_HEX, NULL, 0x0,
1741 "NBSS message flags" }}
1743 static gint *ett[] = {
1748 &ett_nbns_name_flags,
1757 proto_nbns = proto_register_protocol("NetBIOS Name Service", "NBNS", "nbns");
1758 proto_register_field_array(proto_nbns, hf_nbns, array_length(hf_nbns));
1760 proto_nbdgm = proto_register_protocol("NetBIOS Datagram Service",
1762 proto_register_field_array(proto_nbdgm, hf_nbdgm, array_length(hf_nbdgm));
1764 proto_nbss = proto_register_protocol("NetBIOS Session Service",
1766 proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));
1768 proto_register_subtree_array(ett, array_length(ett));
1772 proto_reg_handoff_nbt(void)
1774 old_dissector_add("udp.port", UDP_PORT_NBNS, dissect_nbns, proto_nbns);
1775 old_dissector_add("udp.port", UDP_PORT_NBDGM, dissect_nbdgm, proto_nbdgm);
1776 old_dissector_add("tcp.port", TCP_PORT_NBSS, dissect_nbss, proto_nbss);
1777 old_dissector_add("tcp.port", TCP_PORT_CIFS, dissect_nbss, proto_nbss);