authd/providers: add timeout callback system.

This means that each provider no longer has to keep its own event; it
can set a timeout and have a callbackinstead.
This commit is contained in:
Elizabeth Myers 2016-03-30 17:20:27 -05:00
parent a20190d5ea
commit 15c49abbb3
5 changed files with 47 additions and 98 deletions

View file

@ -52,11 +52,15 @@
#include "provider.h"
#include "notice.h"
static EVH provider_timeout_event;
rb_dlink_list auth_providers;
/* Clients waiting */
rb_dictionary *auth_clients;
static struct ev_entry *timeout_ev;
/* Load a provider */
void
load_provider(struct auth_provider *provider)
@ -105,6 +109,7 @@ void
init_providers(void)
{
auth_clients = rb_dictionary_create("pending auth clients", rb_uint32cmp);
timeout_ev = rb_event_addish("provider_timeout_event", provider_timeout_event, NULL, 1);
load_provider(&rdns_provider);
load_provider(&ident_provider);
load_provider(&blacklist_provider);
@ -345,3 +350,28 @@ handle_cancel_connection(int parc, char *parv[])
cancel_providers(auth);
}
static void
provider_timeout_event(void *notused __unused)
{
struct auth_client *auth;
rb_dictionary_iter iter;
const time_t curtime = rb_current_time();
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, auth_providers.head)
{
struct auth_provider *provider = ptr->data;
const time_t timeout = auth->timeout[provider->id];
if(is_provider_on(auth, provider->id) && provider->timeout != NULL &&
timeout && timeout < curtime)
{
provider->timeout(auth);
}
}
}
}

View file

@ -33,6 +33,7 @@ typedef enum
PROVIDER_RDNS,
PROVIDER_IDENT,
PROVIDER_BLACKLIST,
PROVIDER_OPM,
} provider_t;
struct auth_client
@ -56,6 +57,7 @@ struct auth_client
bool providers_starting; /* Providers are still warming up */
void *data[MAX_PROVIDERS]; /* Provider-specific data slots */
time_t timeout[MAX_PROVIDERS]; /* When to call timeout callback */
};
typedef bool (*provider_init_t)(void);
@ -63,6 +65,7 @@ typedef void (*provider_destroy_t)(void);
typedef bool (*provider_start_t)(struct auth_client *);
typedef void (*provider_cancel_t)(struct auth_client *);
typedef void (*provider_timeout_t)(struct auth_client *);
typedef void (*provider_complete_t)(struct auth_client *, provider_t);
struct auth_stats_handler
@ -82,6 +85,7 @@ struct auth_provider
provider_start_t start; /* Perform authentication */
provider_cancel_t cancel; /* Authentication cancelled */
provider_timeout_t timeout; /* Timeout callback */
provider_complete_t completed; /* Callback for when other performers complete (think dependency chains) */
struct auth_stats_handler stats_handler;

View file

@ -91,11 +91,9 @@ struct blacklist_filter
struct blacklist_user
{
rb_dlink_list queries; /* Blacklist queries in flight */
time_t timeout; /* When this times out */
};
/* public interfaces */
static bool blacklists_init(void);
static void blacklists_destroy(void);
static bool blacklists_start(struct auth_client *);
@ -108,11 +106,9 @@ static struct blacklist *find_blacklist(const char *);
static bool blacklist_check_reply(struct blacklist_lookup *, const char *);
static void blacklist_dns_callback(const char *, bool, query_type, void *);
static void initiate_blacklist_dnsquery(struct blacklist *, struct auth_client *);
static void timeout_blacklist_queries_event(void *);
/* Variables */
static rb_dlink_list blacklist_list = { NULL, NULL, 0 };
static struct ev_entry *timeout_ev;
static int blacklist_timeout = 15;
/* private interfaces */
@ -265,6 +261,7 @@ blacklist_dns_callback(const char *result, bool status, query_type type, void *d
rb_dlink_list_length(&blacklist_list) > 1 ? "s" : "");
rb_free(bluser);
auth->data[PROVIDER_BLACKLIST] = NULL;
auth->timeout[PROVIDER_BLACKLIST] = 0;
provider_done(auth, PROVIDER_BLACKLIST);
}
}
@ -294,25 +291,6 @@ initiate_blacklist_dnsquery(struct blacklist *bl, struct auth_client *auth)
bl->refcount++;
}
/* Timeout outstanding queries */
static void
timeout_blacklist_queries_event(void *notused)
{
struct auth_client *auth;
rb_dictionary_iter iter;
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
struct blacklist_user *bluser = auth->data[PROVIDER_BLACKLIST];
if(bluser != NULL && bluser->timeout < rb_current_time())
{
blacklists_cancel(auth);
provider_done(auth, PROVIDER_BLACKLIST);
}
}
}
static inline void
lookup_all_blacklists(struct auth_client *auth)
{
@ -330,7 +308,7 @@ lookup_all_blacklists(struct auth_client *auth)
initiate_blacklist_dnsquery(bl, auth);
}
bluser->timeout = rb_current_time() + blacklist_timeout;
auth->timeout[PROVIDER_BLACKLIST] = rb_current_time() + blacklist_timeout;
}
static inline void
@ -427,13 +405,8 @@ blacklists_cancel(struct auth_client *auth)
rb_free(bluser);
auth->data[PROVIDER_BLACKLIST] = NULL;
}
static bool
blacklists_init(void)
{
timeout_ev = rb_event_addish("timeout_blacklist_queries_event", timeout_blacklist_queries_event, NULL, 1);
return (timeout_ev != NULL);
auth->timeout[PROVIDER_BLACKLIST] = 0;
provider_done(auth, PROVIDER_BLACKLIST);
}
static void
@ -448,7 +421,6 @@ blacklists_destroy(void)
}
delete_all_blacklists();
rb_event_delete(timeout_ev);
}
static void
@ -576,10 +548,10 @@ struct auth_opts_handler blacklist_options[] =
struct auth_provider blacklist_provider =
{
.id = PROVIDER_BLACKLIST,
.init = blacklists_init,
.destroy = blacklists_destroy,
.start = blacklists_start,
.cancel = blacklists_cancel,
.timeout = blacklists_cancel,
.completed = blacklists_initiate,
.opt_handlers = blacklist_options,
/* .stats_handler = { 'B', blacklist_stats }, */

View file

@ -35,7 +35,6 @@
struct ident_query
{
time_t timeout; /* Timeout interval */
rb_fde_t *F; /* Our FD */
};
@ -58,7 +57,6 @@ typedef enum
REPORT_DISABLED,
} ident_message;
static EVH timeout_ident_queries_event;
static CNCB ident_connected;
static PF read_ident_reply;
@ -66,27 +64,10 @@ static void client_fail(struct auth_client *auth, ident_message message);
static void client_success(struct auth_client *auth);
static char * get_valid_ident(char *buf);
static struct ev_entry *timeout_ev;
static int ident_timeout = 5;
static bool ident_enable = true;
/* Timeout outstanding queries */
static void
timeout_ident_queries_event(void *notused __unused)
{
struct auth_client *auth;
rb_dictionary_iter iter;
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
struct ident_query *query = auth->data[PROVIDER_IDENT];
if(query != NULL && query->timeout < rb_current_time())
client_fail(auth, REPORT_FAIL);
}
}
/*
* ident_connected() - deal with the result of rb_connect_tcp()
*
@ -209,6 +190,7 @@ client_fail(struct auth_client *auth, ident_message report)
rb_free(query);
auth->data[PROVIDER_IDENT] = NULL;
auth->timeout[PROVIDER_IDENT] = 0;
notice_client(auth->cid, messages[report]);
provider_done(auth, PROVIDER_IDENT);
@ -227,6 +209,7 @@ client_success(struct auth_client *auth)
rb_free(query);
auth->data[PROVIDER_IDENT] = NULL;
auth->timeout[PROVIDER_IDENT] = 0;
notice_client(auth->cid, messages[REPORT_FOUND]);
provider_done(auth, PROVIDER_IDENT);
@ -296,13 +279,6 @@ get_valid_ident(char *buf)
return (colon3Ptr);
}
static bool
ident_init(void)
{
timeout_ev = rb_event_addish("timeout_ident_queries_event", timeout_ident_queries_event, NULL, 1);
return (timeout_ev != NULL);
}
static void
ident_destroy(void)
{
@ -338,7 +314,7 @@ static bool ident_start(struct auth_client *auth)
notice_client(auth->cid, messages[REPORT_LOOKUP]);
auth->data[PROVIDER_IDENT] = query;
query->timeout = rb_current_time() + ident_timeout;
auth->timeout[PROVIDER_IDENT] = rb_current_time() + ident_timeout;
if((query->F = rb_socket(family, SOCK_STREAM, 0, "ident")) == NULL)
{
@ -416,10 +392,8 @@ struct auth_opts_handler ident_options[] =
struct auth_provider ident_provider =
{
.id = PROVIDER_IDENT,
.init = ident_init,
.destroy = ident_destroy,
.start = ident_start,
.cancel = ident_cancel,
.completed = NULL,
.timeout = ident_cancel,
.opt_handlers = ident_options,
};

View file

@ -29,7 +29,6 @@
struct user_query
{
struct dns_query *query; /* Pending DNS query */
time_t timeout; /* When the request times out */
};
/* Goinked from old s_auth.c --Elizabeth */
@ -53,8 +52,6 @@ static void client_fail(struct auth_client *auth, dns_message message);
static void client_success(struct auth_client *auth);
static void dns_answer_callback(const char *res, bool status, query_type type, void *data);
static struct ev_entry *timeout_ev;
static EVH timeout_dns_queries_event;
static int rdns_timeout = 15;
static void
@ -74,25 +71,6 @@ dns_answer_callback(const char *res, bool status, query_type type, void *data)
}
}
/* Timeout outstanding queries */
static void
timeout_dns_queries_event(void *notused)
{
struct auth_client *auth;
rb_dictionary_iter iter;
RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
{
struct user_query *query = auth->data[PROVIDER_RDNS];
if(query != NULL && query->timeout < rb_current_time())
{
client_fail(auth, REPORT_FAIL);
return;
}
}
}
static void
client_fail(struct auth_client *auth, dns_message report)
{
@ -108,6 +86,7 @@ client_fail(struct auth_client *auth, dns_message report)
rb_free(query);
auth->data[PROVIDER_RDNS] = NULL;
auth->timeout[PROVIDER_RDNS] = 0;
provider_done(auth, PROVIDER_RDNS);
}
@ -122,17 +101,11 @@ client_success(struct auth_client *auth)
rb_free(query);
auth->data[PROVIDER_RDNS] = NULL;
auth->timeout[PROVIDER_RDNS] = 0;
provider_done(auth, PROVIDER_RDNS);
}
static bool
rdns_init(void)
{
timeout_ev = rb_event_addish("timeout_dns_queries_event", timeout_dns_queries_event, NULL, 1);
return (timeout_ev != NULL);
}
static void
rdns_destroy(void)
{
@ -144,8 +117,6 @@ rdns_destroy(void)
if(auth->data[PROVIDER_RDNS] != NULL)
client_fail(auth, REPORT_FAIL);
}
rb_event_delete(timeout_ev);
}
static bool
@ -153,9 +124,8 @@ rdns_start(struct auth_client *auth)
{
struct user_query *query = rb_malloc(sizeof(struct user_query));
query->timeout = rb_current_time() + rdns_timeout;
auth->data[PROVIDER_RDNS] = query;
auth->timeout[PROVIDER_RDNS] = rb_current_time() + rdns_timeout;
query->query = lookup_hostname(auth->c_ip, dns_answer_callback, auth);
@ -196,10 +166,9 @@ struct auth_opts_handler rdns_options[] =
struct auth_provider rdns_provider =
{
.id = PROVIDER_RDNS,
.init = rdns_init,
.destroy = rdns_destroy,
.start = rdns_start,
.cancel = rdns_cancel,
.completed = NULL,
.timeout = rdns_cancel,
.opt_handlers = rdns_options,
};