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)
re #11128 nsmb_close locking and teardown deadlock
*** 29,41 ****
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/errno.h>
--- 29,42 ----
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/errno.h>
*** 59,106 ****
#include <sys/sdt.h>
#include <fs/fs_subr.h>
#include <sys/modctl.h>
#include <sys/devops.h>
#include <sys/thread.h>
! #include <sys/types.h>
#include <sys/zone.h>
#include <netsmb/smb_osdep.h>
#include <netsmb/mchain.h> /* for "htoles()" */
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
#include <netsmb/smb_subr.h>
#include <netsmb/smb_dev.h>
#include <netsmb/smb_pass.h>
#define NSMB_MIN_MINOR 1
#define NSMB_MAX_MINOR L_MAXMIN32
/* for version checks */
const uint32_t nsmb_version = NSMB_VERSION;
static void *statep;
static major_t nsmb_major;
static minor_t last_minor = NSMB_MIN_MINOR;
- static dev_info_t *nsmb_dip;
static kmutex_t dev_lck;
- /* Zone support */
- zone_key_t nsmb_zone_key;
- extern void nsmb_zone_shutdown(zoneid_t zoneid, void *data);
- extern void nsmb_zone_destroy(zoneid_t zoneid, void *data);
-
/*
* cb_ops device operations.
*/
static int nsmb_open(dev_t *devp, int flag, int otyp, cred_t *credp);
static int nsmb_close(dev_t dev, int flag, int otyp, cred_t *credp);
static int nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
cred_t *credp, int *rvalp);
static int nsmb_close2(smb_dev_t *sdp, cred_t *cr);
/* smbfs cb_ops */
static struct cb_ops nsmb_cbops = {
nsmb_open, /* open */
nsmb_close, /* close */
nodev, /* strategy */
--- 60,123 ----
#include <sys/sdt.h>
#include <fs/fs_subr.h>
#include <sys/modctl.h>
#include <sys/devops.h>
#include <sys/thread.h>
! #include <sys/socket.h>
#include <sys/zone.h>
#include <netsmb/smb_osdep.h>
#include <netsmb/mchain.h> /* for "htoles()" */
#include <netsmb/smb.h>
+ #include <netsmb/smb2.h>
#include <netsmb/smb_conn.h>
#include <netsmb/smb_subr.h>
#include <netsmb/smb_dev.h>
#include <netsmb/smb_pass.h>
+ #ifndef _KERNEL
+ #include <libfknsmb.h>
+
+ #define _init(v) nsmb_drv_init(v)
+ #define _fini(v) nsmb_drv_fini(v)
+
+ #endif /* _KERNEL */
+
#define NSMB_MIN_MINOR 1
#define NSMB_MAX_MINOR L_MAXMIN32
/* for version checks */
const uint32_t nsmb_version = NSMB_VERSION;
+ /* for smb_nbst_create() */
+ dev_t nsmb_dev_tcp = NODEV;
+ dev_t nsmb_dev_tcp6 = NODEV;
+
static void *statep;
static major_t nsmb_major;
static minor_t last_minor = NSMB_MIN_MINOR;
static kmutex_t dev_lck;
/*
* cb_ops device operations.
*/
static int nsmb_open(dev_t *devp, int flag, int otyp, cred_t *credp);
static int nsmb_close(dev_t dev, int flag, int otyp, cred_t *credp);
static int nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
cred_t *credp, int *rvalp);
static int nsmb_close2(smb_dev_t *sdp, cred_t *cr);
+ #ifdef _KERNEL
+
+ static dev_info_t *nsmb_dip;
+
+ /* Zone support */
+ zone_key_t nsmb_zone_key;
+ extern void nsmb_zone_shutdown(zoneid_t zoneid, void *data);
+ extern void nsmb_zone_destroy(zoneid_t zoneid, void *data);
+
/* smbfs cb_ops */
static struct cb_ops nsmb_cbops = {
nsmb_open, /* open */
nsmb_close, /* close */
nodev, /* strategy */
*** 158,171 ****
--- 175,192 ----
MODREV_1,
(void *)&nsmb_modldrv,
NULL
};
+ #endif /* _KERNEL */
+
int
_init(void)
{
+ #ifdef _KERNEL
int error;
+ #endif /* _KERNEL */
(void) ddi_soft_state_init(&statep, sizeof (smb_dev_t), 1);
/* Can initialize some mutexes also. */
mutex_init(&dev_lck, NULL, MUTEX_DRIVER, NULL);
*** 174,189 ****
(void) smb_sm_init();
/* Initialize password Key chain DB. */
smb_pkey_init();
! /* Time conversion stuff. */
! smb_time_init();
!
! /* Initialize crypto mechanisms. */
! smb_crypto_mech_init();
!
zone_key_create(&nsmb_zone_key, NULL, nsmb_zone_shutdown,
nsmb_zone_destroy);
/*
* Install the module. Do this after other init,
--- 195,205 ----
(void) smb_sm_init();
/* Initialize password Key chain DB. */
smb_pkey_init();
! #ifdef _KERNEL
zone_key_create(&nsmb_zone_key, NULL, nsmb_zone_shutdown,
nsmb_zone_destroy);
/*
* Install the module. Do this after other init,
*** 198,207 ****
--- 214,231 ----
mutex_destroy(&dev_lck);
ddi_soft_state_fini(&statep);
return (error);
}
+ #else /* _KERNEL */
+ streams_msg_init();
+ /* No attach, so need to set major. */
+ nsmb_major = 1;
+ /* And these, for smb_nbst_create() */
+ nsmb_dev_tcp = AF_INET;
+ nsmb_dev_tcp6 = AF_INET6;
+ #endif /* _KERNEL */
return (0);
}
int
*** 216,238 ****
if ((status = smb_sm_idle()) != 0)
return (status);
if ((status = smb_pkey_idle()) != 0)
return (status);
/*
* Remove the module. Do this before destroying things,
* to prevent new entrances while we're destorying.
*/
if ((status = mod_remove(&nsmb_modlinkage)) != 0) {
return (status);
}
(void) zone_key_delete(nsmb_zone_key);
- /* Time conversion stuff. */
- smb_time_fini();
-
/* Destroy password Key chain DB. */
smb_pkey_fini();
smb_sm_done();
--- 240,261 ----
if ((status = smb_sm_idle()) != 0)
return (status);
if ((status = smb_pkey_idle()) != 0)
return (status);
+ #ifdef _KERNEL
/*
* Remove the module. Do this before destroying things,
* to prevent new entrances while we're destorying.
*/
if ((status = mod_remove(&nsmb_modlinkage)) != 0) {
return (status);
}
(void) zone_key_delete(nsmb_zone_key);
+ #endif /* _KERNEL */
/* Destroy password Key chain DB. */
smb_pkey_fini();
smb_sm_done();
*** 240,249 ****
--- 263,274 ----
ddi_soft_state_fini(&statep);
return (status);
}
+ #ifdef _KERNEL
+
int
_info(struct modinfo *modinfop)
{
return (mod_info(&nsmb_modlinkage, modinfop));
}
*** 268,277 ****
--- 293,303 ----
}
static int
nsmb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
+ major_t tmaj;
if (cmd != DDI_ATTACH)
return (DDI_FAILURE);
/*
*** 292,301 ****
--- 318,341 ----
* We need the major number a couple places,
* i.e. in smb_dev2share()
*/
nsmb_major = ddi_name_to_major(NSMB_NAME);
+ /*
+ * We also need major numbers for t_kopen
+ */
+ tmaj = ddi_name_to_major("tcp");
+ if (tmaj == DDI_MAJOR_T_NONE)
+ cmn_err(CE_NOTE, "no tcp major?");
+ else
+ nsmb_dev_tcp = makedevice(tmaj, 0);
+ tmaj = ddi_name_to_major("tcp6");
+ if (tmaj == DDI_MAJOR_T_NONE)
+ cmn_err(CE_NOTE, "no tcp6 major?");
+ else
+ nsmb_dev_tcp6 = makedevice(tmaj, 0);
+
nsmb_dip = dip;
ddi_report_dev(dip);
return (DDI_SUCCESS);
}
*** 313,333 ****
ddi_remove_minor_node(dip, NULL);
return (DDI_SUCCESS);
}
/*ARGSUSED*/
static int
nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int flags, /* model.h */
cred_t *cr, int *rvalp)
{
smb_dev_t *sdp;
int err;
sdp = ddi_get_soft_state(statep, getminor(dev));
if (sdp == NULL) {
! return (DDI_FAILURE);
}
if ((sdp->sd_flags & NSMBFL_OPEN) == 0) {
return (EBADF);
}
--- 353,432 ----
ddi_remove_minor_node(dip, NULL);
return (DDI_SUCCESS);
}
+ #else /* _KERNEL */
+
+ /*
+ * Wrappers for libfknsmb: ioctl, open, close, load
+ */
+
/*ARGSUSED*/
+ int
+ nsmb_drv_ioctl(dev32_t dev32, int cmd, intptr_t arg, int flags)
+ {
+ dev_t dev = expldev(dev32);
+ cred_t *cr = CRED();
+ int err;
+
+ err = nsmb_ioctl(dev, cmd, arg, flags, cr, NULL);
+ return (err);
+ }
+
+ /*ARGSUSED*/
+ int
+ nsmb_drv_open(dev32_t *dev32p, int flags, int otyp)
+ {
+ dev_t dev = expldev(*dev32p);
+ int err;
+
+ err = nsmb_open(&dev, flags, otyp, CRED());
+ if (err == 0) {
+ /*
+ * We have NSMB_MAX_MINOR == L_MAXMIN32
+ * therefore cmpldev never fails.
+ */
+ VERIFY(cmpldev(dev32p, dev) != 0);
+ }
+ return (err);
+ }
+
+ /*ARGSUSED*/
+ int
+ nsmb_drv_close(dev32_t dev32, int flags, int otyp)
+ {
+ dev_t dev = expldev(dev32);
+ int err;
+
+ err = nsmb_close(dev, flags, otyp, CRED());
+ return (err);
+ }
+
+ /*
+ * This function intentionally does nothing. It's used only to
+ * force libfknsmb to load at program start so one can set
+ * breakpoints etc. without debugger "force load" tricks.
+ */
+ void
+ nsmb_drv_load(void)
+ {
+ }
+
+ #endif /* _KERNEL */
+
+ /*ARGSUSED*/
static int
nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int flags, /* model.h */
cred_t *cr, int *rvalp)
{
smb_dev_t *sdp;
int err;
sdp = ddi_get_soft_state(statep, getminor(dev));
if (sdp == NULL) {
! return (EBADF);
}
if ((sdp->sd_flags & NSMBFL_OPEN) == 0) {
return (EBADF);
}
*** 344,455 ****
* in a zone that's shutting down. That action will cause
* all of these ioctls to fail on such VCs, so no need to
* check the zone status here on every ioctl call.
*/
! /*
! * Serialize ioctl calls. The smb_usr_... functions
! * don't expect concurrent calls on a given sdp.
! */
! mutex_enter(&sdp->sd_lock);
! if ((sdp->sd_flags & NSMBFL_IOCTL) != 0) {
! mutex_exit(&sdp->sd_lock);
! return (EBUSY);
! }
! sdp->sd_flags |= NSMBFL_IOCTL;
! mutex_exit(&sdp->sd_lock);
- err = 0;
- switch (cmd) {
- case SMBIOC_GETVERS:
- (void) ddi_copyout(&nsmb_version, (void *)arg,
- sizeof (nsmb_version), flags);
- break;
-
- case SMBIOC_FLAGS2:
- err = smb_usr_get_flags2(sdp, arg, flags);
- break;
-
- case SMBIOC_GETSSNKEY:
- err = smb_usr_get_ssnkey(sdp, arg, flags);
- break;
-
- case SMBIOC_DUP_DEV:
- err = smb_usr_dup_dev(sdp, arg, flags);
- break;
-
- case SMBIOC_REQUEST:
- err = smb_usr_simplerq(sdp, arg, flags, cr);
- break;
-
- case SMBIOC_T2RQ:
- err = smb_usr_t2request(sdp, arg, flags, cr);
- break;
-
- case SMBIOC_READ:
- case SMBIOC_WRITE:
- err = smb_usr_rw(sdp, cmd, arg, flags, cr);
- break;
-
- case SMBIOC_NTCREATE:
- err = smb_usr_ntcreate(sdp, arg, flags, cr);
- break;
-
- case SMBIOC_PRINTJOB:
- err = smb_usr_printjob(sdp, arg, flags, cr);
- break;
-
- case SMBIOC_CLOSEFH:
- err = smb_usr_closefh(sdp, cr);
- break;
-
- case SMBIOC_SSN_CREATE:
- case SMBIOC_SSN_FIND:
- err = smb_usr_get_ssn(sdp, cmd, arg, flags, cr);
- break;
-
- case SMBIOC_SSN_KILL:
- case SMBIOC_SSN_RELE:
- err = smb_usr_drop_ssn(sdp, cmd);
- break;
-
- case SMBIOC_TREE_CONNECT:
- case SMBIOC_TREE_FIND:
- err = smb_usr_get_tree(sdp, cmd, arg, flags, cr);
- break;
-
- case SMBIOC_TREE_KILL:
- case SMBIOC_TREE_RELE:
- err = smb_usr_drop_tree(sdp, cmd);
- break;
-
- case SMBIOC_IOD_WORK:
- err = smb_usr_iod_work(sdp, arg, flags, cr);
- break;
-
- case SMBIOC_IOD_IDLE:
- case SMBIOC_IOD_RCFAIL:
- err = smb_usr_iod_ioctl(sdp, cmd, arg, flags);
- break;
-
- case SMBIOC_PK_ADD:
- case SMBIOC_PK_DEL:
- case SMBIOC_PK_CHK:
- case SMBIOC_PK_DEL_OWNER:
- case SMBIOC_PK_DEL_EVERYONE:
- err = smb_pkey_ioctl(cmd, arg, flags, cr);
- break;
-
- default:
- err = ENOTTY;
- break;
- }
-
- mutex_enter(&sdp->sd_lock);
- sdp->sd_flags &= ~NSMBFL_IOCTL;
- mutex_exit(&sdp->sd_lock);
-
return (err);
}
/*
* This does "clone" open, meaning it automatically
--- 443,454 ----
* in a zone that's shutting down. That action will cause
* all of these ioctls to fail on such VCs, so no need to
* check the zone status here on every ioctl call.
*/
! err = smb_usr_ioctl(sdp, cmd, arg, flags, cr);
return (err);
}
/*
* This does "clone" open, meaning it automatically
*** 489,499 ****
return (ENXIO);
}
*dev = makedevice(nsmb_major, m);
mutex_exit(&dev_lck);
- sdp->sd_smbfid = -1;
sdp->sd_flags |= NSMBFL_OPEN;
sdp->zoneid = crgetzoneid(cr);
mutex_init(&sdp->sd_lock, NULL, MUTEX_DRIVER, NULL);
return (0);
--- 488,497 ----
*** 527,544 ****
ddi_soft_state_free(statep, inst);
mutex_exit(&dev_lck);
return (err);
}
static int
nsmb_close2(smb_dev_t *sdp, cred_t *cr)
{
struct smb_vc *vcp;
struct smb_share *ssp;
! if (sdp->sd_smbfid != -1)
! (void) smb_usr_closefh(sdp, cr);
ssp = sdp->sd_share;
if (ssp != NULL)
smb_share_rele(ssp);
--- 525,545 ----
ddi_soft_state_free(statep, inst);
mutex_exit(&dev_lck);
return (err);
}
+ /*ARGSUSED*/
static int
nsmb_close2(smb_dev_t *sdp, cred_t *cr)
{
struct smb_vc *vcp;
struct smb_share *ssp;
+ struct smb_fh *fhp;
! fhp = sdp->sd_fh;
! if (fhp != NULL)
! smb_fh_rele(fhp);
ssp = sdp->sd_share;
if (ssp != NULL)
smb_share_rele(ssp);
*** 564,575 ****
--- 565,578 ----
* the FD for this device instance.
*/
int
smb_usr_dup_dev(smb_dev_t *sdp, intptr_t arg, int flags)
{
+ #ifdef _KERNEL
file_t *fp = NULL;
vnode_t *vp;
+ #endif /* _KERNEL */
smb_dev_t *from_sdp;
dev_t dev;
int32_t ufd;
int err;
*** 580,599 ****
--- 583,610 ----
/*
* Get from_sdp (what we will duplicate)
*/
if (ddi_copyin((void *) arg, &ufd, sizeof (ufd), flags))
return (EFAULT);
+ #ifdef _KERNEL
if ((fp = getf(ufd)) == NULL)
return (EBADF);
/* rele fp below */
vp = fp->f_vnode;
dev = vp->v_rdev;
+ #else /* _KERNEL */
+ /*
+ * No getf(ufd) -- ufd is really a dev32_t
+ */
+ dev = expldev((dev32_t)ufd);
+ #endif /* _KERNEL */
if (dev == 0 || dev == NODEV ||
getmajor(dev) != nsmb_major) {
err = EINVAL;
goto out;
}
+
from_sdp = ddi_get_soft_state(statep, getminor(dev));
if (from_sdp == NULL) {
err = EINVAL;
goto out;
}
*** 607,618 ****
--- 618,631 ----
smb_share_hold(sdp->sd_share);
sdp->sd_level = from_sdp->sd_level;
err = 0;
out:
+ #ifdef _KERNEL
if (fp)
releasef(ufd);
+ #endif /* _KERNEL */
return (err);
}
/*
*** 619,641 ****
* Helper used by smbfs_mount
*/
int
smb_dev2share(int fd, struct smb_share **sspp)
{
file_t *fp = NULL;
vnode_t *vp;
smb_dev_t *sdp;
smb_share_t *ssp;
dev_t dev;
int err;
if ((fp = getf(fd)) == NULL)
return (EBADF);
/* rele fp below */
-
vp = fp->f_vnode;
dev = vp->v_rdev;
if (dev == 0 || dev == NODEV ||
getmajor(dev) != nsmb_major) {
err = EINVAL;
goto out;
}
--- 632,662 ----
* Helper used by smbfs_mount
*/
int
smb_dev2share(int fd, struct smb_share **sspp)
{
+ #ifdef _KERNEL
file_t *fp = NULL;
vnode_t *vp;
+ #endif /* _KERNEL */
smb_dev_t *sdp;
smb_share_t *ssp;
dev_t dev;
int err;
+ #ifdef _KERNEL
if ((fp = getf(fd)) == NULL)
return (EBADF);
/* rele fp below */
vp = fp->f_vnode;
dev = vp->v_rdev;
+ #else /* _KERNEL */
+ /*
+ * No getf(ufd) -- fd is really a dev32_t
+ */
+ dev = expldev((dev32_t)fd);
+ #endif /* _KERNEL */
if (dev == 0 || dev == NODEV ||
getmajor(dev) != nsmb_major) {
err = EINVAL;
goto out;
}
*** 658,666 ****
--- 679,689 ----
*sspp = ssp;
smb_share_hold(ssp);
err = 0;
out:
+ #ifdef _KERNEL
if (fp)
releasef(fd);
+ #endif /* _KERNEL */
return (err);
}