d98fdd80331e93cd698281341360a3ce3e30afbePavel Březina Pavel Březina <pbrezina@redhat.com>
77d165f0629966db65753a3aee84a8b4971673afPavel Březina Copyright (C) 2013 Red Hat
77d165f0629966db65753a3aee84a8b4971673afPavel Březina This program is free software; you can redistribute it and/or modify
77d165f0629966db65753a3aee84a8b4971673afPavel Březina it under the terms of the GNU General Public License as published by
77d165f0629966db65753a3aee84a8b4971673afPavel Březina the Free Software Foundation; either version 3 of the License, or
77d165f0629966db65753a3aee84a8b4971673afPavel Březina (at your option) any later version.
77d165f0629966db65753a3aee84a8b4971673afPavel Březina This program is distributed in the hope that it will be useful,
77d165f0629966db65753a3aee84a8b4971673afPavel Březina but WITHOUT ANY WARRANTY; without even the implied warranty of
77d165f0629966db65753a3aee84a8b4971673afPavel Březina MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
77d165f0629966db65753a3aee84a8b4971673afPavel Březina GNU General Public License for more details.
77d165f0629966db65753a3aee84a8b4971673afPavel Březina You should have received a copy of the GNU General Public License
77d165f0629966db65753a3aee84a8b4971673afPavel Březina along with this program. If not, see <http://www.gnu.org/licenses/>.
77d165f0629966db65753a3aee84a8b4971673afPavel Březinastatic void fo_discover_srv_done(struct tevent_req *subreq);
77d165f0629966db65753a3aee84a8b4971673afPavel Březinastruct tevent_req *fo_discover_srv_send(TALLOC_CTX *mem_ctx,
77d165f0629966db65753a3aee84a8b4971673afPavel Březina req = tevent_req_create(mem_ctx, &state, struct fo_discover_srv_state);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
77d165f0629966db65753a3aee84a8b4971673afPavel Březina subreq = resolv_discover_srv_send(state, ev, resolv_ctx, service,
77d165f0629966db65753a3aee84a8b4971673afPavel Březina tevent_req_set_callback(subreq, fo_discover_srv_done, req);
77d165f0629966db65753a3aee84a8b4971673afPavel Březinastatic void fo_discover_srv_done(struct tevent_req *subreq)
77d165f0629966db65753a3aee84a8b4971673afPavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina state = tevent_req_data(req, struct fo_discover_srv_state);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "Got answer. Processing...\n");
77d165f0629966db65753a3aee84a8b4971673afPavel Březina /* sort and store the answer */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Could not sort the answers from DNS "
77d165f0629966db65753a3aee84a8b4971673afPavel Březina for (record = reply_list; record != NULL; record = record->next) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "Got %zu servers\n", state->num_servers);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina state->servers = talloc_array(state, struct fo_server_info,
77d165f0629966db65753a3aee84a8b4971673afPavel Březina state->servers[i].host = talloc_steal(state->servers, record->host);
002113460c411cab449c0d7dea824cea1a6c68e7Pavel Březina state->servers[i].priority = record->priority;
77d165f0629966db65753a3aee84a8b4971673afPavel Březinaerrno_t fo_discover_srv_recv(TALLOC_CTX *mem_ctx,
77d165f0629966db65753a3aee84a8b4971673afPavel Březina state = tevent_req_data(req, struct fo_discover_srv_state);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina *_dns_domain = talloc_steal(mem_ctx, state->dns_domain);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina *_servers = talloc_steal(mem_ctx, state->servers);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březinastatic void fo_discover_servers_primary_done(struct tevent_req *subreq);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březinastatic void fo_discover_servers_backup_done(struct tevent_req *subreq);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březinastruct tevent_req *fo_discover_servers_send(TALLOC_CTX *mem_ctx,
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina struct fo_discover_servers_state *state = NULL;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina state->service = talloc_strdup(state, service);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina state->protocol = talloc_strdup(state, protocol);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina state->primary_domain = talloc_strdup(state, primary_domain);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina state->backup_domain = talloc_strdup(state, backup_domain);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina if (state->backup_domain == NULL && backup_domain != NULL) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "Looking up primary servers\n");
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina domains = talloc_zero_array(state, const char *, 3);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina subreq = fo_discover_srv_send(state, ev, resolv_ctx,
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina tevent_req_set_callback(subreq, fo_discover_servers_primary_done, req);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březinastatic void fo_discover_servers_primary_done(struct tevent_req *subreq)
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina struct fo_discover_servers_state *state = NULL;
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina state = tevent_req_data(req, struct fo_discover_servers_state);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_OP_FAILURE, "Unable to retrieve primary servers "
07065554c8963e2aa9fc227a51480135bc4d5130Pavel Březina if (ret != ERR_SRV_NOT_FOUND && ret != ERR_SRV_LOOKUP_ERROR) {
07065554c8963e2aa9fc227a51480135bc4d5130Pavel Březina /* abort on system error */
c7c01428baf8e29a7997cb879cea109d63c4e581Pavel Březina /* if there is no backup domain, we are done */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "No backup domain specified\n");
c7c01428baf8e29a7997cb879cea109d63c4e581Pavel Březina && strcasecmp(state->dns_domain, state->backup_domain) == 0) {
c7c01428baf8e29a7997cb879cea109d63c4e581Pavel Březina /* If there was no error and dns_domain is the same as backup domain,
c7c01428baf8e29a7997cb879cea109d63c4e581Pavel Březina * it means that we were unable to resolve SRV in primary domain, but
c7c01428baf8e29a7997cb879cea109d63c4e581Pavel Březina * SRV from backup domain was resolved and those servers are considered
c7c01428baf8e29a7997cb879cea109d63c4e581Pavel Březina * to be primary. We are done. */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "Looking up backup servers\n");
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina domains = talloc_zero_array(state, const char *, 2);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina subreq = fo_discover_srv_send(state, state->ev, state->resolv_ctx,
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina tevent_req_set_callback(subreq, fo_discover_servers_backup_done, req);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březinastatic void fo_discover_servers_backup_done(struct tevent_req *subreq)
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina struct fo_discover_servers_state *state = NULL;
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina state = tevent_req_data(req, struct fo_discover_servers_state);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina ret = fo_discover_srv_recv(state, subreq, NULL,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_MINOR_FAILURE, "Unable to retrieve backup servers "
07065554c8963e2aa9fc227a51480135bc4d5130Pavel Březina if (ret == ERR_SRV_NOT_FOUND || ret == ERR_SRV_LOOKUP_ERROR) {
07065554c8963e2aa9fc227a51480135bc4d5130Pavel Březina /* we have successfully fetched primary servers, so we will
07065554c8963e2aa9fc227a51480135bc4d5130Pavel Březina * finish the request normally on non system error */
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březinaerrno_t fo_discover_servers_recv(TALLOC_CTX *mem_ctx,
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina struct fo_discover_servers_state *state = NULL;
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina state = tevent_req_data(req, struct fo_discover_servers_state);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina *_primary_servers = talloc_steal(mem_ctx, state->primary_servers);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina *_num_primary_servers = state->num_primary_servers;
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina *_backup_servers = talloc_steal(mem_ctx, state->backup_servers);
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina *_num_backup_servers = state->num_backup_servers;
1099620d87afcee7e239cbb75fd364643c8c1124Pavel Březina *_dns_domain = talloc_steal(mem_ctx, state->dns_domain);
77d165f0629966db65753a3aee84a8b4971673afPavel Březinastatic void fo_resolve_srv_dns_domain_done(struct tevent_req *subreq);
77d165f0629966db65753a3aee84a8b4971673afPavel Březinastatic errno_t fo_resolve_srv_dns_discover(struct tevent_req *req);
77d165f0629966db65753a3aee84a8b4971673afPavel Březinastatic void fo_resolve_srv_dns_done(struct tevent_req *subreq);
77d165f0629966db65753a3aee84a8b4971673afPavel Březinafo_resolve_srv_dns_ctx_init(TALLOC_CTX *mem_ctx,
77d165f0629966db65753a3aee84a8b4971673afPavel Březina ctx = talloc_zero(mem_ctx, struct fo_resolve_srv_dns_ctx);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina ctx->sssd_domain = talloc_strdup(ctx, sssd_domain);
77d165f0629966db65753a3aee84a8b4971673afPavel Březinastruct tevent_req *fo_resolve_srv_dns_send(TALLOC_CTX *mem_ctx,
77d165f0629966db65753a3aee84a8b4971673afPavel Březina struct fo_resolve_srv_dns_state *state = NULL;
77d165f0629966db65753a3aee84a8b4971673afPavel Březina req = tevent_req_create(mem_ctx, &state, struct fo_resolve_srv_dns_state);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
77d165f0629966db65753a3aee84a8b4971673afPavel Březina ctx = talloc_get_type(pvt, struct fo_resolve_srv_dns_ctx);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina if (discovery_domain == NULL && ctx->detected_domain == NULL) {
77d165f0629966db65753a3aee84a8b4971673afPavel Březina /* we will try to detect proper discovery domain */
77d165f0629966db65753a3aee84a8b4971673afPavel Březina subreq = resolv_get_domain_send(state, state->ev, ctx->resolv_ctx,
77d165f0629966db65753a3aee84a8b4971673afPavel Březina tevent_req_set_callback(subreq, fo_resolve_srv_dns_domain_done, req);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina /* we will use either provided or previously detected
77d165f0629966db65753a3aee84a8b4971673afPavel Březina * discovery domain */
77d165f0629966db65753a3aee84a8b4971673afPavel Březinastatic void fo_resolve_srv_dns_domain_done(struct tevent_req *subreq)
77d165f0629966db65753a3aee84a8b4971673afPavel Březina struct fo_resolve_srv_dns_state *state = NULL;
77d165f0629966db65753a3aee84a8b4971673afPavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina state = tevent_req_data(req, struct fo_resolve_srv_dns_state);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina ret = resolv_get_domain_recv(state->ctx, subreq,
77d165f0629966db65753a3aee84a8b4971673afPavel Březinastatic errno_t fo_resolve_srv_dns_discover(struct tevent_req *req)
77d165f0629966db65753a3aee84a8b4971673afPavel Březina struct fo_resolve_srv_dns_state *state = NULL;
77d165f0629966db65753a3aee84a8b4971673afPavel Březina state = tevent_req_data(req, struct fo_resolve_srv_dns_state);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina domains = talloc_zero_array(state, const char *, 3);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina /* we will use detected domain with SSSD domain as fallback */
77d165f0629966db65753a3aee84a8b4971673afPavel Březina domains[0] = talloc_strdup(domains, ctx->detected_domain);
4e748c28dec6fcb732ebe24829f1b750074d488ePavel Březina if (strcasecmp(ctx->detected_domain, ctx->sssd_domain) != 0) {
77d165f0629966db65753a3aee84a8b4971673afPavel Březina domains[1] = talloc_strdup(domains, ctx->sssd_domain);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina /* We will use only discovery domain that was provided via plugin
77d165f0629966db65753a3aee84a8b4971673afPavel Březina * interface. We don't have to dup here because it is already on
77d165f0629966db65753a3aee84a8b4971673afPavel Březina subreq = fo_discover_srv_send(state, state->ev, ctx->resolv_ctx,
77d165f0629966db65753a3aee84a8b4971673afPavel Březina tevent_req_set_callback(subreq, fo_resolve_srv_dns_done, req);
77d165f0629966db65753a3aee84a8b4971673afPavel Březinastatic void fo_resolve_srv_dns_done(struct tevent_req *subreq)
77d165f0629966db65753a3aee84a8b4971673afPavel Březina struct fo_resolve_srv_dns_state *state = NULL;
77d165f0629966db65753a3aee84a8b4971673afPavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina state = tevent_req_data(req, struct fo_resolve_srv_dns_state);
77d165f0629966db65753a3aee84a8b4971673afPavel Březinaerrno_t fo_resolve_srv_dns_recv(TALLOC_CTX *mem_ctx,
77d165f0629966db65753a3aee84a8b4971673afPavel Březina struct fo_resolve_srv_dns_state *state = NULL;
77d165f0629966db65753a3aee84a8b4971673afPavel Březina state = tevent_req_data(req, struct fo_resolve_srv_dns_state);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina *_primary_servers = talloc_steal(mem_ctx, state->servers);
77d165f0629966db65753a3aee84a8b4971673afPavel Březina /* backup servers are not supported by simple srv lookup */