struct smbsrv_tcon *tcon;
/* count the number of tcons */
- for (tcon=smb_conn->tcons.list; tcon; tcon=tcon->next) {
+ for (tcon=smb_conn->smb_tcons.list; tcon; tcon=tcon->next) {
count++;
}
r->out.info.tcons.tcons = talloc_array(r, struct smbsrv_tcon_info, count);
NT_STATUS_HAVE_NO_MEMORY(r->out.info.tcons.tcons);
- for (tcon=smb_conn->tcons.list; tcon; tcon=tcon->next) {
+ for (tcon=smb_conn->smb_tcons.list; tcon; tcon=tcon->next) {
struct smbsrv_tcon_info *info = &r->out.info.tcons.tcons[i];
info->tid = tcon->tid;
info->share_name = lp_servicename(tcon->service);
flags = smb_messages[type].flags;
- req->tcon = smbsrv_tcon_find(smb_conn, SVAL(req->in.hdr,HDR_TID));
+ req->tcon = smbsrv_smb_tcon_find(smb_conn, SVAL(req->in.hdr,HDR_TID));
if (!req->session) {
/* setup the user context for this request if it
status = smbsrv_init_sessions(smb_conn, UINT16_MAX);
NT_STATUS_NOT_OK_RETURN(status);
- status = smbsrv_init_tcons(smb_conn, UINT16_MAX);
+ status = smbsrv_smb_init_tcons(smb_conn);
NT_STATUS_NOT_OK_RETURN(status);
srv_init_signing(smb_conn);
struct smbsrv_tcon *tcon;
REQ_CHECK_WCT(req, 0);
- for (tcon=req->smb_conn->tcons.list;tcon;tcon=tcon->next) {
+ for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
req->tcon = tcon;
status = ntvfs_exit(req);
req->tcon = NULL;
/* in user level security we are supposed to close any files
open by this user on all open tree connects */
- for (tcon=req->smb_conn->tcons.list;tcon;tcon=tcon->next) {
+ for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
req->tcon = tcon;
status = ntvfs_logoff(req);
req->tcon = NULL;
return NT_STATUS_ACCESS_DENIED;
}
- tcon = smbsrv_tcon_new(req->smb_conn);
+ tcon = smbsrv_smb_tcon_new(req->smb_conn);
if (!tcon) {
DEBUG(0,("Couldn't find free connection.\n"));
return NT_STATUS_INSUFFICIENT_RESOURCES;
uid = BVAL(req->in.hdr, SMB2_HDR_UID);
req->session = smbsrv_session_find(req->smb_conn, uid);
- req->tcon = smbsrv_tcon_find(req->smb_conn, tid);
+ req->tcon = smbsrv_smb2_tcon_find(req->session, tid);
errno = 0;
status = smbsrv_init_sessions(smb_conn, UINT64_MAX);
NT_STATUS_NOT_OK_RETURN(status);
- status = smbsrv_init_tcons(smb_conn, UINT32_MAX);
- NT_STATUS_NOT_OK_RETURN(status);
-
return NT_STATUS_OK;
}
/* allocate a new session */
smb_sess = smbsrv_session_new(req->smb_conn, gensec_ctx);
+ status = smbsrv_smb2_init_tcons(smb_sess);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(smb_sess);
+ smb_sess = NULL;
+ }
} else {
/* lookup an existing session */
smb_sess = smbsrv_session_find_sesssetup(req->smb_conn, vuid);
{
struct smbsrv_tcon *tcon;
- tcon = smbsrv_tcon_new(req->smb_conn);
+ tcon = smbsrv_smb2_tcon_new(req->session);
NT_STATUS_HAVE_NO_MEMORY(tcon);
/* TODO: do real tree connect */
these basic elements
*/
+struct smbsrv_tcons_context {
+ /* an id tree used to allocate tids */
+ struct idr_context *idtree_tid;
+
+ /* this is the limit of vuid values for this connection */
+ uint32_t idtree_limit;
+
+ /* list of open tree connects */
+ struct smbsrv_tcon *list;
+};
+
+struct smbsrv_sessions_context {
+ /* an id tree used to allocate vuids */
+ /* this holds info on session vuids that are already
+ * validated for this VC */
+ struct idr_context *idtree_vuid;
+
+ /* this is the limit of vuid values for this connection */
+ uint64_t idtree_limit;
+
+ /* also kept as a link list so it can be enumerated by
+ the management code */
+ struct smbsrv_session *list;
+} sessions;
+
/* the current user context for a request */
struct smbsrv_session {
struct smbsrv_session *prev, *next;
struct smbsrv_connection *smb_conn;
+ struct smbsrv_tcons_context smb2_tcons;
+
/*
* an index passed over the wire:
* - 16 bit for smb
struct smbsrv_session *session;
} sec_share;
+ /* some stuff to support share level security */
+ struct {
+ /* in SMB2 a tcon always belongs to one session */
+ struct smbsrv_session *session;
+ } smb2;
+
/* some statictics for the management tools */
struct {
struct timeval connect_time;
} negotiate;
/* the context associated with open tree connects on a smb socket */
- struct {
- /* an id tree used to allocate tids */
- struct idr_context *idtree_tid;
-
- /* this is the limit of vuid values for this connection */
- uint32_t idtree_limit;
-
- /* list of open tree connects */
- struct smbsrv_tcon *list;
- } tcons;
+ struct smbsrv_tcons_context smb_tcons;
/* context associated with currently valid session setups */
- struct {
- /* an id tree used to allocate vuids */
- /* this holds info on session vuids that are already
- * validated for this VC */
- struct idr_context *idtree_vuid;
-
- /* this is the limit of vuid values for this connection */
- uint64_t idtree_limit;
-
- /* also kept as a link list so it can be enumerated by
- the management code */
- struct smbsrv_session *list;
- } sessions;
+ struct smbsrv_sessions_context sessions;
/* the server_context holds a linked list of pending requests,
* this is used for blocking locks and requests blocked due to oplock
/****************************************************************************
init the tcon structures
****************************************************************************/
-NTSTATUS smbsrv_init_tcons(struct smbsrv_connection *smb_conn, uint32_t limit)
+static NTSTATUS smbsrv_init_tcons(struct smbsrv_tcons_context *tcons_ctx, TALLOC_CTX *mem_ctx, uint32_t limit)
{
/*
* the idr_* functions take 'int' as limit,
*/
limit &= 0x00FFFFFF;
- smb_conn->tcons.idtree_tid = idr_init(smb_conn);
- NT_STATUS_HAVE_NO_MEMORY(smb_conn->tcons.idtree_tid);
- smb_conn->tcons.idtree_limit = limit;
- smb_conn->tcons.list = NULL;
+ tcons_ctx->idtree_tid = idr_init(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tcons_ctx->idtree_tid);
+ tcons_ctx->idtree_limit = limit;
+ tcons_ctx->list = NULL;
return NT_STATUS_OK;
}
+NTSTATUS smbsrv_smb_init_tcons(struct smbsrv_connection *smb_conn)
+{
+ return smbsrv_init_tcons(&smb_conn->smb_tcons, smb_conn, UINT16_MAX);
+}
+
+NTSTATUS smbsrv_smb2_init_tcons(struct smbsrv_session *smb_sess)
+{
+ return smbsrv_init_tcons(&smb_sess->smb2_tcons, smb_sess, UINT32_MAX);
+}
+
/****************************************************************************
-find a tcon given a cnum
+find a tcon given a tid for SMB
****************************************************************************/
-struct smbsrv_tcon *smbsrv_tcon_find(struct smbsrv_connection *smb_conn, uint32_t tid)
+static struct smbsrv_tcon *smbsrv_tcon_find(struct smbsrv_tcons_context *tcons_ctx, uint32_t tid)
{
void *p;
struct smbsrv_tcon *tcon;
if (tid == 0) return NULL;
- if (tid > smb_conn->tcons.idtree_limit) return NULL;
+ if (tid > tcons_ctx->idtree_limit) return NULL;
- p = idr_find(smb_conn->tcons.idtree_tid, tid);
+ p = idr_find(tcons_ctx->idtree_tid, tid);
if (!p) return NULL;
tcon = talloc_get_type(p, struct smbsrv_tcon);
return tcon;
}
+struct smbsrv_tcon *smbsrv_smb_tcon_find(struct smbsrv_connection *smb_conn, uint32_t tid)
+{
+ return smbsrv_tcon_find(&smb_conn->smb_tcons, tid);
+}
+
+struct smbsrv_tcon *smbsrv_smb2_tcon_find(struct smbsrv_session *smb_sess, uint32_t tid)
+{
+ if (!smb_sess) return NULL;
+ return smbsrv_tcon_find(&smb_sess->smb2_tcons, tid);
+}
+
/*
destroy a connection structure
*/
static int smbsrv_tcon_destructor(void *ptr)
{
- struct smbsrv_tcon *tcon = ptr;
+ struct smbsrv_tcon *tcon = talloc_get_type(ptr, struct smbsrv_tcon);
+ struct smbsrv_tcons_context *tcons_ctx;
DEBUG(3,("%s closed connection to service %s\n",
socket_get_peer_addr(tcon->smb_conn->connection->socket, tcon),
ntvfs_disconnect(tcon);
}
- idr_remove(tcon->smb_conn->tcons.idtree_tid, tcon->tid);
- DLIST_REMOVE(tcon->smb_conn->tcons.list, tcon);
+ if (tcon->smb2.session) {
+ tcons_ctx = &tcon->smb2.session->smb2_tcons;
+ } else {
+ tcons_ctx = &tcon->smb_conn->smb_tcons;
+ }
+
+ idr_remove(tcons_ctx->idtree_tid, tcon->tid);
+ DLIST_REMOVE(tcons_ctx->list, tcon);
return 0;
}
/*
find first available connection slot
*/
-struct smbsrv_tcon *smbsrv_tcon_new(struct smbsrv_connection *smb_conn)
+static struct smbsrv_tcon *smbsrv_tcon_new(struct smbsrv_connection *smb_conn, struct smbsrv_session *smb_sess)
{
+ TALLOC_CTX *mem_ctx;
+ struct smbsrv_tcons_context *tcons_ctx;
struct smbsrv_tcon *tcon;
int i;
- tcon = talloc_zero(smb_conn, struct smbsrv_tcon);
+ if (smb_sess) {
+ mem_ctx = smb_sess;
+ tcons_ctx = &smb_sess->smb2_tcons;
+ } else {
+ mem_ctx = smb_conn;
+ tcons_ctx = &smb_conn->smb_tcons;
+ }
+
+ tcon = talloc_zero(mem_ctx, struct smbsrv_tcon);
if (!tcon) return NULL;
- tcon->smb_conn = smb_conn;
+ tcon->smb_conn = smb_conn;
+ tcon->smb2.session = smb_sess;
- i = idr_get_new_random(smb_conn->tcons.idtree_tid, tcon, smb_conn->tcons.idtree_limit);
+ i = idr_get_new_random(tcons_ctx->idtree_tid, tcon, tcons_ctx->idtree_limit);
if (i == -1) {
- DEBUG(1,("ERROR! Out of connection structures\n"));
+ DEBUG(1,("ERROR! Out of connection structures\n"));
return NULL;
}
tcon->tid = i;
- DLIST_ADD(smb_conn->tcons.list, tcon);
+ DLIST_ADD(tcons_ctx->list, tcon);
talloc_set_destructor(tcon, smbsrv_tcon_destructor);
/* now fill in some statistics */
return tcon;
}
+
+struct smbsrv_tcon *smbsrv_smb_tcon_new(struct smbsrv_connection *smb_conn)
+{
+ return smbsrv_tcon_new(smb_conn, NULL);
+}
+
+struct smbsrv_tcon *smbsrv_smb2_tcon_new(struct smbsrv_session *smb_sess)
+{
+ return smbsrv_tcon_new(smb_sess->smb_conn, smb_sess);
+}