xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_open_andx.c (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
24  */
25 
26 #include <smbsrv/smb_kproto.h>
27 #include <smbsrv/smb_fsops.h>
28 #include <smbsrv/smb_vops.h>
29 
30 int smb_open_dsize_check = 0;
31 
32 /*
33  *  Client Request                     Description
34  *  ================================== =================================
35  *
36  *  UCHAR WordCount;                   Count of parameter words = 15
37  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF =
38  *                                      none
39  *  UCHAR AndXReserved;                Reserved (must be 0)
40  *  USHORT AndXOffset;                 Offset to next command WordCount
41  *  USHORT Flags;                      Additional information: bit set-
42  *                                      0 - return additional info
43  *                                      1 - exclusive oplock requested
44  *                                      2 - batch oplock requested
45  *  USHORT DesiredAccess;              File open mode
46  *  USHORT SearchAttributes;
47  *  USHORT FileAttributes;
48  *  UTIME CreationTime;                Creation timestamp for file if it
49  *                                      gets created
50  *  USHORT OpenFunction;               Action to take if file exists
51  *  ULONG AllocationSize;              Bytes to reserve on create or
52  *                                      truncate
53  *  ULONG Reserved[2];                 Must be 0
54  *  USHORT ByteCount;                  Count of data bytes;    min = 1
55  *  UCHAR BufferFormat                 0x04
56  *  STRING FileName;
57  *
58  *  Server Response                    Description
59  *  ================================== =================================
60  *
61  *  UCHAR WordCount;                   Count of parameter words = 15
62  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF =
63  *                                      none
64  *  UCHAR AndXReserved;                Reserved (must be 0)
65  *  USHORT AndXOffset;                 Offset to next command WordCount
66  *  USHORT Fid;                        File handle
67  *  USHORT FileAttributes;
68  *  UTIME LastWriteTime;
69  *  ULONG DataSize;                    Current file size
70  *  USHORT GrantedAccess;              Access permissions actually
71  *                                      allowed
72  *  USHORT FileType;                   Type of file opened
73  *  USHORT DeviceState;                State of the named pipe
74  *  USHORT Action;                     Action taken
75  *  ULONG ServerFid;                   Server unique file id
76  *  USHORT Reserved;                   Reserved (must be 0)
77  *  USHORT ByteCount;                  Count of data bytes = 0
78  *
79  * DesiredAccess describes the access the client desires for the file (see
80  * section 3.6 -  Access Mode Encoding).
81  *
82  * OpenFunction specifies the action to be taken depending on whether or
83  * not the file exists (see section 3.8 -  Open Function Encoding).  Action
84  *
85  * in the response specifies the action as a result of the Open request
86  * (see section 3.9 -  Open Action Encoding).
87  *
88  * SearchAttributes indicates the attributes that the file must have to be
89  * found while searching to see if it exists.  The encoding of this field
90  * is described in the "File Attribute Encoding" section elsewhere in this
91  * document.  If SearchAttributes is zero then only normal files are
92  * returned.  If the system file, hidden or directory attributes are
93  * specified then the search is inclusive -- both the specified type(s) of
94  * files and normal files are returned.
95  *
96  * FileType returns the kind of resource actually opened:
97  *
98  *  Name                       Value  Description
99  *  ========================== ====== ==================================
100  *
101  *  FileTypeDisk               0      Disk file or directory as defined
102  *                                     in the attribute field
103  *  FileTypeByteModePipe       1      Named pipe in byte mode
104  *  FileTypeMessageModePipe    2      Named pipe in message mode
105  *  FileTypePrinter            3      Spooled printer
106  *  FileTypeUnknown            0xFFFF Unrecognized resource type
107  *
108  * If bit0 of Flags is clear, the FileAttributes, LastWriteTime, DataSize,
109  * FileType, and DeviceState have indeterminate values in the response.
110  *
111  * This SMB can request an oplock on the opened file.  Oplocks are fully
112  * described in the "Oplocks" section elsewhere in this document, and there
113  * is also discussion of oplocks in the SMB_COM_LOCKING_ANDX SMB
114  * description.  Bit1 and bit2 of the Flags field are used to request
115  * oplocks during open.
116  *
117  * The following SMBs may follow SMB_COM_OPEN_ANDX:
118  *
119  *    SMB_COM_READ    SMB_COM_READ_ANDX
120  *    SMB_COM_IOCTL
121  */
122 
123 /*
124  * This message is sent to obtain a file handle for a data file.  This
125  * returned Fid is used in subsequent client requests such as read, write,
126  * close, etc.
127  *
128  * Client Request                     Description
129  * ================================== =================================
130  *
131  * UCHAR WordCount;                   Count of parameter words = 2
132  * USHORT DesiredAccess;              Mode - read/write/share
133  * USHORT SearchAttributes;
134  * USHORT ByteCount;                  Count of data bytes;    min = 2
135  * UCHAR BufferFormat;                0x04
136  * STRING FileName[];                 File name
137  *
138  * FileName is the fully qualified file name, relative to the root of the
139  * share specified in the Tid field of the SMB header.  If Tid in the SMB
140  * header refers to a print share, this SMB creates a new file which will
141  * be spooled to the printer when closed.  In this case, FileName is
142  * ignored.
143  *
144  * SearchAttributes specifies the type of file desired.  The encoding is
145  * described in the "File Attribute Encoding" section.
146  *
147  * DesiredAccess controls the mode under which the file is opened, and the
148  * file will be opened only if the client has the appropriate permissions.
149  * The encoding of DesiredAccess is discussed in the section entitled
150  * "Access Mode Encoding".
151  *
152  * Server Response                    Description
153  * ================================== =================================
154  *
155  * UCHAR WordCount;                   Count of parameter words = 7
156  * USHORT Fid;                        File handle
157  * USHORT FileAttributes;             Attributes of opened file
158  * UTIME LastWriteTime;               Time file was last written
159  * ULONG DataSize;                    File size
160  * USHORT GrantedAccess;              Access allowed
161  * USHORT ByteCount;                  Count of data bytes = 0
162  *
163  * Fid is the handle value which should be used for subsequent file
164  * operations.
165  *
166  * FileAttributes specifies the type of file obtained.  The encoding is
167  * described in the "File Attribute Encoding" section.
168  *
169  * GrantedAccess indicates the access permissions actually allowed, and may
170  * have one of the following values:
171  *
172  *    0  read-only
173  *    1  write-only
174  *    2 read/write
175  *
176  * File Handles (Fids) are scoped per client.  A Pid may reference any Fid
177  * established by itself or any other Pid on the client (so far as the
178  * server is concerned).  The actual accesses allowed through the Fid
179  * depends on the open and deny modes specified when the file was opened
180  * (see below).
181  *
182  * The MS-DOS compatibility mode of file open provides exclusion at the
183  * client level.  A file open in compatibility mode may be opened (also in
184  * compatibility mode) any number of times for any combination of reading
185  * and writing (subject to the user's permissions) by any Pid on the same
186  * client.  If the first client has the file open for writing, then the
187  * file may not be opened in any way by any other client.  If the first
188  * client has the file open only for reading, then other clients may open
189  * the file, in compatibility mode, for reading..  The above
190  * notwithstanding, if the filename has an extension of .EXE, .DLL, .SYM,
191  * or .COM other clients are permitted to open the file regardless of
192  * read/write open modes of other compatibility mode opens.  However, once
193  * multiple clients have the file open for reading, no client is permitted
194  * to open the file for writing and no other client may open the file in
195  * any mode other than compatibility mode.
196  *
197  * The other file exclusion modes (Deny read/write, Deny write, Deny read,
198  * Deny none) provide exclusion at the file level.  A file opened in any
199  * "Deny" mode may be opened again only for the accesses allowed by the
200  * Deny mode (subject to the user's permissions).  This is true regardless
201  * of the identity of the second opener -a different client, a Pid from the
202  * same client, or the Pid that already has the file open.  For example, if
203  * a file is open in "Deny write" mode a second open may only obtain read
204  * permission to the file.
205  *
206  * Although Fids are available to all Pids on a client, Pids other than the
207  * owner may not have the full access rights specified in the open mode by
208  * the Fid's creator.  If the open creating the Fid specified a deny mode,
209  * then any Pid using the Fid, other than the creating Pid, will have only
210  * those access rights determined by "anding" the open mode rights and the
211  * deny mode rights, i.e., the deny mode is checked on all file accesses.
212  * For example, if a file is opened for Read/Write in Deny write mode, then
213  * other clients may only read the file and cannot write; if a file is
214  * opened for Read in Deny read mode, then the other clients can neither
215  * read nor write the file.
216  */
217 
218 smb_sdrc_t
219 smb_pre_open(smb_request_t *sr)
220 {
221 	struct open_param *op = &sr->arg.open;
222 	int rc;
223 
224 	bzero(op, sizeof (sr->arg.open));
225 
226 	rc = smbsr_decode_vwv(sr, "ww", &op->omode, &op->fqi.fq_sattr);
227 	if (rc == 0)
228 		rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path);
229 
230 	DTRACE_SMB_START(op__Open, smb_request_t *, sr); /* arg.open */
231 
232 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
233 }
234 
235 void
236 smb_post_open(smb_request_t *sr)
237 {
238 	DTRACE_SMB_DONE(op__Open, smb_request_t *, sr);
239 }
240 
241 smb_sdrc_t
242 smb_com_open(smb_request_t *sr)
243 {
244 	struct open_param *op = &sr->arg.open;
245 	smb_ofile_t *of;
246 	uint32_t mtime_sec;
247 	uint32_t status;
248 	uint16_t file_attr;
249 	int rc;
250 
251 	op->desired_access = smb_omode_to_amask(op->omode);
252 	op->share_access = smb_denymode_to_sharemode(op->omode,
253 	    op->fqi.fq_path.pn_path);
254 	op->crtime.tv_sec = op->crtime.tv_nsec = 0;
255 	op->create_disposition = FILE_OPEN;
256 	op->create_options = FILE_NON_DIRECTORY_FILE;
257 	if (op->omode & SMB_DA_WRITE_THROUGH)
258 		op->create_options |= FILE_WRITE_THROUGH;
259 
260 	if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
261 		if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
262 			op->op_oplock_level = SMB_OPLOCK_BATCH;
263 		else
264 			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
265 	} else {
266 		op->op_oplock_level = SMB_OPLOCK_NONE;
267 	}
268 
269 	if (smb_open_dsize_check && op->dsize > UINT_MAX) {
270 		smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
271 		return (SDRC_ERROR);
272 	}
273 
274 	/*
275 	 * The real open call.   Note: this gets attributes into
276 	 * op->fqi.fq_fattr (SMB_AT_ALL).  We need those below.
277 	 */
278 	status = smb_common_open(sr);
279 	if (status != NT_STATUS_SUCCESS) {
280 		smbsr_status(sr, status, 0, 0);
281 		return (SDRC_ERROR);
282 	}
283 	if (op->op_oplock_level != SMB_OPLOCK_NONE) {
284 		/* Oplock req. in op->op_oplock_level etc. */
285 		smb1_oplock_acquire(sr, B_FALSE);
286 	}
287 
288 	/*
289 	 * NB: after the above smb_common_open() success,
290 	 * we have a handle allocated (sr->fid_ofile).
291 	 * If we don't return success, we must close it.
292 	 */
293 	of = sr->fid_ofile;
294 
295 	if (op->op_oplock_level == SMB_OPLOCK_NONE) {
296 		sr->smb_flg &=
297 		    ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY);
298 	}
299 
300 	file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
301 	mtime_sec = smb_time_gmt_to_local(sr,
302 	    op->fqi.fq_fattr.sa_vattr.va_mtime.tv_sec);
303 
304 	rc = smbsr_encode_result(sr, 7, 0, "bwwllww",
305 	    7,
306 	    sr->smb_fid,
307 	    file_attr,
308 	    mtime_sec,
309 	    (uint32_t)op->dsize,
310 	    op->omode,
311 	    (uint16_t)0);	/* bcc */
312 
313 	if (rc == 0)
314 		return (SDRC_SUCCESS);
315 
316 	smb_ofile_close(of, 0);
317 	return (SDRC_ERROR);
318 }
319 
320 int smb_openx_enable_extended_response = 1;
321 
322 /*
323  * smb_pre_open_andx
324  * For compatibility with windows servers, the search attributes
325  * specified in the request are ignored.
326  */
327 smb_sdrc_t
328 smb_pre_open_andx(smb_request_t *sr)
329 {
330 	struct open_param *op = &sr->arg.open;
331 	uint16_t openx_flags;
332 	uint32_t alloc_size;
333 	uint32_t creation_time;
334 	uint16_t file_attr, sattr;
335 	int rc;
336 
337 	bzero(op, sizeof (sr->arg.open));
338 
339 	rc = smbsr_decode_vwv(sr, "b.wwwwwlwll4.", &sr->andx_com,
340 	    &sr->andx_off, &openx_flags, &op->omode, &sattr,
341 	    &file_attr, &creation_time, &op->ofun, &alloc_size, &op->timeo);
342 
343 	if (rc == 0) {
344 		rc = smbsr_decode_data(sr, "%u", sr, &op->fqi.fq_path.pn_path);
345 
346 		op->dattr = file_attr;
347 		op->dsize = alloc_size;
348 
349 		/*
350 		 * The openx_flags use some "extended" flags that
351 		 * happen to match some of the NtCreateX flags.
352 		 */
353 		if (openx_flags & NT_CREATE_FLAG_REQUEST_OPBATCH)
354 			op->op_oplock_level = SMB_OPLOCK_BATCH;
355 		else if (openx_flags & NT_CREATE_FLAG_REQUEST_OPLOCK)
356 			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
357 		else
358 			op->op_oplock_level = SMB_OPLOCK_NONE;
359 		if (openx_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE)
360 			op->nt_flags |= NT_CREATE_FLAG_EXTENDED_RESPONSE;
361 
362 		if ((creation_time != 0) && (creation_time != UINT_MAX))
363 			op->crtime.tv_sec =
364 			    smb_time_local_to_gmt(sr, creation_time);
365 		op->crtime.tv_nsec = 0;
366 
367 		op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
368 	}
369 
370 	DTRACE_SMB_START(op__OpenX, smb_request_t *, sr); /* arg.open */
371 
372 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
373 }
374 
375 void
376 smb_post_open_andx(smb_request_t *sr)
377 {
378 	DTRACE_SMB_DONE(op__OpenX, smb_request_t *, sr);
379 }
380 
381 smb_sdrc_t
382 smb_com_open_andx(smb_request_t *sr)
383 {
384 	struct open_param	*op = &sr->arg.open;
385 	smb_attr_t		*ap = &op->fqi.fq_fattr;
386 	smb_ofile_t		*of;
387 	uint32_t		status;
388 	uint32_t		mtime_sec;
389 	uint16_t		file_attr;
390 	int rc;
391 
392 	op->desired_access = smb_omode_to_amask(op->omode);
393 	op->share_access = smb_denymode_to_sharemode(op->omode,
394 	    op->fqi.fq_path.pn_path);
395 
396 	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
397 		smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
398 		return (SDRC_ERROR);
399 	}
400 
401 	op->create_options = FILE_NON_DIRECTORY_FILE;
402 	if (op->omode & SMB_DA_WRITE_THROUGH)
403 		op->create_options |= FILE_WRITE_THROUGH;
404 
405 	if (smb_open_dsize_check && op->dsize > UINT_MAX) {
406 		smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
407 		return (SDRC_ERROR);
408 	}
409 
410 	status = smb_common_open(sr);
411 	if (status != NT_STATUS_SUCCESS) {
412 		smbsr_status(sr, status, 0, 0);
413 		return (SDRC_ERROR);
414 	}
415 	if (op->op_oplock_level != SMB_OPLOCK_NONE) {
416 		/* Oplock req. in op->op_oplock_level etc. */
417 		smb1_oplock_acquire(sr, B_FALSE);
418 	}
419 
420 	/*
421 	 * NB: after the above smb_common_open() success,
422 	 * we have a handle allocated (sr->fid_ofile).
423 	 * If we don't return success, we must close it.
424 	 */
425 	of = sr->fid_ofile;
426 
427 	if (op->op_oplock_level != SMB_OPLOCK_NONE)
428 		op->action_taken |= SMB_OACT_OPLOCK;
429 	else
430 		op->action_taken &= ~SMB_OACT_OPLOCK;
431 
432 	file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
433 	mtime_sec = smb_time_gmt_to_local(sr, ap->sa_vattr.va_mtime.tv_sec);
434 
435 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
436 	case STYPE_DISKTREE:
437 	case STYPE_PRINTQ:
438 		break;
439 
440 	case STYPE_IPC:
441 		mtime_sec = 0;
442 		break;
443 
444 	default:
445 		smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
446 		    ERRDOS, ERROR_INVALID_FUNCTION);
447 		goto errout;
448 	}
449 
450 	if ((op->nt_flags & NT_CREATE_FLAG_EXTENDED_RESPONSE) != 0 &&
451 	    smb_openx_enable_extended_response != 0) {
452 		uint32_t MaxAccess = 0;
453 		if (of->f_node != NULL) {
454 			smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess);
455 		}
456 		MaxAccess |= of->f_granted_access;
457 
458 		rc = smbsr_encode_result(
459 		    sr, 19, 0, "bb.wwwllwwwwl2.llw",
460 		    19,		/* word count	   (b) */
461 		    sr->andx_com,		/* (b.) */
462 		    VAR_BCC,	/* andx offset	   (w) */
463 		    sr->smb_fid,		/* (w) */
464 		    file_attr,			/* (w) */
465 		    mtime_sec,			/* (l) */
466 		    (uint32_t)op->dsize,	/* (l) */
467 		    op->omode,			/* (w) */
468 		    op->ftype,			/* (w) */
469 		    op->devstate,		/* (w) */
470 		    op->action_taken,		/* (w) */
471 		    0,		/* legacy fileid   (l) */
472 		    /* reserved			  (2.) */
473 		    MaxAccess,			/* (l) */
474 		    0,		/* guest access	   (l) */
475 		    0);		/* byte count	   (w) */
476 
477 	} else {
478 		rc = smbsr_encode_result(
479 		    sr, 15, 0, "bb.wwwllwwwwl2.w",
480 		    15,		/* word count	   (b) */
481 		    sr->andx_com,		/* (b.) */
482 		    VAR_BCC,	/* andx offset	   (w) */
483 		    sr->smb_fid,		/* (w) */
484 		    file_attr,			/* (w) */
485 		    mtime_sec,			/* (l) */
486 		    (uint32_t)op->dsize,	/* (l) */
487 		    op->omode,			/* (w) */
488 		    op->ftype,			/* (w) */
489 		    op->devstate,		/* (w) */
490 		    op->action_taken,		/* (w) */
491 		    0,		/* legacy fileid   (l) */
492 		    /* reserved			  (2.) */
493 		    0);		/* byte count	   (w) */
494 	}
495 
496 	if (rc == 0)
497 		return (SDRC_SUCCESS);
498 
499 errout:
500 	smb_ofile_close(of, 0);
501 	return (SDRC_ERROR);
502 }
503 
504 smb_sdrc_t
505 smb_com_trans2_open2(smb_request_t *sr, smb_xa_t *xa)
506 {
507 	struct open_param *op = &sr->arg.open;
508 	uint32_t	creation_time;
509 	uint32_t	alloc_size;
510 	uint32_t	ea_list_size;
511 	uint16_t	flags;
512 	uint16_t	file_attr;
513 	uint32_t	status;
514 	int		rc;
515 
516 	bzero(op, sizeof (sr->arg.open));
517 
518 	rc = smb_mbc_decodef(&xa->req_param_mb, "%wwwwlwl10.u",
519 	    sr, &flags, &op->omode, &op->fqi.fq_sattr, &file_attr,
520 	    &creation_time, &op->ofun, &alloc_size, &op->fqi.fq_path.pn_path);
521 	if (rc != 0)
522 		return (SDRC_ERROR);
523 
524 	/*
525 	 * The data part of this transaction may contain an EA list.
526 	 * See: SMB_FEA_LIST ExtendedAttributeList
527 	 *
528 	 * If we find a non-empty EA list payload, return the special
529 	 * error that tells the caller this FS does not suport EAs.
530 	 *
531 	 * Note: the first word is the size of the whole data segment,
532 	 * INCLUDING the size of that length word.  That means if
533 	 * the length word specifies a size less than four, it's
534 	 * invalid (and probably a client trying something fishy).
535 	 */
536 	rc = smb_mbc_decodef(&xa->req_data_mb, "l", &ea_list_size);
537 	if (rc == 0 && ea_list_size > 4) {
538 		smbsr_status(sr, NT_STATUS_EAS_NOT_SUPPORTED, 0, 0);
539 		return (SDRC_ERROR);
540 	}
541 
542 	if ((creation_time != 0) && (creation_time != UINT_MAX))
543 		op->crtime.tv_sec = smb_time_local_to_gmt(sr, creation_time);
544 	op->crtime.tv_nsec = 0;
545 
546 	op->dattr = file_attr;
547 	op->dsize = alloc_size;
548 	op->create_options = FILE_NON_DIRECTORY_FILE;
549 
550 	op->desired_access = smb_omode_to_amask(op->omode);
551 	op->share_access = smb_denymode_to_sharemode(op->omode,
552 	    op->fqi.fq_path.pn_path);
553 
554 	op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
555 	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION)
556 		op->create_disposition = FILE_CREATE;
557 
558 	if (op->omode & SMB_DA_WRITE_THROUGH)
559 		op->create_options |= FILE_WRITE_THROUGH;
560 
561 	if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
562 		if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
563 			op->op_oplock_level = SMB_OPLOCK_BATCH;
564 		else
565 			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
566 	} else {
567 		op->op_oplock_level = SMB_OPLOCK_NONE;
568 	}
569 
570 	status = smb_common_open(sr);
571 	if (status != NT_STATUS_SUCCESS) {
572 		smbsr_status(sr, status, 0, 0);
573 		return (SDRC_ERROR);
574 	}
575 	if (op->op_oplock_level != SMB_OPLOCK_NONE) {
576 		/* Oplock req. in op->op_oplock_level etc. */
577 		smb1_oplock_acquire(sr, B_FALSE);
578 	}
579 
580 	if (op->op_oplock_level != SMB_OPLOCK_NONE)
581 		op->action_taken |= SMB_OACT_OPLOCK;
582 	else
583 		op->action_taken &= ~SMB_OACT_OPLOCK;
584 
585 	file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
586 
587 	if (STYPE_ISIPC(sr->tid_tree->t_res_type))
588 		op->dsize = 0;
589 
590 	(void) smb_mbc_encodef(&xa->rep_param_mb, "wwllwwwwlwl",
591 	    sr->smb_fid,
592 	    file_attr,
593 	    (uint32_t)0,	/* creation time */
594 	    (uint32_t)op->dsize,
595 	    op->omode,
596 	    op->ftype,
597 	    op->devstate,
598 	    op->action_taken,
599 	    op->fileid,
600 	    (uint16_t)0,	/* EA error offset */
601 	    (uint32_t)0);	/* EA list length */
602 
603 	return (SDRC_SUCCESS);
604 }
605