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
↓ 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
↓ 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,
↓ 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