root/source3/smbd/connection.c

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

DEFINITIONS

This source file includes following definitions.
  1. yield_connection
  2. count_fn
  3. count_current_connections
  4. count_all_current_connections
  5. claim_connection
  6. register_message_flags

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    connection claim routines
   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 3 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, see <http://www.gnu.org/licenses/>.
  18 */
  19 
  20 #include "includes.h"
  21 
  22 /****************************************************************************
  23  Delete a connection record.
  24 ****************************************************************************/
  25 
  26 bool yield_connection(connection_struct *conn, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
  27 {
  28         struct db_record *rec;
  29         NTSTATUS status;
  30 
  31         DEBUG(3,("Yielding connection to %s\n",name));
  32 
  33         if (!(rec = connections_fetch_entry(NULL, conn, name))) {
  34                 DEBUG(0, ("connections_fetch_entry failed\n"));
  35                 return False;
  36         }
  37 
  38         status = rec->delete_rec(rec);
  39         if (!NT_STATUS_IS_OK(status)) {
  40                 DEBUG( NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) ? 3 : 0,
  41                        ("deleting connection record returned %s\n",
  42                         nt_errstr(status)));
  43         }
  44 
  45         TALLOC_FREE(rec);
  46         return NT_STATUS_IS_OK(status);
  47 }
  48 
  49 struct count_stat {
  50         pid_t mypid;
  51         int curr_connections;
  52         const char *name;
  53         bool Clear;
  54 };
  55 
  56 /****************************************************************************
  57  Count the entries belonging to a service in the connection db.
  58 ****************************************************************************/
  59 
  60 static int count_fn(struct db_record *rec,
     /* [<][>][^][v][top][bottom][index][help] */
  61                     const struct connections_key *ckey,
  62                     const struct connections_data *crec,
  63                     void *udp)
  64 {
  65         struct count_stat *cs = (struct count_stat *)udp;
  66 
  67         if (crec->cnum == -1) {
  68                 return 0;
  69         }
  70 
  71         /* If the pid was not found delete the entry from connections.tdb */
  72 
  73         if (cs->Clear && !process_exists(crec->pid) && (errno == ESRCH)) {
  74                 NTSTATUS status;
  75                 DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
  76                          procid_str_static(&crec->pid), crec->cnum,
  77                          crec->servicename));
  78 
  79                 status = rec->delete_rec(rec);
  80                 if (!NT_STATUS_IS_OK(status)) {
  81                         DEBUG(0,("count_fn: tdb_delete failed with error %s\n",
  82                                  nt_errstr(status)));
  83                 }
  84                 return 0;
  85         }
  86 
  87         if (strequal(crec->servicename, cs->name))
  88                 cs->curr_connections++;
  89 
  90         return 0;
  91 }
  92 
  93 /****************************************************************************
  94  Claim an entry in the connections database.
  95 ****************************************************************************/
  96 
  97 int count_current_connections( const char *sharename, bool clear  )
     /* [<][>][^][v][top][bottom][index][help] */
  98 {
  99         struct count_stat cs;
 100 
 101         cs.mypid = sys_getpid();
 102         cs.curr_connections = 0;
 103         cs.name = sharename;
 104         cs.Clear = clear;
 105 
 106         /*
 107          * This has a race condition, but locking the chain before hand is worse
 108          * as it leads to deadlock.
 109          */
 110 
 111         if (connections_forall(count_fn, &cs) == -1) {
 112                 DEBUG(0,("count_current_connections: traverse of "
 113                          "connections.tdb failed\n"));
 114                 return False;
 115         }
 116 
 117         return cs.curr_connections;
 118 }
 119 
 120 /****************************************************************************
 121  Count the number of connections open across all shares.
 122 ****************************************************************************/
 123 
 124 int count_all_current_connections(void)
     /* [<][>][^][v][top][bottom][index][help] */
 125 {
 126         return count_current_connections(NULL, True /* clear stale entries */);
 127 }
 128 
 129 /****************************************************************************
 130  Claim an entry in the connections database.
 131 ****************************************************************************/
 132 
 133 bool claim_connection(connection_struct *conn, const char *name,
     /* [<][>][^][v][top][bottom][index][help] */
 134                       uint32 msg_flags)
 135 {
 136         struct db_record *rec;
 137         struct connections_data crec;
 138         TDB_DATA dbuf;
 139         NTSTATUS status;
 140         char addr[INET6_ADDRSTRLEN];
 141 
 142         DEBUG(5,("claiming [%s]\n", name));
 143 
 144         if (!(rec = connections_fetch_entry(talloc_tos(), conn, name))) {
 145                 DEBUG(0, ("connections_fetch_entry failed\n"));
 146                 return False;
 147         }
 148 
 149         /* fill in the crec */
 150         ZERO_STRUCT(crec);
 151         crec.magic = 0x280267;
 152         crec.pid = procid_self();
 153         crec.cnum = conn?conn->cnum:-1;
 154         if (conn) {
 155                 crec.uid = conn->server_info->utok.uid;
 156                 crec.gid = conn->server_info->utok.gid;
 157                 strlcpy(crec.servicename, lp_servicename(SNUM(conn)),
 158                         sizeof(crec.servicename));
 159         }
 160         crec.start = time(NULL);
 161         crec.bcast_msg_flags = msg_flags;
 162 
 163         strlcpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine));
 164         strlcpy(crec.addr,conn?conn->client_address:
 165                         client_addr(get_client_fd(),addr,sizeof(addr)),
 166                 sizeof(crec.addr));
 167 
 168         dbuf.dptr = (uint8 *)&crec;
 169         dbuf.dsize = sizeof(crec);
 170 
 171         status = rec->store(rec, dbuf, TDB_REPLACE);
 172 
 173         TALLOC_FREE(rec);
 174 
 175         if (!NT_STATUS_IS_OK(status)) {
 176                 DEBUG(0,("claim_connection: tdb_store failed with error %s.\n",
 177                          nt_errstr(status)));
 178                 return False;
 179         }
 180 
 181         return True;
 182 }
 183 
 184 bool register_message_flags(bool doreg, uint32 msg_flags)
     /* [<][>][^][v][top][bottom][index][help] */
 185 {
 186         struct db_record *rec;
 187         struct connections_data *pcrec;
 188         NTSTATUS status;
 189 
 190         DEBUG(10,("register_message_flags: %s flags 0x%x\n",
 191                 doreg ? "adding" : "removing",
 192                 (unsigned int)msg_flags ));
 193 
 194         if (!(rec = connections_fetch_entry(NULL, NULL, ""))) {
 195                 DEBUG(0, ("connections_fetch_entry failed\n"));
 196                 return False;
 197         }
 198 
 199         if (rec->value.dsize != sizeof(struct connections_data)) {
 200                 DEBUG(0,("register_message_flags: Got wrong record size\n"));
 201                 TALLOC_FREE(rec);
 202                 return False;
 203         }
 204 
 205         pcrec = (struct connections_data *)rec->value.dptr;
 206         if (doreg)
 207                 pcrec->bcast_msg_flags |= msg_flags;
 208         else
 209                 pcrec->bcast_msg_flags &= ~msg_flags;
 210 
 211         status = rec->store(rec, rec->value, TDB_REPLACE);
 212 
 213         if (!NT_STATUS_IS_OK(status)) {
 214                 DEBUG(0,("register_message_flags: tdb_store failed: %s.\n",
 215                          nt_errstr(status)));
 216                 TALLOC_FREE(rec);
 217                 return False;
 218         }
 219 
 220         DEBUG(10,("register_message_flags: new flags 0x%x\n",
 221                 (unsigned int)pcrec->bcast_msg_flags ));
 222 
 223         TALLOC_FREE(rec);
 224 
 225         return True;
 226 }

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