s3/smbd: If we fail to close file_handle ensure we should reset the fd
[Samba.git] / source3 / smbd / conn.c
blob27a4d27c695b157a3ab9dfc9b11a8195f1284dad
1 /*
2 Unix SMB/CIFS implementation.
3 Manage connections_struct structures
4 Copyright (C) Andrew Tridgell 1998
5 Copyright (C) Alexander Bokovoy 2002
6 Copyright (C) Jeremy Allison 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "lib/util/bitmap.h"
27 static void conn_free_internal(connection_struct *conn);
29 /****************************************************************************
30 * Remove a conn struct from conn->sconn->connections
31 * if not already done.
32 ****************************************************************************/
34 static int conn_struct_destructor(connection_struct *conn)
36 if (conn->sconn != NULL) {
37 DLIST_REMOVE(conn->sconn->connections, conn);
38 SMB_ASSERT(conn->sconn->num_connections > 0);
39 conn->sconn->num_connections--;
40 conn->sconn = NULL;
42 conn_free_internal(conn);
43 return 0;
46 /****************************************************************************
47 Return the number of open connections.
48 ****************************************************************************/
50 int conn_num_open(struct smbd_server_connection *sconn)
52 return sconn->num_connections;
55 /****************************************************************************
56 Check if a snum is in use.
57 ****************************************************************************/
59 bool conn_snum_used(struct smbd_server_connection *sconn,
60 int snum)
62 struct connection_struct *conn;
64 for (conn=sconn->connections; conn; conn=conn->next) {
65 if (conn->params->service == snum) {
66 return true;
70 return false;
73 /****************************************************************************
74 Find first available connection slot, starting from a random position.
75 The randomisation stops problems with the server dying and clients
76 thinking the server is still available.
77 ****************************************************************************/
79 connection_struct *conn_new(struct smbd_server_connection *sconn)
81 connection_struct *conn = NULL;
83 conn = talloc_zero(NULL, connection_struct);
84 if (conn == NULL) {
85 DBG_ERR("talloc_zero failed\n");
86 return NULL;
88 conn->params = talloc(conn, struct share_params);
89 if (conn->params == NULL) {
90 DBG_ERR("talloc_zero failed\n");
91 TALLOC_FREE(conn);
92 return NULL;
94 conn->vuid_cache = talloc_zero(conn, struct vuid_cache);
95 if (conn->vuid_cache == NULL) {
96 DBG_ERR("talloc_zero failed\n");
97 TALLOC_FREE(conn);
98 return NULL;
100 conn->connectpath = talloc_strdup(conn, "");
101 if (conn->connectpath == NULL) {
102 DBG_ERR("talloc_zero failed\n");
103 TALLOC_FREE(conn);
104 return NULL;
106 conn->cwd_fsp = talloc_zero(conn, struct files_struct);
107 if (conn->cwd_fsp == NULL) {
108 DBG_ERR("talloc_zero failed\n");
109 TALLOC_FREE(conn);
110 return NULL;
112 conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn->cwd_fsp,
113 ".",
114 NULL,
115 NULL,
118 if (conn->cwd_fsp->fsp_name == NULL) {
119 TALLOC_FREE(conn);
120 return NULL;
122 conn->cwd_fsp->fh = fd_handle_create(conn->cwd_fsp);
123 if (conn->cwd_fsp->fh == NULL) {
124 DBG_ERR("talloc_zero failed\n");
125 TALLOC_FREE(conn);
126 return NULL;
128 conn->sconn = sconn;
129 conn->force_group_gid = (gid_t)-1;
130 fsp_set_fd(conn->cwd_fsp, -1);
131 conn->cwd_fsp->fnum = FNUM_FIELD_INVALID;
132 conn->cwd_fsp->conn = conn;
134 DLIST_ADD(sconn->connections, conn);
135 sconn->num_connections++;
138 * Catches the case where someone forgets to call
139 * conn_free().
141 talloc_set_destructor(conn, conn_struct_destructor);
142 return conn;
145 /****************************************************************************
146 Clear a vuid out of the connection's vuid cache
147 ****************************************************************************/
149 static void conn_clear_vuid_cache(connection_struct *conn, uint64_t vuid)
151 int i;
153 for (i=0; i<VUID_CACHE_SIZE; i++) {
154 struct vuid_cache_entry *ent;
156 ent = &conn->vuid_cache->array[i];
158 if (ent->vuid == vuid) {
159 ent->vuid = UID_FIELD_INVALID;
161 * We need to keep conn->session_info around
162 * if it's equal to ent->session_info as a SMBulogoff
163 * is often followed by a SMBtdis (with an invalid
164 * vuid). The debug code (or regular code in
165 * vfs_full_audit) wants to refer to the
166 * conn->session_info pointer to print debug
167 * statements. Theoretically this is a bug,
168 * as once the vuid is gone the session_info
169 * on the conn struct isn't valid any more,
170 * but there's enough code that assumes
171 * conn->session_info is never null that
172 * it's easier to hold onto the old pointer
173 * until we get a new sessionsetupX.
174 * As everything is hung off the
175 * conn pointer as a talloc context we're not
176 * leaking memory here. See bug #6315. JRA.
178 if (conn->session_info == ent->session_info) {
179 ent->session_info = NULL;
180 } else {
181 TALLOC_FREE(ent->session_info);
183 ent->read_only = False;
184 ent->share_access = 0;
189 /****************************************************************************
190 Clear a vuid out of the validity cache, and as the 'owner' of a connection.
192 Called from invalidate_vuid()
193 ****************************************************************************/
195 void conn_clear_vuid_caches(struct smbd_server_connection *sconn, uint64_t vuid)
197 connection_struct *conn;
199 for (conn=sconn->connections; conn;conn=conn->next) {
200 if (conn->vuid == vuid) {
201 conn->vuid = UID_FIELD_INVALID;
203 conn_clear_vuid_cache(conn, vuid);
207 /****************************************************************************
208 Free a conn structure - internal part.
209 ****************************************************************************/
211 static void conn_free_internal(connection_struct *conn)
213 vfs_handle_struct *handle = NULL, *thandle = NULL;
214 struct trans_state *state = NULL;
216 /* Free vfs_connection_struct */
217 handle = conn->vfs_handles;
218 while(handle) {
219 thandle = handle->next;
220 DLIST_REMOVE(conn->vfs_handles, handle);
221 if (handle->free_data)
222 handle->free_data(&handle->data);
223 handle = thandle;
226 /* Free any pending transactions stored on this conn. */
227 for (state = conn->pending_trans; state; state = state->next) {
228 /* state->setup is a talloc child of state. */
229 SAFE_FREE(state->param);
230 SAFE_FREE(state->data);
233 free_namearray(conn->veto_list);
234 free_namearray(conn->hide_list);
235 free_namearray(conn->veto_oplock_list);
236 free_namearray(conn->aio_write_behind_list);
238 ZERO_STRUCTP(conn);
241 /****************************************************************************
242 Free a conn structure.
243 ****************************************************************************/
245 void conn_free(connection_struct *conn)
247 TALLOC_FREE(conn);
251 * Correctly initialize a share with case options.
253 void conn_setup_case_options(connection_struct *conn)
255 int snum = conn->params->service;
257 if (lp_case_sensitive(snum) == Auto) {
258 /* We will be setting this per packet. Set to be case
259 * insensitive for now. */
260 conn->case_sensitive = false;
261 } else {
262 conn->case_sensitive = (bool)lp_case_sensitive(snum);
265 conn->case_preserve = lp_preserve_case(snum);
266 conn->short_case_preserve = lp_short_preserve_case(snum);