2 * Routines for NetBIOS protocol packet disassembly
3 * Jeff Foster <jfoste@woodward.com>
4 * Copyright 1999 Jeffrey C. Foster
6 * derived from the packet-nbns.c
8 * $Id: packet-netbios.c,v 1.28 2001/01/03 06:55:30 guy Exp $
10 * Ethereal - Network traffic analyzer
11 * By Gerald Combs <gerald@zing.org>
12 * Copyright 1998 Gerald Combs
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
46 #include "packet-netbios.h"
47 #include "packet-smb.h"
49 /* Netbios command numbers */
50 #define NB_ADD_GROUP 0x00
51 #define NB_ADD_NAME 0x01
52 #define NB_NAME_IN_CONFLICT 0x02
53 #define NB_STATUS_QUERY 0x03
54 #define NB_TERMINATE_TRACE_R 0x07
55 #define NB_DATAGRAM 0x08
56 #define NB_DATAGRAM_BCAST 0x09
57 #define NB_NAME_QUERY 0x0a
58 #define NB_ADD_NAME_RESP 0x0d
59 #define NB_NAME_RESP 0x0e
60 #define NB_STATUS_RESP 0x0f
61 #define NB_TERMINATE_TRACE_LR 0x13
62 #define NB_DATA_ACK 0x14
63 #define NB_DATA_FIRST_MIDDLE 0x15
64 #define NB_DATA_ONLY_LAST 0x16
65 #define NB_SESSION_CONFIRM 0x17
66 #define NB_SESSION_END 0x18
67 #define NB_SESSION_INIT 0x19
68 #define NB_NO_RECEIVE 0x1a
69 #define NB_RECEIVE_OUTSTANDING 0x1b
70 #define NB_RECEIVE_CONTINUE 0x1c
71 #define NB_KEEP_ALIVE 0x1f
73 /* Offsets of fields in the NetBIOS header. */
75 #define NB_DELIMITER 2
81 #define NB_CALL_NAME_TYPE 7
82 #define NB_XMIT_CORL 8
83 #define NB_RESP_CORL 10
85 #define NB_LOCAL_SES 13
86 #define NB_RECVER_NAME 12
87 #define NB_SENDER_NAME 28
90 static int proto_netbios = -1;
91 static int hf_netb_cmd = -1;
92 static int hf_netb_hdr_len = -1;
93 static int hf_netb_xmit_corrl = -1;
94 static int hf_netb_resp_corrl = -1;
95 static int hf_netb_call_name_type = -1;
96 static int hf_netb_ack = -1;
97 static int hf_netb_ack_with_data = -1;
98 static int hf_netb_ack_expected = -1;
99 static int hf_netb_recv_cont_req = -1;
100 static int hf_netb_send_no_ack = -1;
101 static int hf_netb_version = -1;
102 static int hf_netb_largest_frame = -1;
103 static int hf_netb_name = -1;
104 static int hf_netb_name_type = -1;
105 static int hf_netb_local_ses_no = -1;
106 static int hf_netb_remote_ses_no = -1;
107 static int hf_netb_data2 = -1;
109 static gint ett_netb = -1;
110 static gint ett_netb_name = -1;
111 static gint ett_netb_flags = -1;
112 static gint ett_netb_status = -1;
114 /* The strings for the station type, used by get_netbios_name function;
115 many of them came from the file "NetBIOS.txt" in the Zip archive at
117 http://www.net3group.com/ftp/browser.zip
120 static const value_string name_type_vals[] = {
121 {0x00, "Workstation/Redirector"},
123 {0x02, "Workstation/Redirector"},
124 /* not sure what 0x02 is, I'm seeing alot of them however */
125 /* i'm seeing them with workstation/redirection host
127 {0x03, "Messenger service/Main name"},
128 {0x05, "Forwarded name"},
129 {0x06, "RAS Server service"},
130 {0x1b, "Domain Master Browser"},
131 {0x1c, "Domain Controllers"},
132 {0x1d, "Local Master Browser"},
133 {0x1e, "Browser Election Service"},
134 {0x1f, "Net DDE Service"},
135 {0x20, "Server service"},
136 {0x21, "RAS client service"},
137 {0x22, "Exchange Interchange (MSMail Connector)"},
138 {0x23, "Exchange Store"},
139 {0x24, "Exchange Directory"},
140 {0x2b, "Lotus Notes Server service"},
141 {0x30, "Modem sharing server service"},
142 {0x31, "Modem sharing client service"},
143 {0x43, "SMS Clients Remote Control"},
144 {0x44, "SMS Administrators Remote Control Tool"},
145 {0x45, "SMS Clients Remote Chat"},
146 {0x46, "SMS Clients Remote Transfer"},
147 {0x4c, "DEC Pathworks TCP/IP Service on Windows NT"},
148 {0x52, "DEC Pathworks TCP/IP Service on Windows NT"},
149 {0x6a, "Microsoft Exchange IMC"},
150 {0x87, "Microsoft Exchange MTA"},
151 {0xbe, "Network Monitor Agent"},
152 {0xbf, "Network Monitor Analyzer"},
158 http://www.s390.ibm.com/bookmgr-cgi/bookmgr.cmd/BOOKS/BK8P7001/CCONTENTS
162 http://ourworld.compuserve.com/homepages/TimothyDEvans/contents.htm
164 for information about the NetBIOS Frame Protocol (which is what this
167 /* the strings for the command types */
169 static char *CommandName[] = {
170 "Add Group Name Query", /* 0x00 */
171 "Add Name Query", /* 0x01 */
172 "Name In Conflict", /* 0x02 */
173 "Status Query", /* 0x03 */
177 "Terminate Trace", /* 0x07 */
178 "Datagram", /* 0x08 */
179 "Broadcast Datagram", /* 0x09 */
180 "Name Query", /* 0x0A */
183 "Add Name Response", /* 0x0D */
184 "Name Recognized", /* 0x0E */
185 "Status Response", /* 0x0F */
189 "Terminate Trace", /* 0x13 */
190 "Data Ack", /* 0x14 */
191 "Data First Middle", /* 0x15 */
192 "Data Only Last", /* 0x16 */
193 "Session Confirm", /* 0x17 */
194 "Session End", /* 0x18 */
195 "Session Initialize", /* 0x19 */
196 "No Receive", /* 0x1a */
197 "Receive Outstanding", /* 0x1b */
198 "Receive Continue", /* 0x1c */
201 "Session Alive", /* 0x1f */
206 static const true_false_string flags_set = {
210 static const true_false_string flags_allowed = {
214 static const true_false_string flags_yes_no = {
219 static const true_false_string netb_version_str = {
225 void capture_netbios(const u_char *pd, int offset, packet_counts *ld)
232 process_netbios_name(const u_char *name_ptr, char *name_ret)
235 int name_type = *(name_ptr + NETBIOS_NAME_LEN - 1);
237 static const char hex_digits[16] = "0123456789abcdef";
239 for (i = 0; i < NETBIOS_NAME_LEN - 1; i++) {
240 name_char = *name_ptr++;
241 if (name_char >= ' ' && name_char <= '~')
242 *name_ret++ = name_char;
244 /* It's not printable; show it as <XX>, where
245 XX is the value in hex. */
247 *name_ret++ = hex_digits[(name_char >> 4)];
248 *name_ret++ = hex_digits[(name_char & 0x0F)];
257 int get_netbios_name( tvbuff_t *tvb, int offset, char *name_ret)
259 {/* Extract the name string and name type. Return the name string in */
260 /* name_ret and return the name_type. */
262 return process_netbios_name( tvb_get_ptr( tvb, offset, NETBIOS_NAME_LEN ), name_ret);
267 * Get a string describing the type of a NetBIOS name.
270 netbios_name_type_descr(int name_type)
272 return val_to_str(name_type, name_type_vals, "Unknown");
275 gboolean netbios_add_name(char* label, tvbuff_t *tvb, int offset,
278 {/* add a name field display tree. Display the name and station type in sub-tree */
280 proto_tree *field_tree;
282 char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
286 /* decode the name field */
287 name_type = get_netbios_name( tvb, offset, name_str);
289 /*$$$ do I need this or does tvbuffer take care of this ? */
292 * Name goes past end of captured data in packet.
297 name_type_str = netbios_name_type_descr(name_type);
299 tf = proto_tree_add_text( tree, tvb, offset, NETBIOS_NAME_LEN,
300 "%s: %s<%02x> (%s)", label, name_str, name_type, name_type_str);
302 field_tree = proto_item_add_subtree( tf, ett_netb_name);
303 proto_tree_add_string_format( field_tree, hf_netb_name, tvb, offset,
304 15, name_str, "%s", name_str);
305 proto_tree_add_uint_format( field_tree, hf_netb_name_type, tvb, offset + 15, 1, name_type,
306 "0x%02x (%s)", name_type, name_type_str);
312 static void netbios_data_first_middle_flags( tvbuff_t *tvb, proto_tree *tree, int offset)
315 proto_tree *field_tree;
317 guint flags = tvb_get_guint8( tvb, offset);
319 /* decode the flag field for Data First Middle packet*/
321 tf = proto_tree_add_text(tree, tvb, offset, 1,
322 "Flags: 0x%02x", flags);
323 field_tree = proto_item_add_subtree(tf, ett_netb_flags);
325 proto_tree_add_boolean( field_tree, hf_netb_ack, tvb, offset, 1, flags);
327 proto_tree_add_boolean( field_tree, hf_netb_ack_expected, tvb, offset, 1, flags);
329 proto_tree_add_boolean( field_tree, hf_netb_recv_cont_req, tvb, offset, 1, flags);
332 static void netbios_data_only_flags( tvbuff_t *tvb, proto_tree *tree,
335 proto_tree *field_tree;
337 guint flags = tvb_get_guint8( tvb, offset);
339 /* decode the flag field for Data Only Last packet*/
341 tf = proto_tree_add_text(tree, tvb, offset, 1,
342 "Flags: 0x%02x", flags);
343 field_tree = proto_item_add_subtree(tf, ett_netb_flags);
345 proto_tree_add_boolean( field_tree, hf_netb_ack, tvb, offset, 1, flags);
347 proto_tree_add_boolean( field_tree, hf_netb_ack_with_data, tvb, offset, 1, flags);
349 proto_tree_add_boolean( field_tree, hf_netb_ack_expected, tvb, offset, 1, flags);
354 static void netbios_add_ses_confirm_flags( tvbuff_t *tvb, proto_tree *tree,
357 proto_tree *field_tree;
359 guint flags = tvb_get_guint8( tvb, offset);
361 /* decode the flag field for Session Confirm packet */
362 tf = proto_tree_add_text(tree, tvb, offset, 1,
363 "Flags: 0x%02x", flags);
364 field_tree = proto_item_add_subtree( tf, ett_netb_flags);
366 proto_tree_add_boolean( field_tree, hf_netb_send_no_ack, tvb, offset, 1, flags);
368 proto_tree_add_boolean( field_tree, hf_netb_version, tvb, offset, 1, flags);
372 static void netbios_add_session_init_flags( tvbuff_t *tvb, proto_tree *tree,
375 proto_tree *field_tree;
377 guint flags = tvb_get_guint8( tvb, offset);
378 /* decode the flag field for Session Init packet */
380 tf = proto_tree_add_text(tree, tvb, offset, 1,
381 "Flags: 0x%02x", flags);
382 field_tree = proto_item_add_subtree(tf, ett_netb_flags);
384 proto_tree_add_boolean( field_tree, hf_netb_send_no_ack, tvb, offset, 1, flags);
386 proto_tree_add_uint( field_tree, hf_netb_largest_frame, tvb, offset, 1,
389 proto_tree_add_boolean( field_tree, hf_netb_version, tvb, offset, 1, flags);
393 static void netbios_no_receive_flags( tvbuff_t *tvb, proto_tree *tree,
397 proto_tree *field_tree;
399 guint flags = tvb_get_guint8( tvb, offset);
401 /* decode the flag field for No Receive packet*/
403 tf = proto_tree_add_text(tree, tvb, offset, 1,
404 "Flags: 0x%02x", flags);
407 field_tree = proto_item_add_subtree(tf, ett_netb_flags);
408 proto_tree_add_text(field_tree, tvb, offset, 1, "%s",
409 decode_boolean_bitfield(flags, 0x02, 8,
410 "SEND.NO.ACK data not received", NULL));
415 /************************************************************************/
417 /* The routines to display the netbios field values in the tree */
419 /************************************************************************/
422 static void nb_xmit_corrl( tvbuff_t *tvb, int offset, proto_tree *tree)
424 {/* display the transmit correlator */
426 proto_tree_add_int( tree, hf_netb_xmit_corrl, tvb, offset + NB_XMIT_CORL,
427 2, tvb_get_letohs( tvb, offset + NB_XMIT_CORL));
431 static void nb_resp_corrl( tvbuff_t *tvb, int offset, proto_tree *tree)
433 {/* display the response correlator */
435 proto_tree_add_int( tree, hf_netb_resp_corrl, tvb, offset + NB_RESP_CORL,
436 2, tvb_get_letohs( tvb, offset + NB_RESP_CORL));
440 static void nb_call_name_type( tvbuff_t *tvb, int offset, proto_tree *tree)
442 {/* display the call name type */
445 int name_type_value = tvb_get_guint8( tvb, offset + NB_CALL_NAME_TYPE);
447 switch (name_type_value) {
450 proto_tree_add_int_format( tree, hf_netb_call_name_type, tvb, offset + NB_CALL_NAME_TYPE,
451 2, tvb_get_letohs( tvb, offset + NB_CALL_NAME_TYPE), "Caller's Name Type: Unique name");
455 proto_tree_add_int_format( tree, hf_netb_call_name_type, tvb, offset + NB_CALL_NAME_TYPE,
456 2, tvb_get_letohs( tvb, offset + NB_CALL_NAME_TYPE), "Caller's Name Type: Group name");
460 proto_tree_add_int_format( tree, hf_netb_call_name_type, tvb, offset + NB_CALL_NAME_TYPE,
461 2, tvb_get_letohs( tvb, offset + NB_CALL_NAME_TYPE),
462 "Caller's Name Type: 0x%02x (should be 0 or 1)", name_type_value);
468 static void nb_local_session( tvbuff_t *tvb, int offset, proto_tree *tree)
470 {/* add the local session to tree */
472 proto_tree_add_uint( tree, hf_netb_local_ses_no, tvb, offset + NB_LOCAL_SES, 1,
473 tvb_get_guint8( tvb, offset + NB_LOCAL_SES));
478 static void nb_remote_session( tvbuff_t *tvb, int offset, proto_tree *tree)
480 {/* add the remote session to tree */
482 proto_tree_add_uint( tree, hf_netb_remote_ses_no, tvb, offset + NB_RMT_SES, 1,
483 tvb_get_guint8( tvb, offset + NB_RMT_SES));
488 static void nb_data2(char *label, int len, tvbuff_t *tvb, int offset,
491 {/* add the DATA2 to tree with format string = label and length of len */
493 int value = (len == 1 ? tvb_get_guint8( tvb, offset + NB_DATA2)
494 : tvb_get_letohs( tvb, offset + NB_DATA2));
496 proto_tree_add_uint( tree, hf_netb_data2, tvb, offset + NB_DATA2, 2, value);
501 static void nb_resync_indicator( tvbuff_t *tvb, int offset, proto_tree *tree, char *cmd_str)
503 guint16 resync_indicator = tvb_get_letohs( tvb, offset + NB_DATA2);
506 switch (resync_indicator) {
509 proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2,
510 "Re-sync indicator: No re-sync");
514 proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2,
515 "Re-sync indicator: First '%s' following 'Receive Outstanding'", cmd_str);
519 proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2,
520 "Re-sync indicator: 0x%04x", resync_indicator);
525 /************************************************************************/
527 /* The routines called by the top level to handle individual commands */
529 /************************************************************************/
531 static void dissect_netb_unknown( tvbuff_t *tvb, int offset, proto_tree *tree)
533 {/* Handle any unknow commands, do nothing */
535 /* old_dissect_data( data_ptr, offset + NB_COMMAND + 1, fd, tree); */
539 static void dissect_netb_add_group_name( tvbuff_t *tvb, int offset,
542 {/* Handle the ADD GROUP NAME QUERY command */
544 nb_resp_corrl( tvb, offset, tree);
546 netbios_add_name("Group name to add", tvb, offset + NB_SENDER_NAME,
551 static void dissect_netb_add_name( tvbuff_t *tvb, int offset,
554 {/* Handle the ADD NAME QUERY command */
556 nb_resp_corrl( tvb, offset, tree);
558 netbios_add_name("Name to add", tvb, offset + NB_SENDER_NAME, tree);
562 static void dissect_netb_name_in_conflict( tvbuff_t *tvb, int offset,
565 {/* Handle the NAME IN CONFLICT command */
567 if (!netbios_add_name("Name In Conflict", tvb, offset + NB_RECVER_NAME, tree))
569 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME, tree);
573 static void dissect_netb_status_query( tvbuff_t *tvb, int offset, proto_tree *tree)
575 {/* Handle the STATUS QUERY command */
577 guint8 status_request = tvb_get_guint8( tvb, offset + NB_DATA1);
579 switch (status_request) {
582 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
583 "Status request: NetBIOS 1.x or 2.0");
587 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
588 "Status request: NetBIOS 2.1, initial status request");
592 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
593 "Status request: NetBIOS 2.1, %u names received so far",
597 nb_data2("Length of status buffer: %u", 2, tvb, offset, tree);
598 nb_resp_corrl( tvb, offset, tree);
599 if (!netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME,
602 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
607 static u_char zeroes[10];
609 static void dissect_netb_datagram( tvbuff_t *tvb, int offset, proto_tree *tree)
611 {/* Handle the DATAGRAM command */
613 if (!netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME,
616 /* Weird. In some datagrams, this is 10 octets of 0, followed
617 by a MAC address.... */
619 if (memcmp( tvb_get_ptr( tvb,offset + NB_SENDER_NAME, 10), zeroes, 10) == 0) {
620 proto_tree_add_text( tree, tvb, offset + NB_SENDER_NAME + 10, 6,
621 "Sender's MAC Address: %s",
622 ether_to_str( tvb_get_ptr( tvb,offset + NB_SENDER_NAME + 10, 6)));
624 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
630 static void dissect_netb_datagram_bcast( tvbuff_t *tvb, int offset,
633 {/* Handle the DATAGRAM BROADCAST command */
635 /* We assume the same weirdness can happen here.... */
636 if ( memcmp( tvb_get_ptr( tvb,offset + NB_SENDER_NAME + 10, 6), zeroes, 10) == 0) {
637 proto_tree_add_text( tree, tvb, offset + NB_SENDER_NAME + 10, 6,
638 "Sender's Node Address: %s",
639 ether_to_str( tvb_get_ptr( tvb,offset + NB_SENDER_NAME + 10, 6)));
641 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
647 static void dissect_netb_name_query( tvbuff_t *tvb, int offset, proto_tree *tree)
649 {/* Handle the NAME QUERY command */
650 guint8 local_session_number = tvb_get_guint8( tvb, offset + NB_DATA2);
652 if (local_session_number == 0) {
653 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
654 "Local Session No.: 0 (FIND.NAME request)");
656 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
657 "Local Session No.: 0x%02x", local_session_number);
659 nb_call_name_type( tvb, offset, tree);
660 nb_resp_corrl( tvb, offset, tree);
661 if (!netbios_add_name("Query Name", tvb, offset + NB_RECVER_NAME, tree))
663 if (local_session_number != 0) {
664 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
670 static void dissect_netb_add_name_resp( tvbuff_t *tvb, int offset,
673 {/* Handle the ADD NAME RESPONSE command */
674 guint8 status = tvb_get_guint8( tvb, offset + NB_DATA1);
675 guint16 name_type = tvb_get_letohs( tvb, offset + NB_DATA2);
680 proto_tree_add_text( tree, tvb, offset + NB_DATA1, 1,
681 "Status: Add name not in process");
685 proto_tree_add_text( tree, tvb, offset + NB_DATA1, 1,
686 "Status: Add name in process");
690 proto_tree_add_text( tree, tvb, offset + NB_DATA1, 1,
691 "Status: 0x%02x (should be 0 or 1)", status);
698 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 2,
699 "Name type: Unique name");
703 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 2,
704 "Name type: Group name");
708 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 2,
709 "Name type: 0x%04x (should be 0 or 1)", name_type);
713 nb_xmit_corrl( tvb, offset, tree);
714 if (!netbios_add_name("Name to be added", tvb, offset + NB_RECVER_NAME,
717 netbios_add_name("Name to be added", tvb, offset + NB_SENDER_NAME,
722 static void dissect_netb_name_resp( tvbuff_t *tvb, int offset,
725 {/* Handle the NAME RECOGNIZED command */
726 guint8 local_session_number = tvb_get_guint8( tvb, offset + NB_DATA2);
728 switch (local_session_number) {
731 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
732 "State of name: No LISTEN pending, or FIND.NAME response");
736 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
737 "State of name: LISTEN pending, but insufficient resources to establish session");
741 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
742 "Local Session No.: 0x%02x", local_session_number);
745 nb_call_name_type( tvb, offset, tree);
746 nb_xmit_corrl( tvb, offset, tree);
747 if (local_session_number != 0x00 && local_session_number != 0xFF)
748 nb_resp_corrl(tvb, offset, tree);
749 if (!netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME,
752 if (local_session_number != 0x00 && local_session_number != 0xFF) {
753 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
759 static void dissect_netb_status_resp( tvbuff_t *tvb, int offset, proto_tree *tree)
761 {/* Handle the STATUS RESPONSE command */
762 guint8 status_response = tvb_get_guint8( tvb, offset + NB_DATA1);
764 proto_tree *data2_tree;
767 nb_call_name_type( tvb, offset, tree);
768 if (status_response == 0) {
769 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
770 "Status response: NetBIOS 1.x or 2.0");
772 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
773 "Status response: NetBIOS 2.1, %u names sent so far",
776 data2 = tvb_get_letohs( tvb, offset + NB_DATA2);
778 td2 = proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2, "Status: 0x%04x",
780 data2_tree = proto_item_add_subtree(td2, ett_netb_status);
781 if (data2 & 0x8000) {
782 proto_tree_add_text(data2_tree, tvb, offset, 2, "%s",
783 decode_boolean_bitfield(data2, 0x8000, 8*2,
784 "Data length exceeds maximum frame size", NULL));
786 if (data2 & 0x4000) {
787 proto_tree_add_text(data2_tree, tvb, offset, 2, "%s",
788 decode_boolean_bitfield(data2, 0x4000, 8*2,
789 "Data length exceeds user's buffer", NULL));
791 proto_tree_add_text(data2_tree, tvb, offset, 2, "%s",
792 decode_numeric_bitfield(data2, 0x3FFF, 2*8,
793 "Status data length = %u"));
794 nb_xmit_corrl( tvb, offset, tree);
795 if (!netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME,
798 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
803 static void dissect_netb_data_ack( tvbuff_t* tvb, int offset, proto_tree *tree)
805 {/* Handle the DATA ACK command */
807 nb_xmit_corrl( tvb, offset, tree);
808 nb_remote_session( tvb, offset, tree);
809 nb_local_session( tvb, offset, tree);
813 static void dissect_netb_data_first_middle( tvbuff_t *tvb, int offset,
816 {/* Handle the DATA FIRST MIDDLE command */
818 netbios_data_first_middle_flags( tvb, tree, offset + NB_FLAGS);
820 nb_resync_indicator( tvb, offset, tree, "DATA FIRST MIDDLE");
821 nb_xmit_corrl( tvb, offset, tree);
822 nb_resp_corrl( tvb, offset, tree);
823 nb_remote_session( tvb, offset, tree);
824 nb_local_session( tvb, offset, tree);
828 static void dissect_netb_data_only_last( tvbuff_t *tvb, int offset,
831 {/* Handle the DATA ONLY LAST command */
833 netbios_data_only_flags( tvb, tree, offset + NB_FLAGS);
835 nb_resync_indicator( tvb, offset, tree, "DATA ONLY LAST");
836 nb_xmit_corrl( tvb, offset, tree);
837 nb_resp_corrl( tvb, offset, tree);
838 nb_remote_session( tvb, offset, tree);
839 nb_local_session( tvb, offset, tree);
843 static void dissect_netb_session_confirm( tvbuff_t *tvb, int offset,
846 {/* Handle the SESSION CONFIRM command */
848 netbios_add_ses_confirm_flags( tvb, tree, offset + NB_FLAGS);
850 nb_data2("Max data recv size: %u", 2, tvb, offset, tree);
851 nb_xmit_corrl( tvb, offset, tree);
852 nb_resp_corrl( tvb, offset, tree);
853 nb_remote_session( tvb, offset, tree);
854 nb_local_session( tvb, offset, tree);
858 static void dissect_netb_session_end( tvbuff_t *tvb, int offset,
861 {/* Handle the SESSION END command */
862 guint16 termination_indicator = tvb_get_letohs( tvb, offset + NB_DATA2);
864 switch (termination_indicator) {
867 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 2,
868 "Termination indicator: Normal session end");
872 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 2,
873 "Termination indicator: Abormal session end");
877 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 2,
878 "Termination indicator: 0x%04x (should be 0x0000 or 0x0001)",
879 termination_indicator);
883 nb_remote_session( tvb, offset, tree);
884 nb_local_session( tvb, offset, tree);
888 static void dissect_netb_session_init( tvbuff_t *tvb, int offset,
891 {/* Handle the SESSION INITIALIZE command */
893 netbios_add_session_init_flags( tvb, tree, offset + NB_FLAGS);
895 nb_data2("Max data recv size: %u", 2, tvb, offset, tree);
896 nb_resp_corrl( tvb, offset, tree);
897 nb_xmit_corrl( tvb, offset, tree);
898 nb_remote_session( tvb, offset, tree);
899 nb_local_session( tvb, offset, tree);
902 static void dissect_netb_no_receive( tvbuff_t *tvb, int offset,
905 {/* Handle the NO RECEIVE command */
907 netbios_no_receive_flags( tvb, tree, offset + NB_FLAGS);
909 nb_data2("Number of data bytes accepted: %u", 2, tvb, offset, tree);
910 nb_remote_session( tvb, offset, tree);
911 nb_local_session( tvb, offset, tree);
915 static void dissect_netb_receive_outstanding( tvbuff_t *tvb, int offset,
918 {/* Handle the RECEIVE OUTSTANDING command */
920 nb_data2("Number of data bytes accepted: %u", 2, tvb, offset, tree);
921 nb_remote_session( tvb, offset, tree);
922 nb_local_session( tvb, offset, tree);
926 static void dissect_netb_receive_continue( tvbuff_t *tvb, int offset,
929 {/* Handle the RECEIVE CONTINUE command */
931 nb_xmit_corrl( tvb, offset, tree);
932 nb_remote_session( tvb, offset, tree);
933 nb_local_session( tvb, offset, tree);
937 /************************************************************************/
939 /* The table routines called by the top level to handle commands */
941 /************************************************************************/
944 void (*dissect_netb[])(tvbuff_t *, int, proto_tree *) = {
946 dissect_netb_add_group_name, /* Add Group Name 0x00 */
947 dissect_netb_add_name, /* Add Name 0x01 */
948 dissect_netb_name_in_conflict,/* Name In Conflict 0x02 */
949 dissect_netb_status_query, /* Status Query 0x03 */
950 dissect_netb_unknown, /* unknown 0x04 */
951 dissect_netb_unknown, /* unknown 0x05 */
952 dissect_netb_unknown, /* unknown 0x06 */
953 dissect_netb_unknown, /* Terminate Trace 0x07 */
954 dissect_netb_datagram, /* Datagram 0x08 */
955 dissect_netb_datagram_bcast, /* Datagram Broadcast 0x09 */
956 dissect_netb_name_query, /* Name Query 0x0A */
957 dissect_netb_unknown, /* unknown 0x0B */
958 dissect_netb_unknown, /* unknown 0x0C */
959 dissect_netb_add_name_resp, /* Add Name Response 0x0D */
960 dissect_netb_name_resp, /* Name Recognized 0x0E */
961 dissect_netb_status_resp, /* Status Response 0x0F */
962 dissect_netb_unknown, /* unknown 0x10 */
963 dissect_netb_unknown, /* unknown 0x11 */
964 dissect_netb_unknown, /* unknown 0x12 */
965 dissect_netb_unknown, /* Terminate Trace 0x13 */
966 dissect_netb_data_ack, /* Data Ack 0x14 */
967 dissect_netb_data_first_middle,/* Data First Middle 0x15 */
968 dissect_netb_data_only_last, /* Data Only Last 0x16 */
969 dissect_netb_session_confirm, /* Session Confirm 0x17 */
970 dissect_netb_session_end, /* Session End 0x18 */
971 dissect_netb_session_init, /* Session Initialize 0x19 */
972 dissect_netb_no_receive, /* No Receive 0x1A */
973 dissect_netb_receive_outstanding,/* Receive Outstanding 0x1B */
974 dissect_netb_receive_continue,/* Receive Continue 0x1C */
975 dissect_netb_unknown, /* unknown 0x1D */
976 dissect_netb_unknown, /* unknown 0x1E */
978 dissect_netb_unknown, /* Session Alive 0x1f (nothing to do) */
979 dissect_netb_unknown,
984 dissect_netbios(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
987 proto_tree *netb_tree;
989 guint16 hdr_len, command;
990 char name[(NETBIOS_NAME_LEN - 1)*4 + 1];
995 CHECK_DISPLAY_AS_DATA(proto_netbios, tvb, pinfo, tree);
998 /* load the display labels */
999 pinfo->current_proto = "NetBIOS";
1000 if (check_col(pinfo->fd, COL_PROTOCOL))
1001 col_set_str(pinfo->fd, COL_PROTOCOL, "NetBIOS");
1004 /* Find NetBIOS marker EFFF, this is done because I have seen an extra LLC */
1005 /* byte on our network. This only checks for one extra LLC byte. */
1007 if ( 0xefff != tvb_get_letohs(tvb, 2)){
1009 if ( 0xefff != tvb_get_letohs(tvb, 3)){
1011 if (check_col( pinfo->fd, COL_INFO)) /* print bad packet */
1012 col_set_str( pinfo->fd, COL_INFO, "Bad packet, no 0xEFFF marker");
1014 return; /* this is an unknow packet, no marker */
1019 hdr_len = tvb_get_letohs(tvb, offset + NB_LENGTH);
1020 command = tvb_get_guint8( tvb, offset + NB_COMMAND);
1021 /* limit command so no table overflows */
1022 command = MIN( command, sizeof( dissect_netb)/ sizeof(void *));
1024 if (check_col( pinfo->fd, COL_INFO)) { /* print command name */
1025 switch ( command ) {
1027 name_type = get_netbios_name( tvb, offset + 12, name);
1028 col_add_fstr( pinfo->fd, COL_INFO, "%s for %s<%02x>",
1029 CommandName[ command], name, name_type);
1035 name_type = get_netbios_name( tvb, offset + 28, name);
1036 col_add_fstr( pinfo->fd, COL_INFO, "%s - %s<%02x>",
1037 CommandName[ command], name, name_type);
1041 col_add_fstr( pinfo->fd, COL_INFO, "%s", CommandName[ command]);
1047 ti = proto_tree_add_item(tree, proto_netbios, tvb, 0, tvb_length(tvb), FALSE);
1048 netb_tree = proto_item_add_subtree(ti, ett_netb);
1050 proto_tree_add_uint_format(netb_tree, hf_netb_hdr_len, tvb, offset, 2, hdr_len,
1051 "Length: %d bytes", hdr_len);
1053 proto_tree_add_text(netb_tree, tvb, offset + 2, 2,
1054 "Delimiter: EFFF (NetBIOS)");
1056 proto_tree_add_uint_format(netb_tree, hf_netb_cmd, tvb, offset + NB_COMMAND, 1, command,
1057 "Command: 0x%02x (%s)", command, CommandName[ command]);
1059 /* if command in table range */
1060 if ( command < sizeof( dissect_netb)/ sizeof(void *))
1062 /* branch to handle commands */
1063 (dissect_netb[ command])( tvb, offset, netb_tree);
1066 /* Test for SMB data */
1067 if ( tvb_length(tvb)> ( hdr_len + 4)){ /* if enough data */
1069 offset += hdr_len; /* move past header */
1071 if (( tvb_get_guint8( tvb, offset) == 0xff) && /* if SMB marker */
1072 ( tvb_get_guint8( tvb, offset + 1) == 'S') &&
1073 ( tvb_get_guint8( tvb, offset + 2) == 'M') &&
1074 ( tvb_get_guint8( tvb, offset + 3) == 'B')) {
1077 const guint8 *next_pd;
1080 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1081 tvb_compat(next_tvb, &next_pd, &next_offset);
1084 dissect_smb( next_pd, next_offset, pinfo->fd, tree,
1085 END_OF_FRAME - next_offset);
1092 void proto_register_netbios(void)
1094 static gint *ett[] = {
1101 static hf_register_info hf_netb[] = {
1103 { "Command", "netbios.command", FT_UINT16, BASE_HEX, NULL, 0x0,
1106 { "Header Length", "netbios.hdr_len", FT_UINT16, BASE_DEC, NULL, 0x0,
1109 { &hf_netb_xmit_corrl,
1110 { "Transmit Correlator", "netbios.xmit_corrl", FT_INT16, BASE_HEX, NULL, 0x0,
1113 { &hf_netb_resp_corrl,
1114 { "Response Correlator", "netbios.resp_corrl", FT_INT16, BASE_HEX, NULL, 0x0,
1116 { &hf_netb_call_name_type,
1117 { "Call Name Type", "netbios.call_name_type", FT_INT16, BASE_HEX, NULL, 0x0,
1119 { &hf_netb_name_type,
1120 { "Netbios Name Type", "netbios.name_type", FT_UINT16, BASE_HEX, NULL, 0x0,
1123 { "Netbios Name", "netbios.name", FT_STRING, BASE_NONE, NULL, 0x0,
1127 { "Acknowledge", "netbios.ack", FT_BOOLEAN, 8, TFS( &flags_set), 0x08,
1130 { &hf_netb_ack_with_data,
1131 { "Acknowledge with data", "netbios.ack_with_data", FT_BOOLEAN, 8, TFS( &flags_allowed), 0x04,
1134 { &hf_netb_ack_expected,
1135 { "Acknowledge expected", "netbios.ack_expected", FT_BOOLEAN, 8,
1136 TFS( &flags_yes_no), 0x02, "" }},
1138 { &hf_netb_recv_cont_req,
1139 { "RECEIVE_CONTINUE requested", "netbios.recv_cont_req", FT_BOOLEAN, 8,
1140 TFS( &flags_yes_no), 0x01, "" }},
1142 { &hf_netb_send_no_ack,
1143 { "Handle SEND.NO.ACK", "netbios.send_no_ack", FT_BOOLEAN, 8,
1144 TFS( &flags_yes_no), 0x80, "" }},
1147 { "NetBIOS Version", "netbios.version", FT_BOOLEAN, 8,
1148 TFS( &netb_version_str), 0x01, "" }},
1150 { &hf_netb_largest_frame,
1151 { "Largest Frame", "netbios.largest_frame", FT_UINT8, BASE_HEX, NULL, 0x0E,
1154 { &hf_netb_local_ses_no,
1155 { "Local Session No. ", "netbios.local_session", FT_UINT8, BASE_HEX, NULL, 0x0,
1158 { &hf_netb_remote_ses_no,
1159 { "Remote Session No. ", "netbios.remote_session", FT_UINT8, BASE_HEX, NULL, 0x0,
1163 { "DATA2 value ", "netbios.data2", FT_UINT16, BASE_HEX, NULL, 0x0,
1167 proto_netbios = proto_register_protocol("NetBIOS", "NetBIOS", "netbios");
1168 proto_register_subtree_array(ett, array_length(ett));
1169 proto_register_field_array(proto_netbios, hf_netb, array_length(hf_netb));
1173 proto_reg_handoff_netbios(void)
1175 dissector_add("llc.dsap", SAP_NETBIOS, dissect_netbios);