Skip to content

Commit

Permalink
failover: Make failover work over IP families
Browse files Browse the repository at this point in the history
Originally the option ipv4_first and ipv6_first was taken into account
when resolving IP address.

When both families are resolvable but the primary is blocked on
firewall, the SSSD must switch to the socondary family.
  • Loading branch information
thalman committed Oct 18, 2024
1 parent 1184397 commit cfb8d91
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 1 deletion.
39 changes: 38 additions & 1 deletion src/providers/fail_over.c
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/providers/fail_over.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
};
Expand Down
1 change: 1 addition & 0 deletions src/providers/fail_over_srv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit cfb8d91

Please sign in to comment.