summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2007-09-04 19:52:59 +0000
committerVolker Lendecke <vlendec@samba.org>2007-09-04 19:52:59 +0000
commit60d092d306035d730abf2cabf4f7a2379a1cb177 (patch)
tree86d547573b3e1dfd40571d64662387bff4ffb537
parentd3c9928bcb0bc3bba1103ba153dd22b1f7a0dcc4 (diff)
downloadsamba-60d092d306035d730abf2cabf4f7a2379a1cb177.tar.gz
samba-60d092d306035d730abf2cabf4f7a2379a1cb177.tar.xz
samba-60d092d306035d730abf2cabf4f7a2379a1cb177.zip
r24957: Merge 21867, 21869, 21870 and 21871:
Simplify calling convention of timeout_processing. lp_deadtime is only referenced in conn_idle_all(). Move sending keepalives out of the main processing loop into idle event. On the way, make lp_keepalive() a proper parameter. Move sending auth_server keepalives out of the main loop into an idle event. Move deadtime processing into an idle event. While there, simplify conn_idle_all() a bit.
-rw-r--r--source/auth/auth.c5
-rw-r--r--source/auth/auth_server.c86
-rw-r--r--source/include/auth.h6
-rw-r--r--source/param/loadparm.c7
-rw-r--r--source/smbd/conn.c33
-rw-r--r--source/smbd/process.c82
-rw-r--r--source/smbd/server.c45
7 files changed, 155 insertions, 109 deletions
diff --git a/source/auth/auth.c b/source/auth/auth.c
index d2f5d8326b3..29f9be9bf66 100644
--- a/source/auth/auth.c
+++ b/source/auth/auth.c
@@ -332,10 +332,7 @@ static void free_auth_context(struct auth_context **auth_context)
if (*auth_context) {
/* Free private data of context's authentication methods */
for (auth_method = (*auth_context)->auth_method_list; auth_method; auth_method = auth_method->next) {
- if (auth_method->free_private_data) {
- auth_method->free_private_data (&auth_method->private_data);
- auth_method->private_data = NULL;
- }
+ TALLOC_FREE(auth_method->private_data);
}
talloc_destroy((*auth_context)->mem_ctx);
diff --git a/source/auth/auth_server.c b/source/auth/auth_server.c
index 37d0d1c879c..b7669e945cf 100644
--- a/source/auth/auth_server.c
+++ b/source/auth/auth_server.c
@@ -140,38 +140,72 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
return cli;
}
+struct server_security_state {
+ struct cli_state *cli;
+};
+
/****************************************************************************
- Clean up our allocated cli.
+ Send a 'keepalive' packet down the cli pipe.
****************************************************************************/
-static void free_server_private_data(void **private_data_pointer)
+static BOOL send_server_keepalive(const struct timeval *now,
+ void *private_data)
{
- struct cli_state **cli = (struct cli_state **)private_data_pointer;
- if (*cli && (*cli)->initialised) {
- DEBUG(10, ("Shutting down smbserver connection\n"));
- cli_shutdown(*cli);
+ struct server_security_state *state = talloc_get_type_abort(
+ private_data, struct server_security_state);
+
+ if (!state->cli || !state->cli->initialised) {
+ return False;
}
- *private_data_pointer = NULL;
+
+ if (send_keepalive(state->cli->fd)) {
+ return True;
+ }
+
+ DEBUG( 2, ( "send_server_keepalive: password server keepalive "
+ "failed.\n"));
+ cli_shutdown(state->cli);
+ state->cli = NULL;
+ return False;
}
-/****************************************************************************
- Send a 'keepalive' packet down the cli pipe.
-****************************************************************************/
+static int destroy_server_security(struct server_security_state *state)
+{
+ if (state->cli) {
+ cli_shutdown(state->cli);
+ }
+ return 0;
+}
-static void send_server_keepalive(void **private_data_pointer)
+static struct server_security_state *make_server_security_state(struct cli_state *cli)
{
- /* also send a keepalive to the password server if its still
- connected */
- if (private_data_pointer) {
- struct cli_state *cli = (struct cli_state *)(*private_data_pointer);
- if (cli && cli->initialised) {
- if (!send_keepalive(cli->fd)) {
- DEBUG( 2, ( "send_server_keepalive: password server keepalive failed.\n"));
- cli_shutdown(cli);
- *private_data_pointer = NULL;
- }
+ struct server_security_state *result;
+
+ if (!(result = talloc(NULL, struct server_security_state))) {
+ DEBUG(0, ("talloc failed\n"));
+ cli_shutdown(cli);
+ return NULL;
+ }
+
+ result->cli = cli;
+ talloc_set_destructor(result, destroy_server_security);
+
+ if (lp_keepalive() != 0) {
+ struct timeval interval;
+ interval.tv_sec = lp_keepalive();
+ interval.tv_usec = 0;
+
+ if (event_add_idle(smbd_event_context(), result, interval,
+ "server_security_keepalive",
+ send_server_keepalive,
+ result) == NULL) {
+ DEBUG(0, ("event_add_idle failed\n"));
+ TALLOC_FREE(result);
+ return NULL;
}
}
+
+ return result;
}
/****************************************************************************
@@ -194,9 +228,9 @@ static DATA_BLOB auth_get_challenge_server(const struct auth_context *auth_conte
/* However, it is still a perfectly fine connection
to pass that unencrypted password over */
- *my_private_data = (void *)cli;
+ *my_private_data =
+ (void *)make_server_security_state(cli);
return data_blob_null;
-
} else if (cli->secblob.length < 8) {
/* We can't do much if we don't get a full challenge */
DEBUG(2,("make_auth_info_server: Didn't receive a full challenge from server\n"));
@@ -204,7 +238,9 @@ static DATA_BLOB auth_get_challenge_server(const struct auth_context *auth_conte
return data_blob_null;
}
- *my_private_data = (void *)cli;
+ if (!(*my_private_data = (void *)make_server_security_state(cli))) {
+ return data_blob(NULL,0);
+ }
/* The return must be allocated on the caller's mem_ctx, as our own will be
destoyed just after the call. */
@@ -408,8 +444,6 @@ static NTSTATUS auth_init_smbserver(struct auth_context *auth_context, const cha
(*auth_method)->name = "smbserver";
(*auth_method)->auth = check_smbserver_security;
(*auth_method)->get_chal = auth_get_challenge_server;
- (*auth_method)->send_keepalive = send_server_keepalive;
- (*auth_method)->free_private_data = free_server_private_data;
return NT_STATUS_OK;
}
diff --git a/source/include/auth.h b/source/include/auth.h
index 0094e163854..a58d150c51d 100644
--- a/source/include/auth.h
+++ b/source/include/auth.h
@@ -114,12 +114,6 @@ typedef struct auth_methods
/* Used to keep tabs on things like the cli for SMB server authentication */
void *private_data;
-
- /* Function to clean up the above arbitary structure */
- void (*free_private_data)(void **private_data);
-
- /* Function to send a keepalive message on the above structure */
- void (*send_keepalive)(void **private_data);
} auth_methods;
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index a089f556ba3..158f5149fdc 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -89,7 +89,6 @@ static BOOL include_registry_globals = False;
#define USERSHARE_VALID 1
#define USERSHARE_PENDING_DELETE 2
-int keepalive = DEFAULT_KEEPALIVE;
BOOL use_getwd_cache = True;
extern int extra_time_offset;
@@ -330,6 +329,7 @@ typedef struct {
int iIdmapNegativeCacheTime;
BOOL bResetOnZeroVC;
+ int iKeepalive;
param_opt_struct *param_opt;
} global;
@@ -1037,7 +1037,7 @@ static struct parm_struct parm_table[] = {
{"block size", P_INTEGER, P_LOCAL, &sDefault.iBlock_size, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL, NULL, FLAG_ADVANCED},
{"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL, NULL, FLAG_ADVANCED},
- {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL, NULL, FLAG_ADVANCED},
+ {"keepalive", P_INTEGER, P_GLOBAL, &Globals.iKeepalive, NULL, NULL, FLAG_ADVANCED},
{"change notify", P_BOOL, P_LOCAL, &sDefault.bChangeNotify, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
{"directory name cache size", P_INTEGER, P_LOCAL, &sDefault.iDirectoryNameCacheSize, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
{"kernel change notify", P_BOOL, P_LOCAL, &sDefault.bKernelChangeNotify, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
@@ -1705,6 +1705,8 @@ static void init_globals(BOOL first_time_only)
/* By default disallow guest access to usershares. */
Globals.bUsershareAllowGuests = False;
+ Globals.iKeepalive = DEFAULT_KEEPALIVE;
+
/* By default no shares out of the registry */
Globals.bRegistryShares = False;
}
@@ -1914,6 +1916,7 @@ FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend) /* deprecated */
FN_GLOBAL_STRING(lp_idmap_alloc_backend, &Globals.szIdmapAllocBackend)
FN_GLOBAL_INTEGER(lp_idmap_cache_time, &Globals.iIdmapCacheTime)
FN_GLOBAL_INTEGER(lp_idmap_negative_cache_time, &Globals.iIdmapNegativeCacheTime)
+FN_GLOBAL_INTEGER(lp_keepalive, &Globals.iKeepalive)
FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
diff --git a/source/smbd/conn.c b/source/smbd/conn.c
index 3aa6de52e4b..50a71edf9d3 100644
--- a/source/smbd/conn.c
+++ b/source/smbd/conn.c
@@ -186,14 +186,18 @@ void conn_close_all(void)
Idle inactive connections.
****************************************************************************/
-BOOL conn_idle_all(time_t t, int deadtime)
+BOOL conn_idle_all(time_t t)
{
+ int deadtime = lp_deadtime()*60;
pipes_struct *plist = NULL;
- BOOL allidle = True;
- connection_struct *conn, *next;
+ connection_struct *conn;
- for (conn=Connections;conn;conn=next) {
- next=conn->next;
+ if (deadtime <= 0)
+ deadtime = DEFAULT_SMBD_TIMEOUT;
+
+ for (conn=Connections;conn;conn=conn->next) {
+
+ time_t age = t - conn->lastused;
/* Update if connection wasn't idle. */
if (conn->lastused != conn->lastused_count) {
@@ -202,12 +206,12 @@ BOOL conn_idle_all(time_t t, int deadtime)
}
/* close dirptrs on connections that are idle */
- if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT) {
+ if (age > DPTR_IDLE_TIMEOUT) {
dptr_idlecnum(conn);
}
- if (conn->num_files_open > 0 || (t-conn->lastused)<deadtime) {
- allidle = False;
+ if (conn->num_files_open > 0 || age < deadtime) {
+ return False;
}
}
@@ -216,11 +220,14 @@ BOOL conn_idle_all(time_t t, int deadtime)
* idle with a handle open.
*/
- for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist))
- if (plist->pipe_handles && plist->pipe_handles->count)
- allidle = False;
+ for (plist = get_first_internal_pipe(); plist;
+ plist = get_next_internal_pipe(plist)) {
+ if (plist->pipe_handles && plist->pipe_handles->count) {
+ return False;
+ }
+ }
- return allidle;
+ return True;
}
/****************************************************************************
@@ -299,6 +306,8 @@ void conn_free(connection_struct *conn)
DLIST_REMOVE(Connections, conn);
bitmap_clear(bmap, conn->cnum);
+
+ SMB_ASSERT(num_open > 0);
num_open--;
conn_free_internal(conn);
diff --git a/source/smbd/process.c b/source/smbd/process.c
index 40ac3376a4a..7faf26af25e 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -20,7 +20,6 @@
#include "includes.h"
-extern int keepalive;
extern struct auth_context *negprot_global_auth_context;
extern int smb_echo_count;
@@ -247,6 +246,7 @@ BOOL push_deferred_smb_message(struct smb_request *req,
struct idle_event {
struct timed_event *te;
struct timeval interval;
+ char *name;
BOOL (*handler)(const struct timeval *now, void *private_data);
void *private_data;
};
@@ -267,17 +267,19 @@ static void idle_event_handler(struct event_context *ctx,
return;
}
- event->te = event_add_timed(smbd_event_context(), event,
+ event->te = event_add_timed(ctx, event,
timeval_sum(now, &event->interval),
- "idle_event_handler",
+ event->name,
idle_event_handler, event);
/* We can't do much but fail here. */
SMB_ASSERT(event->te != NULL);
}
-struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx,
+struct idle_event *event_add_idle(struct event_context *event_ctx,
+ TALLOC_CTX *mem_ctx,
struct timeval interval,
+ const char *name,
BOOL (*handler)(const struct timeval *now,
void *private_data),
void *private_data)
@@ -295,9 +297,15 @@ struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx,
result->handler = handler;
result->private_data = private_data;
- result->te = event_add_timed(smbd_event_context(), result,
+ if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
+ DEBUG(0, ("talloc failed\n"));
+ TALLOC_FREE(result);
+ return NULL;
+ }
+
+ result->te = event_add_timed(event_ctx, result,
timeval_sum(&now, &interval),
- "idle_event_handler",
+ result->name,
idle_event_handler, result);
if (result->te == NULL) {
DEBUG(0, ("event_add_timed failed\n"));
@@ -1507,12 +1515,10 @@ void check_reload(time_t t)
Process any timeout housekeeping. Return False if the caller should exit.
****************************************************************************/
-static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
+static BOOL timeout_processing(int *select_timeout,
+ time_t *last_timeout_processing_time)
{
- static time_t last_keepalive_sent_time = 0;
- static time_t last_idle_closed_check = 0;
time_t t;
- BOOL allidle = True;
if (smb_read_error == READ_EOF) {
DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
@@ -1532,53 +1538,12 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t
*last_timeout_processing_time = t = time(NULL);
- if(last_keepalive_sent_time == 0)
- last_keepalive_sent_time = t;
-
- if(last_idle_closed_check == 0)
- last_idle_closed_check = t;
-
/* become root again if waiting */
change_to_root_user();
/* check if we need to reload services */
check_reload(t);
- /* automatic timeout if all connections are closed */
- if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) {
- DEBUG( 2, ( "Closing idle connection\n" ) );
- return False;
- } else {
- last_idle_closed_check = t;
- }
-
- if (keepalive && (t - last_keepalive_sent_time)>keepalive) {
- if (!send_keepalive(smbd_server_fd())) {
- DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
- return False;
- }
-
- /* send a keepalive for a password server or the like.
- This is attached to the auth_info created in the
- negprot */
- if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method
- && negprot_global_auth_context->challenge_set_method->send_keepalive) {
-
- negprot_global_auth_context->challenge_set_method->send_keepalive
- (&negprot_global_auth_context->challenge_set_method->private_data);
- }
-
- last_keepalive_sent_time = t;
- }
-
- /* check for connection timeouts */
- allidle = conn_idle_all(t, deadtime);
-
- if (allidle && conn_num_open()>0) {
- DEBUG(2,("Closing idle connection 2.\n"));
- return False;
- }
-
if(global_machine_password_needs_changing &&
/* for ADS we need to do a regular ADS password change, not a domain
password change */
@@ -1664,21 +1629,18 @@ void smbd_process(void)
max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
while (True) {
- int deadtime = lp_deadtime()*60;
int select_timeout = setup_select_timeout();
int num_echos;
char *inbuf;
size_t inbuf_len;
TALLOC_CTX *frame = talloc_stackframe();
- if (deadtime <= 0)
- deadtime = DEFAULT_SMBD_TIMEOUT;
-
errno = 0;
/* Did someone ask for immediate checks on things like blocking locks ? */
if (select_timeout == 0) {
- if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
+ if(!timeout_processing(&select_timeout,
+ &last_timeout_processing_time))
return;
num_smbs = 0; /* Reset smb counter. */
}
@@ -1687,7 +1649,7 @@ void smbd_process(void)
while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len,
select_timeout)) {
- if(!timeout_processing(deadtime, &select_timeout,
+ if(!timeout_processing(&select_timeout,
&last_timeout_processing_time))
return;
num_smbs = 0; /* Reset smb counter. */
@@ -1710,7 +1672,7 @@ void smbd_process(void)
TALLOC_FREE(inbuf);
if (smb_echo_count != num_echos) {
- if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
+ if(!timeout_processing( &select_timeout, &last_timeout_processing_time))
return;
num_smbs = 0; /* Reset smb counter. */
}
@@ -1727,7 +1689,9 @@ void smbd_process(void)
if ((num_smbs % 200) == 0) {
time_t new_check_time = time(NULL);
if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
- if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
+ if(!timeout_processing(
+ &select_timeout,
+ &last_timeout_processing_time))
return;
num_smbs = 0; /* Reset smb counter. */
last_timeout_processing_time = new_check_time; /* Reset time. */
diff --git a/source/smbd/server.c b/source/smbd/server.c
index 9989f3463d1..0f47a550e96 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -831,6 +831,35 @@ static BOOL init_structs(void )
return True;
}
+/*
+ * Send keepalive packets to our client
+ */
+static BOOL keepalive_fn(const struct timeval *now, void *private_data)
+{
+ if (!send_keepalive(smbd_server_fd())) {
+ DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
+ return False;
+ }
+ return True;
+}
+
+/*
+ * Do the recurring check if we're idle
+ */
+static BOOL deadtime_fn(const struct timeval *now, void *private_data)
+{
+ if ((conn_num_open() == 0)
+ || (conn_idle_all(now->tv_sec))) {
+ DEBUG( 2, ( "Closing idle connection\n" ) );
+ messaging_send(smbd_messaging_context(), procid_self(),
+ MSG_SHUTDOWN, &data_blob_null);
+ return False;
+ }
+
+ return True;
+}
+
+
/****************************************************************************
main program.
****************************************************************************/
@@ -1146,6 +1175,22 @@ extern void build_options(BOOL screen);
messaging_register(smbd_messaging_context(), NULL,
MSG_SMB_FORCE_TDIS, msg_force_tdis);
+ if ((lp_keepalive() != 0)
+ && !(event_add_idle(smbd_event_context(), NULL,
+ timeval_set(lp_keepalive(), 0),
+ "keepalive", keepalive_fn,
+ NULL))) {
+ DEBUG(0, ("Could not add keepalive event\n"));
+ exit(1);
+ }
+
+ if (!(event_add_idle(smbd_event_context(), NULL,
+ timeval_set(IDLE_CLOSED_TIMEOUT, 0),
+ "deadtime", deadtime_fn, NULL))) {
+ DEBUG(0, ("Could not add deadtime event\n"));
+ exit(1);
+ }
+
smbd_process();
namecache_shutdown();