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