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)
*** 31,43 ****
*
* $Id: smb_conn.h,v 1.32.42.1 2005/05/27 02:35:29 lindak Exp $
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SMB_CONN_H
#define _SMB_CONN_H
--- 31,45 ----
*
* $Id: smb_conn.h,v 1.32.42.1 2005/05/27 02:35:29 lindak Exp $
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Portions Copyright (C) 2001 - 2013 Apple Inc. All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMB_CONN_H
#define _SMB_CONN_H
*** 44,53 ****
--- 46,56 ----
#include <sys/dditypes.h>
#include <sys/t_lock.h>
#include <sys/queue.h> /* for SLIST below */
#include <sys/uio.h>
#include <netsmb/smb_dev.h>
+ #include "smb_signing.h"
/*
* Credentials of user/process for processing in the connection procedures
*/
typedef struct smb_cred {
*** 59,76 ****
*/
#define SMBO_GONE 0x1000000
/*
* Bits in vc_flags (a.k.a. vc_co.co_flags)
! * Many of these were duplicates of SMBVOPT_ flags
! * and we now keep those too instead of merging
! * them into vc_flags.
*/
-
- #define SMBV_WIN95 0x0010 /* used to apply bugfixes for this OS */
- #define SMBV_NT4 0x0020 /* used when NT4 issues invalid resp */
#define SMBV_UNICODE 0x0040 /* conn configured to use Unicode */
/*
* Note: the common "obj" level uses this GONE flag by
* the name SMBO_GONE. Keep this alias as a reminder.
*/
--- 62,79 ----
*/
#define SMBO_GONE 0x1000000
/*
* Bits in vc_flags (a.k.a. vc_co.co_flags)
! * Note: SMBO_GONE is also in vc_flags
*/
#define SMBV_UNICODE 0x0040 /* conn configured to use Unicode */
+ #define SMBV_EXT_SEC 0x0080 /* conn to use extended security */
+ #define SMBV_SIGNING 0x0100 /* negotiated signing */
+ #define SMBV_SMB2 0x0200 /* VC using SMB 2 or 3 */
+ #define SMBV_HAS_FILEIDS 0x0400 /* Use File IDs for hash and inode numbers */
+ #define SMBV_NO_WRITE_THRU 0x0800 /* Can't use ... */
/*
* Note: the common "obj" level uses this GONE flag by
* the name SMBO_GONE. Keep this alias as a reminder.
*/
*** 87,96 ****
--- 90,109 ----
* Note: the common "obj" level uses this GONE flag by
* the name SMBO_GONE. Keep this alias as a reminder.
*/
#define SMBS_GONE SMBO_GONE
+ /*
+ * bits in smb_fh fh_flags (a.k.a. ss_co.co_flags)
+ */
+ #define SMBFH_VALID 0x0002 /* FID is valid */
+ /*
+ * Note: the common "obj" level uses this GONE flag by
+ * the name SMBO_GONE. Keep this alias as a reminder.
+ */
+ #define SMBFH_GONE SMBO_GONE
+
struct smb_rq;
/* This declares struct smb_rqhead */
TAILQ_HEAD(smb_rqhead, smb_rq);
#define SMB_NBTIMO 15
*** 139,153 ****
typedef struct smb_connobj smb_connobj_t;
/*
* "Level" in the connection object hierarchy
*/
! #define SMBL_SM 0
! #define SMBL_VC 1
! #define SMBL_SHARE 2
/*
* Virtual Circuit to a server (really connection + session).
* Yes, calling this a "Virtual Circuit" is confusining,
* because it has nothing to do with the SMB notion of a
* "Virtual Circuit".
*/
--- 152,214 ----
typedef struct smb_connobj smb_connobj_t;
/*
* "Level" in the connection object hierarchy
*/
! enum smbco_level {
! SMBL_SM = 0,
! SMBL_VC = 1,
! SMBL_SHARE = 2,
! SMBL_FH = 3
! };
/*
+ * SMB1 Negotiated protocol parameters
+ */
+ struct smb_sopt {
+ int16_t sv_proto; /* protocol dialect */
+ uchar_t sv_sm; /* security mode */
+ int16_t sv_tz; /* offset in min relative to UTC */
+ uint16_t sv_maxmux; /* max number of outstanding rq's */
+ uint16_t sv_maxvcs; /* max number of VCs */
+ uint16_t sv_rawmode;
+ uint32_t sv_maxtx; /* maximum transmit buf size */
+ uint32_t sv_maxraw; /* maximum raw-buffer size */
+ uint32_t sv_skey; /* session key */
+ uint32_t sv_caps; /* capabilites SMB_CAP_ */
+
+ /* SMB2+ fields */
+ uint32_t sv2_sessflags; /* final session setup reply flags */
+ uint16_t sv2_dialect; /* dialect (non zero for SMB 2/3 */
+ uint32_t sv2_capabilities; /* capabilities */
+ uint32_t sv2_maxtransact; /* max transact size */
+ uint32_t sv2_maxread; /* max read size */
+ uint32_t sv2_maxwrite; /* max write size */
+ uint8_t sv2_guid[16]; /* GUID */
+ uint16_t sv2_security_mode; /* security mode */
+ };
+ typedef struct smb_sopt smb_sopt_t;
+
+ /*
+ * SMB1 I/O Deamon state
+ */
+ struct smb_iods {
+ uint8_t is_hflags; /* SMB header flags */
+ uint16_t is_hflags2; /* SMB header flags2 */
+ uint16_t is_smbuid; /* SMB header UID */
+ uint16_t is_next_mid; /* SMB header MID */
+ uint32_t is_txmax; /* max tx/rx packet size */
+ uint32_t is_rwmax; /* max read/write data size */
+ uint32_t is_rxmax; /* max readx data size */
+ uint32_t is_wxmax; /* max writex data size */
+ /* Signing state */
+ uint32_t is_next_seq; /* my next sequence number */
+
+ };
+ typedef struct smb_iods smb_iods_t;
+
+ /*
* Virtual Circuit to a server (really connection + session).
* Yes, calling this a "Virtual Circuit" is confusining,
* because it has nothing to do with the SMB notion of a
* "Virtual Circuit".
*/
*** 158,182 ****
zoneid_t vc_zoneid;
uid_t vc_owner; /* Unix owner */
int vc_genid; /* "generation" ID */
! int vc_mackeylen; /* length of MAC key */
! uint8_t *vc_mackey; /* MAC key */
- ksema_t vc_sendlock;
struct smb_tran_desc *vc_tdesc; /* transport ops. vector */
void *vc_tdata; /* transport control block */
kcondvar_t iod_idle; /* IOD thread idle CV */
krwlock_t iod_rqlock; /* iod_rqlist */
! struct smb_rqhead iod_rqlist; /* list of outstanding reqs */
struct _kthread *iod_thr; /* the IOD (reader) thread */
int iod_flags; /* see SMBIOD_* below */
! int iod_newrq; /* send needed (iod_rqlock) */
! int iod_muxfull; /* maxmux limit reached */
/* This is copied in/out when IOD enters/returns */
smbioc_ssn_work_t vc_work;
/* session identity, etc. */
smbioc_ossn_t vc_ssn;
--- 219,258 ----
zoneid_t vc_zoneid;
uid_t vc_owner; /* Unix owner */
int vc_genid; /* "generation" ID */
! int vc_mackeylen; /* MAC key length */
! int vc_ssnkeylen; /* session key length */
! uint8_t *vc_mackey; /* MAC key buffer */
! uint8_t *vc_ssnkey; /* session key buffer */
! smb_sign_mech_t vc_signmech;
struct smb_tran_desc *vc_tdesc; /* transport ops. vector */
void *vc_tdata; /* transport control block */
+ /* SMB2+ fields */
+ uint64_t vc2_oldest_message_id;
+ uint64_t vc2_next_message_id;
+ uint64_t vc2_limit_message_id;
+ uint64_t vc2_session_id; /* session id */
+ uint64_t vc2_prev_session_id; /* for reconnect */
+ uint32_t vc2_lease_key; /* lease key gen */
+
kcondvar_t iod_idle; /* IOD thread idle CV */
krwlock_t iod_rqlock; /* iod_rqlist */
! struct smb_rqhead iod_rqlist; /* list of active reqs */
struct _kthread *iod_thr; /* the IOD (reader) thread */
int iod_flags; /* see SMBIOD_* below */
! uint_t iod_muxcnt; /* num. active requests */
! uint_t iod_muxwant; /* waiting to be active */
! kcondvar_t iod_muxwait;
! boolean_t iod_noresp; /* Logged "not responding" */
+ smb_iods_t vc_iods;
+ smb_sopt_t vc_sopt;
+
/* This is copied in/out when IOD enters/returns */
smbioc_ssn_work_t vc_work;
/* session identity, etc. */
smbioc_ossn_t vc_ssn;
*** 185,222 ****
#define vc_lock vc_co.co_lock
#define vc_flags vc_co.co_flags
/* defines for members in vc_ssn */
#define vc_owner vc_ssn.ssn_owner
#define vc_srvname vc_ssn.ssn_srvname
#define vc_srvaddr vc_ssn.ssn_id.id_srvaddr
#define vc_domain vc_ssn.ssn_id.id_domain
#define vc_username vc_ssn.ssn_id.id_user
- #define vc_vopt vc_ssn.ssn_vopt
/* defines for members in vc_work */
! #define vc_sopt vc_work.wk_sopt
! #define vc_maxmux vc_work.wk_sopt.sv_maxmux
! #define vc_tran_fd vc_work.wk_iods.is_tran_fd
! #define vc_hflags vc_work.wk_iods.is_hflags
! #define vc_hflags2 vc_work.wk_iods.is_hflags2
! #define vc_smbuid vc_work.wk_iods.is_smbuid
! #define vc_next_mid vc_work.wk_iods.is_next_mid
! #define vc_txmax vc_work.wk_iods.is_txmax
! #define vc_rwmax vc_work.wk_iods.is_rwmax
! #define vc_rxmax vc_work.wk_iods.is_rxmax
! #define vc_wxmax vc_work.wk_iods.is_wxmax
! #define vc_ssn_key vc_work.wk_iods.is_ssn_key
! #define vc_next_seq vc_work.wk_iods.is_next_seq
! #define vc_u_mackey vc_work.wk_iods.is_u_mackey
! #define vc_u_maclen vc_work.wk_iods.is_u_maclen
#define SMB_VC_LOCK(vcp) mutex_enter(&(vcp)->vc_lock)
#define SMB_VC_UNLOCK(vcp) mutex_exit(&(vcp)->vc_lock)
! #define SMB_UNICODE_STRINGS(vcp) ((vcp)->vc_hflags2 & SMB_FLAGS2_UNICODE)
/* Bits in iod_flags */
#define SMBIOD_RUNNING 0x0001
#define SMBIOD_SHUTDOWN 0x0002
/*
--- 261,305 ----
#define vc_lock vc_co.co_lock
#define vc_flags vc_co.co_flags
/* defines for members in vc_ssn */
#define vc_owner vc_ssn.ssn_owner
+ #define vc_vopt vc_ssn.ssn_vopt
+ #define vc_minver vc_ssn.ssn_minver
+ #define vc_maxver vc_ssn.ssn_maxver
#define vc_srvname vc_ssn.ssn_srvname
#define vc_srvaddr vc_ssn.ssn_id.id_srvaddr
#define vc_domain vc_ssn.ssn_id.id_domain
#define vc_username vc_ssn.ssn_id.id_user
/* defines for members in vc_work */
! #define vc_cl_guid vc_work.wk_cl_guid
+ /* defines for members in vc_sopt ? */
+ #define vc_maxmux vc_sopt.sv_maxmux
+
+ /* defines for members in vc_iods */
+ #define vc_hflags vc_iods.is_hflags
+ #define vc_hflags2 vc_iods.is_hflags2
+ #define vc_smbuid vc_iods.is_smbuid
+ #define vc_next_mid vc_iods.is_next_mid
+ #define vc_txmax vc_iods.is_txmax
+ #define vc_rwmax vc_iods.is_rwmax
+ #define vc_rxmax vc_iods.is_rxmax
+ #define vc_wxmax vc_iods.is_wxmax
+ #define vc_next_seq vc_iods.is_next_seq
+
#define SMB_VC_LOCK(vcp) mutex_enter(&(vcp)->vc_lock)
#define SMB_VC_UNLOCK(vcp) mutex_exit(&(vcp)->vc_lock)
! #define CPTOVC(cp) ((struct smb_vc *)((void *)(cp)))
! #define VCTOCP(vcp) (&(vcp)->vc_co)
+ #define SMB_UNICODE_STRINGS(vcp) \
+ (((vcp)->vc_flags & SMBV_SMB2) != 0 || \
+ ((vcp)->vc_hflags2 & SMB_FLAGS2_UNICODE) != 0)
+
/* Bits in iod_flags */
#define SMBIOD_RUNNING 0x0001
#define SMBIOD_SHUTDOWN 0x0002
/*
*** 229,238 ****
--- 312,324 ----
kcondvar_t ss_conn_done; /* wait for reconnect */
int ss_conn_waiters;
int ss_vcgenid; /* check VC generation ID */
uint16_t ss_tid; /* TID */
uint16_t ss_options; /* option support bits */
+ uint32_t ss2_tree_id;
+ uint32_t ss2_share_flags;
+ uint32_t ss2_share_caps;
smbioc_oshare_t ss_ioc;
} smb_share_t;
#define ss_lock ss_co.co_lock
#define ss_flags ss_co.co_flags
*** 243,273 ****
#define ss_pass ss_ioc.sh_pass
#define SMB_SS_LOCK(ssp) mutex_enter(&(ssp)->ss_lock)
#define SMB_SS_UNLOCK(ssp) mutex_exit(&(ssp)->ss_lock)
- #define CPTOVC(cp) ((struct smb_vc *)((void *)(cp)))
- #define VCTOCP(vcp) (&(vcp)->vc_co)
-
#define CPTOSS(cp) ((struct smb_share *)((void *)(cp)))
- #define SSTOVC(ssp) CPTOVC(((ssp)->ss_co.co_parent))
#define SSTOCP(ssp) (&(ssp)->ss_co)
/*
* Call-back operations vector, so the netsmb module
* can notify smbfs about events affecting mounts.
* Installed in netsmb after smbfs loads.
*/
typedef struct smb_fscb {
/* Called when the VC has disconnected. */
void (*fscb_disconn)(smb_share_t *);
/* Called when the VC has reconnected. */
void (*fscb_connect)(smb_share_t *);
- /* Called when the server becomes unresponsive. */
- void (*fscb_down)(smb_share_t *);
- /* Called when the server is responding again. */
- void (*fscb_up)(smb_share_t *);
} smb_fscb_t;
/* Install the above vector, or pass NULL to clear it. */
void smb_fscb_set(smb_fscb_t *);
/*
--- 329,379 ----
#define ss_pass ss_ioc.sh_pass
#define SMB_SS_LOCK(ssp) mutex_enter(&(ssp)->ss_lock)
#define SMB_SS_UNLOCK(ssp) mutex_exit(&(ssp)->ss_lock)
#define CPTOSS(cp) ((struct smb_share *)((void *)(cp)))
#define SSTOCP(ssp) (&(ssp)->ss_co)
+ #define SSTOVC(ssp) CPTOVC(((ssp)->ss_co.co_parent))
+ typedef struct smb2fid {
+ uint64_t fid_persistent;
+ uint64_t fid_volatile;
+ } smb2fid_t;
+
/*
+ * smb_fh struct describes an open file handle under some share.
+ */
+ typedef struct smb_fh {
+ struct smb_connobj fh_co; /* keep first! See CPTOSS */
+ int fh_vcgenid; /* check VC generation ID */
+ uint32_t fh_rights; /* granted access */
+ smb2fid_t fh_fid2;
+ uint16_t fh_fid1;
+ } smb_fh_t;
+
+ #define fh_lock fh_co.co_lock
+ #define fh_flags fh_co.co_flags
+
+ #define SMB_FH_LOCK(fhp) mutex_enter(&(fhp)->fh_lock)
+ #define SMB_FH_UNLOCK(fhp) mutex_exit(&(fhp)->fh_lock)
+
+ #define CPTOFH(cp) ((struct smb_fh *)((void *)(cp)))
+ #define FHTOCP(fhp) (&(fhp)->fh_co)
+ #define FHTOSS(fhp) CPTOSS(((fhp)->fh_co.co_parent))
+
+ /*
* Call-back operations vector, so the netsmb module
* can notify smbfs about events affecting mounts.
* Installed in netsmb after smbfs loads.
+ * Note: smbfs only uses the fscb_discon hook.
*/
typedef struct smb_fscb {
/* Called when the VC has disconnected. */
void (*fscb_disconn)(smb_share_t *);
/* Called when the VC has reconnected. */
void (*fscb_connect)(smb_share_t *);
} smb_fscb_t;
/* Install the above vector, or pass NULL to clear it. */
void smb_fscb_set(smb_fscb_t *);
/*
*** 276,293 ****
*/
typedef struct smb_dev {
kmutex_t sd_lock;
struct smb_vc *sd_vc; /* Reference to VC */
struct smb_share *sd_share; /* Reference to share if any */
int sd_level; /* SMBL_VC, ... */
int sd_vcgenid; /* Generation of share or VC */
int sd_poll; /* Future use */
int sd_flags; /* State of connection */
! #define NSMBFL_OPEN 0x0001
! #define NSMBFL_IOD 0x0002
! #define NSMBFL_IOCTL 0x0004
! int sd_smbfid; /* library read/write */
zoneid_t zoneid; /* Zone id */
} smb_dev_t;
extern const uint32_t nsmb_version;
--- 382,399 ----
*/
typedef struct smb_dev {
kmutex_t sd_lock;
struct smb_vc *sd_vc; /* Reference to VC */
struct smb_share *sd_share; /* Reference to share if any */
+ struct smb_fh *sd_fh; /* Reference to FH, if any */
int sd_level; /* SMBL_VC, ... */
int sd_vcgenid; /* Generation of share or VC */
int sd_poll; /* Future use */
int sd_flags; /* State of connection */
! #define NSMBFL_OPEN 0x0001 /* Device minor is open */
! #define NSMBFL_IOD 0x0004 /* Open by IOD */
! #define NSMBFL_IOCTL 0x0010 /* Serialize ioctl calls */
zoneid_t zoneid; /* Zone id */
} smb_dev_t;
extern const uint32_t nsmb_version;
*** 298,307 ****
--- 404,415 ----
/*
* smb_usr.c
*/
+ int smb_usr_ioctl(smb_dev_t *, int, intptr_t, int, cred_t *);
+
int smb_usr_get_flags2(smb_dev_t *sdp, intptr_t arg, int flags);
int smb_usr_get_ssnkey(smb_dev_t *sdp, intptr_t arg, int flags);
int smb_usr_dup_dev(smb_dev_t *sdp, intptr_t arg, int flags);
int smb_usr_simplerq(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr);
*** 317,346 ****
int smb_usr_get_tree(smb_dev_t *, int, intptr_t, int, cred_t *);
int smb_usr_drop_tree(smb_dev_t *sdp, int cmd);
int smb_usr_iod_work(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr);
! int smb_usr_iod_ioctl(smb_dev_t *sdp, int cmd, intptr_t arg, int flags);
/*
* IOD functions
*/
int smb_iod_create(smb_vc_t *vcp);
int smb_iod_destroy(smb_vc_t *vcp);
- int smb_iod_connect(smb_vc_t *vcp);
void smb_iod_disconnect(smb_vc_t *vcp);
! int smb_iod_addrq(struct smb_rq *rqp);
! int smb_iod_multirq(struct smb_rq *rqp);
int smb_iod_waitrq(struct smb_rq *rqp);
void smb_iod_removerq(struct smb_rq *rqp);
void smb_iod_shutdown_share(smb_share_t *ssp);
void smb_iod_sendall(smb_vc_t *);
! int smb_iod_recvall(smb_vc_t *);
! int smb_iod_vc_work(smb_vc_t *, cred_t *);
int smb_iod_vc_idle(smb_vc_t *);
int smb_iod_vc_rcfail(smb_vc_t *);
int smb_iod_reconnect(smb_vc_t *);
/*
--- 425,462 ----
int smb_usr_get_tree(smb_dev_t *, int, intptr_t, int, cred_t *);
int smb_usr_drop_tree(smb_dev_t *sdp, int cmd);
int smb_usr_iod_work(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr);
! int smb_usr_iod_ioctl(smb_dev_t *sdp, int cmd, intptr_t arg, int flags,
! cred_t *cr);
+ int smb_pkey_ioctl(int, intptr_t, int, cred_t *);
+
/*
* IOD functions
*/
int smb_iod_create(smb_vc_t *vcp);
int smb_iod_destroy(smb_vc_t *vcp);
void smb_iod_disconnect(smb_vc_t *vcp);
! int smb2_iod_addrq(struct smb_rq *rqp);
! int smb1_iod_addrq(struct smb_rq *rqp);
! int smb1_iod_multirq(struct smb_rq *rqp);
int smb_iod_waitrq(struct smb_rq *rqp);
+ int smb_iod_waitrq_int(struct smb_rq *rqp);
void smb_iod_removerq(struct smb_rq *rqp);
+ int smb_iod_sendrecv(struct smb_rq *, int);
void smb_iod_shutdown_share(smb_share_t *ssp);
void smb_iod_sendall(smb_vc_t *);
! int smb_iod_recvall(smb_vc_t *, boolean_t);
! int nsmb_iod_connect(smb_vc_t *vcp, cred_t *cr);
! int nsmb_iod_negotiate(smb_vc_t *vcp, cred_t *cr);
! int nsmb_iod_ssnsetup(smb_vc_t *vcp, cred_t *cr);
! int smb_iod_vc_work(smb_vc_t *, int, cred_t *);
int smb_iod_vc_idle(smb_vc_t *);
int smb_iod_vc_rcfail(smb_vc_t *);
int smb_iod_reconnect(smb_vc_t *);
/*
*** 379,384 ****
--- 495,509 ----
void smb_share_kill(smb_share_t *ssp);
void smb_share_invalidate(smb_share_t *ssp);
int smb_share_tcon(smb_share_t *, smb_cred_t *);
+ /*
+ * File handle level functions
+ */
+ int smb_fh_create(smb_share_t *ssp, struct smb_fh **fhpp);
+ void smb_fh_opened(struct smb_fh *fhp);
+ void smb_fh_close(struct smb_fh *fhp);
+ void smb_fh_hold(struct smb_fh *fhp);
+ void smb_fh_rele(struct smb_fh *fhp);
+
#endif /* _SMB_CONN_H */