HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-nbns.c
bloba3d54f1a65f09d08015d44e70f18856eb8d10aaf
1 /* packet-nbns.c
2 * Routines for NetBIOS-over-TCP packet disassembly (the name dates back
3 * to when it had only NBNS)
4 * Guy Harris <guy@alum.mit.edu>
6 * $Id$
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "config.h"
29 #include <string.h>
30 #include <glib.h>
32 #include <epan/packet.h>
33 #include <epan/exceptions.h>
34 #include <epan/wmem/wmem.h>
35 #include <epan/prefs.h>
36 #include <epan/strutil.h>
37 #include <epan/show_exception.h>
39 #include "packet-dns.h"
40 #include "packet-netbios.h"
41 #include "packet-tcp.h"
43 static int proto_nbns = -1;
44 static int hf_nbns_flags = -1;
45 static int hf_nbns_flags_response = -1;
46 static int hf_nbns_flags_opcode = -1;
47 static int hf_nbns_flags_authoritative = -1;
48 static int hf_nbns_flags_truncated = -1;
49 static int hf_nbns_flags_recdesired = -1;
50 static int hf_nbns_flags_recavail = -1;
51 static int hf_nbns_flags_broadcast = -1;
52 static int hf_nbns_flags_rcode = -1;
53 static int hf_nbns_transaction_id = -1;
54 static int hf_nbns_count_questions = -1;
55 static int hf_nbns_count_answers = -1;
56 static int hf_nbns_count_auth_rr = -1;
57 static int hf_nbns_count_add_rr = -1;
58 static int hf_nbns_name_flags = -1;
59 static int hf_nbns_name_flags_group = -1;
60 static int hf_nbns_name_flags_ont = -1;
61 static int hf_nbns_name_flags_drg = -1;
62 static int hf_nbns_name_flags_cnf = -1;
63 static int hf_nbns_name_flags_act = -1;
64 static int hf_nbns_name_flags_prm = -1;
65 static int hf_nbns_nb_flags = -1;
66 static int hf_nbns_nb_flags_group = -1;
67 static int hf_nbns_nb_flags_ont = -1;
69 static gint ett_nbns = -1;
70 static gint ett_nbns_qd = -1;
71 static gint ett_nbns_flags = -1;
72 static gint ett_nbns_nb_flags = -1;
73 static gint ett_nbns_name_flags = -1;
74 static gint ett_nbns_rr = -1;
75 static gint ett_nbns_qry = -1;
76 static gint ett_nbns_ans = -1;
78 static int proto_nbdgm = -1;
79 static int hf_nbdgm_type = -1;
80 static int hf_nbdgm_fragment = -1;
81 static int hf_nbdgm_first = -1;
82 static int hf_nbdgm_node_type = -1;
83 static int hf_nbdgm_datagram_id = -1;
84 static int hf_nbdgm_src_ip = -1;
85 static int hf_nbdgm_src_port = -1;
87 static gint ett_nbdgm = -1;
89 static int proto_nbss = -1;
90 static int hf_nbss_type = -1;
91 static int hf_nbss_flags = -1;
92 static int hf_nbss_flags_e = -1;
93 static int hf_nbss_length = -1;
94 static int hf_nbss_cifs_length = -1;
96 static gint ett_nbss = -1;
97 static gint ett_nbss_flags = -1;
99 /* desegmentation of NBSS over TCP */
100 static gboolean nbss_desegment = TRUE;
102 /* See RFC 1001 and 1002 for information on the first three, and see
104 http://www.cifs.com/specs/draft-leach-cifs-v1-spec-01.txt
106 Appendix B, and various messages on the CIFS mailing list such as
108 http://discuss.microsoft.com/SCRIPTS/WA-MSD.EXE?A2=ind9811A&L=cifs&P=R386
110 for information on the fourth. */
111 #define UDP_PORT_NBNS 137
112 #define UDP_PORT_NBDGM 138
113 #define TCP_PORT_NBSS 139
114 #define TCP_PORT_CIFS 445
116 /* Packet structure taken from RFC 1002. See also RFC 1001.
117 * Opcode, flags, and rcode treated as "flags", similarly to DNS,
118 * to make it easier to lift the dissection code from "packet-dns.c". */
120 /* Offsets of fields in the NBNS header. */
121 #define NBNS_ID 0
122 #define NBNS_FLAGS 2
123 #define NBNS_QUEST 4
124 #define NBNS_ANS 6
125 #define NBNS_AUTH 8
126 #define NBNS_ADD 10
128 /* Length of NBNS header. */
129 #define NBNS_HDRLEN 12
131 /* type values */
132 #define T_NB 32 /* NetBIOS name service RR */
133 #define T_NBSTAT 33 /* NetBIOS node status RR */
135 /* Bit fields in the flags */
136 #define F_RESPONSE (1<<15) /* packet is response */
137 #define F_OPCODE (0xF<<11) /* query opcode */
138 #define OPCODE_SHIFT 11
139 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
140 #define F_TRUNCATED (1<<9) /* response is truncated */
141 #define F_RECDESIRED (1<<8) /* recursion desired */
142 #define F_RECAVAIL (1<<7) /* recursion available */
143 #define F_BROADCAST (1<<4) /* broadcast/multicast packet */
144 #define F_RCODE (0xF<<0) /* reply code */
146 static const true_false_string tfs_flags_response = {
147 "Message is a response",
148 "Message is a query"
151 static const true_false_string tfs_flags_authoritative = {
152 "Server is an authority for domain",
153 "Server is not an authority for domain"
156 static const true_false_string tfs_flags_truncated = {
157 "Message is truncated",
158 "Message is not truncated"
161 static const true_false_string tfs_flags_recdesired = {
162 "Do query recursively",
163 "Don't do query recursively"
166 static const true_false_string tfs_flags_recavail = {
167 "Server can do recursive queries",
168 "Server can't do recursive queries"
171 static const true_false_string tfs_flags_broadcast = {
172 "Broadcast packet",
173 "Not a broadcast packet"
176 static const true_false_string tfs_nbss_flags_e = {
177 "Add 65536 to length",
178 "Add 0 to length"
181 /* Opcodes */
182 #define OPCODE_QUERY 0 /* standard query */
183 #define OPCODE_REGISTRATION 5 /* registration */
184 #define OPCODE_RELEASE 6 /* release name */
185 #define OPCODE_WACK 7 /* wait for acknowledgement */
186 #define OPCODE_REFRESH 8 /* refresh registration */
187 #define OPCODE_REFRESHALT 9 /* refresh registration (alternate opcode) */
188 #define OPCODE_MHREGISTRATION 15 /* multi-homed registration */
190 static const value_string opcode_vals[] = {
191 { OPCODE_QUERY, "Name query" },
192 { OPCODE_REGISTRATION, "Registration" },
193 { OPCODE_RELEASE, "Release" },
194 { OPCODE_WACK, "Wait for acknowledgment" },
195 { OPCODE_REFRESH, "Refresh" },
196 { OPCODE_REFRESHALT, "Refresh (alternate opcode)" },
197 { OPCODE_MHREGISTRATION, "Multi-homed registration" },
198 { 0, NULL }
201 /* Reply codes */
202 #define RCODE_NOERROR 0
203 #define RCODE_FMTERROR 1
204 #define RCODE_SERVFAIL 2
205 #define RCODE_NAMEERROR 3
206 #define RCODE_NOTIMPL 4
207 #define RCODE_REFUSED 5
208 #define RCODE_ACTIVE 6
209 #define RCODE_CONFLICT 7
211 static const value_string rcode_vals[] = {
212 { RCODE_NOERROR, "No error" },
213 { RCODE_FMTERROR, "Request was invalidly formatted" },
214 { RCODE_SERVFAIL, "Server failure" },
215 { RCODE_NAMEERROR, "Requested name does not exist" },
216 { RCODE_NOTIMPL, "Request is not implemented" },
217 { RCODE_REFUSED, "Request was refused" },
218 { RCODE_ACTIVE, "Name is owned by another node" },
219 { RCODE_CONFLICT, "Name is in conflict" },
220 { 0, NULL }
223 /* Values for the "NB_FLAGS" field of RR data. From RFC 1001 and 1002,
224 * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
225 * packet traces. */
226 #define NB_FLAGS_ONT (3<<(15-2)) /* bits for node type */
227 #define NB_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
228 #define NB_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
229 #define NB_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
230 #define NB_FLAGS_ONT_H_NODE (3<<(15-2)) /* H-mode node */
232 #define NB_FLAGS_G (1<<(15-0)) /* group name */
234 /* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
235 * RR data. From RFC 1001 and 1002; as I remember, the "NAME_FLAGS"
236 * field doesn't include any special values for H-mode nodes, even
237 * though one can register them (if so, perhaps that was done to
238 * avoid surprising clients that don't know about H-mode nodes). */
239 #define NAME_FLAGS_PRM (1<<(15-6)) /* name is permanent node name */
241 #define NAME_FLAGS_ACT (1<<(15-5)) /* name is active */
243 #define NAME_FLAGS_CNF (1<<(15-4)) /* name is in conflict */
245 #define NAME_FLAGS_DRG (1<<(15-3)) /* name is being deregistered */
247 #define NAME_FLAGS_ONT (3<<(15-2)) /* bits for node type */
248 #define NAME_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
249 #define NAME_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
250 #define NAME_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
252 #define NAME_FLAGS_G (1<<(15-0)) /* group name */
254 static const value_string name_flags_ont_vals[] = {
255 { NAME_FLAGS_ONT_B_NODE, "B-node" },
256 { NAME_FLAGS_ONT_P_NODE, "P-node" },
257 { NAME_FLAGS_ONT_M_NODE, "M-node" },
258 { 0, NULL }
261 static const value_string nb_flags_ont_vals[] = {
262 { NB_FLAGS_ONT_B_NODE, "B-node" },
263 { NB_FLAGS_ONT_P_NODE, "P-node" },
264 { NB_FLAGS_ONT_M_NODE, "M-node" },
265 { NB_FLAGS_ONT_H_NODE, "H-node" },
266 { 0, NULL }
269 static const char *
270 nbns_type_name (int type)
272 switch (type) {
273 case T_NB:
274 return "NB";
275 case T_NBSTAT:
276 return "NBSTAT";
279 return "unknown";
282 #define NBNAME_BUF_LEN 128
284 static proto_tree *
285 add_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
286 const char *name, int namelen,
287 const char *type_name, const char *class_description,
288 guint ttl, gushort data_len)
290 proto_tree *rr_tree;
292 rr_tree = proto_item_add_subtree(trr, rr_type);
293 proto_tree_add_text(rr_tree, tvb, offset+1, namelen-1, "Name: %s", name);
294 offset += namelen;
295 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
296 offset += 2;
297 proto_tree_add_text(rr_tree, tvb, offset, 2, "Class: %s", class_description);
298 offset += 2;
299 proto_tree_add_text(rr_tree, tvb, offset, 4, "Time to live: %s",
300 time_secs_to_str(ttl));
301 offset += 4;
302 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
303 return rr_tree;
306 static int
307 get_nbns_name(tvbuff_t *tvb, int offset, int nbns_data_offset,
308 char *name_ret, int name_ret_len, int *name_type_ret)
310 int name_len;
311 const guchar *name;
312 const guchar *nbname;
313 char *nbname_buf;
314 const guchar *pname;
315 char cname, cnbname;
316 int name_type;
317 char *pname_ret;
318 size_t idx = 0;
320 nbname_buf = (char *)wmem_alloc(wmem_packet_scope(), NBNAME_BUF_LEN);
321 nbname = nbname_buf;
322 /* XXX Fix data len */
323 name_len = get_dns_name(tvb, offset, 0, nbns_data_offset, &name);
325 /* OK, now undo the first-level encoding. */
326 pname = &name[0];
327 pname_ret = name_ret;
329 for (;;) {
330 /* Every two characters of the first level-encoded name
331 * turn into one character in the decoded name. */
332 cname = *pname;
333 if (cname == '\0')
334 break; /* no more characters */
335 if (cname == '.')
336 break; /* scope ID follows */
337 if (cname < 'A' || cname > 'Z') {
338 /* Not legal. */
339 nbname = "Illegal NetBIOS name (1st character not between A and Z in first-level encoding)";
340 goto bad;
342 cname -= 'A';
343 cnbname = cname << 4;
344 pname++;
346 cname = *pname;
347 if (cname == '\0' || cname == '.') {
348 /* No more characters in the name - but we're in
349 * the middle of a pair. Not legal. */
350 nbname = "Illegal NetBIOS name (odd number of bytes)";
351 goto bad;
353 if (cname < 'A' || cname > 'Z') {
354 /* Not legal. */
355 nbname = "Illegal NetBIOS name (2nd character not between A and Z in first-level encoding)";
356 goto bad;
358 cname -= 'A';
359 cnbname |= cname;
360 pname++;
362 /* Do we have room to store the character? */
363 if (idx < NETBIOS_NAME_LEN) {
364 /* Yes - store the character. */
365 nbname_buf[idx++] = cnbname;
369 /* NetBIOS names are supposed to be exactly 16 bytes long. */
370 if (idx != NETBIOS_NAME_LEN) {
371 /* It's not. */
372 g_snprintf(nbname_buf, NBNAME_BUF_LEN, "Illegal NetBIOS name (%lu bytes long)",
373 (unsigned long)idx);
374 goto bad;
377 /* This one is; make its name printable. */
378 name_type = process_netbios_name(nbname, name_ret, name_ret_len);
379 pname_ret += MIN(strlen(name_ret), (size_t) name_ret_len);
380 pname_ret += MIN(name_ret_len-(pname_ret-name_ret),
381 g_snprintf(pname_ret, name_ret_len-(gulong)(pname_ret-name_ret), "<%02x>", name_type));
382 if (cname == '.') {
383 /* We have a scope ID, starting at "pname"; append that to
384 * the decoded host name. */
385 g_snprintf(pname_ret, name_ret_len-(gulong)(pname_ret-name_ret), "%s", pname);
387 if (name_type_ret != NULL)
388 *name_type_ret = name_type;
389 return name_len;
391 bad:
392 if (name_type_ret != NULL)
393 *name_type_ret = -1;
394 /* This is only valid because nbname is always assigned an error string
395 * before jumping to bad: Otherwise nbname wouldn't be \0 terminated */
396 g_snprintf(pname_ret, name_ret_len-(gulong)(pname_ret-name_ret), "%s", nbname);
397 return name_len;
401 static int
402 get_nbns_name_type_class(tvbuff_t *tvb, int offset, int nbns_data_offset,
403 char *name_ret, int *name_len_ret, int *name_type_ret,
404 int *type_ret, int *class_ret)
406 int name_len;
407 int type;
408 int rr_class;
410 name_len = get_nbns_name(tvb, offset, nbns_data_offset, name_ret,
411 *name_len_ret, name_type_ret);
412 offset += name_len;
414 type = tvb_get_ntohs(tvb, offset);
415 offset += 2;
417 rr_class = tvb_get_ntohs(tvb, offset);
419 *type_ret = type;
420 *class_ret = rr_class;
421 *name_len_ret = name_len;
423 return name_len + 4;
426 static void
427 add_name_and_type(proto_tree *tree, tvbuff_t *tvb, int offset, int len,
428 const char *tag, const char *name, int name_type)
430 if (name_type != -1) {
431 proto_tree_add_text(tree, tvb, offset, len, "%s: %s (%s)",
432 tag, name, netbios_name_type_descr(name_type));
433 } else {
434 proto_tree_add_text(tree, tvb, offset, len, "%s: %s",
435 tag, name);
439 #define MAX_NAME_LEN (NETBIOS_NAME_LEN - 1)*4 + MAXDNAME + 64
441 static int
442 dissect_nbns_query(tvbuff_t *tvb, int offset, int nbns_data_offset,
443 column_info *cinfo, proto_tree *nbns_tree)
445 int len;
446 char *name;
447 int name_len;
448 int name_type;
449 int type;
450 int dns_class;
451 const char *type_name;
452 int data_offset;
453 int data_start;
454 proto_tree *q_tree;
455 proto_item *tq;
457 name = (char *)wmem_alloc(wmem_packet_scope(), MAX_NAME_LEN);
458 data_start = data_offset = offset;
460 name_len = MAX_NAME_LEN;
461 len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
462 &name_len, &name_type, &type, &dns_class);
463 data_offset += len;
465 type_name = nbns_type_name(type);
467 if (cinfo != NULL)
468 col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
470 if (nbns_tree != NULL) {
471 tq = proto_tree_add_text(nbns_tree, tvb, offset, len,
472 "%s: type %s, class %s", name, type_name,
473 dns_class_name(dns_class));
474 q_tree = proto_item_add_subtree(tq, ett_nbns_qd);
476 add_name_and_type(q_tree, tvb, offset, name_len, "Name", name,
477 name_type);
478 offset += name_len;
480 proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", type_name);
481 offset += 2;
483 proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s",
484 dns_class_name(dns_class));
485 /*offset += 2;*/
488 return data_offset - data_start;
491 static void
492 nbns_add_nbns_flags(column_info *cinfo, proto_tree *nbns_tree, tvbuff_t *tvb, int offset,
493 gushort flags, int is_wack)
495 char *buf;
496 guint16 opcode;
497 proto_tree *field_tree;
498 proto_item *tf;
500 #define MAX_BUF_SIZE (128+1)
502 if (cinfo) {
503 if (flags & F_RESPONSE && !is_wack) {
504 if ((flags & F_RCODE))
505 col_append_fstr(cinfo, COL_INFO, ", %s",
506 val_to_str_const(flags & F_RCODE, rcode_vals,
507 "Unknown error"));
511 if (!nbns_tree)
512 return;
514 buf = (char *)wmem_alloc(wmem_packet_scope(), MAX_BUF_SIZE);
515 opcode = (guint16) ((flags & F_OPCODE) >> OPCODE_SHIFT);
516 g_snprintf(buf, MAX_BUF_SIZE, "%s", val_to_str_const(opcode, opcode_vals, "Unknown operation"));
517 if (flags & F_RESPONSE && !is_wack) {
518 g_strlcat(buf, " response", MAX_BUF_SIZE);
519 g_strlcat(buf, ", ", MAX_BUF_SIZE);
520 g_strlcat(buf, val_to_str_const(flags & F_RCODE, rcode_vals, "Unknown error"), MAX_BUF_SIZE);
521 buf[MAX_BUF_SIZE-1] = '\0';
523 tf = proto_tree_add_uint_format_value(nbns_tree, hf_nbns_flags,
524 tvb, offset, 2, flags, "0x%04x (%s)", flags, buf);
525 field_tree = proto_item_add_subtree(tf, ett_nbns_flags);
526 proto_tree_add_item(field_tree, hf_nbns_flags_response,
527 tvb, offset, 2, ENC_BIG_ENDIAN);
528 proto_tree_add_item(field_tree, hf_nbns_flags_opcode,
529 tvb, offset, 2, ENC_BIG_ENDIAN);
530 if (flags & F_RESPONSE) {
531 proto_tree_add_item(field_tree, hf_nbns_flags_authoritative,
532 tvb, offset, 2, ENC_BIG_ENDIAN);
534 proto_tree_add_item(field_tree, hf_nbns_flags_truncated,
535 tvb, offset, 2, ENC_BIG_ENDIAN);
536 proto_tree_add_item(field_tree, hf_nbns_flags_recdesired,
537 tvb, offset, 2, ENC_BIG_ENDIAN);
538 if (flags & F_RESPONSE) {
539 proto_tree_add_item(field_tree, hf_nbns_flags_recavail,
540 tvb, offset, 2, ENC_BIG_ENDIAN);
542 proto_tree_add_item(field_tree, hf_nbns_flags_broadcast,
543 tvb, offset, 2, ENC_BIG_ENDIAN);
544 if (flags & F_RESPONSE && !is_wack) {
545 proto_tree_add_item(field_tree, hf_nbns_flags_rcode,
546 tvb, offset, 2, ENC_BIG_ENDIAN);
550 static void
551 nbns_add_nb_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset)
553 proto_tree *field_tree;
554 proto_item *tf;
555 gushort flags;
557 if (!rr_tree)
558 return;
560 flags = tvb_get_ntohs(tvb, offset);
561 tf = proto_tree_add_item(rr_tree, hf_nbns_nb_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
562 field_tree = proto_item_add_subtree(tf, ett_nbns_nb_flags);
563 proto_tree_add_item(field_tree, hf_nbns_nb_flags_group, tvb, offset, 2, ENC_BIG_ENDIAN);
564 proto_tree_add_item(field_tree, hf_nbns_nb_flags_ont, tvb, offset, 2, ENC_BIG_ENDIAN);
566 proto_item_append_text(tf, "(%s, %s",
567 val_to_str_const(flags & NB_FLAGS_ONT, nb_flags_ont_vals, "Unknown"),
568 (flags & NB_FLAGS_G) ? "group" : "unique");
571 static void
572 nbns_add_name_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset)
574 proto_item *field_tree;
575 proto_item *tf;
576 gushort flags;
578 if (!rr_tree)
579 return;
581 flags = tvb_get_ntohs(tvb, offset);
582 tf = proto_tree_add_item(rr_tree, hf_nbns_name_flags, tvb, offset, 2, ENC_BIG_ENDIAN);
583 field_tree = proto_item_add_subtree(tf, ett_nbns_name_flags);
584 proto_tree_add_item(field_tree, hf_nbns_name_flags_group, tvb, offset, 2, ENC_BIG_ENDIAN);
585 proto_tree_add_item(field_tree, hf_nbns_name_flags_ont, tvb, offset, 2, ENC_BIG_ENDIAN);
586 proto_tree_add_item(field_tree, hf_nbns_name_flags_drg, tvb, offset, 2, ENC_BIG_ENDIAN);
587 proto_tree_add_item(field_tree, hf_nbns_name_flags_cnf, tvb, offset, 2, ENC_BIG_ENDIAN);
588 proto_tree_add_item(field_tree, hf_nbns_name_flags_act, tvb, offset, 2, ENC_BIG_ENDIAN);
589 proto_tree_add_item(field_tree, hf_nbns_name_flags_prm, tvb, offset, 2, ENC_BIG_ENDIAN);
591 proto_item_append_text(tf, "(%s, %s",
592 val_to_str_const(flags & NAME_FLAGS_ONT, name_flags_ont_vals, "Unknown"),
593 (flags & NAME_FLAGS_G) ? "group" : "unique");
594 if (flags & NAME_FLAGS_DRG)
595 proto_item_append_text(tf, ", being deregistered");
596 if (flags & NAME_FLAGS_CNF)
597 proto_item_append_text(tf, ", in conflict");
598 if (flags & NAME_FLAGS_ACT)
599 proto_item_append_text(tf, ", active");
600 if (flags & NAME_FLAGS_PRM)
601 proto_item_append_text(tf, ", permanent node name");
602 proto_item_append_text(tf, ")");
605 static int
606 dissect_nbns_answer(tvbuff_t *tvb, int offset, int nbns_data_offset,
607 column_info *cinfo, proto_tree *nbns_tree, int opcode)
609 int len;
610 char *name;
611 int name_len;
612 int name_type;
613 int type;
614 int dns_class;
615 const char *class_name;
616 const char *type_name;
617 int cur_offset;
618 guint ttl;
619 gushort data_len;
620 gushort flags;
621 proto_tree *rr_tree = NULL;
622 proto_item *trr;
623 char *name_str;
624 guint num_names;
625 char *nbname;
627 cur_offset = offset;
629 name = (char *)wmem_alloc(wmem_packet_scope(), MAX_NAME_LEN);
630 name_str = (char *)wmem_alloc(wmem_packet_scope(), MAX_NAME_LEN);
631 nbname = (char *)wmem_alloc(wmem_packet_scope(), 16+4+1); /* 4 for [<last char>] */
633 name_len = MAX_NAME_LEN;
634 len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
635 &name_len, &name_type, &type, &dns_class);
636 cur_offset += len;
638 type_name = nbns_type_name(type);
639 class_name = dns_class_name(dns_class);
641 ttl = tvb_get_ntohl(tvb, cur_offset);
642 cur_offset += 4;
644 data_len = tvb_get_ntohs(tvb, cur_offset);
645 cur_offset += 2;
647 /* XXX: This code should be simplified */
648 switch (type) {
649 case T_NB: /* "NB" record */
650 if (cinfo != NULL) {
651 if (opcode != OPCODE_WACK) {
652 col_append_fstr(cinfo, COL_INFO, " %s %s",
653 type_name,
654 tvb_ip_to_str(tvb, cur_offset+2));
658 if (nbns_tree) {
659 trr = proto_tree_add_text(nbns_tree, tvb, offset,
660 (cur_offset - offset) + data_len,
661 "%s: type %s, class %s",
662 name, type_name, class_name);
663 g_strlcat(name, " (", MAX_NAME_LEN);
664 g_strlcat(name, netbios_name_type_descr(name_type), MAX_NAME_LEN);
665 g_strlcat(name, ")", MAX_NAME_LEN);
666 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
667 name_len, type_name, dns_class_name(dns_class), ttl, data_len);
669 while (data_len > 0) {
670 if (opcode == OPCODE_WACK) {
671 /* WACK response. This doesn't contain the
672 * same type of RR data as other T_NB
673 * responses. */
674 if (data_len < 2) {
675 proto_tree_add_text(rr_tree, tvb, cur_offset,
676 data_len, "(incomplete entry)");
677 break;
679 flags = tvb_get_ntohs(tvb, cur_offset);
680 nbns_add_nbns_flags(cinfo, rr_tree, tvb, cur_offset,
681 flags, 1);
682 cur_offset += 2;
683 data_len -= 2;
684 } else {
685 if (data_len < 2) {
686 proto_tree_add_text(rr_tree, tvb, cur_offset,
687 data_len, "(incomplete entry)");
688 break;
690 nbns_add_nb_flags(rr_tree, tvb, cur_offset);
691 cur_offset += 2;
692 data_len -= 2;
694 if (data_len < 4) {
695 proto_tree_add_text(rr_tree, tvb, cur_offset,
696 data_len, "(incomplete entry)");
697 break;
699 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
700 "Addr: %s",
701 tvb_ip_to_str(tvb, cur_offset));
702 cur_offset += 4;
703 data_len -= 4;
706 break;
708 case T_NBSTAT: /* "NBSTAT" record */
709 if (cinfo != NULL)
710 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
712 if (nbns_tree) {
713 trr = proto_tree_add_text(nbns_tree, tvb, offset,
714 (cur_offset - offset) + data_len,
715 "%s: type %s, class %s",
716 name, type_name, class_name);
717 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
718 name_len, type_name, dns_class_name(dns_class), ttl, data_len);
721 if (data_len < 1) {
722 proto_tree_add_text(rr_tree, tvb, cur_offset,
723 data_len, "(incomplete entry)");
724 break;
727 num_names = tvb_get_guint8(tvb, cur_offset);
728 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
729 "Number of names: %u", num_names);
730 cur_offset += 1;
732 while (num_names != 0) {
733 if (data_len < NETBIOS_NAME_LEN) {
734 proto_tree_add_text(rr_tree, tvb, cur_offset,
735 data_len, "(incomplete entry)");
736 goto out;
738 if (rr_tree) {
739 tvb_memcpy(tvb, (guint8 *)nbname, cur_offset,
740 NETBIOS_NAME_LEN);
741 name_type = process_netbios_name(nbname,
742 name_str, name_len);
743 proto_tree_add_text(rr_tree, tvb, cur_offset,
744 NETBIOS_NAME_LEN, "Name: %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_text(rr_tree, tvb, cur_offset,
753 data_len, "(incomplete entry)");
754 goto out;
756 if (rr_tree) {
757 nbns_add_name_flags(rr_tree, tvb, cur_offset);
759 cur_offset += 2;
760 data_len -= 2;
762 num_names--;
765 if (data_len < 6) {
766 proto_tree_add_text(rr_tree, tvb, cur_offset,
767 data_len, "(incomplete entry)");
768 break;
771 if (rr_tree) {
772 proto_tree_add_text(rr_tree, tvb, cur_offset, 6,
773 "Unit ID: %s",
774 tvb_ether_to_str(tvb, cur_offset));
776 cur_offset += 6;
777 data_len -= 6;
779 if (data_len < 1) {
780 proto_tree_add_text(rr_tree, tvb, cur_offset,
781 data_len, "(incomplete entry)");
782 break;
785 if (rr_tree) {
786 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
787 "Jumpers: 0x%x", tvb_get_guint8(tvb, cur_offset));
789 cur_offset += 1;
790 data_len -= 1;
792 if (data_len < 1) {
793 proto_tree_add_text(rr_tree, tvb, cur_offset,
794 data_len, "(incomplete entry)");
795 break;
797 if (rr_tree) {
798 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
799 "Test result: 0x%x", tvb_get_guint8(tvb, cur_offset));
801 cur_offset += 1;
802 data_len -= 1;
804 if (data_len < 2) {
805 proto_tree_add_text(rr_tree, tvb, cur_offset,
806 data_len, "(incomplete entry)");
807 break;
809 if (rr_tree) {
810 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
811 "Version number: 0x%x", tvb_get_ntohs(tvb, cur_offset));
813 cur_offset += 2;
814 data_len -= 2;
816 if (data_len < 2) {
817 proto_tree_add_text(rr_tree, tvb, cur_offset,
818 data_len, "(incomplete entry)");
819 break;
821 if (rr_tree) {
822 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
823 "Period of statistics: 0x%x",
824 tvb_get_ntohs(tvb, cur_offset));
826 cur_offset += 2;
827 data_len -= 2;
829 if (data_len < 2) {
830 proto_tree_add_text(rr_tree, tvb, cur_offset,
831 data_len, "(incomplete entry)");
832 break;
834 if (rr_tree) {
835 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
836 "Number of CRCs: %u", tvb_get_ntohs(tvb, cur_offset));
838 cur_offset += 2;
839 data_len -= 2;
841 if (data_len < 2) {
842 proto_tree_add_text(rr_tree, tvb, cur_offset,
843 data_len, "(incomplete entry)");
844 break;
846 if (rr_tree) {
847 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
848 "Number of alignment errors: %u",
849 tvb_get_ntohs(tvb, cur_offset));
851 cur_offset += 2;
852 data_len -= 2;
854 if (data_len < 2) {
855 proto_tree_add_text(rr_tree, tvb, cur_offset,
856 data_len, "(incomplete entry)");
857 break;
859 if (rr_tree) {
860 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
861 "Number of collisions: %u", tvb_get_ntohs(tvb, cur_offset));
863 cur_offset += 2;
864 data_len -= 2;
866 if (data_len < 2) {
867 proto_tree_add_text(rr_tree, tvb, cur_offset,
868 data_len, "(incomplete entry)");
869 break;
871 if (rr_tree) {
872 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
873 "Number of send aborts: %u", tvb_get_ntohs(tvb, cur_offset));
875 cur_offset += 2;
876 data_len -= 2;
878 if (data_len < 4) {
879 proto_tree_add_text(rr_tree, tvb, cur_offset,
880 data_len, "(incomplete entry)");
881 break;
883 if (rr_tree) {
884 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
885 "Number of good sends: %u", tvb_get_ntohl(tvb, cur_offset));
887 cur_offset += 4;
888 data_len -= 4;
890 if (data_len < 4) {
891 proto_tree_add_text(rr_tree, tvb, cur_offset,
892 data_len, "(incomplete entry)");
893 break;
895 if (rr_tree) {
896 proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
897 "Number of good receives: %u",
898 tvb_get_ntohl(tvb, cur_offset));
900 cur_offset += 4;
901 data_len -= 4;
903 if (data_len < 2) {
904 proto_tree_add_text(rr_tree, tvb, cur_offset,
905 data_len, "(incomplete entry)");
906 break;
908 if (rr_tree) {
909 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
910 "Number of retransmits: %u", tvb_get_ntohs(tvb, cur_offset));
912 cur_offset += 2;
913 data_len -= 2;
915 if (data_len < 2) {
916 proto_tree_add_text(rr_tree, tvb, cur_offset,
917 data_len, "(incomplete entry)");
918 break;
920 if (rr_tree) {
921 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
922 "Number of no resource conditions: %u",
923 tvb_get_ntohs(tvb, cur_offset));
925 cur_offset += 2;
926 data_len -= 2;
928 if (data_len < 2) {
929 proto_tree_add_text(rr_tree, tvb, cur_offset,
930 data_len, "(incomplete entry)");
931 break;
933 if (rr_tree) {
934 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
935 "Number of command blocks: %u",
936 tvb_get_ntohs(tvb, cur_offset));
938 cur_offset += 2;
939 data_len -= 2;
941 if (data_len < 2) {
942 proto_tree_add_text(rr_tree, tvb, cur_offset,
943 data_len, "(incomplete entry)");
944 break;
946 if (rr_tree) {
947 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
948 "Number of pending sessions: %u",
949 tvb_get_ntohs(tvb, cur_offset));
951 cur_offset += 2;
952 data_len -= 2;
954 if (data_len < 2) {
955 proto_tree_add_text(rr_tree, tvb, cur_offset,
956 data_len, "(incomplete entry)");
957 break;
959 if (rr_tree) {
960 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
961 "Max number of pending sessions: %u",
962 tvb_get_ntohs(tvb, cur_offset));
964 cur_offset += 2;
965 data_len -= 2;
967 if (data_len < 2) {
968 proto_tree_add_text(rr_tree, tvb, cur_offset,
969 data_len, "(incomplete entry)");
970 break;
972 if (rr_tree) {
973 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
974 "Max total sessions possible: %u",
975 tvb_get_ntohs(tvb, cur_offset));
977 cur_offset += 2;
978 data_len -= 2;
980 if (data_len < 2) {
981 proto_tree_add_text(rr_tree, tvb, cur_offset,
982 data_len, "(incomplete entry)");
983 break;
985 if (rr_tree) {
986 proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
987 "Session data packet size: %u",
988 tvb_get_ntohs(tvb, cur_offset));
990 cur_offset += 2;
991 /*data_len -= 2;*/
992 out:
993 break;
995 default:
996 if (cinfo != NULL)
997 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
999 if (nbns_tree) {
1000 trr = proto_tree_add_text(nbns_tree, tvb, offset,
1001 (cur_offset - offset) + data_len,
1002 "%s: type %s, class %s",
1003 name, type_name, class_name);
1004 rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
1005 name_len, type_name, dns_class_name(dns_class), ttl, data_len);
1006 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1008 cur_offset += data_len;
1009 break;
1012 return cur_offset - offset;
1015 static int
1016 dissect_query_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
1017 int count, column_info *cinfo, proto_tree *nbns_tree)
1019 int start_off, add_off;
1020 proto_tree *qatree = NULL;
1021 proto_item *ti = NULL;
1023 start_off = cur_off;
1024 if (nbns_tree != NULL) {
1025 ti = proto_tree_add_text(nbns_tree, tvb, start_off, -1, "Queries");
1026 qatree = proto_item_add_subtree(ti, ett_nbns_qry);
1028 while (count-- > 0) {
1029 add_off = dissect_nbns_query(tvb, cur_off, nbns_data_offset,
1030 cinfo, qatree);
1031 cur_off += add_off;
1033 if (ti != NULL)
1034 proto_item_set_len(ti, cur_off - start_off);
1036 return cur_off - start_off;
1039 static int
1040 dissect_answer_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
1041 int count, column_info *cinfo, proto_tree *nbns_tree,
1042 int opcode, const char *name)
1044 int start_off, add_off;
1045 proto_tree *qatree = NULL;
1046 proto_item *ti = NULL;
1048 start_off = cur_off;
1049 if (nbns_tree != NULL) {
1050 ti = proto_tree_add_text(nbns_tree, tvb, start_off, -1, "%s", name);
1051 qatree = proto_item_add_subtree(ti, ett_nbns_ans);
1053 while (count-- > 0) {
1054 add_off = dissect_nbns_answer(tvb, cur_off, nbns_data_offset,
1055 cinfo, qatree, opcode);
1056 cur_off += add_off;
1058 if (ti != NULL)
1059 proto_item_set_len(ti, cur_off - start_off);
1060 return cur_off - start_off;
1063 static void
1064 dissect_nbns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1066 int offset = 0;
1067 int nbns_data_offset;
1068 proto_tree *nbns_tree = NULL;
1069 proto_item *ti;
1070 guint16 id, flags, opcode, quest, ans, auth, add;
1071 int cur_off;
1073 nbns_data_offset = offset;
1075 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBNS");
1076 col_clear(pinfo->cinfo, COL_INFO);
1078 /* To do: check for runts, errs, etc. */
1079 id = tvb_get_ntohs(tvb, offset + NBNS_ID);
1080 flags = tvb_get_ntohs(tvb, offset + NBNS_FLAGS);
1081 opcode = (guint16) ((flags & F_OPCODE) >> OPCODE_SHIFT);
1083 col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s",
1084 val_to_str(opcode, opcode_vals, "Unknown operation (%u)"),
1085 (flags & F_RESPONSE) ? " response" : "");
1087 if (tree) {
1088 ti = proto_tree_add_item(tree, proto_nbns, tvb, offset, -1,
1089 ENC_NA);
1090 nbns_tree = proto_item_add_subtree(ti, ett_nbns);
1092 proto_tree_add_uint(nbns_tree, hf_nbns_transaction_id, tvb,
1093 offset + NBNS_ID, 2, id);
1096 nbns_add_nbns_flags(pinfo->cinfo, nbns_tree, tvb, offset + NBNS_FLAGS,
1097 flags, 0);
1099 quest = tvb_get_ntohs(tvb, offset + NBNS_QUEST);
1100 if (tree) {
1101 proto_tree_add_uint(nbns_tree, hf_nbns_count_questions, tvb,
1102 offset + NBNS_QUEST, 2, quest);
1104 ans = tvb_get_ntohs(tvb, offset + NBNS_ANS);
1105 if (tree) {
1106 proto_tree_add_uint(nbns_tree, hf_nbns_count_answers, tvb,
1107 offset + NBNS_ANS, 2, ans);
1109 auth = tvb_get_ntohs(tvb, offset + NBNS_AUTH);
1110 if (tree) {
1111 proto_tree_add_uint(nbns_tree, hf_nbns_count_auth_rr, tvb,
1112 offset + NBNS_AUTH, 2, auth);
1114 add = tvb_get_ntohs(tvb, offset + NBNS_ADD);
1115 if (tree) {
1116 proto_tree_add_uint(nbns_tree, hf_nbns_count_add_rr, tvb,
1117 offset + NBNS_ADD, 2, add);
1120 cur_off = offset + NBNS_HDRLEN;
1122 if (quest > 0) {
1123 /* If this is a response, don't add information about the
1124 queries to the summary, just add information about the
1125 answers. */
1126 cur_off += dissect_query_records(tvb, cur_off,
1127 nbns_data_offset, quest,
1128 (!(flags & F_RESPONSE) ? pinfo->cinfo : NULL), nbns_tree);
1131 if (ans > 0) {
1132 /* If this is a request, don't add information about the
1133 answers to the summary, just add information about the
1134 queries. */
1135 cur_off += dissect_answer_records(tvb, cur_off,
1136 nbns_data_offset, ans,
1137 ((flags & F_RESPONSE) ? pinfo->cinfo : NULL), nbns_tree,
1138 opcode, "Answers");
1141 /* Don't add information about the authoritative name
1142 servers, or the additional records, to the summary. */
1143 if (auth > 0)
1144 cur_off += dissect_answer_records(tvb, cur_off,
1145 nbns_data_offset,
1146 auth, NULL, nbns_tree, opcode,
1147 "Authoritative nameservers");
1149 if (add > 0)
1150 /*cur_off += */dissect_answer_records(tvb, cur_off,
1151 nbns_data_offset,
1152 add, NULL, nbns_tree, opcode,
1153 "Additional records");
1156 /* NetBIOS datagram packet, from RFC 1002, page 32 */
1157 struct nbdgm_header {
1158 guint8 msg_type;
1159 struct {
1160 guint8 more;
1161 guint8 first;
1162 guint8 node_type;
1163 } flags;
1164 guint16 dgm_id;
1165 guint32 src_ip;
1166 guint16 src_port;
1168 /* For packets with data */
1169 guint16 dgm_length;
1170 guint16 pkt_offset;
1172 /* For error packets */
1173 guint8 error_code;
1177 * NBDS message types.
1179 #define NBDS_DIRECT_UNIQUE 0x10
1180 #define NBDS_DIRECT_GROUP 0x11
1181 #define NBDS_BROADCAST 0x12
1182 #define NBDS_ERROR 0x13
1183 #define NBDS_QUERY_REQUEST 0x14
1184 #define NBDS_POS_QUERY_RESPONSE 0x15
1185 #define NBDS_NEG_QUERY_RESPONSE 0x16
1187 static const value_string nbds_msgtype_vals[] = {
1188 { NBDS_DIRECT_UNIQUE, "Direct_unique datagram" },
1189 { NBDS_DIRECT_GROUP, "Direct_group datagram" },
1190 { NBDS_BROADCAST, "Broadcast datagram" },
1191 { NBDS_ERROR, "Datagram error" },
1192 { NBDS_QUERY_REQUEST, "Datagram query request" },
1193 { NBDS_POS_QUERY_RESPONSE, "Datagram positive query response" },
1194 { NBDS_NEG_QUERY_RESPONSE, "Datagram negative query response" },
1195 { 0, NULL }
1198 static const value_string node_type_vals[] = {
1199 { 0, "B node" },
1200 { 1, "P node" },
1201 { 2, "M node" },
1202 { 3, "NBDD" },
1203 { 0, NULL }
1206 static void
1207 dissect_nbdgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1209 int offset = 0;
1210 proto_tree *nbdgm_tree = NULL;
1211 proto_item *ti = NULL;
1212 struct nbdgm_header header;
1213 int flags;
1214 tvbuff_t *next_tvb;
1216 static const value_string error_codes[] = {
1217 { 0x82, "Destination name not present" },
1218 { 0x83, "Invalid source name format" },
1219 { 0x84, "Invalid destination name format" },
1220 { 0x00, NULL }
1223 char *name;
1224 int name_type;
1225 int len;
1227 name = (char *)wmem_alloc(wmem_packet_scope(), MAX_NAME_LEN);
1229 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBDS");
1230 col_clear(pinfo->cinfo, COL_INFO);
1232 header.msg_type = tvb_get_guint8(tvb, offset);
1234 flags = tvb_get_guint8(tvb, offset+1);
1235 header.flags.more = flags & 1;
1236 header.flags.first = (flags & 2) >> 1;
1237 header.flags.node_type = (flags & 12) >> 2;
1239 header.dgm_id = tvb_get_ntohs(tvb, offset+2);
1240 header.src_ip = tvb_get_ipv4( tvb, offset+4);
1241 header.src_port = tvb_get_ntohs(tvb, offset+8);
1243 /* avoid gcc warnings */
1244 header.dgm_length = 0;
1245 header.pkt_offset = 0;
1246 header.error_code = 0;
1247 switch (header.msg_type) {
1249 case NBDS_DIRECT_UNIQUE:
1250 case NBDS_DIRECT_GROUP:
1251 case NBDS_BROADCAST:
1252 header.dgm_length = tvb_get_ntohs(tvb, offset+10);
1253 header.pkt_offset = tvb_get_ntohs(tvb, offset+12);
1254 break;
1256 case NBDS_ERROR:
1257 header.error_code = tvb_get_guint8(tvb, offset+10);
1258 break;
1261 col_add_str(pinfo->cinfo, COL_INFO,
1262 val_to_str(header.msg_type, nbds_msgtype_vals,
1263 "Unknown message type (0x%02X)"));
1265 if (tree) {
1266 ti = proto_tree_add_item(tree, proto_nbdgm, tvb, offset, -1,
1267 ENC_NA);
1268 nbdgm_tree = proto_item_add_subtree(ti, ett_nbdgm);
1270 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_type, tvb,
1271 offset, 1,
1272 header.msg_type);
1273 proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_fragment, tvb,
1274 offset+1, 1,
1275 header.flags.more);
1276 proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_first, tvb,
1277 offset+1, 1,
1278 header.flags.first);
1279 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_node_type, tvb,
1280 offset+1, 1,
1281 header.flags.node_type);
1283 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_datagram_id, tvb,
1284 offset+2, 2, header.dgm_id);
1285 proto_tree_add_ipv4(nbdgm_tree, hf_nbdgm_src_ip, tvb,
1286 offset+4, 4, header.src_ip);
1287 proto_tree_add_uint(nbdgm_tree, hf_nbdgm_src_port, tvb,
1288 offset+8, 2, header.src_port);
1292 offset += 10;
1294 switch (header.msg_type) {
1296 case NBDS_DIRECT_UNIQUE:
1297 case NBDS_DIRECT_GROUP:
1298 case NBDS_BROADCAST:
1299 if (tree) {
1300 proto_tree_add_text(nbdgm_tree, tvb, offset, 2,
1301 "Datagram length: %d bytes", header.dgm_length);
1302 proto_tree_add_text(nbdgm_tree, tvb, offset+2, 2,
1303 "Packet offset: %d bytes", header.pkt_offset);
1306 offset += 4;
1308 /* Source name */
1309 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1311 if (tree) {
1312 add_name_and_type(nbdgm_tree, tvb, offset, len,
1313 "Source name", name, name_type);
1315 offset += len;
1317 /* Destination name */
1318 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1320 if (tree) {
1321 add_name_and_type(nbdgm_tree, tvb, offset, len,
1322 "Destination name", name, name_type);
1324 offset += len;
1327 * Here we can pass the packet off to the next protocol.
1328 * Set the length of our top-level tree item to include
1329 * only our stuff.
1331 * XXX - take the datagram length into account?
1333 if (ti != NULL)
1334 proto_item_set_len(ti, offset);
1335 next_tvb = tvb_new_subset_remaining(tvb, offset);
1336 dissect_netbios_payload(next_tvb, pinfo, tree);
1337 break;
1339 case NBDS_ERROR:
1340 if (tree) {
1341 proto_tree_add_text(nbdgm_tree, tvb, offset, 1, "Error code: %s",
1342 val_to_str(header.error_code, error_codes, "Unknown (0x%x)"));
1344 offset += 1;
1345 if (ti != NULL)
1346 proto_item_set_len(ti, offset);
1347 break;
1349 case NBDS_QUERY_REQUEST:
1350 case NBDS_POS_QUERY_RESPONSE:
1351 case NBDS_NEG_QUERY_RESPONSE:
1352 /* Destination name */
1353 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1355 if (tree) {
1356 add_name_and_type(nbdgm_tree, tvb, offset, len,
1357 "Destination name", name, name_type);
1359 offset += len;
1360 if (ti != NULL)
1361 proto_item_set_len(ti, offset);
1362 break;
1367 * NetBIOS Session Service message types (RFC 1002).
1369 #define SESSION_MESSAGE 0x00
1370 #define SESSION_REQUEST 0x81
1371 #define POSITIVE_SESSION_RESPONSE 0x82
1372 #define NEGATIVE_SESSION_RESPONSE 0x83
1373 #define RETARGET_SESSION_RESPONSE 0x84
1374 #define SESSION_KEEP_ALIVE 0x85
1376 static const value_string message_types[] = {
1377 { SESSION_MESSAGE, "Session message" },
1378 { SESSION_REQUEST, "Session request" },
1379 { POSITIVE_SESSION_RESPONSE, "Positive session response" },
1380 { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
1381 { RETARGET_SESSION_RESPONSE, "Retarget session response" },
1382 { SESSION_KEEP_ALIVE, "Session keep-alive" },
1383 { 0x0, NULL }
1387 * NetBIOS Session Service flags.
1389 #define NBSS_FLAGS_E 0x1
1391 static const value_string error_codes[] = {
1392 { 0x80, "Not listening on called name" },
1393 { 0x81, "Not listening for called name" },
1394 { 0x82, "Called name not present" },
1395 { 0x83, "Called name present, but insufficient resources" },
1396 { 0x8F, "Unspecified error" },
1397 { 0x0, NULL }
1401 * Dissect a single NBSS packet (there may be more than one in a given
1402 * TCP segment).
1404 * [ Hmmm, in my experience, I have never seen more than one NBSS in a
1405 * single segment, since they mostly contain SMBs which are essentially
1406 * a request response type protocol (RJS). ]
1408 * [ However, under heavy load with many requests multiplexed on one
1409 * session it is not unusual to see multiple requests in one TCP
1410 * segment. Unfortunately, in this case a single session message is
1411 * frequently split over multiple segments, which frustrates decoding
1412 * (MMM). ]
1414 static int
1415 dissect_nbss_packet(tvbuff_t *tvb, int offset, packet_info *pinfo,
1416 proto_tree *tree, int is_cifs)
1418 proto_tree *nbss_tree = NULL;
1419 proto_item *ti = NULL;
1420 proto_tree *field_tree;
1421 proto_item *tf;
1422 guint8 msg_type;
1423 guint8 flags;
1424 volatile int length;
1425 int length_remaining;
1426 int len;
1427 char *name;
1428 int name_type;
1429 gint reported_len;
1430 tvbuff_t *next_tvb;
1431 const char *saved_proto;
1432 void *pd_save;
1434 name = (char *)wmem_alloc(wmem_packet_scope(), MAX_NAME_LEN);
1436 /* Desegmentation */
1437 length_remaining = tvb_length_remaining(tvb, offset);
1440 * Can we do reassembly?
1442 if (nbss_desegment && pinfo->can_desegment) {
1444 * Yes - is the NBSS header split across segment boundaries?
1446 if (length_remaining < 4) {
1448 * Yes. Tell our caller how many more bytes
1449 * we need.
1451 return -(4 - length_remaining);
1456 * Get the length of the NBSS message.
1458 if (is_cifs) {
1459 flags = 0;
1460 length = tvb_get_ntoh24(tvb, offset + 1);
1461 } else {
1462 flags = tvb_get_guint8(tvb, offset + 1);
1463 length = tvb_get_ntohs(tvb, offset + 2);
1464 if (flags & NBSS_FLAGS_E)
1465 length += 65536;
1468 /* give a hint to TCP where the next PDU starts
1469 * so that it can attempt to find it in case it starts
1470 * somewhere in the middle of a segment.
1472 if(!pinfo->fd->flags.visited){
1473 /* 'Only' SMB is transported ontop of this so make sure
1474 * there is an SMB header there ...
1476 if( ((length+4)>tvb_reported_length_remaining(tvb, offset))
1477 &&(tvb_length_remaining(tvb, offset) >= 8)
1478 &&(tvb_get_guint8(tvb,offset+5) == 'S')
1479 &&(tvb_get_guint8(tvb,offset+6) == 'M')
1480 &&(tvb_get_guint8(tvb,offset+7) == 'B') ){
1481 pinfo->want_pdu_tracking = 2;
1482 pinfo->bytes_until_next_pdu = (length+4)-tvb_reported_length_remaining(tvb, offset);
1487 * Can we do reassembly?
1489 if (nbss_desegment && pinfo->can_desegment) {
1491 * Yes - is the NBSS message split across segment boundaries?
1493 if (length_remaining < length + 4) {
1495 * Yes. Tell our caller how many more bytes
1496 * we need.
1498 return -((length + 4) - length_remaining);
1502 msg_type = tvb_get_guint8(tvb, offset);
1504 ti = proto_tree_add_item(tree, proto_nbss, tvb, offset, length + 4, ENC_NA);
1505 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1507 proto_tree_add_item(nbss_tree, hf_nbss_type, tvb, offset, 1, ENC_NA);
1509 offset += 1;
1511 if (is_cifs) {
1512 proto_tree_add_item(nbss_tree, hf_nbss_cifs_length, tvb, offset, 3, ENC_BIG_ENDIAN);
1513 offset += 3;
1514 } else {
1515 if (tree) {
1516 tf = proto_tree_add_uint(nbss_tree, hf_nbss_flags, tvb, offset, 1, flags);
1517 field_tree = proto_item_add_subtree(tf, ett_nbss_flags);
1518 proto_tree_add_item(field_tree, hf_nbss_flags_e, tvb, offset, 1, ENC_BIG_ENDIAN);
1520 offset += 1;
1522 proto_tree_add_uint(nbss_tree, hf_nbss_length, tvb, offset, 2, length);
1524 offset += 2;
1527 switch (msg_type) {
1529 case SESSION_REQUEST:
1530 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1531 if (tree)
1532 add_name_and_type(nbss_tree, tvb, offset, len,
1533 "Called name", name, name_type);
1534 offset += len;
1536 col_append_fstr(pinfo->cinfo, COL_INFO, ", to %s ", name);
1538 len = get_nbns_name(tvb, offset, offset, name, MAX_NAME_LEN, &name_type);
1540 if (tree)
1541 add_name_and_type(nbss_tree, tvb, offset, len,
1542 "Calling name", name, name_type);
1544 col_append_fstr(pinfo->cinfo, COL_INFO, "from %s", name);
1546 break;
1548 case NEGATIVE_SESSION_RESPONSE:
1549 if (tree)
1550 proto_tree_add_text(nbss_tree, tvb, offset, 1,
1551 "Error code: %s",
1552 val_to_str(tvb_get_guint8(tvb, offset),
1553 error_codes, "Unknown (%x)"));
1555 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1556 val_to_str(tvb_get_guint8(tvb, offset),
1557 error_codes, "Unknown (%x)"));
1559 break;
1561 case RETARGET_SESSION_RESPONSE:
1562 if (tree)
1563 proto_tree_add_text(nbss_tree, tvb, offset, 4,
1564 "Retarget IP address: %s",
1565 tvb_ip_to_str(tvb, offset));
1567 offset += 4;
1569 if (tree)
1570 proto_tree_add_text(nbss_tree, tvb, offset, 2,
1571 "Retarget port: %u",
1572 tvb_get_ntohs(tvb, offset));
1574 break;
1576 case SESSION_MESSAGE:
1578 * Here we can pass the message off to the next protocol.
1579 * Set the length of our top-level tree item to include
1580 * only our stuff.
1582 len = tvb_length_remaining(tvb, offset);
1583 reported_len = tvb_reported_length_remaining(tvb, offset);
1584 if (len > length)
1585 len = length;
1586 if (reported_len > length)
1587 reported_len = length;
1589 next_tvb = tvb_new_subset(tvb, offset, len, reported_len);
1592 * Dissect the message.
1594 * If it gets an error that means there's no point in
1595 * dissecting any more PDUs, rethrow the exception in
1596 * question.
1598 * If it gets any other error, report it and continue, as that
1599 * means that PDU got an error, but that doesn't mean we should
1600 * stop dissecting PDUs within this frame or chunk of reassembled
1601 * data.
1603 saved_proto = pinfo->current_proto;
1604 pd_save = pinfo->private_data;
1605 TRY {
1606 dissect_netbios_payload(next_tvb, pinfo, tree);
1608 CATCH_NONFATAL_ERRORS {
1609 /* Restore the private_data structure in case one of the
1610 * called dissectors modified it (and, due to the exception,
1611 * was unable to restore it).
1613 pinfo->private_data = pd_save;
1614 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1615 pinfo->current_proto = saved_proto;
1617 ENDTRY;
1618 break;
1621 return length + 4;
1624 static int
1625 dissect_continuation_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1627 proto_tree *nbss_tree;
1628 proto_item *ti;
1631 * It looks like a continuation.
1633 col_set_str(pinfo->cinfo, COL_INFO, "NBSS Continuation Message");
1635 if (tree) {
1636 ti = proto_tree_add_item(tree, proto_nbss, tvb, 0, -1, ENC_NA);
1637 nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1638 proto_tree_add_text(nbss_tree, tvb, 0, -1, "Continuation data");
1641 return tvb_length(tvb);
1644 static int
1645 dissect_nbss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1647 struct tcpinfo *tcpinfo = (struct tcpinfo *)data;
1648 int offset = 0;
1649 int max_data;
1650 guint8 msg_type;
1651 guint8 flags;
1652 guint32 length;
1653 int len;
1654 gboolean is_cifs;
1656 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBSS");
1657 col_clear(pinfo->cinfo, COL_INFO);
1659 max_data = tvb_length(tvb);
1661 msg_type = tvb_get_guint8(tvb, offset);
1663 if (pinfo->match_uint == TCP_PORT_CIFS) {
1665 * Windows 2000 CIFS clients can dispense completely
1666 * with the NETBIOS encapsulation and directly use CIFS
1667 * over TCP. As would be expected, the framing is
1668 * identical, except that the length is 24 bits instead
1669 * of 17. The only message types used are
1670 * SESSION_MESSAGE and SESSION_KEEP_ALIVE.
1672 is_cifs = TRUE;
1673 } else {
1674 is_cifs = FALSE;
1678 * This might be a continuation of an earlier message.
1679 * (Yes, that might be true even if we're doing TCP reassembly,
1680 * as the first TCP segment in the capture might start in the
1681 * middle of an NBNS message.)
1685 * If this isn't reassembled data, check to see whether it
1686 * looks like a continuation of a message.
1687 * (If it is reassembled data, it shouldn't be a continuation,
1688 * as reassembly should've gathered the continuations together
1689 * into a message.)
1691 if (!tcpinfo->is_reassembled) {
1692 if (max_data < 4) {
1694 * Not enough data for an NBSS header; assume
1695 * it's a continuation of a message.
1697 * XXX - if there's not enough data, we should
1698 * attempt to reassemble the data, if the first byte
1699 * is a valid message type.
1701 return dissect_continuation_packet(tvb, pinfo, tree);
1705 * The larged size in for non-SMB NBSS traffic is
1706 * 17 bits (0x1FFFF).
1708 * The SMB1 unix extensions and the SMB2 multi credit
1709 * feature allow more than 17 bits (0x1FFFF), they allow
1710 * 24 bits (0xFFFFFF).
1712 * So if it is a SESSION_MESSAGE and SMB1 or SMB2
1713 * mark it as is_cifs.
1715 if (tvb_length_remaining(tvb, offset) >= 8
1716 && tvb_get_guint8(tvb,offset+0) == SESSION_MESSAGE
1717 && tvb_get_guint8(tvb,offset+5) == 'S'
1718 && tvb_get_guint8(tvb,offset+6) == 'M'
1719 && tvb_get_guint8(tvb,offset+7) == 'B') {
1720 is_cifs = TRUE;
1721 } else {
1722 is_cifs = FALSE;
1726 * We have enough data for an NBSS header.
1727 * Get the flags and length of the message,
1728 * and see if they're sane.
1730 if (is_cifs) {
1731 flags = 0;
1732 length = tvb_get_ntoh24(tvb, offset + 1);
1733 } else {
1734 flags = tvb_get_guint8(tvb, offset + 1);
1735 length = tvb_get_ntohs(tvb, offset + 2);
1736 if (flags & NBSS_FLAGS_E)
1737 length += 0x10000;
1739 if ((flags & (~NBSS_FLAGS_E)) != 0) {
1741 * A bogus flag was set; assume it's a continuation.
1743 return dissect_continuation_packet(tvb, pinfo, tree);
1746 switch (msg_type) {
1748 case SESSION_MESSAGE:
1750 * This is variable-length.
1751 * All we know is that it shouldn't be zero.
1752 * (XXX - can we get zero-length messages?
1753 * Not with SMB, but perhaps other NetBIOS-based
1754 * protocols have them.)
1756 if (length == 0)
1757 return dissect_continuation_packet(tvb, pinfo, tree);
1759 break;
1761 case SESSION_REQUEST:
1763 * This is variable-length.
1764 * The names are DNS-encoded 32-byte values;
1765 * we need at least 2 bytes (one for each name;
1766 * actually, we should have more for the first
1767 * name, as there's no name preceding it so
1768 * there should be no compression), and we
1769 * shouldn't have more than 128 bytes (actually,
1770 * we shouldn't have that many).
1772 * XXX - actually, Mac OS X 10.1 (yes, that's
1773 * redundant, but that's what Apple calls it,
1774 * not Mac OS X.1) puts names longer than 16
1775 * characters into session request messages,
1776 * so we can have more than 32 bytes of
1777 * name value, so we can have more than 128
1778 * bytes of data.
1780 if (length < 2 || length > 256)
1781 return dissect_continuation_packet(tvb, pinfo, tree);
1782 break;
1784 case POSITIVE_SESSION_RESPONSE:
1786 * This has no data, so the length must be zero.
1788 if (length != 0)
1789 return dissect_continuation_packet(tvb, pinfo, tree);
1790 break;
1792 case NEGATIVE_SESSION_RESPONSE:
1794 * This has 1 byte of data.
1796 if (length != 1)
1797 return dissect_continuation_packet(tvb, pinfo, tree);
1798 break;
1800 case RETARGET_SESSION_RESPONSE:
1802 * This has 6 bytes of data.
1804 if (length != 6)
1805 return dissect_continuation_packet(tvb, pinfo, tree);
1806 break;
1808 case SESSION_KEEP_ALIVE:
1810 * This has no data, so the length must be zero.
1812 if (length != 0)
1813 return dissect_continuation_packet(tvb, pinfo, tree);
1814 break;
1816 default:
1818 * Unknown message type; assume it's a continuation.
1820 return dissect_continuation_packet(tvb, pinfo, tree);
1824 col_add_str(pinfo->cinfo, COL_INFO,
1825 val_to_str(msg_type, message_types, "Unknown (%02x)"));
1827 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1828 len = dissect_nbss_packet(tvb, offset, pinfo, tree, is_cifs);
1829 if (len < 0) {
1831 * We need more data to dissect this, and
1832 * desegmentation is enabled. "-len" is the
1833 * number of additional bytes of data we need.
1835 * Tell the TCP dissector where the data for this
1836 * message starts in the data it handed us, and
1837 * how many more bytes we need, and return.
1839 pinfo->desegment_offset = offset;
1840 pinfo->desegment_len = -len;
1841 return tvb_length(tvb);
1843 offset += len;
1846 return tvb_length(tvb);
1849 void
1850 proto_register_nbt(void)
1853 static hf_register_info hf_nbns[] = {
1854 { &hf_nbns_flags,
1855 { "Flags", "nbns.flags",
1856 FT_UINT16, BASE_HEX, NULL, 0x0,
1857 NULL, HFILL }},
1858 { &hf_nbns_flags_response,
1859 { "Response", "nbns.flags.response",
1860 FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
1861 "Is the message a response?", HFILL }},
1862 { &hf_nbns_flags_opcode,
1863 { "Opcode", "nbns.flags.opcode",
1864 FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
1865 "Operation code", HFILL }},
1866 { &hf_nbns_flags_authoritative,
1867 { "Authoritative", "nbns.flags.authoritative",
1868 FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
1869 "Is the server is an authority for the domain?", HFILL }},
1870 { &hf_nbns_flags_truncated,
1871 { "Truncated", "nbns.flags.truncated",
1872 FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
1873 "Is the message truncated?", HFILL }},
1874 { &hf_nbns_flags_recdesired,
1875 { "Recursion desired", "nbns.flags.recdesired",
1876 FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
1877 "Do query recursively?", HFILL }},
1878 { &hf_nbns_flags_recavail,
1879 { "Recursion available", "nbns.flags.recavail",
1880 FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
1881 "Can the server do recursive queries?", HFILL }},
1882 { &hf_nbns_flags_broadcast,
1883 { "Broadcast", "nbns.flags.broadcast",
1884 FT_BOOLEAN, 16, TFS(&tfs_flags_broadcast), F_BROADCAST,
1885 "Is this a broadcast packet?", HFILL }},
1886 { &hf_nbns_flags_rcode,
1887 { "Reply code", "nbns.flags.rcode",
1888 FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
1889 NULL, HFILL }},
1890 { &hf_nbns_transaction_id,
1891 { "Transaction ID", "nbns.id",
1892 FT_UINT16, BASE_HEX, NULL, 0x0,
1893 "Identification of transaction", HFILL }},
1894 { &hf_nbns_count_questions,
1895 { "Questions", "nbns.count.queries",
1896 FT_UINT16, BASE_DEC, NULL, 0x0,
1897 "Number of queries in packet", HFILL }},
1898 { &hf_nbns_count_answers,
1899 { "Answer RRs", "nbns.count.answers",
1900 FT_UINT16, BASE_DEC, NULL, 0x0,
1901 "Number of answers in packet", HFILL }},
1902 { &hf_nbns_count_auth_rr,
1903 { "Authority RRs", "nbns.count.auth_rr",
1904 FT_UINT16, BASE_DEC, NULL, 0x0,
1905 "Number of authoritative records in packet", HFILL }},
1906 { &hf_nbns_count_add_rr,
1907 { "Additional RRs", "nbns.count.add_rr",
1908 FT_UINT16, BASE_DEC, NULL, 0x0,
1909 "Number of additional records in packet", HFILL }},
1910 { &hf_nbns_name_flags,
1911 { "Name flags", "nbns.name_flags",
1912 FT_UINT16, BASE_HEX, NULL, 0x0,
1913 NULL, HFILL }},
1914 { &hf_nbns_name_flags_group,
1915 { "Name type", "nbns.name_flags.group",
1916 FT_BOOLEAN, 16, TFS(&tfs_group_unique_name), NAME_FLAGS_G,
1917 NULL, HFILL }},
1918 { &hf_nbns_name_flags_ont,
1919 { "ONT", "nbns.name_flags.ont",
1920 FT_UINT16, BASE_DEC, VALS(name_flags_ont_vals), NAME_FLAGS_ONT,
1921 NULL, HFILL }},
1922 { &hf_nbns_name_flags_drg,
1923 { "Name is being deregistered", "nbns.name_flags.drg",
1924 FT_BOOLEAN, 16, TFS(&tfs_yes_no), NAME_FLAGS_DRG,
1925 NULL, HFILL }},
1926 { &hf_nbns_name_flags_cnf,
1927 { "Name is in conflict", "nbns.name_flags.cnf",
1928 FT_BOOLEAN, 16, TFS(&tfs_yes_no), NAME_FLAGS_CNF,
1929 NULL, HFILL }},
1930 { &hf_nbns_name_flags_act,
1931 { "Name is active", "nbns.name_flags.act",
1932 FT_BOOLEAN, 16, TFS(&tfs_yes_no), NAME_FLAGS_ACT,
1933 NULL, HFILL }},
1934 { &hf_nbns_name_flags_prm,
1935 { "Permanent node name", "nbns.name_flags.prm",
1936 FT_BOOLEAN, 16, TFS(&tfs_yes_no), NAME_FLAGS_PRM,
1937 NULL, HFILL }},
1938 { &hf_nbns_nb_flags,
1939 { "Name flags", "nbns.nb_flags",
1940 FT_UINT16, BASE_HEX, NULL, 0x0,
1941 NULL, HFILL }},
1942 { &hf_nbns_nb_flags_group,
1943 { "Name type", "nbns.nb_flags.group",
1944 FT_BOOLEAN, 16, TFS(&tfs_group_unique_name), NB_FLAGS_G,
1945 NULL, HFILL }},
1946 { &hf_nbns_nb_flags_ont,
1947 { "ONT", "nbns.nb_flags.ont",
1948 FT_UINT16, BASE_DEC, VALS(nb_flags_ont_vals), NB_FLAGS_ONT,
1949 NULL, HFILL }},
1952 static hf_register_info hf_nbdgm[] = {
1953 { &hf_nbdgm_type,
1954 { "Message Type", "nbdgm.type",
1955 FT_UINT8, BASE_DEC, VALS(nbds_msgtype_vals), 0x0,
1956 "NBDGM message type", HFILL }},
1957 { &hf_nbdgm_fragment,
1958 { "More fragments follow", "nbdgm.next",
1959 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
1960 "TRUE if more fragments follow", HFILL }},
1961 { &hf_nbdgm_first,
1962 { "This is first fragment", "nbdgm.first",
1963 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0,
1964 "TRUE if first fragment", HFILL }},
1965 { &hf_nbdgm_node_type,
1966 { "Node Type", "nbdgm.node_type",
1967 FT_UINT8, BASE_DEC, VALS(node_type_vals), 0x0,
1968 NULL, HFILL }},
1969 { &hf_nbdgm_datagram_id,
1970 { "Datagram ID", "nbdgm.dgram_id",
1971 FT_UINT16, BASE_HEX, NULL, 0x0,
1972 "Datagram identifier", HFILL }},
1973 { &hf_nbdgm_src_ip,
1974 { "Source IP", "nbdgm.src.ip",
1975 FT_IPv4, BASE_NONE, NULL, 0x0,
1976 "Source IPv4 address", HFILL }},
1977 { &hf_nbdgm_src_port,
1978 { "Source Port", "nbdgm.src.port",
1979 FT_UINT16, BASE_DEC, NULL, 0x0,
1980 NULL, HFILL }}
1983 static hf_register_info hf_nbss[] = {
1984 { &hf_nbss_type,
1985 { "Message Type", "nbss.type",
1986 FT_UINT8, BASE_HEX, VALS(message_types), 0x0,
1987 "NBSS message type", HFILL }},
1988 { &hf_nbss_flags,
1989 { "Flags", "nbss.flags",
1990 FT_UINT8, BASE_HEX, NULL, 0x0,
1991 "NBSS message flags", HFILL }},
1992 { &hf_nbss_flags_e,
1993 { "Extend", "nbss.flags.e",
1994 FT_BOOLEAN, 8, TFS(&tfs_nbss_flags_e), NBSS_FLAGS_E,
1995 NULL, HFILL }},
1996 { &hf_nbss_length,
1997 { "Length", "nbss.length",
1998 FT_UINT16, BASE_DEC, NULL, 0x0,
1999 "Length of trailer (payload) following this field in bytes", HFILL }},
2000 { &hf_nbss_cifs_length,
2001 { "Length", "nbss.length",
2002 FT_UINT24, BASE_DEC, NULL, 0x0,
2003 "Length trailer (payload) following this field in bytes", HFILL }}
2005 static gint *ett[] = {
2006 &ett_nbns,
2007 &ett_nbns_qd,
2008 &ett_nbns_flags,
2009 &ett_nbns_nb_flags,
2010 &ett_nbns_name_flags,
2011 &ett_nbns_rr,
2012 &ett_nbns_qry,
2013 &ett_nbns_ans,
2014 &ett_nbdgm,
2015 &ett_nbss,
2016 &ett_nbss_flags,
2018 module_t *nbss_module;
2020 proto_nbns = proto_register_protocol("NetBIOS Name Service", "NBNS", "nbns");
2021 proto_register_field_array(proto_nbns, hf_nbns, array_length(hf_nbns));
2023 proto_nbdgm = proto_register_protocol("NetBIOS Datagram Service",
2024 "NBDS", "nbdgm");
2025 proto_register_field_array(proto_nbdgm, hf_nbdgm, array_length(hf_nbdgm));
2027 proto_nbss = proto_register_protocol("NetBIOS Session Service",
2028 "NBSS", "nbss");
2029 proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));
2031 proto_register_subtree_array(ett, array_length(ett));
2033 nbss_module = prefs_register_protocol(proto_nbss, NULL);
2034 prefs_register_bool_preference(nbss_module, "desegment_nbss_commands",
2035 "Reassemble NBSS packets spanning multiple TCP segments",
2036 "Whether the NBSS dissector should reassemble packets spanning multiple TCP segments."
2037 " To use this option, you must also enable"
2038 " \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2039 &nbss_desegment);
2042 void
2043 proto_reg_handoff_nbt(void)
2045 dissector_handle_t nbns_handle, nbdgm_handle, nbss_handle;
2047 nbns_handle = create_dissector_handle(dissect_nbns, proto_nbns);
2048 dissector_add_uint("udp.port", UDP_PORT_NBNS, nbns_handle);
2050 nbdgm_handle = create_dissector_handle(dissect_nbdgm, proto_nbdgm);
2051 dissector_add_uint("udp.port", UDP_PORT_NBDGM, nbdgm_handle);
2053 nbss_handle = new_create_dissector_handle(dissect_nbss, proto_nbss);
2054 dissector_add_uint("tcp.port", TCP_PORT_NBSS, nbss_handle);
2055 dissector_add_uint("tcp.port", TCP_PORT_CIFS, nbss_handle);