Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-16824 SMB client connection setup rework
NEX-17232 SMB client reconnect failures
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (improve debug)
NEX-16818 Add fksmbcl development tool
NEX-17264 SMB client test tp_smbutil_013 fails after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (fix ref leaks)
2552 smbfs: add support for NFS-like remove
Portions contributed by: Gordon Ross <gordon.w.ross@gmail.com>
Reviewed by: Yuri Pankov <yuripv@yuripv.net>
Reviewed by: Jason King <jason.king@joyent.com>
Reviewed by: C Fraire <cfraire@me.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c
+++ new/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c
1 1 /*
2 2 * Copyright (c) 2000-2001 Boris Popov
3 3 * All rights reserved.
4 4 *
5 5 * Redistribution and use in source and binary forms, with or without
6 6 * modification, are permitted provided that the following conditions
7 7 * are met:
8 8 * 1. Redistributions of source code must retain the above copyright
9 9 * notice, this list of conditions and the following disclaimer.
10 10 * 2. Redistributions in binary form must reproduce the above copyright
11 11 * notice, this list of conditions and the following disclaimer in the
12 12 * documentation and/or other materials provided with the distribution.
13 13 * 3. All advertising materials mentioning features or use of this software
14 14 * must display the following acknowledgement:
15 15 * This product includes software developed by Boris Popov.
16 16 * 4. Neither the name of the author nor the names of any co-contributors
17 17 * may be used to endorse or promote products derived from this software
18 18 * without specific prior written permission.
19 19 *
20 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
21 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 30 * SUCH DAMAGE.
31 - *
32 - * $Id: smbfs_smb.c,v 1.73.38.1 2005/05/27 02:35:28 lindak Exp $
33 31 */
34 32
35 33 /*
36 - * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
37 34 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
38 35 * Use is subject to license terms.
36 + *
37 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
39 38 */
40 39
41 40 #include <sys/param.h>
42 41 #include <sys/systm.h>
42 +#include <sys/inttypes.h>
43 43 #include <sys/time.h>
44 44 #include <sys/vnode.h>
45 45 #include <sys/sunddi.h>
46 46 #include <sys/cmn_err.h>
47 47
48 48 #include <netsmb/smb_osdep.h>
49 49
50 50 #include <netsmb/smb.h>
51 +#include <netsmb/smb2.h>
51 52 #include <netsmb/smb_conn.h>
52 53 #include <netsmb/smb_subr.h>
53 54 #include <netsmb/smb_rq.h>
54 55
55 56 #include <smbfs/smbfs.h>
56 57 #include <smbfs/smbfs_node.h>
57 58 #include <smbfs/smbfs_subr.h>
58 59
59 60 /*
60 61 * Jan 1 1980 as 64 bit NT time.
61 62 * (tenths of microseconds since 1601)
62 63 */
63 64 const uint64_t NT1980 = 11960035200ULL*10000000ULL;
64 65
65 -/*
66 - * Local functions.
67 - * Not static, to aid debugging.
68 - */
69 66
70 -int smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen,
71 - struct smbfattr *fap, struct smb_cred *scrp);
72 -int smbfs_smb_trans2_query(struct smbnode *np, struct smbfattr *fap,
73 - struct smb_cred *scrp, uint16_t infolevel);
74 -
75 -int smbfs_smb_statfsLM1(struct smb_share *ssp,
76 - statvfs64_t *sbp, struct smb_cred *scrp);
77 -int smbfs_smb_statfsLM2(struct smb_share *ssp,
78 - statvfs64_t *sbp, struct smb_cred *scrp);
79 -
80 -int smbfs_smb_setfattrNT(struct smbnode *np, int fid,
81 - uint32_t attr, struct timespec *mtime, struct timespec *atime,
82 - struct smb_cred *scrp);
83 -
84 -int smbfs_smb_setftime1(struct smbnode *np, uint16_t fid,
85 - struct timespec *mtime, struct timespec *atime,
86 - struct smb_cred *scrp);
87 -
88 -int smbfs_smb_setpattr1(struct smbnode *np,
89 - const char *name, int len, uint32_t attr,
90 - struct timespec *mtime, struct smb_cred *scrp);
91 -
92 -
93 67 /*
94 - * Todo: locking over-the-wire
68 + * Helper for smbfs_getattr_otw
69 + * used when we have an open FID
95 70 */
96 -#ifdef APPLE
97 -
98 -static int
99 -smbfs_smb_lockandx(struct smbnode *np, int op, uint32_t pid,
100 - offset_t start, uint64_t len, int largelock,
101 - struct smb_cred *scrp, uint32_t timeout)
71 +int
72 +smbfs_smb_getfattr(
73 + struct smbnode *np,
74 + smb_fh_t *fhp,
75 + struct smbfattr *fap,
76 + struct smb_cred *scrp)
102 77 {
103 78 struct smb_share *ssp = np->n_mount->smi_share;
104 - struct smb_rq rq, *rqp = &rq;
105 - struct mbchain *mbp;
106 - uint8_t ltype = 0;
107 79 int error;
108 80
109 - /* Shared lock for n_fid use below. */
110 - ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
111 -
112 - /* After reconnect, n_fid is invalid */
113 - if (np->n_vcgenid != ssp->ss_vcgenid)
114 - return (ESTALE);
115 -
116 - if (op == SMB_LOCK_SHARED)
117 - ltype |= SMB_LOCKING_ANDX_SHARED_LOCK;
118 - /* XXX: if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)? */
119 - if (largelock)
120 - ltype |= SMB_LOCKING_ANDX_LARGE_FILES;
121 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scrp);
122 - if (error)
123 - return (error);
124 - smb_rq_getrequest(rqp, &mbp);
125 - smb_rq_wstart(rqp);
126 - mb_put_uint8(mbp, 0xff); /* secondary command */
127 - mb_put_uint8(mbp, 0); /* MBZ */
128 - mb_put_uint16le(mbp, 0);
129 - mb_put_uint16le(mbp, np->n_fid);
130 - mb_put_uint8(mbp, ltype); /* locktype */
131 - mb_put_uint8(mbp, 0); /* oplocklevel - 0 seems is NO_OPLOCK */
132 - mb_put_uint32le(mbp, timeout); /* 0 nowait, -1 infinite wait */
133 - mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 1 : 0);
134 - mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 0 : 1);
135 - smb_rq_wend(rqp);
136 - smb_rq_bstart(rqp);
137 - mb_put_uint16le(mbp, pid);
138 - if (!largelock) {
139 - mb_put_uint32le(mbp, start);
140 - mb_put_uint32le(mbp, len);
81 + if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
82 + error = smbfs_smb2_qfileinfo(ssp, &fhp->fh_fid2, fap, scrp);
141 83 } else {
142 - mb_put_uint16le(mbp, 0); /* pad */
143 - mb_put_uint32le(mbp, start >> 32); /* OffsetHigh */
144 - mb_put_uint32le(mbp, start & 0xffffffff); /* OffsetLow */
145 - mb_put_uint32le(mbp, len >> 32); /* LengthHigh */
146 - mb_put_uint32le(mbp, len & 0xffffffff); /* LengthLow */
84 + error = smbfs_smb1_trans2_query(np, fhp->fh_fid1, fap, scrp);
147 85 }
148 - smb_rq_bend(rqp);
149 - /*
150 - * Don't want to risk missing a successful
151 - * unlock send or lock response, or we could
152 - * lose track of an outstanding lock.
153 - */
154 - if (op == SMB_LOCK_RELEASE)
155 - rqp->sr_flags |= SMBR_NOINTR_SEND;
156 - else
157 - rqp->sr_flags |= SMBR_NOINTR_RECV;
158 86
159 - error = smb_rq_simple(rqp);
160 - smb_rq_done(rqp);
161 87 return (error);
162 88 }
163 89
164 -int
165 -smbfs_smb_lock(struct smbnode *np, int op, caddr_t id,
166 - offset_t start, uint64_t len, int largelock,
167 - struct smb_cred *scrp, uint32_t timeout)
168 -{
169 - struct smb_share *ssp = np->n_mount->smi_share;
170 -
171 - if (SMB_DIALECT(SSTOVC(ssp)) < SMB_DIALECT_LANMAN1_0)
172 - /*
173 - * TODO: use LOCK_BYTE_RANGE here.
174 - */
175 - return (EINVAL);
176 -
177 - /*
178 - * XXX: compute largelock via:
179 - * (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)?
180 - */
181 - return (smbfs_smb_lockandx(np, op, (uint32_t)id, start, len,
182 - largelock, scrp, timeout));
183 -}
184 -
185 -#endif /* APPLE */
186 -
187 90 /*
188 - * Helper for smbfs_getattr
189 - * Something like nfs_getattr_otw
91 + * Helper for smbfs_getattr_otw
92 + * used when we don't have an open FID
93 + *
94 + * For SMB1 we can just use the path form of trans2 query.
95 + * For SMB2 we need to do an attribute-only open.
96 + * See smbfs_smb2_getpattr()
190 97 */
191 98 int
192 -smbfs_smb_getfattr(
99 +smbfs_smb_getpattr(
193 100 struct smbnode *np,
194 101 struct smbfattr *fap,
195 102 struct smb_cred *scrp)
196 103 {
104 + struct smb_share *ssp = np->n_mount->smi_share;
197 105 int error;
198 106
199 - /*
200 - * This lock is necessary for FID-based calls.
201 - * Lock may be writer (via open) or reader.
202 - */
203 - ASSERT(np->r_lkserlock.count != 0);
204 -
205 - /*
206 - * Extended attribute directory or file.
207 - */
208 - if (np->n_flag & N_XATTR) {
209 - error = smbfs_xa_getfattr(np, fap, scrp);
210 - return (error);
107 + if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
108 + error = smbfs_smb2_getpattr(np, fap, scrp);
109 + } else {
110 + uint16_t fid = SMB_FID_UNUSED;
111 + error = smbfs_smb1_trans2_query(np, fid, fap, scrp);
211 112 }
212 113
213 - error = smbfs_smb_trans2_query(np, fap, scrp, 0);
214 - if (error != EINVAL)
215 - return (error);
216 -
217 - /* fallback */
218 - error = smbfs_smb_query_info(np, NULL, 0, fap, scrp);
219 -
220 114 return (error);
221 115 }
222 116
223 117 /*
224 - * Common function for QueryFileInfo, QueryPathInfo.
118 + * Get and parse FileFsAttributeInformation
225 119 */
226 120 int
227 -smbfs_smb_trans2_query(struct smbnode *np, struct smbfattr *fap,
228 - struct smb_cred *scrp, uint16_t infolevel)
229 -{
230 - struct smb_share *ssp = np->n_mount->smi_share;
231 - struct smb_vc *vcp = SSTOVC(ssp);
232 - struct smb_t2rq *t2p;
233 - int error, svtz, timesok = 1;
234 - struct mbchain *mbp;
235 - struct mdchain *mdp;
236 - uint16_t cmd, date, time, wattr;
237 - uint64_t llongint, lsize;
238 - uint32_t size, dattr;
239 -
240 - /*
241 - * Shared lock for n_fid use below.
242 - * See smbfs_smb_getfattr()
243 - */
244 - ASSERT(np->r_lkserlock.count != 0);
245 -
246 - /*
247 - * If we have a valid open FID, use it.
248 - */
249 - if ((np->n_fidrefs > 0) &&
250 - (np->n_fid != SMB_FID_UNUSED) &&
251 - (np->n_vcgenid == ssp->ss_vcgenid))
252 - cmd = SMB_TRANS2_QUERY_FILE_INFORMATION;
253 - else
254 - cmd = SMB_TRANS2_QUERY_PATH_INFORMATION;
255 -
256 -top:
257 - error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
258 - if (error)
259 - return (error);
260 - mbp = &t2p->t2_tparam;
261 - mb_init(mbp);
262 - if (!infolevel) {
263 - if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12)
264 - infolevel = SMB_QFILEINFO_STANDARD;
265 - else
266 - infolevel = SMB_QFILEINFO_ALL_INFO;
267 - }
268 -
269 - if (cmd == SMB_TRANS2_QUERY_FILE_INFORMATION)
270 - mb_put_uint16le(mbp, np->n_fid);
271 -
272 - mb_put_uint16le(mbp, infolevel);
273 -
274 - if (cmd == SMB_TRANS2_QUERY_PATH_INFORMATION) {
275 - mb_put_uint32le(mbp, 0);
276 - /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */
277 - error = smbfs_fullpath(mbp, vcp, np, NULL, 0, '\\');
278 - if (error) {
279 - smb_t2_done(t2p);
280 - return (error);
281 - }
282 - }
283 -
284 - t2p->t2_maxpcount = 2;
285 - t2p->t2_maxdcount = vcp->vc_txmax;
286 - error = smb_t2_request(t2p);
287 - if (error) {
288 - smb_t2_done(t2p);
289 - /* Invalid info level? Try fallback. */
290 - if (error == EINVAL &&
291 - infolevel == SMB_QFILEINFO_ALL_INFO) {
292 - infolevel = SMB_QFILEINFO_STANDARD;
293 - goto top;
294 - }
295 - return (error);
296 - }
297 - mdp = &t2p->t2_rdata;
298 - svtz = vcp->vc_sopt.sv_tz;
299 - switch (infolevel) {
300 - case SMB_QFILEINFO_STANDARD:
301 - md_get_uint16le(mdp, &date);
302 - md_get_uint16le(mdp, &time); /* creation time */
303 - smb_dos2unixtime(date, time, 0, svtz, &fap->fa_createtime);
304 - md_get_uint16le(mdp, &date);
305 - md_get_uint16le(mdp, &time); /* access time */
306 - smb_dos2unixtime(date, time, 0, svtz, &fap->fa_atime);
307 - md_get_uint16le(mdp, &date);
308 - md_get_uint16le(mdp, &time); /* modify time */
309 - smb_dos2unixtime(date, time, 0, svtz, &fap->fa_mtime);
310 - md_get_uint32le(mdp, &size); /* EOF position */
311 - fap->fa_size = size;
312 - md_get_uint32le(mdp, &size); /* allocation size */
313 - fap->fa_allocsz = size;
314 - error = md_get_uint16le(mdp, &wattr);
315 - fap->fa_attr = wattr;
316 - timesok = 1;
317 - break;
318 - case SMB_QFILEINFO_ALL_INFO:
319 - timesok = 0;
320 - /* creation time */
321 - md_get_uint64le(mdp, &llongint);
322 - if (llongint)
323 - timesok++;
324 - smb_time_NT2local(llongint, &fap->fa_createtime);
325 -
326 - /* last access time */
327 - md_get_uint64le(mdp, &llongint);
328 - if (llongint)
329 - timesok++;
330 - smb_time_NT2local(llongint, &fap->fa_atime);
331 -
332 - /* last write time */
333 - md_get_uint64le(mdp, &llongint);
334 - if (llongint)
335 - timesok++;
336 - smb_time_NT2local(llongint, &fap->fa_mtime);
337 -
338 - /* last change time */
339 - md_get_uint64le(mdp, &llongint);
340 - if (llongint)
341 - timesok++;
342 - smb_time_NT2local(llongint, &fap->fa_ctime);
343 -
344 - /* attributes */
345 - md_get_uint32le(mdp, &dattr);
346 - fap->fa_attr = dattr;
347 -
348 - /*
349 - * 4-Byte alignment - discard
350 - * Specs don't talk about this.
351 - */
352 - md_get_uint32le(mdp, NULL);
353 - /* allocation size */
354 - md_get_uint64le(mdp, &lsize);
355 - fap->fa_allocsz = lsize;
356 - /* File size */
357 - error = md_get_uint64le(mdp, &lsize);
358 - fap->fa_size = lsize;
359 - break;
360 - default:
361 - SMBVDEBUG("unexpected info level %d\n", infolevel);
362 - error = EINVAL;
363 - }
364 - smb_t2_done(t2p);
365 - /*
366 - * if all times are zero (observed with FAT on NT4SP6)
367 - * then fall back to older info level
368 - */
369 - if (!timesok) {
370 - if (infolevel == SMB_QFILEINFO_ALL_INFO) {
371 - infolevel = SMB_QFILEINFO_STANDARD;
372 - goto top;
373 - }
374 - error = EINVAL;
375 - }
376 - return (error);
377 -}
378 -
379 -/*
380 - * Support functions for _qstreaminfo
381 - * Moved to smbfs_xattr.c
382 - */
383 -
384 -int
385 121 smbfs_smb_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *fsa,
386 122 struct smb_cred *scrp)
387 123 {
388 - struct smb_t2rq *t2p;
389 - struct mbchain *mbp;
390 - struct mdchain *mdp;
391 124 int error;
392 - uint32_t nlen;
393 125
394 - error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION,
395 - scrp, &t2p);
396 - if (error)
397 - return (error);
398 - mbp = &t2p->t2_tparam;
399 - mb_init(mbp);
400 - mb_put_uint16le(mbp, SMB_QFS_ATTRIBUTE_INFO);
401 - t2p->t2_maxpcount = 4;
402 - t2p->t2_maxdcount = 4 * 3 + 512;
403 - error = smb_t2_request(t2p);
404 - if (error)
405 - goto out;
406 -
407 - mdp = &t2p->t2_rdata;
408 - md_get_uint32le(mdp, &fsa->fsa_aflags);
409 - md_get_uint32le(mdp, &fsa->fsa_maxname);
410 - error = md_get_uint32le(mdp, &nlen); /* fs name length */
411 - if (error)
412 - goto out;
413 -
414 - /*
415 - * Get the FS type name.
416 - */
417 - bzero(fsa->fsa_tname, FSTYPSZ);
418 - if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) {
419 - uint16_t tmpbuf[FSTYPSZ];
420 - size_t tmplen, outlen;
421 -
422 - if (nlen > sizeof (tmpbuf))
423 - nlen = sizeof (tmpbuf);
424 - error = md_get_mem(mdp, tmpbuf, nlen, MB_MSYSTEM);
425 - tmplen = nlen / 2; /* UCS-2 chars */
426 - outlen = FSTYPSZ - 1;
427 - (void) uconv_u16tou8(tmpbuf, &tmplen,
428 - (uchar_t *)fsa->fsa_tname, &outlen,
429 - UCONV_IN_LITTLE_ENDIAN);
126 + if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
127 + error = smbfs_smb2_qfsattr(ssp, fsa, scrp);
430 128 } else {
431 - if (nlen > (FSTYPSZ - 1))
432 - nlen = FSTYPSZ - 1;
433 - error = md_get_mem(mdp, fsa->fsa_tname, nlen, MB_MSYSTEM);
129 + error = smbfs_smb1_qfsattr(ssp, fsa, scrp);
434 130 }
435 131
436 132 /*
437 133 * If fs_name starts with FAT, we can't set dates before 1980
438 134 */
439 135 if (0 == strncmp(fsa->fsa_tname, "FAT", 3)) {
440 136 SMB_SS_LOCK(ssp);
441 137 ssp->ss_flags |= SMBS_FST_FAT;
442 138 SMB_SS_UNLOCK(ssp);
443 139 }
444 140
445 -out:
446 - smb_t2_done(t2p);
447 - return (0);
141 + return (error);
448 142 }
449 143
450 144 int
451 145 smbfs_smb_statfs(struct smb_share *ssp, statvfs64_t *sbp,
452 146 struct smb_cred *scp)
453 147 {
454 - int error;
455 -
456 - if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0)
457 - error = smbfs_smb_statfsLM2(ssp, sbp, scp);
458 - else
459 - error = smbfs_smb_statfsLM1(ssp, sbp, scp);
460 -
461 - return (error);
462 -}
463 -
464 -int
465 -smbfs_smb_statfsLM2(struct smb_share *ssp, statvfs64_t *sbp,
466 - struct smb_cred *scrp)
467 -{
468 - struct smb_t2rq *t2p;
469 - struct mbchain *mbp;
470 - struct mdchain *mdp;
471 - uint16_t bsize;
472 - uint32_t units, bpu, funits;
473 - uint64_t s, t, f;
474 - int error;
475 -
476 - error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION,
477 - scrp, &t2p);
478 - if (error)
479 - return (error);
480 - mbp = &t2p->t2_tparam;
481 - mb_init(mbp);
482 - mb_put_uint16le(mbp, SMB_QFS_ALLOCATION);
483 - t2p->t2_maxpcount = 4;
484 - t2p->t2_maxdcount = 4 * 4 + 2;
485 - error = smb_t2_request(t2p);
486 - if (error)
487 - goto out;
488 -
489 - mdp = &t2p->t2_rdata;
490 - md_get_uint32le(mdp, NULL); /* fs id */
491 - md_get_uint32le(mdp, &bpu);
492 - md_get_uint32le(mdp, &units);
493 - md_get_uint32le(mdp, &funits);
494 - error = md_get_uint16le(mdp, &bsize);
495 - if (error)
496 - goto out;
497 - s = bsize;
498 - s *= bpu;
499 - t = units;
500 - f = funits;
501 - /*
502 - * Don't allow over-large blocksizes as they determine
503 - * Finder List-view size granularities. On the other
504 - * hand, we mustn't let the block count overflow the
505 - * 31 bits available.
506 - */
507 - while (s > 16 * 1024) {
508 - if (t > LONG_MAX)
509 - break;
510 - s /= 2;
511 - t *= 2;
512 - f *= 2;
513 - }
514 - while (t > LONG_MAX) {
515 - t /= 2;
516 - f /= 2;
517 - s *= 2;
518 - }
519 - sbp->f_bsize = (ulong_t)s; /* file system block size */
520 - sbp->f_blocks = t; /* total data blocks in file system */
521 - sbp->f_bfree = f; /* free blocks in fs */
522 - sbp->f_bavail = f; /* free blocks avail to non-superuser */
523 - sbp->f_files = (-1); /* total file nodes in file system */
524 - sbp->f_ffree = (-1); /* free file nodes in fs */
525 -
526 -out:
527 - smb_t2_done(t2p);
528 - return (0);
529 -}
530 -
531 -int
532 -smbfs_smb_statfsLM1(struct smb_share *ssp, statvfs64_t *sbp,
533 - struct smb_cred *scrp)
534 -{
535 - struct smb_rq rq, *rqp = &rq;
536 - struct mdchain *mdp;
537 - uint16_t units, bpu, bsize, funits;
538 - uint64_t s, t, f;
539 - int error;
540 -
541 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK,
542 - scrp);
543 - if (error)
544 - return (error);
545 - smb_rq_wstart(rqp);
546 - smb_rq_wend(rqp);
547 - smb_rq_bstart(rqp);
548 - smb_rq_bend(rqp);
549 - error = smb_rq_simple(rqp);
550 - if (error)
551 - goto out;
552 -
553 - smb_rq_getreply(rqp, &mdp);
554 - md_get_uint16le(mdp, &units);
555 - md_get_uint16le(mdp, &bpu);
556 - md_get_uint16le(mdp, &bsize);
557 - error = md_get_uint16le(mdp, &funits);
558 - if (error)
559 - goto out;
560 - s = bsize;
561 - s *= bpu;
562 - t = units;
563 - f = funits;
564 - /*
565 - * Don't allow over-large blocksizes as they determine
566 - * Finder List-view size granularities. On the other
567 - * hand, we mustn't let the block count overflow the
568 - * 31 bits available.
569 - */
570 - while (s > 16 * 1024) {
571 - if (t > LONG_MAX)
572 - break;
573 - s /= 2;
574 - t *= 2;
575 - f *= 2;
576 - }
577 - while (t > LONG_MAX) {
578 - t /= 2;
579 - f /= 2;
580 - s *= 2;
581 - }
582 - sbp->f_bsize = (ulong_t)s; /* file system block size */
583 - sbp->f_blocks = t; /* total data blocks in file system */
584 - sbp->f_bfree = f; /* free blocks in fs */
585 - sbp->f_bavail = f; /* free blocks avail to non-superuser */
586 - sbp->f_files = (-1); /* total file nodes in file system */
587 - sbp->f_ffree = (-1); /* free file nodes in fs */
588 -
589 -out:
590 - smb_rq_done(rqp);
591 - return (0);
592 -}
593 -
594 -int
595 -smbfs_smb_seteof(struct smb_share *ssp, uint16_t fid, uint64_t newsize,
596 - struct smb_cred *scrp)
597 -{
598 - struct smb_t2rq *t2p;
148 + struct smb_fs_size_info info;
599 149 struct smb_vc *vcp = SSTOVC(ssp);
600 - struct mbchain *mbp;
150 + uint32_t bps, spu;
601 151 int error;
602 152
603 - error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION,
604 - scrp, &t2p);
605 - if (error)
606 - return (error);
607 - mbp = &t2p->t2_tparam;
608 - mb_init(mbp);
609 - mb_put_uint16le(mbp, fid);
610 - if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
611 - mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFORMATION);
612 - else
613 - mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFO);
614 - mb_put_uint16le(mbp, 0); /* pad */
615 - mbp = &t2p->t2_tdata;
616 - mb_init(mbp);
617 - mb_put_uint64le(mbp, newsize);
618 - t2p->t2_maxpcount = 2;
619 - t2p->t2_maxdcount = 0;
620 - error = smb_t2_request(t2p);
621 - smb_t2_done(t2p);
622 - return (error);
623 -}
624 -
625 -/*ARGSUSED*/
626 -int
627 -smbfs_smb_t2rename(struct smbnode *np, struct smbnode *tdnp,
628 - const char *tname, int tnmlen, struct smb_cred *scrp, int overwrite)
629 -{
630 - struct smb_t2rq *t2p;
631 - struct smb_share *ssp = np->n_mount->smi_share;
632 - struct smb_vc *vcp = SSTOVC(ssp);
633 - struct mbchain *mbp;
634 - int32_t *ucslenp;
635 - int error, cerror;
636 - uint16_t fid = 0;
637 -
638 - /* Shared lock for n_fid use below. */
639 - ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
640 -
641 - /* After reconnect, n_fid is invalid */
642 - if (np->n_vcgenid != ssp->ss_vcgenid)
643 - return (ESTALE);
644 -
645 - if (!(vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU))
646 - return (ENOTSUP);
647 - error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION,
648 - scrp, &t2p);
649 - if (error)
650 - return (error);
651 - if (tdnp) {
652 - error = smbfs_smb_tmpopen(tdnp, SA_RIGHT_FILE_READ_DATA, scrp,
653 - &fid);
654 - if (error)
655 - goto exit;
153 + if (vcp->vc_flags & SMBV_SMB2) {
154 + error = smbfs_smb2_statfs(ssp, &info, scp);
155 + } else {
156 + error = smbfs_smb1_statfs(ssp, &info, scp);
656 157 }
657 - mbp = &t2p->t2_tparam;
658 - mb_init(mbp);
659 - mb_put_uint16le(mbp, np->n_fid);
660 - mb_put_uint16le(mbp, SMB_SFILEINFO_RENAME_INFORMATION);
661 - mb_put_uint16le(mbp, 0); /* reserved, nowadays */
662 - mbp = &t2p->t2_tdata;
663 - mb_init(mbp);
664 - mb_put_uint32le(mbp, overwrite);
665 - mb_put_uint16le(mbp, fid); /* base for tname */
666 - mb_put_uint16le(mbp, 0); /* part of a 32bit fid? */
667 - ucslenp = (int32_t *)mb_reserve(mbp, sizeof (int32_t));
668 - mbp->mb_count = 0;
669 - error = smb_put_dstring(mbp, vcp, tname, SMB_CS_NONE);
670 158 if (error)
671 - goto exit;
672 - mbp->mb_count--; /* don't count the null */
673 - *ucslenp = htolel(mbp->mb_count);
674 - t2p->t2_maxpcount = 2;
675 - t2p->t2_maxdcount = 0;
676 - error = smb_t2_request(t2p);
677 -exit:
678 - if (fid) {
679 - cerror = smbfs_smb_tmpclose(tdnp, fid, scrp);
680 - if (cerror)
681 - SMBVDEBUG("error %d closing %s\n",
682 - cerror, tdnp->n_rpath);
683 - }
684 - smb_t2_done(t2p);
685 - return (error);
686 -}
687 -
688 -int
689 -smbfs_smb_flush(struct smbnode *np, struct smb_cred *scrp)
690 -{
691 - struct smb_share *ssp = np->n_mount->smi_share;
692 - struct smb_rq rq, *rqp = &rq;
693 - struct mbchain *mbp;
694 - int error;
695 -
696 - /* Shared lock for n_fid use below. */
697 - ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
698 -
699 - if (!(np->n_flag & NFLUSHWIRE))
700 - return (0);
701 - if (np->n_fidrefs == 0)
702 - return (0); /* not open */
703 -
704 - /* After reconnect, n_fid is invalid */
705 - if (np->n_vcgenid != ssp->ss_vcgenid)
706 - return (ESTALE);
707 -
708 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scrp);
709 - if (error)
710 159 return (error);
711 - smb_rq_getrequest(rqp, &mbp);
712 - smb_rq_wstart(rqp);
713 - mb_put_uint16le(mbp, np->n_fid);
714 - smb_rq_wend(rqp);
715 - smb_rq_bstart(rqp);
716 - smb_rq_bend(rqp);
717 - error = smb_rq_simple(rqp);
718 - smb_rq_done(rqp);
719 - if (!error) {
720 - mutex_enter(&np->r_statelock);
721 - np->n_flag &= ~NFLUSHWIRE;
722 - mutex_exit(&np->r_statelock);
723 - }
724 - return (error);
725 -}
726 160
727 -int
728 -smbfs_smb_setfsize(struct smbnode *np, uint16_t fid, uint64_t newsize,
729 - struct smb_cred *scrp)
730 -{
731 - struct smb_share *ssp = np->n_mount->smi_share;
732 - struct smb_rq rq, *rqp = &rq;
733 - struct mbchain *mbp;
734 - int error;
161 + /* A bit of paranoia. */
162 + bps = info.bytes_per_sect;
163 + if (bps < DEV_BSIZE)
164 + bps = DEV_BSIZE;
165 + spu = info.sect_per_unit;
166 + if (spu == 0)
167 + spu = 1;
735 168
736 - if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
737 - /*
738 - * This call knows about 64-bit offsets.
739 - */
740 - error = smbfs_smb_seteof(ssp, fid, newsize, scrp);
741 - if (!error) {
742 - mutex_enter(&np->r_statelock);
743 - np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
744 - mutex_exit(&np->r_statelock);
745 - return (0);
746 - }
747 - }
169 + /* preferred file system block size */
170 + sbp->f_bsize = bps * spu;
748 171
749 - /*
750 - * OK, so fallback to SMB_COM_WRITE, but note:
751 - * it only supports 32-bit file offsets.
752 - */
753 - if (newsize > UINT32_MAX)
754 - return (EFBIG);
172 + /* file system block size ("fragment size") */
173 + sbp->f_frsize = bps;
755 174
756 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_WRITE, scrp);
757 - if (error)
758 - return (error);
759 - smb_rq_getrequest(rqp, &mbp);
760 - smb_rq_wstart(rqp);
761 - mb_put_uint16le(mbp, fid);
762 - mb_put_uint16le(mbp, 0);
763 - mb_put_uint32le(mbp, newsize);
764 - mb_put_uint16le(mbp, 0);
765 - smb_rq_wend(rqp);
766 - smb_rq_bstart(rqp);
767 - mb_put_uint8(mbp, SMB_DT_DATA);
768 - mb_put_uint16le(mbp, 0);
769 - smb_rq_bend(rqp);
770 - error = smb_rq_simple(rqp);
771 - smb_rq_done(rqp);
772 - mutex_enter(&np->r_statelock);
773 - np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
774 - mutex_exit(&np->r_statelock);
775 - return (error);
776 -}
175 + /* total blocks of f_frsize */
176 + sbp->f_blocks = info.total_units * spu;
777 177
778 -/*
779 - * Old method for getting file attributes.
780 - */
781 -int
782 -smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen,
783 - struct smbfattr *fap, struct smb_cred *scrp)
784 -{
785 - struct smb_rq rq, *rqp = &rq;
786 - struct smb_share *ssp = np->n_mount->smi_share;
787 - struct mbchain *mbp;
788 - struct mdchain *mdp;
789 - uint8_t wc;
790 - int error;
791 - uint16_t wattr;
792 - uint32_t longint;
178 + /* free blocks of f_frsize */
179 + sbp->f_bfree = info.actual_avail * spu;
793 180
794 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scrp);
795 - if (error)
796 - return (error);
797 - smb_rq_getrequest(rqp, &mbp);
798 - smb_rq_wstart(rqp);
799 - smb_rq_wend(rqp);
800 - smb_rq_bstart(rqp);
801 - mb_put_uint8(mbp, SMB_DT_ASCII);
181 + /* free blocks avail to non-superuser */
182 + sbp->f_bavail = info.caller_avail * spu;
802 183
803 - error = smbfs_fullpath(mbp, SSTOVC(ssp), np,
804 - name, nmlen, '\\');
805 - if (error)
806 - goto out;
807 - smb_rq_bend(rqp);
808 - error = smb_rq_simple(rqp);
809 - if (error)
810 - goto out;
811 - smb_rq_getreply(rqp, &mdp);
812 - error = md_get_uint8(mdp, &wc);
813 - if (error)
814 - goto out;
815 - if (wc != 10) {
816 - error = EBADRPC;
817 - goto out;
818 - }
819 - md_get_uint16le(mdp, &wattr);
820 - fap->fa_attr = wattr;
821 - /*
822 - * Be careful using the time returned here, as
823 - * with FAT on NT4SP6, at least, the time returned is low
824 - * 32 bits of 100s of nanoseconds (since 1601) so it rolls
825 - * over about every seven minutes!
826 - */
827 - md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */
828 - smb_time_server2local(longint,
829 - SSTOVC(ssp)->vc_sopt.sv_tz, &fap->fa_mtime);
830 - error = md_get_uint32le(mdp, &longint);
831 - fap->fa_size = longint;
184 + sbp->f_files = (-1); /* total file nodes in file system */
185 + sbp->f_ffree = (-1); /* free file nodes in fs */
832 186
833 -out:
834 - smb_rq_done(rqp);
835 187 return (error);
836 188 }
837 189
838 -/*
839 - * Set DOS file attributes. mtime should be NULL for dialects above lm10
840 - */
841 190 int
842 -smbfs_smb_setpattr1(struct smbnode *np, const char *name, int len,
843 - uint32_t attr, struct timespec *mtime,
844 - struct smb_cred *scrp)
191 +smbfs_smb_setdisp(struct smb_share *ssp, smb_fh_t *fhp,
192 + uint8_t disp, struct smb_cred *scrp)
845 193 {
846 - struct smb_rq rq, *rqp = &rq;
847 - struct smb_share *ssp = np->n_mount->smi_share;
848 - struct mbchain *mbp;
849 - long time;
850 - int error, svtz;
194 + int err;
851 195
852 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION, scrp);
853 - if (error)
854 - return (error);
855 - svtz = SSTOVC(ssp)->vc_sopt.sv_tz;
856 - smb_rq_getrequest(rqp, &mbp);
857 - smb_rq_wstart(rqp);
858 - mb_put_uint16le(mbp, (uint16_t)attr);
859 - if (mtime) {
860 - smb_time_local2server(mtime, svtz, &time);
861 - } else
862 - time = 0;
863 - mb_put_uint32le(mbp, time); /* mtime */
864 - mb_put_mem(mbp, NULL, 5 * 2, MB_MZERO);
865 - smb_rq_wend(rqp);
866 - smb_rq_bstart(rqp);
867 - mb_put_uint8(mbp, SMB_DT_ASCII);
868 -
869 - error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, len, '\\');
870 - if (error)
871 - goto out;
872 - mb_put_uint8(mbp, SMB_DT_ASCII);
873 - if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) {
874 - mb_put_padbyte(mbp);
875 - mb_put_uint8(mbp, 0); /* 1st byte NULL Unicode char */
196 + if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
197 + err = smbfs_smb2_setdisp(ssp, &fhp->fh_fid2, disp, scrp);
198 + } else {
199 + err = smbfs_smb1_setdisp(ssp, fhp->fh_fid1, disp, scrp);
876 200 }
877 - mb_put_uint8(mbp, 0);
878 - smb_rq_bend(rqp);
879 - error = smb_rq_simple(rqp);
880 201
881 -out:
882 - smb_rq_done(rqp);
883 - return (error);
202 + return (err);
884 203 }
885 204
886 205 int
887 -smbfs_smb_hideit(struct smbnode *np, const char *name, int len,
888 - struct smb_cred *scrp)
206 +smbfs_smb_setfsize(struct smb_share *ssp, smb_fh_t *fhp,
207 + uint64_t size, struct smb_cred *scrp)
889 208 {
890 - struct smbfattr fa;
891 209 int error;
892 - uint32_t attr;
893 210
894 - error = smbfs_smb_query_info(np, name, len, &fa, scrp);
895 - attr = fa.fa_attr;
896 - if (!error && !(attr & SMB_FA_HIDDEN)) {
897 - attr |= SMB_FA_HIDDEN;
898 - error = smbfs_smb_setpattr1(np, name, len, attr, NULL, scrp);
211 + if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
212 + error = smbfs_smb2_seteof(ssp, &fhp->fh_fid2, size, scrp);
213 + } else {
214 + error = smbfs_smb1_seteof(ssp, fhp->fh_fid1, size, scrp);
899 215 }
900 - return (error);
901 -}
902 216
903 -
904 -int
905 -smbfs_smb_unhideit(struct smbnode *np, const char *name, int len,
906 - struct smb_cred *scrp)
907 -{
908 - struct smbfattr fa;
909 - uint32_t attr;
910 - int error;
911 -
912 - error = smbfs_smb_query_info(np, name, len, &fa, scrp);
913 - attr = fa.fa_attr;
914 - if (!error && (attr & SMB_FA_HIDDEN)) {
915 - attr &= ~SMB_FA_HIDDEN;
916 - error = smbfs_smb_setpattr1(np, name, len, attr, NULL, scrp);
917 - }
918 217 return (error);
919 218 }
920 219
220 +
921 221 /*
922 222 * Set file attributes (optionally: DOS attr, atime, mtime)
923 - * either by open FID or by path name (FID == -1).
223 + * Always have an open FID with set attr rights.
924 224 */
925 225 int
926 226 smbfs_smb_setfattr(
927 - struct smbnode *np,
928 - int fid,
227 + struct smb_share *ssp,
228 + smb_fh_t *fhp,
929 229 uint32_t attr,
930 230 struct timespec *mtime,
931 231 struct timespec *atime,
932 232 struct smb_cred *scrp)
933 233 {
934 - struct smb_share *ssp = np->n_mount->smi_share;
935 - struct smb_vc *vcp = SSTOVC(ssp);
234 + struct mbchain mb_info;
235 + struct mbchain *mbp = &mb_info;
236 + uint64_t tm;
936 237 int error;
937 238
938 239 /*
939 - * Normally can use the trans2 call.
240 + * Build a struct FILE_BASIC_INFORMATION in mbp
241 + * LARGE_INTEGER CreationTime;
242 + * LARGE_INTEGER LastAccessTime;
243 + * LARGE_INTEGER LastWriteTime;
244 + * LARGE_INTEGER ChangeTime;
245 + * ULONG FileAttributes;
246 + * Zero in times means "no change".
940 247 */
941 - if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
942 - error = smbfs_smb_setfattrNT(np, fid,
943 - attr, mtime, atime, scrp);
944 - return (error);
945 - }
946 -
947 - /*
948 - * Fall-back for older protocols.
949 - */
950 - if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN1_0) {
951 - error = smbfs_smb_setftime1(np, fid,
952 - mtime, atime, scrp);
953 - return (error);
954 - }
955 - error = smbfs_smb_setpattr1(np, NULL, 0,
956 - attr, mtime, scrp);
957 - return (error);
958 -}
959 -
960 -/*
961 - * Set file atime and mtime. Isn't supported by core dialect.
962 - */
963 -int
964 -smbfs_smb_setftime1(
965 - struct smbnode *np,
966 - uint16_t fid,
967 - struct timespec *mtime,
968 - struct timespec *atime,
969 - struct smb_cred *scrp)
970 -{
971 - struct smb_rq rq, *rqp = &rq;
972 - struct smb_share *ssp = np->n_mount->smi_share;
973 - struct mbchain *mbp;
974 - uint16_t date, time;
975 - int error, tzoff;
976 -
977 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scrp);
978 - if (error)
979 - return (error);
980 -
981 - tzoff = SSTOVC(ssp)->vc_sopt.sv_tz;
982 - smb_rq_getrequest(rqp, &mbp);
983 - smb_rq_wstart(rqp);
984 - mb_put_uint16le(mbp, fid);
985 - mb_put_uint32le(mbp, 0); /* creation time */
986 -
987 - if (atime)
988 - smb_time_unix2dos(atime, tzoff, &date, &time, NULL);
989 - else
990 - time = date = 0;
991 - mb_put_uint16le(mbp, date);
992 - mb_put_uint16le(mbp, time);
993 - if (mtime)
994 - smb_time_unix2dos(mtime, tzoff, &date, &time, NULL);
995 - else
996 - time = date = 0;
997 - mb_put_uint16le(mbp, date);
998 - mb_put_uint16le(mbp, time);
999 - smb_rq_wend(rqp);
1000 - smb_rq_bstart(rqp);
1001 - smb_rq_bend(rqp);
1002 - error = smb_rq_simple(rqp);
1003 - SMBVDEBUG("%d\n", error);
1004 - smb_rq_done(rqp);
1005 - return (error);
1006 -}
1007 -
1008 -/*
1009 - * Set DOS file attributes, either via open FID or by path name.
1010 - * Looks like this call can be used only if CAP_NT_SMBS bit is on.
1011 - *
1012 - * When setting via path (fid == -1):
1013 - * *BASIC_INFO works with Samba, but Win2K servers say it is an
1014 - * invalid information level on a SET_PATH_INFO. Note Win2K does
1015 - * support *BASIC_INFO on a SET_FILE_INFO, and they support the
1016 - * equivalent *BASIC_INFORMATION on SET_PATH_INFO. Go figure.
1017 - */
1018 -int
1019 -smbfs_smb_setfattrNT(
1020 - struct smbnode *np,
1021 - int fid, /* if fid == -1, set by path */
1022 - uint32_t attr,
1023 - struct timespec *mtime,
1024 - struct timespec *atime,
1025 - struct smb_cred *scrp)
1026 -{
1027 - struct smb_t2rq *t2p;
1028 - struct smb_share *ssp = np->n_mount->smi_share;
1029 - struct smb_vc *vcp = SSTOVC(ssp);
1030 - struct mbchain *mbp;
1031 - uint64_t tm;
1032 - int error;
1033 - uint16_t cmd, level;
1034 -
1035 - if (fid == -1) {
1036 - cmd = SMB_TRANS2_SET_PATH_INFORMATION;
1037 - } else {
1038 - if (fid > UINT16_MAX)
1039 - return (EINVAL);
1040 - cmd = SMB_TRANS2_SET_FILE_INFORMATION;
1041 - }
1042 - if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
1043 - level = SMB_SFILEINFO_BASIC_INFORMATION;
1044 - else
1045 - level = SMB_SFILEINFO_BASIC_INFO;
1046 -
1047 - error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
1048 - if (error)
1049 - return (error);
1050 -
1051 - mbp = &t2p->t2_tparam;
1052 248 mb_init(mbp);
1053 -
1054 - if (cmd == SMB_TRANS2_SET_FILE_INFORMATION)
1055 - mb_put_uint16le(mbp, fid);
1056 -
1057 - mb_put_uint16le(mbp, level);
1058 - mb_put_uint32le(mbp, 0); /* MBZ */
1059 -
1060 - if (cmd == SMB_TRANS2_SET_PATH_INFORMATION) {
1061 - error = smbfs_fullpath(mbp, vcp, np, NULL, 0, '\\');
1062 - if (error != 0)
1063 - goto out;
1064 - }
1065 -
1066 - /* FAT file systems don't support dates earlier than 1980. */
1067 -
1068 - mbp = &t2p->t2_tdata;
1069 - mb_init(mbp);
1070 249 mb_put_uint64le(mbp, 0); /* creation time */
1071 250 if (atime) {
1072 251 smb_time_local2NT(atime, &tm);
1073 252 if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
1074 253 tm < NT1980)
1075 254 tm = NT1980;
1076 255 } else
1077 256 tm = 0;
1078 - mb_put_uint64le(mbp, tm); /* access time */
257 + mb_put_uint64le(mbp, tm); /* last access time */
1079 258 if (mtime) {
1080 259 smb_time_local2NT(mtime, &tm);
1081 260 if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
1082 261 tm < NT1980)
1083 262 tm = NT1980;
1084 263 } else
1085 264 tm = 0;
1086 265 mb_put_uint64le(mbp, tm); /* last write time */
1087 - mb_put_uint64le(mbp, 0); /* ctime (no change) */
266 + mb_put_uint64le(mbp, 0); /* change time */
1088 267 mb_put_uint32le(mbp, attr);
1089 - mb_put_uint32le(mbp, 0); /* padding */
1090 - t2p->t2_maxpcount = 2;
1091 - t2p->t2_maxdcount = 0;
1092 - error = smb_t2_request(t2p);
1093 -out:
1094 - smb_t2_done(t2p);
268 +
269 + if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
270 + error = smbfs_smb2_setfattr(ssp, &fhp->fh_fid2, mbp, scrp);
271 + } else {
272 + error = smbfs_smb1_setfattr(ssp, fhp->fh_fid1, mbp, scrp);
273 + }
274 +
1095 275 return (error);
1096 276 }
1097 277
278 +int
279 +smbfs_smb_flush(struct smb_share *ssp, smb_fh_t *fhp,
280 + struct smb_cred *scrp)
281 +{
282 + int error;
283 +
284 + if (SSTOVC(ssp)->vc_flags & SMBV_SMB2) {
285 + error = smbfs_smb2_flush(ssp, &fhp->fh_fid2, scrp);
286 + } else {
287 + error = smbfs_smb1_flush(ssp, fhp->fh_fid1, scrp);
288 + }
289 + return (error);
290 +}
291 +
1098 292 /*
1099 293 * Modern create/open of file or directory.
294 + * On success, fills in fhp->fh_fid* and fhp->fh_rights
1100 295 */
1101 296 int
1102 297 smbfs_smb_ntcreatex(
1103 298 struct smbnode *np,
1104 299 const char *name,
1105 300 int nmlen,
1106 301 int xattr, /* is named stream? */
1107 302 uint32_t req_acc, /* requested access */
1108 303 uint32_t efa, /* ext. file attrs (DOS attr +) */
1109 304 uint32_t share_acc,
1110 305 uint32_t disp, /* open disposition */
1111 306 uint32_t createopt, /* NTCREATEX_OPTIONS_ */
1112 307 struct smb_cred *scrp,
1113 - uint16_t *fidp, /* returned FID */
308 + smb_fh_t *fhp, /* pre-made file handle to fill in */
1114 309 uint32_t *cr_act_p, /* optional returned create action */
1115 310 struct smbfattr *fap) /* optional returned attributes */
1116 311 {
1117 312 struct mbchain name_mb;
1118 313 struct smb_share *ssp = np->n_mount->smi_share;
1119 314 int err;
1120 315
1121 316 mb_init(&name_mb);
1122 317
1123 318 if (name == NULL)
1124 319 nmlen = 0;
1125 320 err = smbfs_fullpath(&name_mb, SSTOVC(ssp),
1126 321 np, name, nmlen, xattr ? ':' : '\\');
1127 322 if (err)
1128 323 goto out;
1129 324
1130 325 err = smb_smb_ntcreate(ssp, &name_mb,
1131 326 0, /* NTCREATEX_FLAGS... */
1132 327 req_acc, efa, share_acc, disp, createopt,
1133 328 NTCREATEX_IMPERSONATION_IMPERSONATION,
1134 - scrp, fidp, cr_act_p, fap);
329 + scrp, fhp, cr_act_p, fap);
1135 330
1136 331 out:
1137 332 mb_done(&name_mb);
1138 333
1139 334 return (err);
1140 335 }
1141 336
1142 -static uint32_t
1143 -smb_mode2rights(int mode)
1144 -{
1145 - mode = mode & SMB_AM_OPENMODE;
1146 - uint32_t rights =
1147 - STD_RIGHT_SYNCHRONIZE_ACCESS |
1148 - STD_RIGHT_READ_CONTROL_ACCESS;
1149 -
1150 - if ((mode == SMB_AM_OPENREAD) ||
1151 - (mode == SMB_AM_OPENRW)) {
1152 - rights |=
1153 - SA_RIGHT_FILE_READ_ATTRIBUTES |
1154 - SA_RIGHT_FILE_READ_DATA;
1155 - }
1156 -
1157 - if ((mode == SMB_AM_OPENWRITE) ||
1158 - (mode == SMB_AM_OPENRW)) {
1159 - rights |=
1160 - SA_RIGHT_FILE_WRITE_ATTRIBUTES |
1161 - SA_RIGHT_FILE_APPEND_DATA |
1162 - SA_RIGHT_FILE_WRITE_DATA;
1163 - }
1164 -
1165 - if (mode == SMB_AM_OPENEXEC) {
1166 - rights |=
1167 - SA_RIGHT_FILE_READ_ATTRIBUTES |
1168 - SA_RIGHT_FILE_EXECUTE;
1169 - }
1170 -
1171 - return (rights);
1172 -}
1173 -
1174 -static int
1175 -smb_rights2mode(uint32_t rights)
1176 -{
1177 - int accmode = SMB_AM_OPENEXEC; /* our fallback */
1178 -
1179 - if (rights & (SA_RIGHT_FILE_APPEND_DATA | SA_RIGHT_FILE_DELETE_CHILD |
1180 - SA_RIGHT_FILE_WRITE_EA | SA_RIGHT_FILE_WRITE_ATTRIBUTES |
1181 - SA_RIGHT_FILE_WRITE_DATA | STD_RIGHT_WRITE_OWNER_ACCESS |
1182 - STD_RIGHT_DELETE_ACCESS | STD_RIGHT_WRITE_DAC_ACCESS))
1183 - accmode = SMB_AM_OPENWRITE;
1184 - if (rights & (SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_READ_ATTRIBUTES |
1185 - SA_RIGHT_FILE_READ_EA | STD_RIGHT_READ_CONTROL_ACCESS))
1186 - accmode = (accmode == SMB_AM_OPENEXEC) ? SMB_AM_OPENREAD
1187 - : SMB_AM_OPENRW;
1188 - return (accmode);
1189 -}
1190 -
1191 -static int
1192 -smbfs_smb_oldopen(
1193 - struct smbnode *np,
1194 - const char *name,
1195 - int nmlen,
1196 - int xattr,
1197 - int accmode,
1198 - struct smb_cred *scrp,
1199 - uint16_t *fidp,
1200 - uint16_t *granted_mode_p,
1201 - smbfattr_t *fap)
1202 -{
1203 - struct smb_rq rq, *rqp = &rq;
1204 - struct smb_share *ssp = np->n_mount->smi_share;
1205 - struct smb_vc *vcp = SSTOVC(ssp);
1206 - struct mbchain *mbp;
1207 - struct mdchain *mdp;
1208 - struct smbfattr fa;
1209 - uint8_t wc;
1210 - uint16_t wattr;
1211 - uint32_t longint;
1212 - int error;
1213 -
1214 - bzero(&fa, sizeof (fa));
1215 -
1216 - /*
1217 - * XXX: move to callers...
1218 - *
1219 - * Use DENYNONE to give unixy semantics of permitting
1220 - * everything not forbidden by permissions. Ie denial
1221 - * is up to server with clients/openers needing to use
1222 - * advisory locks for further control.
1223 - */
1224 - accmode |= SMB_SM_DENYNONE;
1225 -
1226 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN, scrp);
1227 - if (error)
1228 - return (error);
1229 - smb_rq_getrequest(rqp, &mbp);
1230 - smb_rq_wstart(rqp);
1231 - mb_put_uint16le(mbp, accmode);
1232 - mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_RDONLY |
1233 - SMB_FA_DIR);
1234 - smb_rq_wend(rqp);
1235 - smb_rq_bstart(rqp);
1236 - mb_put_uint8(mbp, SMB_DT_ASCII);
1237 -
1238 - error = smbfs_fullpath(mbp, vcp, np, name, nmlen,
1239 - xattr ? ':' : '\\');
1240 - if (error)
1241 - goto done;
1242 - smb_rq_bend(rqp);
1243 - /*
1244 - * Don't want to risk missing a successful
1245 - * open response, or we could "leak" FIDs.
1246 - */
1247 - rqp->sr_flags |= SMBR_NOINTR_RECV;
1248 - error = smb_rq_simple_timed(rqp, smb_timo_open);
1249 - if (error)
1250 - goto done;
1251 - smb_rq_getreply(rqp, &mdp);
1252 - /*
1253 - * 8/2002 a DAVE server returned wc of 15 so we ignore that.
1254 - * (the actual packet length and data was correct)
1255 - */
1256 - error = md_get_uint8(mdp, &wc);
1257 - if (error)
1258 - goto done;
1259 - if (wc != 7 && wc != 15) {
1260 - error = EBADRPC;
1261 - goto done;
1262 - }
1263 - md_get_uint16le(mdp, fidp);
1264 - md_get_uint16le(mdp, &wattr);
1265 - fa.fa_attr = wattr;
1266 - /*
1267 - * Be careful using the time returned here, as
1268 - * with FAT on NT4SP6, at least, the time returned is low
1269 - * 32 bits of 100s of nanoseconds (since 1601) so it rolls
1270 - * over about every seven minutes!
1271 - */
1272 - md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */
1273 - smb_time_server2local(longint, vcp->vc_sopt.sv_tz, &fa.fa_mtime);
1274 - md_get_uint32le(mdp, &longint);
1275 - fa.fa_size = longint;
1276 - error = md_get_uint16le(mdp, granted_mode_p);
1277 -
1278 -done:
1279 - smb_rq_done(rqp);
1280 - if (error)
1281 - return (error);
1282 -
1283 - if (fap)
1284 - *fap = fa; /* struct copy */
1285 -
1286 - return (0);
1287 -}
1288 -
337 +/*
338 + * Get a file handle with (at least) the specified rights.
339 + *
340 + * We'll try to borrow the node ->n_fid if we can. When we
341 + * borrow n_fid, just take a hold on the smb_fh_t, and don't
342 + * bump n_fidrefs as that tracks VFS-level opens. Similarly
343 + * in _tmpclose we just release the smb_fh_t, not n_fidrefs.
344 + */
1289 345 int
1290 346 smbfs_smb_tmpopen(struct smbnode *np, uint32_t rights, struct smb_cred *scrp,
1291 - uint16_t *fidp)
347 + smb_fh_t **fhpp)
1292 348 {
1293 349 struct smb_share *ssp = np->n_mount->smi_share;
1294 - struct smb_vc *vcp = SSTOVC(ssp);
1295 - int accmode, error;
350 + smb_fh_t *fhp = NULL;
351 + int error;
1296 352
1297 - /* Shared lock for n_fid use below. */
1298 - ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
1299 -
1300 353 /* Can we re-use n_fid? or must we open anew? */
1301 354 mutex_enter(&np->r_statelock);
1302 355 if (np->n_fidrefs > 0 &&
1303 - np->n_vcgenid == ssp->ss_vcgenid &&
1304 - (rights & np->n_rights) == rights) {
1305 - np->n_fidrefs++;
1306 - *fidp = np->n_fid;
356 + (fhp = np->n_fid) != NULL &&
357 + fhp->fh_vcgenid == ssp->ss_vcgenid &&
358 + (fhp->fh_rights & rights) == rights) {
359 + smb_fh_hold(fhp);
360 + *fhpp = fhp;
1307 361 mutex_exit(&np->r_statelock);
1308 362 return (0);
1309 363 }
1310 364 mutex_exit(&np->r_statelock);
1311 365
366 + error = smb_fh_create(ssp, &fhp);
367 + if (error != 0)
368 + goto out;
369 +
1312 370 /* re-open an existing file. */
1313 - if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
1314 - error = smbfs_smb_ntcreatex(np,
1315 - NULL, 0, 0, /* name nmlen xattr */
1316 - rights, SMB_EFA_NORMAL,
1317 - NTCREATEX_SHARE_ACCESS_ALL,
1318 - NTCREATEX_DISP_OPEN,
1319 - 0, /* create options */
1320 - scrp, fidp,
1321 - NULL, NULL); /* cr_act_p fa_p */
1322 - return (error);
1323 - }
371 + error = smbfs_smb_ntcreatex(np,
372 + NULL, 0, 0, /* name nmlen xattr */
373 + rights, SMB_EFA_NORMAL,
374 + NTCREATEX_SHARE_ACCESS_ALL,
375 + NTCREATEX_DISP_OPEN,
376 + 0, /* create options */
377 + scrp, fhp,
378 + NULL, NULL); /* cr_act_p fa_p */
379 + if (error != 0)
380 + goto out;
1324 381
1325 - accmode = smb_rights2mode(rights);
1326 - error = smbfs_smb_oldopen(np,
1327 - NULL, 0, 0, /* name nmlen xattr */
1328 - accmode, scrp,
1329 - fidp,
1330 - NULL, /* granted mode p */
1331 - NULL); /* fa p */
382 + fhp->fh_rights = rights;
383 + smb_fh_opened(fhp);
384 + *fhpp = fhp;
385 + fhp = NULL;
1332 386
387 +out:
388 + if (fhp != NULL)
389 + smb_fh_rele(fhp);
390 +
1333 391 return (error);
1334 392 }
1335 393
1336 -int
1337 -smbfs_smb_tmpclose(struct smbnode *np, uint16_t fid, struct smb_cred *scrp)
394 +/* ARGSUSED */
395 +void
396 +smbfs_smb_tmpclose(struct smbnode *np, smb_fh_t *fhp)
1338 397 {
1339 - struct smb_share *ssp = np->n_mount->smi_share;
1340 - int error = 0;
1341 - uint16_t oldfid = SMB_FID_UNUSED;
1342 -
1343 - /* Shared lock for n_fid use below. */
1344 - ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
1345 -
1346 - mutex_enter(&np->r_statelock);
1347 - if (fid == np->n_fid) {
1348 - ASSERT(np->n_fidrefs > 0);
1349 - if (--np->n_fidrefs == 0) {
1350 - /*
1351 - * Don't expect to find the last reference
1352 - * here in tmpclose. Hard to deal with as
1353 - * we don't have r_lkserlock exclusive.
1354 - * Will close oldfid below.
1355 - */
1356 - oldfid = np->n_fid;
1357 - np->n_fid = SMB_FID_UNUSED;
1358 - }
1359 - } else {
1360 - /* Will close the passed fid. */
1361 - oldfid = fid;
1362 - }
1363 - mutex_exit(&np->r_statelock);
1364 -
1365 - if (oldfid != SMB_FID_UNUSED)
1366 - error = smbfs_smb_close(ssp, oldfid, NULL, scrp);
1367 -
1368 - return (error);
398 + smb_fh_rele(fhp);
1369 399 }
1370 400
1371 401 int
1372 402 smbfs_smb_open(
1373 403 struct smbnode *np,
1374 404 const char *name,
1375 405 int nmlen,
1376 406 int xattr,
1377 407 uint32_t rights,
1378 408 struct smb_cred *scrp,
1379 - uint16_t *fidp,
1380 - uint32_t *rightsp,
409 + smb_fh_t **fhpp,
1381 410 smbfattr_t *fap)
1382 411 {
1383 412 struct smb_share *ssp = np->n_mount->smi_share;
1384 - struct smb_vc *vcp = SSTOVC(ssp);
1385 - int accmode, error;
1386 - uint16_t grantedmode;
413 + // struct smb_vc *vcp = SSTOVC(ssp);
414 + smb_fh_t *fhp = NULL;
415 + int error;
1387 416
1388 - /* open an existing file */
1389 - if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
1390 - error = smbfs_smb_ntcreatex(np,
1391 - name, nmlen, xattr,
1392 - rights, SMB_EFA_NORMAL,
1393 - NTCREATEX_SHARE_ACCESS_ALL,
1394 - NTCREATEX_DISP_OPEN,
1395 - 0, /* create options */
1396 - scrp, fidp,
1397 - NULL, fap); /* cr_act_p fa_p */
1398 - if (error != 0)
1399 - return (error);
1400 - *rightsp = rights;
1401 - return (0);
1402 - }
417 + error = smb_fh_create(ssp, &fhp);
418 + if (error != 0)
419 + goto out;
1403 420
1404 - accmode = smb_rights2mode(rights);
1405 - error = smbfs_smb_oldopen(np,
1406 - name, nmlen, xattr, accmode, scrp,
1407 - fidp, &grantedmode, fap);
421 + /* open an existing file */
422 + error = smbfs_smb_ntcreatex(np,
423 + name, nmlen, xattr,
424 + rights, SMB_EFA_NORMAL,
425 + NTCREATEX_SHARE_ACCESS_ALL,
426 + NTCREATEX_DISP_OPEN,
427 + 0, /* create options */
428 + scrp, fhp, NULL, fap);
1408 429 if (error != 0)
1409 - return (error);
1410 - *rightsp = smb_mode2rights(grantedmode);
1411 - (void) smbfs_smb_getfattr(np, fap, scrp);
430 + goto out;
1412 431
1413 - return (0);
1414 -}
432 + fhp->fh_rights = rights;
433 + smb_fh_opened(fhp);
434 + *fhpp = fhp;
435 + fhp = NULL;
1415 436
1416 -int
1417 -smbfs_smb_close(struct smb_share *ssp, uint16_t fid,
1418 - struct timespec *mtime, struct smb_cred *scrp)
1419 -{
1420 - int error;
437 +out:
438 + if (fhp != NULL)
439 + smb_fh_rele(fhp);
1421 440
1422 - error = smb_smb_close(ssp, fid, mtime, scrp);
1423 -
1424 - /*
1425 - * ENOTCONN isn't interesting - if the connection is closed,
1426 - * so are all our FIDs - and EIO is also not interesting,
1427 - * as it means a forced unmount was done. (was ENXIO)
1428 - * Also ETIME, which means we sent the request but gave up
1429 - * waiting before the response came back.
1430 - *
1431 - * Don't clog up the system log with warnings about these
1432 - * uninteresting failures on closes.
1433 - */
1434 - switch (error) {
1435 - case ENOTCONN:
1436 - case ENXIO:
1437 - case EIO:
1438 - case ETIME:
1439 - error = 0;
1440 - }
1441 - return (error);
441 + return (0);
1442 442 }
1443 443
1444 -static int
1445 -smbfs_smb_oldcreate(struct smbnode *dnp, const char *name, int nmlen,
1446 - int xattr, struct smb_cred *scrp, uint16_t *fidp)
444 +void
445 +smbfs_smb_close(smb_fh_t *fhp)
1447 446 {
1448 - struct smb_rq rq, *rqp = &rq;
1449 - struct smb_share *ssp = dnp->n_mount->smi_share;
1450 - struct mbchain *mbp;
1451 - struct mdchain *mdp;
1452 - struct timespec ctime;
1453 - uint8_t wc;
1454 - long tm;
1455 - int error;
1456 - uint16_t attr = SMB_FA_ARCHIVE;
1457 447
1458 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE, scrp);
1459 - if (error)
1460 - return (error);
1461 - smb_rq_getrequest(rqp, &mbp);
1462 - smb_rq_wstart(rqp);
1463 - if (name && *name == '.')
1464 - attr |= SMB_FA_HIDDEN;
1465 - mb_put_uint16le(mbp, attr); /* attributes */
1466 - gethrestime(&ctime);
1467 - smb_time_local2server(&ctime, SSTOVC(ssp)->vc_sopt.sv_tz, &tm);
1468 - mb_put_uint32le(mbp, tm);
1469 - smb_rq_wend(rqp);
1470 - smb_rq_bstart(rqp);
1471 - mb_put_uint8(mbp, SMB_DT_ASCII);
1472 - error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, nmlen,
1473 - xattr ? ':' : '\\');
1474 - if (error)
1475 - goto out;
1476 - smb_rq_bend(rqp);
1477 - /*
1478 - * Don't want to risk missing a successful
1479 - * open response, or we could "leak" FIDs.
1480 - */
1481 - rqp->sr_flags |= SMBR_NOINTR_RECV;
1482 - error = smb_rq_simple_timed(rqp, smb_timo_open);
1483 - if (error)
1484 - goto out;
1485 -
1486 - smb_rq_getreply(rqp, &mdp);
1487 - md_get_uint8(mdp, &wc);
1488 - if (wc != 1) {
1489 - error = EBADRPC;
1490 - goto out;
1491 - }
1492 - error = md_get_uint16le(mdp, fidp);
1493 -
1494 -out:
1495 - smb_rq_done(rqp);
1496 - return (error);
448 + smb_fh_close(fhp);
449 + smb_fh_rele(fhp);
1497 450 }
1498 451
1499 452 int
1500 453 smbfs_smb_create(
1501 454 struct smbnode *dnp,
1502 455 const char *name,
1503 456 int nmlen,
1504 457 int xattr,
1505 458 uint32_t disp,
1506 459 struct smb_cred *scrp,
1507 - uint16_t *fidp)
460 + smb_fh_t **fhpp)
1508 461 {
1509 462 struct smb_share *ssp = dnp->n_mount->smi_share;
1510 - struct smb_vc *vcp = SSTOVC(ssp);
463 + // struct smb_vc *vcp = SSTOVC(ssp);
464 + smb_fh_t *fhp = NULL;
1511 465 uint32_t efa, rights;
1512 466 int error;
1513 467
468 + error = smb_fh_create(ssp, &fhp);
469 + if (error != 0)
470 + goto out;
471 +
1514 472 /*
1515 473 * At present the only access we might need is to WRITE data,
1516 474 * and that only if we are creating a "symlink". When/if the
1517 475 * access needed gets more complex it should made a parameter
1518 476 * and be set upstream.
1519 477 */
1520 - if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
1521 - rights = SA_RIGHT_FILE_WRITE_DATA;
1522 - efa = SMB_EFA_NORMAL;
1523 - if (!xattr && name && *name == '.')
1524 - efa = SMB_EFA_HIDDEN;
1525 - error = smbfs_smb_ntcreatex(dnp,
1526 - name, nmlen, xattr, rights, efa,
1527 - NTCREATEX_SHARE_ACCESS_ALL,
1528 - disp, /* != NTCREATEX_DISP_OPEN */
1529 - NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
1530 - scrp, fidp, NULL, NULL); /* cr_act_p fa_p */
1531 - return (error);
1532 - }
478 + rights = SA_RIGHT_FILE_WRITE_DATA;
479 + efa = SMB_EFA_NORMAL;
480 + if (!xattr && name && *name == '.')
481 + efa = SMB_EFA_HIDDEN;
482 + error = smbfs_smb_ntcreatex(dnp,
483 + name, nmlen, xattr, rights, efa,
484 + NTCREATEX_SHARE_ACCESS_ALL,
485 + disp, /* != NTCREATEX_DISP_OPEN */
486 + NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
487 + scrp, fhp, NULL, NULL);
488 + if (error != 0)
489 + goto out;
1533 490
1534 - error = smbfs_smb_oldcreate(dnp, name, nmlen, xattr, scrp, fidp);
491 + fhp->fh_rights = rights;
492 + smb_fh_opened(fhp);
493 + *fhpp = fhp;
494 + fhp = NULL;
495 +
496 +out:
497 + if (fhp != NULL)
498 + smb_fh_rele(fhp);
499 +
1535 500 return (error);
1536 501 }
1537 502
1538 503 int
1539 -smbfs_smb_delete(struct smbnode *np, struct smb_cred *scrp, const char *name,
1540 - int nmlen, int xattr)
504 +smbfs_smb_rename(struct smbnode *sdnp, struct smbnode *np,
505 + struct smbnode *tdnp, const char *tname, int tnlen,
506 + smb_fh_t *fhp, struct smb_cred *scrp)
1541 507 {
1542 - struct smb_rq rq, *rqp = &rq;
1543 508 struct smb_share *ssp = np->n_mount->smi_share;
1544 - struct mbchain *mbp;
1545 - int error;
509 + struct smb_vc *vcp = SSTOVC(ssp);
510 + int err;
1546 511
1547 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE, scrp);
1548 - if (error)
1549 - return (error);
1550 - smb_rq_getrequest(rqp, &mbp);
1551 - smb_rq_wstart(rqp);
1552 - mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN);
1553 - smb_rq_wend(rqp);
1554 - smb_rq_bstart(rqp);
1555 - mb_put_uint8(mbp, SMB_DT_ASCII);
1556 - error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, nmlen,
1557 - xattr ? ':' : '\\');
1558 - if (!error) {
1559 - smb_rq_bend(rqp);
1560 - error = smb_rq_simple(rqp);
512 + if (vcp->vc_flags & SMBV_SMB2) {
513 + err = smbfs_smb2_rename(np, tdnp, tname, tnlen, 0,
514 + &fhp->fh_fid2, scrp);
515 + return (err);
1561 516 }
1562 - smb_rq_done(rqp);
1563 - return (error);
1564 -}
1565 517
1566 -int
1567 -smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp,
1568 - const char *tname, int tnmlen, struct smb_cred *scrp)
1569 -{
1570 - struct smb_rq rq, *rqp = &rq;
1571 - struct smb_share *ssp = src->n_mount->smi_share;
1572 - struct mbchain *mbp;
1573 - int error;
1574 - uint16_t fa;
1575 - char sep;
1576 -
1577 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_RENAME, scrp);
1578 - if (error)
1579 - return (error);
1580 - smb_rq_getrequest(rqp, &mbp);
1581 - smb_rq_wstart(rqp);
1582 - /* freebsd bug: Let directories be renamed - Win98 requires DIR bit */
1583 - fa = (SMBTOV(src)->v_type == VDIR) ? SMB_FA_DIR : 0;
1584 - fa |= SMB_FA_SYSTEM | SMB_FA_HIDDEN;
1585 - mb_put_uint16le(mbp, fa);
1586 - smb_rq_wend(rqp);
1587 - smb_rq_bstart(rqp);
1588 -
1589 518 /*
1590 - * When we're not adding any component name, the
1591 - * passed sep is ignored, so just pass sep=0.
519 + * SMB1 -- Want to use _t2rename if we can
520 + * (rename in same dir and cap pass-through)
521 + * Most SMB1 servers have cap pass-through.
1592 522 */
1593 - mb_put_uint8(mbp, SMB_DT_ASCII);
1594 - error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0, 0);
1595 - if (error)
1596 - goto out;
523 + if (sdnp == tdnp &&
524 + (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU) != 0) {
525 + err = smbfs_smb1_t2rename(np, tname, tnlen, fhp->fh_fid1, scrp);
526 + } else {
527 + err = smbfs_smb1_oldrename(np, tdnp, tname, tnlen, scrp);
528 + }
1597 529
1598 - /*
1599 - * After XATTR directories, separator is ":"
1600 - */
1601 - sep = (src->n_flag & N_XATTR) ? ':' : '\\';
1602 - mb_put_uint8(mbp, SMB_DT_ASCII);
1603 - error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen, sep);
1604 - if (error)
1605 - goto out;
1606 -
1607 - smb_rq_bend(rqp);
1608 - error = smb_rq_simple(rqp);
1609 -out:
1610 - smb_rq_done(rqp);
1611 - return (error);
530 + return (err);
1612 531 }
1613 532
1614 533 int
1615 -smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp,
1616 - const char *tname, int tnmlen, uint16_t flags, struct smb_cred *scrp)
1617 -{
1618 - struct smb_rq rq, *rqp = &rq;
1619 - struct smb_share *ssp = src->n_mount->smi_share;
1620 - struct mbchain *mbp;
1621 - int error;
1622 -
1623 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_MOVE, scrp);
1624 - if (error)
1625 - return (error);
1626 - smb_rq_getrequest(rqp, &mbp);
1627 - smb_rq_wstart(rqp);
1628 - mb_put_uint16le(mbp, SMB_TID_UNKNOWN);
1629 - mb_put_uint16le(mbp, 0x20); /* delete target file */
1630 - mb_put_uint16le(mbp, flags);
1631 - smb_rq_wend(rqp);
1632 - smb_rq_bstart(rqp);
1633 - mb_put_uint8(mbp, SMB_DT_ASCII);
1634 -
1635 - error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0, '\\');
1636 - if (error)
1637 - goto out;
1638 - mb_put_uint8(mbp, SMB_DT_ASCII);
1639 - error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen, '\\');
1640 - if (error)
1641 - goto out;
1642 - smb_rq_bend(rqp);
1643 - error = smb_rq_simple(rqp);
1644 -
1645 -out:
1646 - smb_rq_done(rqp);
1647 - return (error);
1648 -}
1649 -
1650 -static int
1651 -smbfs_smb_oldmkdir(struct smbnode *dnp, const char *name, int len,
1652 - struct smb_cred *scrp)
1653 -{
1654 - struct smb_rq rq, *rqp = &rq;
1655 - struct smb_share *ssp = dnp->n_mount->smi_share;
1656 - struct mbchain *mbp;
1657 - int error;
1658 -
1659 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scrp);
1660 - if (error)
1661 - return (error);
1662 - smb_rq_getrequest(rqp, &mbp);
1663 - smb_rq_wstart(rqp);
1664 - smb_rq_wend(rqp);
1665 - smb_rq_bstart(rqp);
1666 - mb_put_uint8(mbp, SMB_DT_ASCII);
1667 - error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, len, '\\');
1668 - if (!error) {
1669 - smb_rq_bend(rqp);
1670 - error = smb_rq_simple(rqp);
1671 - }
1672 - smb_rq_done(rqp);
1673 - return (error);
1674 -}
1675 -
1676 -int
1677 534 smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int nmlen,
1678 535 struct smb_cred *scrp)
1679 536 {
537 + smb_fh_t tmp_fh;
1680 538 struct smb_share *ssp = dnp->n_mount->smi_share;
1681 - struct smb_vc *vcp = SSTOVC(ssp);
1682 - uint32_t rights;
1683 - uint16_t fid;
539 + uint32_t efa, rights;
1684 540 int error;
1685 541
1686 542 /*
543 + * Using a faked-up handle here to avoid the work of
544 + * creating and destroying a real "conn obj".
545 + */
546 + bzero(&tmp_fh, sizeof (tmp_fh));
547 +
548 + /*
1687 549 * We ask for SA_RIGHT_FILE_READ_DATA not because we need it, but
1688 550 * just to be asking for something. The rights==0 case could
1689 551 * easily be broken on some old or unusual servers.
1690 552 */
1691 - if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
1692 - rights = SA_RIGHT_FILE_READ_DATA;
1693 - error = smbfs_smb_ntcreatex(dnp,
1694 - name, nmlen, 0, /* xattr */
1695 - rights, SMB_EFA_DIRECTORY,
1696 - NTCREATEX_SHARE_ACCESS_ALL,
1697 - NTCREATEX_DISP_CREATE,
1698 - NTCREATEX_OPTIONS_DIRECTORY,
1699 - scrp, &fid, NULL, NULL); /* cr_act_p fa_p */
1700 - if (error)
1701 - return (error);
1702 - (void) smbfs_smb_close(ssp, fid, NULL, scrp);
1703 - return (0);
553 + rights = SA_RIGHT_FILE_READ_DATA;
554 + efa = SMB_EFA_NORMAL;
555 + if (name && *name == '.')
556 + efa |= SMB_EFA_HIDDEN;
557 + error = smbfs_smb_ntcreatex(dnp,
558 + name, nmlen, 0, /* xattr */
559 + rights, SMB_EFA_DIRECTORY,
560 + NTCREATEX_SHARE_ACCESS_ALL,
561 + NTCREATEX_DISP_CREATE,
562 + NTCREATEX_OPTIONS_DIRECTORY,
563 + scrp, &tmp_fh, NULL, NULL);
564 + if (error == 0) {
565 + (void) smb_smb_close(ssp, &tmp_fh, scrp);
1704 566 }
1705 567
1706 - error = smbfs_smb_oldmkdir(dnp, name, nmlen, scrp);
1707 568 return (error);
1708 569 }
1709 570
1710 -int
1711 -smbfs_smb_rmdir(struct smbnode *np, struct smb_cred *scrp)
1712 -{
1713 - struct smb_rq rq, *rqp = &rq;
1714 - struct smb_share *ssp = np->n_mount->smi_share;
1715 - struct mbchain *mbp;
1716 - int error;
1717 -
1718 - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scrp);
1719 - if (error)
1720 - return (error);
1721 - smb_rq_getrequest(rqp, &mbp);
1722 - smb_rq_wstart(rqp);
1723 - smb_rq_wend(rqp);
1724 - smb_rq_bstart(rqp);
1725 - mb_put_uint8(mbp, SMB_DT_ASCII);
1726 - error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0, '\\');
1727 - if (!error) {
1728 - smb_rq_bend(rqp);
1729 - error = smb_rq_simple(rqp);
1730 - }
1731 - smb_rq_done(rqp);
1732 - return (error);
1733 -}
1734 -
1735 -static int
1736 -smbfs_smb_search(struct smbfs_fctx *ctx)
1737 -{
1738 - struct smb_vc *vcp = SSTOVC(ctx->f_ssp);
1739 - struct smb_rq *rqp;
1740 - struct mbchain *mbp;
1741 - struct mdchain *mdp;
1742 - uint8_t wc, bt;
1743 - uint16_t ec, dlen, bc;
1744 - int maxent, error, iseof = 0;
1745 -
1746 - maxent = min(ctx->f_left,
1747 - (vcp->vc_txmax - SMB_HDRLEN - 2*2) / SMB_DENTRYLEN);
1748 - if (ctx->f_rq) {
1749 - smb_rq_done(ctx->f_rq);
1750 - ctx->f_rq = NULL;
1751 - }
1752 - error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_SEARCH,
1753 - ctx->f_scred, &rqp);
1754 - if (error)
1755 - return (error);
1756 - ctx->f_rq = rqp;
1757 - smb_rq_getrequest(rqp, &mbp);
1758 - smb_rq_wstart(rqp);
1759 - mb_put_uint16le(mbp, maxent); /* max entries to return */
1760 - mb_put_uint16le(mbp, ctx->f_attrmask);
1761 - smb_rq_wend(rqp);
1762 - smb_rq_bstart(rqp);
1763 - mb_put_uint8(mbp, SMB_DT_ASCII); /* buffer format */
1764 - if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
1765 - error = smbfs_fullpath(mbp, vcp, ctx->f_dnp,
1766 - ctx->f_wildcard, ctx->f_wclen, '\\');
1767 - if (error)
1768 - return (error);
1769 - mb_put_uint8(mbp, SMB_DT_VARIABLE);
1770 - mb_put_uint16le(mbp, 0); /* context length */
1771 - ctx->f_flags &= ~SMBFS_RDD_FINDFIRST;
1772 - } else {
1773 - if (SMB_UNICODE_STRINGS(vcp)) {
1774 - mb_put_padbyte(mbp);
1775 - mb_put_uint8(mbp, 0);
1776 - }
1777 - mb_put_uint8(mbp, 0);
1778 - mb_put_uint8(mbp, SMB_DT_VARIABLE);
1779 - mb_put_uint16le(mbp, SMB_SKEYLEN);
1780 - mb_put_mem(mbp, (char *)ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM);
1781 - }
1782 - smb_rq_bend(rqp);
1783 - error = smb_rq_simple(rqp);
1784 - if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnofiles) {
1785 - error = 0;
1786 - iseof = 1;
1787 - ctx->f_flags |= SMBFS_RDD_EOF;
1788 - } else if (error)
1789 - return (error);
1790 - smb_rq_getreply(rqp, &mdp);
1791 - error = md_get_uint8(mdp, &wc);
1792 - if (error)
1793 - return (error);
1794 - if (wc != 1)
1795 - return (iseof ? ENOENT : EBADRPC);
1796 - md_get_uint16le(mdp, &ec);
1797 - md_get_uint16le(mdp, &bc);
1798 - md_get_uint8(mdp, &bt);
1799 - error = md_get_uint16le(mdp, &dlen);
1800 - if (error)
1801 - return (error);
1802 - if (ec == 0)
1803 - return (ENOENT);
1804 - ctx->f_ecnt = ec;
1805 - if (bc < 3)
1806 - return (EBADRPC);
1807 - bc -= 3;
1808 - if (bt != SMB_DT_VARIABLE)
1809 - return (EBADRPC);
1810 - if (dlen != bc || dlen % SMB_DENTRYLEN != 0)
1811 - return (EBADRPC);
1812 - return (0);
1813 -}
1814 -
1815 -
1816 -/*ARGSUSED*/
1817 -static int
1818 -smbfs_smb_findopenLM1(struct smbfs_fctx *ctx, struct smbnode *dnp,
1819 - const char *wildcard, int wclen, uint16_t attr)
1820 -{
1821 -
1822 - ctx->f_type = ft_LM1;
1823 - ctx->f_attrmask = attr;
1824 - if (wildcard) {
1825 - if (wclen == 1 && wildcard[0] == '*') {
1826 - ctx->f_wildcard = "*.*";
1827 - ctx->f_wclen = 3;
1828 - } else {
1829 - ctx->f_wildcard = wildcard;
1830 - ctx->f_wclen = wclen;
1831 - }
1832 - } else {
1833 - ctx->f_wildcard = NULL;
1834 - ctx->f_wclen = 0;
1835 - }
1836 - ctx->f_name = (char *)ctx->f_fname;
1837 - ctx->f_namesz = 0;
1838 - return (0);
1839 -}
1840 -
1841 -static int
1842 -smbfs_smb_findnextLM1(struct smbfs_fctx *ctx, uint16_t limit)
1843 -{
1844 - struct mdchain *mdp;
1845 - struct smb_rq *rqp;
1846 - char *cp;
1847 - uint8_t battr;
1848 - uint16_t date, time;
1849 - uint32_t size;
1850 - int error;
1851 - struct timespec ts;
1852 -
1853 - if (ctx->f_ecnt == 0) {
1854 - if (ctx->f_flags & SMBFS_RDD_EOF)
1855 - return (ENOENT);
1856 - ctx->f_left = ctx->f_limit = limit;
1857 - gethrestime(&ts);
1858 - error = smbfs_smb_search(ctx);
1859 - if (error)
1860 - return (error);
1861 - }
1862 - rqp = ctx->f_rq;
1863 - smb_rq_getreply(rqp, &mdp);
1864 - md_get_mem(mdp, (char *)ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM);
1865 - md_get_uint8(mdp, &battr);
1866 - md_get_uint16le(mdp, &time);
1867 - md_get_uint16le(mdp, &date);
1868 - md_get_uint32le(mdp, &size);
1869 - cp = ctx->f_name;
1870 - error = md_get_mem(mdp, cp, sizeof (ctx->f_fname), MB_MSYSTEM);
1871 - cp[sizeof (ctx->f_fname) - 1] = 0;
1872 - cp += strlen(cp) - 1;
1873 - while (*cp == ' ' && cp >= ctx->f_name)
1874 - *cp-- = 0;
1875 - ctx->f_attr.fa_attr = battr;
1876 - smb_dos2unixtime(date, time, 0, rqp->sr_vc->vc_sopt.sv_tz,
1877 - &ctx->f_attr.fa_mtime);
1878 - ctx->f_attr.fa_size = size;
1879 - ctx->f_nmlen = strlen(ctx->f_name);
1880 - ctx->f_ecnt--;
1881 - ctx->f_left--;
1882 - return (0);
1883 -}
1884 -
1885 -static int
1886 -smbfs_smb_findcloseLM1(struct smbfs_fctx *ctx)
1887 -{
1888 - if (ctx->f_rq)
1889 - smb_rq_done(ctx->f_rq);
1890 - return (0);
1891 -}
1892 -
1893 571 /*
1894 - * TRANS2_FIND_FIRST2/NEXT2, used for NT LM12 dialect
572 + * Protocol-level directory open
1895 573 */
1896 -static int
1897 -smbfs_smb_trans2find2(struct smbfs_fctx *ctx)
1898 -{
1899 - struct smb_t2rq *t2p;
1900 - struct smb_vc *vcp = SSTOVC(ctx->f_ssp);
1901 - struct mbchain *mbp;
1902 - struct mdchain *mdp;
1903 - uint16_t ecnt, eos, lno, flags;
1904 - int error;
1905 -
1906 - if (ctx->f_t2) {
1907 - smb_t2_done(ctx->f_t2);
1908 - ctx->f_t2 = NULL;
1909 - }
1910 - flags = FIND2_RETURN_RESUME_KEYS | FIND2_CLOSE_ON_EOS;
1911 - if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) {
1912 - flags |= FIND2_CLOSE_AFTER_REQUEST;
1913 - ctx->f_flags |= SMBFS_RDD_NOCLOSE;
1914 - }
1915 - if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
1916 - error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_FIRST2,
1917 - ctx->f_scred, &t2p);
1918 - if (error)
1919 - return (error);
1920 - ctx->f_t2 = t2p;
1921 - mbp = &t2p->t2_tparam;
1922 - mb_init(mbp);
1923 - mb_put_uint16le(mbp, ctx->f_attrmask);
1924 - mb_put_uint16le(mbp, ctx->f_limit);
1925 - mb_put_uint16le(mbp, flags);
1926 - mb_put_uint16le(mbp, ctx->f_infolevel);
1927 - mb_put_uint32le(mbp, 0);
1928 - error = smbfs_fullpath(mbp, vcp, ctx->f_dnp,
1929 - ctx->f_wildcard, ctx->f_wclen, '\\');
1930 - if (error)
1931 - return (error);
1932 - } else {
1933 - error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_NEXT2,
1934 - ctx->f_scred, &t2p);
1935 - if (error)
1936 - return (error);
1937 - ctx->f_t2 = t2p;
1938 - mbp = &t2p->t2_tparam;
1939 - mb_init(mbp);
1940 - mb_put_uint16le(mbp, ctx->f_Sid);
1941 - mb_put_uint16le(mbp, ctx->f_limit);
1942 - mb_put_uint16le(mbp, ctx->f_infolevel);
1943 - /* Send whatever resume key we received... */
1944 - mb_put_uint32le(mbp, ctx->f_rkey);
1945 - mb_put_uint16le(mbp, flags);
1946 - /* ... and the resume name if we have one. */
1947 - if (ctx->f_rname) {
1948 - /* resume file name */
1949 - mb_put_mem(mbp, ctx->f_rname, ctx->f_rnamelen,
1950 - MB_MSYSTEM);
1951 - }
1952 - /* Add trailing null - 1 byte if ASCII, 2 if Unicode */
1953 - if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp)))
1954 - mb_put_uint8(mbp, 0); /* 1st byte NULL Unicode char */
1955 - mb_put_uint8(mbp, 0);
1956 - }
1957 - t2p->t2_maxpcount = 5 * 2;
1958 - t2p->t2_maxdcount = 0xF000; /* 64K less some overhead */
1959 - error = smb_t2_request(t2p);
1960 - if (error)
1961 - return (error);
1962 -
1963 - /*
1964 - * This is the "resume name" we just sent.
1965 - * We want the new one (if any) that may be
1966 - * found in the response we just received and
1967 - * will now begin parsing. Free the old one
1968 - * now so we'll know if we found a new one.
1969 - */
1970 - if (ctx->f_rname) {
1971 - kmem_free(ctx->f_rname, ctx->f_rnamelen);
1972 - ctx->f_rname = NULL;
1973 - ctx->f_rnamelen = 0;
1974 - }
1975 -
1976 - mdp = &t2p->t2_rparam;
1977 - if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
1978 - if ((error = md_get_uint16le(mdp, &ctx->f_Sid)) != 0)
1979 - goto nodata;
1980 - ctx->f_flags &= ~SMBFS_RDD_FINDFIRST;
1981 - }
1982 - md_get_uint16le(mdp, &ecnt); /* entry count */
1983 - md_get_uint16le(mdp, &eos); /* end of search */
1984 - md_get_uint16le(mdp, NULL); /* EA err. off. */
1985 - error = md_get_uint16le(mdp, &lno); /* last name off. */
1986 - if (error != 0)
1987 - goto nodata;
1988 -
1989 - /*
1990 - * The "end of search" flag from an XP server sometimes
1991 - * comes back zero when the prior find_next returned exactly
1992 - * the number of entries requested. in which case we'd try again
1993 - * but the search has in fact been closed so an EBADF results.
1994 - * our circumvention is to check here for a zero entry count.
1995 - */
1996 - ctx->f_ecnt = ecnt;
1997 - if (eos || ctx->f_ecnt == 0)
1998 - ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE;
1999 - if (ctx->f_ecnt == 0)
2000 - return (ENOENT);
2001 -
2002 - /* Last Name Off (LNO) is the entry with the resume name. */
2003 - ctx->f_rnameofs = lno;
2004 - ctx->f_eofs = 0;
2005 - return (0);
2006 -
2007 -nodata:
2008 - /*
2009 - * Failed parsing the FindFirst or FindNext response.
2010 - * Force this directory listing closed, otherwise the
2011 - * calling process may hang in an infinite loop.
2012 - */
2013 - ctx->f_ecnt = 0; /* Force closed. */
2014 - ctx->f_flags |= SMBFS_RDD_EOF;
2015 - return (EIO);
2016 -}
2017 -
2018 -static int
2019 -smbfs_smb_findclose2(struct smbfs_fctx *ctx)
2020 -{
2021 - struct smb_rq rq, *rqp = &rq;
2022 - struct mbchain *mbp;
2023 - int error;
2024 -
2025 - error = smb_rq_init(rqp, SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2,
2026 - ctx->f_scred);
2027 - if (error)
2028 - return (error);
2029 - smb_rq_getrequest(rqp, &mbp);
2030 - smb_rq_wstart(rqp);
2031 - mb_put_uint16le(mbp, ctx->f_Sid);
2032 - smb_rq_wend(rqp);
2033 - smb_rq_bstart(rqp);
2034 - smb_rq_bend(rqp);
2035 - /* Ditto comments at _smb_close */
2036 - rqp->sr_flags |= SMBR_NOINTR_SEND;
2037 - error = smb_rq_simple(rqp);
2038 - smb_rq_done(rqp);
2039 - return (error);
2040 -}
2041 -
2042 -/*ARGSUSED*/
2043 -static int
2044 -smbfs_smb_findopenLM2(struct smbfs_fctx *ctx, struct smbnode *dnp,
2045 - const char *wildcard, int wclen, uint16_t attr)
2046 -{
2047 -
2048 - ctx->f_type = ft_LM2;
2049 - ctx->f_namesz = SMB_MAXFNAMELEN + 1;
2050 - if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp)))
2051 - ctx->f_namesz *= 2;
2052 - ctx->f_name = kmem_alloc(ctx->f_namesz, KM_SLEEP);
2053 - ctx->f_infolevel = SMB_DIALECT(SSTOVC(ctx->f_ssp))
2054 - < SMB_DIALECT_NTLM0_12 ? SMB_FIND_STANDARD :
2055 - SMB_FIND_BOTH_DIRECTORY_INFO;
2056 - ctx->f_attrmask = attr;
2057 - ctx->f_wildcard = wildcard;
2058 - ctx->f_wclen = wclen;
2059 - return (0);
2060 -}
2061 -
2062 -static int
2063 -smbfs_smb_findnextLM2(struct smbfs_fctx *ctx, uint16_t limit)
2064 -{
2065 - struct mdchain *mdp;
2066 - struct smb_t2rq *t2p;
2067 - char *cp;
2068 - uint8_t tb;
2069 - uint16_t date, time, wattr;
2070 - uint32_t size, next, dattr, resumekey = 0;
2071 - uint64_t llongint;
2072 - int error, svtz, cnt, fxsz, nmlen, recsz;
2073 - struct timespec ts;
2074 -
2075 - if (ctx->f_ecnt == 0) {
2076 - if (ctx->f_flags & SMBFS_RDD_EOF)
2077 - return (ENOENT);
2078 - ctx->f_left = ctx->f_limit = limit;
2079 - gethrestime(&ts);
2080 - error = smbfs_smb_trans2find2(ctx);
2081 - if (error)
2082 - return (error);
2083 - ctx->f_otws++;
2084 - }
2085 - t2p = ctx->f_t2;
2086 - mdp = &t2p->t2_rdata;
2087 - svtz = SSTOVC(ctx->f_ssp)->vc_sopt.sv_tz;
2088 - switch (ctx->f_infolevel) {
2089 - case SMB_FIND_STANDARD:
2090 - next = 0;
2091 - fxsz = 0;
2092 - md_get_uint16le(mdp, &date);
2093 - md_get_uint16le(mdp, &time); /* creation time */
2094 - smb_dos2unixtime(date, time, 0, svtz,
2095 - &ctx->f_attr.fa_createtime);
2096 - md_get_uint16le(mdp, &date);
2097 - md_get_uint16le(mdp, &time); /* access time */
2098 - smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_atime);
2099 - md_get_uint16le(mdp, &date);
2100 - md_get_uint16le(mdp, &time); /* modify time */
2101 - smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_mtime);
2102 - md_get_uint32le(mdp, &size);
2103 - ctx->f_attr.fa_size = size;
2104 - md_get_uint32le(mdp, &size); /* allocation size */
2105 - ctx->f_attr.fa_allocsz = size;
2106 - md_get_uint16le(mdp, &wattr);
2107 - ctx->f_attr.fa_attr = wattr;
2108 - error = md_get_uint8(mdp, &tb);
2109 - if (error)
2110 - goto nodata;
2111 - size = nmlen = tb;
2112 - fxsz = 23;
2113 - recsz = next = 24 + nmlen; /* docs misses zero byte @end */
2114 - break;
2115 - case SMB_FIND_DIRECTORY_INFO:
2116 - case SMB_FIND_BOTH_DIRECTORY_INFO:
2117 - md_get_uint32le(mdp, &next);
2118 - md_get_uint32le(mdp, &resumekey); /* file index (resume key) */
2119 - md_get_uint64le(mdp, &llongint); /* creation time */
2120 - smb_time_NT2local(llongint, &ctx->f_attr.fa_createtime);
2121 - md_get_uint64le(mdp, &llongint);
2122 - smb_time_NT2local(llongint, &ctx->f_attr.fa_atime);
2123 - md_get_uint64le(mdp, &llongint);
2124 - smb_time_NT2local(llongint, &ctx->f_attr.fa_mtime);
2125 - md_get_uint64le(mdp, &llongint);
2126 - smb_time_NT2local(llongint, &ctx->f_attr.fa_ctime);
2127 - md_get_uint64le(mdp, &llongint); /* file size */
2128 - ctx->f_attr.fa_size = llongint;
2129 - md_get_uint64le(mdp, &llongint); /* alloc. size */
2130 - ctx->f_attr.fa_allocsz = llongint;
2131 - md_get_uint32le(mdp, &dattr); /* ext. file attributes */
2132 - ctx->f_attr.fa_attr = dattr;
2133 - error = md_get_uint32le(mdp, &size); /* name len */
2134 - if (error)
2135 - goto nodata;
2136 - fxsz = 64; /* size ofinfo up to filename */
2137 - if (ctx->f_infolevel == SMB_FIND_BOTH_DIRECTORY_INFO) {
2138 - /*
2139 - * Skip EaSize(4 bytes), a byte of ShortNameLength,
2140 - * a reserved byte, and ShortName(8.3 means 24 bytes,
2141 - * as Leach defined it to always be Unicode)
2142 - */
2143 - error = md_get_mem(mdp, NULL, 30, MB_MSYSTEM);
2144 - if (error)
2145 - goto nodata;
2146 - fxsz += 30;
2147 - }
2148 - recsz = next ? next : fxsz + size;
2149 - break;
2150 - default:
2151 - SMBVDEBUG("unexpected info level %d\n", ctx->f_infolevel);
2152 - return (EINVAL);
2153 - }
2154 -
2155 - if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp)))
2156 - nmlen = min(size, SMB_MAXFNAMELEN * 2);
2157 - else
2158 - nmlen = min(size, SMB_MAXFNAMELEN);
2159 -
2160 - /* Allocated f_name in findopen */
2161 - ASSERT(nmlen < ctx->f_namesz);
2162 - cp = ctx->f_name;
2163 -
2164 - error = md_get_mem(mdp, cp, nmlen, MB_MSYSTEM);
2165 - if (error)
2166 - goto nodata;
2167 - if (next) {
2168 - /* How much data to skip? */
2169 - cnt = next - nmlen - fxsz;
2170 - if (cnt < 0) {
2171 - SMBVDEBUG("out of sync\n");
2172 - goto nodata;
2173 - }
2174 - if (cnt > 0)
2175 - md_get_mem(mdp, NULL, cnt, MB_MSYSTEM);
2176 - }
2177 - /* Don't count any trailing null in the name. */
2178 - if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) {
2179 - if (nmlen > 1 && cp[nmlen - 1] == 0 && cp[nmlen - 2] == 0)
2180 - nmlen -= 2;
2181 - } else {
2182 - if (nmlen && cp[nmlen - 1] == 0)
2183 - nmlen--;
2184 - }
2185 - if (nmlen == 0)
2186 - goto nodata;
2187 -
2188 - /*
2189 - * On a find-next we expect that the server will:
2190 - * 1) if the continue bit is set, use the server's offset,
2191 - * 2) else if the resume key is non-zero, use that offset,
2192 - * 3) else if the resume name is set, use that offset,
2193 - * 4) else use the server's idea of current offset.
2194 - *
2195 - * We always set the resume key flag. If the server returns
2196 - * a resume key then we should always send it back to them.
2197 - */
2198 - ctx->f_rkey = resumekey;
2199 -
2200 - next = ctx->f_eofs + recsz;
2201 - if (ctx->f_rnameofs &&
2202 - ctx->f_rnameofs >= ctx->f_eofs &&
2203 - ctx->f_rnameofs < (int)next) {
2204 - /*
2205 - * This entry is the "resume name".
2206 - * Save it for the next request.
2207 - */
2208 - if (ctx->f_rnamelen != nmlen) {
2209 - if (ctx->f_rname)
2210 - kmem_free(ctx->f_rname, ctx->f_rnamelen);
2211 - ctx->f_rname = kmem_alloc(nmlen, KM_SLEEP);
2212 - ctx->f_rnamelen = nmlen;
2213 - }
2214 - bcopy(ctx->f_name, ctx->f_rname, nmlen);
2215 - }
2216 - ctx->f_nmlen = nmlen;
2217 - ctx->f_eofs = next;
2218 - ctx->f_ecnt--;
2219 - ctx->f_left--;
2220 -
2221 - smbfs_fname_tolocal(ctx);
2222 - return (0);
2223 -
2224 -nodata:
2225 - /*
2226 - * Something bad has happened and we ran out of data
2227 - * before we could parse all f_ecnt entries expected.
2228 - * Force this directory listing closed, otherwise the
2229 - * calling process may hang in an infinite loop.
2230 - */
2231 - SMBVDEBUG("ran out of data\n");
2232 - ctx->f_ecnt = 0; /* Force closed. */
2233 - ctx->f_flags |= SMBFS_RDD_EOF;
2234 - return (EIO);
2235 -}
2236 -
2237 -static int
2238 -smbfs_smb_findcloseLM2(struct smbfs_fctx *ctx)
2239 -{
2240 - int error = 0;
2241 - if (ctx->f_name)
2242 - kmem_free(ctx->f_name, ctx->f_namesz);
2243 - if (ctx->f_t2)
2244 - smb_t2_done(ctx->f_t2);
2245 - /*
2246 - * If SMBFS_RDD_FINDFIRST is still set, we were opened
2247 - * but never saw a findfirst, so we don't have any
2248 - * search handle to close.
2249 - */
2250 - if ((ctx->f_flags & (SMBFS_RDD_FINDFIRST | SMBFS_RDD_NOCLOSE)) == 0)
2251 - error = smbfs_smb_findclose2(ctx);
2252 - return (error);
2253 -}
2254 -
2255 574 int
2256 575 smbfs_smb_findopen(struct smbnode *dnp, const char *wild, int wlen,
2257 576 int attr, struct smb_cred *scrp,
2258 577 struct smbfs_fctx **ctxpp)
2259 578 {
579 + struct smb_share *ssp = dnp->n_mount->smi_share;
580 + struct smb_vc *vcp = SSTOVC(ssp);
2260 581 struct smbfs_fctx *ctx;
2261 582 int error;
2262 583
2263 584 ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
2264 585
2265 586 ctx->f_flags = SMBFS_RDD_FINDFIRST;
2266 587 ctx->f_dnp = dnp;
2267 588 ctx->f_scred = scrp;
2268 - ctx->f_ssp = dnp->n_mount->smi_share;
589 + ctx->f_ssp = ssp;
2269 590
2270 591 if (dnp->n_flag & N_XATTR) {
2271 592 error = smbfs_xa_findopen(ctx, dnp, wild, wlen);
2272 593 goto out;
2273 594 }
2274 595
2275 - if (SMB_DIALECT(SSTOVC(ctx->f_ssp)) < SMB_DIALECT_LANMAN2_0) {
2276 - error = smbfs_smb_findopenLM1(ctx, dnp, wild, wlen, attr);
596 + if (vcp->vc_flags & SMBV_SMB2) {
597 + error = smbfs_smb2_findopen(ctx, dnp, wild, wlen, attr);
2277 598 } else {
2278 599 error = smbfs_smb_findopenLM2(ctx, dnp, wild, wlen, attr);
2279 600 }
2280 601
2281 602 out:
2282 - if (error)
2283 - (void) smbfs_smb_findclose(ctx, scrp);
2284 - else
603 + ctx->f_scred = NULL;
604 + if (error) {
605 + kmem_free(ctx, sizeof (*ctx));
606 + } else {
2285 607 *ctxpp = ctx;
608 + }
609 +
2286 610 return (error);
2287 611 }
2288 612
2289 613 int
2290 614 smbfs_smb_findnext(struct smbfs_fctx *ctx, int limit, struct smb_cred *scrp)
2291 615 {
2292 - int error;
616 + int error = 0;
617 + uint16_t lim;
2293 618
2294 619 /*
2295 620 * Note: "limit" (maxcount) needs to fit in a short!
2296 621 */
2297 622 if (limit > 0xffff)
2298 623 limit = 0xffff;
624 + lim = (uint16_t)limit;
2299 625
2300 626 ctx->f_scred = scrp;
2301 627 for (;;) {
2302 628 bzero(&ctx->f_attr, sizeof (ctx->f_attr));
2303 629 switch (ctx->f_type) {
2304 - case ft_LM1:
2305 - error = smbfs_smb_findnextLM1(ctx, (uint16_t)limit);
630 +
631 + case ft_SMB2:
632 + error = smbfs_smb2_findnext(ctx, lim);
2306 633 break;
2307 634 case ft_LM2:
2308 - error = smbfs_smb_findnextLM2(ctx, (uint16_t)limit);
635 + error = smbfs_smb_findnextLM2(ctx, lim);
2309 636 break;
2310 637 case ft_XA:
2311 - error = smbfs_xa_findnext(ctx, (uint16_t)limit);
638 + error = smbfs_xa_findnext(ctx, lim);
2312 639 break;
2313 640 default:
2314 641 ASSERT(0);
2315 642 error = EINVAL;
2316 643 break;
2317 644 }
2318 645 if (error)
2319 - return (error);
646 + break;
2320 647 /*
2321 648 * Skip "." or ".." - easy now that ctx->f_name
2322 649 * has already been converted to utf-8 format.
2323 650 */
2324 651 if ((ctx->f_nmlen == 1 && ctx->f_name[0] == '.') ||
2325 652 (ctx->f_nmlen == 2 && ctx->f_name[0] == '.' &&
2326 653 ctx->f_name[1] == '.'))
2327 654 continue;
2328 655 break;
2329 656 }
657 + ctx->f_scred = NULL;
658 + if (error != 0)
659 + return (error);
2330 660
2331 - /*
2332 - * Moved the smbfs_fname_tolocal(ctx) call into
2333 - * the ..._findnext functions above.
2334 - */
661 + ctx->f_inum = smbfs_getino(ctx->f_dnp,
662 + ctx->f_name, ctx->f_nmlen);
2335 663
2336 - ctx->f_inum = smbfs_getino(ctx->f_dnp, ctx->f_name, ctx->f_nmlen);
2337 - return (0);
664 +#ifdef DEBUG
665 + SMBVDEBUG("findnext: (%s)\n", ctx->f_name);
666 +#endif
667 +
668 + return (error);
2338 669 }
2339 670
2340 671
2341 672 int
2342 673 smbfs_smb_findclose(struct smbfs_fctx *ctx, struct smb_cred *scrp)
2343 674 {
2344 675 int error;
2345 676
2346 677 ctx->f_scred = scrp;
2347 678 switch (ctx->f_type) {
2348 - case ft_LM1:
2349 - error = smbfs_smb_findcloseLM1(ctx);
679 + case ft_SMB2:
680 + error = smbfs_smb2_findclose(ctx);
2350 681 break;
2351 682 case ft_LM2:
2352 683 error = smbfs_smb_findcloseLM2(ctx);
2353 684 break;
2354 685 case ft_XA:
2355 686 error = smbfs_xa_findclose(ctx);
2356 687 break;
688 + default:
689 + error = ENOSYS;
690 + break;
2357 691 }
692 + ctx->f_scred = NULL;
2358 693 if (ctx->f_rname)
2359 694 kmem_free(ctx->f_rname, ctx->f_rnamelen);
2360 695 if (ctx->f_firstnm)
2361 696 kmem_free(ctx->f_firstnm, ctx->f_firstnmlen);
2362 697 kmem_free(ctx, sizeof (*ctx));
2363 698 return (error);
2364 699 }
2365 700
2366 701
2367 702 int
2368 703 smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp,
2369 704 struct smbfattr *fap, struct smb_cred *scrp)
2370 705 {
2371 706 struct smbfs_fctx *ctx;
2372 707 int error, intr;
2373 708 const char *name = (namep ? *namep : NULL);
2374 709 int nmlen = (nmlenp ? *nmlenp : 0);
2375 710
2376 711 /* This is no longer called with a null dnp */
2377 712 ASSERT(dnp);
2378 713
2379 714 /*
2380 715 * Should not get here with "" anymore.
2381 716 */
2382 717 if (!name || !nmlen) {
2383 718 DEBUG_ENTER("smbfs_smb_lookup: name is NULL");
2384 719 return (EINVAL);
2385 720 }
2386 721
|
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
2387 722 /*
2388 723 * Should not get here with "." or ".." anymore.
2389 724 */
2390 725 if ((nmlen == 1 && name[0] == '.') ||
2391 726 (nmlen == 2 && name[0] == '.' && name[1] == '.')) {
2392 727 DEBUG_ENTER("smbfs_smb_lookup: name is '.' or '..'");
2393 728 return (EINVAL);
2394 729 }
2395 730
2396 731 /*
2397 - * XXX: Should use _qpathinfo here instead.
2398 - * (if SMB_CAP_NT_SMBS)
2399 - */
2400 -
2401 - /*
2402 732 * Shared lock for n_fid use (smb_flush).
2403 733 */
2404 734 intr = dnp->n_mount->smi_flags & SMI_INT;
2405 735 if (smbfs_rw_enter_sig(&dnp->r_lkserlock, RW_READER, intr))
2406 736 return (EINTR);
2407 737
2408 - /*
2409 - * This hides a server bug observable in Win98:
2410 - * size changes may not show until a CLOSE or a FLUSH op
2411 - * XXX: Make this conditional on !NTSMBs
2412 - */
2413 - error = smbfs_smb_flush(dnp, scrp);
2414 - if (error)
2415 - goto out;
2416 738 error = smbfs_smb_findopen(dnp, name, nmlen,
2417 739 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scrp, &ctx);
2418 740 if (error)
2419 741 goto out;
2420 742 ctx->f_flags |= SMBFS_RDD_FINDSINGLE;
2421 743 error = smbfs_smb_findnext(ctx, 1, scrp);
2422 744 if (error == 0) {
2423 745 *fap = ctx->f_attr;
2424 746 /*
2425 747 * Solaris smbfattr doesn't have fa_ino,
2426 748 * and we don't allow name==NULL in this
2427 749 * function anymore.
2428 750 */
2429 751 if (namep)
2430 752 *namep = (const char *)smbfs_name_alloc(
2431 753 ctx->f_name, ctx->f_nmlen);
2432 754 if (nmlenp)
2433 755 *nmlenp = ctx->f_nmlen;
2434 756 }
2435 757 (void) smbfs_smb_findclose(ctx, scrp);
2436 758
2437 759 out:
2438 760 smbfs_rw_exit(&dnp->r_lkserlock);
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
2439 761 return (error);
2440 762 }
2441 763
2442 764 /*
2443 765 * OTW function to Get a security descriptor (SD).
2444 766 *
2445 767 * Note: On success, this fills in mdp->md_top,
2446 768 * which the caller should free.
2447 769 */
2448 770 int
2449 -smbfs_smb_getsec_m(struct smb_share *ssp, uint16_t fid,
2450 - struct smb_cred *scrp, uint32_t selector,
2451 - mblk_t **res, uint32_t *reslen)
771 +smbfs_smb_getsec(struct smb_share *ssp, smb_fh_t *fhp,
772 + uint32_t selector, mblk_t **res, uint32_t *reslen,
773 + struct smb_cred *scrp)
2452 774 {
2453 - struct smb_ntrq *ntp;
2454 - struct mbchain *mbp;
2455 - struct mdchain *mdp;
775 + struct smb_vc *vcp = SSTOVC(ssp);
2456 776 int error, len;
2457 777
2458 - error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_QUERY_SECURITY_DESC,
2459 - scrp, &ntp);
2460 - if (error)
2461 - return (error);
2462 -
2463 - /* Parameters part */
2464 - mbp = &ntp->nt_tparam;
2465 - mb_init(mbp);
2466 - mb_put_uint16le(mbp, fid);
2467 - mb_put_uint16le(mbp, 0); /* reserved */
2468 - mb_put_uint32le(mbp, selector);
2469 - /* Data part (none) */
2470 -
2471 - /* Max. returned parameters and data. */
2472 - ntp->nt_maxpcount = 4;
2473 - ntp->nt_maxdcount = *reslen;
2474 -
2475 - error = smb_nt_request(ntp);
2476 - if (error && !(ntp->nt_flags & SMBT2_MOREDATA))
2477 - goto done;
2478 778 *res = NULL;
2479 779
2480 - /*
2481 - * if there's more data than we said we could receive, here
2482 - * is where we pick up the length of it
2483 - */
2484 - mdp = &ntp->nt_rparam;
2485 - md_get_uint32le(mdp, reslen);
2486 - if (error)
2487 - goto done;
780 + if (vcp->vc_flags & SMBV_SMB2) {
781 + error = smbfs_smb2_getsec(ssp, &fhp->fh_fid2,
782 + selector, res, reslen, scrp);
783 + } else {
784 + error = smbfs_smb1_getsec(ssp, fhp->fh_fid1,
785 + selector, res, reslen, scrp);
786 + }
2488 787
2489 788 /*
2490 789 * get the data part.
2491 790 */
2492 - mdp = &ntp->nt_rdata;
2493 - if (mdp->md_top == NULL) {
2494 - SMBVDEBUG("null md_top? fid 0x%x\n", fid);
791 + if (*res == NULL) {
2495 792 error = EBADRPC;
2496 793 goto done;
2497 794 }
2498 795
2499 796 /*
2500 - * The returned parameter SD_length should match
2501 - * the length of the returned data. Unfortunately,
2502 - * we have to work around server bugs here.
797 + * If message length is < returned SD_length,
798 + * correct *reslen (reduce it). It greater,
799 + * just ignore the extra data.
2503 800 */
2504 - len = m_fixhdr(mdp->md_top);
2505 - if (len != *reslen) {
2506 - SMBVDEBUG("len %d *reslen %d fid 0x%x\n",
2507 - len, *reslen, fid);
2508 - }
2509 -
2510 - /*
2511 - * Actual data provided is < returned SD_length.
2512 - *
2513 - * The following "if (len < *reslen)" handles a Windows bug
2514 - * observed when the underlying filesystem is FAT32. In that
2515 - * case a 32 byte security descriptor comes back (S-1-1-0, ie
2516 - * "Everyone") but the Parameter Block claims 44 is the length
2517 - * of the security descriptor. (The Data Block length
2518 - * claimed is 32. This server bug was reported against NT
2519 - * first and I've personally observed it with W2K.
2520 - */
801 + len = m_fixhdr(*res);
2521 802 if (len < *reslen)
2522 803 *reslen = len;
2523 804
2524 - /*
2525 - * Actual data provided is > returned SD_length.
2526 - * (Seen on StorageTek NAS 5320, s/w ver. 4.21 M0)
2527 - * Narrow work-around for returned SD_length==0.
2528 - */
2529 - if (len > *reslen) {
2530 - /*
2531 - * Increase *reslen, but carefully.
2532 - */
2533 - if (*reslen == 0 && len <= ntp->nt_maxdcount)
2534 - *reslen = len;
2535 - }
2536 - error = md_get_mbuf(mdp, len, res);
2537 -
2538 805 done:
2539 806 if (error == 0 && *res == NULL) {
2540 807 ASSERT(*res);
2541 808 error = EBADRPC;
2542 809 }
2543 810
2544 - smb_nt_done(ntp);
2545 811 return (error);
2546 812 }
2547 813
2548 -#ifdef APPLE
2549 814 /*
2550 - * Wrapper for _getsd() compatible with darwin code.
2551 - */
2552 -int
2553 -smbfs_smb_getsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp,
2554 - uint32_t selector, struct ntsecdesc **res)
2555 -{
2556 - int error;
2557 - uint32_t len, olen;
2558 - struct mdchain *mdp, md_store;
2559 - struct mbuf *m;
2560 -
2561 - bzero(mdp, sizeof (*mdp));
2562 - len = 500; /* "overlarge" values => server errors */
2563 -again:
2564 - olen = len;
2565 - error = smbfs_smb_getsec_m(ssp, fid, scrp, selector, &m, &len);
2566 - /*
2567 - * Server may give us an error indicating that we
2568 - * need a larger data buffer to receive the SD,
2569 - * and the size we'll need. Use the given size,
2570 - * but only after a sanity check.
2571 - *
2572 - * XXX: Check for specific error values here?
2573 - * XXX: also ... && len <= MAX_RAW_SD_SIZE
2574 - */
2575 - if (error && len > olen)
2576 - goto again;
2577 -
2578 - if (error)
2579 - return (error);
2580 -
2581 - mdp = &md_store;
2582 - md_initm(mdp, m);
2583 - MALLOC(*res, struct ntsecdesc *, len, M_TEMP, M_WAITOK);
2584 - error = md_get_mem(mdp, (caddr_t)*res, len, MB_MSYSTEM);
2585 - md_done(mdp);
2586 -
2587 - return (error);
2588 -}
2589 -#endif /* APPLE */
2590 -
2591 -/*
2592 815 * OTW function to Set a security descriptor (SD).
2593 816 * Caller data are carried in an mbchain_t.
2594 817 *
2595 818 * Note: This normally consumes mbp->mb_top, and clears
2596 819 * that pointer when it does.
2597 820 */
2598 -int smbfs_smb_setsec_m(struct smb_share *ssp, uint16_t fid,
2599 - struct smb_cred *scrp, uint32_t selector, mblk_t **mp)
821 +int
822 +smbfs_smb_setsec(struct smb_share *ssp, smb_fh_t *fhp,
823 + uint32_t selector, mblk_t **mp,
824 + struct smb_cred *scrp)
2600 825 {
2601 - struct smb_ntrq *ntp;
2602 - struct mbchain *mbp;
826 + struct smb_vc *vcp = SSTOVC(ssp);
2603 827 int error;
2604 828
2605 - error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_SET_SECURITY_DESC,
2606 - scrp, &ntp);
2607 - if (error)
2608 - return (error);
2609 -
2610 - /* Parameters part */
2611 - mbp = &ntp->nt_tparam;
2612 - mb_init(mbp);
2613 - mb_put_uint16le(mbp, fid);
2614 - mb_put_uint16le(mbp, 0); /* reserved */
2615 - mb_put_uint32le(mbp, selector);
2616 -
2617 - /* Data part */
2618 - mbp = &ntp->nt_tdata;
2619 - mb_initm(mbp, *mp);
2620 - *mp = NULL; /* consumed */
2621 -
2622 - /* No returned parameters or data. */
2623 - ntp->nt_maxpcount = 0;
2624 - ntp->nt_maxdcount = 0;
2625 -
2626 - error = smb_nt_request(ntp);
2627 - smb_nt_done(ntp);
2628 -
2629 - return (error);
2630 -}
2631 -
2632 -#ifdef APPLE
2633 -/*
2634 - * This function builds the SD given the various parts.
2635 - */
2636 -int
2637 -smbfs_smb_setsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp,
2638 - uint32_t selector, uint16_t flags, struct ntsid *owner,
2639 - struct ntsid *group, struct ntacl *sacl, struct ntacl *dacl)
2640 -{
2641 - struct mbchain *mbp, mb_store;
2642 - struct ntsecdesc ntsd;
2643 - int error, off;
2644 -
2645 - /*
2646 - * Build the SD as its own mbuf chain and pass it to
2647 - * smbfs_smb_setsec_m()
2648 - */
2649 - mbp = &mb_store;
2650 - mb_init(mbp);
2651 - bzero(&ntsd, sizeof (ntsd));
2652 - wset_sdrevision(&ntsd);
2653 - /*
2654 - * A note about flags ("SECURITY_DESCRIPTOR_CONTROL" in MSDN)
2655 - * We set here only those bits we can be sure must be set. The rest
2656 - * are up to the caller. In particular, the caller may intentionally
2657 - * set an acl PRESENT bit while giving us a null pointer for the
2658 - * acl - that sets a null acl, giving access to everyone. Note also
2659 - * that the AUTO_INHERITED bits should probably always be set unless
2660 - * the server is NT.
2661 - */
2662 - flags |= SD_SELF_RELATIVE;
2663 - off = sizeof (ntsd);
2664 - if (owner) {
2665 - wset_sdowneroff(&ntsd, off);
2666 - off += sidlen(owner);
829 + if (vcp->vc_flags & SMBV_SMB2) {
830 + error = smbfs_smb2_setsec(ssp, &fhp->fh_fid2,
831 + selector, mp, scrp);
832 + } else {
833 + error = smbfs_smb1_setsec(ssp, fhp->fh_fid1,
834 + selector, mp, scrp);
2667 835 }
2668 - if (group) {
2669 - wset_sdgroupoff(&ntsd, off);
2670 - off += sidlen(group);
2671 - }
2672 - if (sacl) {
2673 - flags |= SD_SACL_PRESENT;
2674 - wset_sdsacloff(&ntsd, off);
2675 - off += acllen(sacl);
2676 - }
2677 - if (dacl) {
2678 - flags |= SD_DACL_PRESENT;
2679 - wset_sddacloff(&ntsd, off);
2680 - }
2681 - wset_sdflags(&ntsd, flags);
2682 - mb_put_mem(mbp, (caddr_t)&ntsd, sizeof (ntsd), MB_MSYSTEM);
2683 - if (owner)
2684 - mb_put_mem(mbp, (caddr_t)owner, sidlen(owner), MB_MSYSTEM);
2685 - if (group)
2686 - mb_put_mem(mbp, (caddr_t)group, sidlen(group), MB_MSYSTEM);
2687 - if (sacl)
2688 - mb_put_mem(mbp, (caddr_t)sacl, acllen(sacl), MB_MSYSTEM);
2689 - if (dacl)
2690 - mb_put_mem(mbp, (caddr_t)dacl, acllen(dacl), MB_MSYSTEM);
2691 836
2692 - /*
2693 - * Just pass the mbuf to _setsec_m
2694 - * It will clear mb_top if consumed.
2695 - */
2696 - error = smbfs_smb_setsec_m(ssp, fid, scrp, selector, &mbp->mb_top);
2697 - mb_done(mbp);
2698 -
2699 837 return (error);
2700 838 }
2701 -
2702 -#endif /* APPLE */
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX