root/source3/smbd/conn.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. conn_init
  2. conn_num_open
  3. conn_snum_used
  4. conn_find
  5. conn_new
  6. conn_close_all
  7. conn_idle_all
  8. conn_clear_vuid_caches
  9. conn_free_internal
  10. conn_free
  11. msg_force_tdis

   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 3 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, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 #include "includes.h"
  22 #include "smbd/globals.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 
  30 /****************************************************************************
  31 init the conn structures
  32 ****************************************************************************/
  33 void conn_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
  34 {
  35         bmap = bitmap_allocate(BITMAP_BLOCK_SZ);
  36 }
  37 
  38 /****************************************************************************
  39 return the number of open connections
  40 ****************************************************************************/
  41 int conn_num_open(void)
     /* [<][>][^][v][top][bottom][index][help] */
  42 {
  43         return num_open;
  44 }
  45 
  46 
  47 /****************************************************************************
  48 check if a snum is in use
  49 ****************************************************************************/
  50 bool conn_snum_used(int snum)
     /* [<][>][^][v][top][bottom][index][help] */
  51 {
  52         connection_struct *conn;
  53         for (conn=Connections;conn;conn=conn->next) {
  54                 if (conn->params->service == snum) {
  55                         return(True);
  56                 }
  57         }
  58         return(False);
  59 }
  60 
  61 /****************************************************************************
  62  Find a conn given a cnum.
  63 ****************************************************************************/
  64 
  65 connection_struct *conn_find(unsigned cnum)
     /* [<][>][^][v][top][bottom][index][help] */
  66 {
  67         int count=0;
  68         connection_struct *conn;
  69 
  70         for (conn=Connections;conn;conn=conn->next,count++) {
  71                 if (conn->cnum == cnum) {
  72                         if (count > 10) {
  73                                 DLIST_PROMOTE(Connections, conn);
  74                         }
  75                         return conn;
  76                 }
  77         }
  78 
  79         return NULL;
  80 }
  81 
  82 /****************************************************************************
  83   find first available connection slot, starting from a random position.
  84 The randomisation stops problems with the server dieing and clients
  85 thinking the server is still available.
  86 ****************************************************************************/
  87 connection_struct *conn_new(void)
     /* [<][>][^][v][top][bottom][index][help] */
  88 {
  89         connection_struct *conn;
  90         int i;
  91         int find_offset = 1;
  92 
  93 find_again:
  94         i = bitmap_find(bmap, find_offset);
  95         
  96         if (i == -1) {
  97                 /* Expand the connections bitmap. */
  98                 int             oldsz = bmap->n;
  99                 int             newsz = bmap->n + BITMAP_BLOCK_SZ;
 100                 struct bitmap * nbmap;
 101 
 102                 if (newsz <= oldsz) {
 103                         /* Integer wrap. */
 104                         DEBUG(0,("ERROR! Out of connection structures\n"));
 105                         return NULL;
 106                 }
 107 
 108                 DEBUG(4,("resizing connections bitmap from %d to %d\n",
 109                         oldsz, newsz));
 110 
 111                 nbmap = bitmap_allocate(newsz);
 112                 if (!nbmap) {
 113                         DEBUG(0,("ERROR! malloc fail.\n"));
 114                         return NULL;
 115                 }
 116 
 117                 bitmap_copy(nbmap, bmap);
 118                 bitmap_free(bmap);
 119 
 120                 bmap = nbmap;
 121                 find_offset = oldsz; /* Start next search in the new portion. */
 122 
 123                 goto find_again;
 124         }
 125 
 126         /* The bitmap position is used below as the connection number
 127          * conn->cnum). This ends up as the TID field in the SMB header,
 128          * which is limited to 16 bits (we skip 0xffff which is the
 129          * NULL TID).
 130          */
 131         if (i > 65534) {
 132                 DEBUG(0, ("Maximum connection limit reached\n"));
 133                 return NULL;
 134         }
 135 
 136         if (!(conn=TALLOC_ZERO_P(NULL, connection_struct)) ||
 137             !(conn->params = TALLOC_P(conn, struct share_params))) {
 138                 DEBUG(0,("TALLOC_ZERO() failed!\n"));
 139                 TALLOC_FREE(conn);
 140                 return NULL;
 141         }
 142         conn->cnum = i;
 143         conn->force_group_gid = (gid_t)-1;
 144 
 145         bitmap_set(bmap, i);
 146 
 147         num_open++;
 148 
 149         string_set(&conn->dirpath,"");
 150         string_set(&conn->connectpath,"");
 151         string_set(&conn->origpath,"");
 152         
 153         DLIST_ADD(Connections, conn);
 154 
 155         return conn;
 156 }
 157 
 158 /****************************************************************************
 159  Close all conn structures.
 160 return true if any were closed
 161 ****************************************************************************/
 162 bool conn_close_all(void)
     /* [<][>][^][v][top][bottom][index][help] */
 163 {
 164         connection_struct *conn, *next;
 165         bool ret = false;
 166         for (conn=Connections;conn;conn=next) {
 167                 next=conn->next;
 168                 set_current_service(conn, 0, True);
 169                 close_cnum(conn, conn->vuid);
 170                 ret = true;
 171         }
 172         return ret;
 173 }
 174 
 175 /****************************************************************************
 176  Idle inactive connections.
 177 ****************************************************************************/
 178 
 179 bool conn_idle_all(time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
 180 {
 181         int deadtime = lp_deadtime()*60;
 182         pipes_struct *plist = NULL;
 183         connection_struct *conn;
 184 
 185         if (deadtime <= 0)
 186                 deadtime = DEFAULT_SMBD_TIMEOUT;
 187 
 188         for (conn=Connections;conn;conn=conn->next) {
 189 
 190                 time_t age = t - conn->lastused;
 191 
 192                 /* Update if connection wasn't idle. */
 193                 if (conn->lastused != conn->lastused_count) {
 194                         conn->lastused = t;
 195                         conn->lastused_count = t;
 196                 }
 197 
 198                 /* close dirptrs on connections that are idle */
 199                 if (age > DPTR_IDLE_TIMEOUT) {
 200                         dptr_idlecnum(conn);
 201                 }
 202 
 203                 if (conn->num_files_open > 0 || age < deadtime) {
 204                         return False;
 205                 }
 206         }
 207 
 208         /*
 209          * Check all pipes for any open handles. We cannot
 210          * idle with a handle open.
 211          */
 212 
 213         for (plist = get_first_internal_pipe(); plist;
 214              plist = get_next_internal_pipe(plist)) {
 215                 if (plist->pipe_handles && plist->pipe_handles->count) {
 216                         return False;
 217                 }
 218         }
 219         
 220         return True;
 221 }
 222 
 223 /****************************************************************************
 224  Clear a vuid out of the validity cache, and as the 'owner' of a connection.
 225 ****************************************************************************/
 226 
 227 void conn_clear_vuid_caches(uint16_t vuid)
     /* [<][>][^][v][top][bottom][index][help] */
 228 {
 229         connection_struct *conn;
 230 
 231         for (conn=Connections;conn;conn=conn->next) {
 232                 if (conn->vuid == vuid) {
 233                         conn->vuid = UID_FIELD_INVALID;
 234                 }
 235                 conn_clear_vuid_cache(conn, vuid);
 236         }
 237 }
 238 
 239 /****************************************************************************
 240  Free a conn structure - internal part.
 241 ****************************************************************************/
 242 
 243 void conn_free_internal(connection_struct *conn)
     /* [<][>][^][v][top][bottom][index][help] */
 244 {
 245         vfs_handle_struct *handle = NULL, *thandle = NULL;
 246         struct trans_state *state = NULL;
 247 
 248         /* Free vfs_connection_struct */
 249         handle = conn->vfs_handles;
 250         while(handle) {
 251                 thandle = handle->next;
 252                 DLIST_REMOVE(conn->vfs_handles, handle);
 253                 if (handle->free_data)
 254                         handle->free_data(&handle->data);
 255                 handle = thandle;
 256         }
 257 
 258         /* Free any pending transactions stored on this conn. */
 259         for (state = conn->pending_trans; state; state = state->next) {
 260                 /* state->setup is a talloc child of state. */
 261                 SAFE_FREE(state->param);
 262                 SAFE_FREE(state->data);
 263         }
 264 
 265         free_namearray(conn->veto_list);
 266         free_namearray(conn->hide_list);
 267         free_namearray(conn->veto_oplock_list);
 268         free_namearray(conn->aio_write_behind_list);
 269         
 270         string_free(&conn->dirpath);
 271         string_free(&conn->connectpath);
 272         string_free(&conn->origpath);
 273 
 274         ZERO_STRUCTP(conn);
 275         talloc_destroy(conn);
 276 }
 277 
 278 /****************************************************************************
 279  Free a conn structure.
 280 ****************************************************************************/
 281 
 282 void conn_free(connection_struct *conn)
     /* [<][>][^][v][top][bottom][index][help] */
 283 {
 284         DLIST_REMOVE(Connections, conn);
 285 
 286         bitmap_clear(bmap, conn->cnum);
 287 
 288         SMB_ASSERT(num_open > 0);
 289         num_open--;
 290 
 291         conn_free_internal(conn);
 292 }
 293  
 294 /****************************************************************************
 295 receive a smbcontrol message to forcibly unmount a share
 296 the message contains just a share name and all instances of that
 297 share are unmounted
 298 the special sharename '*' forces unmount of all shares
 299 ****************************************************************************/
 300 void msg_force_tdis(struct messaging_context *msg,
     /* [<][>][^][v][top][bottom][index][help] */
 301                     void *private_data,
 302                     uint32_t msg_type,
 303                     struct server_id server_id,
 304                     DATA_BLOB *data)
 305 {
 306         connection_struct *conn, *next;
 307         fstring sharename;
 308 
 309         fstrcpy(sharename, (const char *)data->data);
 310 
 311         if (strcmp(sharename, "*") == 0) {
 312                 DEBUG(1,("Forcing close of all shares\n"));
 313                 conn_close_all();
 314                 return;
 315         }
 316 
 317         for (conn=Connections;conn;conn=next) {
 318                 next=conn->next;
 319                 if (strequal(lp_servicename(SNUM(conn)), sharename)) {
 320                         DEBUG(1,("Forcing close of share %s cnum=%d\n",
 321                                  sharename, conn->cnum));
 322                         close_cnum(conn, (uint16)-1);
 323                 }
 324         }
 325 }

/* [<][>][^][v][top][bottom][index][help] */