smbd: Remove sconn->using_smb2
[samba.git] / source3 / smbd / conn_idle.c
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
7
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.
12
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.
17
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/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "rpc_server/rpc_pipes.h"
26 #include "lib/util/tevent_ntstatus.h"
27
28 /****************************************************************************
29  Update last used timestamps.
30 ****************************************************************************/
31
32 static void conn_lastused_update(struct smbd_server_connection *sconn,time_t t)
33 {
34         struct connection_struct *conn;
35
36         for (conn=sconn->connections; conn; conn=conn->next) {
37                 /* Update if connection wasn't idle. */
38                 if (conn->lastused != conn->lastused_count) {
39                         conn->lastused = t;
40                         conn->lastused_count = t;
41                 }
42         }
43 }
44
45 /****************************************************************************
46  Idle inactive connections.
47 ****************************************************************************/
48
49 bool conn_idle_all(struct smbd_server_connection *sconn, time_t t)
50 {
51         int deadtime = lp_deadtime()*60;
52         struct connection_struct *conn;
53
54         conn_lastused_update(sconn, t);
55
56         if (deadtime <= 0) {
57                 return false;
58         }
59
60         for (conn=sconn->connections;conn;conn=conn->next) {
61                 time_t age = t - conn->lastused;
62
63                 if (conn->num_files_open > 0 || age < deadtime) {
64                         return false;
65                 }
66         }
67
68         return true;
69 }
70
71 /****************************************************************************
72  Forcibly unmount a share - async
73  All instances of the parameter 'sharename' share are unmounted.
74  The special sharename '*' forces unmount of all shares.
75 ****************************************************************************/
76
77 static struct tevent_req *conn_force_tdis_send(connection_struct *conn);
78 static void conn_force_tdis_done(struct tevent_req *req);
79
80 void conn_force_tdis(
81         struct smbd_server_connection *sconn,
82         bool (*check_fn)(struct connection_struct *conn,
83                          void *private_data),
84         void *private_data)
85 {
86         connection_struct *conn;
87
88         /* SMB1 and SMB 2*/
89         for (conn = sconn->connections; conn; conn = conn->next) {
90                 struct smbXsrv_tcon *tcon;
91                 bool do_close = false;
92                 struct tevent_req *req;
93
94                 if (conn->tcon == NULL) {
95                         continue;
96                 }
97                 tcon = conn->tcon;
98
99                 if (!NT_STATUS_IS_OK(tcon->status)) {
100                         /* In the process of already being disconnected. */
101                         continue;
102                 }
103
104                 do_close = check_fn(conn, private_data);
105                 if (!do_close) {
106                         continue;
107                 }
108
109                 req = conn_force_tdis_send(conn);
110                 if (req == NULL) {
111                         DBG_WARNING("talloc_fail forcing async close of "
112                                 "share '%s'\n",
113                                 tcon->global->share_name);
114                         continue;
115                 }
116
117                 DBG_WARNING("Forcing close of "
118                             "share '%s' (wire_id=0x%08x)\n",
119                             tcon->global->share_name,
120                             tcon->global->tcon_wire_id);
121
122                 tevent_req_set_callback(req, conn_force_tdis_done, conn);
123         }
124 }
125
126 struct conn_force_tdis_state {
127         struct tevent_queue *wait_queue;
128 };
129
130 static void conn_force_tdis_wait_done(struct tevent_req *subreq);
131
132 static struct tevent_req *conn_force_tdis_send(connection_struct *conn)
133 {
134         struct tevent_req *req;
135         struct conn_force_tdis_state *state;
136         struct tevent_req *subreq;
137         files_struct *fsp;
138
139         /* Create this off the NULL context. We must clean up on return. */
140         req = tevent_req_create(NULL, &state,
141                         struct conn_force_tdis_state);
142         if (req == NULL) {
143                 return NULL;
144         }
145         state->wait_queue = tevent_queue_create(state,
146                         "conn_force_tdis_wait_queue");
147         if (tevent_req_nomem(state->wait_queue, req)) {
148                 TALLOC_FREE(req);
149                 return NULL;
150         }
151
152         /*
153          * Make sure that no new request will be able to use this tcon.
154          * This ensures that once all outstanding fsp->aio_requests
155          * on this tcon are done, we are safe to close it.
156          */
157         conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
158
159         for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
160                 if (fsp->conn != conn) {
161                         continue;
162                 }
163                 /*
164                  * Flag the file as close in progress.
165                  * This will prevent any more IO being
166                  * done on it. Not strictly needed, but
167                  * doesn't hurt to flag it as closing.
168                  */
169                 fsp->fsp_flags.closing = true;
170
171                 if (fsp->num_aio_requests > 0) {
172                         /*
173                          * Now wait until all aio requests on this fsp are
174                          * finished.
175                          *
176                          * We don't set a callback, as we just want to block the
177                          * wait queue and the talloc_free() of fsp->aio_request
178                          * will remove the item from the wait queue.
179                          */
180                         subreq = tevent_queue_wait_send(fsp->aio_requests,
181                                                 conn->sconn->ev_ctx,
182                                                 state->wait_queue);
183                         if (tevent_req_nomem(subreq, req)) {
184                                 TALLOC_FREE(req);
185                                 return NULL;
186                         }
187                 }
188         }
189         /*
190          * Now we add our own waiter to the end of the queue,
191          * this way we get notified when all pending requests are finished
192          * and reply to the outstanding SMB1 request.
193          */
194         subreq = tevent_queue_wait_send(state,
195                                 conn->sconn->ev_ctx,
196                                 state->wait_queue);
197         if (tevent_req_nomem(subreq, req)) {
198                 TALLOC_FREE(req);
199                 return NULL;
200         }
201
202         tevent_req_set_callback(subreq, conn_force_tdis_wait_done, req);
203         return req;
204 }
205
206 static void conn_force_tdis_wait_done(struct tevent_req *subreq)
207 {
208         struct tevent_req *req = tevent_req_callback_data(
209                 subreq, struct tevent_req);
210
211         tevent_queue_wait_recv(subreq);
212         TALLOC_FREE(subreq);
213         tevent_req_done(req);
214 }
215
216 static NTSTATUS conn_force_tdis_recv(struct tevent_req *req)
217 {
218         return tevent_req_simple_recv_ntstatus(req);
219 }
220
221 static void conn_force_tdis_done(struct tevent_req *req)
222 {
223         connection_struct *conn = tevent_req_callback_data(
224                 req, connection_struct);
225         NTSTATUS status;
226         uint64_t vuid = UID_FIELD_INVALID;
227         struct smbXsrv_tcon *tcon = conn->tcon;
228         struct smbd_server_connection *sconn = conn->sconn;
229
230         status = conn_force_tdis_recv(req);
231         TALLOC_FREE(req);
232         if (!NT_STATUS_IS_OK(status)) {
233                 DBG_ERR("conn_force_tdis_recv of share '%s' "
234                         "(wire_id=0x%08x) failed: %s\n",
235                         tcon->global->share_name,
236                         tcon->global->tcon_wire_id,
237                         nt_errstr(status));
238                 return;
239         }
240
241         if (conn_using_smb2(conn->sconn)) {
242                 vuid = conn->vuid;
243         }
244
245         DBG_WARNING("Closing "
246                     "share '%s' (wire_id=0x%08x)\n",
247                     tcon->global->share_name,
248                     tcon->global->tcon_wire_id);
249
250         conn = NULL;
251         status = smbXsrv_tcon_disconnect(tcon, vuid);
252         if (!NT_STATUS_IS_OK(status)) {
253                 DBG_ERR("smbXsrv_tcon_disconnect() of share '%s' "
254                         "(wire_id=0x%08x) failed: %s\n",
255                         tcon->global->share_name,
256                         tcon->global->tcon_wire_id,
257                         nt_errstr(status));
258                 return;
259         }
260
261         TALLOC_FREE(tcon);
262
263         /*
264         * As we've been awoken, we may have changed
265         * uid in the meantime. Ensure we're still root.
266         */
267         change_to_root_user();
268         /*
269          * Use 'false' in the last parameter (test) to force
270          * a full reload of services. Prevents
271          * reload_services caching the fact it's
272          * been called multiple times in a row.
273          * See BUG: https://bugzilla.samba.org/show_bug.cgi?id=14604
274          * for details.
275          */
276         reload_services(sconn, conn_snum_used, false);
277 }