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-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)

*** 19,36 **** --- 19,38 ---- * CDDL HEADER END */ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ /* * Functions supporting Solaris Extended Attributes, * used to provide access to CIFS "named streams". */ #include <sys/systm.h> + #include <sys/inttypes.h> #include <sys/cred.h> #include <sys/vnode.h> #include <sys/vfs.h> #include <sys/filio.h> #include <sys/uio.h>
*** 41,51 **** --- 43,55 ---- #include <sys/stat.h> #include <sys/cmn_err.h> #include <sys/u8_textprep.h> #include <netsmb/smb_osdep.h> + #include <netsmb/smb.h> + #include <netsmb/smb2.h> #include <netsmb/smb_conn.h> #include <netsmb/smb_subr.h> #include <netsmb/smb_rq.h> #include <smbfs/smbfs.h>
*** 287,449 **** return (error); } /* ! * Fetch the entire attribute list here in findopen. ! * Will parse the results in findnext. * * This is called on the XATTR directory, so we * have to get the (real) parent object first. */ ! /* ARGSUSED */ ! int ! smbfs_xa_findopen(struct smbfs_fctx *ctx, struct smbnode *dnp, ! const char *wildcard, int wclen) { vnode_t *pvp; /* parent */ smbnode_t *pnp; ! struct smb_t2rq *t2p; ! struct smb_vc *vcp = SSTOVC(ctx->f_ssp); ! struct mbchain *mbp; int error; - ASSERT(dnp->n_flag & N_XATTR); - - ctx->f_type = ft_XA; - ctx->f_namesz = SMB_MAXFNAMELEN + 1; - if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) - ctx->f_namesz *= 2; - ctx->f_name = kmem_alloc(ctx->f_namesz, KM_SLEEP); - error = smbfs_xa_parent(SMBTOV(dnp), &pvp); if (error) return (error); ASSERT(pvp); /* Note: pvp has a VN_HOLD */ pnp = VTOSMB(pvp); ! if (ctx->f_t2) { ! smb_t2_done(ctx->f_t2); ! ctx->f_t2 = NULL; ! } ! error = smb_t2_alloc(SSTOCP(ctx->f_ssp), ! SMB_TRANS2_QUERY_PATH_INFORMATION, ! ctx->f_scred, &t2p); if (error) goto out; - ctx->f_t2 = t2p; - mbp = &t2p->t2_tparam; - (void) mb_init(mbp); - (void) mb_put_uint16le(mbp, SMB_QFILEINFO_STREAM_INFO); - (void) mb_put_uint32le(mbp, 0); - error = smbfs_fullpath(mbp, vcp, pnp, NULL, NULL, 0); - if (error) - goto out; - t2p->t2_maxpcount = 2; - t2p->t2_maxdcount = INT16_MAX; - error = smb_t2_request(t2p); - if (error) { - if (t2p->t2_sr_error == NT_STATUS_INVALID_PARAMETER) - error = ENOTSUP; - } /* ! * No returned parameters to parse. ! * Returned data are in t2_rdata, ! * which we'll parse in _findnext. ! * However, save the wildcard. */ ! ctx->f_wildcard = wildcard; ! ctx->f_wclen = wclen; out: VN_RELE(pvp); return (error); } /* ! * Get the next name in an XATTR directory into f_name */ - /* ARGSUSED */ int ! smbfs_xa_findnext(struct smbfs_fctx *ctx, uint16_t limit) { - struct mdchain *mdp; - struct smb_t2rq *t2p; - uint32_t size, next; - uint64_t llongint; - int error, skip, used, nmlen; ! t2p = ctx->f_t2; ! mdp = &t2p->t2_rdata; ! if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) { ! ASSERT(ctx->f_wildcard); ! SMBVDEBUG("wildcard: %s\n", ctx->f_wildcard); ! } ! again: ! if (ctx->f_flags & SMBFS_RDD_EOF) ! return (ENOENT); - /* Parse FILE_STREAM_INFORMATION */ - if ((error = md_get_uint32le(mdp, &next)) != 0) /* offset to */ - return (ENOENT); - if ((error = md_get_uint32le(mdp, &size)) != 0) /* name len */ - return (ENOENT); - (void) md_get_uint64le(mdp, &llongint); /* file size */ - ctx->f_attr.fa_size = llongint; - (void) md_get_uint64le(mdp, NULL); /* alloc. size */ - used = 4 + 4 + 8 + 8; /* how much we consumed */ ! /* ! * Copy the string, but skip the first char (":") ! * Watch out for zero-length strings here. */ ! if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) { ! if (size >= 2) { ! size -= 2; used += 2; ! (void) md_get_uint16le(mdp, NULL); ! } ! nmlen = min(size, SMB_MAXFNAMELEN * 2); ! } else { ! if (size >= 1) { ! size -= 1; used += 1; ! (void) md_get_uint8(mdp, NULL); ! } ! nmlen = min(size, SMB_MAXFNAMELEN); ! } ! ASSERT(nmlen < ctx->f_namesz); ! ctx->f_nmlen = nmlen; ! error = md_get_mem(mdp, ctx->f_name, nmlen, MB_MSYSTEM); if (error) return (error); ! used += nmlen; /* ! * Convert UCS-2 to UTF-8 */ ! smbfs_fname_tolocal(ctx); ! if (nmlen) SMBVDEBUG("name: %s\n", ctx->f_name); - else - SMBVDEBUG("null name!\n"); /* - * Skip padding until next offset - */ - if (next > used) { - skip = next - used; - (void) md_get_mem(mdp, NULL, skip, MB_MSYSTEM); - } - if (next == 0) - ctx->f_flags |= SMBFS_RDD_EOF; - - /* * Chop off the trailing ":$DATA" * The 6 here is strlen(":$DATA") */ if (ctx->f_nmlen >= 6) { char *p = ctx->f_name + ctx->f_nmlen - 6; --- 291,411 ---- return (error); } /* ! * Actually go OtW to get the list of "streams". * * This is called on the XATTR directory, so we * have to get the (real) parent object first. */ ! static int ! smbfs_xa_get_streaminfo(struct smbfs_fctx *ctx) { vnode_t *pvp; /* parent */ smbnode_t *pnp; ! smbnode_t *dnp = ctx->f_dnp; ! struct mdchain *mdp; int error; error = smbfs_xa_parent(SMBTOV(dnp), &pvp); if (error) return (error); ASSERT(pvp); /* Note: pvp has a VN_HOLD */ pnp = VTOSMB(pvp); ! /* ! * Get stream info into f_mdchain ! */ ! mdp = &ctx->f_mdchain; ! md_done(mdp); ! if (SSTOVC(ctx->f_ssp)->vc_flags & SMBV_SMB2) { ! error = smbfs_smb2_get_streaminfo(pnp, mdp, ctx->f_scred); ! } else { ! error = smbfs_smb1_get_streaminfo(pnp, mdp, ctx->f_scred); ! } if (error) goto out; /* ! * Have stream info in ctx->f_mdchain ! * Initialize buffer length, position. */ ! ctx->f_left = m_fixhdr(mdp->md_top); ! ctx->f_eofs = 0; + /* + * After one successful call, we're at EOF. + */ + ctx->f_flags |= SMBFS_RDD_EOF; + out: VN_RELE(pvp); return (error); } /* ! * Get a buffer of directory entries (if we don't already have ! * some remaining in the current buffer) then decode one. */ int ! smbfs_xa_findopen(struct smbfs_fctx *ctx, struct smbnode *dnp, ! const char *wildcard, int wclen) { ! ASSERT(dnp->n_flag & N_XATTR); ! ctx->f_type = ft_XA; ! ctx->f_namesz = SMB_MAXFNAMELEN + 1; ! ctx->f_name = kmem_alloc(ctx->f_namesz, KM_SLEEP); ! ctx->f_infolevel = FileStreamInformation; ! ctx->f_wildcard = wildcard; ! ctx->f_wclen = wclen; ! return (0); ! } ! /* ! * Get the next name in an XATTR directory */ ! /* ARGSUSED */ ! int ! smbfs_xa_findnext(struct smbfs_fctx *ctx, uint16_t limit) ! { ! int error; ! /* ! * If we've scanned to the end of the current buffer ! * try to read anohther buffer of dir entries. ! * Treat anything less than 8 bytes as an "empty" ! * buffer to ensure we can read something. ! * (There may be up to 8 bytes of padding.) ! */ ! again: ! if ((ctx->f_eofs + 8) > ctx->f_left) { ! /* Scanned the whole buffer. */ ! if (ctx->f_flags & SMBFS_RDD_EOF) ! return (ENOENT); ! ctx->f_limit = limit; ! error = smbfs_xa_get_streaminfo(ctx); if (error) return (error); ! ctx->f_otws++; ! } /* ! * Decode one entry, advance f_eofs */ ! error = smbfs_decode_dirent(ctx); ! if (error) ! return (error); SMBVDEBUG("name: %s\n", ctx->f_name); /* * Chop off the trailing ":$DATA" * The 6 here is strlen(":$DATA") */ if (ctx->f_nmlen >= 6) { char *p = ctx->f_name + ctx->f_nmlen - 6;
*** 460,471 **** */ if (ctx->f_nmlen == 0) goto again; /* ! * If this is a lookup of a specific name, ! * skip past any non-matching names. */ if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) { if (ctx->f_wclen != ctx->f_nmlen) goto again; if (u8_strcmp(ctx->f_wildcard, ctx->f_name, --- 422,435 ---- */ if (ctx->f_nmlen == 0) goto again; /* ! * When called by lookup, we'll have the "single" flag, ! * and a name with no wildcards. We need to filter here ! * because smbfs_xa_get_streaminfo() gets ALL the names ! * (not just those matching our pattern). */ if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) { if (ctx->f_wclen != ctx->f_nmlen) goto again; if (u8_strcmp(ctx->f_wildcard, ctx->f_name,
*** 486,495 **** smbfs_xa_findclose(struct smbfs_fctx *ctx) { if (ctx->f_name) kmem_free(ctx->f_name, ctx->f_namesz); - if (ctx->f_t2) - smb_t2_done(ctx->f_t2); return (0); } --- 450,457 ----