/* packet-smb.c
* Routines for smb packet dissection
* Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
* 2001 Rewrite by Ronnie Sahlberg and Guy Harris
*
* $Id: packet-smb.c,v 1.276 2002/08/06 19:02:24 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* Copied from packet-pop.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <glib.h>
#include <ctype.h>
#include <epan/packet.h>
#include <epan/conversation.h>
#include "smb.h"
#include "alignment.h"
#include <epan/strutil.h>
#include "prefs.h"
#include "reassemble.h"
#include "packet-smb-mailslot.h"
#include "packet-smb-pipe.h"
/*
* Various specifications and documents about SMB can be found in
*
* ftp://ftp.microsoft.com/developr/drg/CIFS/
*
* and a CIFS specification from the Storage Networking Industry Association
* can be found on a link from the page at
*
* http://www.snia.org/English/Collaterals/Work_Group_Docs/NAS/CIFS/CIFS_Technical_Reference.pdf
*
* (it supercedes the document at
*
* ftp://ftp.microsoft.com/developr/drg/CIFS/draft-leach-cifs-v1-spec-01.txt
*
* ).
*
* There are also some Open Group publications documenting CIFS for sale;
* catalog entries for them are at:
*
* http://www.opengroup.org/products/publications/catalog/c209.htm
*
* http://www.opengroup.org/products/publications/catalog/c195.htm
*
* The document "NT LAN Manager SMB File Sharing Protocol Extensions"
* can be found at
*
* http://www.samba.org/samba/ftp/specs/smb-nt01.doc
*
* (or, presumably a similar path under the Samba mirrors). As the
* ".doc" indicates, it's a Word document. Some of the specs from the
* Microsoft FTP site can be found in the
*
* http://www.samba.org/samba/ftp/specs/
*
* directory as well.
*
* Beware - these specs may have errors.
*/
static int proto_smb = -1;
static int hf_smb_cmd = -1;
static int hf_smb_pid = -1;
static int hf_smb_tid = -1;
static int hf_smb_uid = -1;
static int hf_smb_mid = -1;
static int hf_smb_response_to = -1;
static int hf_smb_time = -1;
static int hf_smb_response_in = -1;
static int hf_smb_continuation_to = -1;
static int hf_smb_nt_status = -1;
static int hf_smb_error_class = -1;
static int hf_smb_error_code = -1;
static int hf_smb_reserved = -1;
static int hf_smb_flags_lock = -1;
static int hf_smb_flags_receive_buffer = -1;
static int hf_smb_flags_caseless = -1;
static int hf_smb_flags_canon = -1;
static int hf_smb_flags_oplock = -1;
static int hf_smb_flags_notify = -1;
static int hf_smb_flags_response = -1;
static int hf_smb_flags2_long_names_allowed = -1;
static int hf_smb_flags2_ea = -1;
static int hf_smb_flags2_sec_sig = -1;
static int hf_smb_flags2_long_names_used = -1;
static int hf_smb_flags2_esn = -1;
static int hf_smb_flags2_dfs = -1;
static int hf_smb_flags2_roe = -1;
static int hf_smb_flags2_nt_error = -1;
static int hf_smb_flags2_string = -1;
static int hf_smb_word_count = -1;
static int hf_smb_byte_count = -1;
static int hf_smb_buffer_format = -1;
static int hf_smb_dialect_name = -1;
static int hf_smb_dialect_index = -1;
static int hf_smb_max_trans_buf_size = -1;
static int hf_smb_max_mpx_count = -1;
static int hf_smb_max_vcs_num = -1;
static int hf_smb_session_key = -1;
static int hf_smb_server_timezone = -1;
static int hf_smb_encryption_key_length = -1;
static int hf_smb_encryption_key = -1;
static int hf_smb_primary_domain = -1;
static int hf_smb_max_raw_buf_size = -1;
static int hf_smb_server_guid = -1;
static int hf_smb_security_blob_len = -1;
static int hf_smb_security_blob = -1;
static int hf_smb_sm_mode16 = -1;
static int hf_smb_sm_password16 = -1;
static int hf_smb_sm_mode = -1;
static int hf_smb_sm_password = -1;
static int hf_smb_sm_signatures = -1;
static int hf_smb_sm_sig_required = -1;
static int hf_smb_rm_read = -1;
static int hf_smb_rm_write = -1;
static int hf_smb_server_date_time = -1;
static int hf_smb_server_smb_date = -1;
static int hf_smb_server_smb_time = -1;
static int hf_smb_server_cap_raw_mode = -1;
static int hf_smb_server_cap_mpx_mode = -1;
static int hf_smb_server_cap_unicode = -1;
static int hf_smb_server_cap_large_files = -1;
static int hf_smb_server_cap_nt_smbs = -1;
static int hf_smb_server_cap_rpc_remote_apis = -1;
static int hf_smb_server_cap_nt_status = -1;
static int hf_smb_server_cap_level_ii_oplocks = -1;
static int hf_smb_server_cap_lock_and_read = -1;
static int hf_smb_server_cap_nt_find = -1;
static int hf_smb_server_cap_dfs = -1;
static int hf_smb_server_cap_infolevel_passthru = -1;
static int hf_smb_server_cap_large_readx = -1;
static int hf_smb_server_cap_large_writex = -1;
static int hf_smb_server_cap_unix = -1;
static int hf_smb_server_cap_reserved = -1;
static int hf_smb_server_cap_bulk_transfer = -1;
static int hf_smb_server_cap_compressed_data = -1;
static int hf_smb_server_cap_extended_security = -1;
static int hf_smb_system_time = -1;
static int hf_smb_unknown = -1;
static int hf_smb_dir_name = -1;
static int hf_smb_echo_count = -1;
static int hf_smb_echo_data = -1;
static int hf_smb_echo_seq_num = -1;
static int hf_smb_max_buf_size = -1;
static int hf_smb_password = -1;
static int hf_smb_password_len = -1;
static int hf_smb_ansi_password = -1;
static int hf_smb_ansi_password_len = -1;
static int hf_smb_unicode_password = -1;
static int hf_smb_unicode_password_len = -1;
static int hf_smb_path = -1;
static int hf_smb_service = -1;
static int hf_smb_move_flags_file = -1;
static int hf_smb_move_flags_dir = -1;
static int hf_smb_move_flags_verify = -1;
static int hf_smb_files_moved = -1;
static int hf_smb_copy_flags_file = -1;
static int hf_smb_copy_flags_dir = -1;
static int hf_smb_copy_flags_dest_mode = -1;
static int hf_smb_copy_flags_source_mode = -1;
static int hf_smb_copy_flags_verify = -1;
static int hf_smb_copy_flags_tree_copy = -1;
static int hf_smb_copy_flags_ea_action = -1;
static int hf_smb_count = -1;
static int hf_smb_file_name = -1;
static int hf_smb_open_function_open = -1;
static int hf_smb_open_function_create = -1;
static int hf_smb_fid = -1;
static int hf_smb_file_attr_read_only_16bit = -1;
static int hf_smb_file_attr_read_only_8bit = -1;
static int hf_smb_file_attr_hidden_16bit = -1;
static int hf_smb_file_attr_hidden_8bit = -1;
static int hf_smb_file_attr_system_16bit = -1;
static int hf_smb_file_attr_system_8bit = -1;
static int hf_smb_file_attr_volume_16bit = -1;
static int hf_smb_file_attr_volume_8bit = -1;
static int hf_smb_file_attr_directory_16bit = -1;
static int hf_smb_file_attr_directory_8bit = -1;
static int hf_smb_file_attr_archive_16bit = -1;
static int hf_smb_file_attr_archive_8bit = -1;
static int hf_smb_file_attr_device = -1;
static int hf_smb_file_attr_normal = -1;
static int hf_smb_file_attr_temporary = -1;
static int hf_smb_file_attr_sparse = -1;
static int hf_smb_file_attr_reparse = -1;
static int hf_smb_file_attr_compressed = -1;
static int hf_smb_file_attr_offline = -1;
static int hf_smb_file_attr_not_content_indexed = -1;
static int hf_smb_file_attr_encrypted = -1;
static int hf_smb_file_size = -1;
static int hf_smb_search_attribute_read_only = -1;
static int hf_smb_search_attribute_hidden = -1;
static int hf_smb_search_attribute_system = -1;
static int hf_smb_search_attribute_volume = -1;
static int hf_smb_search_attribute_directory = -1;
static int hf_smb_search_attribute_archive = -1;
static int hf_smb_access_mode = -1;
static int hf_smb_access_sharing = -1;
static int hf_smb_access_locality = -1;
static int hf_smb_access_caching = -1;
static int hf_smb_access_writetru = -1;
static int hf_smb_create_time = -1;
static int hf_smb_create_dos_date = -1;
static int hf_smb_create_dos_time = -1;
static int hf_smb_last_write_time = -1;
static int hf_smb_last_write_dos_date = -1;
static int hf_smb_last_write_dos_time = -1;
static int hf_smb_access_time = -1;
static int hf_smb_access_dos_date = -1;
static int hf_smb_access_dos_time = -1;
static int hf_smb_old_file_name = -1;
static int hf_smb_offset = -1;
static int hf_smb_remaining = -1;
static int hf_smb_padding = -1;
static int hf_smb_file_data = -1;
static int hf_smb_total_data_len = -1;
static int hf_smb_data_len = -1;
static int hf_smb_seek_mode = -1;
static int hf_smb_data_size = -1;
static int hf_smb_alloc_size = -1;
static int hf_smb_alloc_size64 = -1;
static int hf_smb_max_count = -1;
static int hf_smb_min_count = -1;
static int hf_smb_timeout = -1;
static int hf_smb_high_offset = -1;
static int hf_smb_units = -1;
static int hf_smb_bpu = -1;
static int hf_smb_blocksize = -1;
static int hf_smb_freeunits = -1;
static int hf_smb_data_offset = -1;
static int hf_smb_dcm = -1;
static int hf_smb_request_mask = -1;
static int hf_smb_response_mask = -1;
static int hf_smb_sid = -1;
static int hf_smb_write_mode_write_through = -1;
static int hf_smb_write_mode_return_remaining = -1;
static int hf_smb_write_mode_raw = -1;
static int hf_smb_write_mode_message_start = -1;
static int hf_smb_write_mode_connectionless = -1;
static int hf_smb_resume_key_len = -1;
static int hf_smb_resume_find_id = -1;
static int hf_smb_resume_server_cookie = -1;
static int hf_smb_resume_client_cookie = -1;
static int hf_smb_andxoffset = -1;
static int hf_smb_lock_type_large = -1;
static int hf_smb_lock_type_cancel = -1;
static int hf_smb_lock_type_change = -1;
static int hf_smb_lock_type_oplock = -1;
static int hf_smb_lock_type_shared = -1;
static int hf_smb_locking_ol = -1;
static int hf_smb_number_of_locks = -1;
static int hf_smb_number_of_unlocks = -1;
static int hf_smb_lock_long_offset = -1;
static int hf_smb_lock_long_length = -1;
static int hf_smb_file_type = -1;
static int hf_smb_ipc_state_nonblocking = -1;
static int hf_smb_ipc_state_endpoint = -1;
static int hf_smb_ipc_state_pipe_type = -1;
static int hf_smb_ipc_state_read_mode = -1;
static int hf_smb_ipc_state_icount = -1;
static int hf_smb_server_fid = -1;
static int hf_smb_open_flags_add_info = -1;
static int hf_smb_open_flags_ex_oplock = -1;
static int hf_smb_open_flags_batch_oplock = -1;
static int hf_smb_open_flags_ealen = -1;
static int hf_smb_open_action_open = -1;
static int hf_smb_open_action_lock = -1;
static int hf_smb_vc_num = -1;
static int hf_smb_account = -1;
static int hf_smb_os = -1;
static int hf_smb_lanman = -1;
static int hf_smb_setup_action_guest = -1;
static int hf_smb_fs = -1;
static int hf_smb_connect_flags_dtid = -1;
static int hf_smb_connect_support_search = -1;
static int hf_smb_connect_support_in_dfs = -1;
static int hf_smb_max_setup_count = -1;
static int hf_smb_total_param_count = -1;
static int hf_smb_total_data_count = -1;
static int hf_smb_max_param_count = -1;
static int hf_smb_max_data_count = -1;
static int hf_smb_param_disp16 = -1;
static int hf_smb_param_count16 = -1;
static int hf_smb_param_offset16 = -1;
static int hf_smb_param_disp32 = -1;
static int hf_smb_param_count32 = -1;
static int hf_smb_param_offset32 = -1;
static int hf_smb_data_disp16 = -1;
static int hf_smb_data_count16 = -1;
static int hf_smb_data_offset16 = -1;
static int hf_smb_data_disp32 = -1;
static int hf_smb_data_count32 = -1;
static int hf_smb_data_offset32 = -1;
static int hf_smb_setup_count = -1;
static int hf_smb_nt_trans_subcmd = -1;
static int hf_smb_nt_ioctl_function_code = -1;
static int hf_smb_nt_ioctl_isfsctl = -1;
static int hf_smb_nt_ioctl_flags_root_handle = -1;
static int hf_smb_nt_ioctl_data = -1;
#ifdef SMB_UNUSED_HANDLES
static int hf_smb_nt_security_information = -1;
#endif
static int hf_smb_nt_notify_action = -1;
static int hf_smb_nt_notify_watch_tree = -1;
static int hf_smb_nt_notify_stream_write = -1;
static int hf_smb_nt_notify_stream_size = -1;
static int hf_smb_nt_notify_stream_name = -1;
static int hf_smb_nt_notify_security = -1;
static int hf_smb_nt_notify_ea = -1;
static int hf_smb_nt_notify_creation = -1;
static int hf_smb_nt_notify_last_access = -1;
static int hf_smb_nt_notify_last_write = -1;
static int hf_smb_nt_notify_size = -1;
static int hf_smb_nt_notify_attributes = -1;
static int hf_smb_nt_notify_dir_name = -1;
static int hf_smb_nt_notify_file_name = -1;
static int hf_smb_root_dir_fid = -1;
static int hf_smb_nt_create_disposition = -1;
static int hf_smb_sd_length = -1;
static int hf_smb_ea_length = -1;
static int hf_smb_file_name_len = -1;
static int hf_smb_nt_impersonation_level = -1;
static int hf_smb_nt_security_flags_context_tracking = -1;
static int hf_smb_nt_security_flags_effective_only = -1;
static int hf_smb_nt_access_mask_generic_read = -1;
static int hf_smb_nt_access_mask_generic_write = -1;
static int hf_smb_nt_access_mask_generic_execute = -1;
static int hf_smb_nt_access_mask_generic_all = -1;
static int hf_smb_nt_access_mask_maximum_allowed = -1;
static int hf_smb_nt_access_mask_system_security = -1;
static int hf_smb_nt_access_mask_synchronize = -1;
static int hf_smb_nt_access_mask_write_owner = -1;
static int hf_smb_nt_access_mask_write_dac = -1;
static int hf_smb_nt_access_mask_read_control = -1;
static int hf_smb_nt_access_mask_delete = -1;
static int hf_smb_nt_access_mask_write_attributes = -1;
static int hf_smb_nt_access_mask_read_attributes = -1;
static int hf_smb_nt_access_mask_delete_child = -1;
static int hf_smb_nt_access_mask_execute = -1;
static int hf_smb_nt_access_mask_write_ea = -1;
static int hf_smb_nt_access_mask_read_ea = -1;
static int hf_smb_nt_access_mask_append = -1;
static int hf_smb_nt_access_mask_write = -1;
static int hf_smb_nt_access_mask_read = -1;
static int hf_smb_nt_create_bits_oplock = -1;
static int hf_smb_nt_create_bits_boplock = -1;
static int hf_smb_nt_create_bits_dir = -1;
static int hf_smb_nt_create_options_directory_file = -1;
static int hf_smb_nt_create_options_write_through = -1;
static int hf_smb_nt_create_options_sequential_only = -1;
static int hf_smb_nt_create_options_sync_io_alert = -1;
static int hf_smb_nt_create_options_sync_io_nonalert = -1;
static int hf_smb_nt_create_options_non_directory_file = -1;
static int hf_smb_nt_create_options_no_ea_knowledge = -1;
static int hf_smb_nt_create_options_eight_dot_three_only = -1;
static int hf_smb_nt_create_options_random_access = -1;
static int hf_smb_nt_create_options_delete_on_close = -1;
static int hf_smb_nt_share_access_read = -1;
static int hf_smb_nt_share_access_write = -1;
static int hf_smb_nt_share_access_delete = -1;
static int hf_smb_file_eattr_read_only = -1;
static int hf_smb_file_eattr_hidden = -1;
static int hf_smb_file_eattr_system = -1;
static int hf_smb_file_eattr_volume = -1;
static int hf_smb_file_eattr_directory = -1;
static int hf_smb_file_eattr_archive = -1;
static int hf_smb_file_eattr_device = -1;
static int hf_smb_file_eattr_normal = -1;
static int hf_smb_file_eattr_temporary = -1;
static int hf_smb_file_eattr_sparse = -1;
static int hf_smb_file_eattr_reparse = -1;
static int hf_smb_file_eattr_compressed = -1;
static int hf_smb_file_eattr_offline = -1;
static int hf_smb_file_eattr_not_content_indexed = -1;
static int hf_smb_file_eattr_encrypted = -1;
static int hf_smb_file_eattr_write_through = -1;
static int hf_smb_file_eattr_no_buffering = -1;
static int hf_smb_file_eattr_random_access = -1;
static int hf_smb_file_eattr_sequential_scan = -1;
static int hf_smb_file_eattr_delete_on_close = -1;
static int hf_smb_file_eattr_backup_semantics = -1;
static int hf_smb_file_eattr_posix_semantics = -1;
static int hf_smb_sec_desc_len = -1;
static int hf_smb_sec_desc_revision = -1;
static int hf_smb_sec_desc_type_owner_defaulted = -1;
static int hf_smb_sec_desc_type_group_defaulted = -1;
static int hf_smb_sec_desc_type_dacl_present = -1;
static int hf_smb_sec_desc_type_dacl_defaulted = -1;
static int hf_smb_sec_desc_type_sacl_present = -1;
static int hf_smb_sec_desc_type_sacl_defaulted = -1;
static int hf_smb_sec_desc_type_dacl_auto_inherit_req = -1;
static int hf_smb_sec_desc_type_sacl_auto_inherit_req = -1;
static int hf_smb_sec_desc_type_dacl_auto_inherited = -1;
static int hf_smb_sec_desc_type_sacl_auto_inherited = -1;
static int hf_smb_sec_desc_type_dacl_protected = -1;
static int hf_smb_sec_desc_type_sacl_protected = -1;
static int hf_smb_sec_desc_type_self_relative = -1;
static int hf_smb_sid_revision = -1;
static int hf_smb_sid_num_auth = -1;
static int hf_smb_acl_revision = -1;
static int hf_smb_acl_size = -1;
static int hf_smb_acl_num_aces = -1;
static int hf_smb_ace_type = -1;
static int hf_smb_ace_size = -1;
static int hf_smb_ace_flags_object_inherit = -1;
static int hf_smb_ace_flags_container_inherit = -1;
static int hf_smb_ace_flags_non_propagate_inherit = -1;
static int hf_smb_ace_flags_inherit_only = -1;
static int hf_smb_ace_flags_inherited_ace = -1;
static int hf_smb_ace_flags_successful_access = -1;
static int hf_smb_ace_flags_failed_access = -1;
static int hf_smb_nt_qsd_owner = -1;
static int hf_smb_nt_qsd_group = -1;
static int hf_smb_nt_qsd_dacl = -1;
static int hf_smb_nt_qsd_sacl = -1;
static int hf_smb_extended_attributes = -1;
static int hf_smb_oplock_level = -1;
static int hf_smb_create_action = -1;
static int hf_smb_file_id = -1;
static int hf_smb_ea_error_offset = -1;
static int hf_smb_end_of_file = -1;
static int hf_smb_device_type = -1;
static int hf_smb_is_directory = -1;
static int hf_smb_next_entry_offset = -1;
static int hf_smb_change_time = -1;
static int hf_smb_setup_len = -1;
static int hf_smb_print_mode = -1;
static int hf_smb_print_identifier = -1;
static int hf_smb_restart_index = -1;
static int hf_smb_print_queue_date = -1;
static int hf_smb_print_queue_dos_date = -1;
static int hf_smb_print_queue_dos_time = -1;
static int hf_smb_print_status = -1;
static int hf_smb_print_spool_file_number = -1;
static int hf_smb_print_spool_file_size = -1;
static int hf_smb_print_spool_file_name = -1;
static int hf_smb_start_index = -1;
static int hf_smb_originator_name = -1;
static int hf_smb_destination_name = -1;
static int hf_smb_message_len = -1;
static int hf_smb_message = -1;
static int hf_smb_mgid = -1;
static int hf_smb_forwarded_name = -1;
static int hf_smb_machine_name = -1;
static int hf_smb_cancel_to = -1;
static int hf_smb_trans2_subcmd = -1;
static int hf_smb_trans_name = -1;
static int hf_smb_transaction_flags_dtid = -1;
static int hf_smb_transaction_flags_owt = -1;
static int hf_smb_search_count = -1;
static int hf_smb_search_pattern = -1;
static int hf_smb_ff2_backup = -1;
static int hf_smb_ff2_continue = -1;
static int hf_smb_ff2_resume = -1;
static int hf_smb_ff2_close_eos = -1;
static int hf_smb_ff2_close = -1;
static int hf_smb_ff2_information_level = -1;
static int hf_smb_qpi_loi = -1;
#if 0
static int hf_smb_sfi_writetru = -1;
static int hf_smb_sfi_caching = -1;
#endif
static int hf_smb_storage_type = -1;
static int hf_smb_resume = -1;
static int hf_smb_max_referral_level = -1;
static int hf_smb_qfsi_information_level = -1;
static int hf_smb_ea_size = -1;
static int hf_smb_list_length = -1;
static int hf_smb_number_of_links = -1;
static int hf_smb_delete_pending = -1;
static int hf_smb_index_number = -1;
static int hf_smb_current_offset = -1;
static int hf_smb_t2_alignment = -1;
static int hf_smb_t2_stream_name_length = -1;
static int hf_smb_t2_stream_size = -1;
static int hf_smb_t2_stream_name = -1;
static int hf_smb_t2_compressed_file_size = -1;
static int hf_smb_t2_compressed_format = -1;
static int hf_smb_t2_compressed_unit_shift = -1;
static int hf_smb_t2_compressed_chunk_shift = -1;
static int hf_smb_t2_compressed_cluster_shift = -1;
static int hf_smb_dfs_path_consumed = -1;
static int hf_smb_dfs_num_referrals = -1;
static int hf_smb_get_dfs_server_hold_storage = -1;
static int hf_smb_get_dfs_fielding = -1;
static int hf_smb_dfs_referral_version = -1;
static int hf_smb_dfs_referral_size = -1;
static int hf_smb_dfs_referral_server_type = -1;
static int hf_smb_dfs_referral_flags_strip = -1;
static int hf_smb_dfs_referral_node_offset = -1;
static int hf_smb_dfs_referral_node = -1;
static int hf_smb_dfs_referral_proximity = -1;
static int hf_smb_dfs_referral_ttl = -1;
static int hf_smb_dfs_referral_path_offset = -1;
static int hf_smb_dfs_referral_path = -1;
static int hf_smb_dfs_referral_alt_path_offset = -1;
static int hf_smb_dfs_referral_alt_path = -1;
static int hf_smb_end_of_search = -1;
static int hf_smb_last_name_offset = -1;
static int hf_smb_fn_information_level = -1;
static int hf_smb_monitor_handle = -1;
static int hf_smb_change_count = -1;
static int hf_smb_file_index = -1;
static int hf_smb_short_file_name = -1;
static int hf_smb_short_file_name_len = -1;
static int hf_smb_fs_id = -1;
static int hf_smb_sector_unit = -1;
static int hf_smb_fs_units = -1;
static int hf_smb_fs_sector = -1;
static int hf_smb_avail_units = -1;
static int hf_smb_volume_serial_num = -1;
static int hf_smb_volume_label_len = -1;
static int hf_smb_volume_label = -1;
static int hf_smb_free_alloc_units64 = -1;
static int hf_smb_caller_free_alloc_units64 = -1;
static int hf_smb_actual_free_alloc_units64 = -1;
static int hf_smb_max_name_len = -1;
static int hf_smb_fs_name_len = -1;
static int hf_smb_fs_name = -1;
static int hf_smb_device_char_removable = -1;
static int hf_smb_device_char_read_only = -1;
static int hf_smb_device_char_floppy = -1;
static int hf_smb_device_char_write_once = -1;
static int hf_smb_device_char_remote = -1;
static int hf_smb_device_char_mounted = -1;
static int hf_smb_device_char_virtual = -1;
static int hf_smb_fs_attr_css = -1;
static int hf_smb_fs_attr_cpn = -1;
static int hf_smb_fs_attr_pacls = -1;
static int hf_smb_fs_attr_fc = -1;
static int hf_smb_fs_attr_vq = -1;
static int hf_smb_fs_attr_dim = -1;
static int hf_smb_fs_attr_vic = -1;
static int hf_smb_quota_flags_enabled = -1;
static int hf_smb_quota_flags_deny_disk = -1;
static int hf_smb_quota_flags_log_limit = -1;
static int hf_smb_quota_flags_log_warning = -1;
static int hf_smb_soft_quota_limit = -1;
static int hf_smb_hard_quota_limit = -1;
static int hf_smb_user_quota_used = -1;
static int hf_smb_user_quota_offset = -1;
static int hf_smb_nt_rename_level = -1;
static int hf_smb_cluster_count = -1;
static int hf_smb_segments = -1;
static int hf_smb_segment = -1;
static int hf_smb_segment_overlap = -1;
static int hf_smb_segment_overlap_conflict = -1;
static int hf_smb_segment_multiple_tails = -1;
static int hf_smb_segment_too_long_fragment = -1;
static int hf_smb_segment_error = -1;
static gint ett_smb = -1;
static gint ett_smb_hdr = -1;
static gint ett_smb_command = -1;
static gint ett_smb_fileattributes = -1;
static gint ett_smb_capabilities = -1;
static gint ett_smb_aflags = -1;
static gint ett_smb_dialect = -1;
static gint ett_smb_dialects = -1;
static gint ett_smb_mode = -1;
static gint ett_smb_rawmode = -1;
static gint ett_smb_flags = -1;
static gint ett_smb_flags2 = -1;
static gint ett_smb_desiredaccess = -1;
static gint ett_smb_search = -1;
static gint ett_smb_file = -1;
static gint ett_smb_openfunction = -1;
static gint ett_smb_filetype = -1;
static gint ett_smb_openaction = -1;
static gint ett_smb_writemode = -1;
static gint ett_smb_lock_type = -1;
static gint ett_smb_ssetupandxaction = -1;
static gint ett_smb_optionsup = -1;
static gint ett_smb_time_date = -1;
static gint ett_smb_move_copy_flags = -1;
static gint ett_smb_file_attributes = -1;
static gint ett_smb_search_resume_key = -1;
static gint ett_smb_search_dir_info = -1;
static gint ett_smb_unlocks = -1;
static gint ett_smb_unlock = -1;
static gint ett_smb_locks = -1;
static gint ett_smb_lock = -1;
static gint ett_smb_open_flags = -1;
static gint ett_smb_ipc_state = -1;
static gint ett_smb_open_action = -1;
static gint ett_smb_setup_action = -1;
static gint ett_smb_connect_flags = -1;
static gint ett_smb_connect_support_bits = -1;
static gint ett_smb_nt_access_mask = -1;
static gint ett_smb_nt_create_bits = -1;
static gint ett_smb_nt_create_options = -1;
static gint ett_smb_nt_share_access = -1;
static gint ett_smb_nt_security_flags = -1;
static gint ett_smb_nt_trans_setup = -1;
static gint ett_smb_nt_trans_data = -1;
static gint ett_smb_nt_trans_param = -1;
static gint ett_smb_nt_notify_completion_filter = -1;
static gint ett_smb_nt_ioctl_flags = -1;
static gint ett_smb_security_information_mask = -1;
static gint ett_smb_print_queue_entry = -1;
static gint ett_smb_transaction_flags = -1;
static gint ett_smb_transaction_params = -1;
static gint ett_smb_find_first2_flags = -1;
#if 0
static gint ett_smb_ioflag = -1;
#endif
static gint ett_smb_transaction_data = -1;
static gint ett_smb_stream_info = -1;
static gint ett_smb_dfs_referrals = -1;
static gint ett_smb_dfs_referral = -1;
static gint ett_smb_dfs_referral_flags = -1;
static gint ett_smb_get_dfs_flags = -1;
static gint ett_smb_ff2_data = -1;
static gint ett_smb_device_characteristics = -1;
static gint ett_smb_fs_attributes = -1;
static gint ett_smb_segments = -1;
static gint ett_smb_segment = -1;
static gint ett_smb_sec_desc = -1;
static gint ett_smb_sid = -1;
static gint ett_smb_acl = -1;
static gint ett_smb_ace = -1;
static gint ett_smb_ace_flags = -1;
static gint ett_smb_sec_desc_type = -1;
static gint ett_smb_quotaflags = -1;
fragment_items smb_frag_items = {
&ett_smb_segment,
&ett_smb_segments,
&hf_smb_segments,
&hf_smb_segment,
&hf_smb_segment_overlap,
&hf_smb_segment_overlap_conflict,
&hf_smb_segment_multiple_tails,
&hf_smb_segment_too_long_fragment,
&hf_smb_segment_error,
"segments"
};
proto_tree *top_tree=NULL; /* ugly */
static char *decode_smb_name(unsigned char);
static int dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *smb_tree, guint8 cmd, gboolean first_pdu);
static const gchar *get_unicode_or_ascii_string(tvbuff_t *tvb,
int *offsetp, packet_info *pinfo, int *len, gboolean nopad,
gboolean exactlen, guint16 *bcp);
/*
* Macros for use in the main dissector routines for an SMB.
*/
#define WORD_COUNT \
/* Word Count */ \
wc = tvb_get_guint8(tvb, offset); \
proto_tree_add_uint(tree, hf_smb_word_count, \
tvb, offset, 1, wc); \
offset += 1; \
if(wc==0) goto bytecount;
#define BYTE_COUNT \
bytecount: \
bc = tvb_get_letohs(tvb, offset); \
proto_tree_add_uint(tree, hf_smb_byte_count, \
tvb, offset, 2, bc); \
offset += 2; \
if(bc==0) goto endofcommand;
#define CHECK_BYTE_COUNT(len) \
if (bc < len) goto endofcommand;
#define COUNT_BYTES(len) {\
int tmp; \
tmp=len; \
offset += tmp; \
bc -= tmp; \
}
#define END_OF_SMB \
if (bc != 0) { \
proto_tree_add_text(tree, tvb, offset, bc, \
"Extra byte parameters"); \
offset += bc; \
} \
endofcommand:
/*
* Macros for use in routines called by them.
*/
#define CHECK_BYTE_COUNT_SUBR(len) \
if (*bcp < len) { \
*trunc = TRUE; \
return offset; \
}
#define CHECK_STRING_SUBR(fn) \
if (fn == NULL) { \
*trunc = TRUE; \
return offset; \
}
#define COUNT_BYTES_SUBR(len) \
offset += len; \
*bcp -= len;
/*
* Macros for use when dissecting transaction parameters and data
*/
#define CHECK_BYTE_COUNT_TRANS(len) \
if (bc < len) return offset;
#define CHECK_STRING_TRANS(fn) \
if (fn == NULL) return offset;
#define COUNT_BYTES_TRANS(len) \
offset += len; \
bc -= len;
/*
* Macros for use in subrroutines dissecting transaction parameters or data
*/
#define CHECK_BYTE_COUNT_TRANS_SUBR(len) \
if (*bcp < len) return offset;
#define CHECK_STRING_TRANS_SUBR(fn) \
if (fn == NULL) return offset;
#define COUNT_BYTES_TRANS_SUBR(len) \
offset += len; \
*bcp -= len;
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
These are needed by the reassembly of SMB Transaction payload and DCERPC over SMB
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
static gboolean smb_trans_reassembly = FALSE;
gboolean smb_dcerpc_reassembly = FALSE;
static GHashTable *smb_trans_fragment_table = NULL;
GHashTable *dcerpc_fragment_table = NULL;
static void
smb_trans_reassembly_init(void)
{
fragment_table_init(&smb_trans_fragment_table);
}
static void
smb_dcerpc_reassembly_init(void)
{
fragment_table_init(&dcerpc_fragment_table);
}
static fragment_data *
smb_trans_defragment(proto_tree *tree _U_, packet_info *pinfo, tvbuff_t *tvb,
int offset, int count, int pos, int totlen)
{
fragment_data *fd_head=NULL;
smb_info_t *si;
int more_frags;
more_frags=totlen>(pos+count);
si = (smb_info_t *)pinfo->private_data;
if (si->sip == NULL) {
/*
* We don't have the frame number of the request.
*
* XXX - is there truly nothing we can do here?
* Can we not separately keep track of the original
* transaction and its continuations, as we did
* at one time?
*
* It is probably not much point in even trying to do something here
* if we have never seen the initial request. Without the initial
* request we probably miss all parameters and the begining of data
* so we cant even call a subdissector since we can not determine
* which type of transaction call this is.
*/
return NULL;
}
if(!pinfo->fd->flags.visited){
fd_head = fragment_add(tvb, offset, pinfo,
si->sip->frame_req, smb_trans_fragment_table,
pos, count, more_frags);
} else {
fd_head = fragment_get(pinfo, si->sip->frame_req, smb_trans_fragment_table);
}
/* we only show the defragmented packet for the first fragment,
or else we might end up with dissecting one HUGE transaction PDU
a LOT of times. (first fragment is the only one containing the setup
bytes)
I have seen ONE Transaction PDU that is ~60kb, spanning many Transaction
SMBs. Takes a LOT of time dissecting and is not fun.
*/
if( (pos==0) && fd_head && fd_head->flags&FD_DEFRAGMENTED){
return fd_head;
} else {
return NULL;
}
}
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
These variables and functions are used to match
responses with calls
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
/*
* The information we need to save about a request in order to show the
* frame number of the request in the dissection of the reply.
*/
typedef struct {
guint32 frame;
guint32 pid_mid;
} smb_saved_info_key_t;
static GMemChunk *smb_saved_info_key_chunk = NULL;
static GMemChunk *smb_saved_info_chunk = NULL;
static int smb_saved_info_init_count = 200;
/* unmatched smb_saved_info structures.
For unmatched smb_saved_info structures we store the smb_saved_info
structure using the MID and the PID as the key.
Oh, yes, the key is really a pointer, but we use it as if it was an integer.
Ugly, yes. Not portable to DEC-20 Yes. But it saves a few bytes.
The key is the PID in the upper 16 bits and the MID in the lower 16 bits.
*/
static gint
smb_saved_info_equal_unmatched(gconstpointer k1, gconstpointer k2)
{
register guint32 key1 = (guint32)k1;
register guint32 key2 = (guint32)k2;
return key1==key2;
}
static guint
smb_saved_info_hash_unmatched(gconstpointer k)
{
register guint32 key = (guint32)k;
return key;
}
/* matched smb_saved_info structures.
For matched smb_saved_info structures we store the smb_saved_info
structure twice in the table using the frame number, and a combination
of the MID and the PID, as the key.
The frame number is guaranteed to be unique but if ever someone makes
some change that will renumber the frames in a capture we are in BIG trouble.
This is not likely though since that would break (among other things) all the
reassembly routines as well.
We also need the MID as there may be more than one SMB request or reply
in a single frame, and we also need the PID as there may be more than
one outstanding request with the same MID and different PIDs.
*/
static gint
smb_saved_info_equal_matched(gconstpointer k1, gconstpointer k2)
{
const smb_saved_info_key_t *key1 = k1;
const smb_saved_info_key_t *key2 = k2;
return key1->frame == key2->frame && key1->pid_mid == key2->pid_mid;
}
static guint
smb_saved_info_hash_matched(gconstpointer k)
{
const smb_saved_info_key_t *key = k;
return key->frame + key->pid_mid;
}
/*
* The information we need to save about an NT Transaction request in order
* to dissect the reply.
*/
typedef struct {
int subcmd;
} smb_nt_transact_info_t;
static GMemChunk *smb_nt_transact_info_chunk = NULL;
static int smb_nt_transact_info_init_count = 200;
/*
* The information we need to save about a Transaction2 request in order
* to dissect the reply.
*/
typedef struct {
int subcmd;
int info_level;
gboolean resume_keys; /* if "return resume" keys set in T2 FIND_FIRST request */
} smb_transact2_info_t;
static GMemChunk *smb_transact2_info_chunk = NULL;
static int smb_transact2_info_init_count = 200;
/*
* The information we need to save about a Transaction request in order
* to dissect the reply; this includes information for use by the
* Remote API dissector.
*/
static GMemChunk *smb_transact_info_chunk = NULL;
static int smb_transact_info_init_count = 200;
static GMemChunk *conv_tables_chunk = NULL;
static GSList *conv_tables = NULL;
static int conv_tables_count = 10;
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
End of request/response matching functions
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
static const value_string buffer_format_vals[] = {
{1, "Data Block"},
{2, "Dialect"},
{3, "Pathname"},
{4, "ASCII"},
{5, "Variable Block"},
{0, NULL}
};
/*
* UTIME - this is *almost* like a UNIX time stamp, except that it's
* in seconds since January 1, 1970, 00:00:00 *local* time, not since
* January 1, 1970, 00:00:00 GMT.
*
* This means we have to do some extra work to convert it. This code is
* based on the Samba code:
*
* Unix SMB/Netbios implementation.
* Version 1.9.
* time handling functions
* Copyright (C) Andrew Tridgell 1992-1998
*/
/*
* Yield the difference between *A and *B, in seconds, ignoring leap
* seconds.
*/
#define TM_YEAR_BASE 1900
static int
tm_diff(struct tm *a, struct tm *b)
{
int ay = a->tm_year + (TM_YEAR_BASE - 1);
int by = b->tm_year + (TM_YEAR_BASE - 1);
int intervening_leap_days =
(ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
int years = ay - by;
int days =
365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
int hours = 24*days + (a->tm_hour - b->tm_hour);
int minutes = 60*hours + (a->tm_min - b->tm_min);
int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
return seconds;
}
/*
* Return the UTC offset in seconds west of UTC, or 0 if it cannot be
* determined.
*/
static int
TimeZone(time_t t)
{
struct tm *tm = gmtime(&t);
struct tm tm_utc;
if (tm == NULL)
return 0;
tm_utc = *tm;
tm = localtime(&t);
if (tm == NULL)
return 0;
return tm_diff(&tm_utc,tm);
}
/*
* Return the same value as TimeZone, but it should be more efficient.
*
* We keep a table of DST offsets to prevent calling localtime() on each
* call of this function. This saves a LOT of time on many unixes.
*
* Updated by Paul Eggert <eggert@twinsun.com>
*/
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
#ifndef TIME_T_MIN
#define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \
: ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
#endif
#ifndef TIME_T_MAX
#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
#endif
static int
TimeZoneFaster(time_t t)
{
static struct dst_table {time_t start,end; int zone;} *tdt;
static struct dst_table *dst_table = NULL;
static int table_size = 0;
int i;
int zone = 0;
if (t == 0)
t = time(NULL);
/* Tunis has a 8 day DST region, we need to be careful ... */
#define MAX_DST_WIDTH (365*24*60*60)
#define MAX_DST_SKIP (7*24*60*60)
for (i = 0; i < table_size; i++) {
if (t >= dst_table[i].start && t <= dst_table[i].end)
break;
}
if (i < table_size) {
zone = dst_table[i].zone;
} else {
time_t low,high;
zone = TimeZone(t);
if (dst_table == NULL)
tdt = g_malloc(sizeof(dst_table[0])*(i+1));
else
tdt = g_realloc(dst_table, sizeof(dst_table[0])*(i+1));
if (tdt == NULL) {
if (dst_table)
free(dst_table);
table_size = 0;
} else {
dst_table = tdt;
table_size++;
dst_table[i].zone = zone;
dst_table[i].start = dst_table[i].end = t;
/* no entry will cover more than 6 months */
low = t - MAX_DST_WIDTH/2;
if (t < low)
low = TIME_T_MIN;
high = t + MAX_DST_WIDTH/2;
if (high < t)
high = TIME_T_MAX;
/*
* Widen the new entry using two bisection searches.
*/
while (low+60*60 < dst_table[i].start) {
if (dst_table[i].start - low > MAX_DST_SKIP*2)
t = dst_table[i].start - MAX_DST_SKIP;
else
t = low + (dst_table[i].start-low)/2;
if (TimeZone(t) == zone)
dst_table[i].start = t;
else
low = t;
}
while (high-60*60 > dst_table[i].end) {
if (high - dst_table[i].end > MAX_DST_SKIP*2)
t = dst_table[i].end + MAX_DST_SKIP;
else
t = high - (high-dst_table[i].end)/2;
if (TimeZone(t) == zone)
dst_table[i].end = t;
else
high = t;
}
}
}
return zone;
}
/*
* Return the UTC offset in seconds west of UTC, adjusted for extra time
* offset, for a local time value. If ut = lt + LocTimeDiff(lt), then
* lt = ut - TimeDiff(ut), but the converse does not necessarily hold near
* daylight savings transitions because some local times are ambiguous.
* LocTimeDiff(t) equals TimeDiff(t) except near daylight savings transitions.
*/
static int
LocTimeDiff(time_t lt)
{
int d = TimeZoneFaster(lt);
time_t t = lt + d;
/* if overflow occurred, ignore all the adjustments so far */
if (((t < lt) ^ (d < 0)))
t = lt;
/*
* Now t should be close enough to the true UTC to yield the
* right answer.
*/
return TimeZoneFaster(t);
}
static int
dissect_smb_UTIME(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_date)
{
guint32 timeval;
nstime_t ts;
timeval = tvb_get_letohl(tvb, offset);
if (timeval == 0xffffffff) {
proto_tree_add_text(tree, tvb, offset, 4,
"%s: No time specified (0xffffffff)",
proto_registrar_get_name(hf_date));
offset += 4;
return offset;
}
/*
* We add the local time offset.
*/
ts.secs = timeval + LocTimeDiff(timeval);
ts.nsecs = 0;
proto_tree_add_time(tree, hf_date, tvb, offset, 4, &ts);
offset += 4;
return offset;
}
#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
/*
* Translate an 8-byte FILETIME value, given as the upper and lower 32 bits,
* to an "nstime_t".
* A FILETIME is a 64-bit integer, giving the time since Jan 1, 1601,
* midnight "UTC", in 100ns units.
* Return TRUE if the conversion succeeds, FALSE otherwise.
*
* According to the Samba code, it appears to be kludge-GMT (at least for
* file listings). This means it's the GMT you get by taking a local time
* and adding the server time zone offset. This is NOT the same as GMT in
* some cases. However, we don't know the server time zone, so we don't
* do that adjustment.
*
* This code is based on the Samba code:
*
* Unix SMB/Netbios implementation.
* Version 1.9.
* time handling functions
* Copyright (C) Andrew Tridgell 1992-1998
*/
static gboolean
nt_time_to_nstime(guint32 filetime_high, guint32 filetime_low, nstime_t *tv)
{
double d;
/* The next two lines are a fix needed for the
broken SCO compiler. JRA. */
time_t l_time_min = TIME_T_MIN;
time_t l_time_max = TIME_T_MAX;
if (filetime_high == 0)
return FALSE;
/*
* Get the time as a double, in seconds and fractional seconds.
*/
d = ((double)filetime_high)*4.0*(double)(1<<30);
d += filetime_low;
d *= 1.0e-7;
/* Now adjust by 369 years, to make the seconds since 1970. */
d -= TIME_FIXUP_CONSTANT;
if (!(l_time_min <= d && d <= l_time_max))
return FALSE;
/*
* Get the time as seconds and nanoseconds.
*/
tv->secs = d;
tv->nsecs = (d - tv->secs)*1000000000;
return TRUE;
}
int
dissect_smb_64bit_time(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_date)
{
guint32 filetime_high, filetime_low;
nstime_t ts;
/* XXX there seems also to be another special time value which is fairly common :
0x40000000 00000000
the meaning of this one is yet unknown
*/
if (tree) {
filetime_low = tvb_get_letohl(tvb, offset);
filetime_high = tvb_get_letohl(tvb, offset + 4);
if (filetime_low == 0 && filetime_high == 0) {
proto_tree_add_text(tree, tvb, offset, 8,
"%s: No time specified (0)",
proto_registrar_get_name(hf_date));
} else if(filetime_low==0 && filetime_high==0x80000000){
proto_tree_add_text(tree, tvb, offset, 8,
"%s: Infinity (relative time)",
proto_registrar_get_name(hf_date));
} else if(filetime_low==0xffffffff && filetime_high==0x7fffffff){
proto_tree_add_text(tree, tvb, offset, 8,
"%s: Infinity (absolute time)",
proto_registrar_get_name(hf_date));
} else {
if (nt_time_to_nstime(filetime_high, filetime_low, &ts)) {
proto_tree_add_time(tree, hf_date, tvb,
offset, 8, &ts);
} else {
proto_tree_add_text(tree, tvb, offset, 8,
"%s: Time can't be converted",
proto_registrar_get_name(hf_date));
}
}
}
offset += 8;
return offset;
}
static int
dissect_smb_datetime(tvbuff_t *tvb, proto_tree *parent_tree, int offset,
int hf_date, int hf_dos_date, int hf_dos_time, gboolean time_first)
{
guint16 dos_time, dos_date;
proto_item *item = NULL;
proto_tree *tree = NULL;
struct tm tm;
time_t t;
static const int mday_noleap[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
static const int mday_leap[12] = {
31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
#define ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
nstime_t tv;
if (time_first) {
dos_time = tvb_get_letohs(tvb, offset);
dos_date = tvb_get_letohs(tvb, offset+2);
} else {
dos_date = tvb_get_letohs(tvb, offset);
dos_time = tvb_get_letohs(tvb, offset+2);
}
if ((dos_date == 0xffff && dos_time == 0xffff) ||
(dos_date == 0 && dos_time == 0)) {
/*
* No date/time specified.
*/
if(parent_tree){
proto_tree_add_text(parent_tree, tvb, offset, 4,
"%s: No time specified (0x%08x)",
proto_registrar_get_name(hf_date),
(dos_date << 16) | dos_time);
}
offset += 4;
return offset;
}
tm.tm_sec = (dos_time&0x1f)*2;
tm.tm_min = (dos_time>>5)&0x3f;
tm.tm_hour = (dos_time>>11)&0x1f;
tm.tm_mday = dos_date&0x1f;
tm.tm_mon = ((dos_date>>5)&0x0f) - 1;
tm.tm_year = ((dos_date>>9)&0x7f) + 1980 - 1900;
tm.tm_isdst = -1;
/*
* Do some sanity checks before calling "mktime()";
* "mktime()" doesn't do them, it "normalizes" out-of-range
* values.
*/
if (tm.tm_sec > 59 || tm.tm_min > 59 || tm.tm_hour > 23 ||
tm.tm_mon < 0 || tm.tm_mon > 11 ||
(ISLEAP(tm.tm_year + 1900) ?
tm.tm_mday > mday_leap[tm.tm_mon] :
tm.tm_mday > mday_noleap[tm.tm_mon]) ||
(t = mktime(&tm)) == -1) {
/*
* Invalid date/time.
*/
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset, 4,
"%s: Invalid time",
proto_registrar_get_name(hf_date));
tree = proto_item_add_subtree(item, ett_smb_time_date);
if (time_first) {
proto_tree_add_uint_format(tree, hf_dos_time, tvb, offset, 2, dos_time, "DOS Time: %02d:%02d:%02d (0x%04x)", tm.tm_hour, tm.tm_min, tm.tm_sec, dos_time);
proto_tree_add_uint_format(tree, hf_dos_date, tvb, offset+2, 2, dos_date, "DOS Date: %04d-%02d-%02d (0x%04x)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, dos_date);
} else {
proto_tree_add_uint_format(tree, hf_dos_date, tvb, offset, 2, dos_date, "DOS Date: %04d-%02d-%02d (0x%04x)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, dos_date);
proto_tree_add_uint_format(tree, hf_dos_time, tvb, offset+2, 2, dos_time, "DOS Time: %02d:%02d:%02d (0x%04x)", tm.tm_hour, tm.tm_min, tm.tm_sec, dos_time);
}
}
offset += 4;
return offset;
}
tv.secs = t;
tv.nsecs = 0;
if(parent_tree){
item = proto_tree_add_time(parent_tree, hf_date, tvb, offset, 4, &tv);
tree = proto_item_add_subtree(item, ett_smb_time_date);
if (time_first) {
proto_tree_add_uint_format(tree, hf_dos_time, tvb, offset, 2, dos_time, "DOS Time: %02d:%02d:%02d (0x%04x)", tm.tm_hour, tm.tm_min, tm.tm_sec, dos_time);
proto_tree_add_uint_format(tree, hf_dos_date, tvb, offset+2, 2, dos_date, "DOS Date: %04d-%02d-%02d (0x%04x)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, dos_date);
} else {
proto_tree_add_uint_format(tree, hf_dos_date, tvb, offset, 2, dos_date, "DOS Date: %04d-%02d-%02d (0x%04x)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, dos_date);
proto_tree_add_uint_format(tree, hf_dos_time, tvb, offset+2, 2, dos_time, "DOS Time: %02d:%02d:%02d (0x%04x)", tm.tm_hour, tm.tm_min, tm.tm_sec, dos_time);
}
}
offset += 4;
return offset;
}
static const value_string da_access_vals[] = {
{ 0, "Open for reading"},
{ 1, "Open for writing"},
{ 2, "Open for reading and writing"},
{ 3, "Open for execute"},
{0, NULL}
};
static const value_string da_sharing_vals[] = {
{ 0, "Compatibility mode"},
{ 1, "Deny read/write/execute (exclusive)"},
{ 2, "Deny write"},
{ 3, "Deny read/execute"},
{ 4, "Deny none"},
{0, NULL}
};
static const value_string da_locality_vals[] = {
{ 0, "Locality of reference unknown"},
{ 1, "Mainly sequential access"},
{ 2, "Mainly random access"},
{ 3, "Random access with some locality"},
{0, NULL}
};
static const true_false_string tfs_da_caching = {
"Do not cache this file",
"Caching permitted on this file"
};
static const true_false_string tfs_da_writetru = {
"Write through enabled",
"Write through disabled"
};
static int
dissect_access(tvbuff_t *tvb, proto_tree *parent_tree, int offset, char *type)
{
guint16 mask;
proto_item *item = NULL;
proto_tree *tree = NULL;
mask = tvb_get_letohs(tvb, offset);
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, 2,
"%s Access: 0x%04x", type, mask);
tree = proto_item_add_subtree(item, ett_smb_desiredaccess);
}
proto_tree_add_boolean(tree, hf_smb_access_writetru,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_access_caching,
tvb, offset, 2, mask);
proto_tree_add_uint(tree, hf_smb_access_locality,
tvb, offset, 2, mask);
proto_tree_add_uint(tree, hf_smb_access_sharing,
tvb, offset, 2, mask);
proto_tree_add_uint(tree, hf_smb_access_mode,
tvb, offset, 2, mask);
offset += 2;
return offset;
}
#define FILE_ATTRIBUTE_READ_ONLY 0x00000001
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
#define FILE_ATTRIBUTE_VOLUME 0x00000008
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
#define FILE_ATTRIBUTE_DEVICE 0x00000040
#define FILE_ATTRIBUTE_NORMAL 0x00000080
#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
#define FILE_ATTRIBUTE_SPARSE 0x00000200
#define FILE_ATTRIBUTE_REPARSE 0x00000400
#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
#define FILE_ATTRIBUTE_OFFLINE 0x00001000
#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
#define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
/*
* These are flags to be used in NT Create operations.
*/
#define FILE_ATTRIBUTE_WRITE_THROUGH 0x80000000
#define FILE_ATTRIBUTE_NO_BUFFERING 0x20000000
#define FILE_ATTRIBUTE_RANDOM_ACCESS 0x10000000
#define FILE_ATTRIBUTE_SEQUENTIAL_SCAN 0x08000000
#define FILE_ATTRIBUTE_DELETE_ON_CLOSE 0x04000000
#define FILE_ATTRIBUTE_BACKUP_SEMANTICS 0x02000000
#define FILE_ATTRIBUTE_POSIX_SEMANTICS 0x01000000
static const true_false_string tfs_file_attribute_write_through = {
"This object requires WRITE THROUGH",
"This object does NOT require write through",
};
static const true_false_string tfs_file_attribute_no_buffering = {
"This object requires NO BUFFERING",
"This object can be buffered",
};
static const true_false_string tfs_file_attribute_random_access = {
"This object will be RANDOM ACCESSed",
"Random access is NOT requested",
};
static const true_false_string tfs_file_attribute_sequential_scan = {
"This object is optimized for SEQUENTIAL SCAN",
"This object is NOT optimized for sequential scan",
};
static const true_false_string tfs_file_attribute_delete_on_close = {
"This object will be DELETED ON CLOSE",
"This object will not be deleted on close",
};
static const true_false_string tfs_file_attribute_backup_semantics = {
"This object supports BACKUP SEMANTICS",
"This object does NOT support backup semantics",
};
static const true_false_string tfs_file_attribute_posix_semantics = {
"This object supports POSIX SEMANTICS",
"This object does NOT support POSIX semantics",
};
static const true_false_string tfs_file_attribute_read_only = {
"This file is READ ONLY",
"This file is NOT read only",
};
static const true_false_string tfs_file_attribute_hidden = {
"This is a HIDDEN file",
"This is NOT a hidden file"
};
static const true_false_string tfs_file_attribute_system = {
"This is a SYSTEM file",
"This is NOT a system file"
};
static const true_false_string tfs_file_attribute_volume = {
"This is a VOLUME ID",
"This is NOT a volume ID"
};
static const true_false_string tfs_file_attribute_directory = {
"This is a DIRECTORY",
"This is NOT a directory"
};
static const true_false_string tfs_file_attribute_archive = {
"This is an ARCHIVE file",
"This is NOT an archive file"
};
static const true_false_string tfs_file_attribute_device = {
"This is a DEVICE",
"This is NOT a device"
};
static const true_false_string tfs_file_attribute_normal = {
"This file is an ordinary file",
"This file has some attribute set"
};
static const true_false_string tfs_file_attribute_temporary = {
"This is a TEMPORARY file",
"This is NOT a temporary file"
};
static const true_false_string tfs_file_attribute_sparse = {
"This is a SPARSE file",
"This is NOT a sparse file"
};
static const true_false_string tfs_file_attribute_reparse = {
"This file has an associated REPARSE POINT",
"This file does NOT have an associated reparse point"
};
static const true_false_string tfs_file_attribute_compressed = {
"This is a COMPRESSED file",
"This is NOT a compressed file"
};
static const true_false_string tfs_file_attribute_offline = {
"This file is OFFLINE",
"This file is NOT offline"
};
static const true_false_string tfs_file_attribute_not_content_indexed = {
"This file MAY NOT be indexed by the CONTENT INDEXING service",
"This file MAY be indexed by the content indexing service"
};
static const true_false_string tfs_file_attribute_encrypted = {
"This is an ENCRYPTED file",
"This is NOT an encrypted file"
};
static int
dissect_file_attributes(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
{
guint16 mask;
proto_item *item = NULL;
proto_tree *tree = NULL;
mask = tvb_get_letohs(tvb, offset);
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, 2,
"File Attributes: 0x%04x", mask);
tree = proto_item_add_subtree(item, ett_smb_file_attributes);
}
proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_16bit,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_16bit,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_system_16bit,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_volume_16bit,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_directory_16bit,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_archive_16bit,
tvb, offset, 2, mask);
offset += 2;
return offset;
}
/* 3.11 */
static int
dissect_file_ext_attr(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
{
guint32 mask;
proto_item *item = NULL;
proto_tree *tree = NULL;
mask = tvb_get_letohl(tvb, offset);
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, 4,
"File Attributes: 0x%08x", mask);
tree = proto_item_add_subtree(item, ett_smb_file_attributes);
}
/*
* XXX - Network Monitor disagrees on some of the
* bits, e.g. the bits above temporary are "atomic write"
* and "transaction write", and it says nothing about the
* bits above that.
*
* Does the Win32 API documentation, or the NT Native API book,
* suggest anything?
*/
proto_tree_add_boolean(tree, hf_smb_file_eattr_write_through,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_no_buffering,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_random_access,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_sequential_scan,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_delete_on_close,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_backup_semantics,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_posix_semantics,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_encrypted,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_not_content_indexed,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_offline,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_compressed,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_reparse,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_sparse,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_temporary,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_normal,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_device,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_archive,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_directory,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_volume,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_system,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_hidden,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_file_eattr_read_only,
tvb, offset, 4, mask);
offset += 4;
return offset;
}
static int
dissect_dir_info_file_attributes(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
{
guint8 mask;
proto_item *item = NULL;
proto_tree *tree = NULL;
mask = tvb_get_guint8(tvb, offset);
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, 1,
"File Attributes: 0x%02x", mask);
tree = proto_item_add_subtree(item, ett_smb_file_attributes);
}
proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_8bit,
tvb, offset, 1, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_8bit,
tvb, offset, 1, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_system_8bit,
tvb, offset, 1, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_volume_8bit,
tvb, offset, 1, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_directory_8bit,
tvb, offset, 1, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_archive_8bit,
tvb, offset, 1, mask);
offset += 1;
return offset;
}
static const true_false_string tfs_search_attribute_read_only = {
"Include READ ONLY files in search results",
"Do NOT include read only files in search results",
};
static const true_false_string tfs_search_attribute_hidden = {
"Include HIDDEN files in search results",
"Do NOT include hidden files in search results"
};
static const true_false_string tfs_search_attribute_system = {
"Include SYSTEM files in search results",
"Do NOT include system files in search results"
};
static const true_false_string tfs_search_attribute_volume = {
"Include VOLUME IDs in search results",
"Do NOT include volume IDs in search results"
};
static const true_false_string tfs_search_attribute_directory = {
"Include DIRECTORIES in search results",
"Do NOT include directories in search results"
};
static const true_false_string tfs_search_attribute_archive = {
"Include ARCHIVE files in search results",
"Do NOT include archive files in search results"
};
static int
dissect_search_attributes(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
{
guint16 mask;
proto_item *item = NULL;
proto_tree *tree = NULL;
mask = tvb_get_letohs(tvb, offset);
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, 2,
"Search Attributes: 0x%04x", mask);
tree = proto_item_add_subtree(item, ett_smb_search);
}
proto_tree_add_boolean(tree, hf_smb_search_attribute_read_only,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_search_attribute_hidden,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_search_attribute_system,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_search_attribute_volume,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_search_attribute_directory,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_search_attribute_archive,
tvb, offset, 2, mask);
offset += 2;
return offset;
}
#if 0
/*
* XXX - this isn't used.
* Is this used for anything? NT Create AndX doesn't use it.
* Is there some 16-bit attribute field with more bits than Read Only,
* Hidden, System, Volume ID, Directory, and Archive?
*/
static int
dissect_extended_file_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
{
guint32 mask;
proto_item *item = NULL;
proto_tree *tree = NULL;
mask = tvb_get_letohl(tvb, offset);
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, 2,
"File Attributes: 0x%08x", mask);
tree = proto_item_add_subtree(item, ett_smb_file_attributes);
}
proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_16bit,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_16bit,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_system_16bit,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_volume_16bit,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_directory_16bit,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_archive_16bit,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_device,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_normal,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_temporary,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_sparse,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_reparse,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_compressed,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_offline,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_not_content_indexed,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_file_attr_encrypted,
tvb, offset, 2, mask);
offset += 2;
return offset;
}
#endif
#define SERVER_CAP_RAW_MODE 0x00000001
#define SERVER_CAP_MPX_MODE 0x00000002
#define SERVER_CAP_UNICODE 0x00000004
#define SERVER_CAP_LARGE_FILES 0x00000008
#define SERVER_CAP_NT_SMBS 0x00000010
#define SERVER_CAP_RPC_REMOTE_APIS 0x00000020
#define SERVER_CAP_STATUS32 0x00000040
#define SERVER_CAP_LEVEL_II_OPLOCKS 0x00000080
#define SERVER_CAP_LOCK_AND_READ 0x00000100
#define SERVER_CAP_NT_FIND 0x00000200
#define SERVER_CAP_DFS 0x00001000
#define SERVER_CAP_INFOLEVEL_PASSTHRU 0x00002000
#define SERVER_CAP_LARGE_READX 0x00004000
#define SERVER_CAP_LARGE_WRITEX 0x00008000
#define SERVER_CAP_UNIX 0x00800000
#define SERVER_CAP_RESERVED 0x02000000
#define SERVER_CAP_BULK_TRANSFER 0x20000000
#define SERVER_CAP_COMPRESSED_DATA 0x40000000
#define SERVER_CAP_EXTENDED_SECURITY 0x80000000
static const true_false_string tfs_server_cap_raw_mode = {
"Read Raw and Write Raw are supported",
"Read Raw and Write Raw are not supported"
};
static const true_false_string tfs_server_cap_mpx_mode = {
"Read Mpx and Write Mpx are supported",
"Read Mpx and Write Mpx are not supported"
};
static const true_false_string tfs_server_cap_unicode = {
"Unicode strings are supported",
"Unicode strings are not supported"
};
static const true_false_string tfs_server_cap_large_files = {
"Large files are supported",
"Large files are not supported",
};
static const true_false_string tfs_server_cap_nt_smbs = {
"NT SMBs are supported",
"NT SMBs are not supported"
};
static const true_false_string tfs_server_cap_rpc_remote_apis = {
"RPC remote APIs are supported",
"RPC remote APIs are not supported"
};
static const true_false_string tfs_server_cap_nt_status = {
"NT status codes are supported",
"NT status codes are not supported"
};
static const true_false_string tfs_server_cap_level_ii_oplocks = {
"Level 2 oplocks are supported",
"Level 2 oplocks are not supported"
};
static const true_false_string tfs_server_cap_lock_and_read = {
"Lock and Read is supported",
"Lock and Read is not supported"
};
static const true_false_string tfs_server_cap_nt_find = {
"NT Find is supported",
"NT Find is not supported"
};
static const true_false_string tfs_server_cap_dfs = {
"Dfs is supported",
"Dfs is not supported"
};
static const true_false_string tfs_server_cap_infolevel_passthru = {
"NT information level request passthrough is supported",
"NT information level request passthrough is not supported"
};
static const true_false_string tfs_server_cap_large_readx = {
"Large Read andX is supported",
"Large Read andX is not supported"
};
static const true_false_string tfs_server_cap_large_writex = {
"Large Write andX is supported",
"Large Write andX is not supported"
};
static const true_false_string tfs_server_cap_unix = {
"UNIX extensions are supported",
"UNIX extensions are not supported"
};
static const true_false_string tfs_server_cap_reserved = {
"Reserved",
"Reserved"
};
static const true_false_string tfs_server_cap_bulk_transfer = {
"Bulk Read and Bulk Write are supported",
"Bulk Read and Bulk Write are not supported"
};
static const true_false_string tfs_server_cap_compressed_data = {
"Compressed data transfer is supported",
"Compressed data transfer is not supported"
};
static const true_false_string tfs_server_cap_extended_security = {
"Extended security exchanges are supported",
"Extended security exchanges are not supported"
};
static int
dissect_negprot_capabilities(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
{
guint32 mask;
proto_item *item = NULL;
proto_tree *tree = NULL;
mask = tvb_get_letohl(tvb, offset);
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, 4, "Capabilities: 0x%08x", mask);
tree = proto_item_add_subtree(item, ett_smb_capabilities);
}
proto_tree_add_boolean(tree, hf_smb_server_cap_raw_mode,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_mpx_mode,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_unicode,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_large_files,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_nt_smbs,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_rpc_remote_apis,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_nt_status,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_level_ii_oplocks,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_lock_and_read,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_nt_find,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_dfs,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_infolevel_passthru,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_large_readx,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_large_writex,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_unix,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_reserved,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_bulk_transfer,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_compressed_data,
tvb, offset, 4, mask);
proto_tree_add_boolean(tree, hf_smb_server_cap_extended_security,
tvb, offset, 4, mask);
return mask;
}
#define RAWMODE_READ 0x01
#define RAWMODE_WRITE 0x02
static const true_false_string tfs_rm_read = {
"Read Raw is supported",
"Read Raw is not supported"
};
static const true_false_string tfs_rm_write = {
"Write Raw is supported",
"Write Raw is not supported"
};
static int
dissect_negprot_rawmode(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
{
guint16 mask;
proto_item *item = NULL;
proto_tree *tree = NULL;
mask = tvb_get_letohs(tvb, offset);
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, 2, "Raw Mode: 0x%04x", mask);
tree = proto_item_add_subtree(item, ett_smb_rawmode);
}
proto_tree_add_boolean(tree, hf_smb_rm_read, tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_rm_write, tvb, offset, 2, mask);
offset += 2;
return offset;
}
#define SECURITY_MODE_MODE 0x01
#define SECURITY_MODE_PASSWORD 0x02
#define SECURITY_MODE_SIGNATURES 0x04
#define SECURITY_MODE_SIG_REQUIRED 0x08
static const true_false_string tfs_sm_mode = {
"USER security mode",
"SHARE security mode"
};
static const true_false_string tfs_sm_password = {
"ENCRYPTED password. Use challenge/response",
"PLAINTEXT password"
};
static const true_false_string tfs_sm_signatures = {
"Security signatures ENABLED",
"Security signatures NOT enabled"
};
static const true_false_string tfs_sm_sig_required = {
"Security signatures REQUIRED",
"Security signatures NOT required"
};
static int
dissect_negprot_security_mode(tvbuff_t *tvb, proto_tree *parent_tree, int offset, int wc)
{
guint16 mask = 0;
proto_item *item = NULL;
proto_tree *tree = NULL;
switch(wc){
case 13:
mask = tvb_get_letohs(tvb, offset);
item = proto_tree_add_text(parent_tree, tvb, offset, 2,
"Security Mode: 0x%04x", mask);
tree = proto_item_add_subtree(item, ett_smb_mode);
proto_tree_add_boolean(tree, hf_smb_sm_mode16, tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_sm_password16, tvb, offset, 2, mask);
offset += 2;
break;
case 17:
mask = tvb_get_guint8(tvb, offset);
item = proto_tree_add_text(parent_tree, tvb, offset, 1,
"Security Mode: 0x%02x", mask);
tree = proto_item_add_subtree(item, ett_smb_mode);
proto_tree_add_boolean(tree, hf_smb_sm_mode, tvb, offset, 1, mask);
proto_tree_add_boolean(tree, hf_smb_sm_password, tvb, offset, 1, mask);
proto_tree_add_boolean(tree, hf_smb_sm_signatures, tvb, offset, 1, mask);
proto_tree_add_boolean(tree, hf_smb_sm_sig_required, tvb, offset, 1, mask);
offset += 1;
break;
}
return offset;
}
static int
dissect_negprot_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
proto_item *it = NULL;
proto_tree *tr = NULL;
guint16 bc;
guint8 wc;
WORD_COUNT;
BYTE_COUNT;
if(tree){
it = proto_tree_add_text(tree, tvb, offset, bc,
"Requested Dialects");
tr = proto_item_add_subtree(it, ett_smb_dialects);
}
while(bc){
int len;
const guint8 *str;
proto_item *dit = NULL;
proto_tree *dtr = NULL;
/* XXX - what if this runs past bc? */
len = tvb_strsize(tvb, offset+1);
str = tvb_get_ptr(tvb, offset+1, len);
if(tr){
dit = proto_tree_add_text(tr, tvb, offset, len+1,
"Dialect: %s", str);
dtr = proto_item_add_subtree(dit, ett_smb_dialect);
}
/* Buffer Format */
CHECK_BYTE_COUNT(1);
proto_tree_add_item(dtr, hf_smb_buffer_format, tvb, offset, 1,
TRUE);
COUNT_BYTES(1);
/*Dialect Name */
CHECK_BYTE_COUNT(len);
proto_tree_add_string(dtr, hf_smb_dialect_name, tvb, offset,
len, str);
COUNT_BYTES(len);
}
END_OF_SMB
return offset;
}
static int
dissect_negprot_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
guint8 wc;
guint16 dialect;
const char *dn;
int dn_len;
guint16 bc;
guint16 ekl=0;
guint32 caps=0;
gint16 tz;
WORD_COUNT;
/* Dialect Index */
dialect = tvb_get_letohs(tvb, offset);
switch(wc){
case 1:
if(dialect==0xffff){
proto_tree_add_uint_format(tree, hf_smb_dialect_index,
tvb, offset, 2, dialect,
"Selected Index: -1, PC NETWORK PROGRAM 1.0 choosen");
} else {
proto_tree_add_uint(tree, hf_smb_dialect_index,
tvb, offset, 2, dialect);
}
break;
case 13:
proto_tree_add_uint_format(tree, hf_smb_dialect_index,
tvb, offset, 2, dialect,
"Dialect Index: %u, Greater than CORE PROTOCOL and up to LANMAN2.1", dialect);
break;
case 17:
proto_tree_add_uint_format(tree, hf_smb_dialect_index,
tvb, offset, 2, dialect,
"Dialect Index: %u, greater than LANMAN2.1", dialect);
break;
default:
proto_tree_add_text(tree, tvb, offset, wc*2,
"Words for unknown response format");
offset += wc*2;
goto bytecount;
}
offset += 2;
switch(wc){
case 13:
/* Security Mode */
offset = dissect_negprot_security_mode(tvb, tree, offset, wc);
/* Maximum Transmit Buffer Size */
proto_tree_add_item(tree, hf_smb_max_trans_buf_size,
tvb, offset, 2, TRUE);
offset += 2;
/* Maximum Multiplex Count */
proto_tree_add_item(tree, hf_smb_max_mpx_count,
tvb, offset, 2, TRUE);
offset += 2;
/* Maximum Vcs Number */
proto_tree_add_item(tree, hf_smb_max_vcs_num,
tvb, offset, 2, TRUE);
offset += 2;
/* raw mode */
offset = dissect_negprot_rawmode(tvb, tree, offset);
/* session key */
proto_tree_add_item(tree, hf_smb_session_key,
tvb, offset, 4, TRUE);
offset += 4;
/* current time and date at server */
offset = dissect_smb_datetime(tvb, tree, offset, hf_smb_server_date_time, hf_smb_server_smb_date, hf_smb_server_smb_time,
TRUE);
/* time zone */
tz = tvb_get_letohs(tvb, offset);
proto_tree_add_int_format(tree, hf_smb_server_timezone, tvb, offset, 2, tz, "Server Time Zone: %d min from UTC", tz);
offset += 2;
/* encryption key length */
ekl = tvb_get_letohs(tvb, offset);
proto_tree_add_uint(tree, hf_smb_encryption_key_length, tvb, offset, 2, ekl);
offset += 2;
/* 2 reserved bytes */
proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
offset += 2;
break;
case 17:
/* Security Mode */
offset = dissect_negprot_security_mode(tvb, tree, offset, wc);
/* Maximum Multiplex Count */
proto_tree_add_item(tree, hf_smb_max_mpx_count,
tvb, offset, 2, TRUE);
offset += 2;
/* Maximum Vcs Number */
proto_tree_add_item(tree, hf_smb_max_vcs_num,
tvb, offset, 2, TRUE);
offset += 2;
/* Maximum Transmit Buffer Size */
proto_tree_add_item(tree, hf_smb_max_trans_buf_size,
tvb, offset, 4, TRUE);
offset += 4;
/* maximum raw buffer size */
proto_tree_add_item(tree, hf_smb_max_raw_buf_size,
tvb, offset, 4, TRUE);
offset += 4;
/* session key */
proto_tree_add_item(tree, hf_smb_session_key,
tvb, offset, 4, TRUE);
offset += 4;
/* server capabilities */
caps = dissect_negprot_capabilities(tvb, tree, offset);
offset += 4;
/* system time */
offset = dissect_smb_64bit_time(tvb, tree, offset,
hf_smb_system_time);
/* time zone */
tz = tvb_get_letohs(tvb, offset);
proto_tree_add_int_format(tree, hf_smb_server_timezone,
tvb, offset, 2, tz,
"Server Time Zone: %d min from UTC", tz);
offset += 2;
/* encryption key length */
ekl = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(tree, hf_smb_encryption_key_length,
tvb, offset, 1, ekl);
offset += 1;
break;
}
BYTE_COUNT;
switch(wc){
case 13:
/* challenge/response encryption key */
if(ekl){
CHECK_BYTE_COUNT(ekl);
proto_tree_add_item(tree, hf_smb_encryption_key, tvb, offset, ekl, TRUE);
COUNT_BYTES(ekl);
}
/*
* Primary domain.
*
* XXX - not present if negotiated dialect isn't
* "DOS LANMAN 2.1" or "LANMAN2.1", but we'd either
* have to see the request, or assume what dialect strings
* were sent, to determine that.
*
* Is this something other than a primary domain if the
* negotiated dialect is Windows for Workgroups 3.1a?
* It appears to be 8 bytes of binary data in at least
* one capture - is that an encryption key or something
* such as that?
*/
dn = get_unicode_or_ascii_string(tvb, &offset,
pinfo, &dn_len, FALSE, FALSE, &bc);
if (dn == NULL)
goto endofcommand;
proto_tree_add_string(tree, hf_smb_primary_domain, tvb,
offset, dn_len,dn);
COUNT_BYTES(dn_len);
break;
case 17:
if(!(caps&SERVER_CAP_EXTENDED_SECURITY)){
smb_info_t *si;
/* challenge/response encryption key */
/* XXX - is this aligned on an even boundary? */
if(ekl){
CHECK_BYTE_COUNT(ekl);
proto_tree_add_item(tree, hf_smb_encryption_key,
tvb, offset, ekl, TRUE);
COUNT_BYTES(ekl);
}
/* domain */
/* this string is special, unicode is flagged in caps */
/* This string is NOT padded to be 16bit aligned. (seen in actual capture) */
si = pinfo->private_data;
si->unicode = (caps&SERVER_CAP_UNICODE);
dn = get_unicode_or_ascii_string(tvb,
&offset, pinfo, &dn_len, TRUE, FALSE,
&bc);
if (dn == NULL)
goto endofcommand;
proto_tree_add_string(tree, hf_smb_primary_domain,
tvb, offset, dn_len, dn);
COUNT_BYTES(dn_len);
} else {
/* guid */
/* XXX - show it in the standard Microsoft format
for GUIDs? */
CHECK_BYTE_COUNT(16);
proto_tree_add_item(tree, hf_smb_server_guid,
tvb, offset, 16, TRUE);
COUNT_BYTES(16);
/* security blob */
/* XXX - is this ASN.1-encoded? Is it a Kerberos
data structure, at least in NT 5.0-and-later
server replies? */
if(bc){
proto_tree_add_item(tree, hf_smb_security_blob,
tvb, offset, bc, TRUE);
COUNT_BYTES(bc);
}
}
break;
}
END_OF_SMB
return offset;
}
static int
dissect_old_dir_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
int dn_len;
const char *dn;
guint8 wc;
guint16 bc;
WORD_COUNT;
BYTE_COUNT;
/* buffer format */
CHECK_BYTE_COUNT(1);
proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
COUNT_BYTES(1);
/* dir name */
dn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &dn_len,
FALSE, FALSE, &bc);
if (dn == NULL)
goto endofcommand;
proto_tree_add_string(tree, hf_smb_dir_name, tvb, offset, dn_len,
dn);
COUNT_BYTES(dn_len);
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Directory: %s", dn);
}
END_OF_SMB
return offset;
}
static int
dissect_empty(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
guint8 wc;
guint16 bc;
WORD_COUNT;
BYTE_COUNT;
END_OF_SMB
return offset;
}
static int
dissect_echo_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
guint16 ec, bc;
guint8 wc;
WORD_COUNT;
/* echo count */
ec = tvb_get_letohs(tvb, offset);
proto_tree_add_uint(tree, hf_smb_echo_count, tvb, offset, 2, ec);
offset += 2;
BYTE_COUNT;
if (bc != 0) {
/* echo data */
proto_tree_add_item(tree, hf_smb_echo_data, tvb, offset, bc, TRUE);
COUNT_BYTES(bc);
}
END_OF_SMB
return offset;
}
static int
dissect_echo_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
guint16 bc;
guint8 wc;
WORD_COUNT;
/* echo sequence number */
proto_tree_add_item(tree, hf_smb_echo_seq_num, tvb, offset, 2, TRUE);
offset += 2;
BYTE_COUNT;
if (bc != 0) {
/* echo data */
proto_tree_add_item(tree, hf_smb_echo_data, tvb, offset, bc, TRUE);
COUNT_BYTES(bc);
}
END_OF_SMB
return offset;
}
static int
dissect_tree_connect_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
int an_len, pwlen;
const char *an;
guint8 wc;
guint16 bc;
WORD_COUNT;
BYTE_COUNT;
/* buffer format */
CHECK_BYTE_COUNT(1);
proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
COUNT_BYTES(1);
/* Path */
an = get_unicode_or_ascii_string(tvb, &offset,
pinfo, &an_len, FALSE, FALSE, &bc);
if (an == NULL)
goto endofcommand;
proto_tree_add_string(tree, hf_smb_path, tvb,
offset, an_len, an);
COUNT_BYTES(an_len);
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", an);
}
/* buffer format */
CHECK_BYTE_COUNT(1);
proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
COUNT_BYTES(1);
/* password, ANSI */
/* XXX - what if this runs past bc? */
pwlen = tvb_strsize(tvb, offset);
CHECK_BYTE_COUNT(pwlen);
proto_tree_add_item(tree, hf_smb_password,
tvb, offset, pwlen, TRUE);
COUNT_BYTES(pwlen);
/* buffer format */
CHECK_BYTE_COUNT(1);
proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
COUNT_BYTES(1);
/* Service */
an = get_unicode_or_ascii_string(tvb, &offset,
pinfo, &an_len, FALSE, FALSE, &bc);
if (an == NULL)
goto endofcommand;
proto_tree_add_string(tree, hf_smb_service, tvb,
offset, an_len, an);
COUNT_BYTES(an_len);
END_OF_SMB
return offset;
}
static int
dissect_tree_connect_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
guint8 wc;
guint16 bc;
WORD_COUNT;
/* Maximum Buffer Size */
proto_tree_add_item(tree, hf_smb_max_buf_size, tvb, offset, 2, TRUE);
offset += 2;
/* tid */
proto_tree_add_item(tree, hf_smb_tid, tvb, offset, 2, TRUE);
offset += 2;
BYTE_COUNT;
END_OF_SMB
return offset;
}
static const true_false_string tfs_of_create = {
"Create file if it does not exist",
"Fail if file does not exist"
};
static const value_string of_open[] = {
{ 0, "Fail if file exists"},
{ 1, "Open file if it exists"},
{ 2, "Truncate file if it exists"},
{0, NULL}
};
static int
dissect_open_function(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
{
guint16 mask;
proto_item *item = NULL;
proto_tree *tree = NULL;
mask = tvb_get_letohs(tvb, offset);
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, 2,
"Open Function: 0x%04x", mask);
tree = proto_item_add_subtree(item, ett_smb_openfunction);
}
proto_tree_add_boolean(tree, hf_smb_open_function_create,
tvb, offset, 2, mask);
proto_tree_add_uint(tree, hf_smb_open_function_open,
tvb, offset, 2, mask);
offset += 2;
return offset;
}
static const true_false_string tfs_mf_file = {
"Target must be a file",
"Target needn't be a file"
};
static const true_false_string tfs_mf_dir = {
"Target must be a directory",
"Target needn't be a directory"
};
static const true_false_string tfs_mf_verify = {
"MUST verify all writes",
"Don't have to verify writes"
};
static int
dissect_move_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
{
guint16 mask;
proto_item *item = NULL;
proto_tree *tree = NULL;
mask = tvb_get_letohs(tvb, offset);
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, 2,
"Flags: 0x%04x", mask);
tree = proto_item_add_subtree(item, ett_smb_move_copy_flags);
}
proto_tree_add_boolean(tree, hf_smb_move_flags_verify,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_move_flags_dir,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_move_flags_file,
tvb, offset, 2, mask);
offset += 2;
return offset;
}
static const true_false_string tfs_cf_mode = {
"ASCII",
"Binary"
};
static const true_false_string tfs_cf_tree_copy = {
"Copy is a tree copy",
"Copy is a file copy"
};
static const true_false_string tfs_cf_ea_action = {
"Fail copy",
"Discard EAs"
};
static int
dissect_copy_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
{
guint16 mask;
proto_item *item = NULL;
proto_tree *tree = NULL;
mask = tvb_get_letohs(tvb, offset);
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, 2,
"Flags: 0x%04x", mask);
tree = proto_item_add_subtree(item, ett_smb_move_copy_flags);
}
proto_tree_add_boolean(tree, hf_smb_copy_flags_ea_action,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_copy_flags_tree_copy,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_copy_flags_verify,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_copy_flags_source_mode,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_copy_flags_dest_mode,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_copy_flags_dir,
tvb, offset, 2, mask);
proto_tree_add_boolean(tree, hf_smb_copy_flags_file,
tvb, offset, 2, mask);
offset += 2;
return offset;
}
static int
dissect_move_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
int fn_len;
guint16 tid;
guint16 bc;
guint8 wc;
const char *fn;
WORD_COUNT;
/* tid */
tid = tvb_get_letohs(tvb, offset);
proto_tree_add_uint_format(tree, hf_smb_tid, tvb, offset, 2, tid,
"TID (target): 0x%04x", tid);
offset += 2;
/* open function */
offset = dissect_open_function(tvb, tree, offset);
/* move flags */
offset = dissect_move_flags(tvb, tree, offset);
BYTE_COUNT;
/* buffer format */
CHECK_BYTE_COUNT(1);
proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
COUNT_BYTES(1);
/* file name */
fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
FALSE, FALSE, &bc);
if (fn == NULL)
goto endofcommand;
proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
fn_len, fn, "Old File Name: %s", fn);
COUNT_BYTES(fn_len);
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Old Name: %s", fn);
}
/* buffer format */
CHECK_BYTE_COUNT(1);
proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
COUNT_BYTES(1);
/* file name */
fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
FALSE, FALSE, &bc);
if (fn == NULL)
goto endofcommand;
proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
fn_len, fn, "New File Name: %s", fn);
COUNT_BYTES(fn_len);
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", New Name: %s", fn);
}
END_OF_SMB
return offset;
}
static int
dissect_copy_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
int fn_len;
guint16 tid;
guint16 bc;
guint8 wc;
const char *fn;
WORD_COUNT;
/* tid */
tid = tvb_get_letohs(tvb, offset);
proto_tree_add_uint_format(tree, hf_smb_tid, tvb, offset, 2, tid,
"TID (target): 0x%04x", tid);
offset += 2;
/* open function */
offset = dissect_open_function(tvb, tree, offset);
/* copy flags */
offset = dissect_copy_flags(tvb, tree, offset);
BYTE_COUNT;
/* buffer format */
CHECK_BYTE_COUNT(1);
proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
COUNT_BYTES(1);
/* file name */
fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
FALSE, FALSE, &bc);
if (fn == NULL)
goto endofcommand;
proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
fn_len, fn, "Source File Name: %s", fn);
COUNT_BYTES(fn_len);
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Source Name: %s", fn);
}
/* buffer format */
CHECK_BYTE_COUNT(1);
proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
COUNT_BYTES(1);
/* file name */
fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
FALSE, FALSE, &bc);
if (fn == NULL)
goto endofcommand;
proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
fn_len, fn, "Destination File Name: %s", fn);
COUNT_BYTES(fn_len);
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Destination Name: %s", fn);
}
END_OF_SMB
return offset;
}
static int
dissect_move_copy_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
int fn_len;
const char *fn;
guint8 wc;
guint16 bc;
WORD_COUNT;
/* # of files moved */
proto_tree_add_item(tree, hf_smb_files_moved, tvb, offset, 2, TRUE);
offset += 2;
BYTE_COUNT;
/* buffer format */
CHECK_BYTE_COUNT(1);
proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
COUNT_BYTES(1);
/* file name */
fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
FALSE, FALSE, &bc);
if (fn == NULL)
goto endofcommand;
proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
fn);
COUNT_BYTES(fn_len);
END_OF_SMB
return offset;
}
static int
dissect_open_file_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
int fn_len;
const char *fn;
guint8 wc;
guint16 bc;
WORD_COUNT;
/* desired access */
offset = dissect_access(tvb, tree, offset, "Desired");
/* Search Attributes */
offset = dissect_search_attributes(tvb, tree, offset);
BYTE_COUNT;
/* buffer format */
CHECK_BYTE_COUNT(1);
proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
COUNT_BYTES(1);
/* file name */
fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
FALSE, FALSE, &bc);
if (fn == NULL)
goto endofcommand;
proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
fn);
COUNT_BYTES(fn_len);
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
}
END_OF_SMB
return offset;
}
void
add_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
int len, guint16 fid)
{
proto_tree_add_uint(tree, hf_smb_fid, tvb, offset, len, fid);
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, ", FID: 0x%04x", fid);
}
static int
dissect_open_file_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
guint8 wc;
guint16 bc;
guint16 fid;
WORD_COUNT;
/* fid */
fid = tvb_get_letohs(