diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c index 7f94407c538..6d3deef1f9c 100644 --- a/src/providers/fail_over.c +++ b/src/providers/fail_over.c @@ -268,6 +268,8 @@ str_server_status(enum server_status status) return "working"; case SERVER_NOT_WORKING: return "not working"; + case SERVER_SECOND_FAMILY: + return "second family"; } return "unknown server status"; @@ -481,6 +483,23 @@ service_destructor(struct fo_service *service) return 0; } +static int +try_another_family(struct fo_server *server, enum restrict_family family_order) { + if (server == NULL || server->common == NULL || server->common->rhostent == NULL) { + return 0; + } + + if (server->common->rhostent->family == AF_INET && family_order == IPV4_FIRST) { + return 1; + } + + if (server->common->rhostent->family == AF_INET6 && family_order == IPV6_FIRST) { + return 1; + } + + return 0; +} + int fo_new_service(struct fo_ctx *ctx, const char *name, datacmp_fn user_data_cmp, @@ -937,6 +956,11 @@ get_first_server_entity(struct fo_service *service, struct fo_server **_server) if (service_works(server) && fo_is_server_primary(server)) { goto done; } + if (fo_is_server_primary(server) && try_another_family(server, service->ctx->opts->family_order) ) { + /* set server state shomehow ? */ + fo_set_server_status(server, SERVER_SECOND_FAMILY); + goto done; + } service->active_server = NULL; } @@ -1193,13 +1217,26 @@ fo_resolve_service_server(struct tevent_req *req) struct resolve_service_state); struct tevent_req *subreq; int ret; + enum restrict_family family_restriction; + family_restriction = state->fo_ctx->opts->family_order; switch (get_server_status(state->server)) { + case SERVER_SECOND_FAMILY: + switch (family_restriction) { + case IPV4_FIRST: + family_restriction = IPV6_ONLY; + break; + case IPV6_FIRST: + family_restriction = IPV4_ONLY; + break; + default: + break; + } case SERVER_NAME_NOT_RESOLVED: /* Request name resolution. */ subreq = resolv_gethostbyname_send(state->server->common, state->ev, state->resolv, state->server->common->name, - state->fo_ctx->opts->family_order, + family_restriction, default_host_dbs); if (subreq == NULL) { tevent_req_error(req, ENOMEM); diff --git a/src/providers/fail_over.h b/src/providers/fail_over.h index 924a09970b1..642965bbe69 100644 --- a/src/providers/fail_over.h +++ b/src/providers/fail_over.h @@ -49,6 +49,7 @@ enum server_status { SERVER_NAME_NOT_RESOLVED, /* We didn't yet resolved the host name. */ SERVER_RESOLVING_NAME, /* Name resolving is in progress. */ SERVER_NAME_RESOLVED, /* We resolved the host name but didn't try to connect. */ + SERVER_SECOND_FAMILY, /* We should try second protocol */ SERVER_WORKING, /* We successfully connected to the server. */ SERVER_NOT_WORKING /* We tried and failed to connect to the server. */ }; diff --git a/src/providers/fail_over_srv.c b/src/providers/fail_over_srv.c index 5f474eaee4f..be68761a1de 100644 --- a/src/providers/fail_over_srv.c +++ b/src/providers/fail_over_srv.c @@ -440,6 +440,7 @@ struct fo_resolve_srv_dns_ctx { char *hostname; char *sssd_domain; char *detected_domain; + bool last_family_tried; }; struct fo_resolve_srv_dns_state {