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