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/* Foxconn, add by MJ., 2010.03.29, for making a Semaphore. */ 25#ifdef MAX_USB_ACCESS 26/* Obtain a binary semaphore��s ID, allocating if necessary. */ 27int binary_semaphore_allocation (key_t key, int sem_flags) 28{ 29 return semget (key, 1, sem_flags); 30} 31/* Deallocate a binary semaphore. All users must have finished their 32use. Returns -1 on failure. */ 33int binary_semaphore_deallocate (int semid) 34{ 35 union semun ignored_argument; 36 return semctl (semid, 1, IPC_RMID, ignored_argument); 37} 38 39/* Initialize a binary semaphore with a value of 1. */ 40int binary_semaphore_initialize (int semid) 41{ 42 union semun argument; 43 unsigned short values[1]; 44 values[0] = 1; 45 argument.array = values; 46 return semctl (semid, 0, SETALL, argument); 47} 48/* Wait on a binary semaphore. Block until the semaphore value is positive, then 49decrement it by 1. */ 50int binary_semaphore_wait (int semid) 51{ 52 struct sembuf operations[1]; 53 /* Use the first (and only) semaphore. */ 54 operations[0].sem_num = 0; 55 /* Decrement by 1. */ 56 operations[0].sem_op = -1; 57 /* Permit undo��ing. */ 58 operations[0].sem_flg = SEM_UNDO; 59 return semop (semid, operations, 1); 60} 61 62/* Post to a binary semaphore: increment its value by 1. 63This returns immediately. */ 64int binary_semaphore_post (int semid) 65{ 66 struct sembuf operations[1]; 67 /* Use the first (and only) semaphore. */ 68 operations[0].sem_num = 0; 69 /* Increment by 1. */ 70 operations[0].sem_op = 1; 71 /* Permit undo��ing. */ 72 operations[0].sem_flg = SEM_UNDO; 73 return semop (semid, operations, 1); 74} 75#endif //End of MAX_USB_ACCESS 76/* Foxconn, ened by MJ., 2010.03.29 */ 77 78 79/* The connections bitmap is expanded in increments of BITMAP_BLOCK_SZ. The 80 * maximum size of the bitmap is the largest positive integer, but you will hit 81 * the "max connections" limit, looong before that. 82 */ 83#define BITMAP_BLOCK_SZ 128 84 85static connection_struct *Connections; 86 87/* number of open connections */ 88static struct bitmap *bmap; 89static int num_open; 90 91/**************************************************************************** 92init the conn structures 93****************************************************************************/ 94void conn_init(void) 95{ 96 bmap = bitmap_allocate(BITMAP_BLOCK_SZ); 97} 98 99/**************************************************************************** 100return the number of open connections 101****************************************************************************/ 102int conn_num_open(void) 103{ 104 return num_open; 105} 106 107 108/**************************************************************************** 109check if a snum is in use 110****************************************************************************/ 111BOOL conn_snum_used(int snum) 112{ 113 connection_struct *conn; 114 for (conn=Connections;conn;conn=conn->next) { 115 if (conn->service == snum) { 116 return(True); 117 } 118 } 119 return(False); 120} 121 122 123/**************************************************************************** 124find a conn given a cnum 125****************************************************************************/ 126connection_struct *conn_find(unsigned cnum) 127{ 128 int count=0; 129 connection_struct *conn; 130 131 for (conn=Connections;conn;conn=conn->next,count++) { 132 if (conn->cnum == cnum) { 133 if (count > 10) { 134 DLIST_PROMOTE(Connections, conn); 135 } 136 return conn; 137 } 138 } 139 140 return NULL; 141} 142 143 144/**************************************************************************** 145 find first available connection slot, starting from a random position. 146The randomisation stops problems with the server dieing and clients 147thinking the server is still available. 148****************************************************************************/ 149connection_struct *conn_new(void) 150{ 151 TALLOC_CTX *mem_ctx; 152 connection_struct *conn; 153 int i; 154 int find_offset = 1; 155 /* Foxconn, added by MJ., 2010.03.26 */ 156#if 0 157 extern CON_STATISTIC *con_st; 158 159 if(con_st != NULL){ 160 dbgtext("->total con num: %d, %s\n", con_st->num, __FUNCTION__); 161 binary_semaphore_wait (con_st->sem_id); 162 if(con_st->num >= MAX_CON_NUM){ 163 binary_semaphore_post (con_st->sem_id); 164 return NULL; 165 } 166 binary_semaphore_post (con_st->sem_id); 167 } 168#endif 169 /* Foxconn, ended by MJ., 2010.03.26*/ 170 171find_again: 172 i = bitmap_find(bmap, find_offset); 173 174 if (i == -1) { 175 /* Expand the connections bitmap. */ 176 int oldsz = bmap->n; 177 int newsz = bmap->n + BITMAP_BLOCK_SZ; 178 struct bitmap * nbmap; 179 180 if (newsz <= 0) { 181 /* Integer wrap. */ 182 DEBUG(0,("ERROR! Out of connection structures\n")); 183 return NULL; 184 } 185 186 DEBUG(4,("resizing connections bitmap from %d to %d\n", 187 oldsz, newsz)); 188 189 nbmap = bitmap_allocate(newsz); 190 191 bitmap_copy(nbmap, bmap); 192 bitmap_free(bmap); 193 194 bmap = nbmap; 195 find_offset = oldsz; /* Start next search in the new portion. */ 196 197 goto find_again; 198 } 199 200 if ((mem_ctx=talloc_init("connection_struct"))==NULL) { 201 DEBUG(0,("talloc_init(connection_struct) failed!\n")); 202 203 return NULL; 204 } 205 206 if ((conn=TALLOC_ZERO_P(mem_ctx, connection_struct))==NULL) { 207 DEBUG(0,("talloc_zero() failed!\n")); 208 209 return NULL; 210 } 211 conn->mem_ctx = mem_ctx; 212 conn->cnum = i; 213 214 bitmap_set(bmap, i); 215 216 num_open++; 217 218 string_set(&conn->user,""); 219 string_set(&conn->dirpath,""); 220 string_set(&conn->connectpath,""); 221 string_set(&conn->origpath,""); 222 223 DLIST_ADD(Connections, conn); 224 225 return conn; 226} 227 228/**************************************************************************** 229close all conn structures 230****************************************************************************/ 231void conn_close_all(void) 232{ 233 connection_struct *conn, *next; 234 for (conn=Connections;conn;conn=next) { 235 next=conn->next; 236 set_current_service(conn, 0, True); 237 close_cnum(conn, conn->vuid); 238 } 239} 240 241/**************************************************************************** 242 Idle inactive connections. 243****************************************************************************/ 244 245BOOL conn_idle_all(time_t t, int deadtime) 246{ 247 pipes_struct *plist = NULL; 248 BOOL allidle = True; 249 connection_struct *conn, *next; 250 251 for (conn=Connections;conn;conn=next) { 252 next=conn->next; 253 /* close dirptrs on connections that are idle */ 254 if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT) 255 dptr_idlecnum(conn); 256 257 if (conn->num_files_open > 0 || 258 (t-conn->lastused)<deadtime) 259 allidle = False; 260 } 261 262 /* 263 * Check all pipes for any open handles. We cannot 264 * idle with a handle open. 265 */ 266 267 for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist)) 268 if (plist->pipe_handles && plist->pipe_handles->count) 269 allidle = False; 270 271 return allidle; 272} 273 274/**************************************************************************** 275 Clear a vuid out of the validity cache, and as the 'owner' of a connection. 276****************************************************************************/ 277 278void conn_clear_vuid_cache(uint16 vuid) 279{ 280 connection_struct *conn; 281 unsigned int i; 282 283 for (conn=Connections;conn;conn=conn->next) { 284 if (conn->vuid == vuid) { 285 conn->vuid = UID_FIELD_INVALID; 286 } 287 288 for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++) { 289 if (conn->vuid_cache.array[i].vuid == vuid) { 290 struct vuid_cache_entry *ent = &conn->vuid_cache.array[i]; 291 ent->vuid = UID_FIELD_INVALID; 292 ent->read_only = False; 293 ent->admin_user = False; 294 } 295 } 296 } 297} 298 299/**************************************************************************** 300 Free a conn structure. 301****************************************************************************/ 302 303void conn_free(connection_struct *conn) 304{ 305 vfs_handle_struct *handle = NULL, *thandle = NULL; 306 TALLOC_CTX *mem_ctx = NULL; 307 308 /* Free vfs_connection_struct */ 309 handle = conn->vfs_handles; 310 while(handle) { 311 DLIST_REMOVE(conn->vfs_handles, handle); 312 thandle = handle->next; 313 if (handle->free_data) 314 handle->free_data(&handle->data); 315 handle = thandle; 316 } 317 318 DLIST_REMOVE(Connections, conn); 319 320 if (conn->ngroups && conn->groups) { 321 SAFE_FREE(conn->groups); 322 conn->ngroups = 0; 323 } 324 325 if (conn->nt_user_token) { 326 delete_nt_token(&(conn->nt_user_token)); 327 } 328 329 free_namearray(conn->veto_list); 330 free_namearray(conn->hide_list); 331 free_namearray(conn->veto_oplock_list); 332 333 string_free(&conn->user); 334 string_free(&conn->dirpath); 335 string_free(&conn->connectpath); 336 string_free(&conn->origpath); 337 338 bitmap_clear(bmap, conn->cnum); 339 num_open--; 340 341 mem_ctx = conn->mem_ctx; 342 ZERO_STRUCTP(conn); 343 talloc_destroy(mem_ctx); 344} 345 346 347/**************************************************************************** 348receive a smbcontrol message to forcibly unmount a share 349the message contains just a share name and all instances of that 350share are unmounted 351the special sharename '*' forces unmount of all shares 352****************************************************************************/ 353void msg_force_tdis(int msg_type, pid_t pid, void *buf, size_t len) 354{ 355 connection_struct *conn, *next; 356 fstring sharename; 357 358 fstrcpy(sharename, buf); 359 360 if (strcmp(sharename, "*") == 0) { 361 DEBUG(1,("Forcing close of all shares\n")); 362 conn_close_all(); 363 return; 364 } 365 366 for (conn=Connections;conn;conn=next) { 367 next=conn->next; 368 if (strequal(lp_servicename(conn->service), sharename)) { 369 DEBUG(1,("Forcing close of share %s cnum=%d\n", 370 sharename, conn->cnum)); 371 close_cnum(conn, (uint16)-1); 372 } 373 } 374} 375