1adee6784SGordon Ross /*
2adee6784SGordon Ross  * Copyright (c) 2000-2001 Boris Popov
3adee6784SGordon Ross  * All rights reserved.
4adee6784SGordon Ross  *
5adee6784SGordon Ross  * Redistribution and use in source and binary forms, with or without
6adee6784SGordon Ross  * modification, are permitted provided that the following conditions
7adee6784SGordon Ross  * are met:
8adee6784SGordon Ross  * 1. Redistributions of source code must retain the above copyright
9adee6784SGordon Ross  *    notice, this list of conditions and the following disclaimer.
10adee6784SGordon Ross  * 2. Redistributions in binary form must reproduce the above copyright
11adee6784SGordon Ross  *    notice, this list of conditions and the following disclaimer in the
12adee6784SGordon Ross  *    documentation and/or other materials provided with the distribution.
13adee6784SGordon Ross  * 3. All advertising materials mentioning features or use of this software
14adee6784SGordon Ross  *    must display the following acknowledgement:
15adee6784SGordon Ross  *    This product includes software developed by Boris Popov.
16adee6784SGordon Ross  * 4. Neither the name of the author nor the names of any co-contributors
17adee6784SGordon Ross  *    may be used to endorse or promote products derived from this software
18adee6784SGordon Ross  *    without specific prior written permission.
19adee6784SGordon Ross  *
20adee6784SGordon Ross  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21adee6784SGordon Ross  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22adee6784SGordon Ross  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23adee6784SGordon Ross  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24adee6784SGordon Ross  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25adee6784SGordon Ross  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26adee6784SGordon Ross  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27adee6784SGordon Ross  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28adee6784SGordon Ross  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29adee6784SGordon Ross  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30adee6784SGordon Ross  * SUCH DAMAGE.
31adee6784SGordon Ross  */
32adee6784SGordon Ross 
33adee6784SGordon Ross /*
34adee6784SGordon Ross  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
35adee6784SGordon Ross  * Use is subject to license terms.
36adee6784SGordon Ross  *
37adee6784SGordon Ross  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
38adee6784SGordon Ross  */
39adee6784SGordon Ross 
40adee6784SGordon Ross #include <sys/param.h>
41adee6784SGordon Ross #include <sys/systm.h>
42adee6784SGordon Ross #include <sys/inttypes.h>
43adee6784SGordon Ross #include <sys/time.h>
44adee6784SGordon Ross #include <sys/vnode.h>
45adee6784SGordon Ross #include <sys/sunddi.h>
46adee6784SGordon Ross #include <sys/cmn_err.h>
47adee6784SGordon Ross 
48adee6784SGordon Ross #include <netsmb/smb_osdep.h>
49adee6784SGordon Ross 
50adee6784SGordon Ross #include <netsmb/smb.h>
51adee6784SGordon Ross #include <netsmb/smb_conn.h>
52adee6784SGordon Ross #include <netsmb/smb_subr.h>
53adee6784SGordon Ross #include <netsmb/smb_rq.h>
54adee6784SGordon Ross 
55adee6784SGordon Ross #include <smbfs/smbfs.h>
56adee6784SGordon Ross #include <smbfs/smbfs_node.h>
57adee6784SGordon Ross #include <smbfs/smbfs_subr.h>
58adee6784SGordon Ross 
59adee6784SGordon Ross 
60adee6784SGordon Ross /*
61adee6784SGordon Ross  * Todo: locking over-the-wire
62adee6784SGordon Ross  */
63adee6784SGordon Ross #if 0	// todo
64adee6784SGordon Ross 
65adee6784SGordon Ross int
66adee6784SGordon Ross smbfs_smb1_lockandx(struct smbnode *np, int op, uint32_t pid,
67adee6784SGordon Ross 	offset_t start, uint64_t len, int largelock,
68adee6784SGordon Ross 	struct smb_cred *scrp, uint32_t timeout)
69adee6784SGordon Ross {
70adee6784SGordon Ross 	struct smb_share *ssp = np->n_mount->smi_share;
71adee6784SGordon Ross 	struct smb_rq rq, *rqp = &rq;
72adee6784SGordon Ross 	struct mbchain *mbp;
73adee6784SGordon Ross 	uint8_t ltype = 0;
74adee6784SGordon Ross 	int error;
75adee6784SGordon Ross 
76adee6784SGordon Ross 	/* Shared lock for n_fid use below. */
77adee6784SGordon Ross 	ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
78adee6784SGordon Ross 
79adee6784SGordon Ross 	/* After reconnect, n_fid is invalid */
80adee6784SGordon Ross 	if (np->n_vcgenid != ssp->ss_vcgenid)
81adee6784SGordon Ross 		return (ESTALE);
82adee6784SGordon Ross 
83adee6784SGordon Ross 	if (op == SMB_LOCK_SHARED)
84adee6784SGordon Ross 		ltype |= SMB_LOCKING_ANDX_SHARED_LOCK;
85adee6784SGordon Ross 	/* XXX: if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)? */
86adee6784SGordon Ross 	if (largelock)
87adee6784SGordon Ross 		ltype |= SMB_LOCKING_ANDX_LARGE_FILES;
88adee6784SGordon Ross 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scrp);
89adee6784SGordon Ross 	if (error)
90adee6784SGordon Ross 		return (error);
91adee6784SGordon Ross 	smb_rq_getrequest(rqp, &mbp);
92adee6784SGordon Ross 	smb_rq_wstart(rqp);
93adee6784SGordon Ross 	mb_put_uint8(mbp, 0xff);	/* secondary command */
94adee6784SGordon Ross 	mb_put_uint8(mbp, 0);		/* MBZ */
95adee6784SGordon Ross 	mb_put_uint16le(mbp, 0);
96adee6784SGordon Ross 	mb_put_uint16le(mbp, np->n_fid);
97adee6784SGordon Ross 	mb_put_uint8(mbp, ltype);	/* locktype */
98adee6784SGordon Ross 	mb_put_uint8(mbp, 0);		/* oplocklevel - 0 seems is NO_OPLOCK */
99adee6784SGordon Ross 	mb_put_uint32le(mbp, timeout);	/* 0 nowait, -1 infinite wait */
100adee6784SGordon Ross 	mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 1 : 0);
101adee6784SGordon Ross 	mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 0 : 1);
102adee6784SGordon Ross 	smb_rq_wend(rqp);
103adee6784SGordon Ross 	smb_rq_bstart(rqp);
104adee6784SGordon Ross 	mb_put_uint16le(mbp, pid);
105adee6784SGordon Ross 	if (!largelock) {
106adee6784SGordon Ross 		mb_put_uint32le(mbp, start);
107adee6784SGordon Ross 		mb_put_uint32le(mbp, len);
108adee6784SGordon Ross 	} else {
109adee6784SGordon Ross 		mb_put_uint16le(mbp, 0); /* pad */
110adee6784SGordon Ross 		mb_put_uint32le(mbp, start >> 32); /* OffsetHigh */
111adee6784SGordon Ross 		mb_put_uint32le(mbp, start & 0xffffffff); /* OffsetLow */
112adee6784SGordon Ross 		mb_put_uint32le(mbp, len >> 32); /* LengthHigh */
113adee6784SGordon Ross 		mb_put_uint32le(mbp, len & 0xffffffff); /* LengthLow */
114adee6784SGordon Ross 	}
115adee6784SGordon Ross 	smb_rq_bend(rqp);
116adee6784SGordon Ross 	/*
117adee6784SGordon Ross 	 * Don't want to risk missing a successful
118adee6784SGordon Ross 	 * unlock send or lock response, or we could
119adee6784SGordon Ross 	 * lose track of an outstanding lock.
120adee6784SGordon Ross 	 */
121adee6784SGordon Ross 	if (op == SMB_LOCK_RELEASE)
122adee6784SGordon Ross 		rqp->sr_flags |= SMBR_NOINTR_SEND;
123adee6784SGordon Ross 	else
124adee6784SGordon Ross 		rqp->sr_flags |= SMBR_NOINTR_RECV;
125adee6784SGordon Ross 
126adee6784SGordon Ross 	error = smb_rq_simple(rqp);
127adee6784SGordon Ross 	smb_rq_done(rqp);
128adee6784SGordon Ross 	return (error);
129adee6784SGordon Ross }
130adee6784SGordon Ross 
131adee6784SGordon Ross #endif	// todo
132adee6784SGordon Ross 
133adee6784SGordon Ross /*
134adee6784SGordon Ross  * Common function for QueryFileInfo, QueryPathInfo.
135adee6784SGordon Ross  */
136adee6784SGordon Ross int
smbfs_smb1_trans2_query(struct smbnode * np,uint16_t fid,struct smbfattr * fap,struct smb_cred * scrp)137adee6784SGordon Ross smbfs_smb1_trans2_query(struct smbnode *np,  uint16_t fid,
138adee6784SGordon Ross 	struct smbfattr *fap, struct smb_cred *scrp)
139adee6784SGordon Ross {
140adee6784SGordon Ross 	struct smb_share *ssp = np->n_mount->smi_share;
141adee6784SGordon Ross 	struct smb_vc *vcp = SSTOVC(ssp);
142adee6784SGordon Ross 	struct smb_t2rq *t2p;
143adee6784SGordon Ross 	struct mbchain *mbp;
144adee6784SGordon Ross 	struct mdchain *mdp;
145adee6784SGordon Ross 	uint16_t cmd;
146adee6784SGordon Ross 	uint16_t infolevel = SMB_QFILEINFO_ALL_INFO;
147adee6784SGordon Ross 	int error;
148adee6784SGordon Ross 
149adee6784SGordon Ross 	/*
150adee6784SGordon Ross 	 * If we have a valid open FID, use it.
151adee6784SGordon Ross 	 */
152adee6784SGordon Ross 	if (fid != SMB_FID_UNUSED)
153adee6784SGordon Ross 		cmd = SMB_TRANS2_QUERY_FILE_INFORMATION;
154adee6784SGordon Ross 	else
155adee6784SGordon Ross 		cmd = SMB_TRANS2_QUERY_PATH_INFORMATION;
156adee6784SGordon Ross 
157adee6784SGordon Ross 	error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
158adee6784SGordon Ross 	if (error)
159adee6784SGordon Ross 		return (error);
160adee6784SGordon Ross 	mbp = &t2p->t2_tparam;
161adee6784SGordon Ross 	mb_init(mbp);
162adee6784SGordon Ross 
163adee6784SGordon Ross 	if (cmd == SMB_TRANS2_QUERY_FILE_INFORMATION)
164adee6784SGordon Ross 		mb_put_uint16le(mbp, fid);
165adee6784SGordon Ross 
166adee6784SGordon Ross 	mb_put_uint16le(mbp, infolevel);
167adee6784SGordon Ross 
168adee6784SGordon Ross 	if (cmd == SMB_TRANS2_QUERY_PATH_INFORMATION) {
169adee6784SGordon Ross 		mb_put_uint32le(mbp, 0);
170adee6784SGordon Ross 		/* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */
171adee6784SGordon Ross 		error = smbfs_fullpath(mbp, vcp, np, NULL, 0, '\\');
172adee6784SGordon Ross 		if (error)
173adee6784SGordon Ross 			goto out;
174adee6784SGordon Ross 	}
175adee6784SGordon Ross 
176adee6784SGordon Ross 	t2p->t2_maxpcount = 2;
177adee6784SGordon Ross 	t2p->t2_maxdcount = vcp->vc_txmax;
178adee6784SGordon Ross 	error = smb_t2_request(t2p);
179adee6784SGordon Ross 	if (error)
180adee6784SGordon Ross 		goto out;
181adee6784SGordon Ross 
182adee6784SGordon Ross 	/*
183adee6784SGordon Ross 	 * Parse the SMB_QFILEINFO_ALL_INFO
184adee6784SGordon Ross 	 */
185adee6784SGordon Ross 	mdp = &t2p->t2_rdata;
186adee6784SGordon Ross 	error = smbfs_decode_file_all_info(ssp, mdp, fap);
187adee6784SGordon Ross 
188adee6784SGordon Ross out:
189adee6784SGordon Ross 	smb_t2_done(t2p);
190adee6784SGordon Ross 
191adee6784SGordon Ross 	return (error);
192adee6784SGordon Ross }
193adee6784SGordon Ross 
194adee6784SGordon Ross /*
195adee6784SGordon Ross  * Get some FS information
196adee6784SGordon Ross  */
197adee6784SGordon Ross static int
smbfs_smb1_query_fs_info(struct smb_share * ssp,struct mdchain * info_mdp,uint16_t level,struct smb_cred * scrp)198adee6784SGordon Ross smbfs_smb1_query_fs_info(struct smb_share *ssp, struct mdchain *info_mdp,
199adee6784SGordon Ross 	uint16_t level, struct smb_cred *scrp)
200adee6784SGordon Ross {
201adee6784SGordon Ross 	struct smb_t2rq *t2p;
202adee6784SGordon Ross 	struct mbchain *mbp;
203adee6784SGordon Ross 	struct mdchain *mdp;
204adee6784SGordon Ross 	int error;
205adee6784SGordon Ross 
206adee6784SGordon Ross 	error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION,
207adee6784SGordon Ross 	    scrp, &t2p);
208adee6784SGordon Ross 	if (error)
209adee6784SGordon Ross 		return (error);
210adee6784SGordon Ross 	mbp = &t2p->t2_tparam;
211adee6784SGordon Ross 	mb_init(mbp);
212adee6784SGordon Ross 	mb_put_uint16le(mbp, level);
213adee6784SGordon Ross 	t2p->t2_maxpcount = 4;
214adee6784SGordon Ross 	t2p->t2_maxdcount = 1024;
215adee6784SGordon Ross 	error = smb_t2_request(t2p);
216adee6784SGordon Ross 	if (error)
217adee6784SGordon Ross 		goto out;
218adee6784SGordon Ross 
219adee6784SGordon Ross 	mdp = &t2p->t2_rdata;
220adee6784SGordon Ross 	*info_mdp = *mdp;
221adee6784SGordon Ross 	bzero(mdp, sizeof (*mdp));
222adee6784SGordon Ross 
223adee6784SGordon Ross out:
224adee6784SGordon Ross 	smb_t2_done(t2p);
225adee6784SGordon Ross 	return (error);
226adee6784SGordon Ross }
227adee6784SGordon Ross 
228adee6784SGordon Ross /*
229adee6784SGordon Ross  * Get FILE_FS_ATTRIBUTE_INFORMATION
230adee6784SGordon Ross  */
231adee6784SGordon Ross int
smbfs_smb1_qfsattr(struct smb_share * ssp,struct smb_fs_attr_info * fsa,struct smb_cred * scrp)232adee6784SGordon Ross smbfs_smb1_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *fsa,
233adee6784SGordon Ross 	struct smb_cred *scrp)
234adee6784SGordon Ross {
235adee6784SGordon Ross 	struct mdchain info_mdc, *mdp = &info_mdc;
236adee6784SGordon Ross 	int error;
237adee6784SGordon Ross 
238adee6784SGordon Ross 	bzero(mdp, sizeof (*mdp));
239adee6784SGordon Ross 
240adee6784SGordon Ross 	error = smbfs_smb1_query_fs_info(ssp, mdp,
241adee6784SGordon Ross 	    SMB_QFS_ATTRIBUTE_INFO, scrp);
242adee6784SGordon Ross 	if (error)
243adee6784SGordon Ross 		goto out;
244adee6784SGordon Ross 	error = smbfs_decode_fs_attr_info(ssp, mdp, fsa);
245adee6784SGordon Ross 
246adee6784SGordon Ross out:
247adee6784SGordon Ross 	md_done(mdp);
248adee6784SGordon Ross 
249adee6784SGordon Ross 	return (error);
250adee6784SGordon Ross }
251adee6784SGordon Ross 
252adee6784SGordon Ross /*
253adee6784SGordon Ross  * Get FileFsFullSizeInformation and
254adee6784SGordon Ross  * parse into *info
255adee6784SGordon Ross  */
256adee6784SGordon Ross int
smbfs_smb1_statfs(struct smb_share * ssp,struct smb_fs_size_info * info,struct smb_cred * scrp)257adee6784SGordon Ross smbfs_smb1_statfs(struct smb_share *ssp,
258adee6784SGordon Ross 	struct smb_fs_size_info *info,
259adee6784SGordon Ross 	struct smb_cred *scrp)
260adee6784SGordon Ross {
261adee6784SGordon Ross 	struct mdchain info_mdc, *mdp = &info_mdc;
262adee6784SGordon Ross 	struct smb_vc *vcp = SSTOVC(ssp);
263adee6784SGordon Ross 	uint16_t level;
264adee6784SGordon Ross 	int error;
265adee6784SGordon Ross 
266adee6784SGordon Ross 	bzero(mdp, sizeof (*mdp));
267adee6784SGordon Ross 
268adee6784SGordon Ross 	if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
269adee6784SGordon Ross 		level = SMB_QFS_FULL_SIZE_INFORMATION;
270adee6784SGordon Ross 	else
271adee6784SGordon Ross 		level = SMB_QFS_SIZE_INFO;
272adee6784SGordon Ross 	error = smbfs_smb1_query_fs_info(ssp, mdp, level, scrp);
273adee6784SGordon Ross 	if (error)
274adee6784SGordon Ross 		goto out;
275adee6784SGordon Ross 
276adee6784SGordon Ross 	md_get_uint64le(mdp, &info->total_units);
277adee6784SGordon Ross 	md_get_uint64le(mdp, &info->caller_avail);
278adee6784SGordon Ross 	if (level == SMB_QFS_FULL_SIZE_INFORMATION)
279adee6784SGordon Ross 		md_get_uint64le(mdp, &info->actual_avail);
280adee6784SGordon Ross 	else
281adee6784SGordon Ross 		info->actual_avail = info->caller_avail;
282adee6784SGordon Ross 
283adee6784SGordon Ross 	md_get_uint32le(mdp, &info->sect_per_unit);
284adee6784SGordon Ross 	error = md_get_uint32le(mdp, &info->bytes_per_sect);
285adee6784SGordon Ross 
286adee6784SGordon Ross out:
287adee6784SGordon Ross 	md_done(mdp);
288adee6784SGordon Ross 
289adee6784SGordon Ross 	return (error);
290adee6784SGordon Ross }
291adee6784SGordon Ross 
292adee6784SGordon Ross int
smbfs_smb1_flush(struct smb_share * ssp,uint16_t fid,struct smb_cred * scrp)293adee6784SGordon Ross smbfs_smb1_flush(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp)
294adee6784SGordon Ross {
295adee6784SGordon Ross 	struct smb_rq rq, *rqp = &rq;
296adee6784SGordon Ross 	struct mbchain *mbp;
297adee6784SGordon Ross 	int error;
298adee6784SGordon Ross 
299adee6784SGordon Ross 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scrp);
300adee6784SGordon Ross 	if (error)
301adee6784SGordon Ross 		return (error);
302adee6784SGordon Ross 	smb_rq_getrequest(rqp, &mbp);
303adee6784SGordon Ross 	smb_rq_wstart(rqp);
304adee6784SGordon Ross 	mb_put_uint16le(mbp, fid);
305adee6784SGordon Ross 	smb_rq_wend(rqp);
306adee6784SGordon Ross 	smb_rq_bstart(rqp);
307adee6784SGordon Ross 	smb_rq_bend(rqp);
308adee6784SGordon Ross 	error = smb_rq_simple(rqp);
309adee6784SGordon Ross 	smb_rq_done(rqp);
310adee6784SGordon Ross 	return (error);
311adee6784SGordon Ross }
312adee6784SGordon Ross 
313adee6784SGordon Ross /*
314adee6784SGordon Ross  * Set file info via an open handle.
315adee6784SGordon Ross  * Caller provides payload, info level.
316adee6784SGordon Ross  */
317adee6784SGordon Ross static int
smbfs_smb1_setinfo_file(struct smb_share * ssp,uint16_t fid,struct mbchain * info_mbp,uint16_t level,struct smb_cred * scrp)318adee6784SGordon Ross smbfs_smb1_setinfo_file(struct smb_share *ssp, uint16_t fid,
319adee6784SGordon Ross 	struct mbchain *info_mbp, uint16_t level, struct smb_cred *scrp)
320adee6784SGordon Ross {
321adee6784SGordon Ross 	struct smb_t2rq *t2p = NULL;
322adee6784SGordon Ross 	struct mbchain *mbp;
323adee6784SGordon Ross 	uint16_t cmd = SMB_TRANS2_SET_FILE_INFORMATION;
324adee6784SGordon Ross 	int error;
325adee6784SGordon Ross 
326adee6784SGordon Ross 	ASSERT(fid != SMB_FID_UNUSED);
327adee6784SGordon Ross 
328adee6784SGordon Ross 	error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
329adee6784SGordon Ross 	if (error)
330adee6784SGordon Ross 		return (error);
331adee6784SGordon Ross 	mbp = &t2p->t2_tparam;
332adee6784SGordon Ross 	mb_init(mbp);
333adee6784SGordon Ross 	mb_put_uint16le(mbp, fid);
334adee6784SGordon Ross 	mb_put_uint16le(mbp, level);
335adee6784SGordon Ross 	mb_put_uint16le(mbp, 0); /* pad */
336adee6784SGordon Ross 
337adee6784SGordon Ross 	/* put the payload */
338adee6784SGordon Ross 	mbp = &t2p->t2_tdata;
339adee6784SGordon Ross 	mb_init(mbp);
340adee6784SGordon Ross 	error = mb_put_mbchain(mbp, info_mbp);
341adee6784SGordon Ross 	if (error)
342adee6784SGordon Ross 		goto out;
343adee6784SGordon Ross 
344adee6784SGordon Ross 	t2p->t2_maxpcount = 2;
345adee6784SGordon Ross 	t2p->t2_maxdcount = 0;
346adee6784SGordon Ross 	error = smb_t2_request(t2p);
347adee6784SGordon Ross 
348adee6784SGordon Ross out:
349adee6784SGordon Ross 	smb_t2_done(t2p);
350adee6784SGordon Ross 
351adee6784SGordon Ross 	return (error);
352adee6784SGordon Ross }
353adee6784SGordon Ross 
354adee6784SGordon Ross int
smbfs_smb1_seteof(struct smb_share * ssp,uint16_t fid,uint64_t newsize,struct smb_cred * scrp)355adee6784SGordon Ross smbfs_smb1_seteof(struct smb_share *ssp, uint16_t fid,
356adee6784SGordon Ross 	uint64_t newsize, struct smb_cred *scrp)
357adee6784SGordon Ross {
358adee6784SGordon Ross 	struct mbchain data_mb, *mbp = &data_mb;
359adee6784SGordon Ross 	uint16_t level;
360adee6784SGordon Ross 	int error;
361adee6784SGordon Ross 
362adee6784SGordon Ross 	if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
363adee6784SGordon Ross 		level = SMB_SFILEINFO_END_OF_FILE_INFORMATION;
364adee6784SGordon Ross 	else
365adee6784SGordon Ross 		level = SMB_SFILEINFO_END_OF_FILE_INFO;
366adee6784SGordon Ross 
367adee6784SGordon Ross 	mb_init(mbp);
368adee6784SGordon Ross 	error = mb_put_uint64le(mbp, newsize);
369adee6784SGordon Ross 	if (error)
370adee6784SGordon Ross 		goto out;
371adee6784SGordon Ross 	error = smbfs_smb1_setinfo_file(ssp, fid, mbp, level, scrp);
372adee6784SGordon Ross 
373adee6784SGordon Ross out:
374adee6784SGordon Ross 	mb_done(mbp);
375adee6784SGordon Ross 	return (error);
376adee6784SGordon Ross }
377adee6784SGordon Ross 
378adee6784SGordon Ross int
smbfs_smb1_setdisp(struct smb_share * ssp,uint16_t fid,uint8_t newdisp,struct smb_cred * scrp)379adee6784SGordon Ross smbfs_smb1_setdisp(struct smb_share *ssp, uint16_t fid,
380adee6784SGordon Ross 	uint8_t newdisp, struct smb_cred *scrp)
381adee6784SGordon Ross {
382adee6784SGordon Ross 	struct mbchain data_mb, *mbp = &data_mb;
383adee6784SGordon Ross 	uint16_t level;
384adee6784SGordon Ross 	int error;
385adee6784SGordon Ross 
386adee6784SGordon Ross 	if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
387adee6784SGordon Ross 		level = SMB_SFILEINFO_DISPOSITION_INFORMATION;
388adee6784SGordon Ross 	else
389adee6784SGordon Ross 		level = SMB_SFILEINFO_DISPOSITION_INFO;
390adee6784SGordon Ross 
391adee6784SGordon Ross 	mb_init(mbp);
392adee6784SGordon Ross 	error = mb_put_uint8(mbp, newdisp);
393adee6784SGordon Ross 	if (error)
394adee6784SGordon Ross 		goto out;
395adee6784SGordon Ross 	error = smbfs_smb1_setinfo_file(ssp, fid, mbp, level, scrp);
396adee6784SGordon Ross 
397adee6784SGordon Ross out:
398adee6784SGordon Ross 	mb_done(mbp);
399adee6784SGordon Ross 
400adee6784SGordon Ross 	return (error);
401adee6784SGordon Ross }
402adee6784SGordon Ross 
403adee6784SGordon Ross /*
404adee6784SGordon Ross  * Set FileBasicInformation on an open handle
405adee6784SGordon Ross  * Caller builds the mbchain.
406adee6784SGordon Ross  * Always have a FID here.
407adee6784SGordon Ross  */
408adee6784SGordon Ross int
smbfs_smb1_setfattr(struct smb_share * ssp,uint16_t fid,struct mbchain * mbp,struct smb_cred * scrp)409adee6784SGordon Ross smbfs_smb1_setfattr(struct smb_share *ssp, uint16_t fid,
410adee6784SGordon Ross 	struct mbchain *mbp, struct smb_cred *scrp)
411adee6784SGordon Ross {
412adee6784SGordon Ross 	uint16_t level;
413adee6784SGordon Ross 	int error;
414adee6784SGordon Ross 
415adee6784SGordon Ross 	if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
416adee6784SGordon Ross 		level = SMB_SFILEINFO_BASIC_INFORMATION;
417adee6784SGordon Ross 	else
418adee6784SGordon Ross 		level = SMB_SFILEINFO_BASIC_INFO;
419adee6784SGordon Ross 	error = smbfs_smb1_setinfo_file(ssp, fid, mbp, level, scrp);
420adee6784SGordon Ross 
421adee6784SGordon Ross 	return (error);
422adee6784SGordon Ross }
423adee6784SGordon Ross 
424adee6784SGordon Ross /*
425adee6784SGordon Ross  * On SMB1, the trans2 rename only allows a rename where the
426adee6784SGordon Ross  * source and target are in the same directory.  If you give
427adee6784SGordon Ross  * the server any separators, you get "status not supported".
428adee6784SGordon Ross  *
429adee6784SGordon Ross  * Why bother using this instead of smbfs_smb1_oldrename?
430adee6784SGordon Ross  * Because it works with an open file, and some servers don't
431adee6784SGordon Ross  * allow oldrename of a file that's currently open.  We call
432adee6784SGordon Ross  * this when deleting an open file in smbfsremove(), where
433adee6784SGordon Ross  * the rename is always in the same directory.
434adee6784SGordon Ross  */
435adee6784SGordon Ross /*ARGSUSED*/
436adee6784SGordon Ross int
smbfs_smb1_t2rename(struct smbnode * np,const char * tname,int tnlen,uint16_t fid,struct smb_cred * scrp)437adee6784SGordon Ross smbfs_smb1_t2rename(struct smbnode *np,
438adee6784SGordon Ross 	const char *tname, int tnlen,
439adee6784SGordon Ross 	uint16_t fid, struct smb_cred *scrp)
440adee6784SGordon Ross {
441adee6784SGordon Ross 	struct smb_share *ssp = np->n_mount->smi_share;
442adee6784SGordon Ross 	struct mbchain data_mb, *mbp = &data_mb;
443adee6784SGordon Ross 	struct smb_vc *vcp = SSTOVC(ssp);
444adee6784SGordon Ross 	uint32_t *name_lenp;
445adee6784SGordon Ross 	uint16_t level = SMB_SFILEINFO_RENAME_INFORMATION;
446adee6784SGordon Ross 	int base, len;
447adee6784SGordon Ross 	int error;
448adee6784SGordon Ross 
449adee6784SGordon Ross 	mb_init(mbp);
450adee6784SGordon Ross 	mb_put_uint32le(mbp, 0); /* don't overwrite */
451adee6784SGordon Ross 	mb_put_uint32le(mbp, 0); /* obsolete target dir fid */
452adee6784SGordon Ross 	name_lenp = mb_reserve(mbp, 4);	/* name len */
453adee6784SGordon Ross 
454adee6784SGordon Ross 	/* New name */
455adee6784SGordon Ross 	base = mbp->mb_count;
456adee6784SGordon Ross 	error = smb_put_dmem(mbp, vcp, tname, tnlen, SMB_CS_NONE, NULL);
457adee6784SGordon Ross 	if (error)
458adee6784SGordon Ross 		goto out;
459adee6784SGordon Ross 	len = mbp->mb_count - base;
460adee6784SGordon Ross 	*name_lenp = htolel(len);
461adee6784SGordon Ross 
462adee6784SGordon Ross 	error = smbfs_smb1_setinfo_file(ssp, fid, mbp, level, scrp);
463adee6784SGordon Ross 
464adee6784SGordon Ross out:
465adee6784SGordon Ross 	mb_done(mbp);
466adee6784SGordon Ross 	return (error);
467adee6784SGordon Ross }
468adee6784SGordon Ross 
469adee6784SGordon Ross /*
470adee6784SGordon Ross  * Do an SMB1 (old style) rename using a full dest. path.
471adee6784SGordon Ross  * This is used when renaming to a different directory,
472adee6784SGordon Ross  * because the (preferred) t2rename can't do that.
473adee6784SGordon Ross  */
474adee6784SGordon Ross int
smbfs_smb1_oldrename(struct smbnode * src,struct smbnode * tdnp,const char * tname,int tnmlen,struct smb_cred * scrp)475adee6784SGordon Ross smbfs_smb1_oldrename(struct smbnode *src, struct smbnode *tdnp,
476adee6784SGordon Ross     const char *tname, int tnmlen, struct smb_cred *scrp)
477adee6784SGordon Ross {
478adee6784SGordon Ross 	struct smb_rq rq, *rqp = &rq;
479adee6784SGordon Ross 	struct smb_share *ssp = src->n_mount->smi_share;
480adee6784SGordon Ross 	struct mbchain *mbp;
481adee6784SGordon Ross 	int error;
482adee6784SGordon Ross 	uint16_t fa;
483adee6784SGordon Ross 	char sep;
484adee6784SGordon Ross 
485adee6784SGordon Ross 	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_RENAME, scrp);
486adee6784SGordon Ross 	if (error)
487adee6784SGordon Ross 		return (error);
488adee6784SGordon Ross 	smb_rq_getrequest(rqp, &mbp);
489adee6784SGordon Ross 	smb_rq_wstart(rqp);
490adee6784SGordon Ross 	/* freebsd bug: Let directories be renamed - Win98 requires DIR bit */
491adee6784SGordon Ross 	fa = (SMBTOV(src)->v_type == VDIR) ? SMB_FA_DIR : 0;
492adee6784SGordon Ross 	fa |= SMB_FA_SYSTEM | SMB_FA_HIDDEN;
493adee6784SGordon Ross 	mb_put_uint16le(mbp, fa);
494adee6784SGordon Ross 	smb_rq_wend(rqp);
495adee6784SGordon Ross 	smb_rq_bstart(rqp);
496adee6784SGordon Ross 
497adee6784SGordon Ross 	/*
498adee6784SGordon Ross 	 * When we're not adding any component name, the
499adee6784SGordon Ross 	 * passed sep is ignored, so just pass sep=0.
500adee6784SGordon Ross 	 */
501adee6784SGordon Ross 	mb_put_uint8(mbp, SMB_DT_ASCII);
502adee6784SGordon Ross 	error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0, 0);
503adee6784SGordon Ross 	if (error)
504adee6784SGordon Ross 		goto out;
505adee6784SGordon Ross 
506adee6784SGordon Ross 	/*
507adee6784SGordon Ross 	 * After XATTR directories, separator is ":"
508adee6784SGordon Ross 	 */
509adee6784SGordon Ross 	sep = (src->n_flag & N_XATTR) ? ':' : '\\';
510adee6784SGordon Ross 	mb_put_uint8(mbp, SMB_DT_ASCII);
511adee6784SGordon Ross 	error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen, sep);
512adee6784SGordon Ross 	if (error)
513adee6784SGordon Ross 		goto out;
514adee6784SGordon Ross 
515adee6784SGordon Ross 	smb_rq_bend(rqp);
516adee6784SGordon Ross 	error = smb_rq_simple(rqp);
517adee6784SGordon Ross out:
518adee6784SGordon Ross 	smb_rq_done(rqp);
519adee6784SGordon Ross 	return (error);
520adee6784SGordon Ross }
521adee6784SGordon Ross 
522adee6784SGordon Ross 
523adee6784SGordon Ross /*
524adee6784SGordon Ross  * TRANS2_FIND_FIRST2/NEXT2, used for NT LM12 dialect
525adee6784SGordon Ross  */
526adee6784SGordon Ross static int
smbfs_smb1_trans2find2(struct smbfs_fctx * ctx)527adee6784SGordon Ross smbfs_smb1_trans2find2(struct smbfs_fctx *ctx)
528adee6784SGordon Ross {
529adee6784SGordon Ross 	struct smb_t2rq *t2p;
530adee6784SGordon Ross 	struct smb_vc *vcp = SSTOVC(ctx->f_ssp);
531adee6784SGordon Ross 	struct mbchain *mbp;
532adee6784SGordon Ross 	struct mdchain *mdp;
533adee6784SGordon Ross 	uint16_t ecnt, eos, lno, flags;
534adee6784SGordon Ross 	uint16_t amask, limit;
535adee6784SGordon Ross 	int error;
536adee6784SGordon Ross 
537adee6784SGordon Ross 	/* smbfs_smb_findnextLM2 sets this */
538adee6784SGordon Ross 	limit = ctx->f_limit;
539adee6784SGordon Ross 	amask = (uint16_t)ctx->f_attrmask;
540adee6784SGordon Ross 
541adee6784SGordon Ross 	if (ctx->f_t2) {
542adee6784SGordon Ross 		smb_t2_done(ctx->f_t2);
543adee6784SGordon Ross 		ctx->f_t2 = NULL;
544adee6784SGordon Ross 	}
545adee6784SGordon Ross 	flags = FIND2_RETURN_RESUME_KEYS | FIND2_CLOSE_ON_EOS;
546adee6784SGordon Ross 	if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) {
547adee6784SGordon Ross 		flags |= FIND2_CLOSE_AFTER_REQUEST;
548adee6784SGordon Ross 		ctx->f_flags |= SMBFS_RDD_NOCLOSE;
549adee6784SGordon Ross 	}
550adee6784SGordon Ross 	if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
551adee6784SGordon Ross 		error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_FIRST2,
552adee6784SGordon Ross 		    ctx->f_scred, &t2p);
553adee6784SGordon Ross 		if (error)
554adee6784SGordon Ross 			return (error);
555adee6784SGordon Ross 		ctx->f_t2 = t2p;
556adee6784SGordon Ross 		mbp = &t2p->t2_tparam;
557adee6784SGordon Ross 		mb_init(mbp);
558adee6784SGordon Ross 		mb_put_uint16le(mbp, amask);
559adee6784SGordon Ross 		mb_put_uint16le(mbp, limit);
560adee6784SGordon Ross 		mb_put_uint16le(mbp, flags);
561adee6784SGordon Ross 		mb_put_uint16le(mbp, ctx->f_infolevel);
562adee6784SGordon Ross 		mb_put_uint32le(mbp, 0);
563adee6784SGordon Ross 		error = smbfs_fullpath(mbp, vcp, ctx->f_dnp,
564adee6784SGordon Ross 		    ctx->f_wildcard, ctx->f_wclen, '\\');
565adee6784SGordon Ross 		if (error)
566adee6784SGordon Ross 			return (error);
567adee6784SGordon Ross 	} else	{
568adee6784SGordon Ross 		error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_NEXT2,
569adee6784SGordon Ross 		    ctx->f_scred, &t2p);
570adee6784SGordon Ross 		if (error)
571adee6784SGordon Ross 			return (error);
572adee6784SGordon Ross 		ctx->f_t2 = t2p;
573adee6784SGordon Ross 		mbp = &t2p->t2_tparam;
574adee6784SGordon Ross 		mb_init(mbp);
575adee6784SGordon Ross 		mb_put_uint16le(mbp, ctx->f_Sid);
576adee6784SGordon Ross 		mb_put_uint16le(mbp, limit);
577adee6784SGordon Ross 		mb_put_uint16le(mbp, ctx->f_infolevel);
578adee6784SGordon Ross 		/* Send whatever resume key we received... */
579adee6784SGordon Ross 		mb_put_uint32le(mbp, ctx->f_rkey);
580adee6784SGordon Ross 		mb_put_uint16le(mbp, flags);
581adee6784SGordon Ross 		/* ... and the resume name if we have one. */
582adee6784SGordon Ross 		if (ctx->f_rname) {
583adee6784SGordon Ross 			/* resume file name */
584adee6784SGordon Ross 			mb_put_mem(mbp, ctx->f_rname, ctx->f_rnamelen,
585adee6784SGordon Ross 			    MB_MSYSTEM);
586adee6784SGordon Ross 		}
587adee6784SGordon Ross 		/* Add trailing null - 1 byte if ASCII, 2 if Unicode */
588adee6784SGordon Ross 		if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp)))
589adee6784SGordon Ross 			mb_put_uint8(mbp, 0);	/* 1st byte NULL Unicode char */
590adee6784SGordon Ross 		mb_put_uint8(mbp, 0);
591adee6784SGordon Ross 	}
592adee6784SGordon Ross 	t2p->t2_maxpcount = 5 * 2;
593adee6784SGordon Ross 	t2p->t2_maxdcount = 0xF000;	/* 64K less some overhead */
594adee6784SGordon Ross 	error = smb_t2_request(t2p);
595adee6784SGordon Ross 	if (error)
596adee6784SGordon Ross 		return (error);
597adee6784SGordon Ross 
598adee6784SGordon Ross 	/*
599adee6784SGordon Ross 	 * This is the "resume name" we just sent.
600adee6784SGordon Ross 	 * We want the new one (if any) that may be
601adee6784SGordon Ross 	 * found in the response we just received and
602adee6784SGordon Ross 	 * will now begin parsing.  Free the old one
603adee6784SGordon Ross 	 * now so we'll know if we found a new one.
604adee6784SGordon Ross 	 */
605adee6784SGordon Ross 	if (ctx->f_rname) {
606adee6784SGordon Ross 		kmem_free(ctx->f_rname, ctx->f_rnamelen);
607adee6784SGordon Ross 		ctx->f_rname = NULL;
608adee6784SGordon Ross 		ctx->f_rnamelen = 0;
609adee6784SGordon Ross 	}
610adee6784SGordon Ross 
611adee6784SGordon Ross 	mdp = &t2p->t2_rparam;
612adee6784SGordon Ross 	if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
613adee6784SGordon Ross 		if ((error = md_get_uint16le(mdp, &ctx->f_Sid)) != 0)
614adee6784SGordon Ross 			goto nodata;
615adee6784SGordon Ross 		ctx->f_flags &= ~SMBFS_RDD_FINDFIRST;
616adee6784SGordon Ross 	}
617adee6784SGordon Ross 	md_get_uint16le(mdp, &ecnt);		/* entry count */
618adee6784SGordon Ross 	md_get_uint16le(mdp, &eos);		/* end of search */
619adee6784SGordon Ross 	md_get_uint16le(mdp, NULL);		/* EA err. off. */
620adee6784SGordon Ross 	error = md_get_uint16le(mdp, &lno);	/* last name off. */
621adee6784SGordon Ross 	if (error != 0)
622adee6784SGordon Ross 		goto nodata;
623adee6784SGordon Ross 
624adee6784SGordon Ross 	/*
625adee6784SGordon Ross 	 * The "end of search" flag from an XP server sometimes
626adee6784SGordon Ross 	 * comes back zero when the prior find_next returned exactly
627adee6784SGordon Ross 	 * the number of entries requested.  in which case we'd try again
628adee6784SGordon Ross 	 * but the search has in fact been closed so an EBADF results.
629adee6784SGordon Ross 	 * our circumvention is to check here for a zero entry count.
630adee6784SGordon Ross 	 */
631adee6784SGordon Ross 	ctx->f_ecnt = ecnt;
632adee6784SGordon Ross 	if (eos || ctx->f_ecnt == 0)
633adee6784SGordon Ross 		ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE;
634adee6784SGordon Ross 	if (ctx->f_ecnt == 0)
635adee6784SGordon Ross 		return (ENOENT);
636adee6784SGordon Ross 
637adee6784SGordon Ross 	/* Last Name Off (LNO) is the entry with the resume name. */
638adee6784SGordon Ross 	ctx->f_rnameofs = lno;
639adee6784SGordon Ross 	ctx->f_eofs = 0;
640adee6784SGordon Ross 
641adee6784SGordon Ross 	/*
642adee6784SGordon Ross 	 * Have data. Put the payload in ctx->f_mdchain
643adee6784SGordon Ross 	 * Note struct assignments here.
644adee6784SGordon Ross 	 */
645adee6784SGordon Ross 	mdp = &t2p->t2_rdata;
646adee6784SGordon Ross 	md_done(&ctx->f_mdchain);
647adee6784SGordon Ross 	ctx->f_mdchain = *mdp;
648adee6784SGordon Ross 	ctx->f_left = m_fixhdr(mdp->md_top);
649adee6784SGordon Ross 	bzero(mdp, sizeof (*mdp));
650adee6784SGordon Ross 
651adee6784SGordon Ross 	return (0);
652adee6784SGordon Ross 
653adee6784SGordon Ross nodata:
654adee6784SGordon Ross 	/*
655adee6784SGordon Ross 	 * Failed parsing the FindFirst or FindNext response.
656adee6784SGordon Ross 	 * Force this directory listing closed, otherwise the
657adee6784SGordon Ross 	 * calling process may hang in an infinite loop.
658adee6784SGordon Ross 	 */
659adee6784SGordon Ross 	ctx->f_ecnt = 0; /* Force closed. */
660adee6784SGordon Ross 	ctx->f_flags |= SMBFS_RDD_EOF;
661adee6784SGordon Ross 	return (EIO);
662adee6784SGordon Ross }
663adee6784SGordon Ross 
664adee6784SGordon Ross static int
smbfs_smb1_findclose2(struct smbfs_fctx * ctx)665adee6784SGordon Ross smbfs_smb1_findclose2(struct smbfs_fctx *ctx)
666adee6784SGordon Ross {
667adee6784SGordon Ross 	struct smb_rq rq, *rqp = &rq;
668adee6784SGordon Ross 	struct mbchain *mbp;
669adee6784SGordon Ross 	int error;
670adee6784SGordon Ross 
671adee6784SGordon Ross 	error = smb_rq_init(rqp, SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2,
672adee6784SGordon Ross 	    ctx->f_scred);
673adee6784SGordon Ross 	if (error)
674adee6784SGordon Ross 		return (error);
675adee6784SGordon Ross 	smb_rq_getrequest(rqp, &mbp);
676adee6784SGordon Ross 	smb_rq_wstart(rqp);
677adee6784SGordon Ross 	mb_put_uint16le(mbp, ctx->f_Sid);
678adee6784SGordon Ross 	smb_rq_wend(rqp);
679adee6784SGordon Ross 	smb_rq_bstart(rqp);
680adee6784SGordon Ross 	smb_rq_bend(rqp);
681adee6784SGordon Ross 	/* Ditto comments at _smb_close */
682adee6784SGordon Ross 	rqp->sr_flags |= SMBR_NOINTR_SEND;
683adee6784SGordon Ross 	error = smb_rq_simple(rqp);
684adee6784SGordon Ross 	smb_rq_done(rqp);
685adee6784SGordon Ross 	return (error);
686adee6784SGordon Ross }
687adee6784SGordon Ross 
688adee6784SGordon Ross /*ARGSUSED*/
689adee6784SGordon Ross int
smbfs_smb_findopenLM2(struct smbfs_fctx * ctx,struct smbnode * dnp,const char * wildcard,int wclen,uint32_t attr)690adee6784SGordon Ross smbfs_smb_findopenLM2(struct smbfs_fctx *ctx, struct smbnode *dnp,
691adee6784SGordon Ross     const char *wildcard, int wclen, uint32_t attr)
692adee6784SGordon Ross {
693adee6784SGordon Ross 
694adee6784SGordon Ross 	ctx->f_type = ft_LM2;
695adee6784SGordon Ross 	ctx->f_namesz = SMB_MAXFNAMELEN + 1;
696adee6784SGordon Ross 	ctx->f_name = kmem_alloc(ctx->f_namesz, KM_SLEEP);
697adee6784SGordon Ross 	ctx->f_infolevel = SMB_FIND_FULL_DIRECTORY_INFO;
698adee6784SGordon Ross 	ctx->f_attrmask = attr;
699adee6784SGordon Ross 	ctx->f_wildcard = wildcard;
700adee6784SGordon Ross 	ctx->f_wclen = wclen;
701adee6784SGordon Ross 	return (0);
702adee6784SGordon Ross }
703adee6784SGordon Ross 
704adee6784SGordon Ross int
smbfs_smb_findcloseLM2(struct smbfs_fctx * ctx)705adee6784SGordon Ross smbfs_smb_findcloseLM2(struct smbfs_fctx *ctx)
706adee6784SGordon Ross {
707adee6784SGordon Ross 	int error = 0;
708adee6784SGordon Ross 	if (ctx->f_name)
709adee6784SGordon Ross 		kmem_free(ctx->f_name, ctx->f_namesz);
710adee6784SGordon Ross 	if (ctx->f_t2)
711adee6784SGordon Ross 		smb_t2_done(ctx->f_t2);
712adee6784SGordon Ross 	md_done(&ctx->f_mdchain);
713adee6784SGordon Ross 
714adee6784SGordon Ross 	/*
715adee6784SGordon Ross 	 * If SMBFS_RDD_FINDFIRST is still set, we were opened
716adee6784SGordon Ross 	 * but never saw a findfirst, so we don't have any
717adee6784SGordon Ross 	 * search handle to close.
718adee6784SGordon Ross 	 */
719adee6784SGordon Ross 	if ((ctx->f_flags & (SMBFS_RDD_FINDFIRST | SMBFS_RDD_NOCLOSE)) == 0)
720adee6784SGordon Ross 		error = smbfs_smb1_findclose2(ctx);
721adee6784SGordon Ross 	return (error);
722adee6784SGordon Ross }
723adee6784SGordon Ross 
724adee6784SGordon Ross /*
725adee6784SGordon Ross  * Get a buffer of directory entries (if we don't already have
726adee6784SGordon Ross  * some remaining in the current buffer) then decode one.
727adee6784SGordon Ross  */
728adee6784SGordon Ross int
smbfs_smb_findnextLM2(struct smbfs_fctx * ctx,uint16_t limit)729adee6784SGordon Ross smbfs_smb_findnextLM2(struct smbfs_fctx *ctx, uint16_t limit)
730adee6784SGordon Ross {
731adee6784SGordon Ross 	int error;
732adee6784SGordon Ross 
733adee6784SGordon Ross 	/*
734adee6784SGordon Ross 	 * If we've scanned to the end of the current buffer
735adee6784SGordon Ross 	 * try to read anohther buffer of dir entries.
736adee6784SGordon Ross 	 * Treat anything less than 8 bytes as an "empty"
737adee6784SGordon Ross 	 * buffer to ensure we can read something.
738adee6784SGordon Ross 	 * (There may be up to 8 bytes of padding.)
739adee6784SGordon Ross 	 */
740adee6784SGordon Ross 	if ((ctx->f_eofs + 8) > ctx->f_left) {
741adee6784SGordon Ross 		/* Scanned the whole buffer. */
742adee6784SGordon Ross 		if (ctx->f_flags & SMBFS_RDD_EOF)
743adee6784SGordon Ross 			return (ENOENT);
744adee6784SGordon Ross 		ctx->f_limit = limit;
745adee6784SGordon Ross 		error = smbfs_smb1_trans2find2(ctx);
746adee6784SGordon Ross 		if (error)
747adee6784SGordon Ross 			return (error);
748adee6784SGordon Ross 		ctx->f_otws++;
749adee6784SGordon Ross 	}
750adee6784SGordon Ross 
751adee6784SGordon Ross 	/*
752adee6784SGordon Ross 	 * Decode one entry, advance f_eofs
753adee6784SGordon Ross 	 */
754adee6784SGordon Ross 	error = smbfs_decode_dirent(ctx);
755adee6784SGordon Ross 
756adee6784SGordon Ross 	return (error);
757adee6784SGordon Ross }
758adee6784SGordon Ross 
759adee6784SGordon Ross /*
760adee6784SGordon Ross  * Helper for smbfs_xa_get_streaminfo
761adee6784SGordon Ross  * Query stream info
762adee6784SGordon Ross  */
763adee6784SGordon Ross int
smbfs_smb1_get_streaminfo(smbnode_t * np,struct mdchain * mdp,struct smb_cred * scrp)764adee6784SGordon Ross smbfs_smb1_get_streaminfo(smbnode_t *np, struct mdchain *mdp,
765adee6784SGordon Ross 	struct smb_cred *scrp)
766adee6784SGordon Ross {
767adee6784SGordon Ross 	smb_share_t *ssp = np->n_mount->smi_share;
768adee6784SGordon Ross 	struct smb_vc *vcp = SSTOVC(ssp);
769adee6784SGordon Ross 	struct smb_t2rq *t2p = NULL;
770adee6784SGordon Ross 	struct mbchain *mbp;
771adee6784SGordon Ross 	mblk_t *m;
772adee6784SGordon Ross 	uint16_t cmd = SMB_TRANS2_QUERY_PATH_INFORMATION;
773adee6784SGordon Ross 	int error;
774adee6784SGordon Ross 
775adee6784SGordon Ross 	error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
776adee6784SGordon Ross 	if (error)
777adee6784SGordon Ross 		return (error);
778adee6784SGordon Ross 
779adee6784SGordon Ross 	mbp = &t2p->t2_tparam;
780adee6784SGordon Ross 	(void) mb_init(mbp);
781adee6784SGordon Ross 	(void) mb_put_uint16le(mbp, SMB_QFILEINFO_STREAM_INFO);
782adee6784SGordon Ross 	(void) mb_put_uint32le(mbp, 0);
783*0ddec5a4SToomas Soome 	error = smbfs_fullpath(mbp, vcp, np, NULL, 0, 0);
784adee6784SGordon Ross 	if (error)
785adee6784SGordon Ross 		goto out;
786adee6784SGordon Ross 
787adee6784SGordon Ross 	t2p->t2_maxpcount = 2;
788adee6784SGordon Ross 	t2p->t2_maxdcount = INT16_MAX;
789adee6784SGordon Ross 	error = smb_t2_request(t2p);
790adee6784SGordon Ross 	if (error) {
791adee6784SGordon Ross 		if (t2p->t2_sr_error == NT_STATUS_INVALID_PARAMETER)
792adee6784SGordon Ross 			error = ENOTSUP;
793adee6784SGordon Ross 		goto out;
794adee6784SGordon Ross 	}
795adee6784SGordon Ross 
796adee6784SGordon Ross 	/*
797adee6784SGordon Ross 	 * Have data.  Move it to *mdp
798adee6784SGordon Ross 	 */
799adee6784SGordon Ross 	m = t2p->t2_rdata.md_top;
800adee6784SGordon Ross 	if (m == NULL) {
801adee6784SGordon Ross 		error = EBADRPC;
802adee6784SGordon Ross 		goto out;
803adee6784SGordon Ross 	}
804adee6784SGordon Ross 	t2p->t2_rdata.md_top = NULL;
805adee6784SGordon Ross 	md_initm(mdp, m);
806adee6784SGordon Ross 
807adee6784SGordon Ross out:
808adee6784SGordon Ross 	smb_t2_done(t2p);
809adee6784SGordon Ross 	return (error);
810adee6784SGordon Ross }
811adee6784SGordon Ross 
812adee6784SGordon Ross /*
813adee6784SGordon Ross  * OTW function to Get a security descriptor (SD).
814adee6784SGordon Ross  *
815adee6784SGordon Ross  * The *reslen param is bufsize(in) / length(out)
816adee6784SGordon Ross  * Note: On success, this fills in mdp->md_top,
817adee6784SGordon Ross  * which the caller should free.
818adee6784SGordon Ross  */
819adee6784SGordon Ross int
smbfs_smb1_getsec(struct smb_share * ssp,uint16_t fid,uint32_t selector,mblk_t ** res,uint32_t * reslen,struct smb_cred * scrp)820adee6784SGordon Ross smbfs_smb1_getsec(struct smb_share *ssp, uint16_t fid,
821adee6784SGordon Ross 	uint32_t selector, mblk_t **res, uint32_t *reslen,
822adee6784SGordon Ross 	struct smb_cred *scrp)
823adee6784SGordon Ross {
824adee6784SGordon Ross 	struct smb_ntrq *ntp;
825adee6784SGordon Ross 	struct mbchain *mbp;
826adee6784SGordon Ross 	struct mdchain *mdp;
827adee6784SGordon Ross 	uint32_t dlen;
828adee6784SGordon Ross 	int error;
829adee6784SGordon Ross 
830adee6784SGordon Ross 	*res = NULL;
831adee6784SGordon Ross 
832adee6784SGordon Ross 	error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_QUERY_SECURITY_DESC,
833adee6784SGordon Ross 	    scrp, &ntp);
834adee6784SGordon Ross 	if (error)
835adee6784SGordon Ross 		return (error);
836adee6784SGordon Ross 
837adee6784SGordon Ross 	/* Parameters part */
838adee6784SGordon Ross 	mbp = &ntp->nt_tparam;
839adee6784SGordon Ross 	mb_init(mbp);
840adee6784SGordon Ross 	mb_put_uint16le(mbp, fid);
841adee6784SGordon Ross 	mb_put_uint16le(mbp, 0); /* reserved */
842adee6784SGordon Ross 	mb_put_uint32le(mbp, selector);
843adee6784SGordon Ross 	/* Data part (none) */
844adee6784SGordon Ross 
845adee6784SGordon Ross 	/* Max. returned parameters and data. */
846adee6784SGordon Ross 	ntp->nt_maxpcount = 4;
847adee6784SGordon Ross 	ntp->nt_maxdcount = *reslen;	// out buf size
848adee6784SGordon Ross 
849adee6784SGordon Ross 	error = smb_nt_request(ntp);
850adee6784SGordon Ross 	if (error && !(ntp->nt_flags & SMBT2_MOREDATA))
851adee6784SGordon Ross 		goto done;
852adee6784SGordon Ross 
853adee6784SGordon Ross 	/* Get data len */
854adee6784SGordon Ross 	mdp = &ntp->nt_rparam;
855adee6784SGordon Ross 	error = md_get_uint32le(mdp, &dlen);
856adee6784SGordon Ross 	if (error)
857adee6784SGordon Ross 		goto done;
858adee6784SGordon Ross 
859adee6784SGordon Ross 	/*
860adee6784SGordon Ross 	 * if there's more data than we said we could receive,
861adee6784SGordon Ross 	 * here is where we pick up the length of it
862adee6784SGordon Ross 	 */
863adee6784SGordon Ross 	*reslen = dlen;
864adee6784SGordon Ross 	if (dlen == 0) {
865adee6784SGordon Ross 		error = EBADRPC;
866adee6784SGordon Ross 		goto done;
867adee6784SGordon Ross 	}
868adee6784SGordon Ross 
869adee6784SGordon Ross 	/*
870adee6784SGordon Ross 	 * get the SD data part.
871adee6784SGordon Ross 	 */
872adee6784SGordon Ross 	mdp = &ntp->nt_rdata;
873adee6784SGordon Ross 	error = md_get_mbuf(mdp, dlen, res);
874adee6784SGordon Ross 
875adee6784SGordon Ross done:
876adee6784SGordon Ross 	if (error == 0 && *res == NULL) {
877adee6784SGordon Ross 		ASSERT(*res);
878adee6784SGordon Ross 		error = EBADRPC;
879adee6784SGordon Ross 	}
880adee6784SGordon Ross 
881adee6784SGordon Ross 	smb_nt_done(ntp);
882adee6784SGordon Ross 	return (error);
883adee6784SGordon Ross }
884adee6784SGordon Ross 
885adee6784SGordon Ross 
886adee6784SGordon Ross /*
887adee6784SGordon Ross  * OTW function to Set a security descriptor (SD).
888adee6784SGordon Ross  * Caller data are carried in an mbchain_t.
889adee6784SGordon Ross  *
890adee6784SGordon Ross  * Note: This normally consumes mbp->mb_top, and clears
891adee6784SGordon Ross  * that pointer when it does.
892adee6784SGordon Ross  */
893adee6784SGordon Ross int
smbfs_smb1_setsec(struct smb_share * ssp,uint16_t fid,uint32_t selector,mblk_t ** mp,struct smb_cred * scrp)894adee6784SGordon Ross smbfs_smb1_setsec(struct smb_share *ssp, uint16_t fid,
895adee6784SGordon Ross 	uint32_t selector, mblk_t **mp, struct smb_cred *scrp)
896adee6784SGordon Ross {
897adee6784SGordon Ross 	struct smb_ntrq *ntp;
898adee6784SGordon Ross 	struct mbchain *mbp;
899adee6784SGordon Ross 	int error;
900adee6784SGordon Ross 
901adee6784SGordon Ross 	error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_SET_SECURITY_DESC,
902adee6784SGordon Ross 	    scrp, &ntp);
903adee6784SGordon Ross 	if (error)
904adee6784SGordon Ross 		return (error);
905adee6784SGordon Ross 
906adee6784SGordon Ross 	/* Parameters part */
907adee6784SGordon Ross 	mbp = &ntp->nt_tparam;
908adee6784SGordon Ross 	mb_init(mbp);
909adee6784SGordon Ross 	mb_put_uint16le(mbp, fid);
910adee6784SGordon Ross 	mb_put_uint16le(mbp, 0); /* reserved */
911adee6784SGordon Ross 	mb_put_uint32le(mbp, selector);
912adee6784SGordon Ross 
913adee6784SGordon Ross 	/* Data part */
914adee6784SGordon Ross 	mbp = &ntp->nt_tdata;
915adee6784SGordon Ross 	mb_initm(mbp, *mp);
916adee6784SGordon Ross 	*mp = NULL; /* consumed */
917adee6784SGordon Ross 
918adee6784SGordon Ross 	/* No returned parameters or data. */
919adee6784SGordon Ross 	ntp->nt_maxpcount = 0;
920adee6784SGordon Ross 	ntp->nt_maxdcount = 0;
921adee6784SGordon Ross 
922adee6784SGordon Ross 	error = smb_nt_request(ntp);
923adee6784SGordon Ross 	smb_nt_done(ntp);
924adee6784SGordon Ross 
925adee6784SGordon Ross 	return (error);
926adee6784SGordon Ross }
927