00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "includes.h"
00022
00023 static TDB_CONTEXT *tdb;
00024
00025
00026
00027
00028
00029 TDB_CONTEXT *conn_tdb_ctx(void)
00030 {
00031 if (!tdb)
00032 tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
00033 O_RDWR | O_CREAT, 0644);
00034
00035 return tdb;
00036 }
00037
00038 static void make_conn_key(connection_struct *conn, const char *name, TDB_DATA *pkbuf, struct connections_key *pkey)
00039 {
00040 ZERO_STRUCTP(pkey);
00041 pkey->pid = procid_self();
00042 pkey->cnum = conn?conn->cnum:-1;
00043 fstrcpy(pkey->name, name);
00044 #ifdef DEVELOPER
00045
00046 {
00047 size_t sl = strlen(pkey->name);
00048 if (sizeof(fstring)-sl)
00049 memset(&pkey->name[sl], '\0', sizeof(fstring)-sl);
00050 }
00051 #endif
00052
00053 pkbuf->dptr = (char *)pkey;
00054 pkbuf->dsize = sizeof(*pkey);
00055 }
00056
00057
00058
00059
00060
00061 BOOL yield_connection(connection_struct *conn, const char *name)
00062 {
00063 struct connections_key key;
00064 TDB_DATA kbuf;
00065
00066 if (!tdb)
00067 return False;
00068
00069 DEBUG(3,("Yielding connection to %s\n",name));
00070
00071 make_conn_key(conn, name, &kbuf, &key);
00072
00073 if (tdb_delete(tdb, kbuf) != 0) {
00074 int dbg_lvl = (!conn && (tdb_error(tdb) == TDB_ERR_NOEXIST)) ? 3 : 0;
00075 DEBUG(dbg_lvl,("yield_connection: tdb_delete for name %s failed with error %s.\n",
00076 name, tdb_errorstr(tdb) ));
00077 return (False);
00078 }
00079
00080 return(True);
00081 }
00082
00083 struct count_stat {
00084 pid_t mypid;
00085 int curr_connections;
00086 const char *name;
00087 BOOL Clear;
00088 };
00089
00090
00091
00092
00093
00094 static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *udp)
00095 {
00096 struct connections_data crec;
00097 struct count_stat *cs = (struct count_stat *)udp;
00098
00099 if (dbuf.dsize != sizeof(crec))
00100 return 0;
00101
00102 memcpy(&crec, dbuf.dptr, sizeof(crec));
00103
00104 if (crec.cnum == -1)
00105 return 0;
00106
00107
00108
00109 if (cs->Clear && !process_exists(crec.pid) && (errno == ESRCH)) {
00110 DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
00111 procid_str_static(&crec.pid), crec.cnum, crec.servicename));
00112 if (tdb_delete(the_tdb, kbuf) != 0)
00113 DEBUG(0,("count_fn: tdb_delete failed with error %s\n", tdb_errorstr(tdb) ));
00114 return 0;
00115 }
00116
00117 if (strequal(crec.servicename, cs->name))
00118 cs->curr_connections++;
00119
00120 return 0;
00121 }
00122
00123
00124
00125
00126
00127 int count_current_connections( const char *sharename, BOOL clear )
00128 {
00129 struct count_stat cs;
00130
00131 cs.mypid = sys_getpid();
00132 cs.curr_connections = 0;
00133 cs.name = sharename;
00134 cs.Clear = clear;
00135
00136
00137
00138
00139
00140
00141 if (tdb_traverse(tdb, count_fn, &cs) == -1) {
00142 DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n",
00143 tdb_errorstr(tdb) ));
00144 return False;
00145 }
00146
00147 return cs.curr_connections;
00148 }
00149
00150
00151
00152
00153
00154 BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags)
00155 {
00156 struct connections_key key;
00157 struct connections_data crec;
00158 TDB_DATA kbuf, dbuf;
00159
00160 if (!tdb) {
00161 if ( (tdb =conn_tdb_ctx()) == NULL ) {
00162 return False;
00163 }
00164 }
00165
00166
00167
00168
00169
00170 if (max_connections > 0) {
00171 int curr_connections;
00172
00173 curr_connections = count_current_connections( lp_servicename(SNUM(conn)), True );
00174
00175 if (curr_connections >= max_connections) {
00176 DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n",
00177 max_connections, name ));
00178 return False;
00179 }
00180 }
00181
00182 DEBUG(5,("claiming %s %d\n",name,max_connections));
00183
00184 make_conn_key(conn, name, &kbuf, &key);
00185
00186
00187 ZERO_STRUCT(crec);
00188 crec.magic = 0x280267;
00189 crec.pid = procid_self();
00190 crec.cnum = conn?conn->cnum:-1;
00191 if (conn) {
00192 crec.uid = conn->uid;
00193 crec.gid = conn->gid;
00194 safe_strcpy(crec.servicename,
00195 lp_servicename(SNUM(conn)),sizeof(crec.servicename)-1);
00196 }
00197 crec.start = time(NULL);
00198 crec.bcast_msg_flags = msg_flags;
00199
00200 safe_strcpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)-1);
00201 safe_strcpy(crec.addr,conn?conn->client_address:client_addr(),sizeof(crec.addr)-1);
00202
00203 dbuf.dptr = (char *)&crec;
00204 dbuf.dsize = sizeof(crec);
00205
00206 if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
00207 DEBUG(0,("claim_connection: tdb_store failed with error %s.\n",
00208 tdb_errorstr(tdb) ));
00209 return False;
00210 }
00211
00212 return True;
00213 }
00214
00215 BOOL register_message_flags(BOOL doreg, uint32 msg_flags)
00216 {
00217 struct connections_key key;
00218 struct connections_data *pcrec;
00219 TDB_DATA kbuf, dbuf;
00220
00221 if (!tdb)
00222 return False;
00223
00224 DEBUG(10,("register_message_flags: %s flags 0x%x\n",
00225 doreg ? "adding" : "removing",
00226 (unsigned int)msg_flags ));
00227
00228 make_conn_key(NULL, "", &kbuf, &key);
00229
00230 dbuf = tdb_fetch(tdb, kbuf);
00231 if (!dbuf.dptr) {
00232 DEBUG(0,("register_message_flags: tdb_fetch failed: %s\n",
00233 tdb_errorstr(tdb)));
00234 return False;
00235 }
00236
00237 pcrec = (struct connections_data *)dbuf.dptr;
00238 if (doreg)
00239 pcrec->bcast_msg_flags |= msg_flags;
00240 else
00241 pcrec->bcast_msg_flags &= ~msg_flags;
00242
00243 if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
00244 DEBUG(0,("register_message_flags: tdb_store failed: %s.\n",
00245 tdb_errorstr(tdb) ));
00246 SAFE_FREE(dbuf.dptr);
00247 return False;
00248 }
00249
00250 DEBUG(10,("register_message_flags: new flags 0x%x\n",
00251 (unsigned int)pcrec->bcast_msg_flags ));
00252
00253 SAFE_FREE(dbuf.dptr);
00254 return True;
00255 }
00256
00257
00258
00259
00260 static TDB_DATA* make_pipe_rec_key( struct pipe_open_rec *prec )
00261 {
00262 TDB_DATA *kbuf = NULL;
00263 fstring key_string;
00264
00265 if ( !prec )
00266 return NULL;
00267
00268 if ( (kbuf = TALLOC_P(prec, TDB_DATA)) == NULL ) {
00269 return NULL;
00270 }
00271
00272 snprintf( key_string, sizeof(key_string), "%s/%d/%d",
00273 prec->name, procid_to_pid(&prec->pid), prec->pnum );
00274
00275 if ( (kbuf->dptr = talloc_strdup(prec, key_string)) == NULL )
00276 return NULL;
00277
00278 kbuf->dsize = strlen(key_string)+1;
00279
00280 return kbuf;
00281 }
00282
00283
00284
00285
00286 static void fill_pipe_open_rec( struct pipe_open_rec *prec, smb_np_struct *p )
00287 {
00288 prec->pid = pid_to_procid(sys_getpid());
00289 prec->pnum = p->pnum;
00290 prec->uid = geteuid();
00291 fstrcpy( prec->name, p->name );
00292
00293 return;
00294 }
00295
00296
00297
00298
00299 BOOL store_pipe_opendb( smb_np_struct *p )
00300 {
00301 struct pipe_open_rec *prec;
00302 TDB_DATA *key;
00303 TDB_DATA data;
00304 TDB_CONTEXT *pipe_tdb;
00305 BOOL ret = False;
00306
00307 if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) {
00308 DEBUG(0,("store_pipe_opendb: talloc failed!\n"));
00309 return False;
00310 }
00311
00312 fill_pipe_open_rec( prec, p );
00313 if ( (key = make_pipe_rec_key( prec )) == NULL ) {
00314 goto done;
00315 }
00316
00317 data.dptr = (char*)prec;
00318 data.dsize = sizeof(struct pipe_open_rec);
00319
00320 if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) {
00321 goto done;
00322 }
00323
00324 ret = (tdb_store( pipe_tdb, *key, data, TDB_REPLACE ) != -1);
00325
00326 done:
00327 TALLOC_FREE( prec );
00328 return ret;
00329 }
00330
00331
00332
00333
00334 BOOL delete_pipe_opendb( smb_np_struct *p )
00335 {
00336 struct pipe_open_rec *prec;
00337 TDB_DATA *key;
00338 TDB_CONTEXT *pipe_tdb;
00339 BOOL ret = False;
00340
00341 if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) {
00342 DEBUG(0,("store_pipe_opendb: talloc failed!\n"));
00343 return False;
00344 }
00345
00346 fill_pipe_open_rec( prec, p );
00347 if ( (key = make_pipe_rec_key( prec )) == NULL ) {
00348 goto done;
00349 }
00350
00351 if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) {
00352 goto done;
00353 }
00354
00355 ret = (tdb_delete( pipe_tdb, *key ) != -1 );
00356
00357 done:
00358 TALLOC_FREE( prec );
00359 return ret;
00360 }