From 273f340376452bd072b68d0601dde3f7b43b62db Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Dec 2005 17:59:20 +0000 Subject: r12102: for SMB2 we need to allocate tcons per session metze (This used to be commit 4d527ac005086c2db954578b4126ca128e436e01) --- source4/smb_server/management.c | 4 +- source4/smb_server/smb/receive.c | 4 +- source4/smb_server/smb/reply.c | 4 +- source4/smb_server/smb/service.c | 2 +- source4/smb_server/smb2/receive.c | 5 +-- source4/smb_server/smb2/sesssetup.c | 5 +++ source4/smb_server/smb2/tcon.c | 2 +- source4/smb_server/smb_server.h | 58 +++++++++++++++---------- source4/smb_server/tcon.c | 85 +++++++++++++++++++++++++++++-------- 9 files changed, 116 insertions(+), 53 deletions(-) (limited to 'source4') diff --git a/source4/smb_server/management.c b/source4/smb_server/management.c index d158947ba4..19e2090682 100644 --- a/source4/smb_server/management.c +++ b/source4/smb_server/management.c @@ -71,7 +71,7 @@ static NTSTATUS smbsrv_tcon_information(struct irpc_message *msg, 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++; } @@ -79,7 +79,7 @@ static NTSTATUS smbsrv_tcon_information(struct irpc_message *msg, 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); diff --git a/source4/smb_server/smb/receive.c b/source4/smb_server/smb/receive.c index b77a166b9d..806244ee12 100644 --- a/source4/smb_server/smb/receive.c +++ b/source4/smb_server/smb/receive.c @@ -470,7 +470,7 @@ static void switch_message(int type, struct smbsrv_request *req) 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 @@ -645,7 +645,7 @@ NTSTATUS smbsrv_init_smb_connection(struct smbsrv_connection *smb_conn) 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); diff --git a/source4/smb_server/smb/reply.c b/source4/smb_server/smb/reply.c index eb7b5a1082..d780cb1a75 100644 --- a/source4/smb_server/smb/reply.c +++ b/source4/smb_server/smb/reply.c @@ -1200,7 +1200,7 @@ void reply_exit(struct smbsrv_request *req) 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; @@ -2181,7 +2181,7 @@ void reply_ulogoffX(struct smbsrv_request *req) /* 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; diff --git a/source4/smb_server/smb/service.c b/source4/smb_server/smb/service.c index 213cf6726b..6032e5a20d 100644 --- a/source4/smb_server/smb/service.c +++ b/source4/smb_server/smb/service.c @@ -66,7 +66,7 @@ static NTSTATUS make_connection_snum(struct smbsrv_request *req, 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; diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 66ebe162cf..310ded5355 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -129,7 +129,7 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) 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; @@ -322,9 +322,6 @@ NTSTATUS smbsrv_init_smb2_connection(struct smbsrv_connection *smb_conn) 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; } diff --git a/source4/smb_server/smb2/sesssetup.c b/source4/smb_server/smb2/sesssetup.c index 7915590464..288671ddd3 100644 --- a/source4/smb_server/smb2/sesssetup.c +++ b/source4/smb_server/smb2/sesssetup.c @@ -67,6 +67,11 @@ static NTSTATUS smb2srv_sesssetup_backend(struct smb2srv_request *req, struct sm /* 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); diff --git a/source4/smb_server/smb2/tcon.c b/source4/smb_server/smb2/tcon.c index fb84aa6fdc..9fb2a03ce3 100644 --- a/source4/smb_server/smb2/tcon.c +++ b/source4/smb_server/smb2/tcon.c @@ -28,7 +28,7 @@ static NTSTATUS smb2srv_tcon_backend(struct smb2srv_request *req, struct smb2_tr { 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 */ diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h index f879845134..6a73383480 100644 --- a/source4/smb_server/smb_server.h +++ b/source4/smb_server/smb_server.h @@ -32,12 +32,39 @@ 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 @@ -94,6 +121,12 @@ struct smbsrv_tcon { 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; @@ -232,31 +265,10 @@ struct smbsrv_connection { } 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 diff --git a/source4/smb_server/tcon.c b/source4/smb_server/tcon.c index 6714b61e90..0cb6738d31 100644 --- a/source4/smb_server/tcon.c +++ b/source4/smb_server/tcon.c @@ -29,7 +29,7 @@ /**************************************************************************** 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, @@ -37,27 +37,37 @@ NTSTATUS smbsrv_init_tcons(struct smbsrv_connection *smb_conn, uint32_t 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); @@ -65,12 +75,24 @@ struct smbsrv_tcon *smbsrv_tcon_find(struct smbsrv_connection *smb_conn, uint32_ 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), @@ -81,31 +103,48 @@ static int smbsrv_tcon_destructor(void *ptr) 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 */ @@ -113,3 +152,13 @@ struct smbsrv_tcon *smbsrv_tcon_new(struct smbsrv_connection *smb_conn) 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); +} -- cgit