r12102: for SMB2 we need to allocate tcons per session
authorStefan Metzmacher <metze@samba.org>
Tue, 6 Dec 2005 17:59:20 +0000 (17:59 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:47:09 +0000 (13:47 -0500)
metze
(This used to be commit 4d527ac005086c2db954578b4126ca128e436e01)

source4/smb_server/management.c
source4/smb_server/smb/receive.c
source4/smb_server/smb/reply.c
source4/smb_server/smb/service.c
source4/smb_server/smb2/receive.c
source4/smb_server/smb2/sesssetup.c
source4/smb_server/smb2/tcon.c
source4/smb_server/smb_server.h
source4/smb_server/tcon.c

index d158947ba45510e878da06c202d07813ce723545..19e20906826f6bd26981c2f274b178b5c1a6110e 100644 (file)
@@ -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);
index b77a166b9d56fc4fcbae2cd0a0f437c6a54bf55a..806244ee12e46c7493ddbd36bb407dd503d6a4b3 100644 (file)
@@ -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);
index eb7b5a108248cfc102d2d0a089f28376384deda8..d780cb1a7534b82abfb1fcc73692201548994c0c 100644 (file)
@@ -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;
index 213cf6726bd4d5bff1898af2181ecc138ec3befc..6032e5a20d2eb300c6bab60018548c9f8f2f277f 100644 (file)
@@ -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;
index 66ebe162cf0964ba3278114ebad66eaedbcf6ddd..310ded53557ddd82219a98b4a77b018967ffb7e5 100644 (file)
@@ -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;
        
 }
index 7915590464330919602d88d20ac8141ab4ae186c..288671ddd378ead3f6006414c94697e4b985ba8f 100644 (file)
@@ -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);
index fb84aa6fdc91e51d71ecdcb9de97682a20054f25..9fb2a03ce33363f1da25956c58dda6ce246c2197 100644 (file)
@@ -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 */
index f879845134e2ce07d9648dc501adc1d0ea487c9d..6a7338348000f09c765040ce3ee018958d01176e 100644 (file)
   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
index 6714b61e90f428af97ff6570ca0f11548fe2ca58..0cb6738d31f669c818d470fa0152cb7563aa266a 100644 (file)
@@ -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);
+}