Removed version number from file header.
[ira/wip.git] / source3 / smbd / conn.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Manage connections_struct structures
4    Copyright (C) Andrew Tridgell 1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 /* set these to define the limits of the server. NOTE These are on a
24    per-client basis. Thus any one machine can't connect to more than
25    MAX_CONNECTIONS services, but any number of machines may connect at
26    one time. */
27 #define MAX_CONNECTIONS 128
28
29 static connection_struct *Connections;
30
31 /* number of open connections */
32 static struct bitmap *bmap;
33 static int num_open;
34
35 /****************************************************************************
36 init the conn structures
37 ****************************************************************************/
38 void conn_init(void)
39 {
40         bmap = bitmap_allocate(MAX_CONNECTIONS);
41 }
42
43 /****************************************************************************
44 return the number of open connections
45 ****************************************************************************/
46 int conn_num_open(void)
47 {
48         return num_open;
49 }
50
51
52 /****************************************************************************
53 check if a snum is in use
54 ****************************************************************************/
55 BOOL conn_snum_used(int snum)
56 {
57         connection_struct *conn;
58         for (conn=Connections;conn;conn=conn->next) {
59                 if (conn->service == snum) {
60                         return(True);
61                 }
62         }
63         return(False);
64 }
65
66
67 /****************************************************************************
68 find a conn given a cnum
69 ****************************************************************************/
70 connection_struct *conn_find(int cnum)
71 {
72         int count=0;
73         connection_struct *conn;
74
75         for (conn=Connections;conn;conn=conn->next,count++) {
76                 if (conn->cnum == cnum) {
77                         if (count > 10) {
78                                 DLIST_PROMOTE(Connections, conn);
79                         }
80                         return conn;
81                 }
82         }
83
84         return NULL;
85 }
86
87
88 /****************************************************************************
89   find first available connection slot, starting from a random position.
90 The randomisation stops problems with the server dieing and clients
91 thinking the server is still available.
92 ****************************************************************************/
93 connection_struct *conn_new(void)
94 {
95         connection_struct *conn;
96         int i;
97
98         i = bitmap_find(bmap, 1);
99         
100         if (i == -1) {
101                 DEBUG(1,("ERROR! Out of connection structures\n"));            
102                 return NULL;
103         }
104
105         conn = (connection_struct *)malloc(sizeof(*conn));
106         if (!conn) return NULL;
107
108         ZERO_STRUCTP(conn);
109         conn->cnum = i;
110
111         bitmap_set(bmap, i);
112
113         num_open++;
114
115         string_set(&conn->user,"");
116         string_set(&conn->dirpath,"");
117         string_set(&conn->connectpath,"");
118         string_set(&conn->origpath,"");
119         
120         DLIST_ADD(Connections, conn);
121
122         return conn;
123 }
124
125 /****************************************************************************
126 close all conn structures
127 ****************************************************************************/
128 void conn_close_all(void)
129 {
130         connection_struct *conn, *next;
131         for (conn=Connections;conn;conn=next) {
132                 next=conn->next;
133                 close_cnum(conn, (uint16)-1);
134         }
135 }
136
137 /****************************************************************************
138 idle inactive connections
139 ****************************************************************************/
140 BOOL conn_idle_all(time_t t, int deadtime)
141 {
142         BOOL allidle = True;
143         connection_struct *conn, *next;
144
145         for (conn=Connections;conn;conn=next) {
146                 next=conn->next;
147                 /* close dirptrs on connections that are idle */
148                 if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT)
149                         dptr_idlecnum(conn);
150
151                 if (conn->num_files_open > 0 || 
152                     (t-conn->lastused)<deadtime)
153                         allidle = False;
154         }
155
156         return allidle;
157 }
158
159 /****************************************************************************
160  Free a conn structure.
161 ****************************************************************************/
162
163 void conn_free(connection_struct *conn)
164 {
165         /* Free vfs_connection_struct */
166             
167 #ifdef HAVE_LIBDL
168         if (conn->dl_handle != NULL) {
169                 /* Close dlopen() handle */
170                 dlclose(conn->dl_handle);
171         }
172 #endif /* HAVE_LIBDL */
173
174         DLIST_REMOVE(Connections, conn);
175
176         if (conn->ngroups && conn->groups) {
177                 SAFE_FREE(conn->groups);
178                 conn->ngroups = 0;
179         }
180
181         delete_nt_token(&conn->nt_user_token);
182         free_namearray(conn->veto_list);
183         free_namearray(conn->hide_list);
184         free_namearray(conn->veto_oplock_list);
185         
186         string_free(&conn->user);
187         string_free(&conn->dirpath);
188         string_free(&conn->connectpath);
189         string_free(&conn->origpath);
190
191         bitmap_clear(bmap, conn->cnum);
192         num_open--;
193
194         ZERO_STRUCTP(conn);
195         SAFE_FREE(conn);
196 }
197
198
199 /****************************************************************************
200 receive a smbcontrol message to forcibly unmount a share
201 the message contains just a share name and all instances of that
202 share are unmounted
203 the special sharename '*' forces unmount of all shares
204 ****************************************************************************/
205 void msg_force_tdis(int msg_type, pid_t pid, void *buf, size_t len)
206 {
207         connection_struct *conn, *next;
208         fstring sharename;
209
210         fstrcpy(sharename, buf);
211
212         if (strcmp(sharename, "*") == 0) {
213                 DEBUG(1,("Forcing close of all shares\n"));
214                 conn_close_all();
215                 return;
216         }
217
218         for (conn=Connections;conn;conn=next) {
219                 next=conn->next;
220                 if (strequal(lp_servicename(conn->service), sharename)) {
221                         DEBUG(1,("Forcing close of share %s cnum=%d\n",
222                                  sharename, conn->cnum));
223                         close_cnum(conn, (uint16)-1);
224                 }
225         }
226 }