1/* 2 Unix SMB/CIFS implementation. 3 Manage connections_struct structures 4 Copyright (C) Andrew Tridgell 1998 5 Copyright (C) Alexander Bokovoy 2002 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20*/ 21 22#include "includes.h" 23 24/* The connections bitmap is expanded in increments of BITMAP_BLOCK_SZ. The 25 * maximum size of the bitmap is the largest positive integer, but you will hit 26 * the "max connections" limit, looong before that. 27 */ 28#define BITMAP_BLOCK_SZ 128 29 30static connection_struct *Connections; 31 32/* number of open connections */ 33static struct bitmap *bmap; 34static int num_open; 35 36/**************************************************************************** 37init the conn structures 38****************************************************************************/ 39void conn_init(void) 40{ 41 bmap = bitmap_allocate(BITMAP_BLOCK_SZ); 42} 43 44/**************************************************************************** 45return the number of open connections 46****************************************************************************/ 47int conn_num_open(void) 48{ 49 return num_open; 50} 51 52 53/**************************************************************************** 54check if a snum is in use 55****************************************************************************/ 56BOOL conn_snum_used(int snum) 57{ 58 connection_struct *conn; 59 for (conn=Connections;conn;conn=conn->next) { 60 if (conn->params->service == snum) { 61 return(True); 62 } 63 } 64 return(False); 65} 66 67 68/**************************************************************************** 69find a conn given a cnum 70****************************************************************************/ 71connection_struct *conn_find(unsigned cnum) 72{ 73 int count=0; 74 connection_struct *conn; 75 76 for (conn=Connections;conn;conn=conn->next,count++) { 77 if (conn->cnum == cnum) { 78 if (count > 10) { 79 DLIST_PROMOTE(Connections, conn); 80 } 81 return conn; 82 } 83 } 84 85 return NULL; 86} 87 88 89/**************************************************************************** 90 find first available connection slot, starting from a random position. 91The randomisation stops problems with the server dieing and clients 92thinking the server is still available. 93****************************************************************************/ 94connection_struct *conn_new(void) 95{ 96 TALLOC_CTX *mem_ctx; 97 connection_struct *conn; 98 int i; 99 int find_offset = 1; 100 101find_again: 102 i = bitmap_find(bmap, find_offset); 103 104 if (i == -1) { 105 /* Expand the connections bitmap. */ 106 int oldsz = bmap->n; 107 int newsz = bmap->n + BITMAP_BLOCK_SZ; 108 struct bitmap * nbmap; 109 110 if (newsz <= oldsz) { 111 /* Integer wrap. */ 112 DEBUG(0,("ERROR! Out of connection structures\n")); 113 return NULL; 114 } 115 116 DEBUG(4,("resizing connections bitmap from %d to %d\n", 117 oldsz, newsz)); 118 119 nbmap = bitmap_allocate(newsz); 120 if (!nbmap) { 121 DEBUG(0,("ERROR! malloc fail.\n")); 122 return NULL; 123 } 124 125 bitmap_copy(nbmap, bmap); 126 bitmap_free(bmap); 127 128 bmap = nbmap; 129 find_offset = oldsz; /* Start next search in the new portion. */ 130 131 goto find_again; 132 } 133 134 /* The bitmap position is used below as the connection number 135 * conn->cnum). This ends up as the TID field in the SMB header, 136 * which is limited to 16 bits (we skip 0xffff which is the 137 * NULL TID). 138 */ 139 if (i > 65534) { 140 DEBUG(0, ("Maximum connection limit reached\n")); 141 return NULL; 142 } 143 144 if ((mem_ctx=talloc_init("connection_struct"))==NULL) { 145 DEBUG(0,("talloc_init(connection_struct) failed!\n")); 146 return NULL; 147 } 148 149 if (!(conn=TALLOC_ZERO_P(mem_ctx, connection_struct)) || 150 !(conn->params = TALLOC_P(mem_ctx, struct share_params))) { 151 DEBUG(0,("TALLOC_ZERO() failed!\n")); 152 TALLOC_FREE(mem_ctx); 153 return NULL; 154 } 155 conn->mem_ctx = mem_ctx; 156 conn->cnum = i; 157 158 bitmap_set(bmap, i); 159 160 num_open++; 161 162 string_set(&conn->user,""); 163 string_set(&conn->dirpath,""); 164 string_set(&conn->connectpath,""); 165 string_set(&conn->origpath,""); 166 167 DLIST_ADD(Connections, conn); 168 169 return conn; 170} 171 172/**************************************************************************** 173 Close all conn structures. 174****************************************************************************/ 175 176void conn_close_all(void) 177{ 178 connection_struct *conn, *next; 179 for (conn=Connections;conn;conn=next) { 180 next=conn->next; 181 set_current_service(conn, 0, True); 182 close_cnum(conn, conn->vuid); 183 } 184} 185 186/**************************************************************************** 187 Idle inactive connections. 188****************************************************************************/ 189 190BOOL conn_idle_all(time_t t, int deadtime) 191{ 192 pipes_struct *plist = NULL; 193 BOOL allidle = True; 194 connection_struct *conn, *next; 195 196 for (conn=Connections;conn;conn=next) { 197 next=conn->next; 198 199 /* Update if connection wasn't idle. */ 200 if (conn->lastused != conn->lastused_count) { 201 conn->lastused = t; 202 conn->lastused_count = t; 203 } 204 205 /* close dirptrs on connections that are idle */ 206 if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT) { 207 dptr_idlecnum(conn); 208 } 209 210 if (conn->num_files_open > 0 || (t-conn->lastused)<deadtime) { 211 allidle = False; 212 } 213 } 214 215 /* 216 * Check all pipes for any open handles. We cannot 217 * idle with a handle open. 218 */ 219 220 for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist)) 221 if (plist->pipe_handles && plist->pipe_handles->count) 222 allidle = False; 223 224 return allidle; 225} 226 227/**************************************************************************** 228 Clear a vuid out of the validity cache, and as the 'owner' of a connection. 229****************************************************************************/ 230 231void conn_clear_vuid_cache(uint16 vuid) 232{ 233 connection_struct *conn; 234 unsigned int i; 235 236 for (conn=Connections;conn;conn=conn->next) { 237 if (conn->vuid == vuid) { 238 conn->vuid = UID_FIELD_INVALID; 239 } 240 241 for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++) { 242 if (conn->vuid_cache.array[i].vuid == vuid) { 243 struct vuid_cache_entry *ent = &conn->vuid_cache.array[i]; 244 ent->vuid = UID_FIELD_INVALID; 245 ent->read_only = False; 246 ent->admin_user = False; 247 } 248 } 249 } 250} 251 252/**************************************************************************** 253 Free a conn structure - internal part. 254****************************************************************************/ 255 256void conn_free_internal(connection_struct *conn) 257{ 258 vfs_handle_struct *handle = NULL, *thandle = NULL; 259 TALLOC_CTX *mem_ctx = NULL; 260 struct trans_state *state = NULL; 261 262 /* Free vfs_connection_struct */ 263 handle = conn->vfs_handles; 264 while(handle) { 265 DLIST_REMOVE(conn->vfs_handles, handle); 266 thandle = handle->next; 267 if (handle->free_data) 268 handle->free_data(&handle->data); 269 handle = thandle; 270 } 271 272 /* Free any pending transactions stored on this conn. */ 273 for (state = conn->pending_trans; state; state = state->next) { 274 /* state->setup is a talloc child of state. */ 275 SAFE_FREE(state->param); 276 SAFE_FREE(state->data); 277 } 278 279 free_namearray(conn->veto_list); 280 free_namearray(conn->hide_list); 281 free_namearray(conn->veto_oplock_list); 282 free_namearray(conn->aio_write_behind_list); 283 284 string_free(&conn->user); 285 string_free(&conn->dirpath); 286 string_free(&conn->connectpath); 287 string_free(&conn->origpath); 288 289 mem_ctx = conn->mem_ctx; 290 ZERO_STRUCTP(conn); 291 talloc_destroy(mem_ctx); 292} 293 294/**************************************************************************** 295 Free a conn structure. 296****************************************************************************/ 297 298void conn_free(connection_struct *conn) 299{ 300 DLIST_REMOVE(Connections, conn); 301 302 bitmap_clear(bmap, conn->cnum); 303 num_open--; 304 305 conn_free_internal(conn); 306} 307 308/**************************************************************************** 309receive a smbcontrol message to forcibly unmount a share 310the message contains just a share name and all instances of that 311share are unmounted 312the special sharename '*' forces unmount of all shares 313****************************************************************************/ 314void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len, 315 void *private_data) 316{ 317 connection_struct *conn, *next; 318 fstring sharename; 319 320 fstrcpy(sharename, (const char *)buf); 321 322 if (strcmp(sharename, "*") == 0) { 323 DEBUG(1,("Forcing close of all shares\n")); 324 conn_close_all(); 325 return; 326 } 327 328 for (conn=Connections;conn;conn=next) { 329 next=conn->next; 330 if (strequal(lp_servicename(SNUM(conn)), sharename)) { 331 DEBUG(1,("Forcing close of share %s cnum=%d\n", 332 sharename, conn->cnum)); 333 close_cnum(conn, (uint16)-1); 334 } 335 } 336} 337