Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-nbt.c
blob1d9c54acfd4a7434b53137980967fcafb6b6fe07
1 /* packet-nbt.c
2 * Routines for NetBIOS-over-TCP packet disassembly
3 * Guy Harris <guy@alum.mit.edu>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/expert.h>
16 #include <epan/exceptions.h>
17 #include <epan/prefs.h>
18 #include <epan/show_exception.h>
19 #include <epan/to_str.h>
20 #include <epan/charsets.h>
21 #include <epan/tfs.h>
22 #include <epan/unit_strings.h>
24 #include <wsutil/array.h>
25 #include <wsutil/str_util.h>
27 #include "packet-dns.h"
28 #include "packet-netbios.h"
29 #include "packet-tcp.h"
31 void proto_register_nbt(void);
32 void proto_reg_handoff_nbt(void);
34 static dissector_handle_t nbns_handle, nbdgm_handle, nbss_handle;
36 static int proto_nbns;
37 static int hf_nbns_flags;
38 static int hf_nbns_flags_response;
39 static int hf_nbns_flags_opcode;
40 static int hf_nbns_flags_authoritative;
41 static int hf_nbns_flags_truncated;
42 static int hf_nbns_flags_recdesired;
43 static int hf_nbns_flags_recavail;
44 static int hf_nbns_flags_broadcast;
45 static int hf_nbns_flags_rcode;
46 static int hf_nbns_transaction_id;
47 static int hf_nbns_count_questions;
48 static int hf_nbns_count_answers;
49 static int hf_nbns_count_auth_rr;
50 static int hf_nbns_count_add_rr;
51 static int hf_nbns_name_flags;
52 static int hf_nbns_name_flags_group;
53 static int hf_nbns_name_flags_ont;
54 static int hf_nbns_name_flags_drg;
55 static int hf_nbns_name_flags_cnf;
56 static int hf_nbns_name_flags_act;
57 static int hf_nbns_name_flags_prm;
58 static int hf_nbns_nb_flags;
59 static int hf_nbns_nb_flags_group;
60 static int hf_nbns_nb_flags_ont;
61 static int hf_nbns_name;
62 static int hf_nbns_type;
63 static int hf_nbns_class;
65 /* Generated from convert_proto_tree_add_text.pl */
66 static int hf_nbns_num_alignment_errors;
67 static int hf_nbns_data;
68 static int hf_nbns_unit_id;
69 static int hf_nbns_num_command_blocks;
70 static int hf_nbns_num_retransmits;
71 static int hf_nbns_period_of_statistics;
72 static int hf_nbns_addr;
73 static int hf_nbns_test_result;
74 static int hf_nbns_num_pending_sessions;
75 static int hf_nbns_num_no_resource_conditions;
76 static int hf_nbns_session_data_packet_size;
77 static int hf_nbns_version_number;
78 static int hf_nbns_max_num_pending_sessions;
79 static int hf_nbns_num_collisions;
80 static int hf_nbns_num_good_sends;
81 static int hf_nbns_num_send_aborts;
82 static int hf_nbns_number_of_names;
83 static int hf_nbns_num_crcs;
84 static int hf_nbns_num_good_receives;
85 static int hf_nbns_max_total_sessions_possible;
86 static int hf_nbns_jumpers;
87 static int hf_nbns_netbios_name;
88 static int hf_nbns_ttl;
89 static int hf_nbns_data_length;
91 static int ett_nbns;
92 static int ett_nbns_qd;
93 static int ett_nbns_flags;
94 static int ett_nbns_nb_flags;
95 static int ett_nbns_name_flags;
96 static int ett_nbns_rr;
97 static int ett_nbns_qry;
98 static int ett_nbns_ans;
100 static expert_field ei_nbns_incomplete_entry;
102 static int proto_nbdgm;
103 static int hf_nbdgm_type;
104 static int hf_nbdgm_flags;
105 static int hf_nbdgm_fragment;
106 static int hf_nbdgm_first;
107 static int hf_nbdgm_node_type;
108 static int hf_nbdgm_datagram_id;
109 static int hf_nbdgm_src_ip;
110 static int hf_nbdgm_src_port;
111 static int hf_nbdgm_datagram_length;
112 static int hf_nbdgm_packet_offset;
113 static int hf_nbdgm_error_code;
114 static int hf_nbdgm_source_name;
115 static int hf_nbdgm_destination_name;
117 static int ett_nbdgm;
118 static int ett_nbdgm_flags;
120 static int proto_nbss;
121 static int hf_nbss_type;
122 static int hf_nbss_flags;
123 static int hf_nbss_flags_e;
124 static int hf_nbss_length;
125 static int hf_nbss_cifs_length;
126 static int hf_nbss_error_code;
127 static int hf_nbss_retarget_ip_address;
128 static int hf_nbss_retarget_port;
129 static int hf_nbss_continuation_data;
130 static int hf_nbss_called_name;
131 static int hf_nbss_calling_name;
133 static int ett_nbss;
134 static int ett_nbss_flags;
136 /* desegmentation of NBSS over TCP */
137 static bool nbss_desegment = true;
139 /* See RFC 1001 and 1002 for information on the first three, and see
141 http://www.cifs.com/specs/draft-leach-cifs-v1-spec-01.txt
143 Appendix B, and various messages on the CIFS mailing list such as
145 http://discuss.microsoft.com/SCRIPTS/WA-MSD.EXE?A2=ind9811A&L=cifs&P=R386
147 for information on the fourth. */
148 #define UDP_PORT_NBNS 137
149 #define UDP_PORT_NBDGM 138
150 #define TCP_PORT_NBSS 139
151 #define TCP_PORT_CIFS 445
152 #define TCP_NBSS_PORT_RANGE "139,445"
154 /* Packet structure taken from RFC 1002. See also RFC 1001.
155 * Opcode, flags, and rcode treated as "flags", similarly to DNS,
156 * to make it easier to lift the dissection code from "packet-dns.c". */
158 /* Offsets of fields in the NBNS header. */
159 #define NBNS_ID 0
160 #define NBNS_FLAGS 2
161 #define NBNS_QUEST 4
162 #define NBNS_ANS 6
163 #define NBNS_AUTH 8
164 #define NBNS_ADD 10
166 /* Length of NBNS header. */
167 #define NBNS_HDRLEN 12
169 /* type values */
170 #define T_NB 32 /* NetBIOS name service RR */
171 #define T_NBSTAT 33 /* NetBIOS node status RR */
173 /* Bit fields in the flags */
174 #define F_RESPONSE (1<<15) /* packet is response */
175 #define F_OPCODE (0xF<<11) /* query opcode */
176 #define OPCODE_SHIFT 11
177 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
178 #define F_TRUNCATED (1<<9) /* response is truncated */
179 #define F_RECDESIRED (1<<8) /* recursion desired */
180 #define F_RECAVAIL (1<<7) /* recursion available */
181 #define F_BROADCAST (1<<4) /* broadcast/multicast packet */
182 #define F_RCODE (0xF<<0) /* reply code */
184 static const true_false_string tfs_flags_response = {
185 "Message is a response",
186 "Message is a query"
189 static const true_false_string tfs_flags_authoritative = {
190 "Server is an authority for domain",
191 "Server is not an authority for domain"
194 static const true_false_string tfs_flags_truncated = {
195 "Message is truncated",
196 "Message is not truncated"
199 static const true_false_string tfs_flags_recdesired = {
200 "Do query recursively",
201 "Don't do query recursively"
204 static const true_false_string tfs_flags_recavail = {
205 "Server can do recursive queries",
206 "Server can't do recursive queries"
209 static const true_false_string tfs_flags_broadcast = {
210 "Broadcast packet",
211 "Not a broadcast packet"
214 static const true_false_string tfs_nbss_flags_e = {
215 "Add 65536 to length",
216 "Add 0 to length"
219 /* Opcodes */
220 #define OPCODE_QUERY 0 /* standard query */
221 #define OPCODE_REGISTRATION 5 /* registration */
222 #define OPCODE_RELEASE 6 /* release name */
223 #define OPCODE_WACK 7 /* wait for acknowledgement */
224 #define OPCODE_REFRESH 8 /* refresh registration */
225 #define OPCODE_REFRESHALT 9 /* refresh registration (alternate opcode) */
226 #define OPCODE_MHREGISTRATION 15 /* multi-homed registration */
228 static const value_string opcode_vals[] = {
229 { OPCODE_QUERY, "Name query" },
230 { OPCODE_REGISTRATION, "Registration" },
231 { OPCODE_RELEASE, "Release" },
232 { OPCODE_WACK, "Wait for acknowledgment" },
233 { OPCODE_REFRESH, "Refresh" },
234 { OPCODE_REFRESHALT, "Refresh (alternate opcode)" },
235 { OPCODE_MHREGISTRATION, "Multi-homed registration" },
236 { 0, NULL }
239 /* Reply codes */
240 #define RCODE_NOERROR 0
241 #define RCODE_FMTERROR 1
242 #define RCODE_SERVFAIL 2
243 #define RCODE_NAMEERROR 3
244 #define RCODE_NOTIMPL 4
245 #define RCODE_REFUSED 5
246 #define RCODE_ACTIVE 6
247 #define RCODE_CONFLICT 7
249 static const value_string rcode_vals[] = {
250 { RCODE_NOERROR, "No error" },
251 { RCODE_FMTERROR, "Request was invalidly formatted" },
252 { RCODE_SERVFAIL, "Server failure" },
253 { RCODE_NAMEERROR, "Requested name does not exist" },
254 { RCODE_NOTIMPL, "Request is not implemented" },
255 { RCODE_REFUSED, "Request was refused" },
256 { RCODE_ACTIVE, "Name is owned by another node" },
257 { RCODE_CONFLICT, "Name is in conflict" },
258 { 0, NULL }
261 /* Values for the "NB_FLAGS" field of RR data. From RFC 1001 and 1002,
262 * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
263 * packet traces. */
264 #define NB_FLAGS_ONT (3<<(15-2)) /* bits for node type */
265 #define NB_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
266 #define NB_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
267 #define NB_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
268 #define NB_FLAGS_ONT_H_NODE (3<<(15-2)) /* H-mode node */
270 #define NB_FLAGS_G (1<<(15-0)) /* group name */
272 /* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
273 * RR data. From RFC 1001 and 1002; as I remember, the "NAME_FLAGS"
274 * field doesn't include any special values for H-mode nodes, even
275 * though one can register them (if so, perhaps that was done to
276 * avoid surprising clients that don't know about H-mode nodes). */
277 #define NAME_FLAGS_PRM (1<<(15-6)) /* name is permanent node name */
279 #define NAME_FLAGS_ACT (1<<(15-5)) /* name is active */
281 #define NAME_FLAGS_CNF (1<<(15-4)) /* name is in conflict */
283 #define NAME_FLAGS_DRG (1<<(15-3)) /* name is being deregistered */
285 #define NAME_FLAGS_ONT (3<<(15-2)) /* bits for node type */
286 #define NAME_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
287 #define NAME_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
288 #define NAME_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
290 #define NAME_FLAGS_G (1<<(15-0)) /* group name */
292 static const value_string name_flags_ont_vals[] = {
293 { NAME_FLAGS_ONT_B_NODE, "B-node" },
294 { NAME_FLAGS_ONT_P_NODE, "P-node" },
295 { NAME_FLAGS_ONT_M_NODE, "M-node" },
296 { 0, NULL }
299 static const value_string nb_flags_ont_vals[] = {
300 { NB_FLAGS_ONT_B_NODE, "B-node" },
301 { NB_FLAGS_ONT_P_NODE, "P-node" },
302 { NB_FLAGS_ONT_M_NODE, "M-node" },
303 { NB_FLAGS_ONT_H_NODE, "H-node" },
304 { 0, NULL }
307 static const value_string nb_type_name_vals[] = {
308 { T_NB, "NB" },
309 { T_NBSTAT, "NBSTAT" },
310 { 0, NULL }
313 #define NBNAME_BUF_LEN 128
315 static void
316 add_rr_to_tree(proto_tree *rr_tree, packet_info *pinfo, tvbuff_t *tvb, int offset,
317 const char *name, int namelen,
318 int type, int class_val,
319 unsigned ttl, uint16_t data_len)
321 proto_tree_add_string(rr_tree, hf_nbns_name, tvb, offset+1, namelen-1, name);
322 offset += namelen;
323 proto_tree_add_uint(rr_tree, hf_nbns_type, tvb, offset, 2, type);
324 offset += 2;
325 proto_tree_add_uint(rr_tree, hf_nbns_class, tvb, offset, 2, class_val);
326 offset += 2;
327 proto_tree_add_uint_format_value(rr_tree, hf_nbns_ttl, tvb, offset, 4, ttl, "%s",
328 signed_time_secs_to_str(pinfo->pool, ttl));
329 offset += 4;
330 proto_tree_add_uint(rr_tree, hf_nbns_data_length, tvb, offset, 2, data_len);
333 static int
334 get_nbns_name(tvbuff_t *tvb, int offset, int nbns_data_offset,
335 char *name_ret, int name_ret_len, int *name_type_ret)
337 int name_len;
338 const char *name;
339 const char *nbname;
340 char *nbname_buf;
341 const char *pname;
342 char cname, cnbname;
343 int name_type;
344 char *pname_ret;
345 size_t idx = 0;
346 unsigned used_bytes;
348 nbname_buf = (char *)wmem_alloc(wmem_packet_scope(), NBNAME_BUF_LEN);
349 nbname = nbname_buf;
350 used_bytes = get_dns_name(tvb, offset, 0, nbns_data_offset, &name, &name_len);
352 /* OK, now undo the first-level encoding. */
353 pname = &name[0];
354 pname_ret = name_ret;
356 for (;;) {
357 /* Every two characters of the first level-encoded name
358 * turn into one character in the decoded name. */
359 cname = *pname;
360 if (cname == '\0')
361 break; /* no more characters */
362 if (cname == '.')
363 break; /* scope ID follows */
364 if (cname < 'A' || cname > 'Z') {
365 /* Not legal. */
366 nbname = "Illegal NetBIOS name (1st character not between A and Z in first-level encoding)";
367 goto bad;
369 cname -= 'A';
370 cnbname = cname << 4;
371 pname++;
373 cname = *pname;
374 if (cname == '\0' || cname == '.') {
375 /* No more characters in the name - but we're in
376 * the middle of a pair. Not legal. */
377 nbname = "Illegal NetBIOS name (odd number of bytes)";
378 goto bad;
380 if (cname < 'A' || cname > 'Z') {
381 /* Not legal. */
382 nbname = "Illegal NetBIOS name (2nd character not between A and Z in first-level encoding)";
383 goto bad;
385 cname -= 'A';
386 cnbname |= cname;
387 pname++;
389 /* Do we have room to store the character? */
390 if (idx < NETBIOS_NAME_LEN) {
391 /* Yes - store the character. */
392 nbname_buf[idx++] = cnbname;
396 /* NetBIOS names are supposed to be exactly 16 bytes long. */
397 if (idx != NETBIOS_NAME_LEN) {
398 /* It's not. */
399 snprintf(nbname_buf, NBNAME_BUF_LEN, "Illegal NetBIOS name (%lu bytes long)",
400 (unsigned long)idx);
401 goto bad;
404 /* This one is; make its name printable. */
405 name_type = process_netbios_name(nbname, name_ret, name_ret_len);
406 pname_ret += MIN(strlen(name_ret), (size_t) name_ret_len);
407 snprintf(pname_ret, name_ret_len-(pname_ret-name_ret), "<%02x>", name_type);
408 if (cname == '.') {
409 /* We have a scope ID, starting at "pname"; append that to
410 * the decoded host name. */
411 /* RFC 1001 says that scope IDs "meet the restricted character set
412 * of the domain system and has a leading period." Convert it from
413 * ASCII before appending it to our NBName, so we have a valid
414 * UTF-8 string.
416 const char* scope_id = get_ascii_string(wmem_packet_scope(), pname, (int)strlen(pname));
417 int bytes_attempted = (int)g_strlcat(name_ret, scope_id, name_ret_len);
418 if (bytes_attempted >= name_ret_len) {
419 ws_utf8_truncate(name_ret, name_ret_len - 1);
422 if (name_type_ret != NULL)
423 *name_type_ret = name_type;
424 return used_bytes;
426 bad:
427 if (name_type_ret != NULL)
428 *name_type_ret = -1;
429 /* This is only valid because nbname is always assigned an error string
430 * before jumping to bad: Otherwise nbname wouldn't be \0 terminated */
431 snprintf(pname_ret, name_ret_len-(pname_ret-name_ret), "%s", nbname);
432 return used_bytes;
436 static int
437 get_nbns_name_type_class(tvbuff_t *tvb, int offset, int nbns_data_offset,
438 char *name_ret, int *name_len_ret, int *name_type_ret,
439 int *type_ret, int *class_ret)
441 int name_len;
442 int type;
443 int rr_class;
445 name_len = get_nbns_name(tvb, offset, nbns_data_offset, name_ret,
446 *name_len_ret, name_type_ret);
447 offset += name_len;
449 type = tvb_get_ntohs(tvb, offset);
450 offset += 2;
452 rr_class = tvb_get_ntohs(tvb, offset);
454 *type_ret = type;
455 *class_ret = rr_class;
456 *name_len_ret = name_len;
458 return name_len + 4;
461 static void
462 add_name_and_type(proto_tree *tree, tvbuff_t *tvb, int offset, int len,
463 int hf_tag, const char *name, int name_type)
465 if (name_type != -1) {
466 proto_tree_add_string_format_value(tree, hf_tag, tvb, offset, len, name, "%s (%s)",
467 name, netbios_name_type_descr(name_type));
468 } else {
469 proto_tree_add_string(tree, hf_tag, tvb, offset, len, name);
473 #define MAX_NAME_LEN (NETBIOS_NAME_LEN - 1)*4 + MAX_DNAME_LEN + 64
475 static int
476 dissect_nbns_query(tvbuff_t *tvb, int offset, int nbns_data_offset,
477 column_info *cinfo, proto_tree *nbns_tree)
479 int len;
480 char *name;
481 int name_len;
482 int name_type;
483 int type;
484 int dns_class;
485 const char *type_name;
486 int data_offset;
487 int data_start;
488 proto_tree *q_tree;
490 name = (char *)wmem_alloc(wmem_packet_scope(), MAX_NAME_LEN);
491 data_start = data_offset = offset;
493 name_len = MAX_NAME_LEN;
494 len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
495 &name_len, &name_type, &type, &dns_class);
496 data_offset += len;
498 type_name = val_to_str_const(type, nb_type_name_vals, "Unknown");
500 if (cinfo != NULL)
501 col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
503 if (nbns_tree != NULL) {
504 q_tree = proto_tree_add_subtree_format(nbns_tree, tvb, offset, len,
505 ett_nbns_qd, NULL, "%s: type %s, class %s", name, type_name,
506 val_to_str_const(dns_class, dns_classes, "Unknown"));
508 add_name_and_type(q_tree, tvb, offset, name_len, hf_nbns_name, name,
509 name_type);
510 offset += name_len;
512 proto_tree_add_uint(q_tree, hf_nbns_type, tvb, offset, 2, type);
513 offset += 2;
515 proto_tree_add_uint(q_tree, hf_nbns_class, tvb, offset, 2, dns_class);
516 /*offset += 2;*/
519 return data_offset - data_start;
522 static void
523 nbns_add_nbns_flags(column_info *cinfo, proto_tree *nbns_tree, tvbuff_t *tvb, int offset, int is_wack)
525 uint16_t flag;
526 static int * const req_flags[] = {
527 &hf_nbns_flags_response,
528 &hf_nbns_flags_opcode,
529 &hf_nbns_flags_truncated,
530 &hf_nbns_flags_recdesired,
531 &hf_nbns_flags_broadcast,
532 NULL
535 static int * const resp_flags[] = {
536 &hf_nbns_flags_response,
537 &hf_nbns_flags_opcode,
538 &hf_nbns_flags_authoritative,
539 &hf_nbns_flags_truncated,
540 &hf_nbns_flags_recdesired,
541 &hf_nbns_flags_recavail,
542 &hf_nbns_flags_broadcast,
543 &hf_nbns_flags_rcode,
544 NULL
547 static int * const resp_wack_flags[] = {
548 &hf_nbns_flags_response,
549 &hf_nbns_flags_opcode,
550 &hf_nbns_flags_authoritative,
551 &hf_nbns_flags_truncated,
552 &hf_nbns_flags_recdesired,
553 &hf_nbns_flags_recavail,
554 &hf_nbns_flags_broadcast,
555 NULL
558 flag = tvb_get_ntohs(tvb, offset);
559 if (cinfo) {
560 if (flag & F_RESPONSE && !is_wack) {
561 if ((flag & F_RCODE))
562 col_append_fstr(cinfo, COL_INFO, ", %s",
563 val_to_str_const(flag & F_RCODE, rcode_vals,
564 "Unknown error"));
568 if (!nbns_tree)
569 return;
571 if (flag & F_RESPONSE) {
572 if (!is_wack) {
573 proto_tree_add_bitmask(nbns_tree, tvb, offset, hf_nbns_flags, ett_nbns_flags, resp_flags, ENC_BIG_ENDIAN);
574 } else {
575 proto_tree_add_bitmask(nbns_tree, tvb, offset, hf_nbns_flags, ett_nbns_flags, resp_wack_flags, ENC_BIG_ENDIAN);
577 } else {
578 proto_tree_add_bitmask(nbns_tree, tvb, offset, hf_nbns_flags, ett_nbns_flags, req_flags, ENC_BIG_ENDIAN);
582 static void
583 nbns_add_nb_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset)
585 proto_item *tf;
586 uint16_t flag;
587 static int * const flags[] = {
588 &hf_nbns_nb_flags_group,
589 &hf_nbns_nb_flags_ont,
590 NULL
593 tf = proto_tree_add_bitmask(rr_tree, tvb, offset, hf_nbns_nb_flags, ett_nbns_nb_flags, flags, ENC_BIG_ENDIAN);
595 flag = tvb_get_ntohs(tvb, offset);
596 proto_item_append_text(tf, " (%s, %s)",
597 val_to_str_const(flag & NB_FLAGS_ONT, nb_flags_ont_vals, "Unknown"),
598 (flag & NB_FLAGS_G) ? "group" : "unique");
601 static void
602 nbns_add_name_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset)
604 static int * const flags[] = {
605 &hf_nbns_name_flags_group,
606 &hf_nbns_name_flags_ont,
607 &hf_nbns_name_flags_drg,
608 &hf_nbns_name_flags_cnf,
609 &hf_nbns_name_flags_act,
610 &hf_nbns_name_flags_prm,
611 NULL
614 proto_tree_add_bitmask(rr_tree, tvb, offset, hf_nbns_name_flags, ett_nbns_name_flags, flags, ENC_BIG_ENDIAN);
617 static int
618 dissect_nbns_answer(tvbuff_t *tvb, packet_info *pinfo, int offset, int nbns_data_offset,
619 column_info *cinfo, proto_tree *nbns_tree, int opcode)
621 int len;
622 char *name;
623 int name_len;
624 int name_type;
625 int type;
626 int dns_class;
627 const char *class_name;
628 const char *type_name;
629 int cur_offset;
630 unsigned ttl;
631 uint16_t data_len;
632 proto_tree *rr_tree = NULL;
633 char *name_str;
634 unsigned num_names;
635 char *nbname;
637 cur_offset = offset;
639 name = (char *)wmem_alloc(pinfo->pool, MAX_NAME_LEN);
640 name_str = (char *)wmem_alloc(pinfo->pool, MAX_NAME_LEN);
641 nbname = (char *)wmem_alloc(pinfo->pool, 16+4+1); /* 4 for [<last char>] */
643 name_len = MAX_NAME_LEN;
644 len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
645 &name_len, &name_type, &type, &dns_class);
646 cur_offset += len;
648 type_name = val_to_str_const(type, nb_type_name_vals, "Unknown");
649 class_name = val_to_str_const(dns_class, dns_classes, "Unknown");
651 ttl = tvb_get_ntohl(tvb, cur_offset);
652 cur_offset += 4;
654 data_len = tvb_get_ntohs(tvb, cur_offset);
655 cur_offset += 2;
657 /* XXX: This code should be simplified */
658 switch (type) {
659 case T_NB: /* "NB" record */
660 if (cinfo != NULL) {
661 if (opcode != OPCODE_WACK) {
662 col_append_fstr(cinfo, COL_INFO, " %s %s",
663 type_name,
664 tvb_ip_to_str(pinfo->pool, tvb, cur_offset+2));
668 if (nbns_tree) {
669 rr_tree = proto_tree_add_subtree_format(nbns_tree, tvb, offset,
670 (cur_offset - offset) + data_len,
671 ett_nbns_rr, NULL, "%s: type %s, class %s",
672 name, type_name, class_name);
673 (void) g_strlcat(name, " (", MAX_NAME_LEN);
674 (void) g_strlcat(name, netbios_name_type_descr(name_type), MAX_NAME_LEN);
675 (void) g_strlcat(name, ")", MAX_NAME_LEN);
676 add_rr_to_tree(rr_tree, pinfo, tvb, offset, name,
677 name_len, type, dns_class, ttl, data_len);
679 while (data_len > 0) {
680 if (opcode == OPCODE_WACK) {
681 /* WACK response. This doesn't contain the
682 * same type of RR data as other T_NB
683 * responses. */
684 if (data_len < 2) {
685 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
686 break;
688 nbns_add_nbns_flags(cinfo, rr_tree, tvb, cur_offset, 1);
689 cur_offset += 2;
690 data_len -= 2;
691 } else {
692 if (data_len < 2) {
693 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
694 break;
696 nbns_add_nb_flags(rr_tree, tvb, cur_offset);
697 cur_offset += 2;
698 data_len -= 2;
700 if (data_len < 4) {
701 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
702 break;
704 proto_tree_add_item(rr_tree, hf_nbns_addr, tvb, cur_offset, 4, ENC_BIG_ENDIAN);
705 cur_offset += 4;
706 data_len -= 4;
709 break;
711 case T_NBSTAT: /* "NBSTAT" record */
712 if (cinfo != NULL)
713 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
715 if (nbns_tree) {
716 rr_tree = proto_tree_add_subtree_format(nbns_tree, tvb, offset,
717 (cur_offset - offset) + data_len,
718 ett_nbns_rr, NULL, "%s: type %s, class %s",
719 name, type_name, class_name);
720 add_rr_to_tree(rr_tree, pinfo, tvb, offset, name,
721 name_len, type, dns_class, ttl, data_len);
724 if (data_len < 1) {
725 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
726 break;
729 num_names = tvb_get_uint8(tvb, cur_offset);
730 proto_tree_add_item(rr_tree, hf_nbns_number_of_names, tvb, cur_offset, 1, ENC_BIG_ENDIAN);
731 cur_offset += 1;
733 while (num_names != 0) {
734 if (data_len < NETBIOS_NAME_LEN) {
735 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
736 goto out;
738 if (rr_tree) {
739 tvb_memcpy(tvb, (uint8_t *)nbname, cur_offset,
740 NETBIOS_NAME_LEN);
741 name_type = process_netbios_name(nbname,
742 name_str, name_len);
743 proto_tree_add_string_format_value(rr_tree, hf_nbns_netbios_name, tvb, cur_offset,
744 NETBIOS_NAME_LEN, name_str, "%s<%02x> (%s)",
745 name_str, name_type,
746 netbios_name_type_descr(name_type));
748 cur_offset += NETBIOS_NAME_LEN;
749 data_len -= NETBIOS_NAME_LEN;
751 if (data_len < 2) {
752 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
753 goto out;
755 if (rr_tree) {
756 nbns_add_name_flags(rr_tree, tvb, cur_offset);
758 cur_offset += 2;
759 data_len -= 2;
761 num_names--;
764 if (data_len < 6) {
765 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
766 break;
769 proto_tree_add_item(rr_tree, hf_nbns_unit_id, tvb, cur_offset, 6, ENC_NA);
770 cur_offset += 6;
771 data_len -= 6;
773 if (data_len < 1) {
774 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
775 break;
778 proto_tree_add_item(rr_tree, hf_nbns_jumpers, tvb, cur_offset, 1, ENC_BIG_ENDIAN);
779 cur_offset += 1;
780 data_len -= 1;
782 if (data_len < 1) {
783 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
784 break;
787 proto_tree_add_item(rr_tree, hf_nbns_test_result, tvb, cur_offset, 1, ENC_BIG_ENDIAN);
788 cur_offset += 1;
789 data_len -= 1;
791 if (data_len < 2) {
792 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
793 break;
796 proto_tree_add_item(rr_tree, hf_nbns_version_number, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
797 cur_offset += 2;
798 data_len -= 2;
800 if (data_len < 2) {
801 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
802 break;
805 proto_tree_add_item(rr_tree, hf_nbns_period_of_statistics, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
806 cur_offset += 2;
807 data_len -= 2;
809 if (data_len < 2) {
810 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
811 break;
814 proto_tree_add_item(rr_tree, hf_nbns_num_crcs, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
815 cur_offset += 2;
816 data_len -= 2;
818 if (data_len < 2) {
819 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
820 break;
823 proto_tree_add_item(rr_tree, hf_nbns_num_alignment_errors, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
824 cur_offset += 2;
825 data_len -= 2;
827 if (data_len < 2) {
828 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
829 break;
832 proto_tree_add_item(rr_tree, hf_nbns_num_collisions, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
833 cur_offset += 2;
834 data_len -= 2;
836 if (data_len < 2) {
837 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
838 break;
841 proto_tree_add_item(rr_tree, hf_nbns_num_send_aborts, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
842 cur_offset += 2;
843 data_len -= 2;
845 if (data_len < 4) {
846 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
847 break;
850 proto_tree_add_item(rr_tree, hf_nbns_num_good_sends, tvb, cur_offset, 4, ENC_BIG_ENDIAN);
851 cur_offset += 4;
852 data_len -= 4;
854 if (data_len < 4) {
855 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
856 break;
859 proto_tree_add_item(rr_tree, hf_nbns_num_good_receives, tvb, cur_offset, 4, ENC_BIG_ENDIAN);
860 cur_offset += 4;
861 data_len -= 4;
863 if (data_len < 2) {
864 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
865 break;
868 proto_tree_add_item(rr_tree, hf_nbns_num_retransmits, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
869 cur_offset += 2;
870 data_len -= 2;
872 if (data_len < 2) {
873 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
874 break;
877 proto_tree_add_item(rr_tree, hf_nbns_num_no_resource_conditions, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
878 cur_offset += 2;
879 data_len -= 2;
881 if (data_len < 2) {
882 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
883 break;
886 proto_tree_add_item(rr_tree, hf_nbns_num_command_blocks, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
887 cur_offset += 2;
888 data_len -= 2;
890 if (data_len < 2) {
891 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
892 break;
895 proto_tree_add_item(rr_tree, hf_nbns_num_pending_sessions, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
896 cur_offset += 2;
897 data_len -= 2;
899 if (data_len < 2) {
900 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
901 break;
904 proto_tree_add_item(rr_tree, hf_nbns_max_num_pending_sessions, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
905 cur_offset += 2;
906 data_len -= 2;
908 if (data_len < 2) {
909 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
910 break;
913 proto_tree_add_item(rr_tree, hf_nbns_max_total_sessions_possible, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
914 cur_offset += 2;
915 data_len -= 2;
917 if (data_len < 2) {
918 proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
919 break;
922 proto_tree_add_item(rr_tree, hf_nbns_session_data_packet_size, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
923 cur_offset += 2;
924 /*data_len -= 2;*/
925 out:
926 break;
928 default:
929 if (cinfo != NULL)
930 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
932 if (nbns_tree) {
933 rr_tree = proto_tree_add_subtree_format(nbns_tree, tvb, offset,
934 (cur_offset - offset) + data_len,
935 ett_nbns_rr, NULL, "%s: type %s, class %s",
936 name, type_name, class_name);
937 add_rr_to_tree(rr_tree, pinfo, tvb, offset, name,
938 name_len, type, dns_class, ttl, data_len);
939 proto_tree_add_item(rr_tree, hf_nbns_data, tvb, cur_offset, data_len, ENC_NA);
941 cur_offset += data_len;
942 break;
945 return cur_offset - offset;
948 static int
949 dissect_query_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
950 int count, column_info *cinfo, proto_tree *nbns_tree)
952 int start_off, add_off;
953 proto_tree *qatree;
954 proto_item *ti;
956 start_off = cur_off;
957 qatree = proto_tree_add_subtree(nbns_tree, tvb, start_off, -1, ett_nbns_qry, &ti, "Queries");
959 while (count-- > 0) {
960 add_off = dissect_nbns_query(tvb, cur_off, nbns_data_offset,
961 cinfo, qatree);
962 cur_off += add_off;
965 proto_item_set_len(ti, cur_off - start_off);
967 return cur_off - start_off;
970 static int
971 dissect_answer_records(tvbuff_t *tvb, packet_info *pinfo, int cur_off, int nbns_data_offset,
972 int count, column_info *cinfo, proto_tree *nbns_tree,
973 int opcode, const char *name)
975 int start_off, add_off;
976 proto_tree *qatree;
977 proto_item *ti;
979 start_off = cur_off;
980 qatree = proto_tree_add_subtree(nbns_tree, tvb, start_off, -1, ett_nbns_ans, &ti, name);
982 while (count-- > 0) {
983 add_off = dissect_nbns_answer(tvb, pinfo, cur_off, nbns_data_offset,
984 cinfo, qatree, opcode);
985 cur_off += add_off;
988 proto_item_set_len(ti, cur_off - start_off);
989 return cur_off - start_off;
992 static int
993 dissect_nbns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
995 int offset = 0;
996 int nbns_data_offset;
997 proto_tree *nbns_tree = NULL;
998 proto_item *ti;
999 uint32_t id, flags, opcode, quest, ans, auth, add;
1000 int cur_off;
1002 nbns_data_offset = offset;
1004 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBNS");
1005 col_clear(pinfo->cinfo, COL_INFO);
1007 /* To do: check for runts, errs, etc. */
1008 id = tvb_get_ntohs(tvb, offset + NBNS_ID);
1009 flags = tvb_get_ntohs(tvb, offset + NBNS_FLAGS);
1010 opcode = (uint16_t) ((flags & F_OPCODE) >> OPCODE_SHIFT);
1012 col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s",
1013 val_to_str(opcode, opcode_vals, "Unknown operation (%u)"),
1014 (flags & F_RESPONSE) ? " response" : "");
1016 ti = proto_tree_add_item(tree, proto_nbns, tvb, offset, -1, ENC_NA);
1017 nbns_tree = proto_item_add_subtree(ti, ett_nbns);
1019 proto_tree_add_uint(nbns_tree, hf_nbns_transaction_id, tvb,
1020 offset + NBNS_ID, 2, id);
1022 nbns_add_nbns_flags(pinfo->cinfo, nbns_tree, tvb, offset + NBNS_FLAGS, 0);
1024 proto_tree_add_item_ret_uint(nbns_tree, hf_nbns_count_questions, tvb,
1025 offset + NBNS_QUEST, 2, ENC_BIG_ENDIAN, &quest);
1026 proto_tree_add_item_ret_uint(nbns_tree, hf_nbns_count_answers, tvb,
1027 offset + NBNS_ANS, 2, ENC_BIG_ENDIAN, &ans);
1028 proto_tree_add_item_ret_uint(nbns_tree, hf_nbns_count_auth_rr, tvb,
1029 offset + NBNS_AUTH, 2, ENC_BIG_ENDIAN, &auth);
1030 proto_tree_add_item_ret_uint(nbns_tree, hf_nbns_count_add_rr, tvb,
1031 offset + NBNS_ADD, 2, ENC_BIG_ENDIAN, &add);
1033 cur_off = offset + NBNS_HDRLEN;
1035 if (quest > 0) {
1036 /* If this is a response, don't add information about the
1037 queries to the summary, just add information about the
1038 answers. */
1039 cur_off += dissect_query_records(tvb, cur_off,
1040 nbns_data_offset, quest,
1041 (!(flags & F_RESPONSE) ? pinfo->cinfo : NULL), nbns_tree);
1044 if (ans > 0) {
1045 /* If this is a request, don't add information about the
1046 answers to the summary, just add information about the
1047 queries. */
1048 cur_off += dissect_answer_records(tvb, pinfo, cur_off,
1049 nbns_data_offset, ans,
1050 ((flags & F_RESPONSE) ? pinfo->cinfo : NULL), nbns_tree,
1051 opcode, "Answers");
1054 /* Don't add information about the authoritative name
1055 servers, or the additional records, to the summary. */
1056 if (auth > 0)
1057 cur_off += dissect_answer_records(tvb, pinfo, cur_off,
1058 nbns_data_offset,
1059 auth, NULL, nbns_tree, opcode,
1060 "Authoritative nameservers");
1062 if (add > 0)
1063 /*cur_off += */dissect_answer_records(tvb, pinfo, cur_off,
1064 nbns_data_offset,
1065 add, NULL, nbns_tree, opcode,
1066 "Additional records");
1068 return tvb_captured_length(tvb);
1071 static heur_dissector_list_t netbios_heur_subdissector_list;
1073 static void
1074 dissect_netbios_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1076 heur_dtbl_entry_t *hdtbl_entry;
1079 * Try the heuristic dissectors for NetBIOS; if none of them
1080 * accept the packet, dissect it as data.
1082 if (!dissector_try_heuristic(netbios_heur_subdissector_list,
1083 tvb, pinfo, tree, &hdtbl_entry, NULL))
1084 call_data_dissector(tvb, pinfo, tree);
1088 * NBDS message types.
1090 #define NBDS_DIRECT_UNIQUE 0x10
1091 #define NBDS_DIRECT_GROUP 0x11
1092 #define NBDS_BROADCAST 0x12
1093 #define NBDS_ERROR 0x13
1094 #define NBDS_QUERY_REQUEST 0x14
1095 #define NBDS_POS_QUERY_RESPONSE 0x15
1096 #define NBDS_NEG_QUERY_RESPONSE 0x16
1098 static const value_string nbds_msgtype_vals[] = {
1099 { NBDS_DIRECT_UNIQUE, "Direct_unique datagram" },
1100 { NBDS_DIRECT_GROUP, "Direct_group datagram" },
1101 { NBDS_BROADCAST, "Broadcast datagram" },
1102 { NBDS_ERROR, "Datagram error" },
1103 { NBDS_QUERY_REQUEST, "Datagram query request" },
1104 { NBDS_POS_QUERY_RESPONSE, "Datagram positive query response" },
1105 { NBDS_NEG_QUERY_RESPONSE, "Datagram negative query response" },
1106 { 0, NULL }
1109 static const value_string node_type_vals[] = {
1110 { 0, "B node" },
1111 { 1, "P node" },
1112 { 2, "M node" },
1113 { 3, "NBDD" },
1114 { 0, NULL }
1117 static const value_string nbds_error_codes[] = {
1118 { 0x82, "Destination name not present" },
1119 { 0x83, "Invalid source name format" },
1120 { 0x84, "Invalid destination name format" },
1121 { 0x00, NULL }
1124 static int
1125 dissect_nbdgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1127 int offset = 0;
1128 proto_tree *nbdgm_tree;
1129 proto_item *ti;
1130 tvbuff_t *next_tvb;
1131 uint32_t msg_type;
1133 char *name;
1134 int name_type;
1135 int len;
1137 static int * const flags[] = {
1138 &hf_nbdgm_fragment,
1139 &hf_nbdgm_first,
1140 &hf_nbdgm_node_type,
1141 NULL
1144 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBDS");
1145 col_clear(pinfo->cinfo, COL_INFO);
1147 ti = proto_tree_add_item(tree, proto_nbdgm, tvb, offset, -1, ENC_NA);
1148 nbdgm_tree = proto_item_add_subtree(ti, ett_nbdgm);
1150 proto_tree_add_item_ret_uint(nbdgm_tree, hf_nbdgm_type, tvb,
1151 offset, 1, ENC_NA, &msg_type);
1153 col_add_str(pinfo->cinfo, COL_INFO,
1154 val_to_str(msg_type, nbds_msgtype_vals,
1155 "Unknown message type (0x%02X)"));
1157 proto_tree_add_bitmask(nbdgm_tree, tvb, offset+1, hf_nbdgm_flags, ett_nbdgm_flags, flags, ENC_BIG_ENDIAN);
1159 proto_tree_add_item(nbdgm_tree, hf_nbdgm_datagram_id, tvb, offset+2, 2, ENC_BIG_ENDIAN);
1161 proto_tree_add_item(nbdgm_tree, hf_nbdgm_src_ip, tvb, offset+4, 4, ENC_BIG_ENDIAN);
1163 proto_tree_add_item(nbdgm_tree, hf_nbdgm_src_port, tvb, offset+8, 2, ENC_BIG_ENDIAN);
1165 offset += 10;
1167 switch (msg_type) {
1169 case NBDS_DIRECT_UNIQUE:
1170 case NBDS_DIRECT_GROUP:
1171 case NBDS_BROADCAST:
1172 proto_tree_add_item(nbdgm_tree, hf_nbdgm_datagram_length,
1173 tvb, offset, 2, ENC_BIG_ENDIAN);
1174 offset += 2;
1176 proto_tree_add_item(nbdgm_tree, hf_nbdgm_packet_offset,
1177 tvb, offset, 2, ENC_BIG_ENDIAN);
1178 offset += 2;
1180 name = (char *)wmem_alloc(pinfo->pool, MAX_NAME_LEN);
1182 /* Source name */
1183 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1185 add_name_and_type(nbdgm_tree, tvb, offset, len, hf_nbdgm_source_name, name, name_type);
1186 offset += len;
1188 /* Destination name */
1189 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1191 add_name_and_type(nbdgm_tree, tvb, offset, len, hf_nbdgm_destination_name, name, name_type);
1192 offset += len;
1195 * Here we can pass the packet off to the next protocol.
1196 * Set the length of our top-level tree item to include
1197 * only our stuff.
1199 * XXX - take the datagram length into account, including
1200 * doing datagram reassembly?
1202 proto_item_set_len(ti, offset);
1203 next_tvb = tvb_new_subset_remaining(tvb, offset);
1204 dissect_netbios_payload(next_tvb, pinfo, tree);
1205 break;
1207 case NBDS_ERROR:
1208 proto_tree_add_item(nbdgm_tree, hf_nbdgm_error_code, tvb, offset,
1209 1, ENC_BIG_ENDIAN);
1210 offset += 1;
1211 proto_item_set_len(ti, offset);
1212 break;
1214 case NBDS_QUERY_REQUEST:
1215 case NBDS_POS_QUERY_RESPONSE:
1216 case NBDS_NEG_QUERY_RESPONSE:
1217 name = (char *)wmem_alloc(pinfo->pool, MAX_NAME_LEN);
1219 /* Destination name */
1220 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1222 add_name_and_type(nbdgm_tree, tvb, offset, len,
1223 hf_nbdgm_destination_name, name, name_type);
1224 offset += len;
1225 proto_item_set_len(ti, offset);
1226 break;
1228 return tvb_captured_length(tvb);
1232 * NetBIOS Session Service message types (RFC 1002).
1234 #define SESSION_MESSAGE 0x00
1235 #define SESSION_REQUEST 0x81
1236 #define POSITIVE_SESSION_RESPONSE 0x82
1237 #define NEGATIVE_SESSION_RESPONSE 0x83
1238 #define RETARGET_SESSION_RESPONSE 0x84
1239 #define SESSION_KEEP_ALIVE 0x85
1241 static const value_string message_types[] = {
1242 { SESSION_MESSAGE, "Session message" },
1243 { SESSION_REQUEST, "Session request" },
1244 { POSITIVE_SESSION_RESPONSE, "Positive session response" },
1245 { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
1246 { RETARGET_SESSION_RESPONSE, "Retarget session response" },
1247 { SESSION_KEEP_ALIVE, "Session keep-alive" },
1248 { 0x0, NULL }
1252 * NetBIOS Session Service flags.
1254 #define NBSS_FLAGS_E 0x1
1256 static const value_string nbss_error_codes[] = {
1257 { 0x80, "Not listening on called name" },
1258 { 0x81, "Not listening for calling name" },
1259 { 0x82, "Called name not present" },
1260 { 0x83, "Called name present, but insufficient resources" },
1261 { 0x8F, "Unspecified error" },
1262 { 0x0, NULL }
1266 * Dissect a single NBSS packet (there may be more than one in a given
1267 * TCP segment).
1269 * [ Hmmm, in my experience, I have never seen more than one NBSS in a
1270 * single segment, since they mostly contain SMBs which are essentially
1271 * a request response type protocol (RJS). ]
1273 * [ However, under heavy load with many requests multiplexed on one
1274 * session it is not unusual to see multiple requests in one TCP
1275 * segment. Unfortunately, in this case a single session message is
1276 * frequently split over multiple segments, which frustrates decoding
1277 * (MMM). ]
1279 static void
1280 dissect_nbss_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1281 int is_cifs)
1283 int offset = 0;
1284 proto_tree *nbss_tree = NULL;
1285 proto_item *ti = NULL;
1286 uint8_t msg_type;
1287 uint8_t flags;
1288 uint32_t length;
1289 int len;
1290 char *name;
1291 int name_type;
1292 uint8_t error_code;
1293 tvbuff_t *next_tvb;
1294 const char *saved_proto;
1295 static int * const nbss_flags[] = {
1296 &hf_nbss_flags_e,
1297 NULL
1300 name = (char *)wmem_alloc(pinfo->pool, MAX_NAME_LEN);
1302 msg_type = tvb_get_uint8(tvb, offset);
1304 ti = proto_tree_add_item(tree, proto_nbss, tvb, offset, -1, ENC_NA);
1305 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1307 proto_tree_add_item(nbss_tree, hf_nbss_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1309 offset += 1;
1311 if (is_cifs) {
1312 proto_tree_add_item(nbss_tree, hf_nbss_cifs_length, tvb, offset, 3, ENC_BIG_ENDIAN);
1313 offset += 3;
1314 } else {
1315 flags = tvb_get_uint8(tvb, offset);
1316 proto_tree_add_bitmask(nbss_tree, tvb, offset, hf_nbss_flags, ett_nbss_flags, nbss_flags, ENC_BIG_ENDIAN);
1318 length = tvb_get_ntohs(tvb, offset + 1);
1319 if (flags & NBSS_FLAGS_E)
1320 length += 0x10000;
1321 proto_tree_add_uint(nbss_tree, hf_nbss_length, tvb, offset, 3, length);
1323 offset += 3;
1326 switch (msg_type) {
1328 case SESSION_REQUEST:
1329 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1330 if (tree)
1331 add_name_and_type(nbss_tree, tvb, offset, len,
1332 hf_nbss_called_name, name, name_type);
1333 offset += len;
1335 col_append_fstr(pinfo->cinfo, COL_INFO, ", to %s ", name);
1337 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1339 if (tree)
1340 add_name_and_type(nbss_tree, tvb, offset, len,
1341 hf_nbss_calling_name, name, name_type);
1343 col_append_fstr(pinfo->cinfo, COL_INFO, "from %s", name);
1345 break;
1347 case NEGATIVE_SESSION_RESPONSE:
1348 error_code = tvb_get_uint8(tvb, offset);
1349 proto_tree_add_uint(nbss_tree, hf_nbss_error_code, tvb, offset, 1,
1350 error_code);
1352 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1353 val_to_str(error_code, nbss_error_codes, "Unknown (%x)"));
1355 break;
1357 case RETARGET_SESSION_RESPONSE:
1358 proto_tree_add_item(nbss_tree, hf_nbss_retarget_ip_address,
1359 tvb, offset, 4, ENC_BIG_ENDIAN);
1361 offset += 4;
1363 proto_tree_add_item(nbss_tree, hf_nbss_retarget_port,
1364 tvb, offset, 2, ENC_BIG_ENDIAN);
1366 break;
1368 case SESSION_MESSAGE:
1370 * Here we can pass the message off to the next protocol.
1371 * Set the length of our top-level tree item to include
1372 * only our stuff.
1374 next_tvb = tvb_new_subset_remaining(tvb, offset);
1377 * Dissect the message.
1379 * If it gets an error that means there's no point in
1380 * dissecting any more PDUs, rethrow the exception in
1381 * question.
1383 * If it gets any other error, report it and continue, as that
1384 * means that PDU got an error, but that doesn't mean we should
1385 * stop dissecting PDUs within this frame or chunk of reassembled
1386 * data.
1388 saved_proto = pinfo->current_proto;
1389 TRY {
1390 dissect_netbios_payload(next_tvb, pinfo, tree);
1392 CATCH_NONFATAL_ERRORS {
1393 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1394 pinfo->current_proto = saved_proto;
1396 ENDTRY;
1397 break;
1402 static int
1403 dissect_continuation_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1405 proto_tree *nbss_tree;
1406 proto_item *ti;
1409 * It looks like a continuation.
1411 col_set_str(pinfo->cinfo, COL_INFO, "NBSS Continuation Message");
1413 if (tree) {
1414 ti = proto_tree_add_item(tree, proto_nbss, tvb, 0, -1, ENC_NA);
1415 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1416 proto_tree_add_item(nbss_tree, hf_nbss_continuation_data, tvb, 0, -1, ENC_NA);
1419 return tvb_captured_length(tvb);
1422 static int
1423 dissect_nbss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1425 struct tcpinfo *tcpinfo;
1426 int offset = 0;
1427 unsigned length_remaining;
1428 unsigned plen;
1429 int max_data;
1430 uint8_t msg_type;
1431 uint8_t flags;
1432 uint32_t length;
1433 bool is_cifs;
1434 tvbuff_t *next_tvb;
1436 /* Reject the packet if data is NULL */
1437 if (data == NULL)
1438 return 0;
1439 tcpinfo = (struct tcpinfo *)data;
1441 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBSS");
1442 col_clear(pinfo->cinfo, COL_INFO);
1444 max_data = tvb_captured_length(tvb);
1446 msg_type = tvb_get_uint8(tvb, offset);
1448 if (pinfo->match_uint == TCP_PORT_CIFS) {
1450 * Windows 2000 CIFS clients can dispense completely
1451 * with the NETBIOS encapsulation and directly use CIFS
1452 * over TCP. As would be expected, the framing is
1453 * identical, except that the length is 24 bits instead
1454 * of 17. The only message types used are
1455 * SESSION_MESSAGE and SESSION_KEEP_ALIVE.
1457 is_cifs = true;
1458 } else {
1459 is_cifs = false;
1463 * This might be a continuation of an earlier message.
1464 * (Yes, that might be true even if we're doing TCP reassembly,
1465 * as the first TCP segment in the capture might start in the
1466 * middle of an NBNS message.)
1470 * If this isn't reassembled data, check to see whether it
1471 * looks like a continuation of a message.
1472 * (If it is reassembled data, it shouldn't be a continuation,
1473 * as reassembly should've gathered the continuations together
1474 * into a message.)
1475 * XXX: Unless it was reassembled because we didn't have enough
1476 * data for a NBSS header, it had a first byte that looked like a
1477 * message type, but it turned out not to be a message but continuation
1478 * data after all. Perhaps we should check even reassembled data,
1479 * at least if it's the first message in the conversation.
1481 if (!tcpinfo->is_reassembled) {
1482 if (max_data < 4) {
1484 * Not enough data for an NBSS header. It could be a message
1485 * split into a very small payload, or a continuation of a message.
1487 if (try_val_to_str(msg_type, message_types)) {
1489 * The first byte looks like a valid message type.
1490 * Can we do reassembly?
1492 if (nbss_desegment && pinfo->can_desegment) {
1494 * Yes. Tell the TCP dissector where the data for this message
1495 * starts in the data it handed us and that we need "some more
1496 * data." Don't tell it exactly how many bytes we need because
1497 * if/when we ask for even more (after the header) that will
1498 * break reassembly.
1500 pinfo->desegment_offset = offset;
1501 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1502 return tvb_captured_length(tvb);
1506 * Either we can't do reassembly, or this doesn't look
1507 * like a valid message type. Mark it as continuation.
1509 return dissect_continuation_packet(tvb, pinfo, tree);
1513 * The largest size in for non-SMB NBSS traffic is
1514 * 17 bits (0x1FFFF).
1516 * The SMB1 unix extensions and the SMB2 multi credit
1517 * feature allow more than 17 bits (0x1FFFF), they allow
1518 * 24 bits (0xFFFFFF).
1520 * So if it is a SESSION_MESSAGE and SMB1 or SMB2
1521 * mark it as is_cifs.
1523 if (tvb_captured_length_remaining(tvb, offset) >= 8
1524 && tvb_get_uint8(tvb,offset+0) == SESSION_MESSAGE
1525 && tvb_get_uint8(tvb,offset+5) == 'S'
1526 && tvb_get_uint8(tvb,offset+6) == 'M'
1527 && tvb_get_uint8(tvb,offset+7) == 'B') {
1528 is_cifs = true;
1529 } else {
1530 is_cifs = false;
1534 * We have enough data for an NBSS header.
1535 * Get the flags and length of the message,
1536 * and see if they're sane.
1538 if (is_cifs) {
1539 flags = 0;
1540 length = tvb_get_ntoh24(tvb, offset + 1);
1541 } else {
1542 flags = tvb_get_uint8(tvb, offset + 1);
1543 length = tvb_get_ntohs(tvb, offset + 2);
1544 if (flags & NBSS_FLAGS_E)
1545 length += 0x10000;
1547 if ((flags & (~NBSS_FLAGS_E)) != 0) {
1549 * A bogus flag was set; assume it's a continuation.
1551 return dissect_continuation_packet(tvb, pinfo, tree);
1554 switch (msg_type) {
1556 case SESSION_MESSAGE:
1558 * This is variable-length.
1559 * All we know is that it shouldn't be zero.
1560 * (XXX - can we get zero-length messages?
1561 * Not with SMB, but perhaps other NetBIOS-based
1562 * protocols have them.)
1564 if (length == 0)
1565 return dissect_continuation_packet(tvb, pinfo, tree);
1567 break;
1569 case SESSION_REQUEST:
1571 * This is variable-length.
1572 * The names are DNS-encoded 32-byte values;
1573 * we need at least 2 bytes (one for each name;
1574 * actually, we should have more for the first
1575 * name, as there's no name preceding it so
1576 * there should be no compression), and we
1577 * shouldn't have more than 128 bytes (actually,
1578 * we shouldn't have that many).
1580 * XXX - actually, Mac OS X 10.1 (yes, that's
1581 * redundant, but that's what Apple calls it,
1582 * not Mac OS X.1) puts names longer than 16
1583 * characters into session request messages,
1584 * so we can have more than 32 bytes of
1585 * name value, so we can have more than 128
1586 * bytes of data.
1588 if (length < 2 || length > 256)
1589 return dissect_continuation_packet(tvb, pinfo, tree);
1590 break;
1592 case POSITIVE_SESSION_RESPONSE:
1594 * This has no data, so the length must be zero.
1596 if (length != 0)
1597 return dissect_continuation_packet(tvb, pinfo, tree);
1598 break;
1600 case NEGATIVE_SESSION_RESPONSE:
1602 * This has 1 byte of data.
1604 if (length != 1)
1605 return dissect_continuation_packet(tvb, pinfo, tree);
1606 break;
1608 case RETARGET_SESSION_RESPONSE:
1610 * This has 6 bytes of data.
1612 if (length != 6)
1613 return dissect_continuation_packet(tvb, pinfo, tree);
1614 break;
1616 case SESSION_KEEP_ALIVE:
1618 * This has no data, so the length must be zero.
1620 if (length != 0)
1621 return dissect_continuation_packet(tvb, pinfo, tree);
1622 break;
1624 default:
1626 * Unknown message type; assume it's a continuation.
1628 return dissect_continuation_packet(tvb, pinfo, tree);
1632 col_add_str(pinfo->cinfo, COL_INFO,
1633 val_to_str(msg_type, message_types, "Unknown (%02x)"));
1635 while ((length_remaining = tvb_reported_length_remaining(tvb, offset)) > 0) {
1637 * Can we do reassembly?
1639 if (nbss_desegment && pinfo->can_desegment) {
1641 * Yes - is the NBSS header split across segment boundaries?
1643 if (length_remaining < 4) {
1645 * Yes. Tell the TCP dissector where the data for this message
1646 * starts in the data it handed us and that we need "some more
1647 * data." Don't tell it exactly how many bytes we need because
1648 * if/when we ask for even more (after the header) that will
1649 * break reassembly.
1651 pinfo->desegment_offset = offset;
1652 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1653 return tvb_captured_length(tvb);
1658 * Get the length of the NBSS message.
1660 if (is_cifs) {
1661 length = tvb_get_ntoh24(tvb, offset + 1);
1662 } else {
1663 flags = tvb_get_uint8(tvb, offset + 1);
1664 length = tvb_get_ntohs(tvb, offset + 2);
1665 if (flags & NBSS_FLAGS_E)
1666 length += 65536;
1668 plen = length + 4; /* Include length of NBSS header */
1670 /* give a hint to TCP where the next PDU starts
1671 * so that it can attempt to find it in case it starts
1672 * somewhere in the middle of a segment.
1674 if(!pinfo->fd->visited){
1675 /* 'Only' SMB is transported ontop of this so make sure
1676 * there is an SMB header there ...
1678 if( ((int)plen>tvb_reported_length_remaining(tvb, offset))
1679 &&(tvb_captured_length_remaining(tvb, offset) >= 8)
1680 &&(tvb_get_uint8(tvb,offset+5) == 'S')
1681 &&(tvb_get_uint8(tvb,offset+6) == 'M')
1682 &&(tvb_get_uint8(tvb,offset+7) == 'B') ){
1683 pinfo->want_pdu_tracking = 2;
1684 pinfo->bytes_until_next_pdu = (length+4)-tvb_reported_length_remaining(tvb, offset);
1689 * Can we do reassembly?
1691 if (nbss_desegment && pinfo->can_desegment) {
1693 * Yes - is the NBSS message split across segment boundaries?
1695 if (length_remaining < plen) {
1697 * Yes. Tell the TCP dissector where the data for this message
1698 * starts in the data it handed us, and how many more bytes we
1699 * need, and return.
1701 pinfo->desegment_offset = offset;
1702 pinfo->desegment_len = plen - length_remaining;
1703 return tvb_captured_length(tvb);
1708 * Construct a tvbuff containing the amount of the payload we have
1709 * available. Make its reported length the amount of data in the PDU.
1711 next_tvb = tvb_new_subset_length(tvb, offset, plen);
1713 dissect_nbss_packet(next_tvb, pinfo, tree, is_cifs);
1715 offset += plen;
1718 return tvb_captured_length(tvb);
1721 void
1722 proto_register_nbt(void)
1725 static hf_register_info hf_nbns[] = {
1726 { &hf_nbns_flags,
1727 { "Flags", "nbns.flags",
1728 FT_UINT16, BASE_HEX, NULL, 0x0,
1729 NULL, HFILL }},
1730 { &hf_nbns_flags_response,
1731 { "Response", "nbns.flags.response",
1732 FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
1733 "Is the message a response?", HFILL }},
1734 { &hf_nbns_flags_opcode,
1735 { "Opcode", "nbns.flags.opcode",
1736 FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
1737 "Operation code", HFILL }},
1738 { &hf_nbns_flags_authoritative,
1739 { "Authoritative", "nbns.flags.authoritative",
1740 FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
1741 "Is the server is an authority for the domain?", HFILL }},
1742 { &hf_nbns_flags_truncated,
1743 { "Truncated", "nbns.flags.truncated",
1744 FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
1745 "Is the message truncated?", HFILL }},
1746 { &hf_nbns_flags_recdesired,
1747 { "Recursion desired", "nbns.flags.recdesired",
1748 FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
1749 "Do query recursively?", HFILL }},
1750 { &hf_nbns_flags_recavail,
1751 { "Recursion available", "nbns.flags.recavail",
1752 FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
1753 "Can the server do recursive queries?", HFILL }},
1754 { &hf_nbns_flags_broadcast,
1755 { "Broadcast", "nbns.flags.broadcast",
1756 FT_BOOLEAN, 16, TFS(&tfs_flags_broadcast), F_BROADCAST,
1757 "Is this a broadcast packet?", HFILL }},
1758 { &hf_nbns_flags_rcode,
1759 { "Reply code", "nbns.flags.rcode",
1760 FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
1761 NULL, HFILL }},
1762 { &hf_nbns_transaction_id,
1763 { "Transaction ID", "nbns.id",
1764 FT_UINT16, BASE_HEX, NULL, 0x0,
1765 "Identification of transaction", HFILL }},
1766 { &hf_nbns_count_questions,
1767 { "Questions", "nbns.count.queries",
1768 FT_UINT16, BASE_DEC, NULL, 0x0,
1769 "Number of queries in packet", HFILL }},
1770 { &hf_nbns_count_answers,
1771 { "Answer RRs", "nbns.count.answers",
1772 FT_UINT16, BASE_DEC, NULL, 0x0,
1773 "Number of answers in packet", HFILL }},
1774 { &hf_nbns_count_auth_rr,
1775 { "Authority RRs", "nbns.count.auth_rr",
1776 FT_UINT16, BASE_DEC, NULL, 0x0,
1777 "Number of authoritative records in packet", HFILL }},
1778 { &hf_nbns_count_add_rr,
1779 { "Additional RRs", "nbns.count.add_rr",
1780 FT_UINT16, BASE_DEC, NULL, 0x0,
1781 "Number of additional records in packet", HFILL }},
1782 { &hf_nbns_name_flags,
1783 { "Name flags", "nbns.name_flags",
1784 FT_UINT16, BASE_HEX, NULL, 0x0,
1785 NULL, HFILL }},
1786 { &hf_nbns_name_flags_group,
1787 { "Name type", "nbns.name_flags.group",
1788 FT_BOOLEAN, 16, TFS(&tfs_group_unique_name), NAME_FLAGS_G,
1789 NULL, HFILL }},
1790 { &hf_nbns_name_flags_ont,
1791 { "ONT", "nbns.name_flags.ont",
1792 FT_UINT16, BASE_DEC, VALS(name_flags_ont_vals), NAME_FLAGS_ONT,
1793 NULL, HFILL }},
1794 { &hf_nbns_name_flags_drg,
1795 { "Name is being deregistered", "nbns.name_flags.drg",
1796 FT_BOOLEAN, 16, TFS(&tfs_yes_no), NAME_FLAGS_DRG,
1797 NULL, HFILL }},
1798 { &hf_nbns_name_flags_cnf,
1799 { "Name is in conflict", "nbns.name_flags.cnf",
1800 FT_BOOLEAN, 16, TFS(&tfs_yes_no), NAME_FLAGS_CNF,
1801 NULL, HFILL }},
1802 { &hf_nbns_name_flags_act,
1803 { "Name is active", "nbns.name_flags.act",
1804 FT_BOOLEAN, 16, TFS(&tfs_yes_no), NAME_FLAGS_ACT,
1805 NULL, HFILL }},
1806 { &hf_nbns_name_flags_prm,
1807 { "Permanent node name", "nbns.name_flags.prm",
1808 FT_BOOLEAN, 16, TFS(&tfs_yes_no), NAME_FLAGS_PRM,
1809 NULL, HFILL }},
1810 { &hf_nbns_nb_flags,
1811 { "Name flags", "nbns.nb_flags",
1812 FT_UINT16, BASE_HEX, NULL, 0x0,
1813 NULL, HFILL }},
1814 { &hf_nbns_nb_flags_group,
1815 { "Name type", "nbns.nb_flags.group",
1816 FT_BOOLEAN, 16, TFS(&tfs_group_unique_name), NB_FLAGS_G,
1817 NULL, HFILL }},
1818 { &hf_nbns_nb_flags_ont,
1819 { "ONT", "nbns.nb_flags.ont",
1820 FT_UINT16, BASE_DEC, VALS(nb_flags_ont_vals), NB_FLAGS_ONT,
1821 NULL, HFILL }},
1822 { &hf_nbns_type,
1823 { "Type", "nbns.type",
1824 FT_UINT16, BASE_DEC, VALS(nb_type_name_vals), 0x0,
1825 NULL, HFILL }},
1826 { &hf_nbns_class,
1827 { "Class", "nbns.class",
1828 FT_UINT16, BASE_DEC, VALS(dns_classes), 0x0,
1829 NULL, HFILL }},
1830 { &hf_nbns_name,
1831 { "Name", "nbns.name",
1832 FT_STRING, BASE_NONE, NULL, 0x0,
1833 NULL, HFILL }},
1835 /* Generated from convert_proto_tree_add_text.pl */
1836 { &hf_nbns_addr, { "Addr", "nbns.addr", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1837 { &hf_nbns_number_of_names, { "Number of names", "nbns.number_of_names", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1838 { &hf_nbns_unit_id, { "Unit ID", "nbns.unit_id", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1839 { &hf_nbns_jumpers, { "Jumpers", "nbns.jumpers", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1840 { &hf_nbns_test_result, { "Test result", "nbns.test_result", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1841 { &hf_nbns_version_number, { "Version number", "nbns.version_number", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1842 { &hf_nbns_period_of_statistics, { "Period of statistics", "nbns.period_of_statistics", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1843 { &hf_nbns_num_crcs, { "Number of CRCs", "nbns.num_crcs", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1844 { &hf_nbns_num_alignment_errors, { "Number of alignment errors", "nbns.num_alignment_errors", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1845 { &hf_nbns_num_collisions, { "Number of collisions", "nbns.num_collisions", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1846 { &hf_nbns_num_send_aborts, { "Number of send aborts", "nbns.num_send_aborts", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1847 { &hf_nbns_num_good_sends, { "Number of good sends", "nbns.num_good_sends", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1848 { &hf_nbns_num_good_receives, { "Number of good receives", "nbns.num_good_receives", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1849 { &hf_nbns_num_retransmits, { "Number of retransmits", "nbns.numretransmits", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1850 { &hf_nbns_num_no_resource_conditions, { "Number of no resource conditions", "nbns.num_no_resource_conditions", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1851 { &hf_nbns_num_command_blocks, { "Number of command blocks", "nbns.numcommand_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1852 { &hf_nbns_num_pending_sessions, { "Number of pending sessions", "nbns.numpending_sessions", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1853 { &hf_nbns_max_num_pending_sessions, { "Max number of pending sessions", "nbns.max_num_pending_sessions", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1854 { &hf_nbns_max_total_sessions_possible, { "Max total sessions possible", "nbns.max_total_sessions_possible", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1855 { &hf_nbns_session_data_packet_size, { "Session data packet size", "nbns.session_data_packet_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1856 { &hf_nbns_data, { "Data", "nbns.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1857 { &hf_nbns_netbios_name, { "Name", "nbns.netbios_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1858 { &hf_nbns_ttl, { "Time to live", "nbns.ttl", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1859 { &hf_nbns_data_length, { "Data length", "nbns.data_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1862 static hf_register_info hf_nbdgm[] = {
1863 { &hf_nbdgm_type,
1864 { "Message Type", "nbdgm.type",
1865 FT_UINT8, BASE_DEC, VALS(nbds_msgtype_vals), 0x0,
1866 "NBDGM message type", HFILL }},
1867 { &hf_nbdgm_flags,
1868 { "Flags", "nbdgm.flags",
1869 FT_UINT8, BASE_HEX, NULL, 0x0,
1870 NULL, HFILL }},
1871 { &hf_nbdgm_fragment,
1872 { "More fragments follow", "nbdgm.next",
1873 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1874 "true if more fragments follow", HFILL }},
1875 { &hf_nbdgm_first,
1876 { "This is first fragment", "nbdgm.first",
1877 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1878 "true if first fragment", HFILL }},
1879 { &hf_nbdgm_node_type,
1880 { "Node Type", "nbdgm.node_type",
1881 FT_UINT8, BASE_DEC, VALS(node_type_vals), 0x0C,
1882 NULL, HFILL }},
1883 { &hf_nbdgm_datagram_id,
1884 { "Datagram ID", "nbdgm.dgram_id",
1885 FT_UINT16, BASE_HEX, NULL, 0x0,
1886 "Datagram identifier", HFILL }},
1887 { &hf_nbdgm_src_ip,
1888 { "Source IP", "nbdgm.src.ip",
1889 FT_IPv4, BASE_NONE, NULL, 0x0,
1890 "Source IPv4 address", HFILL }},
1891 { &hf_nbdgm_src_port,
1892 { "Source Port", "nbdgm.src.port",
1893 FT_UINT16, BASE_DEC, NULL, 0x0,
1894 NULL, HFILL }},
1895 { &hf_nbdgm_datagram_length,
1896 { "Datagram length", "nbdgm.dgram_len",
1897 FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0,
1898 NULL, HFILL }},
1899 { &hf_nbdgm_packet_offset,
1900 { "Packet offset", "nbdgm.pkt_offset",
1901 FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0,
1902 NULL, HFILL }},
1903 { &hf_nbdgm_error_code,
1904 { "Error code", "nbdgm.error_code",
1905 FT_UINT8, BASE_HEX, VALS(nbds_error_codes), 0x0,
1906 NULL, HFILL }},
1907 { &hf_nbdgm_source_name,
1908 { "Source name", "nbdgm.source_name",
1909 FT_STRING, BASE_NONE, NULL, 0x0,
1910 NULL, HFILL }},
1911 { &hf_nbdgm_destination_name,
1912 { "Destination name", "nbdgm.destination_name",
1913 FT_STRING, BASE_NONE, NULL, 0x0,
1914 NULL, HFILL }},
1917 static hf_register_info hf_nbss[] = {
1918 { &hf_nbss_type,
1919 { "Message Type", "nbss.type",
1920 FT_UINT8, BASE_HEX, VALS(message_types), 0x0,
1921 "NBSS message type", HFILL }},
1922 { &hf_nbss_flags,
1923 { "Flags", "nbss.flags",
1924 FT_UINT8, BASE_HEX, NULL, 0x0,
1925 "NBSS message flags", HFILL }},
1926 { &hf_nbss_flags_e,
1927 { "Extend", "nbss.flags.e",
1928 FT_BOOLEAN, 8, TFS(&tfs_nbss_flags_e), NBSS_FLAGS_E,
1929 NULL, HFILL }},
1930 { &hf_nbss_length,
1931 { "Length", "nbss.length",
1932 FT_UINT24, BASE_DEC, NULL, 0x0,
1933 "Length of trailer (payload) following this field in bytes", HFILL }},
1934 { &hf_nbss_cifs_length,
1935 { "Length", "nbss.length",
1936 FT_UINT24, BASE_DEC, NULL, 0x0,
1937 "Length trailer (payload) following this field in bytes", HFILL }},
1938 { &hf_nbss_error_code,
1939 { "Error code", "nbss.error_code",
1940 FT_UINT8, BASE_HEX, VALS(nbss_error_codes), 0x0,
1941 NULL, HFILL }},
1942 { &hf_nbss_retarget_ip_address,
1943 { "Retarget IP address", "nbss.retarget_ip_address",
1944 FT_IPv4, BASE_NONE, NULL, 0x0,
1945 NULL, HFILL }},
1946 { &hf_nbss_retarget_port,
1947 { "Retarget port", "nbss.retarget_port",
1948 FT_UINT16, BASE_DEC, NULL, 0x0,
1949 NULL, HFILL }},
1950 { &hf_nbss_continuation_data,
1951 { "Continuation data", "nbss.continuation_data",
1952 FT_BYTES, BASE_NONE, NULL, 0x0,
1953 NULL, HFILL }},
1954 { &hf_nbss_called_name,
1955 { "Called name", "nbss.called_name",
1956 FT_STRING, BASE_NONE, NULL, 0x0,
1957 NULL, HFILL }},
1958 { &hf_nbss_calling_name,
1959 { "Calling name", "nbss.calling_name",
1960 FT_STRING, BASE_NONE, NULL, 0x0,
1961 NULL, HFILL }},
1963 static int *ett[] = {
1964 &ett_nbns,
1965 &ett_nbns_qd,
1966 &ett_nbns_flags,
1967 &ett_nbns_nb_flags,
1968 &ett_nbns_name_flags,
1969 &ett_nbns_rr,
1970 &ett_nbns_qry,
1971 &ett_nbns_ans,
1972 &ett_nbdgm,
1973 &ett_nbdgm_flags,
1974 &ett_nbss,
1975 &ett_nbss_flags,
1978 static ei_register_info ei[] = {
1979 { &ei_nbns_incomplete_entry, { "nbns.incomplete_entry", PI_MALFORMED, PI_ERROR, "incomplete entry", EXPFILL }},
1982 module_t *nbss_module;
1983 expert_module_t* expert_nbns;
1985 proto_nbns = proto_register_protocol("NetBIOS Name Service", "NBNS", "nbns");
1986 nbns_handle = register_dissector("nbns", dissect_nbns, proto_nbns);
1987 proto_register_field_array(proto_nbns, hf_nbns, array_length(hf_nbns));
1988 expert_nbns = expert_register_protocol(proto_nbns);
1989 expert_register_field_array(expert_nbns, ei, array_length(ei));
1991 proto_nbdgm = proto_register_protocol("NetBIOS Datagram Service",
1992 "NBDS", "nbdgm");
1993 nbdgm_handle = register_dissector("nbds", dissect_nbdgm, proto_nbdgm);
1994 proto_register_field_array(proto_nbdgm, hf_nbdgm, array_length(hf_nbdgm));
1996 proto_nbss = proto_register_protocol("NetBIOS Session Service",
1997 "NBSS", "nbss");
1998 nbss_handle = register_dissector("nbss", dissect_nbss, proto_nbss);
1999 proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));
2001 proto_register_subtree_array(ett, array_length(ett));
2003 nbss_module = prefs_register_protocol(proto_nbss, NULL);
2004 prefs_register_bool_preference(nbss_module, "desegment_nbss_commands",
2005 "Reassemble NBSS packets spanning multiple TCP segments",
2006 "Whether the NBSS dissector should reassemble packets spanning multiple TCP segments."
2007 " To use this option, you must also enable"
2008 " \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2009 &nbss_desegment);
2012 void
2013 proto_reg_handoff_nbt(void)
2015 dissector_add_uint_with_preference("udp.port", UDP_PORT_NBNS, nbns_handle);
2016 dissector_add_uint_with_preference("udp.port", UDP_PORT_NBDGM, nbdgm_handle);
2017 dissector_add_uint_range_with_preference("tcp.port", TCP_NBSS_PORT_RANGE, nbss_handle);
2019 netbios_heur_subdissector_list = find_heur_dissector_list("netbios");
2021 dissector_add_string("quic.proto", "smb", nbss_handle);
2025 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2027 * Local variables:
2028 * c-basic-offset: 4
2029 * tab-width: 8
2030 * indent-tabs-mode: nil
2031 * End:
2033 * vi: set shiftwidth=4 tabstop=8 expandtab:
2034 * :indentSize=4:tabSize=8:noTabs=true: