xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c (revision 8622ec4569457733001d4982ef7f5b44427069be)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22cb174861Sjoyce mcintosh  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
235fd03bc0SGordon Ross  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
24da6c28aaSamw  */
25da6c28aaSamw 
26bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
27da6c28aaSamw #include <smbsrv/winioctl.h>
28da6c28aaSamw 
29e3f2c991SKeyur Desai 
30e3f2c991SKeyur Desai static uint32_t smb_nt_trans_ioctl_noop(smb_request_t *, smb_xa_t *);
31fd9ee8b5Sjoyce mcintosh static uint32_t smb_nt_trans_ioctl_invalid_parm(smb_request_t *, smb_xa_t *);
32fd9ee8b5Sjoyce mcintosh static uint32_t smb_nt_trans_ioctl_set_sparse(smb_request_t *, smb_xa_t *);
33fd9ee8b5Sjoyce mcintosh static uint32_t smb_nt_trans_ioctl_query_alloc_ranges(smb_request_t *,
3489dc44ceSjose borrego     smb_xa_t *);
35fd9ee8b5Sjoyce mcintosh static uint32_t smb_nt_trans_ioctl_set_zero_data(smb_request_t *, smb_xa_t *);
36da6c28aaSamw 
37da6c28aaSamw /*
38e3f2c991SKeyur Desai  * This table defines the list of FSCTL values for which we'll
39e3f2c991SKeyur Desai  * call a funtion to perform specific processing.
40cb174861Sjoyce mcintosh  *
41cb174861Sjoyce mcintosh  * Note: If support is added for FSCTL_SET_ZERO_DATA, it must break
42cb174861Sjoyce mcintosh  * any oplocks on the file to none:
43cb174861Sjoyce mcintosh  *   smb_oplock_break(sr, node, SMB_OPLOCK_BREAK_TO_NONE);
44da6c28aaSamw  */
45*8622ec45SGordon Ross static const struct {
46da6c28aaSamw 	uint32_t fcode;
4789dc44ceSjose borrego 	uint32_t (*ioctl_func)(smb_request_t *sr, smb_xa_t *xa);
48da6c28aaSamw } ioctl_ret_tbl[] = {
4989dc44ceSjose borrego 	{ FSCTL_GET_OBJECT_ID, smb_nt_trans_ioctl_invalid_parm },
50fd9ee8b5Sjoyce mcintosh 	{ FSCTL_QUERY_ALLOCATED_RANGES, smb_nt_trans_ioctl_query_alloc_ranges },
51fd9ee8b5Sjoyce mcintosh 	{ FSCTL_SET_ZERO_DATA, smb_nt_trans_ioctl_set_zero_data },
52e3f2c991SKeyur Desai 	{ FSCTL_SRV_ENUMERATE_SNAPSHOTS, smb_vss_ioctl_enumerate_snaps },
53fd9ee8b5Sjoyce mcintosh 	{ FSCTL_SET_SPARSE, smb_nt_trans_ioctl_set_sparse },
549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	{ FSCTL_FIND_FILES_BY_SID, smb_nt_trans_ioctl_noop }
55da6c28aaSamw };
56da6c28aaSamw 
57da6c28aaSamw /*
58da6c28aaSamw  * smb_nt_transact_ioctl
59da6c28aaSamw  *
60da6c28aaSamw  * This command allows device and file system control functions to be
61e3f2c991SKeyur Desai  * transferred transparently from client to server.
62da6c28aaSamw  *
63da6c28aaSamw  * Setup Words Encoding        Description
64da6c28aaSamw  * =========================== =========================================
65da6c28aaSamw  * ULONG FunctionCode;         NT device or file system control code
66da6c28aaSamw  * USHORT Fid;                 Handle for io or fs control. Unless BIT0
67da6c28aaSamw  *                             of ISFLAGS is set.
68da6c28aaSamw  * BOOLEAN IsFsctl;            Indicates whether the command is a device
69da6c28aaSamw  *                             control (FALSE) or a file system control
70da6c28aaSamw  *                             (TRUE).
71da6c28aaSamw  * UCHAR   IsFlags;            BIT0 - command is to be applied to share
72da6c28aaSamw  *                             root handle. Share must be a DFS share.
73da6c28aaSamw  *
74da6c28aaSamw  * Data Block Encoding         Description
75da6c28aaSamw  * =========================== =========================================
76da6c28aaSamw  * Data[ TotalDataCount ]      Passed to the Fsctl or Ioctl
77da6c28aaSamw  *
78da6c28aaSamw  * Server Response             Description
79da6c28aaSamw  * =========================== ==================================
80da6c28aaSamw  * SetupCount                  1
81da6c28aaSamw  * Setup[0]                    Length of information returned by
82da6c28aaSamw  *                             io or fs control.
83da6c28aaSamw  * DataCount                   Length of information returned by
84da6c28aaSamw  *                             io or fs control.
85da6c28aaSamw  * Data[ DataCount ]           The results of the io or fs control.
86da6c28aaSamw  */
877b59d02dSjb150015 smb_sdrc_t
8889dc44ceSjose borrego smb_nt_transact_ioctl(smb_request_t *sr, smb_xa_t *xa)
89da6c28aaSamw {
90e3f2c991SKeyur Desai 	uint32_t status = NT_STATUS_NOT_SUPPORTED;
91da6c28aaSamw 	uint32_t fcode;
92da6c28aaSamw 	unsigned char is_fsctl;
93da6c28aaSamw 	unsigned char is_flags;
94da6c28aaSamw 	int i;
95da6c28aaSamw 
963db3f65cSamw 	if (smb_mbc_decodef(&xa->req_setup_mb, "lwbb",
97fd9ee8b5Sjoyce mcintosh 	    &fcode, &sr->smb_fid, &is_fsctl, &is_flags) != 0) {
98dc20a302Sas200622 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
99faa1795aSjb150015 		return (SDRC_ERROR);
100da6c28aaSamw 	}
101da6c28aaSamw 
102e3f2c991SKeyur Desai 	/*
103e3f2c991SKeyur Desai 	 * Invoke handler if specified, otherwise the default
104e3f2c991SKeyur Desai 	 * behavior is to return NT_STATUS_NOT_SUPPORTED
105e3f2c991SKeyur Desai 	 */
1067b59d02dSjb150015 	for (i = 0; i < sizeof (ioctl_ret_tbl) / sizeof (ioctl_ret_tbl[0]);
107da6c28aaSamw 	    i++) {
108da6c28aaSamw 		if (ioctl_ret_tbl[i].fcode == fcode) {
10989dc44ceSjose borrego 			status = ioctl_ret_tbl[i].ioctl_func(sr, xa);
110da6c28aaSamw 			break;
111da6c28aaSamw 		}
112da6c28aaSamw 	}
113da6c28aaSamw 
1147b59d02dSjb150015 	if (status != NT_STATUS_SUCCESS) {
115dc20a302Sas200622 		smbsr_error(sr, status, 0, 0);
116faa1795aSjb150015 		return (SDRC_ERROR);
1177b59d02dSjb150015 	}
118da6c28aaSamw 
1193db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_param_mb, "l", 0);
120faa1795aSjb150015 	return (SDRC_SUCCESS);
121da6c28aaSamw }
12289dc44ceSjose borrego 
12389dc44ceSjose borrego /* ARGSUSED */
12489dc44ceSjose borrego static uint32_t
125e3f2c991SKeyur Desai smb_nt_trans_ioctl_noop(smb_request_t *sr, smb_xa_t *xa)
126e3f2c991SKeyur Desai {
127e3f2c991SKeyur Desai 	return (NT_STATUS_SUCCESS);
128e3f2c991SKeyur Desai }
129e3f2c991SKeyur Desai 
130e3f2c991SKeyur Desai /* ARGSUSED */
131e3f2c991SKeyur Desai static uint32_t
13289dc44ceSjose borrego smb_nt_trans_ioctl_invalid_parm(smb_request_t *sr, smb_xa_t *xa)
13389dc44ceSjose borrego {
13489dc44ceSjose borrego 	return (NT_STATUS_INVALID_PARAMETER);
13589dc44ceSjose borrego }
136fd9ee8b5Sjoyce mcintosh 
137fd9ee8b5Sjoyce mcintosh /*
138fd9ee8b5Sjoyce mcintosh  * smb_nt_trans_ioctl_set_sparse
139fd9ee8b5Sjoyce mcintosh  *
140fd9ee8b5Sjoyce mcintosh  * There may, or may not be a data block in this request.
141fd9ee8b5Sjoyce mcintosh  * If there IS a data block, the first byte is a boolean
142fd9ee8b5Sjoyce mcintosh  * specifying whether to set (non zero) or clear (zero)
143fd9ee8b5Sjoyce mcintosh  * the sparse attribute of the file.
144fd9ee8b5Sjoyce mcintosh  * If there is no data block, this indicates a request to
145fd9ee8b5Sjoyce mcintosh  * set the sparse attribute.
146fd9ee8b5Sjoyce mcintosh  */
147fd9ee8b5Sjoyce mcintosh static uint32_t
148fd9ee8b5Sjoyce mcintosh smb_nt_trans_ioctl_set_sparse(smb_request_t *sr, smb_xa_t *xa)
149fd9ee8b5Sjoyce mcintosh {
150fd9ee8b5Sjoyce mcintosh 	int		rc = 0;
151fd9ee8b5Sjoyce mcintosh 	uint8_t		set = 1;
1525fd03bc0SGordon Ross 	smb_ofile_t	*of;
153fd9ee8b5Sjoyce mcintosh 	smb_attr_t	attr;
154fd9ee8b5Sjoyce mcintosh 
155fd9ee8b5Sjoyce mcintosh 	if (SMB_TREE_IS_READONLY(sr))
156fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_ACCESS_DENIED);
157fd9ee8b5Sjoyce mcintosh 
158fd9ee8b5Sjoyce mcintosh 	if (STYPE_ISIPC(sr->tid_tree->t_res_type))
159fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_INVALID_PARAMETER);
160fd9ee8b5Sjoyce mcintosh 
161fd9ee8b5Sjoyce mcintosh 	smbsr_lookup_file(sr);
162fd9ee8b5Sjoyce mcintosh 	if (sr->fid_ofile == NULL)
163fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_INVALID_HANDLE);
164fd9ee8b5Sjoyce mcintosh 
165fd9ee8b5Sjoyce mcintosh 	if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) {
166fd9ee8b5Sjoyce mcintosh 		smbsr_release_file(sr);
167fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_INVALID_PARAMETER);
168fd9ee8b5Sjoyce mcintosh 	}
169fd9ee8b5Sjoyce mcintosh 
1705fd03bc0SGordon Ross 	of = sr->fid_ofile;
1715fd03bc0SGordon Ross 	if (smb_node_is_dir(of->f_node)) {
172fd9ee8b5Sjoyce mcintosh 		smbsr_release_file(sr);
173fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_INVALID_PARAMETER);
174fd9ee8b5Sjoyce mcintosh 	}
175fd9ee8b5Sjoyce mcintosh 
176fd9ee8b5Sjoyce mcintosh 	if (smbsr_decode_data_avail(sr)) {
177fd9ee8b5Sjoyce mcintosh 		if (smb_mbc_decodef(&xa->req_data_mb, "b", &set) != 0) {
178fd9ee8b5Sjoyce mcintosh 			smbsr_release_file(sr);
179fd9ee8b5Sjoyce mcintosh 			return (sr->smb_error.status);
180fd9ee8b5Sjoyce mcintosh 		}
181fd9ee8b5Sjoyce mcintosh 	}
182fd9ee8b5Sjoyce mcintosh 
1835fd03bc0SGordon Ross 	/*
1845fd03bc0SGordon Ross 	 * Using kcred because we just want the DOS attrs
1855fd03bc0SGordon Ross 	 * and don't want access errors for this.
1865fd03bc0SGordon Ross 	 */
187fd9ee8b5Sjoyce mcintosh 	bzero(&attr, sizeof (smb_attr_t));
188fd9ee8b5Sjoyce mcintosh 	attr.sa_mask = SMB_AT_DOSATTR;
189*8622ec45SGordon Ross 	rc = smb_node_getattr(sr, of->f_node, zone_kcred(), of, &attr);
1905fd03bc0SGordon Ross 	if (rc != 0) {
191fd9ee8b5Sjoyce mcintosh 		smbsr_errno(sr, rc);
192fd9ee8b5Sjoyce mcintosh 		smbsr_release_file(sr);
193fd9ee8b5Sjoyce mcintosh 		return (sr->smb_error.status);
194fd9ee8b5Sjoyce mcintosh 	}
195fd9ee8b5Sjoyce mcintosh 
196fd9ee8b5Sjoyce mcintosh 	attr.sa_mask = 0;
197fd9ee8b5Sjoyce mcintosh 	if ((set == 0) &&
198fd9ee8b5Sjoyce mcintosh 	    (attr.sa_dosattr & FILE_ATTRIBUTE_SPARSE_FILE)) {
199fd9ee8b5Sjoyce mcintosh 		attr.sa_dosattr &= ~FILE_ATTRIBUTE_SPARSE_FILE;
200fd9ee8b5Sjoyce mcintosh 		attr.sa_mask = SMB_AT_DOSATTR;
201fd9ee8b5Sjoyce mcintosh 	} else if ((set != 0) &&
202fd9ee8b5Sjoyce mcintosh 	    !(attr.sa_dosattr & FILE_ATTRIBUTE_SPARSE_FILE)) {
203fd9ee8b5Sjoyce mcintosh 		attr.sa_dosattr |= FILE_ATTRIBUTE_SPARSE_FILE;
204fd9ee8b5Sjoyce mcintosh 		attr.sa_mask = SMB_AT_DOSATTR;
205fd9ee8b5Sjoyce mcintosh 	}
206fd9ee8b5Sjoyce mcintosh 
207fd9ee8b5Sjoyce mcintosh 	if (attr.sa_mask != 0) {
2085fd03bc0SGordon Ross 		rc = smb_node_setattr(sr, of->f_node, of->f_cr, of, &attr);
209fd9ee8b5Sjoyce mcintosh 		if (rc != 0) {
210fd9ee8b5Sjoyce mcintosh 			smbsr_errno(sr, rc);
211fd9ee8b5Sjoyce mcintosh 			smbsr_release_file(sr);
212fd9ee8b5Sjoyce mcintosh 			return (sr->smb_error.status);
213fd9ee8b5Sjoyce mcintosh 		}
214fd9ee8b5Sjoyce mcintosh 	}
215fd9ee8b5Sjoyce mcintosh 
216fd9ee8b5Sjoyce mcintosh 	smbsr_release_file(sr);
217fd9ee8b5Sjoyce mcintosh 	return (NT_STATUS_SUCCESS);
218fd9ee8b5Sjoyce mcintosh }
219fd9ee8b5Sjoyce mcintosh 
220fd9ee8b5Sjoyce mcintosh /*
221fd9ee8b5Sjoyce mcintosh  * smb_nt_trans_ioctl_set_zero_data
222fd9ee8b5Sjoyce mcintosh  *
223fd9ee8b5Sjoyce mcintosh  * Check that the request is valid on the specified file.
224fd9ee8b5Sjoyce mcintosh  * The implementation is a noop.
225fd9ee8b5Sjoyce mcintosh  */
226fd9ee8b5Sjoyce mcintosh /* ARGSUSED */
227fd9ee8b5Sjoyce mcintosh static uint32_t
228fd9ee8b5Sjoyce mcintosh smb_nt_trans_ioctl_set_zero_data(smb_request_t *sr, smb_xa_t *xa)
229fd9ee8b5Sjoyce mcintosh {
230fd9ee8b5Sjoyce mcintosh 	smb_node_t *node;
231fd9ee8b5Sjoyce mcintosh 
232fd9ee8b5Sjoyce mcintosh 	if (SMB_TREE_IS_READONLY(sr))
233fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_ACCESS_DENIED);
234fd9ee8b5Sjoyce mcintosh 
235fd9ee8b5Sjoyce mcintosh 	if (STYPE_ISIPC(sr->tid_tree->t_res_type))
236fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_INVALID_PARAMETER);
237fd9ee8b5Sjoyce mcintosh 
238fd9ee8b5Sjoyce mcintosh 	smbsr_lookup_file(sr);
239fd9ee8b5Sjoyce mcintosh 	if (sr->fid_ofile == NULL)
240fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_INVALID_HANDLE);
241fd9ee8b5Sjoyce mcintosh 
242fd9ee8b5Sjoyce mcintosh 	if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) {
243fd9ee8b5Sjoyce mcintosh 		smbsr_release_file(sr);
244fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_INVALID_PARAMETER);
245fd9ee8b5Sjoyce mcintosh 	}
246fd9ee8b5Sjoyce mcintosh 
247fd9ee8b5Sjoyce mcintosh 	node = sr->fid_ofile->f_node;
248fd9ee8b5Sjoyce mcintosh 	if (smb_node_is_dir(node)) {
249fd9ee8b5Sjoyce mcintosh 		smbsr_release_file(sr);
250fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_INVALID_PARAMETER);
251fd9ee8b5Sjoyce mcintosh 	}
252fd9ee8b5Sjoyce mcintosh 
253fd9ee8b5Sjoyce mcintosh 	smbsr_release_file(sr);
254fd9ee8b5Sjoyce mcintosh 	return (NT_STATUS_SUCCESS);
255fd9ee8b5Sjoyce mcintosh }
256fd9ee8b5Sjoyce mcintosh 
257fd9ee8b5Sjoyce mcintosh /*
258fd9ee8b5Sjoyce mcintosh  * smb_nt_trans_ioctl_query_alloc_ranges
259fd9ee8b5Sjoyce mcintosh  *
260fd9ee8b5Sjoyce mcintosh  * Responds with either:
261fd9ee8b5Sjoyce mcintosh  * - no data if the file is zero size
262fd9ee8b5Sjoyce mcintosh  * - a single range containing the starting point and length requested
263fd9ee8b5Sjoyce mcintosh  */
264fd9ee8b5Sjoyce mcintosh static uint32_t
265fd9ee8b5Sjoyce mcintosh smb_nt_trans_ioctl_query_alloc_ranges(smb_request_t *sr, smb_xa_t *xa)
266fd9ee8b5Sjoyce mcintosh {
267fd9ee8b5Sjoyce mcintosh 	int		rc;
268fd9ee8b5Sjoyce mcintosh 	uint64_t	offset, len;
2695fd03bc0SGordon Ross 	smb_ofile_t	*of;
270fd9ee8b5Sjoyce mcintosh 	smb_attr_t	attr;
271fd9ee8b5Sjoyce mcintosh 
272fd9ee8b5Sjoyce mcintosh 	if (STYPE_ISIPC(sr->tid_tree->t_res_type))
273fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_INVALID_PARAMETER);
274fd9ee8b5Sjoyce mcintosh 
275fd9ee8b5Sjoyce mcintosh 	smbsr_lookup_file(sr);
276fd9ee8b5Sjoyce mcintosh 	if (sr->fid_ofile == NULL)
277fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_INVALID_HANDLE);
278fd9ee8b5Sjoyce mcintosh 
279fd9ee8b5Sjoyce mcintosh 	if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) {
280fd9ee8b5Sjoyce mcintosh 		smbsr_release_file(sr);
281fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_INVALID_PARAMETER);
282fd9ee8b5Sjoyce mcintosh 	}
283fd9ee8b5Sjoyce mcintosh 
2845fd03bc0SGordon Ross 	of = sr->fid_ofile;
2855fd03bc0SGordon Ross 	if (smb_node_is_dir(of->f_node)) {
286fd9ee8b5Sjoyce mcintosh 		smbsr_release_file(sr);
287fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_INVALID_PARAMETER);
288fd9ee8b5Sjoyce mcintosh 	}
289fd9ee8b5Sjoyce mcintosh 
290fd9ee8b5Sjoyce mcintosh 	/* If zero size file don't return any data */
291fd9ee8b5Sjoyce mcintosh 	bzero(&attr, sizeof (smb_attr_t));
292fd9ee8b5Sjoyce mcintosh 	attr.sa_mask = SMB_AT_SIZE;
2935fd03bc0SGordon Ross 	rc = smb_node_getattr(sr, of->f_node, of->f_cr, of, &attr);
2945fd03bc0SGordon Ross 	if (rc != 0) {
295fd9ee8b5Sjoyce mcintosh 		smbsr_errno(sr, rc);
296fd9ee8b5Sjoyce mcintosh 		smbsr_release_file(sr);
297fd9ee8b5Sjoyce mcintosh 		return (sr->smb_error.status);
298fd9ee8b5Sjoyce mcintosh 	}
299fd9ee8b5Sjoyce mcintosh 
300fd9ee8b5Sjoyce mcintosh 	if (attr.sa_vattr.va_size == 0) {
301fd9ee8b5Sjoyce mcintosh 		smbsr_release_file(sr);
302fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_SUCCESS);
303fd9ee8b5Sjoyce mcintosh 	}
304fd9ee8b5Sjoyce mcintosh 
305fd9ee8b5Sjoyce mcintosh 	if (smb_mbc_decodef(&xa->req_data_mb, "qq", &offset, &len) != 0) {
306fd9ee8b5Sjoyce mcintosh 		smbsr_release_file(sr);
307fd9ee8b5Sjoyce mcintosh 		return (sr->smb_error.status);
308fd9ee8b5Sjoyce mcintosh 	}
309fd9ee8b5Sjoyce mcintosh 
310fd9ee8b5Sjoyce mcintosh 	/*
311fd9ee8b5Sjoyce mcintosh 	 * Return a single range regardless of whether the file
312fd9ee8b5Sjoyce mcintosh 	 * is sparse or not.
313fd9ee8b5Sjoyce mcintosh 	 */
314fd9ee8b5Sjoyce mcintosh 	if (MBC_ROOM_FOR(&xa->rep_data_mb, 16) == 0) {
315fd9ee8b5Sjoyce mcintosh 		smbsr_release_file(sr);
316fd9ee8b5Sjoyce mcintosh 		return (NT_STATUS_BUFFER_TOO_SMALL);
317fd9ee8b5Sjoyce mcintosh 	}
318fd9ee8b5Sjoyce mcintosh 
319fd9ee8b5Sjoyce mcintosh 	if (smb_mbc_encodef(&xa->rep_data_mb, "qq", offset, len) != 0) {
320fd9ee8b5Sjoyce mcintosh 		smbsr_release_file(sr);
321fd9ee8b5Sjoyce mcintosh 		return (sr->smb_error.status);
322fd9ee8b5Sjoyce mcintosh 	}
323fd9ee8b5Sjoyce mcintosh 
324fd9ee8b5Sjoyce mcintosh 	smbsr_release_file(sr);
325fd9ee8b5Sjoyce mcintosh 	return (NT_STATUS_SUCCESS);
326fd9ee8b5Sjoyce mcintosh }
327