2 * Routines for NetBIOS-over-TCP packet disassembly (the name dates back
3 * to when it had only NBNS)
4 * Gilbert Ramirez <gram@verdict.uthscsa.edu>
5 * Much stuff added by Guy Harris <guy@netapp.com>
7 * $Id: packet-nbns.c,v 1.32 1999/11/08 09:16:52 guy Exp $
9 * Ethereal - Network traffic analyzer
10 * By Gerald Combs <gerald@zing.org>
11 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
41 #include "packet-dns.h"
42 #include "packet-netbios.h"
45 static int proto_nbns = -1;
46 static int hf_nbns_response = -1;
47 static int hf_nbns_query = -1;
48 static int hf_nbns_transaction_id = -1;
49 static int hf_nbns_count_questions = -1;
50 static int hf_nbns_count_answers = -1;
51 static int hf_nbns_count_auth_rr = -1;
52 static int hf_nbns_count_add_rr = -1;
54 static int proto_nbdgm = -1;
55 static int hf_nbdgm_type = -1;
56 static int hf_nbdgm_fragment = -1;
57 static int hf_nbdgm_first = -1;
58 static int hf_nbdgm_node_type = -1;
59 static int hf_nbdgm_datagram_id = -1;
60 static int hf_nbdgm_src_ip = -1;
61 static int hf_nbdgm_src_port = -1;
63 static int proto_nbss = -1;
64 static int hf_nbss_type = -1;
65 static int hf_nbss_flags = -1;
67 /* Packet structure taken from RFC 1002. See also RFC 1001.
68 * Opcode, flags, and rcode treated as "flags", similarly to DNS,
69 * to make it easier to lift the dissection code from "packet-dns.c". */
71 /* Offsets of fields in the NBNS header. */
79 /* Length of NBNS header. */
80 #define NBNS_HDRLEN 12
83 #define T_NB 32 /* NetBIOS name service RR */
84 #define T_NBSTAT 33 /* NetBIOS node status RR */
86 /* Bit fields in the flags */
87 #define F_RESPONSE (1<<15) /* packet is response */
88 #define F_OPCODE (0xF<<11) /* query opcode */
89 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
90 #define F_TRUNCATED (1<<9) /* response is truncated */
91 #define F_RECDESIRED (1<<8) /* recursion desired */
92 #define F_RECAVAIL (1<<7) /* recursion available */
93 #define F_BROADCAST (1<<4) /* broadcast/multicast packet */
94 #define F_RCODE (0xF<<0) /* reply code */
97 #define OPCODE_QUERY (0<<11) /* standard query */
98 #define OPCODE_REGISTRATION (5<<11) /* registration */
99 #define OPCODE_RELEASE (6<<11) /* release name */
100 #define OPCODE_WACK (7<<11) /* wait for acknowledgement */
101 #define OPCODE_REFRESH (8<<11) /* refresh registration */
102 #define OPCODE_REFRESHALT (9<<11) /* refresh registration (alternate opcode) */
103 #define OPCODE_MHREGISTRATION (15<<11) /* multi-homed registration */
106 #define RCODE_NOERROR (0<<0)
107 #define RCODE_FMTERROR (1<<0)
108 #define RCODE_SERVFAIL (2<<0)
109 #define RCODE_NAMEERROR (3<<0)
110 #define RCODE_NOTIMPL (4<<0)
111 #define RCODE_REFUSED (5<<0)
112 #define RCODE_ACTIVE (6<<0)
113 #define RCODE_CONFLICT (7<<0)
115 /* Values for the "NB_FLAGS" field of RR data. From RFC 1001 and 1002,
116 * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
118 #define NB_FLAGS_ONT (3<<(15-2)) /* bits for node type */
119 #define NB_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
120 #define NB_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
121 #define NB_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
122 #define NB_FLAGS_ONT_H_NODE (3<<(15-2)) /* H-mode node */
124 #define NB_FLAGS_G (1<<(15-0)) /* group name */
126 /* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
127 * RR data. From RFC 1001 and 1002, except for NAME_FLAGS_ONT_H_NODE,
128 * which was discovered by looking at packet traces. */
129 #define NAME_FLAGS_PRM (1<<(15-6)) /* name is permanent node name */
131 #define NAME_FLAGS_ACT (1<<(15-5)) /* name is active */
133 #define NAME_FLAGS_CNF (1<<(15-4)) /* name is in conflict */
135 #define NAME_FLAGS_DRG (1<<(15-3)) /* name is being deregistered */
137 #define NAME_FLAGS_ONT (3<<(15-2)) /* bits for node type */
138 #define NAME_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
139 #define NAME_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
140 #define NAME_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
142 #define NAME_FLAGS_G (1<<(15-0)) /* group name */
144 static const value_string opcode_vals[] = {
145 { OPCODE_QUERY, "Name query" },
146 { OPCODE_REGISTRATION, "Registration" },
147 { OPCODE_RELEASE, "Release" },
148 { OPCODE_WACK, "Wait for acknowledgment" },
149 { OPCODE_REFRESH, "Refresh" },
150 { OPCODE_REFRESHALT, "Refresh (alternate opcode)" },
151 { OPCODE_MHREGISTRATION, "Multi-homed registration" },
156 nbns_type_name (int type)
169 get_nbns_name(const u_char *pd, int offset, int nbns_data_offset,
170 char *name_ret, int *name_type_ret)
174 char nbname[NETBIOS_NAME_LEN];
175 char *pname, *pnbname, cname, cnbname;
178 name_len = get_dns_name(pd, offset, nbns_data_offset, name,
181 /* OK, now undo the first-level encoding. */
183 pnbname = &nbname[0];
185 /* Every two characters of the first level-encoded name
186 * turn into one character in the decoded name. */
189 break; /* no more characters */
191 break; /* scope ID follows */
192 if (cname < 'A' || cname > 'Z') {
195 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
199 cnbname = cname << 4;
203 if (cname == '\0' || cname == '.') {
204 /* No more characters in the name - but we're in
205 * the middle of a pair. Not legal. */
207 "Illegal NetBIOS name (odd number of bytes)");
210 if (cname < 'A' || cname > 'Z') {
213 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
220 /* Do we have room to store the character? */
221 if (pnbname < &nbname[NETBIOS_NAME_LEN]) {
222 /* Yes - store the character. */
226 /* We bump the pointer even if it's past the end of the
227 name, so we keep track of how long the name is. */
231 /* NetBIOS names are supposed to be exactly 16 bytes long. */
232 if (pnbname - nbname != NETBIOS_NAME_LEN) {
234 sprintf(nbname, "Illegal NetBIOS name (%ld bytes long)",
235 (long)(pnbname - nbname));
239 /* This one is; make its name printable. */
240 name_type = process_netbios_name(nbname, name_ret);
241 name_ret += strlen(name_ret);
242 sprintf(name_ret, "<%02x>", name_type);
245 /* We have a scope ID, starting at "pname"; append that to
246 * the decoded host name. */
247 strcpy(name_ret, pname);
249 if (name_type_ret != NULL)
250 *name_type_ret = name_type;
254 if (name_type_ret != NULL)
256 strcpy (name_ret, nbname);
262 get_nbns_name_type_class(const u_char *pd, int offset, int nbns_data_offset,
263 char *name_ret, int *name_len_ret, int *name_type_ret, int *type_ret,
270 name_len = get_nbns_name(pd, offset, nbns_data_offset, name_ret,
274 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
275 /* We ran past the end of the captured data in the packet. */
278 type = pntohs(&pd[offset]);
281 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
282 /* We ran past the end of the captured data in the packet. */
285 class = pntohs(&pd[offset]);
289 *name_len_ret = name_len;
295 add_name_and_type(proto_tree *tree, int offset, int len, char *tag,
296 char *name, int name_type)
298 if (name_type != -1) {
299 proto_tree_add_text(tree, offset, len, "%s: %s (%s)",
300 tag, name, netbios_name_type_descr(name_type));
302 proto_tree_add_text(tree, offset, len, "%s: %s",
308 dissect_nbns_query(const u_char *pd, int offset, int nbns_data_offset,
309 frame_data *fd, proto_tree *nbns_tree)
312 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
320 const u_char *data_start;
324 data_start = dptr = pd + offset;
326 len = get_nbns_name_type_class(pd, offset, nbns_data_offset, name,
327 &name_len, &name_type, &type, &class);
329 /* We ran past the end of the data in the packet. */
334 type_name = nbns_type_name(type);
335 class_name = dns_class_name(class);
338 col_append_fstr(fd, COL_INFO, " %s %s", type_name, name);
339 if (nbns_tree != NULL) {
340 tq = proto_tree_add_text(nbns_tree, offset, len,
341 "%s: type %s, class %s", name, type_name, class_name);
342 q_tree = proto_item_add_subtree(tq, ETT_NBNS_QD);
344 add_name_and_type(q_tree, offset, name_len, "Name", name,
348 proto_tree_add_text(q_tree, offset, 2, "Type: %s", type_name);
351 proto_tree_add_text(q_tree, offset, 2, "Class: %s", class_name);
355 return dptr - data_start;
359 nbns_add_nbns_flags(proto_tree *nbns_tree, int offset, u_short flags,
363 proto_tree *field_tree;
365 static const value_string rcode_vals[] = {
366 { RCODE_NOERROR, "No error" },
367 { RCODE_FMTERROR, "Request was invalidly formatted" },
368 { RCODE_SERVFAIL, "Server failure" },
369 { RCODE_NAMEERROR, "Requested name does not exist" },
370 { RCODE_NOTIMPL, "Request is not implemented" },
371 { RCODE_REFUSED, "Request was refused" },
372 { RCODE_ACTIVE, "Name is owned by another node" },
373 { RCODE_CONFLICT, "Name is in conflict" },
377 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals,
378 "Unknown operation"));
379 if (flags & F_RESPONSE && !is_wack) {
380 strcat(buf, " response");
382 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
385 tf = proto_tree_add_text(nbns_tree, offset, 2,
386 "Flags: 0x%04x (%s)", flags, buf);
387 field_tree = proto_item_add_subtree(tf, ETT_NBNS_FLAGS);
388 proto_tree_add_text(field_tree, offset, 2, "%s",
389 decode_boolean_bitfield(flags, F_RESPONSE,
390 2*8, "Response", "Query"));
391 proto_tree_add_text(field_tree, offset, 2, "%s",
392 decode_enumerated_bitfield(flags, F_OPCODE,
393 2*8, opcode_vals, "%s"));
394 if (flags & F_RESPONSE) {
395 proto_tree_add_text(field_tree, offset, 2,
397 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
399 "Server is an authority for domain",
400 "Server isn't an authority for domain"));
402 proto_tree_add_text(field_tree, offset, 2, "%s",
403 decode_boolean_bitfield(flags, F_TRUNCATED,
405 "Message is truncated",
406 "Message is not truncated"));
407 proto_tree_add_text(field_tree, offset, 2, "%s",
408 decode_boolean_bitfield(flags, F_RECDESIRED,
410 "Do query recursively",
411 "Don't do query recursively"));
412 if (flags & F_RESPONSE) {
413 proto_tree_add_text(field_tree, offset, 2,
415 decode_boolean_bitfield(flags, F_RECAVAIL,
417 "Server can do recursive queries",
418 "Server can't do recursive queries"));
420 proto_tree_add_text(field_tree, offset, 2, "%s",
421 decode_boolean_bitfield(flags, F_BROADCAST,
424 "Not a broadcast packet"));
425 if (flags & F_RESPONSE && !is_wack) {
426 proto_tree_add_text(field_tree, offset, 2,
428 decode_enumerated_bitfield(flags, F_RCODE,
435 nbns_add_nb_flags(proto_tree *rr_tree, int offset, u_short flags)
438 proto_tree *field_tree;
440 static const value_string nb_flags_ont_vals[] = {
441 { NB_FLAGS_ONT_B_NODE, "B-node" },
442 { NB_FLAGS_ONT_P_NODE, "P-node" },
443 { NB_FLAGS_ONT_M_NODE, "M-node" },
444 { NB_FLAGS_ONT_H_NODE, "H-node" },
448 strcpy(buf, val_to_str(flags & NB_FLAGS_ONT, nb_flags_ont_vals,
451 if (flags & NB_FLAGS_G)
452 strcat(buf, "group");
454 strcat(buf, "unique");
455 tf = proto_tree_add_text(rr_tree, offset, 2, "Flags: 0x%x (%s)", flags,
457 field_tree = proto_item_add_subtree(tf, ETT_NBNS_NB_FLAGS);
458 proto_tree_add_text(field_tree, offset, 2, "%s",
459 decode_boolean_bitfield(flags, NB_FLAGS_G,
463 proto_tree_add_text(field_tree, offset, 2, "%s",
464 decode_enumerated_bitfield(flags, NB_FLAGS_ONT,
465 2*8, nb_flags_ont_vals, "%s"));
469 nbns_add_name_flags(proto_tree *rr_tree, int offset, u_short flags)
472 proto_item *field_tree;
474 static const value_string name_flags_ont_vals[] = {
475 { NAME_FLAGS_ONT_B_NODE, "B-node" },
476 { NAME_FLAGS_ONT_P_NODE, "P-node" },
477 { NAME_FLAGS_ONT_M_NODE, "M-node" },
481 strcpy(buf, val_to_str(flags & NAME_FLAGS_ONT, name_flags_ont_vals,
484 if (flags & NAME_FLAGS_G)
485 strcat(buf, "group");
487 strcat(buf, "unique");
488 if (flags & NAME_FLAGS_DRG)
489 strcat(buf, ", being deregistered");
490 if (flags & NAME_FLAGS_CNF)
491 strcat(buf, ", in conflict");
492 if (flags & NAME_FLAGS_ACT)
493 strcat(buf, ", active");
494 if (flags & NAME_FLAGS_PRM)
495 strcat(buf, ", permanent node name");
496 tf = proto_tree_add_text(rr_tree, offset, 2, "Name flags: 0x%x (%s)",
498 field_tree = proto_item_add_subtree(tf, ETT_NBNS_NAME_FLAGS);
499 proto_tree_add_text(field_tree, offset, 2, "%s",
500 decode_boolean_bitfield(flags, NAME_FLAGS_G,
504 proto_tree_add_text(field_tree, offset, 2, "%s",
505 decode_enumerated_bitfield(flags, NAME_FLAGS_ONT,
506 2*8, name_flags_ont_vals, "%s"));
507 proto_tree_add_text(field_tree, offset, 2, "%s",
508 decode_boolean_bitfield(flags, NAME_FLAGS_DRG,
510 "Name is being deregistered",
511 "Name is not being deregistered"));
512 proto_tree_add_text(field_tree, offset, 2, "%s",
513 decode_boolean_bitfield(flags, NAME_FLAGS_CNF,
515 "Name is in conflict",
516 "Name is not in conflict"));
517 proto_tree_add_text(field_tree, offset, 2, "%s",
518 decode_boolean_bitfield(flags, NAME_FLAGS_ACT,
521 "Name is not active"));
522 proto_tree_add_text(field_tree, offset, 2, "%s",
523 decode_boolean_bitfield(flags, NAME_FLAGS_PRM,
525 "Permanent node name",
526 "Not permanent node name"));
530 dissect_nbns_answer(const u_char *pd, int offset, int nbns_data_offset,
531 frame_data *fd, proto_tree *nbns_tree, int opcode)
534 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME + 64];
543 const u_char *data_start;
549 char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
551 char nbname[16+4+1]; /* 4 for [<last char>] */
554 data_start = dptr = pd + offset;
557 len = get_nbns_name_type_class(pd, offset, nbns_data_offset, name,
558 &name_len, &name_type, &type, &class);
560 /* We ran past the end of the data in the packet. */
566 type_name = nbns_type_name(type);
567 class_name = dns_class_name(class);
569 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
570 /* We ran past the end of the captured data in the packet. */
577 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
578 /* We ran past the end of the captured data in the packet. */
581 data_len = pntohs(dptr);
586 case T_NB: /* "NB" record */
588 if (opcode != OPCODE_WACK) {
589 col_append_fstr(fd, COL_INFO, " %s %s",
590 type_name, ip_to_str((guint8 *)(dptr + 2)));
593 if (nbns_tree == NULL)
595 trr = proto_tree_add_text(nbns_tree, offset,
596 (dptr - data_start) + data_len,
597 "%s: type %s, class %s",
598 name, type_name, class_name);
600 strcat(name, netbios_name_type_descr(name_type));
602 rr_tree = add_rr_to_tree(trr, ETT_NBNS_RR, offset, name,
603 name_len, type_name, class_name, ttl, data_len);
604 while (data_len > 0) {
605 if (opcode == OPCODE_WACK) {
606 /* WACK response. This doesn't contain the
607 * same type of RR data as other T_NB
609 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
610 /* We ran past the end of the captured
611 data in the packet. */
615 proto_tree_add_text(rr_tree, cur_offset,
616 data_len, "(incomplete entry)");
619 flags = pntohs(dptr);
621 nbns_add_nbns_flags(rr_tree, cur_offset,
626 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
627 /* We ran past the end of the captured
628 data in the packet. */
632 proto_tree_add_text(rr_tree, cur_offset,
633 data_len, "(incomplete entry)");
636 flags = pntohs(dptr);
638 nbns_add_nb_flags(rr_tree, cur_offset, flags);
642 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
643 /* We ran past the end of the captured
644 data in the packet. */
648 proto_tree_add_text(rr_tree, cur_offset,
649 data_len, "(incomplete entry)");
652 proto_tree_add_text(rr_tree, cur_offset, 4,
654 ip_to_str((guint8 *)dptr));
662 case T_NBSTAT: /* "NBSTAT" record */
664 col_append_fstr(fd, COL_INFO, " %s", type_name);
665 if (nbns_tree == NULL)
667 trr = proto_tree_add_text(nbns_tree, offset,
668 (dptr - data_start) + data_len,
669 "%s: type %s, class %s",
670 name, type_name, class_name);
671 rr_tree = add_rr_to_tree(trr, ETT_NBNS_RR, offset, name,
672 name_len, type_name, class_name, ttl, data_len);
673 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
674 /* We ran past the end of the captured
675 data in the packet. */
679 proto_tree_add_text(rr_tree, cur_offset,
680 data_len, "(incomplete entry)");
685 proto_tree_add_text(rr_tree, cur_offset, 2,
686 "Number of names: %u", num_names);
689 while (num_names != 0) {
690 if (!BYTES_ARE_IN_FRAME(cur_offset, NETBIOS_NAME_LEN)) {
691 /* We ran past the end of the captured
692 data in the packet. */
695 if (data_len < NETBIOS_NAME_LEN) {
696 proto_tree_add_text(rr_tree, cur_offset,
697 data_len, "(incomplete entry)");
700 memcpy(nbname, dptr, NETBIOS_NAME_LEN);
701 dptr += NETBIOS_NAME_LEN;
702 name_type = process_netbios_name(nbname,
704 proto_tree_add_text(rr_tree, cur_offset,
705 NETBIOS_NAME_LEN, "Name: %s<%02x> (%s)",
707 netbios_name_type_descr(name_type));
708 cur_offset += NETBIOS_NAME_LEN;
709 data_len -= NETBIOS_NAME_LEN;
711 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
712 /* We ran past the end of the captured
713 data in the packet. */
717 proto_tree_add_text(rr_tree, cur_offset,
718 data_len, "(incomplete entry)");
721 name_flags = pntohs(dptr);
723 nbns_add_name_flags(rr_tree, cur_offset, name_flags);
730 if (!BYTES_ARE_IN_FRAME(cur_offset, 6)) {
731 /* We ran past the end of the captured
732 data in the packet. */
736 proto_tree_add_text(rr_tree, cur_offset,
737 data_len, "(incomplete entry)");
740 proto_tree_add_text(rr_tree, cur_offset, 6,
742 ether_to_str((guint8 *)dptr));
747 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
748 /* We ran past the end of the captured
749 data in the packet. */
753 proto_tree_add_text(rr_tree, cur_offset,
754 data_len, "(incomplete entry)");
757 proto_tree_add_text(rr_tree, cur_offset, 1,
758 "Jumpers: 0x%x", *dptr);
763 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
764 /* We ran past the end of the captured
765 data in the packet. */
769 proto_tree_add_text(rr_tree, cur_offset,
770 data_len, "(incomplete entry)");
773 proto_tree_add_text(rr_tree, cur_offset, 1,
774 "Test result: 0x%x", *dptr);
779 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
780 /* We ran past the end of the captured
781 data in the packet. */
785 proto_tree_add_text(rr_tree, cur_offset,
786 data_len, "(incomplete entry)");
789 proto_tree_add_text(rr_tree, cur_offset, 2,
790 "Version number: 0x%x", pntohs(dptr));
795 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
796 /* We ran past the end of the captured
797 data in the packet. */
801 proto_tree_add_text(rr_tree, cur_offset,
802 data_len, "(incomplete entry)");
805 proto_tree_add_text(rr_tree, cur_offset, 2,
806 "Period of statistics: 0x%x", pntohs(dptr));
811 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
812 /* We ran past the end of the captured
813 data in the packet. */
817 proto_tree_add_text(rr_tree, cur_offset,
818 data_len, "(incomplete entry)");
821 proto_tree_add_text(rr_tree, cur_offset, 2,
822 "Number of CRCs: %u", pntohs(dptr));
827 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
828 /* We ran past the end of the captured
829 data in the packet. */
833 proto_tree_add_text(rr_tree, cur_offset,
834 data_len, "(incomplete entry)");
837 proto_tree_add_text(rr_tree, cur_offset, 2,
838 "Number of alignment errors: %u", pntohs(dptr));
843 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
844 /* We ran past the end of the captured
845 data in the packet. */
849 proto_tree_add_text(rr_tree, cur_offset,
850 data_len, "(incomplete entry)");
853 proto_tree_add_text(rr_tree, cur_offset, 2,
854 "Number of collisions: %u", pntohs(dptr));
859 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
860 /* We ran past the end of the captured
861 data in the packet. */
865 proto_tree_add_text(rr_tree, cur_offset,
866 data_len, "(incomplete entry)");
869 proto_tree_add_text(rr_tree, cur_offset, 2,
870 "Number of send aborts: %u", pntohs(dptr));
875 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
876 /* We ran past the end of the captured
877 data in the packet. */
881 proto_tree_add_text(rr_tree, cur_offset,
882 data_len, "(incomplete entry)");
885 proto_tree_add_text(rr_tree, cur_offset, 4,
886 "Number of good sends: %u", pntohl(dptr));
891 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
892 /* We ran past the end of the captured
893 data in the packet. */
897 proto_tree_add_text(rr_tree, cur_offset,
898 data_len, "(incomplete entry)");
901 proto_tree_add_text(rr_tree, cur_offset, 4,
902 "Number of good receives: %u", pntohl(dptr));
907 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
908 /* We ran past the end of the captured
909 data in the packet. */
913 proto_tree_add_text(rr_tree, cur_offset,
914 data_len, "(incomplete entry)");
917 proto_tree_add_text(rr_tree, cur_offset, 2,
918 "Number of retransmits: %u", pntohs(dptr));
923 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
924 /* We ran past the end of the captured
925 data in the packet. */
929 proto_tree_add_text(rr_tree, cur_offset,
930 data_len, "(incomplete entry)");
933 proto_tree_add_text(rr_tree, cur_offset, 2,
934 "Number of no resource conditions: %u", pntohs(dptr));
939 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
940 /* We ran past the end of the captured
941 data in the packet. */
945 proto_tree_add_text(rr_tree, cur_offset,
946 data_len, "(incomplete entry)");
949 proto_tree_add_text(rr_tree, cur_offset, 2,
950 "Number of command blocks: %u", pntohs(dptr));
955 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
956 /* We ran past the end of the captured
957 data in the packet. */
961 proto_tree_add_text(rr_tree, cur_offset,
962 data_len, "(incomplete entry)");
965 proto_tree_add_text(rr_tree, cur_offset, 2,
966 "Number of pending sessions: %u", pntohs(dptr));
971 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
972 /* We ran past the end of the captured
973 data in the packet. */
977 proto_tree_add_text(rr_tree, cur_offset,
978 data_len, "(incomplete entry)");
981 proto_tree_add_text(rr_tree, cur_offset, 2,
982 "Max number of pending sessions: %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, cur_offset,
993 data_len, "(incomplete entry)");
996 proto_tree_add_text(rr_tree, cur_offset, 2,
997 "Max total sessions possible: %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, cur_offset,
1009 data_len, "(incomplete entry)");
1012 proto_tree_add_text(rr_tree, cur_offset, 2,
1013 "Session data packet size: %u", pntohs(dptr));
1022 col_append_fstr(fd, COL_INFO, " %s", type_name);
1023 if (nbns_tree == NULL)
1025 trr = proto_tree_add_text(nbns_tree, offset,
1026 (dptr - data_start) + data_len,
1027 "%s: type %s, class %s",
1028 name, type_name, class_name);
1029 rr_tree = add_rr_to_tree(trr, ETT_NBNS_RR, offset, name,
1030 name_len, type_name, class_name, ttl, data_len);
1031 proto_tree_add_text(rr_tree, cur_offset, data_len, "Data");
1036 return dptr - data_start;
1040 dissect_query_records(const u_char *pd, int cur_off, int nbns_data_offset,
1041 int count, frame_data *fd, proto_tree *nbns_tree)
1043 int start_off, add_off;
1044 proto_tree *qatree = NULL;
1045 proto_item *ti = NULL;
1047 start_off = cur_off;
1048 if (nbns_tree != NULL) {
1049 ti = proto_tree_add_text(nbns_tree, start_off, 0, "Queries");
1050 qatree = proto_item_add_subtree(ti, ETT_NBNS_QRY);
1052 while (count-- > 0) {
1053 add_off = dissect_nbns_query(pd, cur_off, nbns_data_offset,
1056 /* We ran past the end of the captured data in the
1063 proto_item_set_len(ti, cur_off - start_off);
1065 return cur_off - start_off;
1071 dissect_answer_records(const u_char *pd, int cur_off, int nbns_data_offset,
1072 int count, frame_data *fd, proto_tree *nbns_tree, int opcode, char *name)
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, start_off, 0, name);
1081 qatree = proto_item_add_subtree(ti, ETT_NBNS_ANS);
1083 while (count-- > 0) {
1084 add_off = dissect_nbns_answer(pd, cur_off, nbns_data_offset,
1085 fd, qatree, opcode);
1087 /* We ran past the end of the captured data in the
1094 proto_item_set_len(ti, cur_off - start_off);
1095 return cur_off - start_off;
1099 dissect_nbns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1101 int nbns_data_offset;
1102 proto_tree *nbns_tree = NULL;
1104 guint16 id, flags, quest, ans, auth, add;
1107 nbns_data_offset = offset;
1109 if (check_col(fd, COL_PROTOCOL))
1110 col_add_str(fd, COL_PROTOCOL, "NBNS (UDP)");
1112 if (pi.captured_len < NBNS_HDRLEN) {
1113 col_add_str(fd, COL_INFO, "Short NBNS packet");
1114 dissect_data(pd, offset, fd, tree);
1118 /* To do: check for runts, errs, etc. */
1119 id = pntohs(&pd[offset + NBNS_ID]);
1120 flags = pntohs(&pd[offset + NBNS_FLAGS]);
1121 quest = pntohs(&pd[offset + NBNS_QUEST]);
1122 ans = pntohs(&pd[offset + NBNS_ANS]);
1123 auth = pntohs(&pd[offset + NBNS_AUTH]);
1124 add = pntohs(&pd[offset + NBNS_ADD]);
1126 if (check_col(fd, COL_INFO)) {
1127 col_add_fstr(fd, COL_INFO, "%s%s",
1128 val_to_str(flags & F_OPCODE, opcode_vals,
1129 "Unknown operation (%x)"),
1130 (flags & F_RESPONSE) ? " response" : "");
1132 /* Set "fd" to NULL; we pass a NULL "fd" to the query and
1133 answer dissectors, as a way of saying that they shouldn't
1134 add stuff to the COL_INFO column (a call to
1135 "check_col(fd, COL_INFO)" is more expensive than a check
1136 that a pointer isn't NULL). */
1141 ti = proto_tree_add_item(tree, proto_nbns, offset, END_OF_FRAME, NULL);
1142 nbns_tree = proto_item_add_subtree(ti, ETT_NBNS);
1144 if (flags & F_RESPONSE) {
1145 proto_tree_add_item_hidden(nbns_tree, hf_nbns_response,
1148 proto_tree_add_item_hidden(nbns_tree, hf_nbns_query,
1152 proto_tree_add_item(nbns_tree, hf_nbns_transaction_id,
1153 offset + NBNS_ID, 2, id);
1155 nbns_add_nbns_flags(nbns_tree, offset + NBNS_FLAGS, flags, 0);
1156 proto_tree_add_item(nbns_tree, hf_nbns_count_questions,
1157 offset + NBNS_QUEST, 2, quest);
1158 proto_tree_add_item(nbns_tree, hf_nbns_count_answers,
1159 offset + NBNS_ANS, 2, ans);
1160 proto_tree_add_item(nbns_tree, hf_nbns_count_auth_rr,
1161 offset + NBNS_AUTH, 2, auth);
1162 proto_tree_add_item(nbns_tree, hf_nbns_count_add_rr,
1163 offset + NBNS_ADD, 2, add);
1166 cur_off = offset + NBNS_HDRLEN;
1169 /* If this is a response, don't add information about the
1170 queries to the summary, just add information about the
1172 cur_off += dissect_query_records(pd, cur_off,
1173 nbns_data_offset, quest,
1174 (!(flags & F_RESPONSE) ? fd : NULL), nbns_tree);
1178 /* If this is a request, don't add information about the
1179 answers to the summary, just add information about the
1181 cur_off += dissect_answer_records(pd, cur_off,
1182 nbns_data_offset, ans,
1183 ((flags & F_RESPONSE) ? fd : NULL), nbns_tree,
1184 flags & F_OPCODE, "Answers");
1188 /* Don't add information about the authoritative name
1189 servers, or the additional records, to the summary. */
1191 cur_off += dissect_answer_records(pd, cur_off,
1193 auth, NULL, nbns_tree,
1195 "Authoritative nameservers");
1198 cur_off += dissect_answer_records(pd, cur_off,
1200 add, NULL, nbns_tree,
1202 "Additional records");
1206 /* NetBIOS datagram packet, from RFC 1002, page 32 */
1207 struct nbdgm_header {
1218 /* For packets with data */
1222 /* For error packets */
1227 dissect_nbdgm(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1229 proto_tree *nbdgm_tree = NULL;
1231 struct nbdgm_header header;
1234 int max_data = pi.captured_len - offset;
1238 "Direct_unique datagram",
1239 "Direct_group datagram",
1240 "Broadcast datagram",
1242 "Datagram query request",
1243 "Datagram positive query response",
1244 "Datagram negative query response"
1254 static value_string error_codes[] = {
1255 { 0x82, "Destination name not present" },
1256 { 0x83, "Invalid source name format" },
1257 { 0x84, "Invalid destination name format" },
1261 char *yesno[] = { "No", "Yes" };
1263 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1267 header.msg_type = pd[offset];
1269 flags = pd[offset+1];
1270 header.flags.more = flags & 1;
1271 header.flags.first = (flags & 2) >> 1;
1272 header.flags.node_type = (flags & 12) >> 2;
1274 header.dgm_id = pntohs(&pd[offset+2]);
1275 memcpy(&header.src_ip, &pd[offset+4], 4);
1276 header.src_port = pntohs(&pd[offset+8]);
1278 if (header.msg_type == 0x10 ||
1279 header.msg_type == 0x11 || header.msg_type == 0x12) {
1280 header.dgm_length = pntohs(&pd[offset+10]);
1281 header.pkt_offset = pntohs(&pd[offset+12]);
1283 else if (header.msg_type == 0x13) {
1284 header.error_code = pntohs(&pd[offset+10]);
1287 message_index = header.msg_type - 0x0f;
1288 if (message_index < 1 || message_index > 8) {
1292 if (check_col(fd, COL_PROTOCOL))
1293 col_add_str(fd, COL_PROTOCOL, "NBDS (UDP)");
1294 if (check_col(fd, COL_INFO)) {
1295 col_add_fstr(fd, COL_INFO, "%s", message[message_index]);
1299 ti = proto_tree_add_item(tree, proto_nbdgm, offset, header.dgm_length, NULL);
1300 nbdgm_tree = proto_item_add_subtree(ti, ETT_NBDGM);
1302 proto_tree_add_item_format(nbdgm_tree, hf_nbdgm_type,
1306 message[message_index]);
1307 proto_tree_add_item_format(nbdgm_tree, hf_nbdgm_fragment,
1310 "More fragments follow: %s",
1311 yesno[header.flags.more]);
1312 proto_tree_add_item_format(nbdgm_tree, hf_nbdgm_first,
1315 "This is first fragment: %s",
1316 yesno[header.flags.first]);
1317 proto_tree_add_item_format(nbdgm_tree, hf_nbdgm_node_type,
1319 header.flags.node_type,
1321 node[header.flags.node_type]);
1323 proto_tree_add_item(nbdgm_tree, hf_nbdgm_datagram_id,
1324 offset+2, 2, header.dgm_id);
1325 proto_tree_add_item(nbdgm_tree, hf_nbdgm_src_ip,
1326 offset+4, 4, header.src_ip);
1327 proto_tree_add_item(nbdgm_tree, hf_nbdgm_src_port,
1328 offset+8, 2, header.src_port);
1335 if (header.msg_type == 0x10 ||
1336 header.msg_type == 0x11 || header.msg_type == 0x12) {
1339 proto_tree_add_text(nbdgm_tree, offset, 2,
1340 "Datagram length: %d bytes", header.dgm_length);
1341 proto_tree_add_text(nbdgm_tree, offset+2, 2,
1342 "Packet offset: %d bytes", header.pkt_offset);
1349 len = get_nbns_name(pd, offset, offset, name, &name_type);
1352 add_name_and_type(nbdgm_tree, offset, len,
1353 "Source name", name, name_type);
1358 /* Destination name */
1359 len = get_nbns_name(pd, offset, offset, name, &name_type);
1362 add_name_and_type(nbdgm_tree, offset, len,
1363 "Destination name", name, name_type);
1368 /* here we can pass the packet off to the next protocol */
1369 dissect_smb(pd, offset, fd, tree, max_data);
1371 else if (header.msg_type == 0x13) {
1373 proto_tree_add_text(nbdgm_tree, offset, 1, "Error code: %s",
1374 val_to_str(header.error_code, error_codes, "Unknown (0x%x)"));
1377 else if (header.msg_type == 0x14 ||
1378 header.msg_type == 0x15 || header.msg_type == 0x16) {
1379 /* Destination name */
1380 len = get_nbns_name(pd, offset, offset, name, &name_type);
1383 add_name_and_type(nbdgm_tree, offset, len,
1384 "Destination name", name, name_type);
1390 * NetBIOS Session Service message types.
1392 #define SESSION_MESSAGE 0x00
1393 #define SESSION_REQUEST 0x81
1394 #define POSITIVE_SESSION_RESPONSE 0x82
1395 #define NEGATIVE_SESSION_RESPONSE 0x83
1396 #define RETARGET_SESSION_RESPONSE 0x84
1397 #define SESSION_KEEP_ALIVE 0x85
1399 static const value_string message_types[] = {
1400 { SESSION_MESSAGE, "Session message" },
1401 { SESSION_REQUEST, "Session request" },
1402 { POSITIVE_SESSION_RESPONSE, "Positive session response" },
1403 { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
1404 { RETARGET_SESSION_RESPONSE, "Retarget session response" },
1405 { SESSION_KEEP_ALIVE, "Session keep-alive" },
1410 * NetBIOS Session Service flags.
1412 #define NBSS_FLAGS_E 0x1
1414 static const value_string error_codes[] = {
1415 { 0x80, "Not listening on called name" },
1416 { 0x81, "Not listening for called name" },
1417 { 0x82, "Called name not present" },
1418 { 0x83, "Called name present, but insufficient resources" },
1419 { 0x8F, "Unspecified error" },
1424 * Dissect a single NBSS packet (there may be more than one in a given TCP
1425 * segment). Hmmm, in my experience, I have never seen more than one NBSS
1426 * in a single segment, since they mostly contain SMBs which are essentially
1427 * a request response type protocol (RJS). Also, a single session message
1428 * may be split over multiple segments.
1431 dissect_nbss_packet(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data)
1433 proto_tree *nbss_tree = NULL;
1435 proto_tree *field_tree;
1441 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1444 msg_type = pd[offset];
1445 flags = pd[offset + 1];
1446 length = pntohs(&pd[offset + 2]);
1447 if (flags & NBSS_FLAGS_E)
1451 ti = proto_tree_add_item(tree, proto_nbss, offset, length + 4, NULL);
1452 nbss_tree = proto_item_add_subtree(ti, ETT_NBSS);
1454 proto_tree_add_item_format(nbss_tree, hf_nbss_type,
1458 val_to_str(msg_type, message_types,
1465 tf = proto_tree_add_item(nbss_tree, hf_nbss_flags, offset, 1, flags);
1466 field_tree = proto_item_add_subtree(tf, ETT_NBSS_FLAGS);
1467 proto_tree_add_text(field_tree, offset, 1, "%s",
1468 decode_boolean_bitfield(flags, NBSS_FLAGS_E,
1469 8, "Add 65536 to length", "Add 0 to length"));
1475 proto_tree_add_text(nbss_tree, offset, 2, "Length: %u", length);
1482 case SESSION_REQUEST:
1483 len = get_nbns_name(pd, offset, offset, name, &name_type);
1485 add_name_and_type(nbss_tree, offset, len,
1486 "Called name", name, name_type);
1489 len = get_nbns_name(pd, offset, offset, name, &name_type);
1492 add_name_and_type(nbss_tree, offset, len,
1493 "Calling name", name, name_type);
1497 case NEGATIVE_SESSION_RESPONSE:
1499 proto_tree_add_text(nbss_tree, offset, 1,
1501 val_to_str(pd[offset], error_codes, "Unknown (%x)"));
1504 case RETARGET_SESSION_RESPONSE:
1506 proto_tree_add_text(nbss_tree, offset, 4,
1507 "Retarget IP address: %s",
1508 ip_to_str((guint8 *)&pd[offset]));
1513 proto_tree_add_text(nbss_tree, offset, 2,
1514 "Retarget port: %u", pntohs(&pd[offset]));
1518 case SESSION_MESSAGE:
1520 * Here we can pass the packet off to the next protocol.
1523 dissect_smb(pd, offset, fd, tree, max_data - 4);
1532 dissect_nbss(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1540 msg_type = pd[offset];
1541 flags = pd[offset + 1];
1542 length = pntohs(&pd[offset + 2]);
1543 if (flags & NBSS_FLAGS_E)
1547 * XXX - we should set this based on both "pi.captured_len"
1550 max_data = pi.captured_len - offset;
1552 /* Hmmm, it may be a continuation message ... */
1556 if (((msg_type != SESSION_REQUEST) &&
1557 (msg_type != POSITIVE_SESSION_RESPONSE) &&
1558 (msg_type != NEGATIVE_SESSION_RESPONSE) &&
1559 (msg_type != RETARGET_SESSION_RESPONSE) &&
1560 (msg_type != SESSION_MESSAGE)) ||
1561 ((msg_type == SESSION_MESSAGE) &&
1562 (memcmp(pd + offset + 4, "\377SMB", 4) != 0))) {
1564 if (check_col(fd, COL_PROTOCOL))
1565 col_add_str(fd, COL_PROTOCOL, "NBSS (TCP)");
1566 if (check_col(fd, COL_INFO)) {
1567 col_add_fstr(fd, COL_INFO, "NBSS (TCP) Continuation Message");
1571 proto_tree_add_text(tree, offset, max_data, "Continuation data");
1577 if (check_col(fd, COL_PROTOCOL))
1578 col_add_str(fd, COL_PROTOCOL, "NBSS (TCP)");
1579 if (check_col(fd, COL_INFO)) {
1580 col_add_fstr(fd, COL_INFO,
1581 val_to_str(msg_type, message_types, "Unknown (%x)"));
1584 while (max_data > 0) {
1585 len = dissect_nbss_packet(pd, offset, fd, tree, max_data);
1593 proto_register_nbt(void)
1596 static hf_register_info hf_nbns[] = {
1597 { &hf_nbns_response,
1598 { "Response", "nbns.response",
1599 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1600 "TRUE if NBNS response" }},
1602 { "Query", "nbns.query",
1603 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1604 "TRUE if NBNS query" }},
1605 { &hf_nbns_transaction_id,
1606 { "Transaction ID", "nbns.id",
1607 FT_UINT16, BASE_HEX, NULL, 0x0,
1608 "Identification of transaction" }},
1609 { &hf_nbns_count_questions,
1610 { "Questions", "nbns.count.queries",
1611 FT_UINT16, BASE_DEC, NULL, 0x0,
1612 "Number of queries in packet" }},
1613 { &hf_nbns_count_answers,
1614 { "Answer RRs", "nbns.count.answers",
1615 FT_UINT16, BASE_DEC, NULL, 0x0,
1616 "Number of answers in packet" }},
1617 { &hf_nbns_count_auth_rr,
1618 { "Authority RRs", "nbns.count.auth_rr",
1619 FT_UINT16, BASE_DEC, NULL, 0x0,
1620 "Number of authoritative records in packet" }},
1621 { &hf_nbns_count_add_rr,
1622 { "Additional RRs", "nbns.count.add_rr",
1623 FT_UINT16, BASE_DEC, NULL, 0x0,
1624 "Number of additional records in packet" }}
1627 static hf_register_info hf_nbdgm[] = {
1629 { "Message Type", "nbdgm.type",
1630 FT_UINT8, BASE_DEC, NULL, 0x0,
1631 "NBDGM message type" }},
1632 { &hf_nbdgm_fragment,
1633 { "Fragmented", "nbdgm.next",
1634 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1635 "TRUE if more fragments follow" }},
1637 { "First fragment", "nbdgm.first",
1638 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1639 "TRUE if first fragment" }},
1640 { &hf_nbdgm_node_type,
1641 { "Node Type", "nbdgm.node_type",
1642 FT_UINT8, BASE_DEC, NULL, 0x0,
1644 { &hf_nbdgm_datagram_id,
1645 { "Datagram ID", "nbdgm.dgram_id",
1646 FT_UINT16, BASE_HEX, NULL, 0x0,
1647 "Datagram identifier" }},
1649 { "Source IP", "nbdgm.src.ip",
1650 FT_IPv4, BASE_NONE, NULL, 0x0,
1651 "Source IPv4 address" }},
1652 { &hf_nbdgm_src_port,
1653 { "Source Port", "nbdgm.src.port",
1654 FT_UINT16, BASE_DEC, NULL, 0x0,
1658 static hf_register_info hf_nbss[] = {
1660 { "Message Type", "nbss.type",
1661 FT_UINT8, BASE_DEC, NULL, 0x0,
1662 "NBSS message type" }},
1664 { "Flags", "nbss.flags",
1665 FT_UINT8, BASE_HEX, NULL, 0x0,
1666 "NBSS message flags" }}
1669 proto_nbns = proto_register_protocol("NetBIOS Name Service", "nbns");
1670 proto_register_field_array(proto_nbns, hf_nbns, array_length(hf_nbns));
1672 proto_nbdgm = proto_register_protocol("NetBIOS Datagram Service", "nbdgm");
1673 proto_register_field_array(proto_nbdgm, hf_nbdgm, array_length(hf_nbdgm));
1675 proto_nbss = proto_register_protocol("NetBIOS Session Service", "nbss");
1676 proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));