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
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include <epan/packet.h>
37 #include <epan/llcsaps.h>
38 #include <epan/reassemble.h>
39 #include <epan/prefs.h>
40 #include "packet-netbios.h"
42 /* Netbios command numbers */
43 #define NB_ADD_GROUP 0x00
44 #define NB_ADD_NAME 0x01
45 #define NB_NAME_IN_CONFLICT 0x02
46 #define NB_STATUS_QUERY 0x03
47 #define NB_TERMINATE_TRACE_R 0x07
48 #define NB_DATAGRAM 0x08
49 #define NB_DATAGRAM_BCAST 0x09
50 #define NB_NAME_QUERY 0x0a
51 #define NB_ADD_NAME_RESP 0x0d
52 #define NB_NAME_RESP 0x0e
53 #define NB_STATUS_RESP 0x0f
54 #define NB_TERMINATE_TRACE_LR 0x13
55 #define NB_DATA_ACK 0x14
56 #define NB_DATA_FIRST_MIDDLE 0x15
57 #define NB_DATA_ONLY_LAST 0x16
58 #define NB_SESSION_CONFIRM 0x17
59 #define NB_SESSION_END 0x18
60 #define NB_SESSION_INIT 0x19
61 #define NB_NO_RECEIVE 0x1a
62 #define NB_RECEIVE_OUTSTANDING 0x1b
63 #define NB_RECEIVE_CONTINUE 0x1c
64 #define NB_KEEP_ALIVE 0x1f
66 /* Offsets of fields in the NetBIOS header. */
68 #define NB_DELIMITER 2
74 #define NB_CALL_NAME_TYPE 7
75 #define NB_XMIT_CORL 8
76 #define NB_RESP_CORL 10
78 #define NB_LOCAL_SES 13
79 #define NB_RECVER_NAME 12
80 #define NB_SENDER_NAME 28
83 static int proto_netbios = -1;
84 static int hf_netb_cmd = -1;
85 static int hf_netb_hdr_len = -1;
86 static int hf_netb_xmit_corrl = -1;
87 static int hf_netb_resp_corrl = -1;
88 static int hf_netb_call_name_type = -1;
89 static int hf_netb_ack = -1;
90 static int hf_netb_ack_with_data = -1;
91 static int hf_netb_ack_expected = -1;
92 static int hf_netb_recv_cont_req = -1;
93 static int hf_netb_send_no_ack = -1;
94 static int hf_netb_version = -1;
95 static int hf_netb_largest_frame = -1;
96 static int hf_netb_nb_name = -1;
97 static int hf_netb_nb_name_type = -1;
98 static int hf_netb_status_buffer_len = -1;
99 static int hf_netb_status = -1;
100 static int hf_netb_name_type = -1;
101 static int hf_netb_max_data_recv_size = -1;
102 static int hf_netb_termination_indicator = -1;
103 static int hf_netb_num_data_bytes_accepted = -1;
104 static int hf_netb_local_ses_no = -1;
105 static int hf_netb_remote_ses_no = -1;
106 static int hf_netb_data1 = -1;
107 static int hf_netb_data2 = -1;
108 static int hf_netb_fragments = -1;
109 static int hf_netb_fragment = -1;
110 static int hf_netb_fragment_overlap = -1;
111 static int hf_netb_fragment_overlap_conflict = -1;
112 static int hf_netb_fragment_multiple_tails = -1;
113 static int hf_netb_fragment_too_long_fragment = -1;
114 static int hf_netb_fragment_error = -1;
115 static int hf_netb_reassembled_length = -1;
117 static gint ett_netb = -1;
118 static gint ett_netb_name = -1;
119 static gint ett_netb_flags = -1;
120 static gint ett_netb_status = -1;
121 static gint ett_netb_fragments = -1;
122 static gint ett_netb_fragment = -1;
124 static const fragment_items netbios_frag_items = {
129 &hf_netb_fragment_overlap,
130 &hf_netb_fragment_overlap_conflict,
131 &hf_netb_fragment_multiple_tails,
132 &hf_netb_fragment_too_long_fragment,
133 &hf_netb_fragment_error,
135 &hf_netb_reassembled_length,
139 static dissector_handle_t data_handle;
141 /* The strings for the station type, used by get_netbios_name function;
142 many of them came from the file "NetBIOS.txt" in the Zip archive at
144 http://www.net3group.com/ftp/browser.zip
147 static const value_string nb_name_type_vals[] = {
148 {0x00, "Workstation/Redirector"},
150 {0x02, "Workstation/Redirector"},
151 /* not sure what 0x02 is, I'm seeing alot of them however */
152 /* i'm seeing them with workstation/redirection host
154 {0x03, "Messenger service/Main name"},
155 {0x05, "Forwarded name"},
156 {0x06, "RAS Server service"},
157 {0x1b, "Domain Master Browser"},
158 {0x1c, "Domain Controllers"},
159 {0x1d, "Local Master Browser"},
160 {0x1e, "Browser Election Service"},
161 {0x1f, "Net DDE Service"},
162 {0x20, "Server service"},
163 {0x21, "RAS client service"},
164 {0x22, "Exchange Interchange (MSMail Connector)"},
165 {0x23, "Exchange Store"},
166 {0x24, "Exchange Directory"},
167 {0x2b, "Lotus Notes Server service"},
168 {0x30, "Modem sharing server service"},
169 {0x31, "Modem sharing client service"},
170 {0x43, "SMS Clients Remote Control"},
171 {0x44, "SMS Administrators Remote Control Tool"},
172 {0x45, "SMS Clients Remote Chat"},
173 {0x46, "SMS Clients Remote Transfer"},
174 {0x4c, "DEC Pathworks TCP/IP Service on Windows NT"},
175 {0x52, "DEC Pathworks TCP/IP Service on Windows NT"},
176 {0x6a, "Microsoft Exchange IMC"},
177 {0x87, "Microsoft Exchange MTA"},
178 {0xbe, "Network Monitor Agent"},
179 {0xbf, "Network Monitor Analyzer"},
183 /* Tables for reassembly of fragments. */
184 static GHashTable *netbios_fragment_table = NULL;
185 static GHashTable *netbios_reassembled_table = NULL;
187 /* defragmentation of NetBIOS Frame */
188 static gboolean netbios_defragment = TRUE;
192 http://www.s390.ibm.com/bookmgr-cgi/bookmgr.cmd/BOOKS/BK8P7001/CCONTENTS
196 http://ourworld.compuserve.com/homepages/TimothyDEvans/contents.htm
198 for information about the NetBIOS Frame Protocol (which is what this
201 /* the strings for the command types */
203 static const value_string cmd_vals[] = {
204 { NB_ADD_GROUP, "Add Group Name Query" },
205 { NB_ADD_NAME, "Add Name Query" },
206 { NB_NAME_IN_CONFLICT, "Name In Conflict" },
207 { NB_STATUS_QUERY, "Status Query" },
208 { NB_TERMINATE_TRACE_R, "Terminate Trace" },
209 { NB_DATAGRAM, "Datagram" },
210 { NB_DATAGRAM_BCAST, "Broadcast Datagram" },
211 { NB_NAME_QUERY, "Name Query" },
212 { NB_ADD_NAME_RESP, "Add Name Response" },
213 { NB_NAME_RESP, "Name Recognized" },
214 { NB_STATUS_RESP, "Status Response" },
215 { NB_TERMINATE_TRACE_LR, "Terminate Trace" },
216 { NB_DATA_ACK, "Data Ack" },
217 { NB_DATA_FIRST_MIDDLE, "Data First Middle" },
218 { NB_DATA_ONLY_LAST, "Data Only Last" },
219 { NB_SESSION_CONFIRM, "Session Confirm" },
220 { NB_SESSION_END, "Session End" },
221 { NB_SESSION_INIT, "Session Initialize" },
222 { NB_NO_RECEIVE, "No Receive" },
223 { NB_RECEIVE_OUTSTANDING, "Receive Outstanding" },
224 { NB_RECEIVE_CONTINUE, "Receive Continue" },
225 { NB_KEEP_ALIVE, "Session Alive" },
229 static const value_string name_types[] = {
230 { 0, "Unique name" },
235 static const true_false_string flags_allowed = {
240 static const true_false_string netb_version_str = {
245 static const value_string termination_indicator_vals[] = {
246 { 0x0000, "Normal session end" },
247 { 0x0001, "Abnormal session end" },
251 static const value_string status_vals[] = {
252 { 0, "Add name not in process" },
253 { 1, "Add name in process" },
257 static const value_string max_frame_size_vals[] = {
264 { 6, "17800" }, /* 17800 in TR spec, 17749 in NBF spec */
270 void capture_netbios(packet_counts *ld)
277 process_netbios_name(const guchar *name_ptr, char *name_ret, int name_ret_len)
280 int name_type = *(name_ptr + NETBIOS_NAME_LEN - 1);
282 static const char hex_digits[16] = "0123456789abcdef";
284 for (i = 0; i < NETBIOS_NAME_LEN - 1; i++) {
285 name_char = *name_ptr++;
286 if (name_char >= ' ' && name_char <= '~') {
287 if (--name_ret_len > 0)
288 *name_ret++ = name_char;
290 /* It's not printable; show it as <XX>, where
291 XX is the value in hex. */
292 if (--name_ret_len > 0)
294 if (--name_ret_len > 0)
295 *name_ret++ = hex_digits[(name_char >> 4)];
296 if (--name_ret_len > 0)
297 *name_ret++ = hex_digits[(name_char & 0x0F)];
298 if (--name_ret_len > 0)
304 /* Remove trailing space characters from name. */
308 for (i = 0; i < NETBIOS_NAME_LEN - 1; i++) {
309 if (*name_ret != ' ') {
320 int get_netbios_name( tvbuff_t *tvb, int offset, char *name_ret, int name_ret_len)
322 {/* Extract the name string and name type. Return the name string in */
323 /* name_ret and return the name_type. */
325 return process_netbios_name( tvb_get_ptr( tvb, offset, NETBIOS_NAME_LEN ), name_ret, name_ret_len);
330 * Get a string describing the type of a NetBIOS name.
333 netbios_name_type_descr(int name_type)
335 return val_to_str(name_type, nb_name_type_vals, "Unknown");
338 void netbios_add_name(const char* label, tvbuff_t *tvb, int offset,
341 {/* add a name field display tree. Display the name and station type in sub-tree */
343 proto_tree *field_tree;
345 char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
347 const char *name_type_str;
349 /* decode the name field */
350 name_type = get_netbios_name( tvb, offset, name_str, (NETBIOS_NAME_LEN - 1)*4 + 1);
351 name_type_str = netbios_name_type_descr(name_type);
352 tf = proto_tree_add_text( tree, tvb, offset, NETBIOS_NAME_LEN,
353 "%s: %s<%02x> (%s)", label, name_str, name_type, name_type_str);
355 field_tree = proto_item_add_subtree( tf, ett_netb_name);
356 proto_tree_add_string_format( field_tree, hf_netb_nb_name, tvb, offset,
357 15, name_str, "%s", name_str);
358 proto_tree_add_uint_format( field_tree, hf_netb_nb_name_type, tvb, offset + 15, 1, name_type,
359 "0x%02x (%s)", name_type, name_type_str);
363 static void netbios_data_first_middle_flags( tvbuff_t *tvb, proto_tree *tree, int offset)
366 proto_tree *field_tree;
368 guint flags = tvb_get_guint8( tvb, offset);
370 /* decode the flag field for Data First Middle packet*/
372 tf = proto_tree_add_text(tree, tvb, offset, 1,
373 "Flags: 0x%02x", flags);
374 field_tree = proto_item_add_subtree(tf, ett_netb_flags);
376 proto_tree_add_boolean( field_tree, hf_netb_ack, tvb, offset, 1, flags);
378 proto_tree_add_boolean( field_tree, hf_netb_ack_expected, tvb, offset, 1, flags);
380 proto_tree_add_boolean( field_tree, hf_netb_recv_cont_req, tvb, offset, 1, flags);
383 static void netbios_data_only_flags( tvbuff_t *tvb, proto_tree *tree,
386 proto_tree *field_tree;
388 guint flags = tvb_get_guint8( tvb, offset);
390 /* decode the flag field for Data Only Last packet*/
392 tf = proto_tree_add_text(tree, tvb, offset, 1,
393 "Flags: 0x%02x", flags);
394 field_tree = proto_item_add_subtree(tf, ett_netb_flags);
396 proto_tree_add_boolean( field_tree, hf_netb_ack, tvb, offset, 1, flags);
398 proto_tree_add_boolean( field_tree, hf_netb_ack_with_data, tvb, offset, 1, flags);
400 proto_tree_add_boolean( field_tree, hf_netb_ack_expected, tvb, offset, 1, flags);
405 static void netbios_add_ses_confirm_flags( tvbuff_t *tvb, proto_tree *tree,
408 proto_tree *field_tree;
410 guint flags = tvb_get_guint8( tvb, offset);
412 /* decode the flag field for Session Confirm packet */
413 tf = proto_tree_add_text(tree, tvb, offset, 1,
414 "Flags: 0x%02x", flags);
415 field_tree = proto_item_add_subtree( tf, ett_netb_flags);
417 proto_tree_add_boolean( field_tree, hf_netb_send_no_ack, tvb, offset, 1, flags);
419 proto_tree_add_boolean( field_tree, hf_netb_version, tvb, offset, 1, flags);
423 static void netbios_add_session_init_flags( tvbuff_t *tvb, proto_tree *tree,
426 proto_tree *field_tree;
428 guint flags = tvb_get_guint8( tvb, offset);
429 /* decode the flag field for Session Init packet */
431 tf = proto_tree_add_text(tree, tvb, offset, 1,
432 "Flags: 0x%02x", flags);
433 field_tree = proto_item_add_subtree(tf, ett_netb_flags);
435 proto_tree_add_boolean( field_tree, hf_netb_send_no_ack, tvb, offset, 1, flags);
437 proto_tree_add_uint( field_tree, hf_netb_largest_frame, tvb, offset, 1,
440 proto_tree_add_boolean( field_tree, hf_netb_version, tvb, offset, 1, flags);
444 static void netbios_no_receive_flags( tvbuff_t *tvb, proto_tree *tree,
448 proto_tree *field_tree;
450 guint flags = tvb_get_guint8( tvb, offset);
452 /* decode the flag field for No Receive packet*/
454 tf = proto_tree_add_text(tree, tvb, offset, 1,
455 "Flags: 0x%02x", flags);
458 field_tree = proto_item_add_subtree(tf, ett_netb_flags);
459 proto_tree_add_text(field_tree, tvb, offset, 1, "%s",
460 decode_boolean_bitfield(flags, 0x02, 8,
461 "SEND.NO.ACK data not received", NULL));
466 /************************************************************************/
468 /* The routines to display the netbios field values in the tree */
470 /************************************************************************/
473 static void nb_xmit_corrl( tvbuff_t *tvb, int offset, proto_tree *tree)
475 {/* display the transmit correlator */
477 proto_tree_add_item( tree, hf_netb_xmit_corrl, tvb, offset + NB_XMIT_CORL,
482 static void nb_resp_corrl( tvbuff_t *tvb, int offset, proto_tree *tree)
484 {/* display the response correlator */
486 proto_tree_add_item( tree, hf_netb_resp_corrl, tvb, offset + NB_RESP_CORL,
491 static void nb_call_name_type( tvbuff_t *tvb, int offset, proto_tree *tree)
493 {/* display the call name type */
495 proto_tree_add_item( tree, hf_netb_call_name_type, tvb, offset + NB_CALL_NAME_TYPE,
501 static guint8 nb_local_session( tvbuff_t *tvb, int offset, proto_tree *tree)
503 {/* add the local session to tree, and return its value */
505 guint8 local_session = tvb_get_guint8( tvb, offset + NB_LOCAL_SES);
507 proto_tree_add_uint( tree, hf_netb_local_ses_no, tvb, offset + NB_LOCAL_SES, 1,
510 return local_session;
514 static guint8 nb_remote_session( tvbuff_t *tvb, int offset, proto_tree *tree)
516 {/* add the remote session to tree, and return its value */
518 guint8 remote_session = tvb_get_guint8( tvb, offset + NB_RMT_SES);
520 proto_tree_add_uint( tree, hf_netb_remote_ses_no, tvb, offset + NB_RMT_SES, 1,
523 return remote_session;
527 static void nb_data1(int hf, tvbuff_t *tvb, int offset, proto_tree *tree)
529 {/* add the DATA1 to tree with specified hf_ value */
531 proto_tree_add_item( tree, hf, tvb, offset + NB_DATA1, 1, TRUE);
536 static void nb_data2(int hf, tvbuff_t *tvb, int offset, proto_tree *tree)
538 {/* add the DATA2 to tree with specified hf_ value */
540 proto_tree_add_item( tree, hf, tvb, offset + NB_DATA2, 2, TRUE);
545 static void nb_resync_indicator( tvbuff_t *tvb, int offset, proto_tree *tree, const char *cmd_str)
547 guint16 resync_indicator = tvb_get_letohs( tvb, offset + NB_DATA2);
550 switch (resync_indicator) {
553 proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2,
554 "Re-sync indicator: No re-sync");
558 proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2,
559 "Re-sync indicator: First '%s' following 'Receive Outstanding'", cmd_str);
563 proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2,
564 "Re-sync indicator: 0x%04x", resync_indicator);
569 /************************************************************************/
571 /* The routines called by the top level to handle individual commands */
573 /************************************************************************/
576 dissect_netb_unknown( tvbuff_t *tvb, int offset, proto_tree *tree)
578 {/* Handle any unknown commands, do nothing */
580 proto_tree_add_text(tree, tvb, offset + NB_COMMAND + 1, -1,
581 "Unknown NetBIOS command data");
588 dissect_netb_add_group_name( tvbuff_t *tvb, int offset, proto_tree *tree)
590 {/* Handle the ADD GROUP NAME QUERY command */
592 nb_resp_corrl( tvb, offset, tree);
594 netbios_add_name("Group name to add", tvb, offset + NB_SENDER_NAME,
602 dissect_netb_add_name( tvbuff_t *tvb, int offset, proto_tree *tree)
604 {/* Handle the ADD NAME QUERY command */
606 nb_resp_corrl( tvb, offset, tree);
608 netbios_add_name("Name to add", tvb, offset + NB_SENDER_NAME, tree);
615 dissect_netb_name_in_conflict( tvbuff_t *tvb, int offset, proto_tree *tree)
617 {/* Handle the NAME IN CONFLICT command */
619 netbios_add_name("Name In Conflict", tvb, offset + NB_RECVER_NAME,
621 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME, tree);
628 dissect_netb_status_query( tvbuff_t *tvb, int offset, proto_tree *tree)
630 {/* Handle the STATUS QUERY command */
632 guint8 status_request = tvb_get_guint8( tvb, offset + NB_DATA1);
634 switch (status_request) {
637 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
638 "Status request: NetBIOS 1.x or 2.0");
642 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
643 "Status request: NetBIOS 2.1, initial status request");
647 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
648 "Status request: NetBIOS 2.1, %u names received so far",
652 nb_data2( hf_netb_status_buffer_len, tvb, offset, tree);
653 nb_resp_corrl( tvb, offset, tree);
654 netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
655 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME, tree);
662 dissect_netb_terminate_trace( tvbuff_t *tvb _U_, int offset _U_, proto_tree *tree _U_)
664 {/* Handle the TERMINATE TRACE command */
667 * XXX - are any of the fields in this message significant?
668 * The IBM NetBIOS document shows them as "Reserved".
675 static guchar zeroes[10];
678 dissect_netb_datagram( tvbuff_t *tvb, int offset, proto_tree *tree)
680 {/* Handle the DATAGRAM command */
682 netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
683 /* Weird. In some datagrams, this is 10 octets of 0, followed
684 by a MAC address.... */
686 if (memcmp( tvb_get_ptr( tvb,offset + NB_SENDER_NAME, 10), zeroes, 10) == 0) {
687 proto_tree_add_text( tree, tvb, offset + NB_SENDER_NAME + 10, 6,
688 "Sender's MAC Address: %s",
689 ether_to_str( tvb_get_ptr( tvb,offset + NB_SENDER_NAME + 10, 6)));
691 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
700 dissect_netb_datagram_bcast( tvbuff_t *tvb, int offset, proto_tree *tree)
702 {/* Handle the DATAGRAM BROADCAST command */
704 /* We assume the same weirdness can happen here.... */
705 if ( memcmp( tvb_get_ptr( tvb,offset + NB_SENDER_NAME + 10, 6), zeroes, 10) == 0) {
706 proto_tree_add_text( tree, tvb, offset + NB_SENDER_NAME + 10, 6,
707 "Sender's Node Address: %s",
708 ether_to_str( tvb_get_ptr( tvb,offset + NB_SENDER_NAME + 10, 6)));
710 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
719 dissect_netb_name_query( tvbuff_t *tvb, int offset, proto_tree *tree)
721 {/* Handle the NAME QUERY command */
722 guint8 local_session_number = tvb_get_guint8( tvb, offset + NB_DATA2);
724 if (local_session_number == 0) {
725 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
726 "Local Session No.: 0 (FIND.NAME request)");
728 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
729 "Local Session No.: 0x%02x", local_session_number);
731 nb_call_name_type( tvb, offset, tree);
732 nb_resp_corrl( tvb, offset, tree);
733 netbios_add_name("Query Name", tvb, offset + NB_RECVER_NAME, tree);
734 if (local_session_number != 0) {
735 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
744 dissect_netb_add_name_resp( tvbuff_t *tvb, int offset, proto_tree *tree)
746 {/* Handle the ADD NAME RESPONSE command */
748 nb_data1( hf_netb_status, tvb, offset, tree);
749 nb_data2( hf_netb_name_type, tvb, offset, tree);
750 nb_xmit_corrl( tvb, offset, tree);
751 netbios_add_name("Name to be added", tvb, offset + NB_RECVER_NAME,
753 netbios_add_name("Name to be added", tvb, offset + NB_SENDER_NAME,
761 dissect_netb_name_resp( tvbuff_t *tvb, int offset, proto_tree *tree)
763 {/* Handle the NAME RECOGNIZED command */
764 guint8 local_session_number = tvb_get_guint8( tvb, offset + NB_DATA2);
766 switch (local_session_number) {
769 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
770 "State of name: No LISTEN pending, or FIND.NAME response");
774 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
775 "State of name: LISTEN pending, but insufficient resources to establish session");
779 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
780 "Local Session No.: 0x%02x", local_session_number);
783 nb_call_name_type( tvb, offset, tree);
784 nb_xmit_corrl( tvb, offset, tree);
785 if (local_session_number != 0x00 && local_session_number != 0xFF)
786 nb_resp_corrl(tvb, offset, tree);
787 netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
788 if (local_session_number != 0x00 && local_session_number != 0xFF) {
789 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
798 dissect_netb_status_resp( tvbuff_t *tvb, int offset, proto_tree *tree)
800 {/* Handle the STATUS RESPONSE command */
801 guint8 status_response = tvb_get_guint8( tvb, offset + NB_DATA1);
803 proto_tree *data2_tree;
806 nb_call_name_type( tvb, offset, tree);
807 if (status_response == 0) {
808 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
809 "Status response: NetBIOS 1.x or 2.0");
811 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
812 "Status response: NetBIOS 2.1, %u names sent so far",
815 data2 = tvb_get_letohs( tvb, offset + NB_DATA2);
817 td2 = proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2, "Status: 0x%04x",
819 data2_tree = proto_item_add_subtree(td2, ett_netb_status);
820 if (data2 & 0x8000) {
821 proto_tree_add_text(data2_tree, tvb, offset, 2, "%s",
822 decode_boolean_bitfield(data2, 0x8000, 8*2,
823 "Data length exceeds maximum frame size", NULL));
825 if (data2 & 0x4000) {
826 proto_tree_add_text(data2_tree, tvb, offset, 2, "%s",
827 decode_boolean_bitfield(data2, 0x4000, 8*2,
828 "Data length exceeds user's buffer", NULL));
830 proto_tree_add_text(data2_tree, tvb, offset, 2, "%s",
831 decode_numeric_bitfield(data2, 0x3FFF, 2*8,
832 "Status data length = %u"));
833 nb_xmit_corrl( tvb, offset, tree);
834 netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
835 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
843 dissect_netb_data_ack( tvbuff_t* tvb, int offset, proto_tree *tree)
845 {/* Handle the DATA ACK command */
847 nb_xmit_corrl( tvb, offset, tree);
848 nb_remote_session( tvb, offset, tree);
849 nb_local_session( tvb, offset, tree);
856 dissect_netb_data_first_middle( tvbuff_t *tvb, int offset, proto_tree *tree)
858 {/* Handle the DATA FIRST MIDDLE command */
860 guint8 remote_session, local_session;
863 * This is the first frame, or the middle frame, of a fragmented
866 * XXX - there are no sequence numbers, so we have to assume
867 * that fragments arrive in order with no duplicates.
868 * In fact, 802.2 LLC is supposed to handle that, so we
869 * might have to have the LLC dissector do so (but the TCP
870 * dissector doesn't currently handle out-of-order or duplicate
874 netbios_data_first_middle_flags( tvb, tree, offset + NB_FLAGS);
876 nb_resync_indicator( tvb, offset, tree, "DATA FIRST MIDDLE");
877 nb_xmit_corrl( tvb, offset, tree);
878 nb_resp_corrl( tvb, offset, tree);
879 remote_session = nb_remote_session( tvb, offset, tree);
880 local_session = nb_local_session( tvb, offset, tree);
883 * Return a combination of the remote and local session numbers,
884 * for use when reassembling.
886 return (remote_session << 8) + local_session;
891 dissect_netb_data_only_last( tvbuff_t *tvb, int offset, proto_tree *tree)
893 {/* Handle the DATA ONLY LAST command */
895 guint8 remote_session, local_session;
898 * This is a complete packet, or the last frame of a fragmented
902 netbios_data_only_flags( tvb, tree, offset + NB_FLAGS);
904 nb_resync_indicator( tvb, offset, tree, "DATA ONLY LAST");
905 nb_xmit_corrl( tvb, offset, tree);
906 nb_resp_corrl( tvb, offset, tree);
907 remote_session = nb_remote_session( tvb, offset, tree);
908 local_session = nb_local_session( tvb, offset, tree);
911 * Return a combination of the remote and local session numbers,
912 * for use when reassembling.
914 return (remote_session << 8) + local_session;
919 dissect_netb_session_confirm( tvbuff_t *tvb, int offset, proto_tree *tree)
921 {/* Handle the SESSION CONFIRM command */
923 netbios_add_ses_confirm_flags( tvb, tree, offset + NB_FLAGS);
925 nb_data2( hf_netb_max_data_recv_size, tvb, offset, tree);
926 nb_xmit_corrl( tvb, offset, tree);
927 nb_resp_corrl( tvb, offset, tree);
928 nb_remote_session( tvb, offset, tree);
929 nb_local_session( tvb, offset, tree);
936 dissect_netb_session_end( tvbuff_t *tvb, int offset, proto_tree *tree)
938 {/* Handle the SESSION END command */
940 nb_data2( hf_netb_termination_indicator, tvb, offset, tree);
941 nb_remote_session( tvb, offset, tree);
942 nb_local_session( tvb, offset, tree);
949 dissect_netb_session_init( tvbuff_t *tvb, int offset, proto_tree *tree)
951 {/* Handle the SESSION INITIALIZE command */
953 netbios_add_session_init_flags( tvb, tree, offset + NB_FLAGS);
955 nb_data2( hf_netb_max_data_recv_size, tvb, offset, tree);
956 nb_resp_corrl( tvb, offset, tree);
957 nb_xmit_corrl( tvb, offset, tree);
958 nb_remote_session( tvb, offset, tree);
959 nb_local_session( tvb, offset, tree);
965 dissect_netb_no_receive( tvbuff_t *tvb, int offset, proto_tree *tree)
967 {/* Handle the NO RECEIVE command */
969 netbios_no_receive_flags( tvb, tree, offset + NB_FLAGS);
971 nb_data2( hf_netb_num_data_bytes_accepted, tvb, offset, tree);
972 nb_remote_session( tvb, offset, tree);
973 nb_local_session( tvb, offset, tree);
980 dissect_netb_receive_outstanding( tvbuff_t *tvb, int offset, proto_tree *tree)
982 {/* Handle the RECEIVE OUTSTANDING command */
984 nb_data2( hf_netb_num_data_bytes_accepted, tvb, offset, tree);
985 nb_remote_session( tvb, offset, tree);
986 nb_local_session( tvb, offset, tree);
993 dissect_netb_receive_continue( tvbuff_t *tvb, int offset, proto_tree *tree)
995 {/* Handle the RECEIVE CONTINUE command */
997 nb_xmit_corrl( tvb, offset, tree);
998 nb_remote_session( tvb, offset, tree);
999 nb_local_session( tvb, offset, tree);
1006 dissect_netb_session_alive( tvbuff_t *tvb, int offset, proto_tree *tree)
1008 {/* Handle the SESSION ALIVE command */
1011 * XXX - all the fields are claimed to be "Reserved", but
1012 * the session numbers appear to be non-zero in at least
1013 * one capture, and they do appear to match session numbers
1014 * in other messages, and I'd expect that you had to identify
1015 * sessions in this message in any case.
1017 * We show only those fields.
1019 nb_remote_session( tvb, offset, tree);
1020 nb_local_session( tvb, offset, tree);
1026 /************************************************************************/
1028 /* The table routines called by the top level to handle commands */
1030 /************************************************************************/
1033 static guint32 (*dissect_netb[])(tvbuff_t *, int, proto_tree *) = {
1035 dissect_netb_add_group_name, /* Add Group Name 0x00 */
1036 dissect_netb_add_name, /* Add Name 0x01 */
1037 dissect_netb_name_in_conflict,/* Name In Conflict 0x02 */
1038 dissect_netb_status_query, /* Status Query 0x03 */
1039 dissect_netb_unknown, /* unknown 0x04 */
1040 dissect_netb_unknown, /* unknown 0x05 */
1041 dissect_netb_unknown, /* unknown 0x06 */
1042 dissect_netb_terminate_trace, /* Terminate Trace 0x07 */
1043 dissect_netb_datagram, /* Datagram 0x08 */
1044 dissect_netb_datagram_bcast, /* Datagram Broadcast 0x09 */
1045 dissect_netb_name_query, /* Name Query 0x0A */
1046 dissect_netb_unknown, /* unknown 0x0B */
1047 dissect_netb_unknown, /* unknown 0x0C */
1048 dissect_netb_add_name_resp, /* Add Name Response 0x0D */
1049 dissect_netb_name_resp, /* Name Recognized 0x0E */
1050 dissect_netb_status_resp, /* Status Response 0x0F */
1051 dissect_netb_unknown, /* unknown 0x10 */
1052 dissect_netb_unknown, /* unknown 0x11 */
1053 dissect_netb_unknown, /* unknown 0x12 */
1054 dissect_netb_terminate_trace, /* Terminate Trace 0x13 */
1055 dissect_netb_data_ack, /* Data Ack 0x14 */
1056 dissect_netb_data_first_middle,/* Data First Middle 0x15 */
1057 dissect_netb_data_only_last, /* Data Only Last 0x16 */
1058 dissect_netb_session_confirm, /* Session Confirm 0x17 */
1059 dissect_netb_session_end, /* Session End 0x18 */
1060 dissect_netb_session_init, /* Session Initialize 0x19 */
1061 dissect_netb_no_receive, /* No Receive 0x1A */
1062 dissect_netb_receive_outstanding,/* Receive Outstanding 0x1B */
1063 dissect_netb_receive_continue,/* Receive Continue 0x1C */
1064 dissect_netb_unknown, /* unknown 0x1D */
1065 dissect_netb_unknown, /* unknown 0x1E */
1066 dissect_netb_session_alive, /* Session Alive 0x1f */
1067 dissect_netb_unknown,
1070 static heur_dissector_list_t netbios_heur_subdissector_list;
1073 dissect_netbios_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1076 * Try the heuristic dissectors for NetBIOS; if none of them
1077 * accept the packet, dissect it as data.
1079 if (!dissector_try_heuristic(netbios_heur_subdissector_list,
1081 call_dissector(data_handle,tvb, pinfo, tree);
1085 dissect_netbios(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1088 proto_tree *netb_tree = NULL;
1090 guint16 hdr_len, command;
1091 const char *command_name;
1092 char name[(NETBIOS_NAME_LEN - 1)*4 + 1];
1095 gboolean save_fragmented;
1097 fragment_data *fd_head;
1102 /* load the display labels */
1103 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NetBIOS");
1106 /* Find NetBIOS marker EFFF, this is done because I have seen an extra LLC */
1107 /* byte on our network. This only checks for one extra LLC byte. */
1109 if ( 0xefff != tvb_get_letohs(tvb, 2)){
1111 if ( 0xefff != tvb_get_letohs(tvb, 3)){
1113 /* print bad packet */
1114 col_set_str( pinfo->cinfo, COL_INFO, "Bad packet, no 0xEFFF marker");
1116 return; /* this is an unknown packet, no marker */
1121 hdr_len = tvb_get_letohs(tvb, offset + NB_LENGTH);
1122 command = tvb_get_guint8( tvb, offset + NB_COMMAND);
1123 /* limit command so no table overflows */
1124 command = MIN( command, sizeof( dissect_netb)/ sizeof(void *));
1126 if (check_col( pinfo->cinfo, COL_INFO)) { /* print command name */
1127 command_name = val_to_str(command, cmd_vals, "Unknown (0x%02x)");
1128 switch ( command ) {
1130 name_type = get_netbios_name( tvb, offset + 12, name, (NETBIOS_NAME_LEN - 1)*4 + 1);
1131 col_add_fstr( pinfo->cinfo, COL_INFO, "%s for %s<%02x>",
1132 command_name, name, name_type);
1138 name_type = get_netbios_name( tvb, offset + 28, name, (NETBIOS_NAME_LEN - 1)*4 + 1);
1139 col_add_fstr( pinfo->cinfo, COL_INFO, "%s - %s<%02x>",
1140 command_name, name, name_type);
1144 col_add_str( pinfo->cinfo, COL_INFO,
1151 ti = proto_tree_add_item(tree, proto_netbios, tvb, 0, hdr_len, FALSE);
1152 netb_tree = proto_item_add_subtree(ti, ett_netb);
1154 proto_tree_add_uint_format(netb_tree, hf_netb_hdr_len, tvb, offset, 2, hdr_len,
1155 "Length: %d bytes", hdr_len);
1157 proto_tree_add_text(netb_tree, tvb, offset + 2, 2,
1158 "Delimiter: EFFF (NetBIOS)");
1160 proto_tree_add_uint(netb_tree, hf_netb_cmd, tvb, offset + NB_COMMAND, 1, command);
1163 /* if command in table range */
1164 if ( command < sizeof( dissect_netb)/ sizeof(void *)) {
1166 /* branch to handle commands */
1167 session_id = (dissect_netb[ command])( tvb, offset, netb_tree);
1169 offset += hdr_len; /* move past header */
1171 save_fragmented = pinfo->fragmented;
1174 * Process user data in frames that have it.
1179 case NB_DATAGRAM_BCAST:
1181 * No fragmentation here.
1183 next_tvb = tvb_new_subset_remaining(tvb, offset);
1184 dissect_netbios_payload(next_tvb, pinfo, tree);
1187 case NB_DATA_FIRST_MIDDLE:
1188 case NB_DATA_ONLY_LAST:
1190 * Possibly fragmented.
1192 len = tvb_reported_length_remaining(tvb, offset);
1193 if (netbios_defragment &&
1194 tvb_bytes_exist(tvb, offset, len)) {
1195 fd_head = fragment_add_seq_next(tvb, offset,
1197 netbios_fragment_table,
1198 netbios_reassembled_table,
1199 len, command == NB_DATA_FIRST_MIDDLE);
1200 if (fd_head != NULL) {
1201 if (fd_head->next != NULL) {
1202 next_tvb = tvb_new_child_real_data(tvb, fd_head->data,
1203 fd_head->len, fd_head->len);
1204 add_new_data_source(pinfo,
1206 "Reassembled NetBIOS");
1207 /* Show all fragments. */
1209 proto_item *frag_tree_item;
1211 show_fragment_seq_tree(fd_head,
1212 &netbios_frag_items,
1214 next_tvb, &frag_tree_item);
1217 next_tvb = tvb_new_subset_remaining(tvb,
1225 * Dissect this, regardless of whether
1226 * it's NB_DATA_FIRST_MIDDLE or
1227 * NB_DATA_ONLY_LAST.
1229 * XXX - it'd be nice to show
1230 * NB_DATA_FIRST_MIDDLE as a fragment
1231 * if it's not the first fragment (i.e.,
1232 * MIDDLE rather than FIRST), and show
1233 * NB_DATA_ONLY_LAST as a fragment if
1234 * it's part of a fragmented datagram
1235 * (i.e, LAST rather than ONLY), but
1236 * we'd have to do reassembly to
1237 * be able to determine that.
1239 next_tvb = tvb_new_subset_remaining(tvb, offset);
1241 if (next_tvb != NULL)
1242 dissect_netbios_payload(next_tvb, pinfo, tree);
1244 next_tvb = tvb_new_subset_remaining (tvb, offset);
1245 call_dissector(data_handle, next_tvb, pinfo,
1257 * Initialize the fragment and reassembly tables.
1259 fragment_table_init(&netbios_fragment_table);
1260 reassembled_table_init(&netbios_reassembled_table);
1263 void proto_register_netbios(void)
1265 static gint *ett[] = {
1270 &ett_netb_fragments,
1274 static hf_register_info hf_netb[] = {
1276 { "Command", "netbios.command", FT_UINT8, BASE_HEX, VALS(cmd_vals), 0x0,
1280 { "Header Length", "netbios.hdr_len", FT_UINT16, BASE_DEC, NULL, 0x0,
1283 { &hf_netb_xmit_corrl,
1284 { "Transmit Correlator", "netbios.xmit_corrl", FT_UINT16, BASE_HEX, NULL, 0x0,
1287 { &hf_netb_resp_corrl,
1288 { "Response Correlator", "netbios.resp_corrl", FT_UINT16, BASE_HEX, NULL, 0x0,
1291 { &hf_netb_call_name_type,
1292 { "Caller's Name Type", "netbios.call_name_type", FT_UINT8, BASE_HEX, VALS(name_types), 0x0,
1295 { &hf_netb_nb_name_type,
1296 { "NetBIOS Name Type", "netbios.nb_name_type", FT_UINT8, BASE_HEX, VALS(nb_name_type_vals), 0x0,
1300 { "NetBIOS Name", "netbios.nb_name", FT_STRING, BASE_NONE, NULL, 0x0,
1304 { "Acknowledge", "netbios.ack", FT_BOOLEAN, 8, TFS( &tfs_set_notset), 0x08,
1307 { &hf_netb_ack_with_data,
1308 { "Acknowledge with data", "netbios.ack_with_data", FT_BOOLEAN, 8, TFS( &flags_allowed), 0x04,
1311 { &hf_netb_ack_expected,
1312 { "Acknowledge expected", "netbios.ack_expected", FT_BOOLEAN, 8,
1313 TFS( &tfs_yes_no), 0x02, NULL, HFILL }},
1315 { &hf_netb_recv_cont_req,
1316 { "RECEIVE_CONTINUE requested", "netbios.recv_cont_req", FT_BOOLEAN, 8,
1317 TFS( &tfs_yes_no), 0x01, NULL, HFILL }},
1319 { &hf_netb_send_no_ack,
1320 { "Handle SEND.NO.ACK", "netbios.send_no_ack", FT_BOOLEAN, 8,
1321 TFS( &tfs_yes_no), 0x80, NULL, HFILL }},
1324 { "NetBIOS Version", "netbios.version", FT_BOOLEAN, 8,
1325 TFS( &netb_version_str), 0x01, NULL, HFILL }},
1327 { &hf_netb_largest_frame,
1328 { "Largest Frame", "netbios.largest_frame", FT_UINT8, BASE_DEC, VALS(max_frame_size_vals), 0x0E,
1331 { &hf_netb_status_buffer_len,
1332 { "Length of status buffer", "netbios.status_buffer_len", FT_UINT16, BASE_DEC, NULL, 0x0,
1336 { "Status", "netbios.status", FT_UINT8, BASE_DEC, VALS(status_vals), 0x0,
1339 { &hf_netb_name_type,
1340 { "Name type", "netbios.name_type", FT_UINT16, BASE_DEC, VALS(name_types), 0x0,
1343 { &hf_netb_max_data_recv_size,
1344 { "Maximum data receive size", "netbios.max_data_recv_size", FT_UINT16, BASE_DEC, NULL, 0x0,
1347 { &hf_netb_termination_indicator,
1348 { "Termination indicator", "netbios.termination_indicator", FT_UINT16, BASE_HEX, VALS(termination_indicator_vals), 0x0,
1351 { &hf_netb_num_data_bytes_accepted,
1352 { "Number of data bytes accepted", "netbios.num_data_bytes_accepted", FT_UINT16, BASE_DEC, NULL, 0x0,
1355 { &hf_netb_local_ses_no,
1356 { "Local Session No.", "netbios.local_session", FT_UINT8, BASE_HEX, NULL, 0x0,
1359 { &hf_netb_remote_ses_no,
1360 { "Remote Session No.", "netbios.remote_session", FT_UINT8, BASE_HEX, NULL, 0x0,
1364 { "DATA1 value", "netbios.data1", FT_UINT8, BASE_HEX, NULL, 0x0,
1368 { "DATA2 value", "netbios.data2", FT_UINT16, BASE_HEX, NULL, 0x0,
1371 { &hf_netb_fragment_overlap,
1372 { "Fragment overlap", "netbios.fragment.overlap", FT_BOOLEAN, BASE_NONE,
1373 NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
1375 { &hf_netb_fragment_overlap_conflict,
1376 { "Conflicting data in fragment overlap", "netbios.fragment.overlap.conflict",
1377 FT_BOOLEAN, BASE_NONE,
1378 NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
1380 { &hf_netb_fragment_multiple_tails,
1381 { "Multiple tail fragments found", "netbios.fragment.multipletails",
1382 FT_BOOLEAN, BASE_NONE,
1383 NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
1385 { &hf_netb_fragment_too_long_fragment,
1386 { "Fragment too long", "netbios.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE,
1387 NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
1389 { &hf_netb_fragment_error,
1390 {"Defragmentation error", "netbios.fragment.error", FT_FRAMENUM, BASE_NONE,
1391 NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
1393 { &hf_netb_fragment,
1394 { "NetBIOS Fragment", "netbios.fragment", FT_FRAMENUM, BASE_NONE,
1395 NULL, 0x0, NULL, HFILL }},
1397 { &hf_netb_fragments,
1398 { "NetBIOS Fragments", "netbios.fragments", FT_NONE, BASE_NONE,
1399 NULL, 0x0, NULL, HFILL }},
1401 { &hf_netb_reassembled_length,
1402 {"Reassembled NetBIOS length", "netbios.reassembled.length", FT_UINT32, BASE_DEC,
1403 NULL, 0x0, "The total length of the reassembled payload", HFILL }},
1405 module_t *netbios_module;
1407 proto_netbios = proto_register_protocol("NetBIOS", "NetBIOS", "netbios");
1408 proto_register_subtree_array(ett, array_length(ett));
1409 proto_register_field_array(proto_netbios, hf_netb, array_length(hf_netb));
1411 register_heur_dissector_list("netbios", &netbios_heur_subdissector_list);
1413 netbios_module = prefs_register_protocol(proto_netbios, NULL);
1414 prefs_register_bool_preference(netbios_module, "defragment",
1415 "Reassemble fragmented NetBIOS messages spanning multiple frames",
1416 "Whether the NetBIOS dissector should defragment messages spanning multiple frames",
1417 &netbios_defragment);
1419 register_init_routine(netbios_init);
1423 proto_reg_handoff_netbios(void)
1425 dissector_handle_t netbios_handle;
1427 netbios_handle = create_dissector_handle(dissect_netbios,
1429 dissector_add("llc.dsap", SAP_NETBIOS, netbios_handle);
1430 data_handle = find_dissector("data");