s3:smbd: call file_close_user() before removing tree connects in conn_close_all()
[ambi/samba-autobuild/.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
27 /****************************************************************************
28  Update last used timestamps.
29 ****************************************************************************/
30
31 static void conn_lastused_update(struct smbd_server_connection *sconn,time_t t)
32 {
33         struct connection_struct *conn;
34
35         for (conn=sconn->connections; conn; conn=conn->next) {
36                 /* Update if connection wasn't idle. */
37                 if (conn->lastused != conn->lastused_count) {
38                         conn->lastused = t;
39                         conn->lastused_count = t;
40                 }
41         }
42 }
43
44 /****************************************************************************
45  Idle inactive connections.
46 ****************************************************************************/
47
48 bool conn_idle_all(struct smbd_server_connection *sconn, time_t t)
49 {
50         int deadtime = lp_deadtime()*60;
51         struct connection_struct *conn;
52
53         conn_lastused_update(sconn, t);
54
55         if (deadtime <= 0) {
56                 deadtime = DEFAULT_SMBD_TIMEOUT;
57         }
58
59         for (conn=sconn->connections;conn;conn=conn->next) {
60                 time_t age = t - conn->lastused;
61
62                 /* close dirptrs on connections that are idle */
63                 if (age > DPTR_IDLE_TIMEOUT) {
64                         dptr_idlecnum(conn);
65                 }
66
67                 if (conn->num_files_open > 0 || age < deadtime) {
68                         return false;
69                 }
70         }
71
72         /*
73          * Check all pipes for any open handles. We cannot
74          * idle with a handle open.
75          */
76         if (check_open_pipes()) {
77                 return false;
78         }
79
80         return true;
81 }
82
83 /****************************************************************************
84  Close all conn structures.
85  Return true if any were closed.
86 ****************************************************************************/
87
88 bool conn_close_all(struct smbd_server_connection *sconn)
89 {
90         bool ret = false;
91
92         if (sconn->using_smb2) {
93                 /* SMB2 */
94                 struct smbd_smb2_session *sess;
95
96                 for (sess = sconn->smb2.sessions.list; sess; sess = sess->next) {
97                         struct smbd_smb2_tcon *tcon, *tc_next;
98
99                         file_close_user(sconn, sess->vuid);
100
101                         for (tcon = sess->tcons.list; tcon; tcon = tc_next) {
102                                 tc_next = tcon->next;
103                                 TALLOC_FREE(tcon);
104                                 ret = true;
105                         }
106                 }
107         } else {
108                 /* SMB1 */
109                 connection_struct *conn, *next;
110
111                 for (conn=sconn->connections;conn;conn=next) {
112                         next=conn->next;
113                         set_current_service(conn, 0, True);
114                         close_cnum(conn, conn->vuid);
115                         ret = true;
116                 }
117         }
118         return ret;
119 }
120
121
122 /****************************************************************************
123  Forcibly unmount a share.
124  All instances of the parameter 'sharename' share are unmounted.
125  The special sharename '*' forces unmount of all shares.
126 ****************************************************************************/
127
128 void conn_force_tdis(struct smbd_server_connection *sconn, const char *sharename)
129 {
130         connection_struct *conn, *next;
131
132         if (strcmp(sharename, "*") == 0) {
133                 DEBUG(1,("Forcing close of all shares\n"));
134                 conn_close_all(sconn);
135                 return;
136         }
137
138         if (sconn->using_smb2) {
139                 /* SMB2 */
140                 struct smbd_smb2_session *sess;
141                 for (sess = sconn->smb2.sessions.list; sess; sess = sess->next) {
142                         struct smbd_smb2_tcon *tcon, *tc_next;
143
144                         for (tcon = sess->tcons.list; tcon; tcon = tc_next) {
145                                 tc_next = tcon->next;
146                                 if (tcon->compat_conn &&
147                                                 strequal(lp_servicename(SNUM(tcon->compat_conn)),
148                                                                 sharename)) {
149                                         DEBUG(1,("Forcing close of share %s cnum=%d\n",
150                                                 sharename, tcon->compat_conn->cnum));
151                                         TALLOC_FREE(tcon);
152                                 }
153                         }
154                 }
155         } else {
156                 /* SMB1 */
157                 for (conn=sconn->connections;conn;conn=next) {
158                         next=conn->next;
159                         if (strequal(lp_servicename(SNUM(conn)), sharename)) {
160                                 DEBUG(1,("Forcing close of share %s cnum=%d\n",
161                                         sharename, conn->cnum));
162                                 close_cnum(conn, (uint16)-1);
163                         }
164                 }
165         }
166 }