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