diff options
author | Pavel Březina <pbrezina@redhat.com> | 2013-04-11 13:37:39 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2013-05-02 16:48:12 +0200 |
commit | 1099620d87afcee7e239cbb75fd364643c8c1124 (patch) | |
tree | b88a8ad87d246c25fb39b1da69a34dfb03a96201 | |
parent | 4ada3948dd888e7d95831a377bff3f8608cd778b (diff) | |
download | sssd-1099620d87afcee7e239cbb75fd364643c8c1124.tar.gz sssd-1099620d87afcee7e239cbb75fd364643c8c1124.tar.bz2 sssd-1099620d87afcee7e239cbb75fd364643c8c1124.zip |
add fo_discover_servers request
This request takes discovery domain for primary servers and other
domain for backup servers and returns list of primary and backup
servers.
If primary domain is not reachable, it returns servers found in
backup domain as primary servers.
-rw-r--r-- | src/providers/fail_over_srv.c | 239 | ||||
-rw-r--r-- | src/providers/fail_over_srv.h | 16 |
2 files changed, 254 insertions, 1 deletions
diff --git a/src/providers/fail_over_srv.c b/src/providers/fail_over_srv.c index aa0bccb2..c16bea27 100644 --- a/src/providers/fail_over_srv.c +++ b/src/providers/fail_over_srv.c @@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <string.h> +#include <strings.h> #include <talloc.h> #include <tevent.h> @@ -165,6 +165,243 @@ errno_t fo_discover_srv_recv(TALLOC_CTX *mem_ctx, return EOK; } +struct fo_discover_servers_state { + struct tevent_context *ev; + struct resolv_ctx *resolv_ctx; + const char *service; + const char *protocol; + const char *primary_domain; + const char *backup_domain; + + char *dns_domain; + struct fo_server_info *primary_servers; + size_t num_primary_servers; + struct fo_server_info *backup_servers; + size_t num_backup_servers; +}; + +static void fo_discover_servers_primary_done(struct tevent_req *subreq); +static void fo_discover_servers_backup_done(struct tevent_req *subreq); + +struct tevent_req *fo_discover_servers_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resolv_ctx *resolv_ctx, + const char *service, + const char *protocol, + const char *primary_domain, + const char *backup_domain) +{ + struct fo_discover_servers_state *state = NULL; + struct tevent_req *req = NULL; + struct tevent_req *subreq = NULL; + const char **domains = NULL; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, + struct fo_discover_servers_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n")); + return NULL; + } + + if (primary_domain == NULL) { + if (backup_domain == NULL) { + state->primary_servers = NULL; + state->num_primary_servers = 0; + state->backup_servers = NULL; + state->num_backup_servers = 0; + state->dns_domain = NULL; + + ret = EOK; + goto immediately; + } else { + primary_domain = backup_domain; + backup_domain = NULL; + } + } + + state->ev = ev; + state->resolv_ctx = resolv_ctx; + + state->service = talloc_strdup(state, service); + if (state->service == NULL) { + ret = ENOMEM; + goto immediately; + } + + state->protocol = talloc_strdup(state, protocol); + if (state->protocol == NULL) { + ret = ENOMEM; + goto immediately; + } + + state->primary_domain = talloc_strdup(state, primary_domain); + if (state->primary_domain == NULL) { + ret = ENOMEM; + goto immediately; + } + + state->backup_domain = talloc_strdup(state, backup_domain); + if (state->backup_domain == NULL && backup_domain != NULL) { + ret = ENOMEM; + goto immediately; + } + + DEBUG(SSSDBG_TRACE_FUNC, ("Looking up primary servers\n")); + + domains = talloc_zero_array(state, const char *, 3); + if (domains == NULL) { + ret = ENOMEM; + goto immediately; + } + + domains[0] = state->primary_domain; + domains[1] = state->backup_domain; + + subreq = fo_discover_srv_send(state, ev, resolv_ctx, + state->service, state->protocol, domains); + if (subreq == NULL) { + ret = ENOMEM; + goto immediately; + } + + tevent_req_set_callback(subreq, fo_discover_servers_primary_done, req); + + return req; + +immediately: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + + return req; +} + +static void fo_discover_servers_primary_done(struct tevent_req *subreq) +{ + struct fo_discover_servers_state *state = NULL; + struct tevent_req *req = NULL; + const char **domains = NULL; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct fo_discover_servers_state); + + ret = fo_discover_srv_recv(state, subreq, + &state->dns_domain, + &state->primary_servers, + &state->num_primary_servers); + talloc_zfree(subreq); + if (ret != EOK) { + goto done; + } + + if (strcasecmp(state->dns_domain, state->backup_domain) == 0) { + /* primary domain was unreachable, we will use servers from backup + * domain as primary */ + state->backup_servers = NULL; + state->num_backup_servers = 0; + + ret = EOK; + goto done; + } + + DEBUG(SSSDBG_TRACE_FUNC, ("Looking up backup servers\n")); + + domains = talloc_zero_array(state, const char *, 2); + if (domains == NULL) { + ret = ENOMEM; + goto done; + } + + domains[0] = state->backup_domain; + + subreq = fo_discover_srv_send(state, state->ev, state->resolv_ctx, + state->service, state->protocol, domains); + if (subreq == NULL) { + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, fo_discover_servers_backup_done, req); + + ret = EAGAIN; + +done: + if (ret == EOK) { + tevent_req_done(req); + } else if (ret != EAGAIN) { + tevent_req_error(req, ret); + } + + return; +} + +static void fo_discover_servers_backup_done(struct tevent_req *subreq) +{ + struct fo_discover_servers_state *state = NULL; + struct tevent_req *req = NULL; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct fo_discover_servers_state); + + ret = fo_discover_srv_recv(state, subreq, NULL, + &state->backup_servers, + &state->num_backup_servers); + talloc_zfree(subreq); + if (ret == ERR_SRV_NOT_FOUND || ret == ERR_SRV_LOOKUP_ERROR) { + /* we have successfully fetched primary servers, so we will + * finish the request normally */ + DEBUG(SSSDBG_MINOR_FAILURE, ("Unable to retrieve backup servers " + "[%d]: %s\n", ret, sss_strerror(ret))); + ret = EOK; + } + + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +errno_t fo_discover_servers_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + char **_dns_domain, + struct fo_server_info **_primary_servers, + size_t *_num_primary_servers, + struct fo_server_info **_backup_servers, + size_t *_num_backup_servers) +{ + struct fo_discover_servers_state *state = NULL; + state = tevent_req_data(req, struct fo_discover_servers_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + if (_primary_servers) { + *_primary_servers = talloc_steal(mem_ctx, state->primary_servers); + } + + if (_num_primary_servers) { + *_num_primary_servers = state->num_primary_servers; + } + + if (_backup_servers) { + *_backup_servers = talloc_steal(mem_ctx, state->backup_servers); + } + + if (_num_backup_servers) { + *_num_backup_servers = state->num_backup_servers; + } + + if (_dns_domain) { + *_dns_domain = talloc_steal(mem_ctx, state->dns_domain); + } + + + return EOK; +} + struct fo_resolve_srv_dns_ctx { struct resolv_ctx *resolv_ctx; enum restrict_family family_order; diff --git a/src/providers/fail_over_srv.h b/src/providers/fail_over_srv.h index 4550b09d..0c824f46 100644 --- a/src/providers/fail_over_srv.h +++ b/src/providers/fail_over_srv.h @@ -82,6 +82,22 @@ errno_t fo_discover_srv_recv(TALLOC_CTX *mem_ctx, struct fo_server_info **_servers, size_t *_num_servers); +struct tevent_req *fo_discover_servers_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct resolv_ctx *resolv_ctx, + const char *service, + const char *protocol, + const char *primary_domain, + const char *backup_domain); + +errno_t fo_discover_servers_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + char **_dns_domain, + struct fo_server_info **_primary_servers, + size_t *_num_primary_servers, + struct fo_server_info **_backup_servers, + size_t *_num_backup_servers); + /* Simple SRV lookup plugin */ struct fo_resolve_srv_dns_ctx; |