summaryrefslogtreecommitdiffstats
path: root/src/providers
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2010-02-22 10:28:26 +0100
committerStephen Gallagher <sgallagh@redhat.com>2010-02-22 12:54:53 -0500
commite0bb119bdc1549d731f371202428c0cb667d3388 (patch)
tree3c4edcfb90558ca95a36c6edafdf9a98f35474d0 /src/providers
parent48dbc3c447449b9bb1a9b7c839b9471ef4f547bf (diff)
downloadsssd-e0bb119bdc1549d731f371202428c0cb667d3388.tar.gz
sssd-e0bb119bdc1549d731f371202428c0cb667d3388.tar.xz
sssd-e0bb119bdc1549d731f371202428c0cb667d3388.zip
Restrict family lookups
Adds a new option that tells resolver which address family to prefer or use exclusively. Fixes: #404
Diffstat (limited to 'src/providers')
-rw-r--r--src/providers/data_provider_fo.c52
-rw-r--r--src/providers/fail_over.c25
-rw-r--r--src/providers/fail_over.h22
3 files changed, 84 insertions, 15 deletions
diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
index 7d0240489..482f74446 100644
--- a/src/providers/data_provider_fo.c
+++ b/src/providers/data_provider_fo.c
@@ -53,9 +53,47 @@ struct be_failover_ctx {
struct be_svc_data *svcs;
};
+static int be_fo_get_options(TALLOC_CTX *mem_ctx, struct be_ctx *ctx,
+ struct fo_options *opts)
+{
+ char *str_opt;
+ int ret;
+
+ /* todo get timeout from configuration */
+ opts->retry_timeout = 30;
+
+ ret = confdb_get_string(ctx->cdb, mem_ctx, ctx->conf_path,
+ CONFDB_DOMAIN_FAMILY_ORDER,
+ "ipv4_first", &str_opt);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ DEBUG(7, ("Lookup order: %s\n", str_opt));
+
+ if (strcasecmp(str_opt, "ipv4_first") == 0) {
+ opts->family_order = IPV4_FIRST;
+ } else if (strcasecmp(str_opt, "ipv4_only") == 0) {
+ opts->family_order = IPV4_ONLY;
+ } else if (strcasecmp(str_opt, "ipv6_first") == 0) {
+ opts->family_order = IPV6_FIRST;
+ } else if (strcasecmp(str_opt, "ipv6_only") == 0) {
+ opts->family_order = IPV6_ONLY;
+ } else {
+ DEBUG(1, ("Unknown value for option %s: %s\n",
+ CONFDB_DOMAIN_FAMILY_ORDER, str_opt));
+ talloc_free(str_opt);
+ return EINVAL;
+ }
+
+ talloc_free(str_opt);
+ return EOK;
+}
+
int be_init_failover(struct be_ctx *ctx)
{
int ret;
+ struct fo_options fopts;
if (ctx->be_fo != NULL) {
return EOK;
@@ -72,8 +110,13 @@ int be_init_failover(struct be_ctx *ctx)
return ret;
}
- /* todo get timeout from configuration */
- ctx->be_fo->fo_ctx = fo_context_init(ctx->be_fo, 30);
+ ret = be_fo_get_options(ctx->be_fo, ctx, &fopts);
+ if (ret != EOK) {
+ talloc_zfree(ctx->be_fo);
+ return ret;
+ }
+
+ ctx->be_fo->fo_ctx = fo_context_init(ctx->be_fo, &fopts);
if (!ctx->be_fo->fo_ctx) {
talloc_zfree(ctx->be_fo);
return ENOMEM;
@@ -250,7 +293,9 @@ struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
state->attempts = 0;
subreq = fo_resolve_service_send(state, ev,
- ctx->be_fo->resolv, svc->fo_service);
+ ctx->be_fo->resolv,
+ ctx->be_fo->fo_ctx,
+ svc->fo_service);
if (!subreq) {
talloc_zfree(req);
return NULL;
@@ -305,6 +350,7 @@ static void be_resolve_server_done(struct tevent_req *subreq)
DEBUG(6, ("Trying with the next one!\n"));
subreq = fo_resolve_service_send(state, state->ev,
state->ctx->be_fo->resolv,
+ state->ctx->be_fo->fo_ctx,
state->svc->fo_service);
if (!subreq) {
tevent_req_error(req, ENOMEM);
diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c
index 7560b89ee..54ad0329e 100644
--- a/src/providers/fail_over.c
+++ b/src/providers/fail_over.c
@@ -45,8 +45,7 @@ struct fo_ctx {
struct fo_service *service_list;
struct server_common *server_common_list;
- /* Settings. */
- time_t retry_timeout;
+ struct fo_options *opts;
};
struct fo_service {
@@ -99,7 +98,7 @@ struct status {
};
struct fo_ctx *
-fo_context_init(TALLOC_CTX *mem_ctx, time_t retry_timeout)
+fo_context_init(TALLOC_CTX *mem_ctx, struct fo_options *opts)
{
struct fo_ctx *ctx;
@@ -108,11 +107,17 @@ fo_context_init(TALLOC_CTX *mem_ctx, time_t retry_timeout)
DEBUG(1, ("No memory\n"));
return NULL;
}
+ ctx->opts = talloc_zero(ctx, struct fo_options);
+ if (ctx->opts == NULL) {
+ DEBUG(1, ("No memory\n"));
+ return NULL;
+ }
- ctx->retry_timeout = retry_timeout;
+ ctx->opts->retry_timeout = opts->retry_timeout;
+ ctx->opts->family_order = opts->family_order;
DEBUG(3, ("Created new fail over context, retry timeout is %d\n",
- retry_timeout));
+ ctx->opts->retry_timeout));
return ctx;
}
@@ -166,7 +171,7 @@ get_server_status(struct fo_server *server)
DEBUG(7, ("Status of server '%s' is '%s'\n", SERVER_NAME(server),
str_server_status(server->common->server_status)));
- timeout = server->service->ctx->retry_timeout;
+ timeout = server->service->ctx->opts->retry_timeout;
if (timeout != 0 && server->common->server_status == SERVER_NOT_WORKING) {
gettimeofday(&tv, NULL);
if (STATUS_DIFF(server->common, tv) > timeout) {
@@ -193,7 +198,7 @@ get_port_status(struct fo_server *server)
DEBUG(7, ("Port status of port %d for server '%s' is '%s'\n", server->port,
SERVER_NAME(server), str_port_status(server->port_status)));
- timeout = server->service->ctx->retry_timeout;
+ timeout = server->service->ctx->opts->retry_timeout;
if (timeout != 0 && server->port_status == PORT_NOT_WORKING) {
gettimeofday(&tv, NULL);
if (STATUS_DIFF(server, tv) > timeout) {
@@ -467,7 +472,8 @@ static void fo_resolve_service_done(struct tevent_req *subreq);
struct tevent_req *
fo_resolve_service_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- struct resolv_ctx *resolv, struct fo_service *service)
+ struct resolv_ctx *resolv, struct fo_ctx *ctx,
+ struct fo_service *service)
{
int ret;
struct fo_server *server;
@@ -498,7 +504,8 @@ fo_resolve_service_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
switch (get_server_status(server)) {
case SERVER_NAME_NOT_RESOLVED: /* Request name resolution. */
subreq = resolv_gethostbyname_send(server->common, ev, resolv,
- server->common->name);
+ server->common->name,
+ ctx->opts->family_order);
if (subreq == NULL) {
ret = ENOMEM;
goto done;
diff --git a/src/providers/fail_over.h b/src/providers/fail_over.h
index f11848321..ffcd06877 100644
--- a/src/providers/fail_over.h
+++ b/src/providers/fail_over.h
@@ -28,9 +28,10 @@
#include <stdbool.h>
#include <talloc.h>
+#include "resolv/async_resolv.h"
+
/* Some forward declarations that don't have to do anything with fail over. */
struct hostent;
-struct resolv_ctx;
struct tevent_context;
struct tevent_req;
@@ -53,12 +54,26 @@ struct fo_service;
struct fo_server;
/*
- * Create a new fail over context. The 'retry_timeout' argument specifies the
+ * Failover settings.
+ *
+ * The 'retry_timeout' member specifies the
* duration in seconds of how long a server or port will be considered
* non-working after being marked as such.
+ *
+ * The family_order member specifies the order of address families to
+ * try when looking up the service.
+ */
+struct fo_options {
+ time_t retry_timeout;
+ enum restrict_family family_order;
+};
+
+/*
+ * Create a new fail over context based on options passed in the
+ * opts parameter
*/
struct fo_ctx *fo_context_init(TALLOC_CTX *mem_ctx,
- time_t retry_timeout);
+ struct fo_options *opts);
/*
* Create a new service structure for 'ctx', saving it to the location pointed
@@ -94,6 +109,7 @@ int fo_add_server(struct fo_service *service,
struct tevent_req *fo_resolve_service_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct resolv_ctx *resolv,
+ struct fo_ctx *ctx,
struct fo_service *service);
int fo_resolve_service_recv(struct tevent_req *req,