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