From 60d092d306035d730abf2cabf4f7a2379a1cb177 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Sep 2007 19:52:59 +0000 Subject: 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. --- source/auth/auth.c | 5 +-- source/auth/auth_server.c | 86 +++++++++++++++++++++++++++++++++-------------- source/include/auth.h | 6 ---- source/param/loadparm.c | 7 ++-- source/smbd/conn.c | 33 +++++++++++------- source/smbd/process.c | 82 +++++++++++++------------------------------- source/smbd/server.c | 45 +++++++++++++++++++++++++ 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)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(); -- cgit