Export dissect_nt_sec_desc() so it can be used by other dissectors.
[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.209 2002/02/21 18:39:49 tpot 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
542 static gint ett_smb = -1;
543 static gint ett_smb_hdr = -1;
544 static gint ett_smb_command = -1;
545 static gint ett_smb_fileattributes = -1;
546 static gint ett_smb_capabilities = -1;
547 static gint ett_smb_aflags = -1;
548 static gint ett_smb_dialect = -1;
549 static gint ett_smb_dialects = -1;
550 static gint ett_smb_mode = -1;
551 static gint ett_smb_rawmode = -1;
552 static gint ett_smb_flags = -1;
553 static gint ett_smb_flags2 = -1;
554 static gint ett_smb_desiredaccess = -1;
555 static gint ett_smb_search = -1;
556 static gint ett_smb_file = -1;
557 static gint ett_smb_openfunction = -1;
558 static gint ett_smb_filetype = -1;
559 static gint ett_smb_openaction = -1;
560 static gint ett_smb_writemode = -1;
561 static gint ett_smb_lock_type = -1;
562 static gint ett_smb_ssetupandxaction = -1;
563 static gint ett_smb_optionsup = -1;
564 static gint ett_smb_time_date = -1;
565 static gint ett_smb_move_flags = -1;
566 static gint ett_smb_file_attributes = -1;
567 static gint ett_smb_search_resume_key = -1;
568 static gint ett_smb_search_dir_info = -1;
569 static gint ett_smb_unlocks = -1;
570 static gint ett_smb_unlock = -1;
571 static gint ett_smb_locks = -1;
572 static gint ett_smb_lock = -1;
573 static gint ett_smb_open_flags = -1;
574 static gint ett_smb_ipc_state = -1;
575 static gint ett_smb_open_action = -1;
576 static gint ett_smb_setup_action = -1;
577 static gint ett_smb_connect_flags = -1;
578 static gint ett_smb_connect_support_bits = -1;
579 static gint ett_smb_nt_access_mask = -1;
580 static gint ett_smb_nt_create_bits = -1;
581 static gint ett_smb_nt_create_options = -1;
582 static gint ett_smb_nt_share_access = -1;
583 static gint ett_smb_nt_security_flags = -1;
584 static gint ett_smb_nt_trans_setup = -1;
585 static gint ett_smb_nt_notify_completion_filter = -1;
586 static gint ett_smb_nt_ioctl_flags = -1;
587 static gint ett_smb_security_information_mask = -1;
588 static gint ett_smb_print_queue_entry = -1;
589 static gint ett_smb_transaction_flags = -1;
590 static gint ett_smb_transaction_params = -1;
591 static gint ett_smb_find_first2_flags = -1;
592 static gint ett_smb_transaction_data = -1;
593 static gint ett_smb_stream_info = -1;
594 static gint ett_smb_dfs_referrals = -1;
595 static gint ett_smb_dfs_referral = -1;
596 static gint ett_smb_dfs_referral_flags = -1;
597 static gint ett_smb_get_dfs_flags = -1;
598 static gint ett_smb_ff2_data = -1;
599 static gint ett_smb_device_characteristics = -1;
600 static gint ett_smb_fs_attributes = -1;
601 static gint ett_smb_segments = -1;
602 static gint ett_smb_sec_desc = -1;
603 static gint ett_smb_sid = -1;
604 static gint ett_smb_acl = -1;
605 static gint ett_smb_ace = -1;
606 static gint ett_smb_ace_flags = -1;
607 static gint ett_smb_sec_desc_type = -1;
608
609 proto_tree *top_tree=NULL;     /* ugly */
610
611 static char *decode_smb_name(unsigned char);
612 static int dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree, guint8 cmd);
613 static const gchar *get_unicode_or_ascii_string(tvbuff_t *tvb,
614     int *offsetp, packet_info *pinfo, int *len, gboolean nopad,
615     gboolean exactlen, guint16 *bcp);
616
617 /*
618  * Macros for use in the main dissector routines for an SMB.
619  */
620
621 #define WORD_COUNT      \
622         /* Word Count */                                \
623         wc = tvb_get_guint8(tvb, offset);               \
624         proto_tree_add_uint(tree, hf_smb_word_count,    \
625                 tvb, offset, 1, wc);                    \
626         offset += 1;                                    \
627         if(wc==0) goto bytecount;
628
629 #define BYTE_COUNT      \
630         bytecount:                                      \
631         bc = tvb_get_letohs(tvb, offset);               \
632         proto_tree_add_uint(tree, hf_smb_byte_count,    \
633                         tvb, offset, 2, bc);            \
634         offset += 2;                                    \
635         if(bc==0) goto endofcommand;
636
637 #define CHECK_BYTE_COUNT(len)   \
638         if (bc < len) goto endofcommand;
639
640 #define COUNT_BYTES(len)   {\
641         int tmp;            \
642         tmp=len;            \
643         offset += tmp;      \
644         bc -= tmp;          \
645         }
646
647 #define END_OF_SMB      \
648         if (bc != 0) { \
649                 proto_tree_add_text(tree, tvb, offset, bc, \
650                     "Extra byte parameters");           \
651                 offset += bc;                           \
652         }                                               \
653         endofcommand:
654
655 /*
656  * Macros for use in routines called by them.
657  */
658 #define CHECK_BYTE_COUNT_SUBR(len)      \
659         if (*bcp < len) {               \
660                 *trunc = TRUE;          \
661                 return offset;          \
662         }
663
664 #define CHECK_STRING_SUBR(fn)   \
665         if (fn == NULL) {       \
666                 *trunc = TRUE;  \
667                 return offset;  \
668         }
669
670 #define COUNT_BYTES_SUBR(len)   \
671         offset += len;          \
672         *bcp -= len;
673
674 /*
675  * Macros for use when dissecting transaction parameters and data
676  */
677 #define CHECK_BYTE_COUNT_TRANS(len)     \
678         if (bc < len) return offset;
679
680 #define CHECK_STRING_TRANS(fn)  \
681         if (fn == NULL) return offset;
682
683 #define COUNT_BYTES_TRANS(len)  \
684         offset += len;          \
685         bc -= len;
686
687 /*
688  * Macros for use in subrroutines dissecting transaction parameters or data
689  */
690 #define CHECK_BYTE_COUNT_TRANS_SUBR(len)        \
691         if (*bcp < len) return offset;
692
693 #define CHECK_STRING_TRANS_SUBR(fn)     \
694         if (fn == NULL) return offset;
695
696 #define COUNT_BYTES_TRANS_SUBR(len)     \
697         offset += len;                  \
698         *bcp -= len;
699
700
701 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
702    These are needed by the reassembly of SMB Transaction payload and DCERPC over SMB
703    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
704 static gboolean smb_trans_reassembly = FALSE;
705 gboolean smb_dcerpc_reassembly = FALSE;
706
707 static GHashTable *smb_trans_fragment_table = NULL;
708 GHashTable *dcerpc_fragment_table = NULL;
709
710 static void
711 smb_trans_reassembly_init(void)
712 {
713         fragment_table_init(&smb_trans_fragment_table);
714 }
715 static void
716 smb_dcerpc_reassembly_init(void)
717 {
718         fragment_table_init(&dcerpc_fragment_table);
719 }
720
721
722 static fragment_data *
723 smb_trans_defragment(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
724                      int offset, int count, int pos, int totlen)
725 {
726         fragment_data *fd_head=NULL;
727         smb_info_t *si;
728         int more_frags;
729
730         more_frags=totlen>(pos+count);
731
732         si = (smb_info_t *)pinfo->private_data;
733         if (si->sip == NULL) {
734                 /*
735                  * We don't have the frame number of the request.
736                  *
737                  * XXX - is there truly nothing we can do here?
738                  * Can we not separately keep track of the original
739                  * transaction and its continuations, as we did
740                  * at one time?
741                  *
742                  * It is probably not much point in even trying to do something here
743                  * if we have never seen the initial request. Without the initial 
744                  * request we probably miss all parameters and the begining of data
745                  * so we cant even call a subdissector since we can not determine
746                  * which type of transaction call this is.
747                  */
748                 return NULL;
749         }
750
751         if(!pinfo->fd->flags.visited){
752                 fd_head = fragment_add(tvb, offset, pinfo,
753                                        si->sip->frame_req, smb_trans_fragment_table,
754                                        pos, count, more_frags);
755         } else {
756                 fd_head = fragment_get(pinfo, si->sip->frame_req, smb_trans_fragment_table);
757         }
758
759         /* we only show the defragmented packet for the first fragment,
760            or else we might end up with dissecting one HUGE transaction PDU
761            a LOT of times. (first fragment is the only one containing the setup
762            bytes)
763            I have seen ONE Transaction PDU that is ~60kb, spanning many Transaction 
764            SMBs. Takes a LOT of time dissecting and is not fun.
765         */
766         if( (pos==0) && fd_head && fd_head->flags&FD_DEFRAGMENTED){
767                 return fd_head;
768         } else {
769                 return NULL;
770         }
771 }
772                 
773
774
775
776
777 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
778    These variables and functions are used to match
779    responses with calls
780    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
781 /*
782  * The information we need to save about a request in order to show the
783  * frame number of the request in the dissection of the reply.
784  */
785 typedef struct  {
786         guint32 frame;
787         guint32 pid_mid;
788 } smb_saved_info_key_t;
789
790 static GMemChunk *smb_saved_info_key_chunk = NULL;
791 static GMemChunk *smb_saved_info_chunk = NULL;
792 static int smb_saved_info_init_count = 200;
793
794 /* unmatched smb_saved_info structures.
795    For unmatched smb_saved_info structures we store the smb_saved_info
796    structure using the MID and the PID as the key.
797
798    Oh, yes, the key is really a pointer, but we use it as if it was an integer.
799    Ugly, yes. Not portable to DEC-20 Yes. But it saves a few bytes.
800    The key is the PID in the upper 16 bits and the MID in the lower 16 bits.
801 */
802 static gint
803 smb_saved_info_equal_unmatched(gconstpointer k1, gconstpointer k2)
804 {
805         register guint32 key1 = (guint32)k1;
806         register guint32 key2 = (guint32)k2;
807         return key1==key2;
808 }
809 static guint
810 smb_saved_info_hash_unmatched(gconstpointer k)
811 {
812         register guint32 key = (guint32)k;
813         return key;
814 }
815
816 /* matched smb_saved_info structures.
817    For matched smb_saved_info structures we store the smb_saved_info
818    structure twice in the table using the frame number, and a combination
819    of the MID and the PID, as the key.
820    The frame number is guaranteed to be unique but if ever someone makes
821    some change that will renumber the frames in a capture we are in BIG trouble.
822    This is not likely though since that would break (among other things) all the
823    reassembly routines as well.
824
825    We also need the MID as there may be more than one SMB request or reply
826    in a single frame, and we also need the PID as there may be more than
827    one outstanding request with the same MID and different PIDs.
828 */
829 static gint
830 smb_saved_info_equal_matched(gconstpointer k1, gconstpointer k2)
831 {
832         const smb_saved_info_key_t *key1 = k1;
833         const smb_saved_info_key_t *key2 = k2;
834         return key1->frame == key2->frame && key1->pid_mid == key2->pid_mid;
835 }
836 static guint
837 smb_saved_info_hash_matched(gconstpointer k)
838 {
839         const smb_saved_info_key_t *key = k;
840         return key->frame + key->pid_mid;
841 }
842
843 /*
844  * The information we need to save about an NT Transaction request in order
845  * to dissect the reply.
846  */
847 typedef struct {
848         int subcmd;
849 } smb_nt_transact_info_t;
850
851 static GMemChunk *smb_nt_transact_info_chunk = NULL;
852 static int smb_nt_transact_info_init_count = 200;
853
854 /*
855  * The information we need to save about a Transaction2 request in order
856  * to dissect the reply.
857  */
858 typedef struct {
859         int subcmd;
860         int info_level;
861 } smb_transact2_info_t;
862
863 static GMemChunk *smb_transact2_info_chunk = NULL;
864 static int smb_transact2_info_init_count = 200;
865
866 /*
867  * The information we need to save about a Transaction request in order
868  * to dissect the reply; this includes information for use by the
869  * Remote API dissector.
870  */
871 static GMemChunk *smb_transact_info_chunk = NULL;
872 static int smb_transact_info_init_count = 200;
873
874 static GMemChunk *conv_tables_chunk = NULL;
875 static GSList *conv_tables = NULL;
876 static int conv_tables_count = 10;
877
878
879 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
880    End of request/response matching functions
881    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
882
883 static const value_string buffer_format_vals[] = {
884         {1,     "Data Block"},
885         {2,     "Dialect"},
886         {3,     "Pathname"},
887         {4,     "ASCII"},
888         {5,     "Variable Block"},
889         {0,     NULL}
890 };
891
892 /*
893  * UTIME - this is *almost* like a UNIX time stamp, except that it's
894  * in seconds since January 1, 1970, 00:00:00 *local* time, not since
895  * January 1, 1970, 00:00:00 GMT.
896  *
897  * This means we have to do some extra work to convert it.  This code is
898  * based on the Samba code:
899  *
900  *      Unix SMB/Netbios implementation.
901  *      Version 1.9.
902  *      time handling functions
903  *      Copyright (C) Andrew Tridgell 1992-1998
904  */
905
906 /*
907  * Yield the difference between *A and *B, in seconds, ignoring leap
908  * seconds.
909  */
910 #define TM_YEAR_BASE 1900
911
912 static int
913 tm_diff(struct tm *a, struct tm *b)
914 {
915         int ay = a->tm_year + (TM_YEAR_BASE - 1);
916         int by = b->tm_year + (TM_YEAR_BASE - 1);
917         int intervening_leap_days =
918             (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
919         int years = ay - by;
920         int days =
921             365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
922         int hours = 24*days + (a->tm_hour - b->tm_hour);
923         int minutes = 60*hours + (a->tm_min - b->tm_min);
924         int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
925
926         return seconds;
927 }
928
929 /*
930  * Return the UTC offset in seconds west of UTC, or 0 if it cannot be
931  * determined.
932  */
933 static int
934 TimeZone(time_t t)
935 {
936         struct tm *tm = gmtime(&t);
937         struct tm tm_utc;
938
939         if (tm == NULL)
940                 return 0;
941         tm_utc = *tm;
942         tm = localtime(&t);
943         if (tm == NULL)
944                 return 0;
945         return tm_diff(&tm_utc,tm);
946 }
947
948 /*
949  * Return the same value as TimeZone, but it should be more efficient.
950  *
951  * We keep a table of DST offsets to prevent calling localtime() on each 
952  * call of this function. This saves a LOT of time on many unixes.
953  *
954  * Updated by Paul Eggert <eggert@twinsun.com>
955  */
956 #ifndef CHAR_BIT
957 #define CHAR_BIT 8
958 #endif
959
960 #ifndef TIME_T_MIN
961 #define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \
962                     : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
963 #endif
964 #ifndef TIME_T_MAX
965 #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
966 #endif
967
968 static int
969 TimeZoneFaster(time_t t)
970 {
971         static struct dst_table {time_t start,end; int zone;} *tdt;
972         static struct dst_table *dst_table = NULL;
973         static int table_size = 0;
974         int i;
975         int zone = 0;
976
977         if (t == 0)
978                 t = time(NULL);
979
980         /* Tunis has a 8 day DST region, we need to be careful ... */
981 #define MAX_DST_WIDTH (365*24*60*60)
982 #define MAX_DST_SKIP (7*24*60*60)
983
984         for (i = 0; i < table_size; i++) {
985                 if (t >= dst_table[i].start && t <= dst_table[i].end)
986                         break;
987         }
988
989         if (i < table_size) {
990                 zone = dst_table[i].zone;
991         } else {
992                 time_t low,high;
993
994                 zone = TimeZone(t);
995                 if (dst_table == NULL)
996                         tdt = g_malloc(sizeof(dst_table[0])*(i+1));
997                 else
998                         tdt = g_realloc(dst_table, sizeof(dst_table[0])*(i+1));
999                 if (tdt == NULL) {
1000                         if (dst_table)
1001                                 free(dst_table);
1002                         table_size = 0;
1003                 } else {
1004                         dst_table = tdt;
1005                         table_size++;
1006     
1007                         dst_table[i].zone = zone; 
1008                         dst_table[i].start = dst_table[i].end = t;
1009     
1010                         /* no entry will cover more than 6 months */
1011                         low = t - MAX_DST_WIDTH/2;
1012                         if (t < low)
1013                                 low = TIME_T_MIN;
1014       
1015                         high = t + MAX_DST_WIDTH/2;
1016                         if (high < t)
1017                                 high = TIME_T_MAX;
1018       
1019                         /*
1020                          * Widen the new entry using two bisection searches.
1021                          */
1022                         while (low+60*60 < dst_table[i].start) {
1023                                 if (dst_table[i].start - low > MAX_DST_SKIP*2)
1024                                         t = dst_table[i].start - MAX_DST_SKIP;
1025                                 else
1026                                         t = low + (dst_table[i].start-low)/2;
1027                                 if (TimeZone(t) == zone)
1028                                         dst_table[i].start = t;
1029                                 else
1030                                         low = t;
1031                         }
1032
1033                         while (high-60*60 > dst_table[i].end) {
1034                                 if (high - dst_table[i].end > MAX_DST_SKIP*2)
1035                                         t = dst_table[i].end + MAX_DST_SKIP;
1036                                 else
1037                                         t = high - (high-dst_table[i].end)/2;
1038                                 if (TimeZone(t) == zone)
1039                                         dst_table[i].end = t;
1040                                 else
1041                                         high = t;
1042                         }
1043                 }
1044         }
1045         return zone;
1046 }
1047
1048 /*
1049  * Return the UTC offset in seconds west of UTC, adjusted for extra time
1050  * offset, for a local time value.  If ut = lt + LocTimeDiff(lt), then
1051  * lt = ut - TimeDiff(ut), but the converse does not necessarily hold near
1052  * daylight savings transitions because some local times are ambiguous.
1053  * LocTimeDiff(t) equals TimeDiff(t) except near daylight savings transitions.
1054  */
1055 static int
1056 LocTimeDiff(time_t lt)
1057 {
1058         int d = TimeZoneFaster(lt);
1059         time_t t = lt + d;
1060
1061         /* if overflow occurred, ignore all the adjustments so far */
1062         if (((t < lt) ^ (d < 0)))
1063                 t = lt;
1064
1065         /*
1066          * Now t should be close enough to the true UTC to yield the
1067          * right answer.
1068          */
1069         return TimeZoneFaster(t);
1070 }
1071
1072 static int
1073 dissect_smb_UTIME(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int hf_date)
1074 {
1075         guint32 timeval;
1076         nstime_t ts;
1077  
1078         timeval = tvb_get_letohl(tvb, offset);
1079         if (timeval == 0xffffffff) {
1080                 proto_tree_add_text(tree, tvb, offset, 4,
1081                     "%s: No time specified (0xffffffff)",
1082                     proto_registrar_get_name(hf_date));
1083                 offset += 4;
1084                 return offset;
1085         }
1086
1087         /*
1088          * We add the local time offset.
1089          */
1090         ts.secs = timeval + LocTimeDiff(timeval);
1091         ts.nsecs = 0;
1092
1093         proto_tree_add_time(tree, hf_date, tvb, offset, 4, &ts);
1094         offset += 4;
1095  
1096         return offset;
1097 }
1098
1099 #define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
1100
1101 /*
1102  * Translate an 8-byte FILETIME value, given as the upper and lower 32 bits,
1103  * to an "nstime_t".
1104  * A FILETIME is a 64-bit integer, giving the time since Jan 1, 1601,
1105  * midnight "UTC", in 100ns units.
1106  * Return TRUE if the conversion succeeds, FALSE otherwise.
1107  *
1108  * According to the Samba code, it appears to be kludge-GMT (at least for
1109  * file listings). This means it's the GMT you get by taking a local time
1110  * and adding the server time zone offset.  This is NOT the same as GMT in
1111  * some cases.   However, we don't know the server time zone, so we don't
1112  * do that adjustment.
1113  *
1114  * This code is based on the Samba code:
1115  *
1116  *      Unix SMB/Netbios implementation.
1117  *      Version 1.9.
1118  *      time handling functions
1119  *      Copyright (C) Andrew Tridgell 1992-1998
1120  */
1121 static gboolean
1122 nt_time_to_nstime(guint32 filetime_high, guint32 filetime_low, nstime_t *tv)
1123 {
1124         double d;
1125         /* The next two lines are a fix needed for the 
1126             broken SCO compiler. JRA. */
1127         time_t l_time_min = TIME_T_MIN;
1128         time_t l_time_max = TIME_T_MAX;
1129
1130         if (filetime_high == 0)
1131                 return FALSE;
1132
1133         /*
1134          * Get the time as a double, in seconds and fractional seconds.
1135          */
1136         d = ((double)filetime_high)*4.0*(double)(1<<30);
1137         d += filetime_low;
1138         d *= 1.0e-7;
1139  
1140         /* Now adjust by 369 years, to make the seconds since 1970. */
1141         d -= TIME_FIXUP_CONSTANT;
1142
1143         if (!(l_time_min <= d && d <= l_time_max))
1144                 return FALSE;
1145
1146         /*
1147          * Get the time as seconds and nanoseconds.
1148          */
1149         tv->secs = d;
1150         tv->nsecs = (d - tv->secs)*1000000000;
1151
1152         return TRUE;
1153 }
1154
1155 int
1156 dissect_smb_64bit_time(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int hf_date)
1157 {
1158         guint32 filetime_high, filetime_low;
1159         nstime_t ts;
1160
1161         if (tree) {
1162                 filetime_low = tvb_get_letohl(tvb, offset);
1163                 filetime_high = tvb_get_letohl(tvb, offset + 4);
1164                 if (filetime_low == 0 && filetime_high == 0) {
1165                         proto_tree_add_text(tree, tvb, offset, 8,
1166                             "%s: No time specified (0)",
1167                             proto_registrar_get_name(hf_date));
1168                 } else if(filetime_low==0 && filetime_high==0x80000000){
1169                         proto_tree_add_text(tree, tvb, offset, 8,
1170                             "%s: Infinity (absolute time)",
1171                             proto_registrar_get_name(hf_date));
1172                 } else if(filetime_low==0xffffffff && filetime_high==0x7fffffff){
1173                         proto_tree_add_text(tree, tvb, offset, 8,
1174                             "%s: Infinity (relative time)",
1175                             proto_registrar_get_name(hf_date));
1176                 } else {                        
1177                         if (nt_time_to_nstime(filetime_high, filetime_low, &ts)) {
1178                                 proto_tree_add_time(tree, hf_date, tvb,
1179                                     offset, 8, &ts);
1180                         } else {
1181                                 proto_tree_add_text(tree, tvb, offset, 8,
1182                                     "%s: Time can't be converted",
1183                                     proto_registrar_get_name(hf_date));
1184                         }
1185                 }
1186         }
1187
1188         offset += 8;
1189         return offset;
1190 }
1191
1192 static int
1193 dissect_smb_datetime(tvbuff_t *tvb, packet_info *pinfo,
1194     proto_tree *parent_tree, int offset, int hf_date, int hf_dos_date,
1195     int hf_dos_time, gboolean time_first)
1196 {
1197         guint16 dos_time, dos_date;
1198         proto_item *item = NULL;
1199         proto_tree *tree = NULL;
1200         struct tm tm;
1201         time_t t;
1202         static const int mday_noleap[12] = {
1203                 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1204         };
1205         static const int mday_leap[12] = {
1206                 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
1207         };
1208 #define ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
1209         nstime_t tv;
1210
1211         if (time_first) {
1212                 dos_time = tvb_get_letohs(tvb, offset);
1213                 dos_date = tvb_get_letohs(tvb, offset+2);
1214         } else {
1215                 dos_date = tvb_get_letohs(tvb, offset);
1216                 dos_time = tvb_get_letohs(tvb, offset+2);
1217         }
1218
1219         if ((dos_time == 0xffff && dos_time == 0xffff) ||
1220             (dos_time == 0 && dos_time == 0)) {
1221                 /*
1222                  * No date/time specified.
1223                  */
1224                 if(parent_tree){
1225                         proto_tree_add_text(parent_tree, tvb, offset, 4,
1226                             "%s: No time specified (0x%08x)",
1227                             proto_registrar_get_name(hf_date),
1228                             (dos_date << 16) | dos_time);
1229                 }
1230                 offset += 4;
1231                 return offset;
1232         }
1233
1234         tm.tm_sec = (dos_time&0x1f)*2;
1235         tm.tm_min = (dos_time>>5)&0x3f;
1236         tm.tm_hour = (dos_time>>11)&0x1f;
1237         tm.tm_mday = dos_date&0x1f;
1238         tm.tm_mon = ((dos_date>>5)&0x0f) - 1;
1239         tm.tm_year = ((dos_date>>9)&0x7f) + 1980 - 1900;
1240         tm.tm_isdst = -1;
1241
1242         /*
1243          * Do some sanity checks before calling "mktime()";
1244          * "mktime()" doesn't do them, it "normalizes" out-of-range
1245          * values.
1246          */
1247         if (tm.tm_sec > 59 || tm.tm_min > 59 || tm.tm_hour > 23 ||
1248            tm.tm_mon < 0 || tm.tm_mon > 11 ||
1249            (ISLEAP(tm.tm_year + 1900) ?
1250              tm.tm_mday > mday_leap[tm.tm_mon] :
1251              tm.tm_mday > mday_noleap[tm.tm_mon]) ||
1252              (t = mktime(&tm)) == -1) {
1253                 /*
1254                  * Invalid date/time.
1255                  */
1256                 if (parent_tree) {
1257                         item = proto_tree_add_text(parent_tree, tvb, offset, 4,
1258                             "%s: Invalid time",
1259                             proto_registrar_get_name(hf_date));
1260                         tree = proto_item_add_subtree(item, ett_smb_time_date);
1261                         if (time_first) {
1262                                 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);
1263                                 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);
1264                         } else {
1265                                 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);
1266                                 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);
1267                         }
1268                 }
1269                 offset += 4;
1270                 return offset;
1271         }
1272
1273         tv.secs = t;
1274         tv.nsecs = 0;
1275
1276         if(parent_tree){
1277                 item = proto_tree_add_time(parent_tree, hf_date, tvb, offset, 4, &tv);
1278                 tree = proto_item_add_subtree(item, ett_smb_time_date);
1279                 if (time_first) {
1280                         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);
1281                         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);
1282                 } else {
1283                         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);
1284                         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);
1285                 }
1286         }
1287
1288         offset += 4;
1289
1290         return offset;
1291 }
1292
1293
1294 static const value_string da_access_vals[] = {
1295         { 0,            "Open for reading"},
1296         { 1,            "Open for writing"},
1297         { 2,            "Open for reading and writing"},
1298         { 3,            "Open for execute"},
1299         {0, NULL}
1300 };
1301 static const value_string da_sharing_vals[] = {
1302         { 0,            "Compatibility mode"},
1303         { 1,            "Deny read/write/execute (exclusive)"},
1304         { 2,            "Deny write"},
1305         { 3,            "Deny read/execute"},
1306         { 4,            "Deny none"},
1307         {0, NULL}
1308 };
1309 static const value_string da_locality_vals[] = {
1310         { 0,            "Locality of reference unknown"},
1311         { 1,            "Mainly sequential access"},
1312         { 2,            "Mainly random access"},
1313         { 3,            "Random access with some locality"},
1314         {0, NULL}
1315 };
1316 static const true_false_string tfs_da_caching = {
1317         "Do not cache this file",
1318         "Caching permitted on this file"
1319 };
1320 static const true_false_string tfs_da_writetru = {
1321         "Write through enabled",
1322         "Write through disabled"
1323 };
1324 static int
1325 dissect_access(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, char *type)
1326 {
1327         guint16 mask;
1328         proto_item *item = NULL;
1329         proto_tree *tree = NULL;
1330
1331         mask = tvb_get_letohs(tvb, offset);
1332
1333         if(parent_tree){
1334                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
1335                         "%s Access: 0x%04x", type, mask);
1336                 tree = proto_item_add_subtree(item, ett_smb_desiredaccess);
1337         }
1338
1339         proto_tree_add_boolean(tree, hf_smb_access_writetru,
1340                 tvb, offset, 2, mask);
1341         proto_tree_add_boolean(tree, hf_smb_access_caching,
1342                 tvb, offset, 2, mask);
1343         proto_tree_add_uint(tree, hf_smb_access_locality,
1344                 tvb, offset, 2, mask);
1345         proto_tree_add_uint(tree, hf_smb_access_sharing,
1346                 tvb, offset, 2, mask);
1347         proto_tree_add_uint(tree, hf_smb_access_mode,
1348                 tvb, offset, 2, mask);
1349
1350         offset += 2;
1351
1352         return offset;
1353 }
1354
1355 #define FILE_ATTRIBUTE_READ_ONLY                0x00000001
1356 #define FILE_ATTRIBUTE_HIDDEN                   0x00000002
1357 #define FILE_ATTRIBUTE_SYSTEM                   0x00000004
1358 #define FILE_ATTRIBUTE_VOLUME                   0x00000008
1359 #define FILE_ATTRIBUTE_DIRECTORY                0x00000010
1360 #define FILE_ATTRIBUTE_ARCHIVE                  0x00000020
1361 #define FILE_ATTRIBUTE_DEVICE                   0x00000040
1362 #define FILE_ATTRIBUTE_NORMAL                   0x00000080
1363 #define FILE_ATTRIBUTE_TEMPORARY                0x00000100
1364 #define FILE_ATTRIBUTE_SPARSE                   0x00000200
1365 #define FILE_ATTRIBUTE_REPARSE                  0x00000400
1366 #define FILE_ATTRIBUTE_COMPRESSED               0x00000800
1367 #define FILE_ATTRIBUTE_OFFLINE                  0x00001000
1368 #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED      0x00002000
1369 #define FILE_ATTRIBUTE_ENCRYPTED                0x00004000
1370
1371 /*
1372  * These are flags to be used in NT Create operations.
1373  */
1374 #define FILE_ATTRIBUTE_WRITE_THROUGH            0x80000000
1375 #define FILE_ATTRIBUTE_NO_BUFFERING             0x20000000
1376 #define FILE_ATTRIBUTE_RANDOM_ACCESS            0x10000000
1377 #define FILE_ATTRIBUTE_SEQUENTIAL_SCAN          0x08000000
1378 #define FILE_ATTRIBUTE_DELETE_ON_CLOSE          0x04000000
1379 #define FILE_ATTRIBUTE_BACKUP_SEMANTICS         0x02000000
1380 #define FILE_ATTRIBUTE_POSIX_SEMANTICS          0x01000000
1381
1382 static const true_false_string tfs_file_attribute_write_through = {
1383         "This object requires WRITE THROUGH",
1384         "This object does NOT require write through",
1385 };
1386 static const true_false_string tfs_file_attribute_no_buffering = {
1387         "This object requires NO BUFFERING",
1388         "This object can be buffered",
1389 };
1390 static const true_false_string tfs_file_attribute_random_access = {
1391         "This object will be RANDOM ACCESSed",
1392         "Random access is NOT requested",
1393 };
1394 static const true_false_string tfs_file_attribute_sequential_scan = {
1395         "This object is optimized for SEQUENTIAL SCAN",
1396         "This object is NOT optimized for sequential scan",
1397 };
1398 static const true_false_string tfs_file_attribute_delete_on_close = {
1399         "This object will be DELETED ON CLOSE",
1400         "This object will not be deleted on close",
1401 };
1402 static const true_false_string tfs_file_attribute_backup_semantics = {
1403         "This object supports BACKUP SEMANTICS",
1404         "This object does NOT support backup semantics",
1405 };
1406 static const true_false_string tfs_file_attribute_posix_semantics = {
1407         "This object supports POSIX SEMANTICS",
1408         "This object does NOT support POSIX semantics",
1409 };
1410 static const true_false_string tfs_file_attribute_read_only = {
1411         "This file is READ ONLY",
1412         "This file is NOT read only",
1413 };
1414 static const true_false_string tfs_file_attribute_hidden = {
1415         "This is a HIDDEN file",
1416         "This is NOT a hidden file"
1417 };
1418 static const true_false_string tfs_file_attribute_system = {
1419         "This is a SYSTEM file",
1420         "This is NOT a system file"
1421 };
1422 static const true_false_string tfs_file_attribute_volume = {
1423         "This is a VOLUME ID",
1424         "This is NOT a volume ID"
1425 };
1426 static const true_false_string tfs_file_attribute_directory = {
1427         "This is a DIRECTORY",
1428         "This is NOT a directory"
1429 };
1430 static const true_false_string tfs_file_attribute_archive = {
1431         "This is an ARCHIVE file",
1432         "This is NOT an archive file"
1433 };
1434 static const true_false_string tfs_file_attribute_device = {
1435         "This is a DEVICE",
1436         "This is NOT a device"
1437 };
1438 static const true_false_string tfs_file_attribute_normal = {
1439         "This file is an ordinary file",
1440         "This file has some attribute set"
1441 };
1442 static const true_false_string tfs_file_attribute_temporary = {
1443         "This is a TEMPORARY file",
1444         "This is NOT a temporary file"
1445 };
1446 static const true_false_string tfs_file_attribute_sparse = {
1447         "This is a SPARSE file",
1448         "This is NOT a sparse file"
1449 };
1450 static const true_false_string tfs_file_attribute_reparse = {
1451         "This file has an associated REPARSE POINT",
1452         "This file does NOT have an associated reparse point"
1453 };
1454 static const true_false_string tfs_file_attribute_compressed = {
1455         "This is a COMPRESSED file",
1456         "This is NOT a compressed file"
1457 };
1458 static const true_false_string tfs_file_attribute_offline = {
1459         "This file is OFFLINE",
1460         "This file is NOT offline"
1461 };
1462 static const true_false_string tfs_file_attribute_not_content_indexed = {
1463         "This file MAY NOT be indexed by the CONTENT INDEXING service",
1464         "This file MAY be indexed by the content indexing service"
1465 };
1466 static const true_false_string tfs_file_attribute_encrypted = {
1467         "This is an ENCRYPTED file",
1468         "This is NOT an encrypted file"
1469 };
1470
1471 static int
1472 dissect_file_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
1473 {
1474         guint16 mask;
1475         proto_item *item = NULL;
1476         proto_tree *tree = NULL;
1477
1478         mask = tvb_get_letohs(tvb, offset);
1479
1480         if(parent_tree){
1481                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
1482                         "File Attributes: 0x%04x", mask);
1483                 tree = proto_item_add_subtree(item, ett_smb_file_attributes);
1484         }
1485         proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_16bit,
1486                 tvb, offset, 2, mask);
1487         proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_16bit,
1488                 tvb, offset, 2, mask);
1489         proto_tree_add_boolean(tree, hf_smb_file_attr_system_16bit,
1490                 tvb, offset, 2, mask);
1491         proto_tree_add_boolean(tree, hf_smb_file_attr_volume_16bit,
1492                 tvb, offset, 2, mask);
1493         proto_tree_add_boolean(tree, hf_smb_file_attr_directory_16bit,
1494                 tvb, offset, 2, mask);
1495         proto_tree_add_boolean(tree, hf_smb_file_attr_archive_16bit,
1496                 tvb, offset, 2, mask);
1497
1498         offset += 2;
1499
1500         return offset;
1501 }
1502
1503 /* 3.11 */
1504 static int
1505 dissect_file_ext_attr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
1506 {
1507         guint32 mask;
1508         proto_item *item = NULL;
1509         proto_tree *tree = NULL;
1510
1511         mask = tvb_get_letohl(tvb, offset);
1512
1513         if(parent_tree){
1514                 item = proto_tree_add_text(parent_tree, tvb, offset, 4,
1515                         "File Attributes: 0x%08x", mask);
1516                 tree = proto_item_add_subtree(item, ett_smb_file_attributes);
1517         }
1518
1519         /*
1520          * XXX - Network Monitor disagrees on some of the
1521          * bits, e.g. the bits above temporary are "atomic write"
1522          * and "transaction write", and it says nothing about the
1523          * bits above that.
1524          *
1525          * Does the Win32 API documentation, or the NT Native API book,
1526          * suggest anything?
1527          */
1528         proto_tree_add_boolean(tree, hf_smb_file_eattr_write_through,
1529                 tvb, offset, 4, mask);
1530         proto_tree_add_boolean(tree, hf_smb_file_eattr_no_buffering,
1531                 tvb, offset, 4, mask);
1532         proto_tree_add_boolean(tree, hf_smb_file_eattr_random_access,
1533                 tvb, offset, 4, mask);
1534         proto_tree_add_boolean(tree, hf_smb_file_eattr_sequential_scan,
1535                 tvb, offset, 4, mask);
1536         proto_tree_add_boolean(tree, hf_smb_file_eattr_delete_on_close,
1537                 tvb, offset, 4, mask);
1538         proto_tree_add_boolean(tree, hf_smb_file_eattr_backup_semantics,
1539                 tvb, offset, 4, mask);
1540         proto_tree_add_boolean(tree, hf_smb_file_eattr_posix_semantics,
1541                 tvb, offset, 4, mask);
1542         proto_tree_add_boolean(tree, hf_smb_file_eattr_encrypted,
1543                 tvb, offset, 4, mask);
1544         proto_tree_add_boolean(tree, hf_smb_file_eattr_not_content_indexed,
1545                 tvb, offset, 4, mask);
1546         proto_tree_add_boolean(tree, hf_smb_file_eattr_offline,
1547                 tvb, offset, 4, mask);
1548         proto_tree_add_boolean(tree, hf_smb_file_eattr_compressed,
1549                 tvb, offset, 4, mask);
1550         proto_tree_add_boolean(tree, hf_smb_file_eattr_reparse,
1551                 tvb, offset, 4, mask);
1552         proto_tree_add_boolean(tree, hf_smb_file_eattr_sparse,
1553                 tvb, offset, 4, mask);
1554         proto_tree_add_boolean(tree, hf_smb_file_eattr_temporary,
1555                 tvb, offset, 4, mask);
1556         proto_tree_add_boolean(tree, hf_smb_file_eattr_normal,
1557                 tvb, offset, 4, mask);
1558         proto_tree_add_boolean(tree, hf_smb_file_eattr_device,
1559                 tvb, offset, 4, mask);
1560         proto_tree_add_boolean(tree, hf_smb_file_eattr_archive,
1561                 tvb, offset, 4, mask);
1562         proto_tree_add_boolean(tree, hf_smb_file_eattr_directory,
1563                 tvb, offset, 4, mask);
1564         proto_tree_add_boolean(tree, hf_smb_file_eattr_volume,
1565                 tvb, offset, 4, mask);
1566         proto_tree_add_boolean(tree, hf_smb_file_eattr_system,
1567                 tvb, offset, 4, mask);
1568         proto_tree_add_boolean(tree, hf_smb_file_eattr_hidden,
1569                 tvb, offset, 4, mask);
1570         proto_tree_add_boolean(tree, hf_smb_file_eattr_read_only,
1571                 tvb, offset, 4, mask);
1572
1573         offset += 4;
1574
1575         return offset;
1576 }
1577
1578 static int
1579 dissect_dir_info_file_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
1580 {
1581         guint8 mask;
1582         proto_item *item = NULL;
1583         proto_tree *tree = NULL;
1584
1585         mask = tvb_get_guint8(tvb, offset);
1586
1587         if(parent_tree){
1588                 item = proto_tree_add_text(parent_tree, tvb, offset, 1,
1589                         "File Attributes: 0x%02x", mask);
1590                 tree = proto_item_add_subtree(item, ett_smb_file_attributes);
1591         }
1592         proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_8bit,
1593                 tvb, offset, 1, mask);
1594         proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_8bit,
1595                 tvb, offset, 1, mask);
1596         proto_tree_add_boolean(tree, hf_smb_file_attr_system_8bit,
1597                 tvb, offset, 1, mask);
1598         proto_tree_add_boolean(tree, hf_smb_file_attr_volume_8bit,
1599                 tvb, offset, 1, mask);
1600         proto_tree_add_boolean(tree, hf_smb_file_attr_directory_8bit,
1601                 tvb, offset, 1, mask);
1602         proto_tree_add_boolean(tree, hf_smb_file_attr_archive_8bit,
1603                 tvb, offset, 1, mask);
1604
1605         offset += 1;
1606
1607         return offset;
1608 }
1609
1610 static const true_false_string tfs_search_attribute_read_only = {
1611         "Include READ ONLY files in search results",
1612         "Do NOT include read only files in search results",
1613 };
1614 static const true_false_string tfs_search_attribute_hidden = {
1615         "Include HIDDEN files in search results",
1616         "Do NOT include hidden files in search results"
1617 };
1618 static const true_false_string tfs_search_attribute_system = {
1619         "Include SYSTEM files in search results",
1620         "Do NOT include system files in search results"
1621 };
1622 static const true_false_string tfs_search_attribute_volume = {
1623         "Include VOLUME IDs in search results",
1624         "Do NOT include volume IDs in search results"
1625 };
1626 static const true_false_string tfs_search_attribute_directory = {
1627         "Include DIRECTORIES in search results",
1628         "Do NOT include directories in search results"
1629 };
1630 static const true_false_string tfs_search_attribute_archive = {
1631         "Include ARCHIVE files in search results",
1632         "Do NOT include archive files in search results"
1633 };
1634
1635 static int
1636 dissect_search_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
1637 {
1638         guint16 mask;
1639         proto_item *item = NULL;
1640         proto_tree *tree = NULL;
1641
1642         mask = tvb_get_letohs(tvb, offset);
1643
1644         if(parent_tree){
1645                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
1646                         "Search Attributes: 0x%04x", mask);
1647                 tree = proto_item_add_subtree(item, ett_smb_search);
1648         }
1649
1650         proto_tree_add_boolean(tree, hf_smb_search_attribute_read_only,
1651                 tvb, offset, 2, mask);
1652         proto_tree_add_boolean(tree, hf_smb_search_attribute_hidden,
1653                 tvb, offset, 2, mask);
1654         proto_tree_add_boolean(tree, hf_smb_search_attribute_system,
1655                 tvb, offset, 2, mask);  
1656         proto_tree_add_boolean(tree, hf_smb_search_attribute_volume,
1657                 tvb, offset, 2, mask);
1658         proto_tree_add_boolean(tree, hf_smb_search_attribute_directory,
1659                 tvb, offset, 2, mask);
1660         proto_tree_add_boolean(tree, hf_smb_search_attribute_archive,
1661                 tvb, offset, 2, mask);
1662
1663         offset += 2;
1664         return offset;
1665 }
1666
1667 #if 0
1668 /*
1669  * XXX - this isn't used.
1670  * Is this used for anything?  NT Create AndX doesn't use it.
1671  * Is there some 16-bit attribute field with more bits than Read Only,
1672  * Hidden, System, Volume ID, Directory, and Archive?
1673  */
1674 static int
1675 dissect_extended_file_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
1676 {
1677         guint32 mask;
1678         proto_item *item = NULL;
1679         proto_tree *tree = NULL;
1680
1681         mask = tvb_get_letohl(tvb, offset);
1682
1683         if(parent_tree){
1684                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
1685                         "File Attributes: 0x%08x", mask);
1686                 tree = proto_item_add_subtree(item, ett_smb_file_attributes);
1687         }
1688         proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_16bit,
1689                 tvb, offset, 2, mask);
1690         proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_16bit,
1691                 tvb, offset, 2, mask);
1692         proto_tree_add_boolean(tree, hf_smb_file_attr_system_16bit,
1693                 tvb, offset, 2, mask);
1694         proto_tree_add_boolean(tree, hf_smb_file_attr_volume_16bit,
1695                 tvb, offset, 2, mask);
1696         proto_tree_add_boolean(tree, hf_smb_file_attr_directory_16bit,
1697                 tvb, offset, 2, mask);
1698         proto_tree_add_boolean(tree, hf_smb_file_attr_archive_16bit,
1699                 tvb, offset, 2, mask);
1700         proto_tree_add_boolean(tree, hf_smb_file_attr_device,
1701                 tvb, offset, 2, mask);
1702         proto_tree_add_boolean(tree, hf_smb_file_attr_normal,
1703                 tvb, offset, 2, mask);
1704         proto_tree_add_boolean(tree, hf_smb_file_attr_temporary,
1705                 tvb, offset, 2, mask);
1706         proto_tree_add_boolean(tree, hf_smb_file_attr_sparse,
1707                 tvb, offset, 2, mask);
1708         proto_tree_add_boolean(tree, hf_smb_file_attr_reparse,
1709                 tvb, offset, 2, mask);
1710         proto_tree_add_boolean(tree, hf_smb_file_attr_compressed,
1711                 tvb, offset, 2, mask);
1712         proto_tree_add_boolean(tree, hf_smb_file_attr_offline,
1713                 tvb, offset, 2, mask);
1714         proto_tree_add_boolean(tree, hf_smb_file_attr_not_content_indexed,
1715                 tvb, offset, 2, mask);
1716         proto_tree_add_boolean(tree, hf_smb_file_attr_encrypted,
1717                 tvb, offset, 2, mask);
1718
1719         offset += 2;
1720
1721         return offset;
1722 }
1723 #endif
1724
1725
1726 #define SERVER_CAP_RAW_MODE            0x00000001
1727 #define SERVER_CAP_MPX_MODE            0x00000002
1728 #define SERVER_CAP_UNICODE             0x00000004
1729 #define SERVER_CAP_LARGE_FILES         0x00000008
1730 #define SERVER_CAP_NT_SMBS             0x00000010
1731 #define SERVER_CAP_RPC_REMOTE_APIS     0x00000020
1732 #define SERVER_CAP_STATUS32            0x00000040
1733 #define SERVER_CAP_LEVEL_II_OPLOCKS    0x00000080
1734 #define SERVER_CAP_LOCK_AND_READ       0x00000100
1735 #define SERVER_CAP_NT_FIND             0x00000200
1736 #define SERVER_CAP_DFS                 0x00001000
1737 #define SERVER_CAP_INFOLEVEL_PASSTHRU  0x00002000
1738 #define SERVER_CAP_LARGE_READX         0x00004000
1739 #define SERVER_CAP_LARGE_WRITEX        0x00008000
1740 #define SERVER_CAP_UNIX                0x00800000
1741 #define SERVER_CAP_RESERVED            0x02000000
1742 #define SERVER_CAP_BULK_TRANSFER       0x20000000
1743 #define SERVER_CAP_COMPRESSED_DATA     0x40000000
1744 #define SERVER_CAP_EXTENDED_SECURITY   0x80000000
1745 static const true_false_string tfs_server_cap_raw_mode = {
1746         "Read Raw and Write Raw are supported",
1747         "Read Raw and Write Raw are not supported"
1748 };
1749 static const true_false_string tfs_server_cap_mpx_mode = {
1750         "Read Mpx and Write Mpx are supported",
1751         "Read Mpx and Write Mpx are not supported"
1752 };
1753 static const true_false_string tfs_server_cap_unicode = {
1754         "Unicode strings are supported",
1755         "Unicode strings are not supported"
1756 };
1757 static const true_false_string tfs_server_cap_large_files = {
1758         "Large files are supported",
1759         "Large files are not supported",
1760 };
1761 static const true_false_string tfs_server_cap_nt_smbs = {
1762         "NT SMBs are supported",
1763         "NT SMBs are not supported"
1764 };
1765 static const true_false_string tfs_server_cap_rpc_remote_apis = {
1766         "RPC remote APIs are supported",
1767         "RPC remote APIs are not supported"
1768 };
1769 static const true_false_string tfs_server_cap_nt_status = {
1770         "NT status codes are supported",
1771         "NT status codes are not supported"
1772 };
1773 static const true_false_string tfs_server_cap_level_ii_oplocks = {
1774         "Level 2 oplocks are supported",
1775         "Level 2 oplocks are not supported"
1776 };
1777 static const true_false_string tfs_server_cap_lock_and_read = {
1778         "Lock and Read is supported",
1779         "Lock and Read is not supported"
1780 };
1781 static const true_false_string tfs_server_cap_nt_find = {
1782         "NT Find is supported",
1783         "NT Find is not supported"
1784 };
1785 static const true_false_string tfs_server_cap_dfs = {
1786         "Dfs is supported",
1787         "Dfs is not supported"
1788 };
1789 static const true_false_string tfs_server_cap_infolevel_passthru = {
1790         "NT information level request passthrough is supported",
1791         "NT information level request passthrough is not supported"
1792 };
1793 static const true_false_string tfs_server_cap_large_readx = {
1794         "Large Read andX is supported",
1795         "Large Read andX is not supported"
1796 };
1797 static const true_false_string tfs_server_cap_large_writex = {
1798         "Large Write andX is supported",
1799         "Large Write andX is not supported"
1800 };
1801 static const true_false_string tfs_server_cap_unix = {
1802         "UNIX extensions are supported",
1803         "UNIX extensions are not supported"
1804 };
1805 static const true_false_string tfs_server_cap_reserved = {
1806         "Reserved",
1807         "Reserved"
1808 };
1809 static const true_false_string tfs_server_cap_bulk_transfer = {
1810         "Bulk Read and Bulk Write are supported",
1811         "Bulk Read and Bulk Write are not supported"
1812 };
1813 static const true_false_string tfs_server_cap_compressed_data = {
1814         "Compressed data transfer is supported",
1815         "Compressed data transfer is not supported"
1816 };
1817 static const true_false_string tfs_server_cap_extended_security = {
1818         "Extended security exchanges are supported",
1819         "Extended security exchanges are not supported"
1820 };
1821 static int
1822 dissect_negprot_capabilities(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
1823 {
1824         guint32 mask;
1825         proto_item *item = NULL;
1826         proto_tree *tree = NULL;
1827
1828         mask = tvb_get_letohl(tvb, offset);
1829
1830         if(parent_tree){
1831                 item = proto_tree_add_text(parent_tree, tvb, offset, 4, "Capabilities: 0x%08x", mask);
1832                 tree = proto_item_add_subtree(item, ett_smb_capabilities);
1833         }
1834
1835         proto_tree_add_boolean(tree, hf_smb_server_cap_raw_mode,
1836                 tvb, offset, 4, mask);
1837         proto_tree_add_boolean(tree, hf_smb_server_cap_mpx_mode,
1838                 tvb, offset, 4, mask);
1839         proto_tree_add_boolean(tree, hf_smb_server_cap_unicode,
1840                 tvb, offset, 4, mask);
1841         proto_tree_add_boolean(tree, hf_smb_server_cap_large_files,
1842                 tvb, offset, 4, mask);
1843         proto_tree_add_boolean(tree, hf_smb_server_cap_nt_smbs,
1844                 tvb, offset, 4, mask);
1845         proto_tree_add_boolean(tree, hf_smb_server_cap_rpc_remote_apis,
1846                 tvb, offset, 4, mask);
1847         proto_tree_add_boolean(tree, hf_smb_server_cap_nt_status,
1848                 tvb, offset, 4, mask);
1849         proto_tree_add_boolean(tree, hf_smb_server_cap_level_ii_oplocks,
1850                 tvb, offset, 4, mask);
1851         proto_tree_add_boolean(tree, hf_smb_server_cap_lock_and_read,
1852                 tvb, offset, 4, mask);
1853         proto_tree_add_boolean(tree, hf_smb_server_cap_nt_find,
1854                 tvb, offset, 4, mask);
1855         proto_tree_add_boolean(tree, hf_smb_server_cap_dfs,
1856                 tvb, offset, 4, mask);
1857         proto_tree_add_boolean(tree, hf_smb_server_cap_infolevel_passthru,
1858                 tvb, offset, 4, mask);
1859         proto_tree_add_boolean(tree, hf_smb_server_cap_large_readx,
1860                 tvb, offset, 4, mask);
1861         proto_tree_add_boolean(tree, hf_smb_server_cap_large_writex,
1862                 tvb, offset, 4, mask);
1863         proto_tree_add_boolean(tree, hf_smb_server_cap_unix,
1864                 tvb, offset, 4, mask);
1865         proto_tree_add_boolean(tree, hf_smb_server_cap_reserved,
1866                 tvb, offset, 4, mask);
1867         proto_tree_add_boolean(tree, hf_smb_server_cap_bulk_transfer,
1868                 tvb, offset, 4, mask);
1869         proto_tree_add_boolean(tree, hf_smb_server_cap_compressed_data,
1870                 tvb, offset, 4, mask);
1871         proto_tree_add_boolean(tree, hf_smb_server_cap_extended_security,
1872                 tvb, offset, 4, mask);
1873
1874         return mask;
1875 }
1876
1877 #define RAWMODE_READ   0x01
1878 #define RAWMODE_WRITE  0x02
1879 static const true_false_string tfs_rm_read = {
1880         "Read Raw is supported",
1881         "Read Raw is not supported"
1882 };
1883 static const true_false_string tfs_rm_write = {
1884         "Write Raw is supported",
1885         "Write Raw is not supported"
1886 };
1887
1888 static int
1889 dissect_negprot_rawmode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
1890 {
1891         guint16 mask;
1892         proto_item *item = NULL;
1893         proto_tree *tree = NULL;
1894
1895         mask = tvb_get_letohs(tvb, offset);
1896
1897         if(parent_tree){
1898                 item = proto_tree_add_text(parent_tree, tvb, offset, 2, "Raw Mode: 0x%04x", mask);
1899                 tree = proto_item_add_subtree(item, ett_smb_rawmode);
1900         }
1901
1902         proto_tree_add_boolean(tree, hf_smb_rm_read, tvb, offset, 2, mask);
1903         proto_tree_add_boolean(tree, hf_smb_rm_write, tvb, offset, 2, mask);
1904
1905         offset += 2;
1906
1907         return offset;
1908 }
1909
1910 #define SECURITY_MODE_MODE             0x01
1911 #define SECURITY_MODE_PASSWORD         0x02
1912 #define SECURITY_MODE_SIGNATURES       0x04
1913 #define SECURITY_MODE_SIG_REQUIRED     0x08
1914 static const true_false_string tfs_sm_mode = {
1915         "USER security mode",
1916         "SHARE security mode"
1917 };
1918 static const true_false_string tfs_sm_password = {
1919         "ENCRYPTED password. Use challenge/response",
1920         "PLAINTEXT password"
1921 };
1922 static const true_false_string tfs_sm_signatures = {
1923         "Security signatures ENABLED",
1924         "Security signatures NOT enabled"
1925 };
1926 static const true_false_string tfs_sm_sig_required = {
1927         "Security signatures REQUIRED",
1928         "Security signatures NOT required"
1929 };
1930
1931 static int
1932 dissect_negprot_security_mode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, int wc)
1933 {
1934         guint16 mask = 0;
1935         proto_item *item = NULL;
1936         proto_tree *tree = NULL;
1937
1938         switch(wc){
1939         case 13:
1940                 mask = tvb_get_letohs(tvb, offset);
1941                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
1942                                 "Security Mode: 0x%04x", mask);
1943                 tree = proto_item_add_subtree(item, ett_smb_mode);
1944                 proto_tree_add_boolean(tree, hf_smb_sm_mode16, tvb, offset, 2, mask);
1945                 proto_tree_add_boolean(tree, hf_smb_sm_password16, tvb, offset, 2, mask);
1946                 offset += 2;
1947                 break;
1948
1949         case 17:
1950                 mask = tvb_get_guint8(tvb, offset);
1951                 item = proto_tree_add_text(parent_tree, tvb, offset, 1,
1952                                 "Security Mode: 0x%02x", mask);
1953                 tree = proto_item_add_subtree(item, ett_smb_mode);
1954                 proto_tree_add_boolean(tree, hf_smb_sm_mode, tvb, offset, 1, mask);
1955                 proto_tree_add_boolean(tree, hf_smb_sm_password, tvb, offset, 1, mask);
1956                 proto_tree_add_boolean(tree, hf_smb_sm_signatures, tvb, offset, 1, mask);
1957                 proto_tree_add_boolean(tree, hf_smb_sm_sig_required, tvb, offset, 1, mask);
1958                 offset += 1;
1959                 break;
1960         }
1961
1962         return offset;
1963 }
1964
1965 static int
1966 dissect_negprot_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
1967 {
1968         proto_item *it = NULL;
1969         proto_tree *tr = NULL;
1970         guint16 bc;
1971         guint8 wc;
1972
1973         WORD_COUNT;
1974
1975         BYTE_COUNT;
1976
1977         if(tree){
1978                 it = proto_tree_add_text(tree, tvb, offset, bc,
1979                                 "Requested Dialects");
1980                 tr = proto_item_add_subtree(it, ett_smb_dialects);
1981         }
1982
1983         while(bc){
1984                 int len;
1985                 const guint8 *str;
1986                 proto_item *dit = NULL;
1987                 proto_tree *dtr = NULL;
1988
1989                 /* XXX - what if this runs past bc? */
1990                 len = tvb_strsize(tvb, offset+1);
1991                 str = tvb_get_ptr(tvb, offset+1, len);
1992
1993                 if(tr){
1994                         dit = proto_tree_add_text(tr, tvb, offset, len+1,
1995                                         "Dialect: %s", str);
1996                         dtr = proto_item_add_subtree(dit, ett_smb_dialect);
1997                 }
1998
1999                 /* Buffer Format */
2000                 CHECK_BYTE_COUNT(1);
2001                 proto_tree_add_item(dtr, hf_smb_buffer_format, tvb, offset, 1,
2002                         TRUE);
2003                 COUNT_BYTES(1);
2004
2005                 /*Dialect Name */
2006                 CHECK_BYTE_COUNT(len);
2007                 proto_tree_add_string(dtr, hf_smb_dialect_name, tvb, offset,
2008                         len, str);
2009                 COUNT_BYTES(len);
2010         }
2011
2012         END_OF_SMB
2013
2014         return offset;
2015 }
2016
2017 static int
2018 dissect_negprot_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2019 {
2020         guint8 wc;
2021         guint16 dialect;
2022         const char *dn;
2023         int dn_len;
2024         guint16 bc;
2025         guint16 ekl=0;
2026         guint32 caps=0;
2027         gint16 tz;
2028
2029         WORD_COUNT;
2030
2031         /* Dialect Index */
2032         dialect = tvb_get_letohs(tvb, offset);
2033         switch(wc){
2034         case 1:
2035                 if(dialect==0xffff){
2036                         proto_tree_add_uint_format(tree, hf_smb_dialect_index,
2037                                 tvb, offset, 2, dialect,
2038                                 "Selected Index: -1, PC NETWORK PROGRAM 1.0 choosen");
2039                 } else {
2040                         proto_tree_add_uint(tree, hf_smb_dialect_index,
2041                                 tvb, offset, 2, dialect);
2042                 }
2043                 break;
2044         case 13:
2045                 proto_tree_add_uint_format(tree, hf_smb_dialect_index,
2046                         tvb, offset, 2, dialect,
2047                         "Dialect Index: %u, Greater than CORE PROTOCOL and up to LANMAN2.1", dialect);
2048                 break;
2049         case 17:
2050                 proto_tree_add_uint_format(tree, hf_smb_dialect_index,
2051                         tvb, offset, 2, dialect,
2052                         "Dialect Index: %u, greater than LANMAN2.1", dialect);
2053                 break;
2054         default:
2055                 proto_tree_add_text(tree, tvb, offset, wc*2,
2056                         "Words for unknown response format");
2057                 offset += wc*2;
2058                 goto bytecount;
2059         }
2060         offset += 2;
2061
2062         switch(wc){
2063         case 13:
2064                 /* Security Mode */
2065                 offset = dissect_negprot_security_mode(tvb, pinfo, tree, offset,
2066                                 wc);
2067
2068                 /* Maximum Transmit Buffer Size */
2069                 proto_tree_add_item(tree, hf_smb_max_trans_buf_size,
2070                         tvb, offset, 2, TRUE);
2071                 offset += 2;
2072
2073                 /* Maximum Multiplex Count */
2074                 proto_tree_add_item(tree, hf_smb_max_mpx_count,
2075                         tvb, offset, 2, TRUE);
2076                 offset += 2;
2077
2078                 /* Maximum Vcs Number */
2079                 proto_tree_add_item(tree, hf_smb_max_vcs_num,
2080                         tvb, offset, 2, TRUE);
2081                 offset += 2;
2082
2083                 /* raw mode */
2084                 offset = dissect_negprot_rawmode(tvb, pinfo, tree, offset);
2085
2086                 /* session key */
2087                 proto_tree_add_item(tree, hf_smb_session_key,
2088                         tvb, offset, 4, TRUE);
2089                 offset += 4;
2090
2091                 /* current time and date at server */
2092                 offset = dissect_smb_datetime(tvb, pinfo, tree, offset, hf_smb_server_date_time, hf_smb_server_smb_date, hf_smb_server_smb_time,
2093                     TRUE);
2094
2095                 /* time zone */
2096                 tz = tvb_get_letohs(tvb, offset);
2097                 proto_tree_add_int_format(tree, hf_smb_server_timezone, tvb, offset, 2, tz, "Server Time Zone: %d min from UTC", tz);
2098                 offset += 2;
2099
2100                 /* encryption key length */
2101                 ekl = tvb_get_letohs(tvb, offset);
2102                 proto_tree_add_uint(tree, hf_smb_encryption_key_length, tvb, offset, 2, ekl);
2103                 offset += 2;
2104
2105                 /* 2 reserved bytes */
2106                 proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
2107                 offset += 2;
2108
2109                 break;
2110
2111         case 17:
2112                 /* Security Mode */
2113                 offset = dissect_negprot_security_mode(tvb, pinfo, tree, offset, wc);
2114
2115                 /* Maximum Multiplex Count */
2116                 proto_tree_add_item(tree, hf_smb_max_mpx_count,
2117                         tvb, offset, 2, TRUE);
2118                 offset += 2;
2119
2120                 /* Maximum Vcs Number */
2121                 proto_tree_add_item(tree, hf_smb_max_vcs_num,
2122                         tvb, offset, 2, TRUE);
2123                 offset += 2;
2124
2125                 /* Maximum Transmit Buffer Size */
2126                 proto_tree_add_item(tree, hf_smb_max_trans_buf_size,
2127                         tvb, offset, 4, TRUE);
2128                 offset += 4;
2129
2130                 /* maximum raw buffer size */
2131                 proto_tree_add_item(tree, hf_smb_max_raw_buf_size,
2132                         tvb, offset, 4, TRUE);
2133                 offset += 4;
2134
2135                 /* session key */
2136                 proto_tree_add_item(tree, hf_smb_session_key,
2137                         tvb, offset, 4, TRUE);
2138                 offset += 4;
2139
2140                 /* server capabilities */
2141                 caps = dissect_negprot_capabilities(tvb, pinfo, tree, offset);
2142                 offset += 4;
2143
2144                 /* system time */
2145                 offset = dissect_smb_64bit_time(tvb, pinfo, tree, offset,
2146                                 hf_smb_system_time);
2147
2148                 /* time zone */
2149                 tz = tvb_get_letohs(tvb, offset);
2150                 proto_tree_add_int_format(tree, hf_smb_server_timezone,
2151                         tvb, offset, 2, tz,
2152                         "Server Time Zone: %d min from UTC", tz);
2153                 offset += 2;
2154
2155                 /* encryption key length */
2156                 ekl = tvb_get_guint8(tvb, offset);
2157                 proto_tree_add_uint(tree, hf_smb_encryption_key_length,
2158                         tvb, offset, 1, ekl);
2159                 offset += 1;
2160
2161                 break;
2162         }
2163
2164         BYTE_COUNT;
2165
2166         switch(wc){
2167         case 13:
2168                 /* challenge/response encryption key */
2169                 if(ekl){
2170                         CHECK_BYTE_COUNT(ekl);
2171                         proto_tree_add_item(tree, hf_smb_encryption_key, tvb, offset, ekl, TRUE);
2172                         COUNT_BYTES(ekl);
2173                 }
2174
2175                 /* domain */
2176                 dn = get_unicode_or_ascii_string(tvb, &offset,
2177                         pinfo, &dn_len, FALSE, FALSE, &bc);
2178                 if (dn == NULL)
2179                         goto endofcommand;
2180                 proto_tree_add_string(tree, hf_smb_primary_domain, tvb,
2181                         offset, dn_len,dn);
2182                 COUNT_BYTES(dn_len);
2183                 break;
2184
2185         case 17:
2186                 if(!(caps&SERVER_CAP_EXTENDED_SECURITY)){
2187                         smb_info_t *si;
2188
2189                         /* challenge/response encryption key */
2190                         /* XXX - is this aligned on an even boundary? */
2191                         if(ekl){
2192                                 CHECK_BYTE_COUNT(ekl);
2193                                 proto_tree_add_item(tree, hf_smb_encryption_key,
2194                                         tvb, offset, ekl, TRUE);
2195                                 COUNT_BYTES(ekl);
2196                         }
2197
2198                         /* domain */
2199                         /* this string is special, unicode is flagged in caps */
2200                         /* This string is NOT padded to be 16bit aligned. (seen in actual capture) */
2201                         si = pinfo->private_data;
2202                         si->unicode = (caps&SERVER_CAP_UNICODE);
2203                         dn = get_unicode_or_ascii_string(tvb,
2204                                 &offset, pinfo, &dn_len, TRUE, FALSE,
2205                                 &bc);
2206                         if (dn == NULL)
2207                                 goto endofcommand;
2208                         proto_tree_add_string(tree, hf_smb_primary_domain,
2209                                 tvb, offset, dn_len, dn);
2210                         COUNT_BYTES(dn_len);
2211                 } else {
2212                         /* guid */
2213                         /* XXX - show it in the standard Microsoft format
2214                            for GUIDs? */
2215                         CHECK_BYTE_COUNT(16);
2216                         proto_tree_add_item(tree, hf_smb_server_guid,
2217                                 tvb, offset, 16, TRUE);
2218                         COUNT_BYTES(16);
2219
2220                         /* security blob */
2221                         /* XXX - is this ASN.1-encoded?  Is it a Kerberos
2222                            data structure, at least in NT 5.0-and-later
2223                            server replies? */
2224                         if(bc){
2225                                 proto_tree_add_item(tree, hf_smb_security_blob,
2226                                         tvb, offset, bc, TRUE);
2227                                 COUNT_BYTES(bc);
2228                         }
2229                 }
2230                 break;
2231         }
2232
2233         END_OF_SMB
2234
2235         return offset;
2236 }
2237
2238
2239 static int
2240 dissect_old_dir_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2241 {
2242         int dn_len;
2243         const char *dn;
2244         guint8 wc;
2245         guint16 bc;
2246
2247         WORD_COUNT;
2248  
2249         BYTE_COUNT;
2250
2251         /* buffer format */
2252         CHECK_BYTE_COUNT(1);
2253         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2254         COUNT_BYTES(1);
2255
2256         /* dir name */
2257         dn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &dn_len,
2258                 FALSE, FALSE, &bc);
2259         if (dn == NULL)
2260                 goto endofcommand;
2261         proto_tree_add_string(tree, hf_smb_dir_name, tvb, offset, dn_len,
2262                 dn);
2263         COUNT_BYTES(dn_len);
2264
2265         if (check_col(pinfo->cinfo, COL_INFO)) {
2266                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Directory: %s", dn);
2267         }
2268
2269         END_OF_SMB
2270
2271         return offset;
2272 }
2273
2274 static int
2275 dissect_empty(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2276 {
2277         guint8 wc;
2278         guint16 bc;
2279  
2280         WORD_COUNT;
2281  
2282         BYTE_COUNT;
2283
2284         END_OF_SMB
2285
2286         return offset;
2287 }
2288
2289 static int
2290 dissect_echo_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2291 {
2292         guint16 ec, bc;
2293         guint8 wc;
2294
2295         WORD_COUNT;
2296
2297         /* echo count */
2298         ec = tvb_get_letohs(tvb, offset);
2299         proto_tree_add_uint(tree, hf_smb_echo_count, tvb, offset, 2, ec);
2300         offset += 2;
2301
2302         BYTE_COUNT;
2303
2304         if (bc != 0) {
2305                 /* echo data */
2306                 proto_tree_add_item(tree, hf_smb_echo_data, tvb, offset, bc, TRUE);
2307                 COUNT_BYTES(bc);
2308         }
2309
2310         END_OF_SMB
2311
2312         return offset;
2313 }
2314
2315 static int
2316 dissect_echo_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2317 {
2318         guint16 bc;
2319         guint8 wc;
2320
2321         WORD_COUNT;
2322
2323         /* echo sequence number */
2324         proto_tree_add_item(tree, hf_smb_echo_seq_num, tvb, offset, 2, TRUE);
2325         offset += 2;
2326
2327         BYTE_COUNT;
2328
2329         if (bc != 0) {
2330                 /* echo data */
2331                 proto_tree_add_item(tree, hf_smb_echo_data, tvb, offset, bc, TRUE);
2332                 COUNT_BYTES(bc);
2333         }
2334
2335         END_OF_SMB
2336
2337         return offset;
2338 }
2339
2340 static int
2341 dissect_tree_connect_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2342 {
2343         int an_len, pwlen;
2344         const char *an;
2345         guint8 wc;
2346         guint16 bc;
2347
2348         WORD_COUNT;
2349  
2350         BYTE_COUNT;
2351
2352         /* buffer format */
2353         CHECK_BYTE_COUNT(1);
2354         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2355         COUNT_BYTES(1);
2356
2357         /* Path */
2358         an = get_unicode_or_ascii_string(tvb, &offset,
2359                 pinfo, &an_len, FALSE, FALSE, &bc);
2360         if (an == NULL)
2361                 goto endofcommand;
2362         proto_tree_add_string(tree, hf_smb_path, tvb,
2363                 offset, an_len, an);
2364         COUNT_BYTES(an_len);
2365
2366         if (check_col(pinfo->cinfo, COL_INFO)) {
2367                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", an);
2368         }
2369
2370         /* buffer format */
2371         CHECK_BYTE_COUNT(1);
2372         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2373         COUNT_BYTES(1);
2374
2375         /* password, ANSI */
2376         /* XXX - what if this runs past bc? */
2377         pwlen = tvb_strsize(tvb, offset);
2378         CHECK_BYTE_COUNT(pwlen);
2379         proto_tree_add_item(tree, hf_smb_password,
2380                 tvb, offset, pwlen, TRUE);
2381         COUNT_BYTES(pwlen);
2382
2383         /* buffer format */
2384         CHECK_BYTE_COUNT(1);
2385         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2386         COUNT_BYTES(1);
2387
2388         /* Service */
2389         an = get_unicode_or_ascii_string(tvb, &offset,
2390                 pinfo, &an_len, FALSE, FALSE, &bc);
2391         if (an == NULL)
2392                 goto endofcommand;
2393         proto_tree_add_string(tree, hf_smb_service, tvb,
2394                 offset, an_len, an);
2395         COUNT_BYTES(an_len);
2396
2397         END_OF_SMB
2398
2399         return offset;
2400 }
2401
2402 static int
2403 dissect_tree_connect_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2404 {
2405         guint8 wc;
2406         guint16 bc;
2407
2408         WORD_COUNT;
2409  
2410         /* Maximum Buffer Size */
2411         proto_tree_add_item(tree, hf_smb_max_buf_size, tvb, offset, 2, TRUE);
2412         offset += 2;
2413
2414         /* tid */
2415         proto_tree_add_item(tree, hf_smb_tid, tvb, offset, 2, TRUE);
2416         offset += 2;
2417
2418         BYTE_COUNT;
2419
2420         END_OF_SMB
2421
2422         return offset;
2423 }
2424  
2425
2426 static const true_false_string tfs_of_create = {
2427         "Create file if it does not exist",
2428         "Fail if file does not exist"
2429 };
2430 static const value_string of_open[] = {
2431         { 0,            "Fail if file exists"},
2432         { 1,            "Open file if it exists"},
2433         { 2,            "Truncate file if it exists"},
2434         {0, NULL}
2435 };
2436 static int
2437 dissect_open_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
2438 {
2439         guint16 mask;
2440         proto_item *item = NULL;
2441         proto_tree *tree = NULL;
2442
2443         mask = tvb_get_letohs(tvb, offset);
2444
2445         if(parent_tree){
2446                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
2447                         "Open Function: 0x%04x", mask);
2448                 tree = proto_item_add_subtree(item, ett_smb_openfunction);
2449         }
2450
2451         proto_tree_add_boolean(tree, hf_smb_open_function_create,
2452                 tvb, offset, 2, mask);
2453         proto_tree_add_uint(tree, hf_smb_open_function_open,
2454                 tvb, offset, 2, mask);
2455
2456         offset += 2;
2457
2458         return offset;
2459 }
2460
2461
2462 static const true_false_string tfs_mf_file = {
2463         "Target must be a file",
2464         "Target needn't be a file"
2465  };
2466 static const true_false_string tfs_mf_dir = {
2467         "Target must be a directory",
2468         "Target needn't be a directory"
2469 };
2470 static const true_false_string tfs_mf_verify = {
2471         "MUST verify all writes",
2472         "Don't have to verify writes"
2473 };
2474 static int
2475 dissect_move_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
2476 {
2477         guint16 mask;
2478         proto_item *item = NULL;
2479         proto_tree *tree = NULL;
2480
2481         mask = tvb_get_letohs(tvb, offset);
2482
2483         if(parent_tree){
2484                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
2485                         "Flags: 0x%04x", mask);
2486                 tree = proto_item_add_subtree(item, ett_smb_move_flags);
2487         }
2488  
2489         proto_tree_add_boolean(tree, hf_smb_move_flags_verify,
2490                 tvb, offset, 2, mask);
2491         proto_tree_add_boolean(tree, hf_smb_move_flags_dir,
2492                 tvb, offset, 2, mask);
2493         proto_tree_add_boolean(tree, hf_smb_move_flags_file,
2494                 tvb, offset, 2, mask);
2495
2496         offset += 2;
2497
2498         return offset;
2499 }
2500
2501 static int
2502 dissect_move_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2503 {
2504         int fn_len;
2505         guint16 tid;
2506         guint16 bc;
2507         guint8 wc;
2508         const char *fn;
2509
2510         WORD_COUNT;
2511
2512         /* tid */
2513         tid = tvb_get_letohs(tvb, offset);
2514         proto_tree_add_uint_format(tree, hf_smb_tid, tvb, offset, 2, tid,
2515                 "TID (target): 0x%04x", tid);
2516         offset += 2;
2517
2518         /* open function */
2519         offset = dissect_open_function(tvb, pinfo, tree, offset);
2520
2521         /* move flags */
2522         offset = dissect_move_flags(tvb, pinfo, tree, offset);
2523
2524         BYTE_COUNT;
2525
2526         /* buffer format */
2527         CHECK_BYTE_COUNT(1);
2528         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2529         COUNT_BYTES(1);
2530
2531         /* file name */
2532         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
2533                 FALSE, FALSE, &bc);
2534         if (fn == NULL)
2535                 goto endofcommand;
2536         proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
2537                 fn_len, fn, "Old File Name: %s", fn);
2538         COUNT_BYTES(fn_len);
2539
2540         if (check_col(pinfo->cinfo, COL_INFO)) {
2541                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Old Name: %s", fn);
2542         }
2543
2544         /* buffer format */
2545         CHECK_BYTE_COUNT(1);
2546         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2547         COUNT_BYTES(1);
2548
2549         /* file name */
2550         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
2551                 FALSE, FALSE, &bc);
2552         if (fn == NULL)
2553                 goto endofcommand;
2554         proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
2555                 fn_len, fn, "New File Name: %s", fn);
2556         COUNT_BYTES(fn_len);
2557
2558         if (check_col(pinfo->cinfo, COL_INFO)) {
2559                 col_append_fstr(pinfo->cinfo, COL_INFO, ", New Name: %s", fn);
2560         }
2561
2562         END_OF_SMB
2563
2564         return offset;
2565 }
2566
2567 static int
2568 dissect_move_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2569 {
2570         int fn_len;
2571         const char *fn;
2572         guint8 wc;
2573         guint16 bc;
2574
2575         WORD_COUNT;
2576
2577         /* # of files moved */
2578         proto_tree_add_item(tree, hf_smb_move_files_moved, tvb, offset, 2, TRUE);
2579         offset += 2;
2580
2581         BYTE_COUNT;
2582
2583         /* buffer format */
2584         CHECK_BYTE_COUNT(1);
2585         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2586         COUNT_BYTES(1);
2587
2588         /* file name */
2589         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
2590                 FALSE, FALSE, &bc);
2591         if (fn == NULL)
2592                 goto endofcommand;
2593         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
2594                 fn);
2595         COUNT_BYTES(fn_len);
2596
2597         END_OF_SMB
2598
2599         return offset;
2600 }
2601
2602 static int
2603 dissect_open_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2604 {
2605         int fn_len;
2606         const char *fn;
2607         guint8 wc;
2608         guint16 bc;
2609
2610         WORD_COUNT;
2611
2612         /* desired access */
2613         offset = dissect_access(tvb, pinfo, tree, offset, "Desired");
2614
2615         /* Search Attributes */
2616         offset = dissect_search_attributes(tvb, pinfo, tree, offset);
2617
2618         BYTE_COUNT;
2619
2620         /* buffer format */
2621         CHECK_BYTE_COUNT(1);
2622         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2623         COUNT_BYTES(1);
2624
2625         /* file name */
2626         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
2627                 FALSE, FALSE, &bc);
2628         if (fn == NULL)
2629                 goto endofcommand;
2630         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
2631                 fn);
2632         COUNT_BYTES(fn_len);
2633
2634         if (check_col(pinfo->cinfo, COL_INFO)) {
2635                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
2636         }
2637
2638         END_OF_SMB
2639
2640         return offset;
2641 }
2642
2643 void
2644 add_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2645     int len, guint16 fid)
2646 {
2647         proto_tree_add_uint(tree, hf_smb_fid, tvb, offset, len, fid);
2648         if (check_col(pinfo->cinfo, COL_INFO))
2649                 col_append_fstr(pinfo->cinfo, COL_INFO, ", FID: 0x%04x", fid);
2650 }
2651
2652 static int
2653 dissect_open_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2654 {
2655         guint8 wc;
2656         guint16 bc;
2657         guint16 fid;
2658
2659         WORD_COUNT;
2660
2661         /* fid */
2662         fid = tvb_get_letohs(tvb, offset);
2663         add_fid(tvb, pinfo, tree, offset, 2, fid);
2664         offset += 2;
2665
2666         /* File Attributes */
2667         offset = dissect_file_attributes(tvb, pinfo, tree, offset);
2668
2669         /* last write time */
2670         offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
2671         
2672         /* File Size */
2673         proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
2674         offset += 4;
2675
2676         /* granted access */
2677         offset = dissect_access(tvb, pinfo, tree, offset, "Granted");
2678
2679         BYTE_COUNT;
2680
2681         END_OF_SMB
2682
2683         return offset;
2684 }
2685
2686 static int
2687 dissect_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2688 {
2689         guint8 wc;
2690         guint16 bc;
2691         guint16 fid;
2692
2693         WORD_COUNT;
2694
2695         /* fid */
2696         fid = tvb_get_letohs(tvb, offset);
2697         add_fid(tvb, pinfo, tree, offset, 2, fid);
2698         offset += 2;
2699
2700         BYTE_COUNT;
2701
2702         END_OF_SMB
2703
2704         return offset;
2705 }
2706
2707 static int
2708 dissect_create_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2709 {
2710         int fn_len;
2711         const char *fn;
2712         guint8 wc;
2713         guint16 bc;
2714
2715         WORD_COUNT;
2716
2717         /* file attributes */
2718         offset = dissect_file_attributes(tvb, pinfo, tree, offset);
2719
2720         /* creation time */
2721         offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_create_time);
2722
2723         BYTE_COUNT;
2724
2725         /* buffer format */
2726         CHECK_BYTE_COUNT(1);
2727         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2728         COUNT_BYTES(1);
2729
2730         /* File Name */
2731         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
2732                 FALSE, FALSE, &bc);
2733         if (fn == NULL)
2734                 goto endofcommand;
2735         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
2736                 fn);
2737         COUNT_BYTES(fn_len);
2738
2739         if (check_col(pinfo->cinfo, COL_INFO)) {
2740                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
2741         }
2742
2743         END_OF_SMB
2744
2745         return offset;
2746 }
2747
2748 static int
2749 dissect_close_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2750 {
2751         guint8 wc;
2752         guint16 bc, fid;
2753
2754         WORD_COUNT;
2755
2756         /* fid */
2757         fid = tvb_get_letohs(tvb, offset);
2758         add_fid(tvb, pinfo, tree, offset, 2, fid);
2759         offset += 2;
2760
2761         /* last write time */
2762         offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
2763
2764         BYTE_COUNT;
2765
2766         END_OF_SMB
2767
2768         return offset;
2769 }
2770
2771 static int
2772 dissect_delete_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2773 {
2774         int fn_len;
2775         const char *fn;
2776         guint8 wc;
2777         guint16 bc;
2778
2779         WORD_COUNT;
2780
2781         /* search attributes */
2782         offset = dissect_search_attributes(tvb, pinfo, tree, offset);
2783
2784         BYTE_COUNT;
2785
2786         /* buffer format */
2787         CHECK_BYTE_COUNT(1);
2788         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2789         COUNT_BYTES(1);
2790
2791         /* file name */
2792         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
2793                 FALSE, FALSE, &bc);
2794         if (fn == NULL)
2795                 goto endofcommand;
2796         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
2797                 fn);
2798         COUNT_BYTES(fn_len);
2799
2800         if (check_col(pinfo->cinfo, COL_INFO)) {
2801                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
2802         }
2803
2804         END_OF_SMB
2805
2806         return offset;
2807 }
2808
2809 static int
2810 dissect_rename_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2811 {
2812         int fn_len;
2813         const char *fn;
2814         guint8 wc;
2815         guint16 bc;
2816
2817         WORD_COUNT;
2818
2819         /* search attributes */
2820         offset = dissect_search_attributes(tvb, pinfo, tree, offset);
2821
2822         BYTE_COUNT;
2823
2824         /* buffer format */
2825         CHECK_BYTE_COUNT(1);
2826         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2827         COUNT_BYTES(1);
2828
2829         /* old file name */
2830         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
2831                 FALSE, FALSE, &bc);
2832         if (fn == NULL)
2833                 goto endofcommand;
2834         proto_tree_add_string(tree, hf_smb_old_file_name, tvb, offset, fn_len,
2835                 fn);
2836         COUNT_BYTES(fn_len);
2837
2838         if (check_col(pinfo->cinfo, COL_INFO)) {
2839                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Old Name: %s", fn);
2840         }
2841
2842         /* buffer format */
2843         CHECK_BYTE_COUNT(1);
2844         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2845         COUNT_BYTES(1);
2846
2847         /* file name */
2848         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
2849                 FALSE, FALSE, &bc);
2850         if (fn == NULL)
2851                 goto endofcommand;
2852         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
2853                 fn);
2854         COUNT_BYTES(fn_len);
2855
2856         if (check_col(pinfo->cinfo, COL_INFO)) {
2857                 col_append_fstr(pinfo->cinfo, COL_INFO, ", New Name: %s", fn);
2858         }
2859
2860         END_OF_SMB
2861
2862         return offset;
2863 }
2864
2865 static int
2866 dissect_query_information_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2867 {
2868         guint16 bc;
2869         guint8 wc;
2870         const char *fn;
2871         int fn_len;
2872
2873         WORD_COUNT;
2874
2875         BYTE_COUNT;
2876
2877         /* Buffer Format */
2878         CHECK_BYTE_COUNT(1);
2879         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2880         COUNT_BYTES(1);
2881
2882         /* File Name */
2883         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
2884                 FALSE, FALSE, &bc);
2885         if (fn == NULL)
2886                 goto endofcommand;
2887         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
2888                 fn);
2889         COUNT_BYTES(fn_len);
2890
2891         if (check_col(pinfo->cinfo, COL_INFO)) {
2892                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
2893         }
2894
2895         END_OF_SMB
2896
2897         return offset;
2898 }
2899  
2900 static int
2901 dissect_query_information_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2902 {
2903         guint16 bc;
2904         guint8 wc;
2905
2906         WORD_COUNT;
2907
2908         /* File Attributes */
2909         offset = dissect_file_attributes(tvb, pinfo, tree, offset);
2910
2911         /* Last Write Time */
2912         offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
2913
2914         /* File Size */
2915         proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
2916         offset += 4;
2917
2918         /* 10 reserved bytes */
2919         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 10, TRUE);
2920         offset += 10;
2921
2922         BYTE_COUNT;
2923
2924         END_OF_SMB
2925
2926         return offset;
2927 }
2928
2929 static int
2930 dissect_set_information_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2931 {
2932         int fn_len;
2933         const char *fn;
2934         guint8 wc;
2935         guint16 bc;
2936
2937         WORD_COUNT;
2938
2939         /* file attributes */
2940         offset = dissect_file_attributes(tvb, pinfo, tree, offset);
2941
2942         /* last write time */
2943         offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
2944
2945         /* 10 reserved bytes */
2946         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 10, TRUE);
2947         offset += 10;
2948
2949         BYTE_COUNT;
2950
2951         /* buffer format */
2952         CHECK_BYTE_COUNT(1);
2953         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
2954         COUNT_BYTES(1);
2955
2956         /* file name */
2957         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
2958                 FALSE, FALSE, &bc);
2959         if (fn == NULL)
2960                 goto endofcommand;
2961         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
2962                 fn);
2963         COUNT_BYTES(fn_len);
2964
2965         if (check_col(pinfo->cinfo, COL_INFO)) {
2966                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
2967         }
2968
2969         END_OF_SMB
2970
2971         return offset;
2972 }
2973
2974 static int
2975 dissect_read_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
2976 {
2977         guint8 wc;
2978         guint16 bc, fid;
2979
2980         WORD_COUNT;
2981
2982         /* fid */
2983         fid = tvb_get_letohs(tvb, offset);
2984         add_fid(tvb, pinfo, tree, offset, 2, fid);
2985         offset += 2;
2986
2987         /* read count */
2988         proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
2989         offset += 2;
2990
2991         /* offset */
2992         proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
2993         offset += 4;
2994
2995         /* remaining */
2996         proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
2997         offset += 2;
2998
2999         BYTE_COUNT;
3000
3001         END_OF_SMB
3002
3003         return offset;
3004 }
3005
3006 int
3007 dissect_file_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 bc, guint16 datalen)
3008 {
3009         int tvblen;
3010
3011         if(bc>datalen){
3012                 /* We have some initial padding bytes. */
3013                 /* XXX - use the data offset here instead? */
3014                 proto_tree_add_item(tree, hf_smb_padding, tvb, offset, bc-datalen,
3015                         TRUE);
3016                 offset += bc-datalen;
3017                 bc = datalen;
3018         }
3019         tvblen = tvb_length_remaining(tvb, offset);
3020         if(bc>tvblen){
3021                 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);
3022                 offset += tvblen;
3023         } else {
3024                 proto_tree_add_item(tree, hf_smb_file_data, tvb, offset, bc, TRUE);
3025                 offset += bc;
3026         }
3027         return offset;
3028 }
3029
3030 static int
3031 dissect_read_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3032 {
3033         guint16 cnt=0, bc;
3034         guint8 wc;
3035
3036         WORD_COUNT;
3037
3038         /* read count */
3039         cnt = tvb_get_letohs(tvb, offset);
3040         proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
3041         offset += 2;
3042
3043         /* 8 reserved bytes */
3044         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 8, TRUE);
3045         offset += 8;
3046
3047         BYTE_COUNT;
3048
3049         /* buffer format */
3050         CHECK_BYTE_COUNT(1);
3051         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
3052         COUNT_BYTES(1);
3053
3054         /* data len */
3055         CHECK_BYTE_COUNT(2);
3056         proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
3057         COUNT_BYTES(2);
3058
3059         if (bc != 0) {
3060                 /* file data */
3061                 offset = dissect_file_data(tvb, pinfo, tree, offset, bc, bc);
3062                 bc = 0;
3063         }
3064
3065         END_OF_SMB
3066
3067         return offset;
3068 }
3069
3070 static int
3071 dissect_lock_and_read_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3072 {
3073         guint16 cnt, bc;
3074         guint8 wc;
3075
3076         WORD_COUNT;
3077
3078         /* read count */
3079         cnt = tvb_get_letohs(tvb, offset);
3080         proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
3081         offset += 2;
3082
3083         /* 8 reserved bytes */
3084         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 8, TRUE);
3085         offset += 8;
3086
3087         BYTE_COUNT;
3088
3089         /* buffer format */
3090         CHECK_BYTE_COUNT(1);
3091         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
3092         COUNT_BYTES(1);
3093
3094         /* data len */
3095         CHECK_BYTE_COUNT(2);
3096         proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
3097         COUNT_BYTES(2);
3098
3099         END_OF_SMB
3100
3101         return offset;
3102 }
3103
3104
3105 static int
3106 dissect_write_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3107 {
3108         guint32 ofs=0;
3109         guint16 cnt=0, bc, fid;
3110         guint8 wc;
3111
3112         WORD_COUNT;
3113
3114         /* fid */
3115         fid = tvb_get_letohs(tvb, offset);
3116         add_fid(tvb, pinfo, tree, offset, 2, fid);
3117         offset += 2;
3118
3119         /* write count */
3120         cnt = tvb_get_letohs(tvb, offset);
3121         proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
3122         offset += 2;
3123
3124         /* offset */
3125         ofs = tvb_get_letohl(tvb, offset);
3126         proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
3127         offset += 4;
3128
3129         if (check_col(pinfo->cinfo, COL_INFO))
3130                 col_append_fstr(pinfo->cinfo, COL_INFO, 
3131                                 ", %d byte%s at offset %d", cnt, 
3132                                 (cnt == 1) ? "" : "s", ofs);
3133
3134         /* remaining */
3135         proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
3136         offset += 2;
3137
3138         BYTE_COUNT;
3139
3140         /* buffer format */
3141         CHECK_BYTE_COUNT(1);
3142         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
3143         COUNT_BYTES(1);
3144
3145         /* data len */
3146         CHECK_BYTE_COUNT(2);
3147         proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
3148         COUNT_BYTES(2);
3149
3150         if (check_col(pinfo->cinfo, COL_INFO))
3151                 col_append_fstr(pinfo->cinfo, COL_INFO, 
3152                                 ", %d byte%s at offset %d", cnt, 
3153                                 (cnt == 1) ? "" : "s", ofs);
3154
3155         if (bc != 0) {
3156                 /* file data */
3157                 offset = dissect_file_data(tvb, pinfo, tree, offset, bc, bc);
3158                 bc = 0;
3159         }
3160
3161         END_OF_SMB
3162
3163         return offset;
3164 }
3165  
3166 static int
3167 dissect_write_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3168 {
3169         guint8 wc;
3170         guint16 bc, cnt;
3171
3172         WORD_COUNT;
3173
3174         /* write count */
3175         cnt = tvb_get_letohs(tvb, offset);
3176         proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
3177         offset += 2;
3178
3179         if (check_col(pinfo->cinfo, COL_INFO))
3180                 col_append_fstr(pinfo->cinfo, COL_INFO, 
3181                                 ", %d byte%s", cnt, (cnt == 1) ? "" : "s");
3182
3183         BYTE_COUNT;
3184
3185         END_OF_SMB
3186
3187         return offset;
3188 }
3189
3190 static int
3191 dissect_lock_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3192 {
3193         guint8 wc;
3194         guint16 bc, fid;
3195
3196         WORD_COUNT;
3197
3198         /* fid */
3199         fid = tvb_get_letohs(tvb, offset);
3200         add_fid(tvb, pinfo, tree, offset, 2, fid);
3201         offset += 2;
3202
3203         /* lock count */
3204         proto_tree_add_item(tree, hf_smb_count, tvb, offset, 4, TRUE);
3205         offset += 4;
3206
3207         /* offset */
3208         proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
3209         offset += 4;
3210
3211         BYTE_COUNT;
3212
3213         END_OF_SMB
3214
3215         return offset;
3216 }
3217
3218 static int
3219 dissect_create_temporary_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3220 {
3221         int fn_len;
3222         const char *fn;
3223         guint8 wc;
3224         guint16 bc;
3225
3226         WORD_COUNT;
3227
3228         /* 2 reserved bytes */
3229         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
3230         offset += 2;
3231
3232         /* Creation time */
3233         offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_create_time);
3234
3235         BYTE_COUNT;
3236
3237         /* buffer format */
3238         CHECK_BYTE_COUNT(1);
3239         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
3240         COUNT_BYTES(1);
3241
3242         /* directory name */
3243         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
3244                 FALSE, FALSE, &bc);
3245         if (fn == NULL)
3246                 goto endofcommand;
3247         proto_tree_add_string(tree, hf_smb_dir_name, tvb, offset, fn_len,
3248                 fn);
3249         COUNT_BYTES(fn_len);
3250
3251         if (check_col(pinfo->cinfo, COL_INFO)) {
3252                 col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
3253         }
3254
3255         END_OF_SMB
3256
3257         return offset;
3258 }
3259
3260 static int
3261 dissect_create_temporary_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3262 {
3263         int fn_len;
3264         const char *fn;
3265         guint8 wc;
3266         guint16 bc, fid;
3267
3268         WORD_COUNT;
3269
3270         /* fid */
3271         fid = tvb_get_letohs(tvb, offset);
3272         add_fid(tvb, pinfo, tree, offset, 2, fid);
3273         offset += 2;
3274
3275         BYTE_COUNT;
3276
3277         /* buffer format */
3278         CHECK_BYTE_COUNT(1);
3279         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
3280         COUNT_BYTES(1);
3281
3282         /* file name */
3283         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
3284                 FALSE, FALSE, &bc);
3285         if (fn == NULL)
3286                 goto endofcommand;
3287         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
3288                 fn);
3289         COUNT_BYTES(fn_len);
3290
3291         END_OF_SMB
3292
3293         return offset;
3294 }
3295
3296 static const value_string seek_mode_vals[] = {
3297         {0,     "From Start Of File"},
3298         {1,     "From Current Position"},
3299         {2,     "From End Of File"},
3300         {0,     NULL}
3301 };
3302
3303 static int
3304 dissect_seek_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3305 {
3306         guint8 wc;
3307         guint16 bc, fid;
3308
3309         WORD_COUNT;
3310
3311         /* fid */
3312         fid = tvb_get_letohs(tvb, offset);
3313         add_fid(tvb, pinfo, tree, offset, 2, fid);
3314         offset += 2;
3315
3316         /* Seek Mode */
3317         proto_tree_add_item(tree, hf_smb_seek_mode, tvb, offset, 2, TRUE);
3318         offset += 2;
3319
3320         /* offset */
3321         proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
3322         offset += 4;
3323
3324         BYTE_COUNT;
3325
3326         END_OF_SMB
3327
3328         return offset;
3329 }
3330
3331 static int
3332 dissect_seek_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3333 {
3334         guint8 wc;
3335         guint16 bc;
3336
3337         WORD_COUNT;
3338
3339         /* offset */
3340         proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
3341         offset += 4;
3342
3343         BYTE_COUNT;
3344
3345         END_OF_SMB
3346
3347         return offset;
3348 }
3349  
3350 static int
3351 dissect_set_information2_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3352 {
3353         guint8 wc;
3354         guint16 bc, fid;
3355
3356         WORD_COUNT;
3357
3358         /* fid */
3359         fid = tvb_get_letohs(tvb, offset);
3360         add_fid(tvb, pinfo, tree, offset, 2, fid);
3361         offset += 2;
3362
3363         /* create time */
3364         offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
3365                 hf_smb_create_time,
3366                 hf_smb_create_dos_date, hf_smb_create_dos_time, FALSE);
3367
3368         /* access time */
3369         offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
3370                 hf_smb_access_time,
3371                 hf_smb_access_dos_date, hf_smb_access_dos_time, FALSE);
3372
3373         /* last write time */
3374         offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
3375                 hf_smb_last_write_time,
3376                 hf_smb_last_write_dos_date, hf_smb_last_write_dos_time, FALSE);
3377
3378         BYTE_COUNT;
3379
3380         END_OF_SMB
3381
3382         return offset;
3383 }
3384
3385 static int
3386 dissect_query_information2_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3387 {
3388         guint8 wc;
3389         guint16 bc;
3390
3391         WORD_COUNT;
3392
3393         /* create time */
3394         offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
3395                 hf_smb_create_time,
3396                 hf_smb_create_dos_date, hf_smb_create_dos_time, FALSE);
3397
3398         /* access time */
3399         offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
3400                 hf_smb_access_time,
3401                 hf_smb_access_dos_date, hf_smb_access_dos_time, FALSE);
3402
3403         /* last write time */
3404         offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
3405                 hf_smb_last_write_time,
3406                 hf_smb_last_write_dos_date, hf_smb_last_write_dos_time, FALSE);
3407
3408         /* data size */
3409         proto_tree_add_item(tree, hf_smb_data_size, tvb, offset, 4, TRUE);
3410         offset += 4;
3411
3412         /* allocation size */
3413         proto_tree_add_item(tree, hf_smb_alloc_size, tvb, offset, 4, TRUE);
3414         offset += 4;
3415
3416         /* File Attributes */
3417         offset = dissect_file_attributes(tvb, pinfo, tree, offset);
3418
3419         BYTE_COUNT;
3420
3421         END_OF_SMB
3422
3423         return offset;
3424 }
3425
3426 static int
3427 dissect_write_and_close_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3428 {
3429         guint8 wc;
3430         guint16 cnt=0;
3431         guint16 bc, fid;
3432
3433         WORD_COUNT;
3434
3435         /* fid */
3436         fid = tvb_get_letohs(tvb, offset);
3437         add_fid(tvb, pinfo, tree, offset, 2, fid);
3438         offset += 2;
3439
3440         /* write count */
3441         cnt = tvb_get_letohs(tvb, offset);
3442         proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
3443         offset += 2;
3444
3445         /* offset */
3446         proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
3447         offset += 4;
3448
3449         /* last write time */
3450         offset = dissect_smb_UTIME(tvb, pinfo, tree, offset, hf_smb_last_write_time);
3451         
3452         if(wc==12){
3453                 /* 12 reserved bytes */
3454                 proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 12, TRUE);
3455                 offset += 12;
3456         }
3457
3458         BYTE_COUNT;
3459
3460         /* 1 pad byte */
3461         CHECK_BYTE_COUNT(1);
3462         proto_tree_add_item(tree, hf_smb_padding, tvb, offset, 1, TRUE);
3463         COUNT_BYTES(1);
3464         
3465         offset = dissect_file_data(tvb, pinfo, tree, offset, cnt, cnt);
3466         bc = 0; /* XXX */
3467
3468         END_OF_SMB
3469
3470         return offset;
3471 }
3472  
3473 static int
3474 dissect_write_and_close_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3475 {
3476         guint8 wc;
3477         guint16 bc;
3478
3479         WORD_COUNT;
3480
3481         /* write count */
3482         proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
3483         offset += 2;
3484
3485         BYTE_COUNT;
3486
3487         END_OF_SMB
3488
3489         return offset;
3490 }
3491
3492 static int
3493 dissect_read_raw_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3494 {
3495         guint8 wc;
3496         guint16 bc, fid;
3497         guint32 to;
3498
3499         WORD_COUNT;
3500
3501         /* fid */
3502         fid = tvb_get_letohs(tvb, offset);
3503         add_fid(tvb, pinfo, tree, offset, 2, fid);
3504         offset += 2;
3505
3506         /* offset */
3507         proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
3508         offset += 4;
3509
3510         /* max count */
3511         proto_tree_add_item(tree, hf_smb_max_count, tvb, offset, 2, TRUE);
3512         offset += 2;
3513
3514         /* min count */
3515         proto_tree_add_item(tree, hf_smb_min_count, tvb, offset, 2, TRUE);
3516         offset += 2;
3517
3518         /* timeout */
3519         to = tvb_get_letohl(tvb, offset);
3520         proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: %s", time_msecs_to_str(to));
3521         offset += 4;
3522
3523         /* 2 reserved bytes */
3524         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
3525         offset += 2;
3526
3527         if(wc==10){
3528                 /* high offset */
3529                 proto_tree_add_item(tree, hf_smb_high_offset, tvb, offset, 4, TRUE);
3530                 offset += 4;
3531         }
3532
3533         BYTE_COUNT;
3534
3535         END_OF_SMB
3536
3537         return offset;
3538 }
3539
3540 static int
3541 dissect_query_information_disk_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3542 {
3543         guint8 wc;
3544         guint16 bc;
3545
3546         WORD_COUNT;
3547
3548         /* units */
3549         proto_tree_add_item(tree, hf_smb_units, tvb, offset, 2, TRUE);
3550         offset += 2;
3551
3552         /* bpu */
3553         proto_tree_add_item(tree, hf_smb_bpu, tvb, offset, 2, TRUE);
3554         offset += 2;
3555
3556         /* block size */
3557         proto_tree_add_item(tree, hf_smb_blocksize, tvb, offset, 2, TRUE);
3558         offset += 2;
3559
3560         /* free units */
3561         proto_tree_add_item(tree, hf_smb_freeunits, tvb, offset, 2, TRUE);
3562         offset += 2;
3563
3564         /* 2 reserved bytes */
3565         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
3566         offset += 2;
3567
3568         BYTE_COUNT;
3569
3570         END_OF_SMB
3571
3572         return offset;
3573 }
3574
3575 static int
3576 dissect_read_mpx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3577 {
3578         guint8 wc;
3579         guint16 bc, fid;
3580
3581         WORD_COUNT;
3582
3583         /* fid */
3584         fid = tvb_get_letohs(tvb, offset);
3585         add_fid(tvb, pinfo, tree, offset, 2, fid);
3586         offset += 2;
3587
3588         /* offset */
3589         proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
3590         offset += 4;
3591
3592         /* max count */
3593         proto_tree_add_item(tree, hf_smb_max_count, tvb, offset, 2, TRUE);
3594         offset += 2;
3595
3596         /* min count */
3597         proto_tree_add_item(tree, hf_smb_min_count, tvb, offset, 2, TRUE);
3598         offset += 2;
3599
3600         /* 6 reserved bytes */
3601         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 6, TRUE);
3602         offset += 6;
3603
3604         BYTE_COUNT;
3605
3606         END_OF_SMB
3607
3608         return offset;
3609 }
3610
3611 static int
3612 dissect_read_mpx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3613 {
3614         guint16 datalen=0, bc;
3615         guint8 wc;
3616
3617         WORD_COUNT;
3618
3619         /* offset */
3620         proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
3621         offset += 4;
3622
3623         /* count */
3624         proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
3625         offset += 2;
3626
3627         /* 2 reserved bytes */
3628         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
3629         offset += 2;
3630
3631         /* data compaction mode */
3632         proto_tree_add_item(tree, hf_smb_dcm, tvb, offset, 2, TRUE);
3633         offset += 2;
3634
3635         /* 2 reserved bytes */
3636         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
3637         offset += 2;
3638
3639         /* data len */
3640         datalen = tvb_get_letohs(tvb, offset);
3641         proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, datalen);
3642         offset += 2;
3643
3644         /* data offset */
3645         proto_tree_add_item(tree, hf_smb_data_offset, tvb, offset, 2, TRUE);
3646         offset += 2;
3647
3648         BYTE_COUNT;
3649
3650         /* file data */
3651         offset = dissect_file_data(tvb, pinfo, tree, offset, bc, datalen);
3652         bc = 0;
3653
3654         END_OF_SMB
3655
3656         return offset;
3657 }
3658
3659
3660 static const true_false_string tfs_write_mode_write_through = {
3661         "WRITE THROUGH requested",
3662         "Write through not requested"
3663 };
3664 static const true_false_string tfs_write_mode_return_remaining = {
3665         "RETURN REMAINING (pipe/dev) requested",
3666         "DON'T return remaining (pipe/dev)"
3667 };
3668 static const true_false_string tfs_write_mode_raw = {
3669         "Use WriteRawNamedPipe (pipe)",
3670         "DON'T use WriteRawNamedPipe (pipe)"
3671 };
3672 static const true_false_string tfs_write_mode_message_start = {
3673         "This is the START of a MESSAGE (pipe)",
3674         "This is NOT the start of a message (pipe)"
3675 };
3676 static const true_false_string tfs_write_mode_connectionless = {
3677         "CONNECTIONLESS mode requested",
3678         "Connectionless mode NOT requested"
3679 };
3680 static int
3681 dissect_write_mode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, int bm)
3682 {
3683         guint16 mask;
3684         proto_item *item = NULL;
3685         proto_tree *tree = NULL;
3686
3687         mask = tvb_get_letohs(tvb, offset);
3688
3689         if(parent_tree){
3690                 item = proto_tree_add_text(parent_tree, tvb, offset, 2,
3691                         "Write Mode: 0x%04x", mask);
3692                 tree = proto_item_add_subtree(item, ett_smb_rawmode);
3693         }
3694
3695         if(bm&0x0080){
3696                 proto_tree_add_boolean(tree, hf_smb_write_mode_connectionless,
3697                         tvb, offset, 2, mask);
3698         }
3699         if(bm&0x0008){
3700                 proto_tree_add_boolean(tree, hf_smb_write_mode_message_start,
3701                         tvb, offset, 2, mask);
3702         }
3703         if(bm&0x0004){
3704                 proto_tree_add_boolean(tree, hf_smb_write_mode_raw,
3705                         tvb, offset, 2, mask);
3706         }
3707         if(bm&0x0002){
3708                 proto_tree_add_boolean(tree, hf_smb_write_mode_return_remaining,
3709                         tvb, offset, 2, mask);
3710         }
3711         if(bm&0x0001){
3712                 proto_tree_add_boolean(tree, hf_smb_write_mode_write_through,
3713                         tvb, offset, 2, mask);
3714         }
3715
3716         offset += 2;
3717         return offset;
3718 }
3719
3720 static int
3721 dissect_write_raw_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3722 {
3723         guint32 to;
3724         guint16 datalen=0, bc, fid;
3725         guint8 wc;
3726
3727         WORD_COUNT;
3728
3729         /* fid */
3730         fid = tvb_get_letohs(tvb, offset);
3731         add_fid(tvb, pinfo, tree, offset, 2, fid);
3732         offset += 2;
3733
3734         /* total data length */
3735         proto_tree_add_item(tree, hf_smb_total_data_len, tvb, offset, 2, TRUE);
3736         offset += 2;
3737
3738         /* 2 reserved bytes */
3739         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
3740         offset += 2;
3741
3742         /* offset */
3743         proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
3744         offset += 4;
3745
3746         /* timeout */
3747         to = tvb_get_letohl(tvb, offset);
3748         proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: %s", time_msecs_to_str(to));
3749         offset += 4;
3750
3751         /* mode */
3752         offset = dissect_write_mode(tvb, pinfo, tree, offset, 0x0003);
3753
3754         /* 4 reserved bytes */
3755         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
3756         offset += 4;
3757
3758         /* data len */
3759         datalen = tvb_get_letohs(tvb, offset);
3760         proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, datalen);
3761         offset += 2;
3762
3763         /* data offset */
3764         proto_tree_add_item(tree, hf_smb_data_offset, tvb, offset, 2, TRUE);
3765         offset += 2;
3766
3767         BYTE_COUNT;
3768
3769         /* file data */
3770         /* XXX - use the data offset to determine where the data starts? */
3771         offset = dissect_file_data(tvb, pinfo, tree, offset, bc, datalen);
3772         bc = 0;
3773
3774         END_OF_SMB
3775
3776         return offset;
3777 }
3778  
3779 static int
3780 dissect_write_raw_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3781 {
3782         guint8 wc;
3783         guint16 bc;
3784
3785         WORD_COUNT;
3786
3787         /* remaining */
3788         proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
3789         offset += 2;
3790
3791         BYTE_COUNT;
3792
3793         END_OF_SMB
3794
3795         return offset;
3796 }
3797
3798 static int
3799 dissect_write_mpx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3800 {
3801         guint32 to;
3802         guint16 datalen=0, bc, fid;
3803         guint8 wc;
3804
3805         WORD_COUNT;
3806
3807         /* fid */
3808         fid = tvb_get_letohs(tvb, offset);
3809         add_fid(tvb, pinfo, tree, offset, 2, fid);
3810         offset += 2;
3811
3812         /* total data length */
3813         proto_tree_add_item(tree, hf_smb_total_data_len, tvb, offset, 2, TRUE);
3814         offset += 2;
3815
3816         /* 2 reserved bytes */
3817         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
3818         offset += 2;
3819
3820         /* offset */
3821         proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
3822         offset += 4;
3823
3824         /* timeout */
3825         to = tvb_get_letohl(tvb, offset);
3826         proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: %s", time_msecs_to_str(to));
3827         offset += 4;
3828
3829         /* mode */
3830         offset = dissect_write_mode(tvb, pinfo, tree, offset, 0x0083);
3831
3832         /* request mask */
3833         proto_tree_add_item(tree, hf_smb_request_mask, tvb, offset, 4, TRUE);
3834         offset += 4;
3835         
3836         /* data len */
3837         datalen = tvb_get_letohs(tvb, offset);
3838         proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, datalen);
3839         offset += 2;
3840
3841         /* data offset */
3842         proto_tree_add_item(tree, hf_smb_data_offset, tvb, offset, 2, TRUE);
3843         offset += 2;
3844
3845         BYTE_COUNT;
3846
3847         /* file data */
3848         /* XXX - use the data offset to determine where the data starts? */
3849         offset = dissect_file_data(tvb, pinfo, tree, offset, bc, datalen);
3850         bc = 0;
3851
3852         END_OF_SMB
3853
3854         return offset;
3855 }
3856  
3857 static int
3858 dissect_write_mpx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3859 {
3860         guint8 wc;
3861         guint16 bc;
3862
3863         WORD_COUNT;
3864
3865         /* response mask */
3866         proto_tree_add_item(tree, hf_smb_response_mask, tvb, offset, 4, TRUE);
3867         offset += 4;
3868         
3869         BYTE_COUNT;
3870
3871         END_OF_SMB
3872
3873         return offset;
3874 }
3875
3876 static int
3877 dissect_sid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
3878 {
3879         guint8 wc;
3880         guint16 bc;
3881
3882         WORD_COUNT;
3883
3884         /* sid */
3885         proto_tree_add_item(tree, hf_smb_sid, tvb, offset, 2, TRUE);
3886         offset += 2;
3887
3888         BYTE_COUNT;
3889
3890         END_OF_SMB
3891
3892         return offset;
3893 }
3894
3895 static int
3896 dissect_search_resume_key(tvbuff_t *tvb, packet_info *pinfo,
3897     proto_tree *parent_tree, int offset, guint16 *bcp, gboolean *trunc)
3898 {
3899         proto_item *item = NULL;
3900         proto_tree *tree = NULL;
3901         int fn_len;
3902         const char *fn;
3903         char fname[11+1];
3904
3905         if(parent_tree){
3906                 item = proto_tree_add_text(parent_tree, tvb, offset, 21,
3907                         "Resume Key");
3908                 tree = proto_item_add_subtree(item, ett_smb_search_resume_key);
3909         }
3910
3911         /* reserved byte */
3912         CHECK_BYTE_COUNT_SUBR(1);
3913         proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
3914         COUNT_BYTES_SUBR(1);
3915
3916         /* file name */
3917         fn_len = 11;
3918         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
3919                 TRUE, TRUE, bcp);
3920         CHECK_STRING_SUBR(fn);
3921         /* ensure that it's null-terminated */
3922         strncpy(fname, fn, 11);
3923         fname[11] = '\0';
3924         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, 11,
3925                 fname);
3926         COUNT_BYTES_SUBR(fn_len);
3927
3928         /* server cookie */
3929         CHECK_BYTE_COUNT_SUBR(5);
3930         proto_tree_add_item(tree, hf_smb_resume_server_cookie, tvb, offset, 5, TRUE);
3931         COUNT_BYTES_SUBR(5);
3932
3933         /* client cookie */
3934         CHECK_BYTE_COUNT_SUBR(4);
3935         proto_tree_add_item(tree, hf_smb_resume_client_cookie, tvb, offset, 4, TRUE);
3936         COUNT_BYTES_SUBR(4);
3937
3938         *trunc = FALSE;
3939         return offset;
3940 }
3941
3942 static int
3943 dissect_search_dir_info(tvbuff_t *tvb, packet_info *pinfo,
3944     proto_tree *parent_tree, int offset, guint16 *bcp, gboolean *trunc)
3945 {
3946         proto_item *item = NULL;
3947         proto_tree *tree = NULL;
3948         int fn_len;
3949         const char *fn;
3950         char fname[13+1];
3951
3952         if(parent_tree){
3953                 item = proto_tree_add_text(parent_tree, tvb, offset, 46,
3954                         "Directory Information");
3955                 tree = proto_item_add_subtree(item, ett_smb_search_dir_info);
3956         }
3957
3958         /* resume key */
3959         offset = dissect_search_resume_key(tvb, pinfo, tree, offset, bcp, trunc);
3960         if (*trunc)
3961                 return offset;
3962
3963         /* File Attributes */
3964         CHECK_BYTE_COUNT_SUBR(1);
3965         offset = dissect_dir_info_file_attributes(tvb, pinfo, tree, offset);
3966         *bcp -= 1;
3967
3968         /* last write time */
3969         CHECK_BYTE_COUNT_SUBR(4);
3970         offset = dissect_smb_datetime(tvb, pinfo, tree, offset,
3971                 hf_smb_last_write_time,
3972                 hf_smb_last_write_dos_date, hf_smb_last_write_dos_time,
3973                 TRUE);
3974         *bcp -= 4;
3975
3976         /* File Size */
3977         CHECK_BYTE_COUNT_SUBR(4);
3978         proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
3979         COUNT_BYTES_SUBR(4);
3980
3981         /* file name */
3982         fn_len = 13;
3983         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
3984                 TRUE, TRUE, bcp);
3985         CHECK_STRING_SUBR(fn);
3986         /* ensure that it's null-terminated */
3987         strncpy(fname, fn, 13);
3988         fname[13] = '\0';
3989         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
3990                 fname);
3991         COUNT_BYTES_SUBR(fn_len);
3992
3993         *trunc = FALSE;
3994         return offset;
3995 }
3996
3997
3998 static int
3999 dissect_search_dir_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
4000 {
4001         int fn_len;
4002         const char *fn;
4003         guint16 rkl;
4004         guint8 wc;
4005         guint16 bc;
4006         gboolean trunc;
4007
4008         WORD_COUNT;
4009
4010         /* max count */
4011         proto_tree_add_item(tree, hf_smb_max_count, tvb, offset, 2, TRUE);
4012         offset += 2;
4013
4014         /* Search Attributes */
4015         offset = dissect_search_attributes(tvb, pinfo, tree, offset);
4016
4017         BYTE_COUNT;
4018
4019         /* buffer format */
4020         CHECK_BYTE_COUNT(1);
4021         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
4022         COUNT_BYTES(1);
4023
4024         /* file name */
4025         fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
4026                 TRUE, FALSE, &bc);
4027         if (fn == NULL)
4028                 goto endofcommand;
4029         proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
4030                 fn);
4031         COUNT_BYTES(fn_len);
4032
4033         if (check_col(pinfo->cinfo, COL_INFO)) {
4034                 col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s", fn);
4035         }
4036
4037         /* buffer format */
4038         CHECK_BYTE_COUNT(1);
4039         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
4040         COUNT_BYTES(1);
4041
4042         /* resume key length */
4043         CHECK_BYTE_COUNT(2);
4044         rkl = tvb_get_letohs(tvb, offset);
4045         proto_tree_add_uint(tree, hf_smb_resume_key_len, tvb, offset, 2, rkl);
4046         COUNT_BYTES(2);
4047
4048         /* resume key */
4049         if(rkl){
4050                 offset = dissect_search_resume_key(tvb, pinfo, tree, offset,
4051                     &bc, &trunc);
4052                 if (trunc)
4053                         goto endofcommand;
4054         }
4055
4056         END_OF_SMB
4057
4058         return offset;
4059 }
4060
4061 static int
4062 dissect_search_dir_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
4063 {
4064         guint16 count=0;
4065         guint8 wc;
4066         guint16 bc;
4067         gboolean trunc;
4068
4069         WORD_COUNT;
4070
4071         /* count */
4072         count = tvb_get_letohs(tvb, offset);
4073         proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, count);
4074         offset += 2;
4075
4076         BYTE_COUNT;
4077
4078         /* buffer format */
4079         CHECK_BYTE_COUNT(1);
4080         proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
4081         COUNT_BYTES(1);
4082
4083         /* data len */
4084         CHECK_BYTE_COUNT(2);
4085         proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
4086         COUNT_BYTES(2);
4087
4088         while(count--){
4089                 offset = dissect_search_dir_info(tvb, pinfo, tree, offset,
4090                     &bc, &trunc);
4091                 if (trunc)
4092                &n