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.39 2000/04/08 07:07:29 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 #define UDP_PORT_NBNS 137
83 #define UDP_PORT_NBDGM 138
84 #define TCP_PORT_NBSS 139
86 /* Packet structure taken from RFC 1002. See also RFC 1001.
87 * Opcode, flags, and rcode treated as "flags", similarly to DNS,
88 * to make it easier to lift the dissection code from "packet-dns.c". */
90 /* Offsets of fields in the NBNS header. */
98 /* Length of NBNS header. */
99 #define NBNS_HDRLEN 12
102 #define T_NB 32 /* NetBIOS name service RR */
103 #define T_NBSTAT 33 /* NetBIOS node status RR */
105 /* Bit fields in the flags */
106 #define F_RESPONSE (1<<15) /* packet is response */
107 #define F_OPCODE (0xF<<11) /* query opcode */
108 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
109 #define F_TRUNCATED (1<<9) /* response is truncated */
110 #define F_RECDESIRED (1<<8) /* recursion desired */
111 #define F_RECAVAIL (1<<7) /* recursion available */
112 #define F_BROADCAST (1<<4) /* broadcast/multicast packet */
113 #define F_RCODE (0xF<<0) /* reply code */
116 #define OPCODE_QUERY (0<<11) /* standard query */
117 #define OPCODE_REGISTRATION (5<<11) /* registration */
118 #define OPCODE_RELEASE (6<<11) /* release name */
119 #define OPCODE_WACK (7<<11) /* wait for acknowledgement */
120 #define OPCODE_REFRESH (8<<11) /* refresh registration */
121 #define OPCODE_REFRESHALT (9<<11) /* refresh registration (alternate opcode) */
122 #define OPCODE_MHREGISTRATION (15<<11) /* multi-homed registration */
125 #define RCODE_NOERROR (0<<0)
126 #define RCODE_FMTERROR (1<<0)
127 #define RCODE_SERVFAIL (2<<0)
128 #define RCODE_NAMEERROR (3<<0)
129 #define RCODE_NOTIMPL (4<<0)
130 #define RCODE_REFUSED (5<<0)
131 #define RCODE_ACTIVE (6<<0)
132 #define RCODE_CONFLICT (7<<0)
134 /* Values for the "NB_FLAGS" field of RR data. From RFC 1001 and 1002,
135 * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
137 #define NB_FLAGS_ONT (3<<(15-2)) /* bits for node type */
138 #define NB_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
139 #define NB_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
140 #define NB_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
141 #define NB_FLAGS_ONT_H_NODE (3<<(15-2)) /* H-mode node */
143 #define NB_FLAGS_G (1<<(15-0)) /* group name */
145 /* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
146 * RR data. From RFC 1001 and 1002, except for NAME_FLAGS_ONT_H_NODE,
147 * which was discovered by looking at packet traces. */
148 #define NAME_FLAGS_PRM (1<<(15-6)) /* name is permanent node name */
150 #define NAME_FLAGS_ACT (1<<(15-5)) /* name is active */
152 #define NAME_FLAGS_CNF (1<<(15-4)) /* name is in conflict */
154 #define NAME_FLAGS_DRG (1<<(15-3)) /* name is being deregistered */
156 #define NAME_FLAGS_ONT (3<<(15-2)) /* bits for node type */
157 #define NAME_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
158 #define NAME_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
159 #define NAME_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
161 #define NAME_FLAGS_G (1<<(15-0)) /* group name */
163 static const value_string opcode_vals[] = {
164 { OPCODE_QUERY, "Name query" },
165 { OPCODE_REGISTRATION, "Registration" },
166 { OPCODE_RELEASE, "Release" },
167 { OPCODE_WACK, "Wait for acknowledgment" },
168 { OPCODE_REFRESH, "Refresh" },
169 { OPCODE_REFRESHALT, "Refresh (alternate opcode)" },
170 { OPCODE_MHREGISTRATION, "Multi-homed registration" },
175 nbns_type_name (int type)
188 get_nbns_name(const u_char *pd, int offset, int nbns_data_offset,
189 char *name_ret, int *name_type_ret)
193 char nbname[NETBIOS_NAME_LEN];
194 char *pname, *pnbname, cname, cnbname;
197 name_len = get_dns_name(pd, offset, nbns_data_offset, name,
200 /* OK, now undo the first-level encoding. */
202 pnbname = &nbname[0];
204 /* Every two characters of the first level-encoded name
205 * turn into one character in the decoded name. */
208 break; /* no more characters */
210 break; /* scope ID follows */
211 if (cname < 'A' || cname > 'Z') {
214 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
218 cnbname = cname << 4;
222 if (cname == '\0' || cname == '.') {
223 /* No more characters in the name - but we're in
224 * the middle of a pair. Not legal. */
226 "Illegal NetBIOS name (odd number of bytes)");
229 if (cname < 'A' || cname > 'Z') {
232 "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
239 /* Do we have room to store the character? */
240 if (pnbname < &nbname[NETBIOS_NAME_LEN]) {
241 /* Yes - store the character. */
245 /* We bump the pointer even if it's past the end of the
246 name, so we keep track of how long the name is. */
250 /* NetBIOS names are supposed to be exactly 16 bytes long. */
251 if (pnbname - nbname != NETBIOS_NAME_LEN) {
253 sprintf(nbname, "Illegal NetBIOS name (%ld bytes long)",
254 (long)(pnbname - nbname));
258 /* This one is; make its name printable. */
259 name_type = process_netbios_name(nbname, name_ret);
260 name_ret += strlen(name_ret);
261 sprintf(name_ret, "<%02x>", name_type);
264 /* We have a scope ID, starting at "pname"; append that to
265 * the decoded host name. */
266 strcpy(name_ret, pname);
268 if (name_type_ret != NULL)
269 *name_type_ret = name_type;
273 if (name_type_ret != NULL)
275 strcpy (name_ret, nbname);
281 get_nbns_name_type_class(const u_char *pd, int offset, int nbns_data_offset,
282 char *name_ret, int *name_len_ret, int *name_type_ret, int *type_ret,
289 name_len = get_nbns_name(pd, offset, nbns_data_offset, name_ret,
293 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
294 /* We ran past the end of the captured data in the packet. */
297 type = pntohs(&pd[offset]);
300 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
301 /* We ran past the end of the captured data in the packet. */
304 class = pntohs(&pd[offset]);
308 *name_len_ret = name_len;
314 add_name_and_type(proto_tree *tree, int offset, int len, char *tag,
315 char *name, int name_type)
317 if (name_type != -1) {
318 proto_tree_add_text(tree, offset, len, "%s: %s (%s)",
319 tag, name, netbios_name_type_descr(name_type));
321 proto_tree_add_text(tree, offset, len, "%s: %s",
327 dissect_nbns_query(const u_char *pd, int offset, int nbns_data_offset,
328 frame_data *fd, proto_tree *nbns_tree)
331 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
339 const u_char *data_start;
343 data_start = dptr = pd + offset;
345 len = get_nbns_name_type_class(pd, offset, nbns_data_offset, name,
346 &name_len, &name_type, &type, &class);
348 /* We ran past the end of the data in the packet. */
353 type_name = nbns_type_name(type);
354 class_name = dns_class_name(class);
357 col_append_fstr(fd, COL_INFO, " %s %s", type_name, name);
358 if (nbns_tree != NULL) {
359 tq = proto_tree_add_text(nbns_tree, offset, len,
360 "%s: type %s, class %s", name, type_name, class_name);
361 q_tree = proto_item_add_subtree(tq, ett_nbns_qd);
363 add_name_and_type(q_tree, offset, name_len, "Name", name,
367 proto_tree_add_text(q_tree, offset, 2, "Type: %s", type_name);
370 proto_tree_add_text(q_tree, offset, 2, "Class: %s", class_name);
374 return dptr - data_start;
378 nbns_add_nbns_flags(proto_tree *nbns_tree, int offset, u_short flags,
382 proto_tree *field_tree;
384 static const value_string rcode_vals[] = {
385 { RCODE_NOERROR, "No error" },
386 { RCODE_FMTERROR, "Request was invalidly formatted" },
387 { RCODE_SERVFAIL, "Server failure" },
388 { RCODE_NAMEERROR, "Requested name does not exist" },
389 { RCODE_NOTIMPL, "Request is not implemented" },
390 { RCODE_REFUSED, "Request was refused" },
391 { RCODE_ACTIVE, "Name is owned by another node" },
392 { RCODE_CONFLICT, "Name is in conflict" },
396 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals,
397 "Unknown operation"));
398 if (flags & F_RESPONSE && !is_wack) {
399 strcat(buf, " response");
401 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
404 tf = proto_tree_add_text(nbns_tree, offset, 2,
405 "Flags: 0x%04x (%s)", flags, buf);
406 field_tree = proto_item_add_subtree(tf, ett_nbns_flags);
407 proto_tree_add_text(field_tree, offset, 2, "%s",
408 decode_boolean_bitfield(flags, F_RESPONSE,
409 2*8, "Response", "Query"));
410 proto_tree_add_text(field_tree, offset, 2, "%s",
411 decode_enumerated_bitfield(flags, F_OPCODE,
412 2*8, opcode_vals, "%s"));
413 if (flags & F_RESPONSE) {
414 proto_tree_add_text(field_tree, offset, 2,
416 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
418 "Server is an authority for domain",
419 "Server isn't an authority for domain"));
421 proto_tree_add_text(field_tree, offset, 2, "%s",
422 decode_boolean_bitfield(flags, F_TRUNCATED,
424 "Message is truncated",
425 "Message is not truncated"));
426 proto_tree_add_text(field_tree, offset, 2, "%s",
427 decode_boolean_bitfield(flags, F_RECDESIRED,
429 "Do query recursively",
430 "Don't do query recursively"));
431 if (flags & F_RESPONSE) {
432 proto_tree_add_text(field_tree, offset, 2,
434 decode_boolean_bitfield(flags, F_RECAVAIL,
436 "Server can do recursive queries",
437 "Server can't do recursive queries"));
439 proto_tree_add_text(field_tree, offset, 2, "%s",
440 decode_boolean_bitfield(flags, F_BROADCAST,
443 "Not a broadcast packet"));
444 if (flags & F_RESPONSE && !is_wack) {
445 proto_tree_add_text(field_tree, offset, 2,
447 decode_enumerated_bitfield(flags, F_RCODE,
454 nbns_add_nb_flags(proto_tree *rr_tree, int offset, u_short flags)
457 proto_tree *field_tree;
459 static const value_string nb_flags_ont_vals[] = {
460 { NB_FLAGS_ONT_B_NODE, "B-node" },
461 { NB_FLAGS_ONT_P_NODE, "P-node" },
462 { NB_FLAGS_ONT_M_NODE, "M-node" },
463 { NB_FLAGS_ONT_H_NODE, "H-node" },
467 strcpy(buf, val_to_str(flags & NB_FLAGS_ONT, nb_flags_ont_vals,
470 if (flags & NB_FLAGS_G)
471 strcat(buf, "group");
473 strcat(buf, "unique");
474 tf = proto_tree_add_text(rr_tree, offset, 2, "Flags: 0x%x (%s)", flags,
476 field_tree = proto_item_add_subtree(tf, ett_nbns_nb_flags);
477 proto_tree_add_text(field_tree, offset, 2, "%s",
478 decode_boolean_bitfield(flags, NB_FLAGS_G,
482 proto_tree_add_text(field_tree, offset, 2, "%s",
483 decode_enumerated_bitfield(flags, NB_FLAGS_ONT,
484 2*8, nb_flags_ont_vals, "%s"));
488 nbns_add_name_flags(proto_tree *rr_tree, int offset, u_short flags)
491 proto_item *field_tree;
493 static const value_string name_flags_ont_vals[] = {
494 { NAME_FLAGS_ONT_B_NODE, "B-node" },
495 { NAME_FLAGS_ONT_P_NODE, "P-node" },
496 { NAME_FLAGS_ONT_M_NODE, "M-node" },
500 strcpy(buf, val_to_str(flags & NAME_FLAGS_ONT, name_flags_ont_vals,
503 if (flags & NAME_FLAGS_G)
504 strcat(buf, "group");
506 strcat(buf, "unique");
507 if (flags & NAME_FLAGS_DRG)
508 strcat(buf, ", being deregistered");
509 if (flags & NAME_FLAGS_CNF)
510 strcat(buf, ", in conflict");
511 if (flags & NAME_FLAGS_ACT)
512 strcat(buf, ", active");
513 if (flags & NAME_FLAGS_PRM)
514 strcat(buf, ", permanent node name");
515 tf = proto_tree_add_text(rr_tree, offset, 2, "Name flags: 0x%x (%s)",
517 field_tree = proto_item_add_subtree(tf, ett_nbns_name_flags);
518 proto_tree_add_text(field_tree, offset, 2, "%s",
519 decode_boolean_bitfield(flags, NAME_FLAGS_G,
523 proto_tree_add_text(field_tree, offset, 2, "%s",
524 decode_enumerated_bitfield(flags, NAME_FLAGS_ONT,
525 2*8, name_flags_ont_vals, "%s"));
526 proto_tree_add_text(field_tree, offset, 2, "%s",
527 decode_boolean_bitfield(flags, NAME_FLAGS_DRG,
529 "Name is being deregistered",
530 "Name is not being deregistered"));
531 proto_tree_add_text(field_tree, offset, 2, "%s",
532 decode_boolean_bitfield(flags, NAME_FLAGS_CNF,
534 "Name is in conflict",
535 "Name is not in conflict"));
536 proto_tree_add_text(field_tree, offset, 2, "%s",
537 decode_boolean_bitfield(flags, NAME_FLAGS_ACT,
540 "Name is not active"));
541 proto_tree_add_text(field_tree, offset, 2, "%s",
542 decode_boolean_bitfield(flags, NAME_FLAGS_PRM,
544 "Permanent node name",
545 "Not permanent node name"));
549 dissect_nbns_answer(const u_char *pd, int offset, int nbns_data_offset,
550 frame_data *fd, proto_tree *nbns_tree, int opcode)
553 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME + 64];
562 const u_char *data_start;
568 char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
570 char nbname[16+4+1]; /* 4 for [<last char>] */
573 data_start = dptr = pd + offset;
576 len = get_nbns_name_type_class(pd, offset, nbns_data_offset, name,
577 &name_len, &name_type, &type, &class);
579 /* We ran past the end of the data in the packet. */
585 type_name = nbns_type_name(type);
586 class_name = dns_class_name(class);
588 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
589 /* We ran past the end of the captured data in the packet. */
596 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
597 /* We ran past the end of the captured data in the packet. */
600 data_len = pntohs(dptr);
605 case T_NB: /* "NB" record */
607 if (opcode != OPCODE_WACK) {
608 col_append_fstr(fd, COL_INFO, " %s %s",
609 type_name, ip_to_str((guint8 *)(dptr + 2)));
612 if (nbns_tree == NULL)
614 trr = proto_tree_add_text(nbns_tree, offset,
615 (dptr - data_start) + data_len,
616 "%s: type %s, class %s",
617 name, type_name, class_name);
619 strcat(name, netbios_name_type_descr(name_type));
621 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, offset, name,
622 name_len, type_name, class_name, ttl, data_len);
623 while (data_len > 0) {
624 if (opcode == OPCODE_WACK) {
625 /* WACK response. This doesn't contain the
626 * same type of RR data as other T_NB
628 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
629 /* We ran past the end of the captured
630 data in the packet. */
634 proto_tree_add_text(rr_tree, cur_offset,
635 data_len, "(incomplete entry)");
638 flags = pntohs(dptr);
640 nbns_add_nbns_flags(rr_tree, cur_offset,
645 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
646 /* We ran past the end of the captured
647 data in the packet. */
651 proto_tree_add_text(rr_tree, cur_offset,
652 data_len, "(incomplete entry)");
655 flags = pntohs(dptr);
657 nbns_add_nb_flags(rr_tree, cur_offset, flags);
661 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
662 /* We ran past the end of the captured
663 data in the packet. */
667 proto_tree_add_text(rr_tree, cur_offset,
668 data_len, "(incomplete entry)");
671 proto_tree_add_text(rr_tree, cur_offset, 4,
673 ip_to_str((guint8 *)dptr));
681 case T_NBSTAT: /* "NBSTAT" record */
683 col_append_fstr(fd, COL_INFO, " %s", type_name);
684 if (nbns_tree == NULL)
686 trr = proto_tree_add_text(nbns_tree, offset,
687 (dptr - data_start) + data_len,
688 "%s: type %s, class %s",
689 name, type_name, class_name);
690 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, offset, name,
691 name_len, type_name, class_name, ttl, data_len);
692 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
693 /* We ran past the end of the captured
694 data in the packet. */
698 proto_tree_add_text(rr_tree, cur_offset,
699 data_len, "(incomplete entry)");
704 proto_tree_add_text(rr_tree, cur_offset, 2,
705 "Number of names: %u", num_names);
708 while (num_names != 0) {
709 if (!BYTES_ARE_IN_FRAME(cur_offset, NETBIOS_NAME_LEN)) {
710 /* We ran past the end of the captured
711 data in the packet. */
714 if (data_len < NETBIOS_NAME_LEN) {
715 proto_tree_add_text(rr_tree, cur_offset,
716 data_len, "(incomplete entry)");
719 memcpy(nbname, dptr, NETBIOS_NAME_LEN);
720 dptr += NETBIOS_NAME_LEN;
721 name_type = process_netbios_name(nbname,
723 proto_tree_add_text(rr_tree, cur_offset,
724 NETBIOS_NAME_LEN, "Name: %s<%02x> (%s)",
726 netbios_name_type_descr(name_type));
727 cur_offset += NETBIOS_NAME_LEN;
728 data_len -= NETBIOS_NAME_LEN;
730 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
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 name_flags = pntohs(dptr);
742 nbns_add_name_flags(rr_tree, cur_offset, name_flags);
749 if (!BYTES_ARE_IN_FRAME(cur_offset, 6)) {
750 /* We ran past the end of the captured
751 data in the packet. */
755 proto_tree_add_text(rr_tree, cur_offset,
756 data_len, "(incomplete entry)");
759 proto_tree_add_text(rr_tree, cur_offset, 6,
761 ether_to_str((guint8 *)dptr));
766 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
767 /* We ran past the end of the captured
768 data in the packet. */
772 proto_tree_add_text(rr_tree, cur_offset,
773 data_len, "(incomplete entry)");
776 proto_tree_add_text(rr_tree, cur_offset, 1,
777 "Jumpers: 0x%x", *dptr);
782 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
783 /* We ran past the end of the captured
784 data in the packet. */
788 proto_tree_add_text(rr_tree, cur_offset,
789 data_len, "(incomplete entry)");
792 proto_tree_add_text(rr_tree, cur_offset, 1,
793 "Test result: 0x%x", *dptr);
798 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
799 /* We ran past the end of the captured
800 data in the packet. */
804 proto_tree_add_text(rr_tree, cur_offset,
805 data_len, "(incomplete entry)");
808 proto_tree_add_text(rr_tree, cur_offset, 2,
809 "Version number: 0x%x", pntohs(dptr));
814 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
815 /* We ran past the end of the captured
816 data in the packet. */
820 proto_tree_add_text(rr_tree, cur_offset,
821 data_len, "(incomplete entry)");
824 proto_tree_add_text(rr_tree, cur_offset, 2,
825 "Period of statistics: 0x%x", pntohs(dptr));
830 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
831 /* We ran past the end of the captured
832 data in the packet. */
836 proto_tree_add_text(rr_tree, cur_offset,
837 data_len, "(incomplete entry)");
840 proto_tree_add_text(rr_tree, cur_offset, 2,
841 "Number of CRCs: %u", pntohs(dptr));
846 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
847 /* We ran past the end of the captured
848 data in the packet. */
852 proto_tree_add_text(rr_tree, cur_offset,
853 data_len, "(incomplete entry)");
856 proto_tree_add_text(rr_tree, cur_offset, 2,
857 "Number of alignment errors: %u", pntohs(dptr));
862 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
863 /* We ran past the end of the captured
864 data in the packet. */
868 proto_tree_add_text(rr_tree, cur_offset,
869 data_len, "(incomplete entry)");
872 proto_tree_add_text(rr_tree, cur_offset, 2,
873 "Number of collisions: %u", pntohs(dptr));
878 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
879 /* We ran past the end of the captured
880 data in the packet. */
884 proto_tree_add_text(rr_tree, cur_offset,
885 data_len, "(incomplete entry)");
888 proto_tree_add_text(rr_tree, cur_offset, 2,
889 "Number of send aborts: %u", pntohs(dptr));
894 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
895 /* We ran past the end of the captured
896 data in the packet. */
900 proto_tree_add_text(rr_tree, cur_offset,
901 data_len, "(incomplete entry)");
904 proto_tree_add_text(rr_tree, cur_offset, 4,
905 "Number of good sends: %u", pntohl(dptr));
910 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
911 /* We ran past the end of the captured
912 data in the packet. */
916 proto_tree_add_text(rr_tree, cur_offset,
917 data_len, "(incomplete entry)");
920 proto_tree_add_text(rr_tree, cur_offset, 4,
921 "Number of good receives: %u", pntohl(dptr));
926 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
927 /* We ran past the end of the captured
928 data in the packet. */
932 proto_tree_add_text(rr_tree, cur_offset,
933 data_len, "(incomplete entry)");
936 proto_tree_add_text(rr_tree, cur_offset, 2,
937 "Number of retransmits: %u", pntohs(dptr));
942 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
943 /* We ran past the end of the captured
944 data in the packet. */
948 proto_tree_add_text(rr_tree, cur_offset,
949 data_len, "(incomplete entry)");
952 proto_tree_add_text(rr_tree, cur_offset, 2,
953 "Number of no resource conditions: %u", pntohs(dptr));
958 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
959 /* We ran past the end of the captured
960 data in the packet. */
964 proto_tree_add_text(rr_tree, cur_offset,
965 data_len, "(incomplete entry)");
968 proto_tree_add_text(rr_tree, cur_offset, 2,
969 "Number of command blocks: %u", pntohs(dptr));
974 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
975 /* We ran past the end of the captured
976 data in the packet. */
980 proto_tree_add_text(rr_tree, cur_offset,
981 data_len, "(incomplete entry)");
984 proto_tree_add_text(rr_tree, cur_offset, 2,
985 "Number of pending sessions: %u", pntohs(dptr));
990 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
991 /* We ran past the end of the captured
992 data in the packet. */
996 proto_tree_add_text(rr_tree, cur_offset,
997 data_len, "(incomplete entry)");
1000 proto_tree_add_text(rr_tree, cur_offset, 2,
1001 "Max number of pending sessions: %u", pntohs(dptr));
1005 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1006 /* We ran past the end of the captured
1007 data in the packet. */
1011 proto_tree_add_text(rr_tree, cur_offset,
1012 data_len, "(incomplete entry)");
1015 proto_tree_add_text(rr_tree, cur_offset, 2,
1016 "Max total sessions possible: %u", pntohs(dptr));
1021 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1022 /* We ran past the end of the captured
1023 data in the packet. */
1027 proto_tree_add_text(rr_tree, cur_offset,
1028 data_len, "(incomplete entry)");
1031 proto_tree_add_text(rr_tree, cur_offset, 2,
1032 "Session data packet size: %u", pntohs(dptr));
1041 col_append_fstr(fd, COL_INFO, " %s", type_name);
1042 if (nbns_tree == NULL)
1044 trr = proto_tree_add_text(nbns_tree, offset,
1045 (dptr - data_start) + data_len,
1046 "%s: type %s, class %s",
1047 name, type_name, class_name);
1048 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, offset, name,
1049 name_len, type_name, class_name, ttl, data_len);
1050 proto_tree_add_text(rr_tree, cur_offset, data_len, "Data");
1055 return dptr - data_start;
1059 dissect_query_records(const u_char *pd, int cur_off, int nbns_data_offset,
1060 int count, frame_data *fd, proto_tree *nbns_tree)
1062 int start_off, add_off;
1063 proto_tree *qatree = NULL;
1064 proto_item *ti = NULL;
1066 start_off = cur_off;
1067 if (nbns_tree != NULL) {
1068 ti = proto_tree_add_text(nbns_tree, start_off, 0, "Queries");
1069 qatree = proto_item_add_subtree(ti, ett_nbns_qry);
1071 while (count-- > 0) {
1072 add_off = dissect_nbns_query(pd, cur_off, nbns_data_offset,
1075 /* We ran past the end of the captured data in the
1082 proto_item_set_len(ti, cur_off - start_off);
1084 return cur_off - start_off;
1090 dissect_answer_records(const u_char *pd, int cur_off, int nbns_data_offset,
1091 int count, frame_data *fd, proto_tree *nbns_tree, int opcode, char *name)
1093 int start_off, add_off;
1094 proto_tree *qatree = NULL;
1095 proto_item *ti = NULL;
1097 start_off = cur_off;
1098 if (nbns_tree != NULL) {
1099 ti = proto_tree_add_text(nbns_tree, start_off, 0, name);
1100 qatree = proto_item_add_subtree(ti, ett_nbns_ans);
1102 while (count-- > 0) {
1103 add_off = dissect_nbns_answer(pd, cur_off, nbns_data_offset,
1104 fd, qatree, opcode);
1106 /* We ran past the end of the captured data in the
1113 proto_item_set_len(ti, cur_off - start_off);
1114 return cur_off - start_off;
1118 dissect_nbns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1120 int nbns_data_offset;
1121 proto_tree *nbns_tree = NULL;
1123 guint16 id, flags, quest, ans, auth, add;
1126 nbns_data_offset = offset;
1128 if (check_col(fd, COL_PROTOCOL))
1129 col_add_str(fd, COL_PROTOCOL, "NBNS");
1131 if (pi.captured_len < NBNS_HDRLEN) {
1132 col_add_str(fd, COL_INFO, "Short NBNS packet");
1133 dissect_data(pd, offset, fd, tree);
1137 /* To do: check for runts, errs, etc. */
1138 id = pntohs(&pd[offset + NBNS_ID]);
1139 flags = pntohs(&pd[offset + NBNS_FLAGS]);
1140 quest = pntohs(&pd[offset + NBNS_QUEST]);
1141 ans = pntohs(&pd[offset + NBNS_ANS]);
1142 auth = pntohs(&pd[offset + NBNS_AUTH]);
1143 add = pntohs(&pd[offset + NBNS_ADD]);
1145 if (check_col(fd, COL_INFO)) {
1146 col_add_fstr(fd, COL_INFO, "%s%s",
1147 val_to_str(flags & F_OPCODE, opcode_vals,
1148 "Unknown operation (%x)"),
1149 (flags & F_RESPONSE) ? " response" : "");
1151 /* Set "fd" to NULL; we pass a NULL "fd" to the query and
1152 answer dissectors, as a way of saying that they shouldn't
1153 add stuff to the COL_INFO column (a call to
1154 "check_col(fd, COL_INFO)" is more expensive than a check
1155 that a pointer isn't NULL). */
1160 ti = proto_tree_add_item(tree, proto_nbns, offset, END_OF_FRAME, NULL);
1161 nbns_tree = proto_item_add_subtree(ti, ett_nbns);
1163 if (flags & F_RESPONSE) {
1164 proto_tree_add_item_hidden(nbns_tree, hf_nbns_response,
1167 proto_tree_add_item_hidden(nbns_tree, hf_nbns_query,
1171 proto_tree_add_item(nbns_tree, hf_nbns_transaction_id,
1172 offset + NBNS_ID, 2, id);
1174 nbns_add_nbns_flags(nbns_tree, offset + NBNS_FLAGS, flags, 0);
1175 proto_tree_add_item(nbns_tree, hf_nbns_count_questions,
1176 offset + NBNS_QUEST, 2, quest);
1177 proto_tree_add_item(nbns_tree, hf_nbns_count_answers,
1178 offset + NBNS_ANS, 2, ans);
1179 proto_tree_add_item(nbns_tree, hf_nbns_count_auth_rr,
1180 offset + NBNS_AUTH, 2, auth);
1181 proto_tree_add_item(nbns_tree, hf_nbns_count_add_rr,
1182 offset + NBNS_ADD, 2, add);
1185 cur_off = offset + NBNS_HDRLEN;
1188 /* If this is a response, don't add information about the
1189 queries to the summary, just add information about the
1191 cur_off += dissect_query_records(pd, cur_off,
1192 nbns_data_offset, quest,
1193 (!(flags & F_RESPONSE) ? fd : NULL), nbns_tree);
1197 /* If this is a request, don't add information about the
1198 answers to the summary, just add information about the
1200 cur_off += dissect_answer_records(pd, cur_off,
1201 nbns_data_offset, ans,
1202 ((flags & F_RESPONSE) ? fd : NULL), nbns_tree,
1203 flags & F_OPCODE, "Answers");
1207 /* Don't add information about the authoritative name
1208 servers, or the additional records, to the summary. */
1210 cur_off += dissect_answer_records(pd, cur_off,
1212 auth, NULL, nbns_tree,
1214 "Authoritative nameservers");
1217 cur_off += dissect_answer_records(pd, cur_off,
1219 add, NULL, nbns_tree,
1221 "Additional records");
1225 /* NetBIOS datagram packet, from RFC 1002, page 32 */
1226 struct nbdgm_header {
1237 /* For packets with data */
1241 /* For error packets */
1246 dissect_nbdgm(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1248 proto_tree *nbdgm_tree = NULL;
1250 struct nbdgm_header header;
1253 int max_data = pi.captured_len - offset;
1257 "Direct_unique datagram",
1258 "Direct_group datagram",
1259 "Broadcast datagram",
1261 "Datagram query request",
1262 "Datagram positive query response",
1263 "Datagram negative query response"
1273 static value_string error_codes[] = {
1274 { 0x82, "Destination name not present" },
1275 { 0x83, "Invalid source name format" },
1276 { 0x84, "Invalid destination name format" },
1280 char *yesno[] = { "No", "Yes" };
1282 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1286 header.msg_type = pd[offset];
1288 flags = pd[offset+1];
1289 header.flags.more = flags & 1;
1290 header.flags.first = (flags & 2) >> 1;
1291 header.flags.node_type = (flags & 12) >> 2;
1293 header.dgm_id = pntohs(&pd[offset+2]);
1294 memcpy(&header.src_ip, &pd[offset+4], 4);
1295 header.src_port = pntohs(&pd[offset+8]);
1297 if (header.msg_type == 0x10 ||
1298 header.msg_type == 0x11 || header.msg_type == 0x12) {
1299 header.dgm_length = pntohs(&pd[offset+10]);
1300 header.pkt_offset = pntohs(&pd[offset+12]);
1302 else if (header.msg_type == 0x13) {
1303 header.error_code = pntohs(&pd[offset+10]);
1306 message_index = header.msg_type - 0x0f;
1307 if (message_index < 1 || message_index > 8) {
1311 if (check_col(fd, COL_PROTOCOL))
1312 col_add_str(fd, COL_PROTOCOL, "NBDS");
1313 if (check_col(fd, COL_INFO)) {
1314 col_add_fstr(fd, COL_INFO, "%s", message[message_index]);
1318 ti = proto_tree_add_item(tree, proto_nbdgm, offset, header.dgm_length, NULL);
1319 nbdgm_tree = proto_item_add_subtree(ti, ett_nbdgm);
1321 proto_tree_add_uint_format(nbdgm_tree, hf_nbdgm_type,
1325 message[message_index]);
1326 proto_tree_add_boolean_format(nbdgm_tree, hf_nbdgm_fragment,
1329 "More fragments follow: %s",
1330 yesno[header.flags.more]);
1331 proto_tree_add_boolean_format(nbdgm_tree, hf_nbdgm_first,
1334 "This is first fragment: %s",
1335 yesno[header.flags.first]);
1336 proto_tree_add_uint_format(nbdgm_tree, hf_nbdgm_node_type,
1338 header.flags.node_type,
1340 node[header.flags.node_type]);
1342 proto_tree_add_item(nbdgm_tree, hf_nbdgm_datagram_id,
1343 offset+2, 2, header.dgm_id);
1344 proto_tree_add_item(nbdgm_tree, hf_nbdgm_src_ip,
1345 offset+4, 4, header.src_ip);
1346 proto_tree_add_item(nbdgm_tree, hf_nbdgm_src_port,
1347 offset+8, 2, header.src_port);
1354 if (header.msg_type == 0x10 ||
1355 header.msg_type == 0x11 || header.msg_type == 0x12) {
1358 proto_tree_add_text(nbdgm_tree, offset, 2,
1359 "Datagram length: %d bytes", header.dgm_length);
1360 proto_tree_add_text(nbdgm_tree, offset+2, 2,
1361 "Packet offset: %d bytes", header.pkt_offset);
1368 len = get_nbns_name(pd, offset, offset, name, &name_type);
1371 add_name_and_type(nbdgm_tree, offset, len,
1372 "Source name", name, name_type);
1377 /* Destination name */
1378 len = get_nbns_name(pd, offset, offset, name, &name_type);
1381 add_name_and_type(nbdgm_tree, offset, len,
1382 "Destination name", name, name_type);
1387 /* here we can pass the packet off to the next protocol */
1388 dissect_smb(pd, offset, fd, tree, max_data);
1390 else if (header.msg_type == 0x13) {
1392 proto_tree_add_text(nbdgm_tree, offset, 1, "Error code: %s",
1393 val_to_str(header.error_code, error_codes, "Unknown (0x%x)"));
1396 else if (header.msg_type == 0x14 ||
1397 header.msg_type == 0x15 || header.msg_type == 0x16) {
1398 /* Destination name */
1399 len = get_nbns_name(pd, offset, offset, name, &name_type);
1402 add_name_and_type(nbdgm_tree, offset, len,
1403 "Destination name", name, name_type);
1409 * NetBIOS Session Service message types.
1411 #define SESSION_MESSAGE 0x00
1412 #define SESSION_REQUEST 0x81
1413 #define POSITIVE_SESSION_RESPONSE 0x82
1414 #define NEGATIVE_SESSION_RESPONSE 0x83
1415 #define RETARGET_SESSION_RESPONSE 0x84
1416 #define SESSION_KEEP_ALIVE 0x85
1418 static const value_string message_types[] = {
1419 { SESSION_MESSAGE, "Session message" },
1420 { SESSION_REQUEST, "Session request" },
1421 { POSITIVE_SESSION_RESPONSE, "Positive session response" },
1422 { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
1423 { RETARGET_SESSION_RESPONSE, "Retarget session response" },
1424 { SESSION_KEEP_ALIVE, "Session keep-alive" },
1429 * NetBIOS Session Service flags.
1431 #define NBSS_FLAGS_E 0x1
1433 static const value_string error_codes[] = {
1434 { 0x80, "Not listening on called name" },
1435 { 0x81, "Not listening for called name" },
1436 { 0x82, "Called name not present" },
1437 { 0x83, "Called name present, but insufficient resources" },
1438 { 0x8F, "Unspecified error" },
1443 * Dissect a single NBSS packet (there may be more than one in a given TCP
1444 * segment). Hmmm, in my experience, I have never seen more than one NBSS
1445 * in a single segment, since they mostly contain SMBs which are essentially
1446 * a request response type protocol (RJS). Also, a single session message
1447 * may be split over multiple segments.
1450 dissect_nbss_packet(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data)
1452 proto_tree *nbss_tree = NULL;
1454 proto_tree *field_tree;
1460 char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
1463 msg_type = pd[offset];
1464 flags = pd[offset + 1];
1465 length = pntohs(&pd[offset + 2]);
1466 if (flags & NBSS_FLAGS_E)
1470 ti = proto_tree_add_item(tree, proto_nbss, offset, length + 4, NULL);
1471 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1473 proto_tree_add_uint_format(nbss_tree, hf_nbss_type,
1477 val_to_str(msg_type, message_types,
1484 tf = proto_tree_add_item(nbss_tree, hf_nbss_flags, offset, 1, flags);
1485 field_tree = proto_item_add_subtree(tf, ett_nbss_flags);
1486 proto_tree_add_text(field_tree, offset, 1, "%s",
1487 decode_boolean_bitfield(flags, NBSS_FLAGS_E,
1488 8, "Add 65536 to length", "Add 0 to length"));
1494 proto_tree_add_text(nbss_tree, offset, 2, "Length: %u", length);
1501 case SESSION_REQUEST:
1502 len = get_nbns_name(pd, offset, offset, name, &name_type);
1504 add_name_and_type(nbss_tree, offset, len,
1505 "Called name", name, name_type);
1508 len = get_nbns_name(pd, offset, offset, name, &name_type);
1511 add_name_and_type(nbss_tree, offset, len,
1512 "Calling name", name, name_type);
1516 case NEGATIVE_SESSION_RESPONSE:
1518 proto_tree_add_text(nbss_tree, offset, 1,
1520 val_to_str(pd[offset], error_codes, "Unknown (%x)"));
1523 case RETARGET_SESSION_RESPONSE:
1525 proto_tree_add_text(nbss_tree, offset, 4,
1526 "Retarget IP address: %s",
1527 ip_to_str((guint8 *)&pd[offset]));
1532 proto_tree_add_text(nbss_tree, offset, 2,
1533 "Retarget port: %u", pntohs(&pd[offset]));
1537 case SESSION_MESSAGE:
1539 * Here we can pass the packet off to the next protocol.
1542 dissect_smb(pd, offset, fd, tree, max_data - 4);
1551 dissect_nbss(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1559 msg_type = pd[offset];
1560 flags = pd[offset + 1];
1561 length = pntohs(&pd[offset + 2]);
1562 if (flags & NBSS_FLAGS_E)
1566 * XXX - we should set this based on both "pi.captured_len"
1569 max_data = pi.captured_len - offset;
1571 /* Hmmm, it may be a continuation message ... */
1575 if (((msg_type != SESSION_REQUEST) &&
1576 (msg_type != POSITIVE_SESSION_RESPONSE) &&
1577 (msg_type != NEGATIVE_SESSION_RESPONSE) &&
1578 (msg_type != RETARGET_SESSION_RESPONSE) &&
1579 (msg_type != SESSION_MESSAGE)) ||
1580 ((msg_type == SESSION_MESSAGE) &&
1581 (memcmp(pd + offset + 4, "\377SMB", 4) != 0))) {
1583 if (check_col(fd, COL_PROTOCOL))
1584 col_add_str(fd, COL_PROTOCOL, "NBSS");
1585 if (check_col(fd, COL_INFO)) {
1586 col_add_fstr(fd, COL_INFO, "NBSS Continuation Message");
1590 proto_tree_add_text(tree, offset, max_data, "Continuation data");
1596 if (check_col(fd, COL_PROTOCOL))
1597 col_add_str(fd, COL_PROTOCOL, "NBSS");
1598 if (check_col(fd, COL_INFO)) {
1599 col_add_fstr(fd, COL_INFO,
1600 val_to_str(msg_type, message_types, "Unknown (%x)"));
1603 while (max_data > 0) {
1604 len = dissect_nbss_packet(pd, offset, fd, tree, max_data);
1612 proto_register_nbt(void)
1615 static hf_register_info hf_nbns[] = {
1616 { &hf_nbns_response,
1617 { "Response", "nbns.response",
1618 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1619 "TRUE if NBNS response" }},
1621 { "Query", "nbns.query",
1622 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1623 "TRUE if NBNS query" }},
1624 { &hf_nbns_transaction_id,
1625 { "Transaction ID", "nbns.id",
1626 FT_UINT16, BASE_HEX, NULL, 0x0,
1627 "Identification of transaction" }},
1628 { &hf_nbns_count_questions,
1629 { "Questions", "nbns.count.queries",
1630 FT_UINT16, BASE_DEC, NULL, 0x0,
1631 "Number of queries in packet" }},
1632 { &hf_nbns_count_answers,
1633 { "Answer RRs", "nbns.count.answers",
1634 FT_UINT16, BASE_DEC, NULL, 0x0,
1635 "Number of answers in packet" }},
1636 { &hf_nbns_count_auth_rr,
1637 { "Authority RRs", "nbns.count.auth_rr",
1638 FT_UINT16, BASE_DEC, NULL, 0x0,
1639 "Number of authoritative records in packet" }},
1640 { &hf_nbns_count_add_rr,
1641 { "Additional RRs", "nbns.count.add_rr",
1642 FT_UINT16, BASE_DEC, NULL, 0x0,
1643 "Number of additional records in packet" }}
1646 static hf_register_info hf_nbdgm[] = {
1648 { "Message Type", "nbdgm.type",
1649 FT_UINT8, BASE_DEC, NULL, 0x0,
1650 "NBDGM message type" }},
1651 { &hf_nbdgm_fragment,
1652 { "Fragmented", "nbdgm.next",
1653 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1654 "TRUE if more fragments follow" }},
1656 { "First fragment", "nbdgm.first",
1657 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1658 "TRUE if first fragment" }},
1659 { &hf_nbdgm_node_type,
1660 { "Node Type", "nbdgm.node_type",
1661 FT_UINT8, BASE_DEC, NULL, 0x0,
1663 { &hf_nbdgm_datagram_id,
1664 { "Datagram ID", "nbdgm.dgram_id",
1665 FT_UINT16, BASE_HEX, NULL, 0x0,
1666 "Datagram identifier" }},
1668 { "Source IP", "nbdgm.src.ip",
1669 FT_IPv4, BASE_NONE, NULL, 0x0,
1670 "Source IPv4 address" }},
1671 { &hf_nbdgm_src_port,
1672 { "Source Port", "nbdgm.src.port",
1673 FT_UINT16, BASE_DEC, NULL, 0x0,
1677 static hf_register_info hf_nbss[] = {
1679 { "Message Type", "nbss.type",
1680 FT_UINT8, BASE_DEC, NULL, 0x0,
1681 "NBSS message type" }},
1683 { "Flags", "nbss.flags",
1684 FT_UINT8, BASE_HEX, NULL, 0x0,
1685 "NBSS message flags" }}
1687 static gint *ett[] = {
1692 &ett_nbns_name_flags,
1701 proto_nbns = proto_register_protocol("NetBIOS Name Service", "nbns");
1702 proto_register_field_array(proto_nbns, hf_nbns, array_length(hf_nbns));
1704 proto_nbdgm = proto_register_protocol("NetBIOS Datagram Service", "nbdgm");
1705 proto_register_field_array(proto_nbdgm, hf_nbdgm, array_length(hf_nbdgm));
1707 proto_nbss = proto_register_protocol("NetBIOS Session Service", "nbss");
1708 proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));
1710 proto_register_subtree_array(ett, array_length(ett));
1714 proto_reg_handoff_nbt(void)
1716 dissector_add("udp.port", UDP_PORT_NBNS, dissect_nbns);
1717 dissector_add("udp.port", UDP_PORT_NBDGM, dissect_nbdgm);
1718 dissector_add("tcp.port", TCP_PORT_NBSS, dissect_nbss);