Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-netbios.c
blob638bac53396e50420892edac85ff6d4e410e84f4
1 /* packet-netbios.c
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 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "config.h"
17 #include <epan/packet.h>
18 #include <epan/capture_dissectors.h>
19 #include <epan/llcsaps.h>
20 #include <epan/reassemble.h>
21 #include <epan/prefs.h>
22 #include <epan/expert.h>
23 #include <epan/tfs.h>
24 #include <wsutil/array.h>
25 #include "packet-netbios.h"
27 void proto_register_netbios(void);
28 void proto_reg_handoff_netbios(void);
30 static dissector_handle_t netbios_handle;
31 static capture_dissector_handle_t netbios_cap_handle;
33 /* Netbios command numbers */
34 #define NB_ADD_GROUP 0x00
35 #define NB_ADD_NAME 0x01
36 #define NB_NAME_IN_CONFLICT 0x02
37 #define NB_STATUS_QUERY 0x03
38 #define NB_TERMINATE_TRACE_R 0x07
39 #define NB_DATAGRAM 0x08
40 #define NB_DATAGRAM_BCAST 0x09
41 #define NB_NAME_QUERY 0x0a
42 #define NB_ADD_NAME_RESP 0x0d
43 #define NB_NAME_RESP 0x0e
44 #define NB_STATUS_RESP 0x0f
45 #define NB_TERMINATE_TRACE_LR 0x13
46 #define NB_DATA_ACK 0x14
47 #define NB_DATA_FIRST_MIDDLE 0x15
48 #define NB_DATA_ONLY_LAST 0x16
49 #define NB_SESSION_CONFIRM 0x17
50 #define NB_SESSION_END 0x18
51 #define NB_SESSION_INIT 0x19
52 #define NB_NO_RECEIVE 0x1a
53 #define NB_RECEIVE_OUTSTANDING 0x1b
54 #define NB_RECEIVE_CONTINUE 0x1c
55 #define NB_KEEP_ALIVE 0x1f
57 /* Offsets of fields in the NetBIOS header. */
58 #define NB_LENGTH 0
59 #define NB_DELIMITER 2
60 #define NB_COMMAND 4
61 #define NB_FLAGS 5
62 #define NB_DATA1 5
63 #define NB_RESYNC 6
64 #define NB_DATA2 6
65 #define NB_CALL_NAME_TYPE 7
66 #define NB_XMIT_CORL 8
67 #define NB_RESP_CORL 10
68 #define NB_RMT_SES 12
69 #define NB_LOCAL_SES 13
70 #define NB_RECVER_NAME 12
71 #define NB_SENDER_NAME 28
74 static int proto_netbios;
75 static int hf_netb_cmd;
76 static int hf_netb_hdr_len;
77 static int hf_netb_delimiter;
78 static int hf_netb_xmit_corrl;
79 static int hf_netb_resp_corrl;
80 static int hf_netb_call_name_type;
81 static int hf_netb_version;
82 static int hf_netbios_no_receive_flags;
83 static int hf_netbios_no_receive_flags_send_no_ack;
84 static int hf_netb_largest_frame;
85 static int hf_netb_nb_name;
86 static int hf_netb_nb_name_type;
87 static int hf_netb_status_buffer_len;
88 static int hf_netb_status;
89 static int hf_netb_name_type;
90 static int hf_netb_max_data_recv_size;
91 static int hf_netb_termination_indicator;
92 static int hf_netb_num_data_bytes_accepted;
93 static int hf_netb_local_ses_no;
94 static int hf_netb_remote_ses_no;
95 static int hf_netb_flags;
96 static int hf_netb_flags_send_no_ack;
97 static int hf_netb_flags_ack;
98 static int hf_netb_flags_ack_with_data;
99 static int hf_netb_flags_ack_expected;
100 static int hf_netb_flags_recv_cont_req;
101 static int hf_netb_data2;
102 static int hf_netb_data2_frame;
103 static int hf_netb_data2_user;
104 static int hf_netb_data2_status;
105 static int hf_netb_datagram_mac;
106 static int hf_netb_datagram_bcast_mac;
107 static int hf_netb_resync_indicator;
108 static int hf_netb_status_request;
109 static int hf_netb_local_session_no;
110 static int hf_netb_state_of_name;
111 static int hf_netb_status_response;
112 static int hf_netb_fragments;
113 static int hf_netb_fragment;
114 static int hf_netb_fragment_overlap;
115 static int hf_netb_fragment_overlap_conflict;
116 static int hf_netb_fragment_multiple_tails;
117 static int hf_netb_fragment_too_long_fragment;
118 static int hf_netb_fragment_error;
119 static int hf_netb_fragment_count;
120 static int hf_netb_reassembled_length;
122 static int ett_netb;
123 static int ett_netb_name;
124 static int ett_netb_flags;
125 static int ett_netb_status;
126 static int ett_netb_fragments;
127 static int ett_netb_fragment;
129 static expert_field ei_netb_unknown_command_data;
131 static const fragment_items netbios_frag_items = {
132 &ett_netb_fragment,
133 &ett_netb_fragments,
134 &hf_netb_fragments,
135 &hf_netb_fragment,
136 &hf_netb_fragment_overlap,
137 &hf_netb_fragment_overlap_conflict,
138 &hf_netb_fragment_multiple_tails,
139 &hf_netb_fragment_too_long_fragment,
140 &hf_netb_fragment_error,
141 &hf_netb_fragment_count,
142 NULL,
143 &hf_netb_reassembled_length,
144 /* Reassembled data field */
145 NULL,
146 "fragments"
149 /* The strings for the station type, used by get_netbios_name function;
150 many of them came from the file "NetBIOS.txt" in the Zip archive at
152 http://www.net3group.com/ftp/browser.zip
155 static const value_string nb_name_type_vals[] = {
156 {0x00, "Workstation/Redirector"},
157 {0x01, "Browser"},
158 {0x02, "Workstation/Redirector"},
159 /* not sure what 0x02 is, I'm seeing a lot of them however */
160 /* I'm seeing them with workstation/redirection host
161 announcements */
162 {0x03, "Messenger service/Main name"},
163 {0x05, "Forwarded name"},
164 {0x06, "RAS Server service"},
165 {0x1b, "Domain Master Browser"},
166 {0x1c, "Domain Controllers"},
167 {0x1d, "Local Master Browser"},
168 {0x1e, "Browser Election Service"},
169 {0x1f, "Net DDE Service"},
170 {0x20, "Server service"},
171 {0x21, "RAS client service"},
172 {0x22, "Exchange Interchange (MSMail Connector)"},
173 {0x23, "Exchange Store"},
174 {0x24, "Exchange Directory"},
175 {0x2b, "Lotus Notes Server service"},
176 {0x30, "Modem sharing server service"},
177 {0x31, "Modem sharing client service"},
178 {0x43, "SMS Clients Remote Control"},
179 {0x44, "SMS Administrators Remote Control Tool"},
180 {0x45, "SMS Clients Remote Chat"},
181 {0x46, "SMS Clients Remote Transfer"},
182 {0x4c, "DEC Pathworks TCP/IP Service on Windows NT"},
183 {0x52, "DEC Pathworks TCP/IP Service on Windows NT"},
184 {0x6a, "Microsoft Exchange IMC"},
185 {0x87, "Microsoft Exchange MTA"},
186 {0xbe, "Network Monitor Agent"},
187 {0xbf, "Network Monitor Analyzer"},
188 {0x00, NULL}
190 static value_string_ext nb_name_type_vals_ext = VALUE_STRING_EXT_INIT(nb_name_type_vals);
192 /* Table for reassembly of fragments. */
193 static reassembly_table netbios_reassembly_table;
195 /* defragmentation of NetBIOS Frame */
196 static bool netbios_defragment = true;
198 /* See
200 http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/BK8P7001/CCONTENTS
204 http://ourworld.compuserve.com/homepages/TimothyDEvans/contents.htm
206 for information about the NetBIOS Frame Protocol (which is what this
207 module dissects). */
209 /* the strings for the command types */
211 static const value_string cmd_vals[] = {
212 { NB_ADD_GROUP, "Add Group Name Query" },
213 { NB_ADD_NAME, "Add Name Query" },
214 { NB_NAME_IN_CONFLICT, "Name In Conflict" },
215 { NB_STATUS_QUERY, "Status Query" },
216 { NB_TERMINATE_TRACE_R, "Terminate Trace" },
217 { NB_DATAGRAM, "Datagram" },
218 { NB_DATAGRAM_BCAST, "Broadcast Datagram" },
219 { NB_NAME_QUERY, "Name Query" },
220 { NB_ADD_NAME_RESP, "Add Name Response" },
221 { NB_NAME_RESP, "Name Recognized" },
222 { NB_STATUS_RESP, "Status Response" },
223 { NB_TERMINATE_TRACE_LR, "Terminate Trace" },
224 { NB_DATA_ACK, "Data Ack" },
225 { NB_DATA_FIRST_MIDDLE, "Data First Middle" },
226 { NB_DATA_ONLY_LAST, "Data Only Last" },
227 { NB_SESSION_CONFIRM, "Session Confirm" },
228 { NB_SESSION_END, "Session End" },
229 { NB_SESSION_INIT, "Session Initialize" },
230 { NB_NO_RECEIVE, "No Receive" },
231 { NB_RECEIVE_OUTSTANDING, "Receive Outstanding" },
232 { NB_RECEIVE_CONTINUE, "Receive Continue" },
233 { NB_KEEP_ALIVE, "Session Alive" },
234 { 0, NULL }
236 static value_string_ext cmd_vals_ext = VALUE_STRING_EXT_INIT(cmd_vals);
238 static const value_string name_types[] = {
239 { 0, "Unique name" },
240 { 1, "Group name" },
241 { 0, NULL }
245 static const true_false_string netb_version_str = {
246 "2.00 or higher",
247 "1.xx"
250 static const value_string termination_indicator_vals[] = {
251 { 0x0000, "Normal session end" },
252 { 0x0001, "Abnormal session end" },
253 { 0, NULL }
256 static const value_string status_vals[] = {
257 { 0, "Add name not in process" },
258 { 1, "Add name in process" },
259 { 0, NULL }
262 static const value_string max_frame_size_vals[] = {
263 { 0, "516" },
264 { 1, "1500" },
265 { 2, "2052" },
266 { 3, "4472" },
267 { 4, "8144" },
268 { 5, "11407" },
269 { 6, "17800" }, /* 17800 in TR spec, 17749 in NBF spec */
270 { 7, "65535" },
271 { 0, NULL }
275 static bool
276 capture_netbios(const unsigned char *pd _U_, int offset _U_, int len _U_, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_)
278 capture_dissector_increment_count(cpinfo, proto_netbios);
279 return true;
284 process_netbios_name(const unsigned char *name_ptr, char *name_ret, int name_ret_len)
286 int i;
287 int name_type = *(name_ptr + NETBIOS_NAME_LEN - 1);
288 unsigned char name_char;
289 char *name_ret_orig = name_ret;
290 static const char hex_digits[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
292 for (i = 0; i < NETBIOS_NAME_LEN - 1; i++) {
293 name_char = *name_ptr++;
294 if (name_char >= ' ' && name_char <= '~') {
295 if (--name_ret_len > 0)
296 *name_ret++ = name_char;
297 } else {
298 /* It's not printable; show it as <XX>, where
299 XX is the value in hex. */
300 if (--name_ret_len > 0)
301 *name_ret++ = '<';
302 if (--name_ret_len > 0)
303 *name_ret++ = hex_digits[(name_char >> 4)];
304 if (--name_ret_len > 0)
305 *name_ret++ = hex_digits[(name_char & 0x0F)];
306 if (--name_ret_len > 0)
307 *name_ret++ = '>';
310 *name_ret = '\0';
312 /* Remove trailing space characters from name. */
314 name_ret--;
316 while (name_ret >= name_ret_orig) {
317 if (*name_ret != ' ') {
318 *(name_ret + 1) = 0;
319 break;
321 name_ret--;
324 return name_type;
329 get_netbios_name( tvbuff_t *tvb, int offset, char *name_ret, int name_ret_len)
331 {/* Extract the name string and name type. Return the name string in */
332 /* name_ret and return the name_type. */
334 return process_netbios_name( tvb_get_ptr( tvb, offset, NETBIOS_NAME_LEN ), name_ret, name_ret_len);
339 * Get a string describing the type of a NetBIOS name.
341 const char *
342 netbios_name_type_descr(int name_type)
345 return val_to_str_ext_const(name_type, &nb_name_type_vals_ext, "Unknown");
348 void
349 netbios_add_name(const char* label, tvbuff_t *tvb, int offset, proto_tree *tree)
351 {/* add a name field display tree. Display the name and station type in sub-tree */
353 proto_tree *field_tree;
354 char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
355 int name_type;
356 const char *name_type_str;
358 /* decode the name field */
359 name_type = get_netbios_name( tvb, offset, name_str, (NETBIOS_NAME_LEN - 1)*4 + 1);
360 name_type_str = netbios_name_type_descr(name_type);
361 field_tree = proto_tree_add_subtree_format( tree, tvb, offset, NETBIOS_NAME_LEN,
362 ett_netb_name, NULL, "%s: %s<%02x> (%s)", label, name_str, name_type, name_type_str);
364 proto_tree_add_string_format( field_tree, hf_netb_nb_name, tvb, offset,
365 15, name_str, "%s", name_str);
366 proto_tree_add_uint_format( field_tree, hf_netb_nb_name_type, tvb, offset + 15, 1, name_type,
367 "0x%02x (%s)", name_type, name_type_str);
371 static void
372 netbios_data_first_middle_flags( tvbuff_t *tvb, proto_tree *tree, int offset)
375 proto_tree *field_tree;
376 proto_item *tf;
378 /* decode the flag field for Data First Middle packet*/
380 tf = proto_tree_add_item(tree, hf_netb_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
381 field_tree = proto_item_add_subtree(tf, ett_netb_flags);
383 proto_tree_add_item( field_tree, hf_netb_flags_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
385 proto_tree_add_item( field_tree, hf_netb_flags_ack_expected, tvb, offset, 1, ENC_LITTLE_ENDIAN);
387 proto_tree_add_item( field_tree, hf_netb_flags_recv_cont_req, tvb, offset, 1, ENC_LITTLE_ENDIAN);
390 static void
391 netbios_data_only_flags( tvbuff_t *tvb, proto_tree *tree, int offset)
394 proto_tree *field_tree;
395 proto_item *tf;
397 /* decode the flag field for Data Only Last packet*/
398 tf = proto_tree_add_item(tree, hf_netb_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
399 field_tree = proto_item_add_subtree(tf, ett_netb_flags);
401 proto_tree_add_item( field_tree, hf_netb_flags_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
403 proto_tree_add_item( field_tree, hf_netb_flags_ack_with_data, tvb, offset, 1, ENC_LITTLE_ENDIAN);
405 proto_tree_add_item( field_tree, hf_netb_flags_ack_expected, tvb, offset, 1, ENC_LITTLE_ENDIAN);
410 static void
411 netbios_add_ses_confirm_flags( tvbuff_t *tvb, proto_tree *tree, int offset)
414 proto_tree *field_tree;
415 proto_item *tf;
417 /* decode the flag field for Session Confirm packet */
418 tf = proto_tree_add_item(tree, hf_netb_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
419 field_tree = proto_item_add_subtree( tf, ett_netb_flags);
421 proto_tree_add_item( field_tree, hf_netb_flags_send_no_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
423 proto_tree_add_item( field_tree, hf_netb_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
427 static void
428 netbios_add_session_init_flags( tvbuff_t *tvb, proto_tree *tree, int offset)
431 proto_tree *field_tree;
432 proto_item *tf;
434 /* decode the flag field for Session Init packet */
435 tf = proto_tree_add_item(tree, hf_netb_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
436 field_tree = proto_item_add_subtree(tf, ett_netb_flags);
438 proto_tree_add_item( field_tree, hf_netb_flags_send_no_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
440 proto_tree_add_item( field_tree, hf_netb_largest_frame, tvb, offset, 1, ENC_LITTLE_ENDIAN);
442 proto_tree_add_item( field_tree, hf_netb_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
446 static void
447 netbios_no_receive_flags( tvbuff_t *tvb, proto_tree *tree, int offset)
450 proto_tree *field_tree;
451 proto_item *tf;
453 /* decode the flag field for No Receive packet*/
454 tf = proto_tree_add_item(tree, hf_netbios_no_receive_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
455 field_tree = proto_item_add_subtree(tf, ett_netb_flags);
456 proto_tree_add_item(field_tree, hf_netbios_no_receive_flags_send_no_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
460 /************************************************************************/
461 /* */
462 /* The routines to display the netbios field values in the tree */
463 /* */
464 /************************************************************************/
467 static void
468 nb_xmit_corrl( tvbuff_t *tvb, int offset, proto_tree *tree)
470 {/* display the transmit correlator */
472 proto_tree_add_item( tree, hf_netb_xmit_corrl, tvb, offset + NB_XMIT_CORL,
473 2, ENC_LITTLE_ENDIAN);
477 static void
478 nb_resp_corrl( tvbuff_t *tvb, int offset, proto_tree *tree)
480 {/* display the response correlator */
482 proto_tree_add_item( tree, hf_netb_resp_corrl, tvb, offset + NB_RESP_CORL,
483 2, ENC_LITTLE_ENDIAN);
487 static void
488 nb_call_name_type( tvbuff_t *tvb, int offset, proto_tree *tree)
490 {/* display the call name type */
492 proto_tree_add_item( tree, hf_netb_call_name_type, tvb, offset + NB_CALL_NAME_TYPE,
493 1, ENC_LITTLE_ENDIAN);
498 static uint8_t
499 nb_local_session( tvbuff_t *tvb, int offset, proto_tree *tree)
501 {/* add the local session to tree, and return its value */
503 uint8_t local_session = tvb_get_uint8( tvb, offset + NB_LOCAL_SES);
505 proto_tree_add_uint( tree, hf_netb_local_ses_no, tvb, offset + NB_LOCAL_SES, 1,
506 local_session);
508 return local_session;
512 static uint8_t
513 nb_remote_session( tvbuff_t *tvb, int offset, proto_tree *tree)
515 {/* add the remote session to tree, and return its value */
517 uint8_t remote_session = tvb_get_uint8( tvb, offset + NB_RMT_SES);
519 proto_tree_add_uint( tree, hf_netb_remote_ses_no, tvb, offset + NB_RMT_SES, 1,
520 remote_session);
522 return remote_session;
526 static void
527 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, ENC_LITTLE_ENDIAN);
536 static void
537 nb_data2(int hf, tvbuff_t *tvb, int offset, proto_tree *tree)
539 {/* add the DATA2 to tree with specified hf_ value */
541 proto_tree_add_item( tree, hf, tvb, offset + NB_DATA2, 2, ENC_LITTLE_ENDIAN);
546 static void
547 nb_resync_indicator( tvbuff_t *tvb, int offset, proto_tree *tree, const char *cmd_str)
550 uint16_t resync_indicator = tvb_get_letohs( tvb, offset + NB_DATA2);
553 switch (resync_indicator) {
555 case 0x0000:
556 proto_tree_add_uint_format_value(tree, hf_netb_resync_indicator, tvb, offset + NB_DATA2, 2,
557 resync_indicator, "No re-sync");
558 break;
560 case 0x0001:
561 proto_tree_add_uint_format_value(tree, hf_netb_resync_indicator, tvb, offset + NB_DATA2, 2,
562 resync_indicator, "First '%s' following 'Receive Outstanding'", cmd_str);
563 break;
565 default:
566 proto_tree_add_item(tree, hf_netb_resync_indicator, tvb, offset + NB_DATA2, 2, ENC_LITTLE_ENDIAN);
567 break;
571 /************************************************************************/
572 /* */
573 /* The routines called by the top level to handle individual commands */
574 /* */
575 /************************************************************************/
577 static uint32_t
578 dissect_netb_unknown( tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree)
580 {/* Handle any unknown commands, do nothing */
582 proto_tree_add_expert(tree, pinfo, &ei_netb_unknown_command_data, tvb, offset + NB_COMMAND + 1, -1);
584 return 0;
588 static uint32_t
589 dissect_netb_add_group_name( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
591 {/* Handle the ADD GROUP NAME QUERY command */
593 nb_resp_corrl( tvb, offset, tree);
595 netbios_add_name("Group name to add", tvb, offset + NB_SENDER_NAME,
596 tree);
598 return 0;
602 static uint32_t
603 dissect_netb_add_name( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
605 {/* Handle the ADD NAME QUERY command */
607 nb_resp_corrl( tvb, offset, tree);
609 netbios_add_name("Name to add", tvb, offset + NB_SENDER_NAME, tree);
611 return 0;
615 static uint32_t
616 dissect_netb_name_in_conflict( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
618 {/* Handle the NAME IN CONFLICT command */
620 netbios_add_name("Name In Conflict", tvb, offset + NB_RECVER_NAME,
621 tree);
622 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME, tree);
624 return 0;
628 static uint32_t
629 dissect_netb_status_query( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
631 {/* Handle the STATUS QUERY command */
632 uint8_t status_request = tvb_get_uint8( tvb, offset + NB_DATA1);
634 switch (status_request) {
636 case 0:
637 proto_tree_add_uint_format_value(tree, hf_netb_status_request, tvb, offset + NB_DATA1, 1,
638 status_request, "NetBIOS 1.x or 2.0");
639 break;
641 case 1:
642 proto_tree_add_uint_format_value(tree, hf_netb_status_request, tvb, offset + NB_DATA1, 1,
643 status_request, "NetBIOS 2.1, initial status request");
644 break;
646 default:
647 proto_tree_add_uint_format_value(tree, hf_netb_status_request, tvb, offset + NB_DATA1, 1,
648 status_request, "NetBIOS 2.1, %u names received so far",
649 status_request);
650 break;
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);
657 return 0;
661 static uint32_t
662 dissect_netb_terminate_trace( tvbuff_t *tvb _U_, packet_info *pinfo _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".
671 return 0;
675 static const unsigned char zeroes[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
677 static uint32_t
678 dissect_netb_datagram( tvbuff_t *tvb, packet_info *pinfo _U_, 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 (tvb_memeql(tvb, offset + NB_SENDER_NAME, zeroes, 10) == 0) {
687 proto_tree_add_item(tree, hf_netb_datagram_mac,
688 tvb, offset + NB_SENDER_NAME + 10, 6, ENC_NA );
689 } else {
690 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
691 tree);
694 return 0;
698 static uint32_t
699 dissect_netb_datagram_bcast( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
701 {/* Handle the DATAGRAM BROADCAST command */
703 /* We assume the same weirdness can happen here.... */
704 if (tvb_memeql(tvb, offset + NB_SENDER_NAME, zeroes, 10) == 0) {
705 proto_tree_add_item(tree, hf_netb_datagram_bcast_mac,
706 tvb, offset + NB_SENDER_NAME + 10, 6, ENC_NA );
707 } else {
708 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
709 tree);
712 return 0;
716 static uint32_t
717 dissect_netb_name_query( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
719 {/* Handle the NAME QUERY command */
720 uint8_t local_session_number = tvb_get_uint8( tvb, offset + NB_DATA2);
722 if (local_session_number == 0) {
723 proto_tree_add_uint_format_value( tree, hf_netb_local_session_no, tvb, offset + NB_DATA2, 1,
724 local_session_number, "0 (FIND.NAME request)");
725 } else {
726 proto_tree_add_item( tree, hf_netb_local_session_no, tvb, offset + NB_DATA2, 1, ENC_LITTLE_ENDIAN);
728 nb_call_name_type( tvb, offset, tree);
729 nb_resp_corrl( tvb, offset, tree);
730 netbios_add_name("Query Name", tvb, offset + NB_RECVER_NAME, tree);
731 if (local_session_number != 0) {
732 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
733 tree);
736 return 0;
740 static uint32_t
741 dissect_netb_add_name_resp( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
743 {/* Handle the ADD NAME RESPONSE command */
745 nb_data1( hf_netb_status, tvb, offset, tree);
746 nb_data2( hf_netb_name_type, tvb, offset, tree);
747 nb_xmit_corrl( tvb, offset, tree);
748 netbios_add_name("Name to be added", tvb, offset + NB_RECVER_NAME,
749 tree);
750 netbios_add_name("Name to be added", tvb, offset + NB_SENDER_NAME,
751 tree);
753 return 0;
757 static uint32_t
758 dissect_netb_name_resp( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
760 {/* Handle the NAME RECOGNIZED command */
761 uint8_t local_session_number = tvb_get_uint8( tvb, offset + NB_DATA2);
763 switch (local_session_number) {
765 case 0x00:
766 proto_tree_add_uint_format_value( tree, hf_netb_state_of_name, tvb, offset + NB_DATA2, 1,
767 local_session_number, "No LISTEN pending, or FIND.NAME response");
768 break;
770 case 0xFF:
771 proto_tree_add_uint_format_value( tree, hf_netb_state_of_name, tvb, offset + NB_DATA2, 1,
772 local_session_number, "LISTEN pending, but insufficient resources to establish session");
773 break;
775 default:
776 proto_tree_add_item( tree, hf_netb_local_session_no, tvb, offset + NB_DATA2, 1, ENC_LITTLE_ENDIAN);
777 break;
779 nb_call_name_type( tvb, offset, tree);
780 nb_xmit_corrl( tvb, offset, tree);
781 if (local_session_number != 0x00 && local_session_number != 0xFF)
782 nb_resp_corrl(tvb, offset, tree);
783 netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
784 if (local_session_number != 0x00 && local_session_number != 0xFF) {
785 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
786 tree);
789 return 0;
793 static uint32_t
794 dissect_netb_status_resp( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
796 {/* Handle the STATUS RESPONSE command */
797 uint8_t status_response = tvb_get_uint8( tvb, offset + NB_DATA1);
798 proto_item *td2;
799 proto_tree *data2_tree;
801 nb_call_name_type( tvb, offset, tree);
802 if (status_response == 0) {
803 proto_tree_add_uint_format_value(tree, hf_netb_status_response, tvb, offset + NB_DATA1, 1,
804 status_response, "NetBIOS 1.x or 2.0");
805 } else {
806 proto_tree_add_uint_format_value(tree, hf_netb_status_response, tvb, offset + NB_DATA1, 1,
807 status_response, "NetBIOS 2.1, %u names sent so far",
808 status_response);
811 td2 = proto_tree_add_item(tree, hf_netb_data2, tvb, offset + NB_DATA2, 2, ENC_LITTLE_ENDIAN);
812 data2_tree = proto_item_add_subtree(td2, ett_netb_status);
813 proto_tree_add_item(data2_tree, hf_netb_data2_frame, tvb, offset + NB_DATA2, 2, ENC_LITTLE_ENDIAN);
814 proto_tree_add_item(data2_tree, hf_netb_data2_user, tvb, offset + NB_DATA2, 2, ENC_LITTLE_ENDIAN);
815 proto_tree_add_item(data2_tree, hf_netb_data2_status, tvb, offset + NB_DATA2, 2, ENC_LITTLE_ENDIAN);
817 nb_xmit_corrl( tvb, offset, tree);
818 netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
819 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
820 tree);
822 return 0;
826 static uint32_t
827 dissect_netb_data_ack( tvbuff_t* tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
829 {/* Handle the DATA ACK command */
831 nb_xmit_corrl( tvb, offset, tree);
832 nb_remote_session( tvb, offset, tree);
833 nb_local_session( tvb, offset, tree);
835 return 0;
839 static uint32_t
840 dissect_netb_data_first_middle( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
842 {/* Handle the DATA FIRST MIDDLE command */
844 uint8_t remote_session, local_session;
847 * This is the first frame, or the middle frame, of a fragmented
848 * packet.
850 * XXX - there are no sequence numbers, so we have to assume
851 * that fragments arrive in order with no duplicates.
852 * In fact, 802.2 LLC is supposed to handle that, so we
853 * might have to have the LLC dissector do so (but the TCP
854 * dissector doesn't currently handle out-of-order or duplicate
855 * data, either).
858 netbios_data_first_middle_flags( tvb, tree, offset + NB_FLAGS);
860 nb_resync_indicator( tvb, offset, tree, "DATA FIRST MIDDLE");
861 nb_xmit_corrl( tvb, offset, tree);
862 nb_resp_corrl( tvb, offset, tree);
863 remote_session = nb_remote_session( tvb, offset, tree);
864 local_session = nb_local_session( tvb, offset, tree);
867 * Return a combination of the remote and local session numbers,
868 * for use when reassembling.
870 return (remote_session << 8) + local_session;
874 static uint32_t
875 dissect_netb_data_only_last( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
877 {/* Handle the DATA ONLY LAST command */
879 uint8_t remote_session, local_session;
882 * This is a complete packet, or the last frame of a fragmented
883 * packet.
886 netbios_data_only_flags( tvb, tree, offset + NB_FLAGS);
888 nb_resync_indicator( tvb, offset, tree, "DATA ONLY LAST");
889 nb_xmit_corrl( tvb, offset, tree);
890 nb_resp_corrl( tvb, offset, tree);
891 remote_session = nb_remote_session( tvb, offset, tree);
892 local_session = nb_local_session( tvb, offset, tree);
895 * Return a combination of the remote and local session numbers,
896 * for use when reassembling.
898 return (remote_session << 8) + local_session;
902 static uint32_t
903 dissect_netb_session_confirm( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
905 {/* Handle the SESSION CONFIRM command */
907 netbios_add_ses_confirm_flags( tvb, tree, offset + NB_FLAGS);
909 nb_data2( hf_netb_max_data_recv_size, tvb, offset, tree);
910 nb_xmit_corrl( tvb, offset, tree);
911 nb_resp_corrl( tvb, offset, tree);
912 nb_remote_session( tvb, offset, tree);
913 nb_local_session( tvb, offset, tree);
915 return 0;
919 static uint32_t
920 dissect_netb_session_end( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
922 {/* Handle the SESSION END command */
924 nb_data2( hf_netb_termination_indicator, tvb, offset, tree);
925 nb_remote_session( tvb, offset, tree);
926 nb_local_session( tvb, offset, tree);
928 return 0;
932 static uint32_t
933 dissect_netb_session_init( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
935 {/* Handle the SESSION INITIALIZE command */
937 netbios_add_session_init_flags( tvb, tree, offset + NB_FLAGS);
939 nb_data2( hf_netb_max_data_recv_size, tvb, offset, tree);
940 nb_resp_corrl( tvb, offset, tree);
941 nb_xmit_corrl( tvb, offset, tree);
942 nb_remote_session( tvb, offset, tree);
943 nb_local_session( tvb, offset, tree);
945 return 0;
948 static uint32_t
949 dissect_netb_no_receive( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
951 {/* Handle the NO RECEIVE command */
953 netbios_no_receive_flags( tvb, tree, offset + NB_FLAGS);
955 nb_data2( hf_netb_num_data_bytes_accepted, tvb, offset, tree);
956 nb_remote_session( tvb, offset, tree);
957 nb_local_session( tvb, offset, tree);
959 return 0;
963 static uint32_t
964 dissect_netb_receive_outstanding( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
966 {/* Handle the RECEIVE OUTSTANDING command */
968 nb_data2( hf_netb_num_data_bytes_accepted, tvb, offset, tree);
969 nb_remote_session( tvb, offset, tree);
970 nb_local_session( tvb, offset, tree);
972 return 0;
976 static uint32_t
977 dissect_netb_receive_continue( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
979 {/* Handle the RECEIVE CONTINUE command */
981 nb_xmit_corrl( tvb, offset, tree);
982 nb_remote_session( tvb, offset, tree);
983 nb_local_session( tvb, offset, tree);
985 return 0;
989 static uint32_t
990 dissect_netb_session_alive( tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree)
992 {/* Handle the SESSION ALIVE command */
995 * XXX - all the fields are claimed to be "Reserved", but
996 * the session numbers appear to be non-zero in at least
997 * one capture, and they do appear to match session numbers
998 * in other messages, and I'd expect that you had to identify
999 * sessions in this message in any case.
1001 * We show only those fields.
1003 nb_remote_session( tvb, offset, tree);
1004 nb_local_session( tvb, offset, tree);
1006 return 0;
1010 /************************************************************************/
1011 /* */
1012 /* The table routines called by the top level to handle commands */
1013 /* */
1014 /************************************************************************/
1016 static uint32_t (*const dissect_netb[])(tvbuff_t *, packet_info *, int, proto_tree *) = {
1018 dissect_netb_add_group_name, /* Add Group Name 0x00 */
1019 dissect_netb_add_name, /* Add Name 0x01 */
1020 dissect_netb_name_in_conflict, /* Name In Conflict 0x02 */
1021 dissect_netb_status_query, /* Status Query 0x03 */
1022 dissect_netb_unknown, /* unknown 0x04 */
1023 dissect_netb_unknown, /* unknown 0x05 */
1024 dissect_netb_unknown, /* unknown 0x06 */
1025 dissect_netb_terminate_trace, /* Terminate Trace 0x07 */
1026 dissect_netb_datagram, /* Datagram 0x08 */
1027 dissect_netb_datagram_bcast, /* Datagram Broadcast 0x09 */
1028 dissect_netb_name_query, /* Name Query 0x0A */
1029 dissect_netb_unknown, /* unknown 0x0B */
1030 dissect_netb_unknown, /* unknown 0x0C */
1031 dissect_netb_add_name_resp, /* Add Name Response 0x0D */
1032 dissect_netb_name_resp, /* Name Recognized 0x0E */
1033 dissect_netb_status_resp, /* Status Response 0x0F */
1034 dissect_netb_unknown, /* unknown 0x10 */
1035 dissect_netb_unknown, /* unknown 0x11 */
1036 dissect_netb_unknown, /* unknown 0x12 */
1037 dissect_netb_terminate_trace, /* Terminate Trace 0x13 */
1038 dissect_netb_data_ack, /* Data Ack 0x14 */
1039 dissect_netb_data_first_middle, /* Data First Middle 0x15 */
1040 dissect_netb_data_only_last, /* Data Only Last 0x16 */
1041 dissect_netb_session_confirm, /* Session Confirm 0x17 */
1042 dissect_netb_session_end, /* Session End 0x18 */
1043 dissect_netb_session_init, /* Session Initialize 0x19 */
1044 dissect_netb_no_receive, /* No Receive 0x1A */
1045 dissect_netb_receive_outstanding, /* Receive Outstanding 0x1B */
1046 dissect_netb_receive_continue, /* Receive Continue 0x1C */
1047 dissect_netb_unknown, /* unknown 0x1D */
1048 dissect_netb_unknown, /* unknown 0x1E */
1049 dissect_netb_session_alive, /* Session Alive 0x1f */
1050 dissect_netb_unknown,
1053 static heur_dissector_list_t netbios_heur_subdissector_list;
1055 static void
1056 dissect_netbios_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1058 heur_dtbl_entry_t *hdtbl_entry;
1061 * Try the heuristic dissectors for NetBIOS; if none of them
1062 * accept the packet, dissect it as data.
1064 if (!dissector_try_heuristic(netbios_heur_subdissector_list,
1065 tvb, pinfo, tree, &hdtbl_entry, NULL))
1066 call_data_dissector(tvb, pinfo, tree);
1069 static int
1070 dissect_netbios(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1072 proto_tree *netb_tree = NULL;
1073 proto_item *ti;
1074 uint16_t hdr_len, command;
1075 const char *command_name;
1076 char name[(NETBIOS_NAME_LEN - 1)*4 + 1];
1077 int name_type;
1078 uint16_t session_id;
1079 bool save_fragmented;
1080 int len;
1081 fragment_head *fd_head;
1082 tvbuff_t *next_tvb;
1084 int offset = 0;
1086 /* load the display labels */
1087 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NetBIOS");
1090 /* Find NetBIOS marker EFFF, this is done because I have seen an extra LLC */
1091 /* byte on our network. This only checks for one extra LLC byte. */
1093 if ( 0xefff != tvb_get_letohs(tvb, 2)){
1094 ++offset;
1095 if ( 0xefff != tvb_get_letohs(tvb, 3)){
1097 /* print bad packet */
1098 col_set_str( pinfo->cinfo, COL_INFO, "Bad packet, no 0xEFFF marker");
1100 return 3; /* this is an unknown packet, no marker */
1105 hdr_len = tvb_get_letohs(tvb, offset + NB_LENGTH);
1106 command = tvb_get_uint8( tvb, offset + NB_COMMAND);
1107 /* limit command so no table overflows */
1108 command = MIN(command, array_length(dissect_netb));
1110 /* print command name */
1111 command_name = val_to_str_ext(command, &cmd_vals_ext, "Unknown (0x%02x)");
1112 switch ( command ) {
1113 case NB_NAME_QUERY:
1114 name_type = get_netbios_name( tvb, offset + 12, name, (NETBIOS_NAME_LEN - 1)*4 + 1);
1115 col_add_fstr( pinfo->cinfo, COL_INFO, "%s for %s<%02x>", command_name, name, name_type);
1116 break;
1118 case NB_NAME_RESP:
1119 case NB_ADD_NAME:
1120 case NB_ADD_GROUP:
1121 name_type = get_netbios_name( tvb, offset + 28, name, (NETBIOS_NAME_LEN - 1)*4 + 1);
1122 col_add_fstr( pinfo->cinfo, COL_INFO, "%s - %s<%02x>", command_name, name, name_type);
1123 break;
1125 default:
1126 col_add_str( pinfo->cinfo, COL_INFO, command_name);
1127 break;
1130 if ( tree) {
1131 ti = proto_tree_add_item(tree, proto_netbios, tvb, 0, hdr_len, ENC_NA);
1132 netb_tree = proto_item_add_subtree(ti, ett_netb);
1134 proto_tree_add_uint_format_value(netb_tree, hf_netb_hdr_len, tvb, offset, 2, hdr_len,
1135 "%d bytes", hdr_len);
1137 proto_tree_add_uint_format_value(netb_tree, hf_netb_delimiter, tvb, offset + 2, 2,
1138 tvb_get_letohs(tvb, offset + 2), "EFFF (NetBIOS)");
1140 proto_tree_add_uint(netb_tree, hf_netb_cmd, tvb, offset + NB_COMMAND, 1, command);
1143 /* if command in table range */
1144 if ( command < array_length(dissect_netb)) {
1146 /* branch to handle commands */
1147 session_id = (dissect_netb[ command])( tvb, pinfo, offset, netb_tree);
1149 offset += hdr_len; /* move past header */
1151 save_fragmented = pinfo->fragmented;
1154 * Process user data in frames that have it.
1156 switch (command) {
1158 case NB_DATAGRAM:
1159 case NB_DATAGRAM_BCAST:
1161 * No fragmentation here.
1163 next_tvb = tvb_new_subset_remaining(tvb, offset);
1164 dissect_netbios_payload(next_tvb, pinfo, tree);
1165 break;
1167 case NB_DATA_FIRST_MIDDLE:
1168 case NB_DATA_ONLY_LAST:
1170 * Possibly fragmented.
1172 len = tvb_reported_length_remaining(tvb, offset);
1173 if (netbios_defragment &&
1174 tvb_bytes_exist(tvb, offset, len)) {
1175 fd_head = fragment_add_seq_next(&netbios_reassembly_table,
1176 tvb, offset,
1177 pinfo, session_id, NULL,
1178 len, command == NB_DATA_FIRST_MIDDLE);
1179 if (fd_head != NULL) {
1180 if (fd_head->next != NULL) {
1181 next_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
1182 add_new_data_source(pinfo,
1183 next_tvb,
1184 "Reassembled NetBIOS");
1185 /* Show all fragments. */
1186 if (tree) {
1187 proto_item *frag_tree_item;
1189 show_fragment_seq_tree(fd_head,
1190 &netbios_frag_items,
1191 netb_tree, pinfo,
1192 next_tvb, &frag_tree_item);
1194 } else {
1195 next_tvb = tvb_new_subset_remaining(tvb,
1196 offset);
1198 } else {
1199 next_tvb = NULL;
1201 } else {
1203 * Dissect this, regardless of whether
1204 * it's NB_DATA_FIRST_MIDDLE or
1205 * NB_DATA_ONLY_LAST.
1207 * XXX - it'd be nice to show
1208 * NB_DATA_FIRST_MIDDLE as a fragment
1209 * if it's not the first fragment (i.e.,
1210 * MIDDLE rather than FIRST), and show
1211 * NB_DATA_ONLY_LAST as a fragment if
1212 * it's part of a fragmented datagram
1213 * (i.e, LAST rather than ONLY), but
1214 * we'd have to do reassembly to
1215 * be able to determine that.
1217 next_tvb = tvb_new_subset_remaining(tvb, offset);
1219 if (next_tvb != NULL)
1220 dissect_netbios_payload(next_tvb, pinfo, tree);
1221 else {
1222 next_tvb = tvb_new_subset_remaining (tvb, offset);
1223 call_data_dissector(next_tvb, pinfo, tree);
1225 break;
1227 pinfo->fragmented = save_fragmented;
1229 return tvb_captured_length(tvb);
1232 void
1233 proto_register_netbios(void)
1235 static int *ett[] = {
1236 &ett_netb,
1237 &ett_netb_name,
1238 &ett_netb_flags,
1239 &ett_netb_status,
1240 &ett_netb_fragments,
1241 &ett_netb_fragment,
1244 static hf_register_info hf_netb[] = {
1245 { &hf_netb_cmd,
1246 { "Command", "netbios.command", FT_UINT8, BASE_HEX | BASE_EXT_STRING,
1247 &cmd_vals_ext, 0x0, NULL, HFILL }},
1249 { &hf_netb_hdr_len,
1250 { "Length", "netbios.hdr_len", FT_UINT16, BASE_DEC,
1251 NULL, 0x0, "Header Length", HFILL }},
1253 { &hf_netb_delimiter,
1254 { "Delimiter", "netbios.delimiter", FT_UINT16, BASE_HEX,
1255 NULL, 0x0, NULL, HFILL }},
1257 { &hf_netb_xmit_corrl,
1258 { "Transmit Correlator", "netbios.xmit_corrl", FT_UINT16, BASE_HEX,
1259 NULL, 0x0, NULL, HFILL }},
1261 { &hf_netb_resp_corrl,
1262 { "Response Correlator", "netbios.resp_corrl", FT_UINT16, BASE_HEX,
1263 NULL, 0x0, NULL, HFILL }},
1265 { &hf_netb_call_name_type,
1266 { "Caller's Name Type", "netbios.call_name_type", FT_UINT8, BASE_HEX,
1267 VALS(name_types), 0x0, NULL, HFILL }},
1269 { &hf_netb_nb_name_type,
1270 { "NetBIOS Name Type", "netbios.nb_name_type", FT_UINT8, BASE_HEX |BASE_EXT_STRING,
1271 &nb_name_type_vals_ext, 0x0, NULL, HFILL }},
1273 { &hf_netb_nb_name,
1274 { "NetBIOS Name", "netbios.nb_name", FT_STRING, BASE_NONE,
1275 NULL, 0x0, NULL, HFILL }},
1277 { &hf_netb_version,
1278 { "NetBIOS Version", "netbios.version", FT_BOOLEAN, 8,
1279 TFS( &netb_version_str), 0x01, NULL, HFILL }},
1281 { &hf_netbios_no_receive_flags,
1282 { "Flags", "netbios.no_receive_flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1283 NULL, HFILL }},
1285 { &hf_netbios_no_receive_flags_send_no_ack,
1286 { "SEND.NO.ACK data received", "netbios.no_receive_flags.send_no_ack", FT_BOOLEAN, 8,
1287 TFS( &tfs_no_yes), 0x02, NULL, HFILL }},
1289 { &hf_netb_largest_frame,
1290 { "Largest Frame", "netbios.largest_frame", FT_UINT8, BASE_DEC,
1291 VALS(max_frame_size_vals), 0x0E, NULL, HFILL }},
1293 { &hf_netb_status_buffer_len,
1294 { "Length of status buffer", "netbios.status_buffer_len", FT_UINT16, BASE_DEC,
1295 NULL, 0x0, NULL, HFILL }},
1297 { &hf_netb_status,
1298 { "Status", "netbios.status", FT_UINT8, BASE_DEC,
1299 VALS(status_vals), 0x0, NULL, HFILL }},
1301 { &hf_netb_name_type,
1302 { "Name type", "netbios.name_type", FT_UINT16, BASE_DEC,
1303 VALS(name_types), 0x0, NULL, HFILL }},
1305 { &hf_netb_max_data_recv_size,
1306 { "Maximum data receive size", "netbios.max_data_recv_size", FT_UINT16, BASE_DEC,
1307 NULL, 0x0, NULL, HFILL }},
1309 { &hf_netb_termination_indicator,
1310 { "Termination indicator", "netbios.termination_indicator", FT_UINT16, BASE_HEX,
1311 VALS(termination_indicator_vals), 0x0, NULL, HFILL }},
1313 { &hf_netb_num_data_bytes_accepted,
1314 { "Number of data bytes accepted", "netbios.num_data_bytes_accepted", FT_UINT16, BASE_DEC,
1315 NULL, 0x0, NULL, HFILL }},
1317 { &hf_netb_local_ses_no,
1318 { "Local Session No.", "netbios.local_session", FT_UINT8, BASE_HEX,
1319 NULL, 0x0, NULL, HFILL }},
1321 { &hf_netb_remote_ses_no,
1322 { "Remote Session No.", "netbios.remote_session", FT_UINT8, BASE_HEX,
1323 NULL, 0x0, NULL, HFILL }},
1325 { &hf_netb_flags,
1326 { "Flags", "netbios.flags", FT_UINT8, BASE_HEX,
1327 NULL, 0x0, NULL, HFILL }},
1329 { &hf_netb_flags_send_no_ack,
1330 { "Handle SEND.NO.ACK", "netbios.flags.send_no_ack", FT_BOOLEAN, 8,
1331 TFS( &tfs_yes_no), 0x80, NULL, HFILL }},
1333 { &hf_netb_flags_ack,
1334 { "Acknowledge", "netbios.flags.ack", FT_BOOLEAN, 8,
1335 TFS( &tfs_set_notset), 0x08, NULL, HFILL }},
1337 { &hf_netb_flags_ack_with_data,
1338 { "Acknowledge with data", "netbios.flags.ack_with_data", FT_BOOLEAN, 8,
1339 TFS( &tfs_allowed_not_allowed), 0x04, NULL, HFILL }},
1341 { &hf_netb_flags_ack_expected,
1342 { "Acknowledge expected", "netbios.flags.ack_expected", FT_BOOLEAN, 8,
1343 TFS( &tfs_yes_no), 0x02, NULL, HFILL }},
1345 { &hf_netb_flags_recv_cont_req,
1346 { "RECEIVE_CONTINUE requested", "netbios.flags.recv_cont_req", FT_BOOLEAN, 8,
1347 TFS( &tfs_yes_no), 0x01, NULL, HFILL }},
1349 { &hf_netb_data2,
1350 { "DATA2 value", "netbios.data2", FT_UINT16, BASE_HEX,
1351 NULL, 0x0, NULL, HFILL }},
1353 { &hf_netb_data2_frame,
1354 { "Data length exceeds maximum frame size", "netbios.data2.frame", FT_BOOLEAN, 16,
1355 TFS(&tfs_yes_no), 0x8000, NULL, HFILL }},
1357 { &hf_netb_data2_user,
1358 { "Data length exceeds user's buffer", "netbios.data2.user", FT_BOOLEAN, 16,
1359 TFS(&tfs_yes_no), 0x4000, NULL, HFILL }},
1361 { &hf_netb_data2_status,
1362 { "Status data length", "netbios.data2.status", FT_UINT16, BASE_DEC,
1363 NULL, 0x3FFF, NULL, HFILL }},
1365 { &hf_netb_datagram_mac,
1366 { "Sender's MAC Address", "netbios.datagram_mac", FT_ETHER, BASE_NONE,
1367 NULL, 0x0, NULL, HFILL }},
1369 { &hf_netb_datagram_bcast_mac,
1370 { "Sender's Node Address", "netbios.datagram_bcast_mac", FT_ETHER, BASE_NONE,
1371 NULL, 0x0, NULL, HFILL }},
1373 { &hf_netb_resync_indicator,
1374 { "Re-sync indicator", "netbios.resync_indicator", FT_UINT16, BASE_HEX,
1375 NULL, 0x0, NULL, HFILL }},
1377 { &hf_netb_status_request,
1378 { "Status request", "netbios.status_request", FT_UINT8, BASE_DEC,
1379 NULL, 0x0, NULL, HFILL }},
1381 { &hf_netb_local_session_no,
1382 { "Local Session No.", "netbios.local_session_no", FT_UINT8, BASE_HEX,
1383 NULL, 0x0, NULL, HFILL }},
1385 { &hf_netb_state_of_name,
1386 { "State of name", "netbios.state_of_name", FT_UINT8, BASE_HEX,
1387 NULL, 0x0, NULL, HFILL }},
1389 { &hf_netb_status_response,
1390 { "Status response", "netbios.status_response", FT_UINT8, BASE_DEC,
1391 NULL, 0x0, NULL, HFILL }},
1393 { &hf_netb_fragment_overlap,
1394 { "Fragment overlap", "netbios.fragment.overlap", FT_BOOLEAN, BASE_NONE,
1395 NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
1397 { &hf_netb_fragment_overlap_conflict,
1398 { "Conflicting data in fragment overlap", "netbios.fragment.overlap.conflict",
1399 FT_BOOLEAN, BASE_NONE,
1400 NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
1402 { &hf_netb_fragment_multiple_tails,
1403 { "Multiple tail fragments found", "netbios.fragment.multipletails",
1404 FT_BOOLEAN, BASE_NONE,
1405 NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
1407 { &hf_netb_fragment_too_long_fragment,
1408 { "Fragment too long", "netbios.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE,
1409 NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
1411 { &hf_netb_fragment_error,
1412 { "Defragmentation error", "netbios.fragment.error", FT_FRAMENUM, BASE_NONE,
1413 NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
1415 { &hf_netb_fragment_count,
1416 { "Fragment count", "netbios.fragment.count", FT_UINT32, BASE_DEC,
1417 NULL, 0x0, NULL, HFILL }},
1419 { &hf_netb_fragment,
1420 { "NetBIOS Fragment", "netbios.fragment", FT_FRAMENUM, BASE_NONE,
1421 NULL, 0x0, NULL, HFILL }},
1423 { &hf_netb_fragments,
1424 { "NetBIOS Fragments", "netbios.fragments", FT_NONE, BASE_NONE,
1425 NULL, 0x0, NULL, HFILL }},
1427 { &hf_netb_reassembled_length,
1428 {"Reassembled NetBIOS length", "netbios.reassembled.length", FT_UINT32, BASE_DEC,
1429 NULL, 0x0, "The total length of the reassembled payload", HFILL }},
1432 static ei_register_info ei[] = {
1433 { &ei_netb_unknown_command_data, { "netbios.unknown_command_data", PI_UNDECODED, PI_WARN, "Unknown NetBIOS command data", EXPFILL }},
1436 module_t *netbios_module;
1437 expert_module_t* expert_netbios;
1439 proto_netbios = proto_register_protocol("NetBIOS", "NetBIOS", "netbios");
1440 proto_register_subtree_array(ett, array_length(ett));
1441 proto_register_field_array(proto_netbios, hf_netb, array_length(hf_netb));
1442 expert_netbios = expert_register_protocol(proto_netbios);
1443 expert_register_field_array(expert_netbios, ei, array_length(ei));
1445 netbios_handle = register_dissector("netbios", dissect_netbios, proto_netbios);
1446 netbios_cap_handle = register_capture_dissector("netbios", capture_netbios, proto_netbios);
1448 netbios_heur_subdissector_list = register_heur_dissector_list_with_description("netbios", "NetBIOS payload", proto_netbios);
1450 netbios_module = prefs_register_protocol(proto_netbios, NULL);
1451 prefs_register_bool_preference(netbios_module, "defragment",
1452 "Reassemble fragmented NetBIOS messages spanning multiple frames",
1453 "Whether the NetBIOS dissector should defragment messages spanning multiple frames",
1454 &netbios_defragment);
1456 reassembly_table_register(&netbios_reassembly_table,
1457 &addresses_reassembly_table_functions);
1460 void
1461 proto_reg_handoff_netbios(void)
1463 dissector_add_uint("llc.dsap", SAP_NETBIOS, netbios_handle);
1464 capture_dissector_add_uint("llc.dsap", SAP_NETBIOS, netbios_cap_handle);
1469 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1471 * Local variables:
1472 * c-basic-offset: 8
1473 * tab-width: 8
1474 * indent-tabs-mode: t
1475 * End:
1477 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1478 * :indentSize=8:tabSize=8:noTabs=false: