Removed trailing whitespaces from .h and .c files using the
[obnox/wireshark/wip.git] / packet-smb.c
1 /* packet-smb.c
2  * Routines for smb packet dissection
3  * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
4  * 2001  Rewrite by Ronnie Sahlberg and Guy Harris
5  *
6  * $Id: packet-smb.c,v 1.283 2002/08/25 22:57:26 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * Copied from packet-pop.c
13  * 
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  * 
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <stdio.h>
34
35 #include <time.h>
36 #include <string.h>
37 #include <glib.h>
38 #include <ctype.h>
39 #include <epan/packet.h>
40 #include <epan/conversation.h>
41 #include "smb.h"
42 #include "alignment.h"
43 #include <epan/strutil.h>
44 #include "prefs.h"
45 #include "reassemble.h"
46
47 #include "packet-smb-common.h"
48 #include "packet-smb-mailslot.h"
49 #include "packet-smb-pipe.h"
50
51 /*
52  * Various specifications and documents about SMB can be found in
53  *
54  *      ftp://ftp.microsoft.com/developr/drg/CIFS/
55  *
56  * and a CIFS specification from the Storage Networking Industry Association
57  * can be found on a link from the page at
58  *
59  *      http://www.snia.org/English/Collaterals/Work_Group_Docs/NAS/CIFS/CIFS_Technical_Reference.pdf
60  *
61  * (it supercedes the document at
62  *
63  *      ftp://ftp.microsoft.com/developr/drg/CIFS/draft-leach-cifs-v1-spec-01.txt
64  *
65  * ).
66  *
67  * There are also some Open Group publications documenting CIFS for sale;
68  * catalog entries for them are at:
69  *
70  *      http://www.opengroup.org/products/publications/catalog/c209.htm
71  *
72  *      http://www.opengroup.org/products/publications/catalog/c195.htm
73  *
74  * The document "NT LAN Manager SMB File Sharing Protocol Extensions"
75  * can be found at
76  *
77  *      http://www.samba.org/samba/ftp/specs/smb-nt01.doc
78  *
79  * (or, presumably a similar path under the Samba mirrors).  As the
80  * ".doc" indicates, it's a Word document.  Some of the specs from the
81  * Microsoft FTP site can be found in the
82  *
83  *      http://www.samba.org/samba/ftp/specs/
84  *
85  * directory as well.
86  *
87  * Beware - these specs may have errors.
88  */
89 static int proto_smb = -1;
90 static int hf_smb_cmd = -1;
91 static int hf_smb_pid = -1;
92 static int hf_smb_tid = -1;
93 static int hf_smb_uid = -1;
94 static int hf_smb_mid = -1;
95 static int hf_smb_response_to = -1;
96 static int hf_smb_time = -1;
97 static int hf_smb_response_in = -1;
98 static int hf_smb_continuation_to = -1;
99 static int hf_smb_nt_status = -1;
100 static int hf_smb_error_class = -1;
101 static int hf_smb_error_code = -1;
102 static int hf_smb_reserved = -1;
103 static int hf_smb_flags_lock = -1;
104 static int hf_smb_flags_receive_buffer = -1;
105 static int hf_smb_flags_caseless = -1;
106 static int hf_smb_flags_canon = -1;
107 static int hf_smb_flags_oplock = -1;
108 static int hf_smb_flags_notify = -1;
109 static int hf_smb_flags_response = -1;
110 static int hf_smb_flags2_long_names_allowed = -1;
111 static int hf_smb_flags2_ea = -1;
112 static int hf_smb_flags2_sec_sig = -1;
113 static int hf_smb_flags2_long_names_used = -1;
114 static int hf_smb_flags2_esn = -1;
115 static int hf_smb_flags2_dfs = -1;
116 static int hf_smb_flags2_roe = -1;
117 static int hf_smb_flags2_nt_error = -1;
118 static int hf_smb_flags2_string = -1;
119 static int hf_smb_word_count = -1;
120 static int hf_smb_byte_count = -1;
121 static int hf_smb_buffer_format = -1;
122 static int hf_smb_dialect_name = -1;
123 static int hf_smb_dialect_index = -1;
124 static int hf_smb_max_trans_buf_size = -1;
125 static int hf_smb_max_mpx_count = -1;
126 static int hf_smb_max_vcs_num = -1;
127 static int hf_smb_session_key = -1;
128 static int hf_smb_server_timezone = -1;
129 static int hf_smb_encryption_key_length = -1;
130 static int hf_smb_encryption_key = -1;
131 static int hf_smb_primary_domain = -1;
132 static int hf_smb_server = -1;
133 static int hf_smb_max_raw_buf_size = -1;
134 static int hf_smb_server_guid = -1;
135 static int hf_smb_security_blob_len = -1;
136 static int hf_smb_security_blob = -1;
137 static int hf_smb_sm_mode16 = -1;
138 static int hf_smb_sm_password16 = -1;
139 static int hf_smb_sm_mode = -1;
140 static int hf_smb_sm_password = -1;
141 static int hf_smb_sm_signatures = -1;
142 static int hf_smb_sm_sig_required = -1;
143 static int hf_smb_rm_read = -1;
144 static int hf_smb_rm_write = -1;
145 static int hf_smb_server_date_time = -1;
146 static int hf_smb_server_smb_date = -1;
147 static int hf_smb_server_smb_time = -1;
148 static int hf_smb_server_cap_raw_mode = -1;
149 static int hf_smb_server_cap_mpx_mode = -1;
150 static int hf_smb_server_cap_unicode = -1;
151 static int hf_smb_server_cap_large_files = -1;
152 static int hf_smb_server_cap_nt_smbs = -1;
153 static int hf_smb_server_cap_rpc_remote_apis = -1;
154 static int hf_smb_server_cap_nt_status = -1;
155 static int hf_smb_server_cap_level_ii_oplocks = -1;
156 static int hf_smb_server_cap_lock_and_read = -1;
157 static int hf_smb_server_cap_nt_find = -1;
158 static int hf_smb_server_cap_dfs = -1;
159 static int hf_smb_server_cap_infolevel_passthru = -1;
160 static int hf_smb_server_cap_large_readx = -1;
161 static int hf_smb_server_cap_large_writex = -1;
162 static int hf_smb_server_cap_unix = -1;
163 static int hf_smb_server_cap_reserved = -1;
164 static int hf_smb_server_cap_bulk_transfer = -1;
165 static int hf_smb_server_cap_compressed_data = -1;
166 static int hf_smb_server_cap_extended_security = -1;
167 static int hf_smb_system_time = -1;
168 static int hf_smb_unknown = -1;
169 static int hf_smb_dir_name = -1;
170 static int hf_smb_echo_count = -1;
171 static int hf_smb_echo_data = -1;
172 static int hf_smb_echo_seq_num = -1;
173 static int hf_smb_max_buf_size = -1;
174 static int hf_smb_password = -1;
175 static int hf_smb_password_len = -1;
176 static int hf_smb_ansi_password = -1;
177 static int hf_smb_ansi_password_len = -1;
178 static int hf_smb_unicode_password = -1;
179 static int hf_smb_unicode_password_len = -1;
180 static int hf_smb_path = -1;
181 static int hf_smb_service = -1;
182 static int hf_smb_move_flags_file = -1;
183 static int hf_smb_move_flags_dir = -1;
184 static int hf_smb_move_flags_verify = -1;
185 static int hf_smb_files_moved = -1;
186 static int hf_smb_copy_flags_file = -1;
187 static int hf_smb_copy_flags_dir = -1;
188 static int hf_smb_copy_flags_dest_mode = -1;
189 static int hf_smb_copy_flags_source_mode = -1;
190 static int hf_smb_copy_flags_verify = -1;
191 static int hf_smb_copy_flags_tree_copy = -1;
192 static int hf_smb_copy_flags_ea_action = -1;
193 static int hf_smb_count = -1;
194 static int hf_smb_file_name = -1;
195 static int hf_smb_open_function_open = -1;
196 static int hf_smb_open_function_create = -1;
197 static int hf_smb_fid = -1;
198 static int hf_smb_file_attr_read_only_16bit = -1;
199 static int hf_smb_file_attr_read_only_8bit = -1;
200 static int hf_smb_file_attr_hidden_16bit = -1;
201 static int hf_smb_file_attr_hidden_8bit = -1;
202 static int hf_smb_file_attr_system_16bit = -1;
203 static int hf_smb_file_attr_system_8bit = -1;
204 static int hf_smb_file_attr_volume_16bit = -1;
205 static int hf_smb_file_attr_volume_8bit = -1;
206 static int hf_smb_file_attr_directory_16bit = -1;
207 static int hf_smb_file_attr_directory_8bit = -1;
208 static int hf_smb_file_attr_archive_16bit = -1;
209 static int hf_smb_file_attr_archive_8bit = -1;
210 static int hf_smb_file_attr_device = -1;
211 static int hf_smb_file_attr_normal = -1;
212 static int hf_smb_file_attr_temporary = -1;
213 static int hf_smb_file_attr_sparse = -1;
214 static int hf_smb_file_attr_reparse = -1;
215 static int hf_smb_file_attr_compressed = -1;
216 static int hf_smb_file_attr_offline = -1;
217 static int hf_smb_file_attr_not_content_indexed = -1;
218 static int hf_smb_file_attr_encrypted = -1;
219 static int hf_smb_file_size = -1;
220 static int hf_smb_search_attribute_read_only = -1;
221 static int hf_smb_search_attribute_hidden = -1;
222 static int hf_smb_search_attribute_system = -1;
223 static int hf_smb_search_attribute_volume = -1;
224 static int hf_smb_search_attribute_directory = -1;
225 static int hf_smb_search_attribute_archive = -1;
226 static int hf_smb_access_mode = -1;
227 static int hf_smb_access_sharing = -1;
228 static int hf_smb_access_locality = -1;
229 static int hf_smb_access_caching = -1;
230 static int hf_smb_access_writetru = -1;
231 static int hf_smb_create_time = -1;
232 static int hf_smb_modify_time = -1;
233 static int hf_smb_backup_time = -1;
234 static int hf_smb_mac_alloc_block_count = -1;
235 static int hf_smb_mac_alloc_block_size = -1;
236 static int hf_smb_mac_free_block_count = -1;
237 static int hf_smb_mac_fndrinfo = -1;
238 static int hf_smb_mac_root_file_count = -1;
239 static int hf_smb_mac_root_dir_count = -1;
240 static int hf_smb_mac_file_count = -1;
241 static int hf_smb_mac_dir_count = -1;
242 static int hf_smb_mac_support_flags = -1;
243 static int hf_smb_mac_sup_access_ctrl = -1;
244 static int hf_smb_mac_sup_getset_comments = -1;
245 static int hf_smb_mac_sup_desktopdb_calls = -1;
246 static int hf_smb_mac_sup_unique_ids = -1;
247 static int hf_smb_mac_sup_streams = -1;
248 static int hf_smb_create_dos_date = -1;
249 static int hf_smb_create_dos_time = -1;
250 static int hf_smb_last_write_time = -1;
251 static int hf_smb_last_write_dos_date = -1;
252 static int hf_smb_last_write_dos_time = -1;
253 static int hf_smb_access_time = -1;
254 static int hf_smb_access_dos_date = -1;
255 static int hf_smb_access_dos_time = -1;
256 static int hf_smb_old_file_name = -1;
257 static int hf_smb_offset = -1;
258 static int hf_smb_remaining = -1;
259 static int hf_smb_padding = -1;
260 static int hf_smb_file_data = -1;
261 static int hf_smb_total_data_len = -1;
262 static int hf_smb_data_len = -1;
263 static int hf_smb_seek_mode = -1;
264 static int hf_smb_data_size = -1;
265 static int hf_smb_alloc_size = -1;
266 static int hf_smb_alloc_size64 = -1;
267 static int hf_smb_max_count = -1;
268 static int hf_smb_min_count = -1;
269 static int hf_smb_timeout = -1;
270 static int hf_smb_high_offset = -1;
271 static int hf_smb_units = -1;
272 static int hf_smb_bpu = -1;
273 static int hf_smb_blocksize = -1;
274 static int hf_smb_freeunits = -1;
275 static int hf_smb_data_offset = -1;
276 static int hf_smb_dcm = -1;
277 static int hf_smb_request_mask = -1;
278 static int hf_smb_response_mask = -1;
279 static int hf_smb_sid = -1;
280 static int hf_smb_write_mode_write_through = -1;
281 static int hf_smb_write_mode_return_remaining = -1;
282 static int hf_smb_write_mode_raw = -1;
283 static int hf_smb_write_mode_message_start = -1;
284 static int hf_smb_write_mode_connectionless = -1;
285 static int hf_smb_resume_key_len = -1;
286 static int hf_smb_resume_find_id = -1;
287 static int hf_smb_resume_server_cookie = -1;
288 static int hf_smb_resume_client_cookie = -1;
289 static int hf_smb_andxoffset = -1;
290 static int hf_smb_lock_type_large = -1;
291 static int hf_smb_lock_type_cancel = -1;
292 static int hf_smb_lock_type_change = -1;
293 static int hf_smb_lock_type_oplock = -1;
294 static int hf_smb_lock_type_shared = -1;
295 static int hf_smb_locking_ol = -1;
296 static int hf_smb_number_of_locks = -1;
297 static int hf_smb_number_of_unlocks = -1;
298 static int hf_smb_lock_long_offset = -1;
299 static int hf_smb_lock_long_length = -1;
300 static int hf_smb_file_type = -1;
301 static int hf_smb_ipc_state_nonblocking = -1;
302 static int hf_smb_ipc_state_endpoint = -1;
303 static int hf_smb_ipc_state_pipe_type = -1;
304 static int hf_smb_ipc_state_read_mode = -1;
305 static int hf_smb_ipc_state_icount = -1;
306 static int hf_smb_server_fid = -1;
307 static int hf_smb_open_flags_add_info = -1;
308 static int hf_smb_open_flags_ex_oplock = -1;
309 static int hf_smb_open_flags_batch_oplock = -1;
310 static int hf_smb_open_flags_ealen = -1;
311 static int hf_smb_open_action_open = -1;
312 static int hf_smb_open_action_lock = -1;
313 static int hf_smb_vc_num = -1;
314 static int hf_smb_account = -1;
315 static int hf_smb_os = -1;
316 static int hf_smb_lanman = -1;
317 static int hf_smb_setup_action_guest = -1;
318 static int hf_smb_fs = -1;
319 static int hf_smb_connect_flags_dtid = -1;
320 static int hf_smb_connect_support_search = -1;
321 static int hf_smb_connect_support_in_dfs = -1;
322 static int hf_smb_max_setup_count = -1;
323 static int hf_smb_total_param_count = -1;
324 static int hf_smb_total_data_count = -1;
325 static int hf_smb_max_param_count = -1;
326 static int hf_smb_max_data_count = -1;
327 static int hf_smb_param_disp16 = -1;
328 static int hf_smb_param_count16 = -1;
329 static int hf_smb_param_offset16 = -1;
330 static int hf_smb_param_disp32 = -1;
331 static int hf_smb_param_count32 = -1;
332 static int hf_smb_param_offset32 = -1;
333 static int hf_smb_data_disp16 = -1;
334 static int hf_smb_data_count16 = -1;
335 static int hf_smb_data_offset16 = -1;
336 static int hf_smb_data_disp32 = -1;
337 static int hf_smb_data_count32 = -1;
338 static int hf_smb_data_offset32 = -1;
339 static int hf_smb_setup_count = -1;
340 static int hf_smb_nt_trans_subcmd = -1;
341 static int hf_smb_nt_ioctl_function_code = -1;
342 static int hf_smb_nt_ioctl_isfsctl = -1;
343 static int hf_smb_nt_ioctl_flags_root_handle = -1;
344 static int hf_smb_nt_ioctl_data = -1;
345 #ifdef SMB_UNUSED_HANDLES
346 static int hf_smb_nt_security_information = -1;
347 #endif
348 static int hf_smb_nt_notify_action = -1;
349 static int hf_smb_nt_notify_watch_tree = -1;
350 static int hf_smb_nt_notify_stream_write = -1;
351 static int hf_smb_nt_notify_stream_size = -1;
352 static int hf_smb_nt_notify_stream_name = -1;
353 static int hf_smb_nt_notify_security = -1;
354 static int hf_smb_nt_notify_ea = -1;
355 static int hf_smb_nt_notify_creation = -1;
356 static int hf_smb_nt_notify_last_access = -1;
357 static int hf_smb_nt_notify_last_write = -1;
358 static int hf_smb_nt_notify_size = -1;
359 static int hf_smb_nt_notify_attributes = -1;
360 static int hf_smb_nt_notify_dir_name = -1;
361 static int hf_smb_nt_notify_file_name = -1;
362 static int hf_smb_root_dir_fid = -1;
363 static int hf_smb_nt_create_disposition = -1;
364 static int hf_smb_sd_length = -1;
365 static int hf_smb_ea_length = -1;
366 static int hf_smb_file_name_len = -1;
367 static int hf_smb_nt_impersonation_level = -1;
368 static int hf_smb_nt_security_flags_context_tracking = -1;
369 static int hf_smb_nt_security_flags_effective_only = -1;
370 static int hf_smb_nt_access_mask_generic_read = -1;
371 static int hf_smb_nt_access_mask_generic_write = -1;
372 static int hf_smb_nt_access_mask_generic_execute = -1;
373 static int hf_smb_nt_access_mask_generic_all = -1;
374 static int hf_smb_nt_access_mask_maximum_allowed = -1;
375 static int hf_smb_nt_access_mask_system_security = -1;
376 static int hf_smb_nt_access_mask_synchronize = -1;
377 static int hf_smb_nt_access_mask_write_owner = -1;
378 static int hf_smb_nt_access_mask_write_dac = -1;
379 static int hf_smb_nt_access_mask_read_control = -1;
380 static int hf_smb_nt_access_mask_delete = -1;
381 static int hf_smb_nt_access_mask_write_attributes = -1;
382 static int hf_smb_nt_access_mask_read_attributes = -1;
383 static int hf_smb_nt_access_mask_delete_child = -1;
384 static int hf_smb_nt_access_mask_execute = -1;
385 static int hf_smb_nt_access_mask_write_ea = -1;
386 static int hf_smb_nt_access_mask_read_ea = -1;
387 static int hf_smb_nt_access_mask_append = -1;
388 static int hf_smb_nt_access_mask_write = -1;
389 static int hf_smb_nt_access_mask_read = -1;
390 static int hf_smb_nt_create_bits_oplock = -1;
391 static int hf_smb_nt_create_bits_boplock = -1;
392 static int hf_smb_nt_create_bits_dir = -1;
393 static int hf_smb_nt_create_options_directory_file = -1;
394 static int hf_smb_nt_create_options_write_through = -1;
395 static int hf_smb_nt_create_options_sequential_only = -1;
396 static int hf_smb_nt_create_options_sync_io_alert = -1;
397 static int hf_smb_nt_create_options_sync_io_nonalert = -1;
398 static int hf_smb_nt_create_options_non_directory_file = -1;
399 static int hf_smb_nt_create_options_no_ea_knowledge = -1;
400 static int hf_smb_nt_create_options_eight_dot_three_only = -1;
401 static int hf_smb_nt_create_options_random_access = -1;
402 static int hf_smb_nt_create_options_delete_on_close = -1;
403 static int hf_smb_nt_share_access_read = -1;
404 static int hf_smb_nt_share_access_write = -1;
405 static int hf_smb_nt_share_access_delete = -1;
406 static int hf_smb_file_eattr_read_only = -1;
407 static int hf_smb_file_eattr_hidden = -1;
408 static int hf_smb_file_eattr_system = -1;
409 static int hf_smb_file_eattr_volume = -1;
410 static int hf_smb_file_eattr_directory = -1;
411 static int hf_smb_file_eattr_archive = -1;
412 static int hf_smb_file_eattr_device = -1;
413 static int hf_smb_file_eattr_normal = -1;
414 static int hf_smb_file_eattr_temporary = -1;
415 static int hf_smb_file_eattr_sparse = -1;
416 static int hf_smb_file_eattr_reparse = -1;
417 static int hf_smb_file_eattr_compressed = -1;
418 static int hf_smb_file_eattr_offline = -1;
419 static int hf_smb_file_eattr_not_content_indexed = -1;
420 static int hf_smb_file_eattr_encrypted = -1;
421 static int hf_smb_file_eattr_write_through = -1;
422 static int hf_smb_file_eattr_no_buffering = -1;
423 static int hf_smb_file_eattr_random_access = -1;
424 static int hf_smb_file_eattr_sequential_scan = -1;
425 static int hf_smb_file_eattr_delete_on_close = -1;
426 static int hf_smb_file_eattr_backup_semantics = -1;
427 static int hf_smb_file_eattr_posix_semantics = -1;
428 static int hf_smb_sec_desc_len = -1;
429 static int hf_smb_sec_desc_revision = -1;
430 static int hf_smb_sec_desc_type_owner_defaulted = -1;
431 static int hf_smb_sec_desc_type_group_defaulted = -1;
432 static int hf_smb_sec_desc_type_dacl_present = -1;
433 static int hf_smb_sec_desc_type_dacl_defaulted = -1;
434 static int hf_smb_sec_desc_type_sacl_present = -1;
435 static int hf_smb_sec_desc_type_sacl_defaulted = -1;
436 static int hf_smb_sec_desc_type_dacl_auto_inherit_req = -1;
437 static int hf_smb_sec_desc_type_sacl_auto_inherit_req = -1;
438 static int hf_smb_sec_desc_type_dacl_auto_inherited = -1;
439 static int hf_smb_sec_desc_type_sacl_auto_inherited = -1;
440 static int hf_smb_sec_desc_type_dacl_protected = -1;
441 static int hf_smb_sec_desc_type_sacl_protected = -1;
442 static int hf_smb_sec_desc_type_self_relative = -1;
443 static int hf_smb_sid_revision = -1;
444 static int hf_smb_sid_num_auth = -1;
445 static int hf_smb_acl_revision = -1;
446 static int hf_smb_acl_size = -1;
447 static int hf_smb_acl_num_aces = -1;
448 static int hf_smb_ace_type = -1;
449 static int hf_smb_ace_size = -1;
450 static int hf_smb_ace_flags_object_inherit = -1;
451 static int hf_smb_ace_flags_container_inherit = -1;
452 static int hf_smb_ace_flags_non_propagate_inherit = -1;
453 static int hf_smb_ace_flags_inherit_only = -1;
454 static int hf_smb_ace_flags_inherited_ace = -1;
455 static int hf_smb_ace_flags_successful_access = -1;
456 static int hf_smb_ace_flags_failed_access = -1;
457 static int hf_smb_nt_qsd_owner = -1;
458 static int hf_smb_nt_qsd_group = -1;
459 static int hf_smb_nt_qsd_dacl = -1;
460 static int hf_smb_nt_qsd_sacl = -1;
461 static int hf_smb_extended_attributes = -1;
462 static int hf_smb_oplock_level = -1;
463 static int hf_smb_create_action = -1;
464 static int hf_smb_file_id = -1;
465 static int hf_smb_ea_error_offset = -1;
466 static int hf_smb_end_of_file = -1;
467 static int hf_smb_device_type = -1;
468 static int hf_smb_is_directory = -1;
469 static int hf_smb_next_entry_offset = -1;
470 static int hf_smb_change_time = -1;
471 static int hf_smb_setup_len = -1;
472 static int hf_smb_print_mode = -1;
473 static int hf_smb_print_identifier = -1;
474 static int hf_smb_restart_index = -1;
475 static int hf_smb_print_queue_date = -1;
476 static int hf_smb_print_queue_dos_date = -1;
477 static int hf_smb_print_queue_dos_time = -1;
478 static int hf_smb_print_status = -1;
479 static int hf_smb_print_spool_file_number = -1;
480 static int hf_smb_print_spool_file_size = -1;
481 static int hf_smb_print_spool_file_name = -1;
482 static int hf_smb_start_index = -1;
483 static int hf_smb_originator_name = -1;
484 static int hf_smb_destination_name = -1;
485 static int hf_smb_message_len = -1;
486 static int hf_smb_message = -1;
487 static int hf_smb_mgid = -1;
488 static int hf_smb_forwarded_name = -1;
489 static int hf_smb_machine_name = -1;
490 static int hf_smb_cancel_to = -1;
491 static int hf_smb_trans2_subcmd = -1;
492 static int hf_smb_trans_name = -1;
493 static int hf_smb_transaction_flags_dtid = -1;
494 static int hf_smb_transaction_flags_owt = -1;
495 static int hf_smb_search_count = -1;
496 static int hf_smb_search_pattern = -1;
497 static int hf_smb_ff2_backup = -1;
498 static int hf_smb_ff2_continue = -1;
499 static int hf_smb_ff2_resume = -1;
500 static int hf_smb_ff2_close_eos = -1;
501 static int hf_smb_ff2_close = -1;
502 static int hf_smb_ff2_information_level = -1;
503 static int hf_smb_qpi_loi = -1;
504 #if 0
505 static int hf_smb_sfi_writetru = -1;
506 static int hf_smb_sfi_caching = -1;
507 #endif
508 static int hf_smb_storage_type = -1;
509 static int hf_smb_resume = -1;
510 static int hf_smb_max_referral_level = -1;
511 static int hf_smb_qfsi_information_level = -1;
512 static int hf_smb_ea_size = -1;
513 static int hf_smb_list_length = -1;
514 static int hf_smb_number_of_links = -1;
515 static int hf_smb_delete_pending = -1;
516 static int hf_smb_index_number = -1;
517 static int hf_smb_current_offset = -1;
518 static int hf_smb_t2_alignment = -1;
519 static int hf_smb_t2_stream_name_length = -1;
520 static int hf_smb_t2_stream_size = -1;
521 static int hf_smb_t2_stream_name = -1;
522 static int hf_smb_t2_compressed_file_size = -1;
523 static int hf_smb_t2_compressed_format = -1;
524 static int hf_smb_t2_compressed_unit_shift = -1;
525 static int hf_smb_t2_compressed_chunk_shift = -1;
526 static int hf_smb_t2_compressed_cluster_shift = -1;
527 static int hf_smb_dfs_path_consumed = -1;
528 static int hf_smb_dfs_num_referrals = -1;
529 static int hf_smb_get_dfs_server_hold_storage = -1;
530 static int hf_smb_get_dfs_fielding = -1;
531 static int hf_smb_dfs_referral_version = -1;
532 static int hf_smb_dfs_referral_size = -1;
533 static int hf_smb_dfs_referral_server_type = -1;
534 static int hf_smb_dfs_referral_flags_strip = -1;
535 static int hf_smb_dfs_referral_node_offset = -1;
536 static int hf_smb_dfs_referral_node = -1;
537 static int hf_smb_dfs_referral_proximity = -1;
538 static int hf_smb_dfs_referral_ttl = -1;
539 static int hf_smb_dfs_referral_path_offset = -1;
540 static int hf_smb_dfs_referral_path = -1;
541 static int hf_smb_dfs_referral_alt_path_offset = -1;
542 static int hf_smb_dfs_referral_alt_path = -1;
543 static int hf_smb_end_of_search = -1;
544 static int hf_smb_last_name_offset = -1;
545 static int hf_smb_fn_information_level = -1;
546 static int hf_smb_monitor_handle = -1;
547 static int hf_smb_change_count = -1;
548 static int hf_smb_file_index = -1;
549 static int hf_smb_short_file_name = -1;
550 static int hf_smb_short_file_name_len = -1;
551 static int hf_smb_fs_id = -1;
552 static int hf_smb_sector_unit = -1;
553 static int hf_smb_fs_units = -1;
554 static int hf_smb_fs_sector = -1;
555 static int hf_smb_avail_units = -1;
556 static int hf_smb_volume_serial_num = -1;
557 static int hf_smb_volume_label_len = -1;
558 static int hf_smb_volume_label = -1;
559 static int hf_smb_free_alloc_units64 = -1;
560 static int hf_smb_caller_free_alloc_units64 = -1;
561 static int hf_smb_actual_free_alloc_units64 = -1;
562 static int hf_smb_max_name_len = -1;
563 static int hf_smb_fs_name_len = -1;
564 static int hf_smb_fs_name = -1;
565 static int hf_smb_device_char_removable = -1;
566 static int hf_smb_device_char_read_only = -1;
567 static int hf_smb_device_char_floppy = -1;
568 static int hf_smb_device_char_write_once = -1;
569 static int hf_smb_device_char_remote = -1;
570 static int hf_smb_device_char_mounted = -1;
571 static int hf_smb_device_char_virtual = -1;
572 static int hf_smb_fs_attr_css = -1;
573 static int hf_smb_fs_attr_cpn = -1;
574 static int hf_smb_fs_attr_pacls = -1;
575 static int hf_smb_fs_attr_fc = -1;
576 static int hf_smb_fs_attr_vq = -1;
577 static int hf_smb_fs_attr_dim = -1;
578 static int hf_smb_fs_attr_vic = -1;
579 static int hf_smb_quota_flags_enabled = -1;
580 static int hf_smb_quota_flags_deny_disk = -1;
581 static int hf_smb_quota_flags_log_limit = -1;
582 static int hf_smb_quota_flags_log_warning = -1;
583 static int hf_smb_soft_quota_limit = -1;
584 static int hf_smb_hard_quota_limit = -1;
585 static int hf_smb_user_quota_used = -1;
586 static int hf_smb_user_quota_offset = -1;
587 static int hf_smb_nt_rename_level = -1;
588 static int hf_smb_cluster_count = -1;
589 static int hf_smb_segments = -1;
590 static int hf_smb_segment = -1;
591 static int hf_smb_segment_overlap = -1;
592 static int hf_smb_segment_overlap_conflict = -1;
593 static int hf_smb_segment_multiple_tails = -1;
594 static int hf_smb_segment_too_long_fragment = -1;
595 static int hf_smb_segment_error = -1;
596
597 static gint ett_smb = -1;
598 static gint ett_smb_hdr = -1;
599 static gint ett_smb_command = -1;
600 static gint ett_smb_fileattributes = -1;
601 static gint ett_smb_capabilities = -1;
602 static gint ett_smb_aflags = -1;
603 static gint ett_smb_dialect = -1;
604 static gint ett_smb_dialects = -1;
605 static gint ett_smb_mode = -1;
606 static gint ett_smb_rawmode = -1;
607 static gint ett_smb_flags = -1;
608 static gint ett_smb_flags2 = -1;
609 static gint ett_smb_desiredaccess = -1;
610 static gint ett_smb_search = -1;
611 static gint ett_smb_file = -1;
612 static gint ett_smb_openfunction = -1;
613 static gint ett_smb_filetype = -1;
614 static gint ett_smb_openaction = -1;
615 static gint ett_smb_writemode = -1;
616 static gint ett_smb_lock_type = -1;
617 static gint ett_smb_ssetupandxaction = -1;
618 static gint ett_smb_optionsup = -1;
619 static gint ett_smb_time_date = -1;
620 static gint ett_smb_move_copy_flags = -1;
621 static gint ett_smb_file_attributes = -1;
622 static gint ett_smb_search_resume_key = -1;
623 static gint ett_smb_search_dir_info = -1;
624 static gint ett_smb_unlocks = -1;
625 static gint ett_smb_unlock = -1;
626 static gint ett_smb_locks = -1;
627 static gint ett_smb_lock = -1;
628 static gint ett_smb_open_flags = -1;
629 static gint ett_smb_ipc_state = -1;
630 static gint ett_smb_open_action = -1;
631 static gint ett_smb_setup_action = -1;
632 static gint ett_smb_connect_flags = -1;
633 static gint ett_smb_connect_support_bits = -1;
634 static gint ett_smb_nt_access_mask = -1;
635 static gint ett_smb_nt_create_bits = -1;
636 static gint ett_smb_nt_create_options = -1;
637 static gint ett_smb_nt_share_access = -1;
638 static gint ett_smb_nt_security_flags = -1;
639 static gint ett_smb_nt_trans_setup = -1;
640 static gint ett_smb_nt_trans_data = -1;
641 static gint ett_smb_nt_trans_param = -1;
642 static gint ett_smb_nt_notify_completion_filter = -1;
643 static gint ett_smb_nt_ioctl_flags = -1;
644 static gint ett_smb_security_information_mask = -1;
645 static gint ett_smb_print_queue_entry = -1;
646 static gint ett_smb_transaction_flags = -1;
647 static gint ett_smb_transaction_params = -1;
648 static gint ett_smb_find_first2_flags = -1;
649 static gint ett_smb_mac_support_flags = -1;
650 #if 0
651 static gint ett_smb_ioflag = -1;
652 #endif
653 static gint ett_smb_transaction_data = -1;
654 static gint ett_smb_stream_info = -1;
655 static gint ett_smb_dfs_referrals = -1;
656 static gint ett_smb_dfs_referral = -1;
657 static gint ett_smb_dfs_referral_flags = -1;
658 static gint ett_smb_get_dfs_flags = -1;
659 static gint ett_smb_ff2_data = -1;
660 static gint ett_smb_device_characteristics = -1;
661 static gint ett_smb_fs_attributes = -1;
662 static gint ett_smb_segments = -1;
663 static gint ett_smb_segment = -1;
664 static gint ett_smb_sec_desc = -1;
665 static gint ett_smb_sid = -1;
666 static gint ett_smb_acl = -1;
667 static gint ett_smb_ace = -1;
668 static gint ett_smb_ace_flags = -1;
669 static gint ett_smb_sec_desc_type = -1;
670 static gint ett_smb_quotaflags = -1;
671 static gint ett_smb_gssapi = -1;
672
673 static dissector_handle_t gssapi_handle = NULL;
674
675 fragment_items smb_frag_items = {
676         &ett_smb_segment,
677         &ett_smb_segments,
678
679         &hf_smb_segments,
680         &hf_smb_segment,
681         &hf_smb_segment_overlap,
682         &hf_smb_segment_overlap_conflict,
683         &hf_smb_segment_multiple_tails,
684         &hf_smb_segment_too_long_fragment,
685         &hf_smb_segment_error,
686
687         "segments"
688 };
689
690 proto_tree *top_tree=NULL;     /* ugly */
691
692 static char *decode_smb_name(unsigned char);
693 static int dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *smb_tree, guint8 cmd, gboolean first_pdu);
694
695 /*
696  * Macros for use in the main dissector routines for an SMB.
697  */
698
699 #define WORD_COUNT      \
700         /* Word Count */                                \
701         wc = tvb_get_guint8(tvb, offset);               \
702         proto_tree_add_uint(tree, hf_smb_word_count,    \
703                 tvb, offset, 1, wc);                    \
704         offset += 1;                                    \
705         if(wc==0) goto bytecount;
706
707 #define BYTE_COUNT      \
708         bytecount:                                      \
709         bc = tvb_get_letohs(tvb, offset);               \
710         proto_tree_add_uint(tree, hf_smb_byte_count,    \
711                         tvb, offset, 2, bc);            \
712         offset += 2;                                    \
713         if(bc==0) goto endofcommand;
714
715 #define CHECK_BYTE_COUNT(len)   \
716         if (bc < len) goto endofcommand;
717
718 #define COUNT_BYTES(len)   {\
719         int tmp;            \
720         tmp=len;            \
721         offset += tmp;      \
722         bc -= tmp;          \
723         }
724
725 #define END_OF_SMB      \
726         if (bc != 0) { \
727                 proto_tree_add_text(tree, tvb, offset, bc, \
728                     "Extra byte parameters");           \
729                 offset += bc;                           \
730         }                                               \
731         endofcommand:
732
733 /*
734  * Macros for use in routines called by them.
735  */
736 #define CHECK_BYTE_COUNT_SUBR(len)      \
737         if (*bcp < len) {               \
738                 *trunc = TRUE;          \
739                 return offset;          \
740         }
741
742 #define CHECK_STRING_SUBR(fn)   \
743         if (fn == NULL) {       \
744                 *trunc = TRUE;  \
745                 return offset;  \
746         }
747
748 #define COUNT_BYTES_SUBR(len)   \
749         offset += len;          \
750         *bcp -= len;
751
752 /*
753  * Macros for use when dissecting transaction parameters and data
754  */
755 #define CHECK_BYTE_COUNT_TRANS(len)     \
756         if (bc < len) return offset;
757
758 #define CHECK_STRING_TRANS(fn)  \
759         if (fn == NULL) return offset;
760
761 #define COUNT_BYTES_TRANS(len)  \
762         offset += len;          \
763         bc -= len;
764
765 /*
766  * Macros for use in subrroutines dissecting transaction parameters or data
767  */
768 #define CHECK_BYTE_COUNT_TRANS_SUBR(len)        \
769         if (*bcp < len) return offset;
770
771 #define CHECK_STRING_TRANS_SUBR(fn)     \
772         if (fn == NULL) return offset;
773
774 #define COUNT_BYTES_TRANS_SUBR(len)     \
775         offset += len;                  \
776         *bcp -= len;
777
778
779 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
780    These are needed by the reassembly of SMB Transaction payload and DCERPC over SMB
781    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
782 static gboolean smb_trans_reassembly = FALSE;
783 gboolean smb_dcerpc_reassembly = FALSE;
784
785 static GHashTable *smb_trans_fragment_table = NULL;
786 GHashTable *dcerpc_fragment_table = NULL;
787
788 static void
789 smb_trans_reassembly_init(void)
790 {
791         fragment_table_init(&smb_trans_fragment_table);
792 }
793 static void
794 smb_dcerpc_reassembly_init(void)
795 {
796         fragment_table_init(&dcerpc_fragment_table);
797 }
798
799
800 static fragment_data *
801 smb_trans_defragment(proto_tree *tree _U_, packet_info *pinfo, tvbuff_t *tvb,
802                      int offset, int count, int pos, int totlen)
803 {
804         fragment_data *fd_head=NULL;
805         smb_info_t *si;
806         int more_frags;
807
808         more_frags=totlen>(pos+count);
809
810         si = (smb_info_t *)pinfo->private_data;
811         if (si->sip == NULL) {
812                 /*
813                  * We don't have the frame number of the request.
814                  *
815                  * XXX - is there truly nothing we can do here?
816                  * Can we not separately keep track of the original
817                  * transaction and its continuations, as we did
818                  * at one time?
819                  *
820                  * It is probably not much point in even trying to do something here
821                  * if we have never seen the initial request. Without the initial 
822                  * request we probably miss all parameters and the begining of data
823                  * so we cant even call a subdissector since we can not determine
824                  * which type of transaction call this is.
825                  */
826                 return NULL;
827         }
828
829         if(!pinfo->fd->flags.visited){
830                 fd_head = fragment_add(tvb, offset, pinfo,
831                                        si->sip->frame_req, smb_trans_fragment_table,
832                                        pos, count, more_frags);
833         } else {
834                 fd_head = fragment_get(pinfo, si->sip->frame_req, smb_trans_fragment_table);
835         }
836
837         /* we only show the defragmented packet for the first fragment,
838            or else we might end up with dissecting one HUGE transaction PDU
839            a LOT of times. (first fragment is the only one containing the setup
840            bytes)
841            I have seen ONE Transaction PDU that is ~60kb, spanning many Transaction 
842            SMBs. Takes a LOT of time dissecting and is not fun.
843         */
844         if( (pos==0) && fd_head && fd_head->flags&FD_DEFRAGMENTED){
845                 return fd_head;
846         } else {
847                 return NULL;
848         }
849 }
850                 
851
852
853
854
855 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
856    These variables and functions are used to match
857    responses with calls
858    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
859 /*
860  * The information we need to save about a request in order to show the
861  * frame number of the request in the dissection of the reply.
862  */
863 typedef struct  {
864         guint32 frame;
865         guint32 pid_mid;
866 } smb_saved_info_key_t;
867
868 static GMemChunk *smb_saved_info_key_chunk = NULL;
869 static GMemChunk *smb_saved_info_chunk = NULL;
870 static int smb_saved_info_init_count = 200;
871
872 /* unmatched smb_saved_info structures.
873    For unmatched smb_saved_info structures we store the smb_saved_info
874    structure using the MID and the PID as the key.
875
876    Oh, yes, the key is really a pointer, but we use it as if it was an integer.
877    Ugly, yes. Not portable to DEC-20 Yes. But it saves a few bytes.
878    The key is the PID in the upper 16 bits and the MID in the lower 16 bits.
879 */
880 static gint
881 smb_saved_info_equal_unmatched(gconstpointer k1, gconstpointer k2)
882 {
883         register guint32 key1 = (guint32)k1;
884         register guint32 key2 = (guint32)k2;
885         return key1==key2;
886 }
887 static guint
888 smb_saved_info_hash_unmatched(gconstpointer k)
889 {
890         register guint32 key = (guint32)k;
891         return key;
892 }
893
894 /* matched smb_saved_info structures.
895    For matched smb_saved_info structures we store the smb_saved_info
896    structure twice in the table using the frame number, and a combination
897    of the MID and the PID, as the key.
898    The frame number is guaranteed to be unique but if ever someone makes
899    some change that will renumber the frames in a capture we are in BIG trouble.
900    This is not likely though since that would break (among other things) all the
901    reassembly routines as well.
902
903    We also need the MID as there may be more than one SMB request or reply
904    in a single frame, and we also need the PID as there may be more than
905    one outstanding request with the same MID and different PIDs.
906 */
907 static gint
908 smb_saved_info_equal_matched(gconstpointer k1, gconstpointer k2)
909 {
910         const smb_saved_info_key_t *key1 = k1;
911         const smb_saved_info_key_t *key2 = k2;
912         return key1->frame == key2->frame && key1->pid_mid == key2->pid_mid;
913 }
914 static guint
915 smb_saved_info_hash_matched(gconstpointer k)
916 {
917         const smb_saved_info_key_t *key = k;
918         return key->frame + key->pid_mid;
919 }
920
921 /*
922  * The information we need to save about an NT Transaction request in order
923  * to dissect the reply.
924  */
925 typedef struct {
926         int subcmd;
927 } smb_nt_transact_info_t;
928
929 static GMemChunk *smb_nt_transact_info_chunk = NULL;
930 static int smb_nt_transact_info_init_count = 200;
931
932 /*
933  * The information we need to save about a Transaction2 request in order
934  * to dissect the reply.
935  */
936 typedef struct {
937         int subcmd;
938         int info_level;
939         gboolean resume_keys;   /* if "return resume" keys set in T2 FIND_FIRST request */
940 } smb_transact2_info_t;
941
942 static GMemChunk *smb_transact2_info_chunk = NULL;
943 static int smb_transact2_info_init_count = 200;
944
945 /*
946  * The information we need to save about a Transaction request in order
947  * to dissect the reply; this includes information for use by the
948  * Remote API dissector.
949  */
950 static GMemChunk *smb_transact_info_chunk = NULL;
951 static int smb_transact_info_init_count = 200;
952
953 static GMemChunk *conv_tables_chunk = NULL;
954 static GSList *conv_tables = NULL;
955 static int conv_tables_count = 10;
956
957
958 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
959    End of request/response matching functions
960    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
961
962 static const value_string buffer_format_vals[] = {
963         {1,     "Data Block"},
964         {2,     "Dialect"},
965         {3,     "Pathname"},
966         {4,     "ASCII"},
967         {5,     "Variable Block"},
968         {0,     NULL}
969 };
970
971 /*
972  * UTIME - this is *almost* like a UNIX time stamp, except that it's
973  * in seconds since January 1, 1970, 00:00:00 *local* time, not since
974  * January 1, 1970, 00:00:00 GMT.
975  *
976  * This means we have to do some extra work to convert it.  This code is
977  * based on the Samba code:
978  *
979  *      Unix SMB/Netbios implementation.
980  *      Version 1.9.
981  *      time handling functions
982  *      Copyright (C) Andrew Tridgell 1992-1998
983  */
984
985 /*
986  * Yield the difference between *A and *B, in seconds, ignoring leap
987  * seconds.
988  */
989 #define TM_YEAR_BASE 1900
990
991 static int
992 tm_diff(struct tm *a, struct tm *b)
993 {
994         int ay = a->tm_year + (TM_YEAR_BASE - 1);
995         int by = b->tm_year + (TM_YEAR_BASE - 1);
996         int intervening_leap_days =
997             (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
998         int years = ay - by;
999         int days =
1000             365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
1001         int hours = 24*days + (a->tm_hour - b->tm_hour);
1002         int minutes = 60*hours + (a->tm_min - b->tm_min);
1003         int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
1004
1005         return seconds;
1006 }
1007
1008 /*
1009  * Return the UTC offset in seconds west of UTC, or 0 if it cannot be
1010  * determined.
1011  */
1012 static int
1013 TimeZone(time_t t)
1014 {
1015         struct tm *tm = gmtime(&t);
1016         struct tm tm_utc;
1017
1018         if (tm == NULL)
1019                 return 0;
1020         tm_utc = *tm;
1021         tm = localtime(&t);
1022         if (tm == NULL)
1023                 return 0;
1024         return tm_diff(&tm_utc,tm);
1025 }
1026
1027 /*
1028  * Return the same value as TimeZone, but it should be more efficient.
1029  *
1030  * We keep a table of DST offsets to prevent calling localtime() on each 
1031  * call of this function. This saves a LOT of time on many unixes.
1032  *
1033  * Updated by Paul Eggert <eggert@twinsun.com>
1034  */
1035 #ifndef CHAR_BIT
1036 #define CHAR_BIT 8
1037 #endif
1038
1039 #ifndef TIME_T_MIN
1040 #define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \
1041                     : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
1042 #endif
1043 #ifndef TIME_T_MAX
1044 #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
1045 #endif
1046
1047 static int
1048 TimeZoneFaster(time_t t)
1049 {
1050         static struct dst_table {time_t start,end; int zone;} *tdt;
1051         static struct dst_table *dst_table = NULL;
1052         static int table_size = 0;
1053         int i;
1054         int zone = 0;
1055
1056         if (t == 0)
1057                 t = time(NULL);
1058
1059         /* Tunis has a 8 day DST region, we need to be careful ... */
1060 #define MAX_DST_WIDTH (365*24*60*60)
1061 #define MAX_DST_SKIP (7*24*60*60)
1062
1063         for (i = 0; i < table_size; i++) {
1064                 if (t >= dst_table[i].start && t <= dst_table[i].end)
1065                         break;
1066         }
1067
1068         if (i < table_size) {
1069                 zone = dst_table[i].zone;
1070         } else {
1071                 time_t low,high;
1072
1073                 zone = TimeZone(t);
1074                 if (dst_table == NULL)
1075                         tdt = g_malloc(sizeof(dst_table[0])*(i+1));
1076                 else
1077                         tdt = g_realloc(dst_table, sizeof(dst_table[0])*(i+1));
1078                 if (tdt == NULL) {
1079                         if (dst_table)
1080                                 free(dst_table);
1081                         table_size = 0;
1082                 } else {
1083                         dst_table = tdt;
1084                         table_size++;
1085     
1086                         dst_table[i].zone = zone; 
1087                         dst_table[i].start = dst_table[i].end = t;
1088     
1089                         /* no entry will cover more than 6 months */
1090                         low = t - MAX_DST_WIDTH/2;
1091                         if (t < low)
1092                                 low = TIME_T_MIN;
1093       
1094                         high = t + MAX_DST_WIDTH/2;
1095                         if (high < t)
1096                                 high = TIME_T_MAX;
1097       
1098                         /*
1099                          * Widen the new entry using two bisection searches.
1100                          */
1101                         while (low+60*60 < dst_table[i].start) {
1102                                 if (dst_table[i].start - low > MAX_DST_SKIP*2)
1103                                         t = dst_table[i].start - MAX_DST_SKIP;
1104                                 else
1105                                         t = low + (dst_table[i].start-low)/2;
1106                                 if (TimeZone(t) == zone)
1107                                         dst_table[i].start = t;
1108                                 else
1109                                         low = t;
1110                         }
1111
1112                         while (high-60*60 > dst_table[i].end) {
1113                                 if (high - dst_table[i].end > MAX_DST_SKIP*2)
1114                                         t = dst_table[i].end + MAX_DST_SKIP;
1115                                 else
1116                                         t = high - (high-dst_table[i].end)/2;
1117                                 if (TimeZone(t) == zone)
1118                                         dst_table[i].end = t;
1119                                 else
1120                                         high = t;
1121                         }
1122                 }
1123         }
1124         return zone;
1125 }
1126
1127 /*
1128  * Return the UTC offset in seconds west of UTC, adjusted for extra time
1129  * offset, for a local time value.  If ut = lt + LocTimeDiff(lt), then
1130  * lt = ut - TimeDiff(ut), but the converse does not necessarily hold near
1131  * daylight savings transitions because some local times are ambiguous.
1132  * LocTimeDiff(t) equals TimeDiff(t) except near daylight savings transitions.
1133  */
1134 static int
1135 LocTimeDiff(time_t lt)
1136 {
1137         int d = TimeZoneFaster(lt);
1138         time_t t = lt + d;
1139
1140         /* if overflow occurred, ignore all the adjustments so far */
1141         if (((t < lt) ^ (d < 0)))
1142                 t = lt;
1143
1144         /*
1145          * Now t should be close enough to the true UTC to yield the
1146          * right answer.
1147          */
1148         return TimeZoneFaster(t);
1149 }
1150
1151 static int
1152 dissect_smb_UTIME(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_date)
1153 {
1154         guint32 timeval;
1155         nstime_t ts;
1156  
1157         timeval = tvb_get_letohl(tvb, offset);
1158         if (timeval == 0xffffffff) {
1159                 proto_tree_add_text(tree, tvb, offset, 4,
1160                     "%s: No time specified (0xffffffff)",
1161                     proto_registrar_get_name(hf_date));
1162                 offset += 4;
1163                 return offset;
1164         }
1165
1166         /*
1167          * We add the local time offset.
1168          */
1169         ts.secs = timeval + LocTimeDiff(timeval);
1170         ts.nsecs = 0;
1171
1172         proto_tree_add_time(tree, hf_date, tvb, offset, 4, &ts);
1173         offset += 4;
1174  
1175         return offset;
1176 }
1177
1178 #define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
1179
1180 /*
1181  * Translate an 8-byte FILETIME value, given as the upper and lower 32 bits,
1182  * to an "nstime_t".
1183  * A FILETIME is a 64-bit integer, giving the time since Jan 1, 1601,
1184  * midnight "UTC", in 100ns units.
1185  * Return TRUE if the conversion succeeds, FALSE otherwise.
1186  *
1187  * According to the Samba code, it appears to be kludge-GMT (at least for
1188  * file listings). This means it's the GMT you get by taking a local time
1189  * and adding the server time zone offset.  This is NOT the same as GMT in
1190  * some cases.   However, we don't know the server time zone, so we don't
1191  * do that adjustment.
1192  *
1193  * This code is based on the Samba code:
1194  *
1195  *      Unix SMB/Netbios implementation.
1196  *      Version 1.9.
1197  *      time handling functions
1198  *      Copyright (C) Andrew Tridgell 1992-1998
1199  */
1200 static gboolean
1201 nt_time_to_nstime(guint32 filetime_high, guint32 filetime_low, nstime_t *tv)
1202 {
1203         double d;
1204         /* The next two lines are a fix needed for the 
1205             broken SCO compiler. JRA. */
1206         time_t l_time_min = TIME_T_MIN;
1207         time_t l_time_max = TIME_T_MAX;
1208
1209         if (filetime_high == 0)
1210                 return FALSE;
1211
1212         /*
1213          * Get the time as a double, in seconds and fractional seconds.
1214          */
1215         d = ((double)filetime_high)*4.0*(double)(1<<30);
1216         d += filetime_low;
1217         d *= 1.0e-7;
1218  
1219         /* Now adjust by 369 years, to make the seconds since 1970. */
1220         d -= TIME_FIXUP_CONSTANT;
1221
1222         if (!(l_time_min <= d && d <= l_time_max))
1223                 return FALSE;
1224
1225         /*
1226          * Get the time as seconds and nanoseconds.
1227          */
1228         tv->secs = d;
1229         tv->nsecs = (d - tv->secs)*1000000000;
1230
1231         return TRUE;
1232 }
1233
1234 int
1235 dissect_smb_64bit_time(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_date)
1236 {
1237         guint32 filetime_high, filetime_low;
1238         nstime_t ts;
1239
1240         /* XXX there seems also to be another special time value which is fairly common :
1241            0x40000000 00000000  
1242            the meaning of this one is yet unknown 
1243         */
1244         if (tree) {
1245                 filetime_low = tvb_get_letohl(tvb, offset);
1246                 filetime_high = tvb_get_letohl(tvb, offset + 4);
1247                 if (filetime_low == 0 && filetime_high == 0) {
1248                         proto_tree_add_text(tree, tvb, offset, 8,
1249                             "%s: No time specified (0)",
1250                             proto_registrar_get_name(hf_date));
1251                 } else if(filetime_low==0 && filetime_high==0x80000000){
1252                         proto_tree_add_text(tree, tvb, offset, 8,
1253                             "%s: Infinity (relative time)",
1254                             proto_registrar_get_name(hf_date));
1255                 } else if(filetime_low==0xffffffff && filetime_high==0x7fffffff){
1256                         proto_tree_add_text(tree, tvb, offset, 8,
1257                             "%s: Infinity (absolute time)",
1258                             proto_registrar_get_name(hf_date));
1259                 } else {                        
1260                         if (nt_time_to_nstime(filetime_high, filetime_low, &ts)) {
1261                                 proto_tree_add_time(tree, hf_date, tvb,
1262                                     offset, 8, &ts);
1263                         } else {
1264                                 proto_tree_add_text(tree, tvb, offset, 8,
1265                                     "%s: Time can't be converted",
1266                                     proto_registrar_get_name(hf_date));
1267                         }
1268                 }
1269         }
1270
1271         offset += 8;
1272         return offset;
1273 }
1274
1275 static int
1276 dissect_smb_datetime(tvbuff_t *tvb, proto_tree *parent_tree, int offset,
1277     int hf_date, int hf_dos_date, int hf_dos_time, gboolean time_first)
1278 {
1279         guint16 dos_time, dos_date;
1280         proto_item *item = NULL;
1281         proto_tree *tree = NULL;
1282         struct tm tm;
1283         time_t t;
1284         static const int mday_noleap[12] = {
1285                 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1286         };
1287         static const int mday_leap[12] = {
1288                 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1289         };
1290 #define ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
1291         nstime_t tv;
1292
1293         if (time_first) {
1294                 dos_time = tvb_get_letohs(tvb, offset);
1295                 dos_date = tvb_get_letohs(tvb, offset+2);
1296         } else {
1297                 dos_date = tvb_get_letohs(tvb, offset);
1298                 dos_time = tvb_get_letohs(tvb, offset+2);
1299         }
1300
1301         if ((dos_date == 0xffff && dos_time == 0xffff) ||
1302             (dos_date == 0 && dos_time == 0)) {
1303                 /*
1304                  * No date/time specified.
1305                  */
1306                 if(parent_tree){
1307                         proto_tree_add_text(parent_tree, tvb, offset, 4,
1308                             "%s: No time specified (0x%08x)",
1309                             proto_registrar_get_name(hf_date),
1310                             (dos_date << 16) | dos_time);
1311                 }
1312                 offset += 4;
1313                 return offset;
1314         }
1315
1316         tm.tm_sec = (dos_time&0x1f)*2;
1317         tm.tm_min = (dos_time>>5)&0x3f;
1318         tm.tm_hour = (dos_time>>11)&0x1f;
1319         tm.tm_mday = dos_date&0x1f;
1320         tm.tm_mon = ((dos_date>>5)&0x0f) - 1;
1321         tm.tm_year = ((dos_date>>9)&0x7f) + 1980 - 1900;
1322         tm.tm_isdst = -1;
1323
1324         /*
1325          * Do some sanity checks before calling "mktime()";
1326          * "mktime()" doesn't do them, it "normalizes" out-of-range
1327          * values.
1328          */
1329         if (tm.tm_sec > 59 || tm.tm_min > 59 || tm.tm_hour > 23 ||
1330            tm.tm_mon < 0 || tm.tm_mon > 11 ||
1331            (ISLEAP(tm.tm_year + 1900) ?
1332              tm.tm_mday > mday_leap[tm.tm_mon] :
1333              tm.tm_mday > mday_noleap[tm.tm_mon]) ||
1334              (t = mktime(&tm)) == -1) {
1335                 /*
1336                  * Invalid date/time.
1337                  */
1338                 if (parent_tree) {
1339                         item = proto_tree_add_text(parent_tree, tvb, offset, 4,
1340                             "%s: Invalid time",
1341                             proto_registrar_get_name(hf_date));
1342                         tree = proto_item_add_subtree(item, ett_smb_time_date);
1343                         if (time_first) {
1344                                 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);
1345                                 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);
1346                         } else {
1347                                 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);
1348                                 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);
1349                         }
1350                 }
1351                 offset += 4;
1352                 return offset;
1353         }
1354
1355         tv.secs = t;
1356         tv.nsecs = 0;
1357
1358         if(parent_tree){
1359                 item = proto_tree_add_time(parent_tree, hf_date, tvb, offset, 4, &tv);
1360                 tree = proto_item_add_subtree(item, ett_smb_time_date);
1361                 if (time_first) {
1362                         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);
1363                         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);
1364                 } else {
1365                         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);
1366                         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);
1367                 }
1368         }
1369
1370         offset += 4;
1371
1372         return offset;
1373 }
1374
1375
1376 static const value_string da_access_vals[] = {
1377         { 0,            "Open for reading"},
1378         { 1,            "Open for writing"},
1379         { 2,            "Open for reading and writing"},
1380         { 3,            "Open for execute"},
1381         {0, NULL}
1382 };
1383 static const value_string da_sharing_vals[] = {
1384         { 0,            "Compatibility mode"},
1385         { 1,            "Deny read/write/execute (exclusive)"},
1386         { 2,            "Deny write"},
1387         { 3,            "Deny read/execute"},
1388         { 4,            "Deny none"},
1389         {0, NULL}
1390 };
1391 static const value_string da_locality_vals[] = {
1392         { 0,            "Locality of reference unknown"},
1393         { 1,            "Mainly sequential access"},
1394         { 2,            "Mainly random access"},
1395         { 3,            "Random access with some locality"},
1396         {0, NULL}
1397 };
1398 static const true_false_string tfs_da_caching = {
1399         "Do not cache this file",
1400         "Caching permitted on this file"
1401 };
1402 static const true_false_string tfs_da_writetru = {
1403         "Write through enabled",
1404         "Write through disabled"
1405 };
1406 static int
1407 dissect_access(tvbuff_t *tvb, proto_tree *parent_tree, int offset, char *type)
1408 {
1409         guint16 mask;
1410         proto_item *item = NULL;
1411         proto_tree *tree = NULL;
1412
1413         mask = tvb_get_letohs(tvb, offset);
1414
1415         if(parent_tree){
1416                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
1417                         "%s Access: 0x%04x", type, mask);
1418                 tree = proto_item_add_subtree(item, ett_smb_desiredaccess);
1419         }
1420
1421         proto_tree_add_boolean(tree, hf_smb_access_writetru,
1422                 tvb, offset, 2, mask);
1423         proto_tree_add_boolean(tree, hf_smb_access_caching,
1424                 tvb, offset, 2, mask);
1425         proto_tree_add_uint(tree, hf_smb_access_locality,
1426                 tvb, offset, 2, mask);
1427         proto_tree_add_uint(tree, hf_smb_access_sharing,
1428                 tvb, offset, 2, mask);
1429         proto_tree_add_uint(tree, hf_smb_access_mode,
1430                 tvb, offset, 2, mask);
1431
1432         offset += 2;
1433
1434         return offset;
1435 }
1436
1437 #define FILE_ATTRIBUTE_READ_ONLY                0x00000001
1438 #define FILE_ATTRIBUTE_HIDDEN                   0x00000002
1439 #define FILE_ATTRIBUTE_SYSTEM                   0x00000004
1440 #define FILE_ATTRIBUTE_VOLUME                   0x00000008
1441 #define FILE_ATTRIBUTE_DIRECTORY                0x00000010
1442 #define FILE_ATTRIBUTE_ARCHIVE                  0x00000020
1443 #define FILE_ATTRIBUTE_DEVICE                   0x00000040
1444 #define FILE_ATTRIBUTE_NORMAL                   0x00000080
1445 #define FILE_ATTRIBUTE_TEMPORARY                0x00000100
1446 #define FILE_ATTRIBUTE_SPARSE                   0x00000200
1447 #define FILE_ATTRIBUTE_REPARSE                  0x00000400
1448 #define FILE_ATTRIBUTE_COMPRESSED               0x00000800
1449 #define FILE_ATTRIBUTE_OFFLINE                  0x00001000
1450 #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED      0x00002000
1451 #define FILE_ATTRIBUTE_ENCRYPTED                0x00004000
1452
1453 /*
1454  * These are flags to be used in NT Create operations.
1455  */
1456 #define FILE_ATTRIBUTE_WRITE_THROUGH            0x80000000
1457 #define FILE_ATTRIBUTE_NO_BUFFERING             0x20000000
1458 #define FILE_ATTRIBUTE_RANDOM_ACCESS            0x10000000
1459 #define FILE_ATTRIBUTE_SEQUENTIAL_SCAN          0x08000000
1460 #define FILE_ATTRIBUTE_DELETE_ON_CLOSE          0x04000000
1461 #define FILE_ATTRIBUTE_BACKUP_SEMANTICS         0x02000000
1462 #define FILE_ATTRIBUTE_POSIX_SEMANTICS          0x01000000
1463
1464 static const true_false_string tfs_file_attribute_write_through = {
1465         "This object requires WRITE THROUGH",
1466         "This object does NOT require write through",
1467 };
1468 static const true_false_string tfs_file_attribute_no_buffering = {
1469         "This object requires NO BUFFERING",
1470         "This object can be buffered",
1471 };
1472 static const true_false_string tfs_file_attribute_random_access = {
1473         "This object will be RANDOM ACCESSed",
1474         "Random access is NOT requested",
1475 };
1476 static const true_false_string tfs_file_attribute_sequential_scan = {
1477         "This object is optimized for SEQUENTIAL SCAN",
1478         "This object is NOT optimized for sequential scan",
1479 };
1480 static const true_false_string tfs_file_attribute_delete_on_close = {
1481         "This object will be DELETED ON CLOSE",
1482         "This object will not be deleted on close",
1483 };
1484 static const true_false_string tfs_file_attribute_backup_semantics = {
1485         "This object supports BACKUP SEMANTICS",
1486         "This object does NOT support backup semantics",
1487 };
1488 static const true_false_string tfs_file_attribute_posix_semantics = {
1489         "This object supports POSIX SEMANTICS",
1490         "This object does NOT support POSIX semantics",
1491 };
1492 static const true_false_string tfs_file_attribute_read_only = {
1493         "This file is READ ONLY",
1494         "This file is NOT read only",
1495 };
1496 static const true_false_string tfs_file_attribute_hidden = {
1497         "This is a HIDDEN file",
1498         "This is NOT a hidden file"
1499 };
1500 static const true_false_string tfs_file_attribute_system = {
1501         "This is a SYSTEM file",
1502         "This is NOT a system file"
1503 };
1504 static const true_false_string tfs_file_attribute_volume = {
1505         "This is a VOLUME ID",
1506         "This is NOT a volume ID"
1507 };
1508 static const true_false_string tfs_file_attribute_directory = {
1509         "This is a DIRECTORY",
1510         "This is NOT a directory"
1511 };
1512 static const true_false_string tfs_file_attribute_archive = {
1513         "This is an ARCHIVE file",
1514         "This is NOT an archive file"
1515 };
1516 static const true_false_string tfs_file_attribute_device = {
1517         "This is a DEVICE",
1518         "This is NOT a device"
1519 };
1520 static const true_false_string tfs_file_attribute_normal = {
1521         "This file is an ordinary file",
1522         "This file has some attribute set"
1523 };
1524 static const true_false_string tfs_file_attribute_temporary = {
1525         "This is a TEMPORARY file",
1526         "This is NOT a temporary file"
1527 };
1528 static const true_false_string tfs_file_attribute_sparse = {
1529         "This is a SPARSE file",
1530         "This is NOT a sparse file"
1531 };
1532 static const true_false_string tfs_file_attribute_reparse = {
1533         "This file has an associated REPARSE POINT",
1534         "This file does NOT have an associated reparse point"
1535 };
1536 static const true_false_string tfs_file_attribute_compressed = {
1537         "This is a COMPRESSED file",
1538         "This is NOT a compressed file"
1539 };
1540 static const true_false_string tfs_file_attribute_offline = {
1541         "This file is OFFLINE",
1542         "This file is NOT offline"
1543 };
1544 static const true_false_string tfs_file_attribute_not_content_indexed = {
1545         "This file MAY NOT be indexed by the CONTENT INDEXING service",
1546         "This file MAY be indexed by the content indexing service"
1547 };
1548 static const true_false_string tfs_file_attribute_encrypted = {
1549         "This is an ENCRYPTED file",
1550         "This is NOT an encrypted file"
1551 };
1552
1553 static int
1554 dissect_file_attributes(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
1555 {
1556         guint16 mask;
1557         proto_item *item = NULL;
1558         proto_tree *tree = NULL;
1559
1560         mask = tvb_get_letohs(tvb, offset);
1561
1562         if(parent_tree){
1563                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
1564                         "File Attributes: 0x%04x", mask);
1565                 tree = proto_item_add_subtree(item, ett_smb_file_attributes);
1566         }
1567         proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_16bit,
1568                 tvb, offset, 2, mask);
1569         proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_16bit,
1570                 tvb, offset, 2, mask);
1571         proto_tree_add_boolean(tree, hf_smb_file_attr_system_16bit,
1572                 tvb, offset, 2, mask);
1573         proto_tree_add_boolean(tree, hf_smb_file_attr_volume_16bit,
1574                 tvb, offset, 2, mask);
1575         proto_tree_add_boolean(tree, hf_smb_file_attr_directory_16bit,
1576                 tvb, offset, 2, mask);
1577         proto_tree_add_boolean(tree, hf_smb_file_attr_archive_16bit,
1578                 tvb, offset, 2, mask);
1579
1580         offset += 2;
1581
1582         return offset;
1583 }
1584
1585 /* 3.11 */
1586 static int
1587 dissect_file_ext_attr(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
1588 {
1589         guint32 mask;
1590         proto_item *item = NULL;
1591         proto_tree *tree = NULL;
1592
1593         mask = tvb_get_letohl(tvb, offset);
1594
1595         if(parent_tree){
1596                 item = proto_tree_add_text(parent_tree, tvb, offset, 4,
1597                         "File Attributes: 0x%08x", mask);
1598                 tree = proto_item_add_subtree(item, ett_smb_file_attributes);
1599         }
1600
1601         /*
1602          * XXX - Network Monitor disagrees on some of the
1603          * bits, e.g. the bits above temporary are "atomic write"
1604          * and "transaction write", and it says nothing about the
1605          * bits above that.
1606          *
1607          * Does the Win32 API documentation, or the NT Native API book,
1608          * suggest anything?
1609          */
1610         proto_tree_add_boolean(tree, hf_smb_file_eattr_write_through,
1611                 tvb, offset, 4, mask);
1612         proto_tree_add_boolean(tree, hf_smb_file_eattr_no_buffering,
1613                 tvb, offset, 4, mask);
1614         proto_tree_add_boolean(tree, hf_smb_file_eattr_random_access,
1615                 tvb, offset, 4, mask);
1616         proto_tree_add_boolean(tree, hf_smb_file_eattr_sequential_scan,
1617                 tvb, offset, 4, mask);
1618         proto_tree_add_boolean(tree, hf_smb_file_eattr_delete_on_close,
1619                 tvb, offset, 4, mask);
1620         proto_tree_add_boolean(tree, hf_smb_file_eattr_backup_semantics,
1621                 tvb, offset, 4, mask);
1622         proto_tree_add_boolean(tree, hf_smb_file_eattr_posix_semantics,
1623                 tvb, offset, 4, mask);
1624         proto_tree_add_boolean(tree, hf_smb_file_eattr_encrypted,
1625                 tvb, offset, 4, mask);
1626         proto_tree_add_boolean(tree, hf_smb_file_eattr_not_content_indexed,
1627                 tvb, offset, 4, mask);
1628         proto_tree_add_boolean(tree, hf_smb_file_eattr_offline,
1629                 tvb, offset, 4, mask);
1630         proto_tree_add_boolean(tree, hf_smb_file_eattr_compressed,
1631                 tvb, offset, 4, mask);
1632         proto_tree_add_boolean(tree, hf_smb_file_eattr_reparse,
1633                 tvb, offset, 4, mask);
1634         proto_tree_add_boolean(tree, hf_smb_file_eattr_sparse,
1635                 tvb, offset, 4, mask);
1636         proto_tree_add_boolean(tree, hf_smb_file_eattr_temporary,
1637                 tvb, offset, 4, mask);
1638         proto_tree_add_boolean(tree, hf_smb_file_eattr_normal,
1639                 tvb, offset, 4, mask);
1640         proto_tree_add_boolean(tree, hf_smb_file_eattr_device,
1641                 tvb, offset, 4, mask);
1642         proto_tree_add_boolean(tree, hf_smb_file_eattr_archive,
1643                 tvb, offset, 4, mask);
1644         proto_tree_add_boolean(tree, hf_smb_file_eattr_directory,
1645                 tvb, offset, 4, mask);
1646         proto_tree_add_boolean(tree, hf_smb_file_eattr_volume,
1647                 tvb, offset, 4, mask);
1648         proto_tree_add_boolean(tree, hf_smb_file_eattr_system,
1649                 tvb, offset, 4, mask);
1650         proto_tree_add_boolean(tree, hf_smb_file_eattr_hidden,
1651                 tvb, offset, 4, mask);
1652         proto_tree_add_boolean(tree, hf_smb_file_eattr_read_only,
1653                 tvb, offset, 4, mask);
1654
1655         offset += 4;
1656
1657         return offset;
1658 }
1659
1660 static int
1661 dissect_dir_info_file_attributes(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
1662 {
1663         guint8 mask;
1664         proto_item *item = NULL;
1665         proto_tree *tree = NULL;
1666
1667         mask = tvb_get_guint8(tvb, offset);
1668
1669         if(parent_tree){
1670                 item = proto_tree_add_text(parent_tree, tvb, offset, 1,
1671                         "File Attributes: 0x%02x", mask);
1672                 tree = proto_item_add_subtree(item, ett_smb_file_attributes);
1673         }
1674         proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_8bit,
1675                 tvb, offset, 1, mask);
1676         proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_8bit,
1677                 tvb, offset, 1, mask);
1678         proto_tree_add_boolean(tree, hf_smb_file_attr_system_8bit,
1679                 tvb, offset, 1, mask);
1680         proto_tree_add_boolean(tree, hf_smb_file_attr_volume_8bit,
1681                 tvb, offset, 1, mask);
1682         proto_tree_add_boolean(tree, hf_smb_file_attr_directory_8bit,
1683                 tvb, offset, 1, mask);
1684         proto_tree_add_boolean(tree, hf_smb_file_attr_archive_8bit,
1685                 tvb, offset, 1, mask);
1686
1687         offset += 1;
1688
1689         return offset;
1690 }
1691
1692 static const true_false_string tfs_search_attribute_read_only = {
1693         "Include READ ONLY files in search results",
1694         "Do NOT include read only files in search results",
1695 };
1696 static const true_false_string tfs_search_attribute_hidden = {
1697         "Include HIDDEN files in search results",
1698         "Do NOT include hidden files in search results"
1699 };
1700 static const true_false_string tfs_search_attribute_system = {
1701         "Include SYSTEM files in search results",
1702         "Do NOT include system files in search results"
1703 };
1704 static const true_false_string tfs_search_attribute_volume = {
1705         "Include VOLUME IDs in search results",
1706         "Do NOT include volume IDs in search results"
1707 };
1708 static const true_false_string tfs_search_attribute_directory = {
1709         "Include DIRECTORIES in search results",
1710         "Do NOT include directories in search results"
1711 };
1712 static const true_false_string tfs_search_attribute_archive = {
1713         "Include ARCHIVE files in search results",
1714         "Do NOT include archive files in search results"
1715 };
1716
1717 static int
1718 dissect_search_attributes(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
1719 {
1720         guint16 mask;
1721         proto_item *item = NULL;
1722         proto_tree *tree = NULL;
1723
1724         mask = tvb_get_letohs(tvb, offset);
1725
1726         if(parent_tree){
1727                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
1728                         "Search Attributes: 0x%04x", mask);
1729                 tree = proto_item_add_subtree(item, ett_smb_search);
1730         }
1731
1732         proto_tree_add_boolean(tree, hf_smb_search_attribute_read_only,
1733                 tvb, offset, 2, mask);
1734         proto_tree_add_boolean(tree, hf_smb_search_attribute_hidden,
1735                 tvb, offset, 2, mask);
1736         proto_tree_add_boolean(tree, hf_smb_search_attribute_system,
1737                 tvb, offset, 2, mask);  
1738         proto_tree_add_boolean(tree, hf_smb_search_attribute_volume,
1739                 tvb, offset, 2, mask);
1740         proto_tree_add_boolean(tree, hf_smb_search_attribute_directory,
1741                 tvb, offset, 2, mask);
1742         proto_tree_add_boolean(tree, hf_smb_search_attribute_archive,
1743                 tvb, offset, 2, mask);
1744
1745         offset += 2;
1746         return offset;
1747 }
1748
1749 #if 0
1750 /*
1751  * XXX - this isn't used.
1752  * Is this used for anything?  NT Create AndX doesn't use it.
1753  * Is there some 16-bit attribute field with more bits than Read Only,
1754  * Hidden, System, Volume ID, Directory, and Archive?
1755  */
1756 static int
1757 dissect_extended_file_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
1758 {
1759         guint32 mask;
1760         proto_item *item = NULL;
1761         proto_tree *tree = NULL;
1762
1763         mask = tvb_get_letohl(tvb, offset);
1764
1765         if(parent_tree){
1766                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
1767                         "File Attributes: 0x%08x", mask);
1768                 tree = proto_item_add_subtree(item, ett_smb_file_attributes);
1769         }
1770         proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_16bit,
1771                 tvb, offset, 2, mask);
1772         proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_16bit,
1773                 tvb, offset, 2, mask);
1774         proto_tree_add_boolean(tree, hf_smb_file_attr_system_16bit,
1775                 tvb, offset, 2, mask);
1776         proto_tree_add_boolean(tree, hf_smb_file_attr_volume_16bit,
1777                 tvb, offset, 2, mask);
1778         proto_tree_add_boolean(tree, hf_smb_file_attr_directory_16bit,
1779                 tvb, offset, 2, mask);
1780         proto_tree_add_boolean(tree, hf_smb_file_attr_archive_16bit,
1781                 tvb, offset, 2, mask);
1782         proto_tree_add_boolean(tree, hf_smb_file_attr_device,
1783                 tvb, offset, 2, mask);
1784         proto_tree_add_boolean(tree, hf_smb_file_attr_normal,
1785                 tvb, offset, 2, mask);
1786         proto_tree_add_boolean(tree, hf_smb_file_attr_temporary,
1787                 tvb, offset, 2, mask);
1788         proto_tree_add_boolean(tree, hf_smb_file_attr_sparse,
1789                 tvb, offset, 2, mask);
1790         proto_tree_add_boolean(tree, hf_smb_file_attr_reparse,
1791                 tvb, offset, 2, mask);
1792         proto_tree_add_boolean(tree, hf_smb_file_attr_compressed,
1793                 tvb, offset, 2, mask);
1794         proto_tree_add_boolean(tree, hf_smb_file_attr_offline,
1795                 tvb, offset, 2, mask);
1796         proto_tree_add_boolean(tree, hf_smb_file_attr_not_content_indexed,
1797                 tvb, offset, 2, mask);
1798         proto_tree_add_boolean(tree, hf_smb_file_attr_encrypted,
1799                 tvb, offset, 2, mask);
1800
1801         offset += 2;
1802
1803         return offset;
1804 }
1805 #endif
1806
1807
1808 #define SERVER_CAP_RAW_MODE            0x00000001
1809 #define SERVER_CAP_MPX_MODE            0x00000002
1810 #define SERVER_CAP_UNICODE             0x00000004
1811 #define SERVER_CAP_LARGE_FILES         0x00000008
1812 #define SERVER_CAP_NT_SMBS             0x00000010
1813 #define SERVER_CAP_RPC_REMOTE_APIS     0x00000020
1814 #define SERVER_CAP_STATUS32            0x00000040
1815 #define SERVER_CAP_LEVEL_II_OPLOCKS    0x00000080
1816 #define SERVER_CAP_LOCK_AND_READ       0x00000100
1817 #define SERVER_CAP_NT_FIND             0x00000200
1818 #define SERVER_CAP_DFS                 0x00001000
1819 #define SERVER_CAP_INFOLEVEL_PASSTHRU  0x00002000
1820 #define SERVER_CAP_LARGE_READX         0x00004000
1821 #define SERVER_CAP_LARGE_WRITEX        0x00008000
1822 #define SERVER_CAP_UNIX                0x00800000
1823 #define SERVER_CAP_RESERVED            0x02000000
1824 #define SERVER_CAP_BULK_TRANSFER       0x20000000
1825 #define SERVER_CAP_COMPRESSED_DATA     0x40000000
1826 #define SERVER_CAP_EXTENDED_SECURITY   0x80000000
1827 static const true_false_string tfs_server_cap_raw_mode = {
1828         "Read Raw and Write Raw are supported",
1829         "Read Raw and Write Raw are not supported"
1830 };
1831 static const true_false_string tfs_server_cap_mpx_mode = {
1832         "Read Mpx and Write Mpx are supported",
1833         "Read Mpx and Write Mpx are not supported"
1834 };
1835 static const true_false_string tfs_server_cap_unicode = {
1836         "Unicode strings are supported",
1837         "Unicode strings are not supported"
1838 };
1839 static const true_false_string tfs_server_cap_large_files = {
1840         "Large files are supported",
1841         "Large files are not supported",
1842 };
1843 static const true_false_string tfs_server_cap_nt_smbs = {
1844         "NT SMBs are supported",
1845         "NT SMBs are not supported"
1846 };
1847 static const true_false_string tfs_server_cap_rpc_remote_apis = {
1848         "RPC remote APIs are supported",
1849         "RPC remote APIs are not supported"
1850 };
1851 static const true_false_string tfs_server_cap_nt_status = {
1852         "NT status codes are supported",
1853         "NT status codes are not supported"
1854 };
1855 static const true_false_string tfs_server_cap_level_ii_oplocks = {
1856         "Level 2 oplocks are supported",
1857         "Level 2 oplocks are not supported"
1858 };
1859 static const true_false_string tfs_server_cap_lock_and_read = {
1860         "Lock and Read is supported",
1861         "Lock and Read is not supported"
1862 };
1863 static const true_false_string tfs_server_cap_nt_find = {
1864         "NT Find is supported",
1865         "NT Find is not supported"
1866 };
1867 static const true_false_string tfs_server_cap_dfs = {
1868         "Dfs is supported",
1869         "Dfs is not supported"
1870 };
1871 static const true_false_string tfs_server_cap_infolevel_passthru = {
1872         "NT information level request passthrough is supported",
1873         "NT information level request passthrough is not supported"
1874 };
1875 static const true_false_string tfs_server_cap_large_readx = {
1876         "Large Read andX is supported",
1877         "Large Read andX is not supported"
1878 };
1879 static const true_false_string tfs_server_cap_large_writex = {
1880         "Large Write andX is supported",
1881         "Large Write andX is not supported"
1882 };
1883 static const true_false_string tfs_server_cap_unix = {
1884         "UNIX extensions are supported",
1885         "UNIX extensions are not supported"
1886 };
1887 static const true_false_string tfs_server_cap_reserved = {
1888         "Reserved",
1889         "Reserved"
1890 };
1891 static const true_false_string tfs_server_cap_bulk_transfer = {
1892         "Bulk Read and Bulk Write are supported",
1893         "Bulk Read and Bulk Write are not supported"
1894 };
1895 static const true_false_string tfs_server_cap_compressed_data = {
1896         "Compressed data transfer is supported",
1897         "Compressed data transfer is not supported"
1898 };
1899 static const true_false_string tfs_server_cap_extended_security = {
1900         "Extended security exchanges are supported",
1901         "Extended security exchanges are not supported"
1902 };
1903 static int
1904 dissect_negprot_capabilities(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
1905 {
1906         guint32 mask;
1907         proto_item *item = NULL;
1908         proto_tree *tree = NULL;
1909
1910         mask = tvb_get_letohl(tvb, offset);
1911
1912         if(parent_tree){
1913                 item = proto_tree_add_text(parent_tree, tvb, offset, 4, "Capabilities: 0x%08x", mask);
1914                 tree = proto_item_add_subtree(item, ett_smb_capabilities);
1915         }
1916
1917         proto_tree_add_boolean(tree, hf_smb_server_cap_raw_mode,
1918                 tvb, offset, 4, mask);
1919         proto_tree_add_boolean(tree, hf_smb_server_cap_mpx_mode,
1920                 tvb, offset, 4, mask);
1921         proto_tree_add_boolean(tree, hf_smb_server_cap_unicode,
1922                 tvb, offset, 4, mask);
1923         proto_tree_add_boolean(tree, hf_smb_server_cap_large_files,
1924                 tvb, offset, 4, mask);
1925         proto_tree_add_boolean(tree, hf_smb_server_cap_nt_smbs,
1926                 tvb, offset, 4, mask);
1927         proto_tree_add_boolean(tree, hf_smb_server_cap_rpc_remote_apis,
1928                 tvb, offset, 4, mask);
1929         proto_tree_add_boolean(tree, hf_smb_server_cap_nt_status,
1930                 tvb, offset, 4, mask);
1931         proto_tree_add_boolean(tree, hf_smb_server_cap_level_ii_oplocks,
1932                 tvb, offset, 4, mask);
1933         proto_tree_add_boolean(tree, hf_smb_server_cap_lock_and_read,
1934                 tvb, offset, 4, mask);
1935         proto_tree_add_boolean(tree, hf_smb_server_cap_nt_find,
1936                 tvb, offset, 4, mask);
1937         proto_tree_add_boolean(tree, hf_smb_server_cap_dfs,
1938                 tvb, offset, 4, mask);
1939         proto_tree_add_boolean(tree, hf_smb_server_cap_infolevel_passthru,
1940                 tvb, offset, 4, mask);
1941         proto_tree_add_boolean(tree, hf_smb_server_cap_large_readx,
1942                 tvb, offset, 4, mask);
1943         proto_tree_add_boolean(tree, hf_smb_server_cap_large_writex,
1944                 tvb, offset, 4, mask);
1945         proto_tree_add_boolean(tree, hf_smb_server_cap_unix,
1946                 tvb, offset, 4, mask);
1947         proto_tree_add_boolean(tree, hf_smb_server_cap_reserved,
1948                 tvb, offset, 4, mask);
1949         proto_tree_add_boolean(tree, hf_smb_server_cap_bulk_transfer,
1950                 tvb, offset, 4, mask);
1951         proto_tree_add_boolean(tree, hf_smb_server_cap_compressed_data,
1952                 tvb, offset, 4, mask);
1953         proto_tree_add_boolean(tree, hf_smb_server_cap_extended_security,
1954                 tvb, offset, 4, mask);
1955
1956         return mask;
1957 }
1958
1959 #define RAWMODE_READ   0x01
1960 #define RAWMODE_WRITE  0x02
1961 static const true_false_string tfs_rm_read = {
1962         "Read Raw is supported",
1963         "Read Raw is not supported"
1964 };
1965 static const true_false_string tfs_rm_write = {
1966         "Write Raw is supported",
1967         "Write Raw is not supported"
1968 };
1969
1970 static int
1971 dissect_negprot_rawmode(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
1972 {
1973         guint16 mask;
1974         proto_item *item = NULL;
1975         proto_tree *tree = NULL;
1976
1977         mask = tvb_get_letohs(tvb, offset);
1978
1979         if(parent_tree){
1980                 item = proto_tree_add_text(parent_tree, tvb, offset, 2, "Raw Mode: 0x%04x", mask);
1981                 tree = proto_item_add_subtree(item, ett_smb_rawmode);
1982         }
1983
1984         proto_tree_add_boolean(tree, hf_smb_rm_read, tvb, offset, 2, mask);
1985         proto_tree_add_boolean(tree, hf_smb_rm_write, tvb, offset, 2, mask);
1986
1987         offset += 2;
1988
1989         return offset;
1990 }
1991
1992 #define SECURITY_MODE_MODE             0x01
1993 #define SECURITY_MODE_PASSWORD         0x02
1994 #define SECURITY_MODE_SIGNATURES       0x04
1995 #define SECURITY_MODE_SIG_REQUIRED     0x08
1996 static const true_false_string tfs_sm_mode = {
1997         "USER security mode",
1998         "SHARE security mode"
1999 };
2000 static const true_false_string tfs_sm_password = {
2001         "ENCRYPTED password. Use challenge/response",
2002         "PLAINTEXT password"
2003 };
2004 static const true_false_string tfs_sm_signatures = {
2005         "Security signatures ENABLED",
2006         "Security signatures NOT enabled"
2007 };
2008 static const true_false_string tfs_sm_sig_required = {
2009         "Security signatures REQUIRED",
2010         "Security signatures NOT required"
2011 };
2012
2013 static int
2014 dissect_negprot_security_mode(tvbuff_t *tvb, proto_tree *parent_tree, int offset, int wc)
2015 {
2016         guint16 mask = 0;
2017         proto_item *item = NULL;
2018         proto_tree *tree = NULL;
2019
2020         switch(wc){
2021         case 13:
2022                 mask = tvb_get_letohs(tvb, offset);
2023                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
2024                                 "Security Mode: 0x%04x", mask);
2025                 tree = proto_item_add_subtree(item, ett_smb_mode);
2026                 proto_tree_add_boolean(tree, hf_smb_sm_mode16, tvb, offset, 2, mask);
2027                 proto_tree_add_boolean(tree, hf_smb_sm_password16, tvb, offset, 2, mask);
2028                 offset += 2;
2029                 break;
2030
2031         case 17:
2032                 mask = tvb_get_guint8(tvb, offset);
2033                 item = proto_tree_add_text(parent_tree, tvb, offset, 1,
2034                                 "Security Mode: 0x%02x", mask);
2035                 tree = proto_item_add_subtree(item, ett_smb_mode);
2036                 proto_tree_add_boolean(tree, hf_smb_sm_mode, tvb, offset, 1, mask);
2037                 proto_tree_add_boolean(tree, hf_smb_sm_password, tvb, offset, 1, mask);
2038                 proto_tree_add_boolean(tree, hf_smb_sm_signatures, tvb, offset, 1, mask);
2039                 proto_tree_add_boolean(tree, hf_smb_sm_sig_required, tvb, offset, 1, mask);
2040                 offset += 1;
2041                 break;
2042         }
2043
2044         return offset;
2045 }
2046
2047 static int
2048 dissect_negprot_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2049 {
2050         proto_item *it = NULL;
2051         proto_tree *tr = NULL;
2052         guint16 bc;
2053         guint8 wc;
2054
2055         WORD_COUNT;
2056
2057         BYTE_COUNT;
2058
2059         if(tree){
2060                 it = proto_tree_add_text(tree, tvb, offset, bc,
2061                                 "Requested Dialects");
2062                 tr = proto_item_add_subtree(it, ett_smb_dialects);
2063         }
2064
2065         while(bc){
2066                 int len;
2067                 const guint8 *str;
2068                 proto_item *dit = NULL;
2069                 proto_tree *dtr = NULL;
2070
2071                 /* XXX - what if this runs past bc? */
2072                 len = tvb_strsize(tvb, offset+1);
2073                 str = tvb_get_ptr(tvb, offset+1, len);
2074
2075                 if(tr){
2076                         dit = proto_tree_add_text(tr, tvb, offset, len+1,
2077                                         "Dialect: %s", str);
2078                         dtr = proto_item_add_subtree(dit, ett_smb_dialect);
2079                 }
2080
2081                 /* Buffer Format */
2082                 CHECK_BYTE_COUNT(1);
2083                 proto_tree_add_item(dtr, hf_smb_buffer_format, tvb, offset, 1,
2084                         TRUE);
2085                 COUNT_BYTES(1);
2086
2087                 /*Dialect Name */
2088                 CHECK_BYTE_COUNT(len);
2089                 proto_tree_add_string(dtr, hf_smb_dialect_name, tvb, offset,
2090                         len, str);
2091                 COUNT_BYTES(len);
2092         }
2093
2094         END_OF_SMB
2095
2096         return offset;
2097 }
2098
2099 static int
2100 dissect_negprot_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2101 {
2102         smb_info_t *si = pinfo->private_data;
2103         guint8 wc;
2104         guint16 dialect;
2105         const char *dn;
2106         int dn_len;
2107         guint16 bc;
2108         guint16 ekl=0;
2109         guint32 caps=0;
2110         gint16 tz;
2111
2112         WORD_COUNT;
2113
2114         /* Dialect Index */
2115         dialect = tvb_get_letohs(tvb, offset);
2116         switch(wc){
2117         case 1:
2118                 if(dialect==0xffff){
2119                         proto_tree_add_uint_format(tree, hf_smb_dialect_index,
2120                                 tvb, offset, 2, dialect,
2121                                 "Selected Index: -1, PC NETWORK PROGRAM 1.0 choosen");
2122                 } else {
2123                         proto_tree_add_uint(tree, hf_smb_dialect_index,
2124                                 tvb, offset, 2, dialect);
2125                 }
2126                 break;
2127         case 13:
2128                 proto_tree_add_uint_format(tree, hf_smb_dialect_index,
2129                         tvb, offset, 2, dialect,
2130                         "Dialect Index: %u, Greater than CORE PROTOCOL and up to LANMAN2.1", dialect);
2131                 break;
2132         case 17:
2133                 proto_tree_add_uint_format(tree, hf_smb_dialect_index,
2134                         tvb, offset, 2, dialect,
2135                         "Dialect Index: %u, greater than LANMAN2.1", dialect);
2136                 break;
2137         default:
2138                 proto_tree_add_text(tree, tvb, offset, wc*2,
2139                         "Words for unknown response format");
2140                 offset += wc*2;
2141                 goto bytecount;
2142         }
2143         offset += 2;
2144
2145         switch(wc){
2146         case 13:
2147                 /* Security Mode */
2148                 offset = dissect_negprot_security_mode(tvb, tree, offset, wc);
2149
2150                 /* Maximum Transmit Buffer Size */
2151                 proto_tree_add_item(tree, hf_smb_max_trans_buf_size,
2152                         tvb, offset, 2, TRUE);
2153                 offset += 2;
2154
2155                 /* Maximum Multiplex Count */
2156                 proto_tree_add_item(tree, hf_smb_max_mpx_count,
2157                         tvb, offset, 2, TRUE);
2158                 offset += 2;
2159
2160                 /* Maximum Vcs Number */
2161                 proto_tree_add_item(tree, hf_smb_max_vcs_num,
2162                         tvb, offset, 2, TRUE);
2163                 offset += 2;
2164
2165                 /* raw mode */
2166                 offset = dissect_negprot_rawmode(tvb, tree, offset);
2167
2168                 /* session key */
2169                 proto_tree_add_item(tree, hf_smb_session_key,
2170                         tvb, offset, 4, TRUE);
2171                 offset += 4;
2172
2173                 /* current time and date at server */
2174                 offset = dissect_smb_datetime(tvb, tree, offset, hf_smb_server_date_time, hf_smb_server_smb_date, hf_smb_server_smb_time,
2175                     TRUE);
2176
2177                 /* time zone */
2178                 tz = tvb_get_letohs(tvb, offset);
2179                 proto_tree_add_int_format(tree, hf_smb_server_timezone, tvb, offset, 2, tz, "Server Time Zone: %d min from UTC", tz);
2180                 offset += 2;
2181
2182                 /* encryption key length */
2183                 ekl = tvb_get_letohs(tvb, offset);
2184                 proto_tree_add_uint(tree, hf_smb_encryption_key_length, tvb, offset, 2, ekl);
2185                 offset += 2;
2186
2187                 /* 2 reserved bytes */
2188                 proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
2189                 offset += 2;
2190
2191                 break;
2192
2193         case 17:
2194                 /* Security Mode */
2195                 offset = dissect_negprot_security_mode(tvb, tree, offset, wc);
2196
2197                 /* Maximum Multiplex Count */
2198                 proto_tree_add_item(tree, hf_smb_max_mpx_count,
2199                         tvb, offset, 2, TRUE);
2200                 offset += 2;
2201
2202                 /* Maximum Vcs Number */
2203                 proto_tree_add_item(tree, hf_smb_max_vcs_num,
2204                         tvb, offset, 2, TRUE);
2205                 offset += 2;
2206
2207                 /* Maximum Transmit Buffer Size */
2208                 proto_tree_add_item(tree, hf_smb_max_trans_buf_size,
2209                         tvb, offset, 4, TRUE);
2210                 offset += 4;
2211
2212                 /* maximum raw buffer size */
2213                 proto_tree_add_item(tree, hf_smb_max_raw_buf_size,
2214                         tvb, offset, 4, TRUE);
2215                 offset += 4;
2216
2217                 /* session key */
2218                 proto_tree_add_item(tree, hf_smb_session_key,
2219                         tvb, offset, 4, TRUE);
2220                 offset += 4;
2221
2222                 /* server capabilities */
2223                 caps = dissect_negprot_capabilities(tvb, tree, offset);
2224                 offset += 4;
2225
2226                 /* system time */
2227                 offset = dissect_smb_64bit_time(tvb, tree, offset,
2228                                 hf_smb_system_time);
2229
2230                 /* time zone */
2231                 tz = tvb_get_letohs(tvb, offset);
2232                 proto_tree_add_int_format(tree, hf_smb_server_timezone,
2233                         tvb, offset, 2, tz,
2234                         "Server Time Zone: %d min from UTC", tz);
2235                 offset += 2;
2236
2237                 /* encryption key length */
2238                 ekl = tvb_get_guint8(tvb, offset);
2239                 proto_tree_add_uint(tree, hf_smb_encryption_key_length,
2240                         tvb, offset, 1, ekl);
2241                 offset += 1;
2242
2243                 break;
2244         }
2245
2246         BYTE_COUNT;
2247
2248         switch(wc){
2249         case 13:
2250                 /* challenge/response encryption key */
2251                 if(ekl){
2252                         CHECK_BYTE_COUNT(ekl);
2253                         proto_tree_add_item(tree, hf_smb_encryption_key, tvb, offset, ekl, TRUE);
2254                         COUNT_BYTES(ekl);
2255                 }
2256
2257                 /*
2258                  * Primary domain.
2259                  *
2260                  * XXX - not present if negotiated dialect isn't
2261                  * "DOS LANMAN 2.1" or "LANMAN2.1", but we'd either
2262                  * have to see the request, or assume what dialect strings
2263                  * were sent, to determine that.
2264                  *
2265                  * Is this something other than a primary domain if the
2266                  * negotiated dialect is Windows for Workgroups 3.1a?
2267                  * It appears to be 8 bytes of binary data in at least
2268                  * one capture - is that an encryption key or something
2269                  * such as that?
2270                  */
2271                 dn = get_unicode_or_ascii_string(tvb, &offset,
2272                         si->unicode, &dn_len, FALSE, FALSE, &bc);
2273                 if (dn == NULL)
2274                         goto endofcommand;
2275                 proto_tree_add_string(tree, hf_smb_primary_domain, tvb,
2276                         offset, dn_len,dn);
2277                 COUNT_BYTES(dn_len);
2278                 break;
2279
2280         case 17:
2281                 if(!(caps&SERVER_CAP_EXTENDED_SECURITY)){
2282                         /* challenge/response encryption key */
2283                         /* XXX - is this aligned on an even boundary? */
2284                         if(ekl){
2285                                 CHECK_BYTE_COUNT(ekl);
2286                                 proto_tree_add_item(tree, hf_smb_encryption_key,
2287                                         tvb, offset, ekl, TRUE);
2288                                 COUNT_BYTES(ekl);
2289                         }
2290
2291                         /* domain */
2292                         /* this string is special, unicode is flagged in caps */
2293                         /* This string is NOT padded to be 16bit aligned.
2294                            (seen in actual capture)
2295                            XXX - I've seen a capture where it appears to be
2296                            so aligned, but I've also seen captures where
2297                            it is.  The captures where it appeared to be
2298                            aligned may have been from buggy servers. */
2299                         si->unicode = (caps&SERVER_CAP_UNICODE);
2300                         dn = get_unicode_or_ascii_string(tvb,
2301                                 &offset, si->unicode, &dn_len, TRUE, FALSE,
2302                                 &bc);
2303                         if (dn == NULL)
2304                                 goto endofcommand;
2305                         proto_tree_add_string(tree, hf_smb_primary_domain,
2306                                 tvb, offset, dn_len, dn);
2307                         COUNT_BYTES(dn_len);
2308
2309                         /* server name, seen in w2k pro capture */
2310                         dn = get_unicode_or_ascii_string(tvb,
2311                                 &offset, si->unicode, &dn_len, TRUE, FALSE,
2312                                 &bc);
2313                         if (dn == NULL)
2314                                 goto endofcommand;
2315                         proto_tree_add_string(tree, hf_smb_server,
2316                                 tvb, offset, dn_len, dn);
2317                         COUNT_BYTES(dn_len);
2318
2319                 } else {
2320                         proto_item *blob_item;
2321
2322                         /* guid */
2323                         /* XXX - show it in the standard Microsoft format
2324                            for GUIDs? */
2325                         CHECK_BYTE_COUNT(16);
2326                         proto_tree_add_item(tree, hf_smb_server_guid,
2327                                 tvb, offset, 16, TRUE);
2328                         COUNT_BYTES(16);
2329
2330                         blob_item = proto_tree_add_item(
2331                                 tree, hf_smb_security_blob,
2332                                 tvb, offset, bc, TRUE);
2333
2334                         /* security blob */
2335                         if(bc){
2336                                 tvbuff_t *gssapi_tvb;
2337                                 proto_tree *gssapi_tree;
2338
2339                                 gssapi_tree = proto_item_add_subtree(
2340                                         blob_item, ett_smb_gssapi);
2341
2342                                 gssapi_tvb = tvb_new_subset(
2343                                         tvb, offset, bc, bc);
2344
2345                                 call_dissector(
2346                                         gssapi_handle, gssapi_tvb, pinfo, 
2347                                         gssapi_tree);
2348
2349                                 COUNT_BYTES(bc);
2350                         }
2351                 }
2352                 break;
2353         }
2354
2355         END_OF_SMB
2356
2357         return offset;
2358 }
2359
2360
2361 static int
2362 dissect_old_dir_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2363 {
2364         smb_info_t *si = pinfo->private_data;
2365         int dn_len;
2366         const char *dn;
2367         guint8 wc;
2368         guint16 bc;
2369
2370         WORD_COUNT;
2371  
2372         BYTE_COUNT;
2373
2374         /* buffer format */
2375         CHECK_BYTE_COUNT(1);
2376         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2377         COUNT_BYTES(1);
2378
2379         /* dir name */
2380         dn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &dn_len,
2381                 FALSE, FALSE, &bc);
2382         if (dn == NULL)
2383                 goto endofcommand;
2384         proto_tree_add_string(tree, hf_smb_dir_name, tvb, offset, dn_len,
2385                 dn);
2386         COUNT_BYTES(dn_len);
2387
2388         if (check_col(pinfo->cinfo, COL_INFO)) {
2389                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Directory: %s", dn);
2390         }
2391
2392         END_OF_SMB
2393
2394         return offset;
2395 }
2396
2397 static int
2398 dissect_empty(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2399 {
2400         guint8 wc;
2401         guint16 bc;
2402  
2403         WORD_COUNT;
2404  
2405         BYTE_COUNT;
2406
2407         END_OF_SMB
2408
2409         return offset;
2410 }
2411
2412 static int
2413 dissect_echo_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2414 {
2415         guint16 ec, bc;
2416         guint8 wc;
2417
2418         WORD_COUNT;
2419
2420         /* echo count */
2421         ec = tvb_get_letohs(tvb, offset);
2422         proto_tree_add_uint(tree, hf_smb_echo_count, tvb, offset, 2, ec);
2423         offset += 2;
2424
2425         BYTE_COUNT;
2426
2427         if (bc != 0) {
2428                 /* echo data */
2429                 proto_tree_add_item(tree, hf_smb_echo_data, tvb, offset, bc, TRUE);
2430                 COUNT_BYTES(bc);
2431         }
2432
2433         END_OF_SMB
2434
2435         return offset;
2436 }
2437
2438 static int
2439 dissect_echo_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2440 {
2441         guint16 bc;
2442         guint8 wc;
2443
2444         WORD_COUNT;
2445
2446         /* echo sequence number */
2447         proto_tree_add_item(tree, hf_smb_echo_seq_num, tvb, offset, 2, TRUE);
2448         offset += 2;
2449
2450         BYTE_COUNT;
2451
2452         if (bc != 0) {
2453                 /* echo data */
2454                 proto_tree_add_item(tree, hf_smb_echo_data, tvb, offset, bc, TRUE);
2455                 COUNT_BYTES(bc);
2456         }
2457
2458         END_OF_SMB
2459
2460         return offset;
2461 }
2462
2463 static int
2464 dissect_tree_connect_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2465 {
2466         smb_info_t *si = pinfo->private_data;
2467         int an_len, pwlen;
2468         const char *an;
2469         guint8 wc;
2470         guint16 bc;
2471
2472         WORD_COUNT;
2473  
2474         BYTE_COUNT;
2475
2476         /* buffer format */
2477         CHECK_BYTE_COUNT(1);
2478         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2479         COUNT_BYTES(1);
2480
2481         /* Path */
2482         an = get_unicode_or_ascii_string(tvb, &offset,
2483                 si->unicode, &an_len, FALSE, FALSE, &bc);
2484         if (an == NULL)
2485                 goto endofcommand;
2486         proto_tree_add_string(tree, hf_smb_path, tvb,
2487                 offset, an_len, an);
2488         COUNT_BYTES(an_len);
2489
2490         if (check_col(pinfo->cinfo, COL_INFO)) {
2491                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", an);
2492         }
2493
2494         /* buffer format */
2495         CHECK_BYTE_COUNT(1);
2496         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2497         COUNT_BYTES(1);
2498
2499         /* password, ANSI */
2500         /* XXX - what if this runs past bc? */
2501         pwlen = tvb_strsize(tvb, offset);
2502         CHECK_BYTE_COUNT(pwlen);
2503         proto_tree_add_item(tree, hf_smb_password,
2504                 tvb, offset, pwlen, TRUE);
2505         COUNT_BYTES(pwlen);
2506
2507         /* buffer format */
2508         CHECK_BYTE_COUNT(1);
2509         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2510         COUNT_BYTES(1);
2511
2512         /* Service */
2513         an = get_unicode_or_ascii_string(tvb, &offset,
2514                 si->unicode, &an_len, FALSE, FALSE, &bc);
2515         if (an == NULL)
2516                 goto endofcommand;
2517         proto_tree_add_string(tree, hf_smb_service, tvb,
2518                 offset, an_len, an);
2519         COUNT_BYTES(an_len);
2520
2521         END_OF_SMB
2522
2523         return offset;
2524 }
2525
2526 static int
2527 dissect_tree_connect_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2528 {
2529         guint8 wc;
2530         guint16 bc;
2531
2532         WORD_COUNT;
2533  
2534         /* Maximum Buffer Size */
2535         proto_tree_add_item(tree, hf_smb_max_buf_size, tvb, offset, 2, TRUE);
2536         offset += 2;
2537
2538         /* tid */
2539         proto_tree_add_item(tree, hf_smb_tid, tvb, offset, 2, TRUE);
2540         offset += 2;
2541
2542         BYTE_COUNT;
2543
2544         END_OF_SMB
2545
2546         return offset;
2547 }
2548  
2549
2550 static const true_false_string tfs_of_create = {
2551         "Create file if it does not exist",
2552         "Fail if file does not exist"
2553 };
2554 static const value_string of_open[] = {
2555         { 0,            "Fail if file exists"},
2556         { 1,            "Open file if it exists"},
2557         { 2,            "Truncate file if it exists"},
2558         {0, NULL}
2559 };
2560 static int
2561 dissect_open_function(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
2562 {
2563         guint16 mask;
2564         proto_item *item = NULL;
2565         proto_tree *tree = NULL;
2566
2567         mask = tvb_get_letohs(tvb, offset);
2568
2569         if(parent_tree){
2570                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
2571                         "Open Function: 0x%04x", mask);
2572                 tree = proto_item_add_subtree(item, ett_smb_openfunction);
2573         }
2574
2575         proto_tree_add_boolean(tree, hf_smb_open_function_create,
2576                 tvb, offset, 2, mask);
2577         proto_tree_add_uint(tree, hf_smb_open_function_open,
2578                 tvb, offset, 2, mask);
2579
2580         offset += 2;
2581
2582         return offset;
2583 }
2584
2585
2586 static const true_false_string tfs_mf_file = {
2587         "Target must be a file",
2588         "Target needn't be a file"
2589 };
2590 static const true_false_string tfs_mf_dir = {
2591         "Target must be a directory",
2592         "Target needn't be a directory"
2593 };
2594 static const true_false_string tfs_mf_verify = {
2595         "MUST verify all writes",
2596         "Don't have to verify writes"
2597 };
2598 static int
2599 dissect_move_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
2600 {
2601         guint16 mask;
2602         proto_item *item = NULL;
2603         proto_tree *tree = NULL;
2604
2605         mask = tvb_get_letohs(tvb, offset);
2606
2607         if(parent_tree){
2608                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
2609                         "Flags: 0x%04x", mask);
2610                 tree = proto_item_add_subtree(item, ett_smb_move_copy_flags);
2611         }
2612  
2613         proto_tree_add_boolean(tree, hf_smb_move_flags_verify,
2614                 tvb, offset, 2, mask);
2615         proto_tree_add_boolean(tree, hf_smb_move_flags_dir,
2616                 tvb, offset, 2, mask);
2617         proto_tree_add_boolean(tree, hf_smb_move_flags_file,
2618                 tvb, offset, 2, mask);
2619
2620         offset += 2;
2621
2622         return offset;
2623 }
2624
2625 static const true_false_string tfs_cf_mode = {
2626         "ASCII",
2627         "Binary"
2628 };
2629 static const true_false_string tfs_cf_tree_copy = {
2630         "Copy is a tree copy",
2631         "Copy is a file copy"
2632 };
2633 static const true_false_string tfs_cf_ea_action = {
2634         "Fail copy",
2635         "Discard EAs"
2636 };
2637 static int
2638 dissect_copy_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
2639 {
2640         guint16 mask;
2641         proto_item *item = NULL;
2642         proto_tree *tree = NULL;
2643
2644         mask = tvb_get_letohs(tvb, offset);
2645
2646         if(parent_tree){
2647                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
2648                         "Flags: 0x%04x", mask);
2649                 tree = proto_item_add_subtree(item, ett_smb_move_copy_flags);
2650         }
2651  
2652         proto_tree_add_boolean(tree, hf_smb_copy_flags_ea_action,
2653                 tvb, offset, 2, mask);
2654         proto_tree_add_boolean(tree, hf_smb_copy_flags_tree_copy,
2655                 tvb, offset, 2, mask);
2656         proto_tree_add_boolean(tree, hf_smb_copy_flags_verify,
2657                 tvb, offset, 2, mask);
2658         proto_tree_add_boolean(tree, hf_smb_copy_flags_source_mode,
2659                 tvb, offset, 2, mask);
2660         proto_tree_add_boolean(tree, hf_smb_copy_flags_dest_mode,
2661                 tvb, offset, 2, mask);
2662         proto_tree_add_boolean(tree, hf_smb_copy_flags_dir,
2663                 tvb, offset, 2, mask);
2664         proto_tree_add_boolean(tree, hf_smb_copy_flags_file,
2665                 tvb, offset, 2, mask);
2666
2667         offset += 2;
2668
2669         return offset;
2670 }
2671
2672 static int
2673 dissect_move_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2674 {
2675         smb_info_t *si = pinfo->private_data;
2676         int fn_len;
2677         guint16 tid;
2678         guint16 bc;
2679         guint8 wc;
2680         const char *fn;
2681
2682         WORD_COUNT;
2683
2684         /* tid */
2685         tid = tvb_get_letohs(tvb, offset);
2686         proto_tree_add_uint_format(tree, hf_smb_tid, tvb, offset, 2, tid,
2687                 "TID (target): 0x%04x", tid);
2688         offset += 2;
2689
2690         /* open function */
2691         offset = dissect_open_function(tvb, tree, offset);
2692
2693         /* move flags */
2694         offset = dissect_move_flags(tvb, tree, offset);
2695
2696         BYTE_COUNT;
2697
2698         /* buffer format */
2699         CHECK_BYTE_COUNT(1);
2700         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2701         COUNT_BYTES(1);
2702
2703         /* file name */
2704         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
2705                 FALSE, FALSE, &bc);
2706         if (fn == NULL)
2707                 goto endofcommand;
2708         proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
2709                 fn_len, fn, "Old File Name: %s", fn);
2710         COUNT_BYTES(fn_len);
2711
2712         if (check_col(pinfo->cinfo, COL_INFO)) {
2713                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Old Name: %s", fn);
2714         }
2715
2716         /* buffer format */
2717         CHECK_BYTE_COUNT(1);
2718         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2719         COUNT_BYTES(1);
2720
2721         /* file name */
2722         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
2723                 FALSE, FALSE, &bc);
2724         if (fn == NULL)
2725                 goto endofcommand;
2726         proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
2727                 fn_len, fn, "New File Name: %s", fn);
2728         COUNT_BYTES(fn_len);
2729
2730         if (check_col(pinfo->cinfo, COL_INFO)) {
2731                 col_append_fstr(pinfo->cinfo, COL_INFO, ", New Name: %s", fn);
2732         }
2733
2734         END_OF_SMB
2735
2736         return offset;
2737 }
2738
2739 static int
2740 dissect_copy_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2741 {
2742         smb_info_t *si = pinfo->private_data;
2743         int fn_len;
2744         guint16 tid;
2745         guint16 bc;
2746         guint8 wc;
2747         const char *fn;
2748
2749         WORD_COUNT;
2750
2751         /* tid */
2752         tid = tvb_get_letohs(tvb, offset);
2753         proto_tree_add_uint_format(tree, hf_smb_tid, tvb, offset, 2, tid,
2754                 "TID (target): 0x%04x", tid);
2755         offset += 2;
2756
2757         /* open function */
2758         offset = dissect_open_function(tvb, tree, offset);
2759
2760         /* copy flags */
2761         offset = dissect_copy_flags(tvb, tree, offset);
2762
2763         BYTE_COUNT;
2764
2765         /* buffer format */
2766         CHECK_BYTE_COUNT(1);
2767         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2768         COUNT_BYTES(1);
2769
2770         /* file name */
2771         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
2772                 FALSE, FALSE, &bc);
2773         if (fn == NULL)
2774                 goto endofcommand;
2775         proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
2776                 fn_len, fn, "Source File Name: %s", fn);
2777         COUNT_BYTES(fn_len);
2778
2779         if (check_col(pinfo->cinfo, COL_INFO)) {
2780                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Source Name: %s", fn);
2781         }
2782
2783         /* buffer format */
2784         CHECK_BYTE_COUNT(1);
2785         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2786         COUNT_BYTES(1);
2787
2788         /* file name */
2789         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
2790                 FALSE, FALSE, &bc);
2791         if (fn == NULL)
2792                 goto endofcommand;
2793         proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
2794                 fn_len, fn, "Destination File Name: %s", fn);
2795         COUNT_BYTES(fn_len);
2796
2797         if (check_col(pinfo->cinfo, COL_INFO)) {
2798                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Destination Name: %s", fn);
2799         }
2800
2801         END_OF_SMB
2802
2803         return offset;
2804 }
2805
2806 static int
2807 dissect_move_copy_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2808 {
2809         smb_info_t *si = pinfo->private_data;
2810         int fn_len;
2811         const char *fn;
2812         guint8 wc;
2813         guint16 bc;
2814
2815         WORD_COUNT;
2816
2817         /* # of files moved */
2818         proto_tree_add_item(tree, hf_smb_files_moved, tvb, offset, 2, TRUE);
2819         offset += 2;
2820
2821         BYTE_COUNT;
2822
2823         /* buffer format */
2824         CHECK_BYTE_COUNT(1);
2825         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2826         COUNT_BYTES(1);
2827
2828         /* file name */
2829         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
2830                 FALSE, FALSE, &bc);
2831         if (fn == NULL)
2832                 goto endofcommand;
2833         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
2834                 fn);
2835         COUNT_BYTES(fn_len);
2836
2837         END_OF_SMB
2838
2839         return offset;
2840 }
2841
2842 static int
2843 dissect_open_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2844 {
2845         smb_info_t *si = pinfo->private_data;
2846         int fn_len;
2847         const char *fn;
2848         guint8 wc;
2849         guint16 bc;
2850
2851         WORD_COUNT;
2852
2853         /* desired access */
2854         offset = dissect_access(tvb, tree, offset, "Desired");
2855
2856         /* Search Attributes */
2857         offset = dissect_search_attributes(tvb, tree, offset);
2858
2859         BYTE_COUNT;
2860
2861         /* buffer format */
2862         CHECK_BYTE_COUNT(1);
2863         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2864         COUNT_BYTES(1);
2865
2866         /* file name */
2867         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
2868                 FALSE, FALSE, &bc);
2869         if (fn == NULL)
2870                 goto endofcommand;
2871         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
2872                 fn);
2873         COUNT_BYTES(fn_len);
2874
2875         if (check_col(pinfo->cinfo, COL_INFO)) {
2876                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
2877         }
2878
2879         END_OF_SMB
2880
2881         return offset;
2882 }
2883
2884 void
2885 add_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2886     int len, guint16 fid)
2887 {
2888         proto_tree_add_uint(tree, hf_smb_fid, tvb, offset, len, fid);
2889         if (check_col(pinfo->cinfo, COL_INFO))
2890                 col_append_fstr(pinfo->cinfo, COL_INFO, ", FID: 0x%04x", fid);
2891 }
2892
2893 static int
2894 dissect_open_file_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2895 {
2896         guint8 wc;
2897         guint16 bc;
2898         guint16 fid;
2899
2900         WORD_COUNT;
2901
2902         /* fid */
2903         fid = tvb_get_letohs(tvb, offset);
2904         add_fid(tvb, pinfo, tree, offset, 2, fid);
2905         offset += 2;
2906
2907         /* File Attributes */
2908         offset = dissect_file_attributes(tvb, tree, offset);
2909
2910         /* last write time */
2911         offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_last_write_time);
2912         
2913         /* File Size */
2914         proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
2915         offset += 4;
2916
2917         /* granted access */
2918         offset = dissect_access(tvb, tree, offset, "Granted");
2919
2920         BYTE_COUNT;
2921
2922         END_OF_SMB
2923
2924         return offset;
2925 }
2926
2927 static int
2928 dissect_fid(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2929 {
2930         guint8 wc;
2931         guint16 bc;
2932         guint16 fid;
2933
2934         WORD_COUNT;
2935
2936         /* fid */
2937         fid = tvb_get_letohs(tvb, offset);
2938         add_fid(tvb, pinfo, tree, offset, 2, fid);
2939         offset += 2;
2940
2941         BYTE_COUNT;
2942
2943         END_OF_SMB
2944
2945         return offset;
2946 }
2947
2948 static int
2949 dissect_create_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2950 {
2951         smb_info_t *si = pinfo->private_data;
2952         int fn_len;
2953         const char *fn;
2954         guint8 wc;
2955         guint16 bc;
2956
2957         WORD_COUNT;
2958
2959         /* file attributes */
2960         offset = dissect_file_attributes(tvb, tree, offset);
2961
2962         /* creation time */
2963         offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_create_time);
2964
2965         BYTE_COUNT;
2966
2967         /* buffer format */
2968         CHECK_BYTE_COUNT(1);
2969         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2970         COUNT_BYTES(1);
2971
2972         /* File Name */
2973         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
2974                 FALSE, FALSE, &bc);
2975         if (fn == NULL)
2976                 goto endofcommand;
2977         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
2978                 fn);
2979         COUNT_BYTES(fn_len);
2980
2981         if (check_col(pinfo->cinfo, COL_INFO)) {
2982                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
2983         }
2984
2985         END_OF_SMB
2986
2987         return offset;
2988 }
2989
2990 static int
2991 dissect_close_file_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
2992 {
2993         guint8 wc;
2994         guint16 bc, fid;
2995
2996         WORD_COUNT;
2997
2998         /* fid */
2999         fid = tvb_get_letohs(tvb, offset);
3000         add_fid(tvb, pinfo, tree, offset, 2, fid);
3001         offset += 2;
3002
3003         /* last write time */
3004         offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_last_write_time);
3005
3006         BYTE_COUNT;
3007
3008         END_OF_SMB
3009
3010         return offset;
3011 }
3012
3013 static int
3014 dissect_delete_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
3015 {
3016         smb_info_t *si = pinfo->private_data;
3017         int fn_len;
3018         const char *fn;
3019         guint8 wc;
3020         guint16 bc;
3021
3022         WORD_COUNT;
3023
3024         /* search attributes */
3025         offset = dissect_search_attributes(tvb, tree, offset);
3026
3027         BYTE_COUNT;
3028
3029         /* buffer format */
3030         CHECK_BYTE_COUNT(1);
3031         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
3032         COUNT_BYTES(1);
3033
3034         /* file name */
3035         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
3036                 FALSE, FALSE, &bc);
3037         if (fn == NULL)
3038                 goto endofcommand;
3039         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
3040                 fn);
3041         COUNT_BYTES(fn_len);
3042
3043         if (check_col(pinfo->cinfo, COL_INFO)) {
3044                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
3045         }
3046
3047         END_OF_SMB
3048
3049         return offset;
3050 }
3051
3052 static int
3053 dissect_rename_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
3054 {
3055         smb_info_t *si = pinfo->private_data;
3056         int fn_len;
3057         const char *fn;
3058         guint8 wc;
3059         guint16 bc;
3060
3061         WORD_COUNT;
3062
3063         /* search attributes */
3064         offset = dissect_search_attributes(tvb, tree, offset);
3065
3066         BYTE_COUNT;
3067
3068         /* buffer format */
3069         CHECK_BYTE_COUNT(1);
3070         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
3071         COUNT_BYTES(1);
3072
3073         /* old file name */
3074         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
3075                 FALSE, FALSE, &bc);
3076         if (fn == NULL)
3077                 goto endofcommand;
3078         proto_tree_add_string(tree, hf_smb_old_file_name, tvb, offset, fn_len,
3079                 fn);
3080         COUNT_BYTES(fn_len);
3081
3082         if (check_col(pinfo->cinfo, COL_INFO)) {
3083                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Old Name: %s", fn);
3084         }
3085
3086         /* buffer format */
3087         CHECK_BYTE_COUNT(1);
3088         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
3089         COUNT_BYTES(1);
3090
3091         /* file name */
3092         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
3093                 FALSE, FALSE, &bc);
3094         if (fn == NULL)
3095                 goto endofcommand;
3096         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
3097                 fn);
3098         COUNT_BYTES(fn_len);
3099
3100         if (check_col(pinfo->cinfo, COL_INFO)) {
3101                 col_append_fstr(pinfo->cinfo, COL_INFO, ", New Name: %s", fn);
3102         }
3103
3104         END_OF_SMB
3105
3106         return offset;
3107 }
3108
3109 static int
3110 dissect_nt_rename_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
3111 {
3112         smb_info_t *si = pinfo->private_data;
3113         int fn_len;
3114         const char *fn;
3115         guint8 wc;
3116         guint16 bc;
3117
3118         WORD_COUNT;
3119
3120         /* search attributes */
3121         offset = dissect_search_attributes(tvb, tree, offset);
3122  
3123         proto_tree_add_uint(tree, hf_smb_nt_rename_level, tvb, offset, 2, tvb_get_letohs(tvb, offset));
3124         offset += 2;
3125
3126         proto_tree_add_item(tree, hf_smb_cluster_count, tvb, offset, 4, TRUE);
3127         offset += 4;
3128
3129         BYTE_COUNT;
3130
3131         /* buffer format */
3132         CHECK_BYTE_COUNT(1);
3133         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
3134         COUNT_BYTES(1);
3135
3136         /* old file name */
3137         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
3138                 FALSE, FALSE, &bc);
3139         if (fn == NULL)
3140                 goto endofcommand;
3141         proto_tree_add_string(tree, hf_smb_old_file_name, tvb, offset, fn_len,
3142                 fn);
3143         COUNT_BYTES(fn_len);
3144
3145         if (check_col(pinfo->cinfo, COL_INFO)) {
3146                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Old Name: %s", fn);
3147         }
3148
3149         /* buffer format */
3150         CHECK_BYTE_COUNT(1);
3151         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
3152         COUNT_BYTES(1);
3153
3154         /* file name */
3155         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
3156                 FALSE, FALSE, &bc);
3157         if (fn == NULL)
3158                 goto endofcommand;
3159         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
3160                 fn);
3161         COUNT_BYTES(fn_len);
3162
3163         if (check_col(pinfo->cinfo, COL_INFO)) {
3164                 col_append_fstr(pinfo->cinfo, COL_INFO, ", New Name: %s", fn);
3165         }
3166
3167         END_OF_SMB
3168
3169         return offset;
3170 }
3171
3172
3173 static int
3174 dissect_query_information_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
3175 {
3176         smb_info_t *si = pinfo->private_data;
3177         guint16 bc;
3178         guint8 wc;
3179         const char *fn;
3180         int fn_len;
3181
3182         WORD_COUNT;
3183
3184         BYTE_COUNT;
3185
3186         /* Buffer Format */
3187         CHECK_BYTE_COUNT(1);
3188         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
3189         COUNT_BYTES(1);
3190
3191         /* File Name */
3192         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
3193                 FALSE, FALSE, &bc);
3194         if (fn == NULL)
3195                 goto endofcommand;
3196         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
3197                 fn);
3198         COUNT_BYTES(fn_len);
3199
3200         if (check_col(pinfo->cinfo, COL_INFO)) {
3201                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
3202         }
3203
3204         END_OF_SMB
3205
3206         return offset;
3207 }
3208  
3209 static int
3210 dissect_query_information_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
3211 {
3212         guint16 bc;
3213         guint8 wc;
3214
3215         WORD_COUNT;
3216
3217         /* File Attributes */
3218         offset = dissect_file_attributes(tvb, tree, offset);
3219
3220         /* Last Write Time */
3221         offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_last_write_time);
3222
3223         /* File Size */
3224         proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
3225         offset += 4;
3226
3227         /* 10 reserved bytes */
3228         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 10, TRUE);
3229         offset += 10;
3230
3231         BYTE_COUNT;
3232
3233         END_OF_SMB
3234
3235         return offset;
3236 }
3237
3238 static int
3239 dissect_set_information_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
3240 {
3241         smb_info_t *si = pinfo->private_data;
3242         int fn_len;
3243         const char *fn;
3244         guint8 wc;
3245         guint16 bc;
3246
3247         WORD_COUNT;
3248
3249         /* file attributes */
3250         offset = dissect_file_attributes(tvb, tree, offset);
3251
3252         /* last write time */
3253         offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_last_write_time);
3254
3255         /* 10 reserved bytes */
3256         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 10, TRUE);
3257         offset += 10;
3258
3259         BYTE_COUNT;
3260
3261         /* buffer format */
3262         CHECK_BYTE_COUNT(1);
3263         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
3264         COUNT_BYTES(1);
3265
3266         /* file name */
3267         fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
3268                 FALSE, FALSE, &bc);
3269         if (fn == NULL)
3270                 goto endofcommand;
3271         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
3272                 fn);
3273         COUNT_BYTES(fn_len);
3274
3275         if (check_col(pinfo->cinfo, COL_INFO)) {
3276                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
3277         }
3278
3279         END_OF_SMB
3280
3281         return offset;
3282 }
3283
3284 static int
3285 dissect_read_file_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
3286 {
3287         guint8 wc;
3288         guint16 bc;
3289         smb_info_t *si;
3290         unsigned int fid;
3291
3292         WORD_COUNT;
3293
3294         /* fid */
3295         fid = tvb_get_letohs(tvb, offset);
3296         add_fid(tvb, pinfo, tree, offset, 2, fid);
3297         offset += 2;
3298         if (!pinfo->fd->flags.visited) {
3299                 /* remember the FID for the processing of the response */
3300                 si = (smb_info_t *)pinfo->private_data;
3301                 si->sip->extra_info=(void *)fid;
3302         }
3303
3304         /* read count */
3305         proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
3306         offset += 2;
3307
3308         /* offset */
3309         proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
3310         offset += 4;
3311
3312         /* remaining */
3313         proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
3314         offset += 2;
3315
3316         BYTE_COUNT;
3317
3318         END_OF_SMB
3319
3320         return offset;
3321 }
3322
3323 int
3324 dissect_file_data(tvbuff_t *tvb, proto_tree *tree, int offset, guint16 bc, guint16 datalen)
3325 {
3326         int tvblen;
3327
3328         if(bc>datalen){
3329                 /* We have some initial padding bytes. */
3330                 /* XXX - use the data offset here instead? */
3331                 proto_tree_add_item(tree, hf_smb_padding, tvb, offset, bc-datalen,
3332                         TRUE);
3333                 offset += bc-datalen;
3334                 bc = datalen;
3335         }
3336         tvblen = tvb_length_remaining(tvb, offset);
3337         if(bc>tvblen){
3338                 proto_tree_add_bytes_format(tree, hf_smb_file_data, tvb, offset, tvblen, tvb_get_ptr(tvb, offset, tvblen),"File Data: Incomplete. Only %d of %u bytes", tvblen, bc);
3339                 offset += tvblen;
3340         } else {
3341                 proto_tree_add_item(tree, hf_smb_file_data, tvb, offset, bc, TRUE);
3342                 offset += bc;
3343         }
3344         return offset;
3345 }
3346
3347 static int
3348 dissect_file_data_dcerpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3349     proto_tree *top_tree, int offset, guint16 bc, guint16 datalen, guint16 fid)
3350 {
3351         int tvblen;
3352         tvbuff_t *dcerpc_tvb;
3353
3354         if(bc>datalen){
3355                 /* We have some initial padding bytes. */
3356                 /* XXX - use the data offset here instead? */
3357                 proto_tree_add_item(tree, hf_smb_padding, tvb, offset, bc-datalen,
3358                         TRUE);
3359                 offset += bc-datalen;
3360                 bc = datalen;
3361         }
3362         tvblen = tvb_length_remaining(tvb, offset);
3363         dcerpc_tvb = tvb_new_subset(tvb, offset, tvblen, bc);
3364         dissect_pipe_dcerpc(dcerpc_tvb, pinfo, top_tree, tree, fid);
3365         if(bc>tvblen)
3366                 offset += tvblen;
3367         else
3368                 offset += bc;
3369         return offset;
3370 }
3371
3372 static int
3373 dissect_read_file_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
3374 {
3375         guint16 cnt=0, bc;
3376         guint8 wc;
3377         smb_info_t *si = (smb_info_t *)pinfo->private_data;
3378         int fid=0;
3379
3380         WORD_COUNT;
3381
3382         /* read count */
3383         cnt = tvb_get_letohs(tvb, offset);
3384         proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
3385         offset += 2;
3386
3387         /* 8 reserved bytes */
3388         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 8, TRUE);
3389         offset += 8;
3390
3391         /* If we have seen the request, then print which FID this refers to */
3392         /* first check if we have seen the request */
3393         if(si->sip != NULL && si->sip->frame_req>0){
3394                 fid=(int)si->sip->extra_info;
3395                 add_fid(tvb, pinfo, tree, 0, 0, fid);
3396         }
3397
3398         BYTE_COUNT;
3399
3400         /* buffer format */
3401         CHECK_BYTE_COUNT(1);
3402         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
3403         COUNT_BYTES(1);
3404
3405         /* data len */
3406         CHECK_BYTE_COUNT(2);
3407         proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
3408         COUNT_BYTES(2);
3409
3410         /* another way to transport DCERPC over SMB is to skip Transaction completely and just
3411            read write */
3412         if(bc){
3413                 if(si->sip != NULL && si->sip->flags&SMB_SIF_TID_IS_IPC){
3414                         /* dcerpc call */
3415                         offset = dissect_file_data_dcerpc(tvb, pinfo, tree,
3416                             top_tree, offset, bc, bc, fid);
3417                 } else {
3418                         /* ordinary file data, or we didn't see the request,
3419                            so we don't know whether this is a DCERPC call
3420                            or not */
3421                         offset = dissect_file_data(tvb, tree, offset, bc, bc);
3422                 }
3423                 bc = 0;
3424         }
3425
3426         END_OF_SMB
3427
3428         return offset;
3429 }
3430
3431 static int
3432 dissect_lock_and_read_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
3433 {
3434         guint16 cnt, bc;
3435         guint8 wc;
3436
3437         WORD_COUNT;
3438
3439         /* read count */
3440         cnt = tvb_get_letohs(tvb, offset);
3441         proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
3442         offset += 2;
3443
3444         /* 8 reserved bytes */
3445         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 8, TRUE);
3446         offset += 8;
3447
3448         BYTE_COUNT;
3449
3450         /* buffer format */
3451         CHECK_BYTE_COUNT(1);
3452         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);