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