88275cccddf39892e01682b39b02292eb74729bdPavel Březina/*
88275cccddf39892e01682b39b02292eb74729bdPavel Březina Authors:
d98fdd80331e93cd698281341360a3ce3e30afbePavel Březina Pavel Březina <pbrezina@redhat.com>
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina Copyright (C) 2013 Red Hat
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina This program is free software; you can redistribute it and/or modify
88275cccddf39892e01682b39b02292eb74729bdPavel Březina it under the terms of the GNU General Public License as published by
88275cccddf39892e01682b39b02292eb74729bdPavel Březina the Free Software Foundation; either version 3 of the License, or
88275cccddf39892e01682b39b02292eb74729bdPavel Březina (at your option) any later version.
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina This program is distributed in the hope that it will be useful,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina but WITHOUT ANY WARRANTY; without even the implied warranty of
88275cccddf39892e01682b39b02292eb74729bdPavel Březina MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
88275cccddf39892e01682b39b02292eb74729bdPavel Březina GNU General Public License for more details.
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina You should have received a copy of the GNU General Public License
88275cccddf39892e01682b39b02292eb74729bdPavel Březina along with this program. If not, see <http://www.gnu.org/licenses/>.
88275cccddf39892e01682b39b02292eb74729bdPavel Březina*/
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina#include <string.h>
88275cccddf39892e01682b39b02292eb74729bdPavel Březina#include <talloc.h>
88275cccddf39892e01682b39b02292eb74729bdPavel Březina#include <tevent.h>
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina#include "util/util.h"
88275cccddf39892e01682b39b02292eb74729bdPavel Březina#include "resolv/async_resolv.h"
88275cccddf39892e01682b39b02292eb74729bdPavel Březina#include "providers/fail_over_srv.h"
5cd4414fce1e0eb4133dfc6fc828bf25c8a959f9Lukas Slebodnik#include "providers/ipa/ipa_srv.h"
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina#define IPA_DNS_LOCATION "_location"
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březinastruct ipa_srv_plugin_ctx {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct resolv_ctx *resolv_ctx;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina const char *hostname;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina const char *ipa_domain;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina};
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březinastruct ipa_srv_plugin_ctx *
88275cccddf39892e01682b39b02292eb74729bdPavel Březinaipa_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct resolv_ctx *resolv_ctx,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina const char *hostname,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina const char *ipa_domain)
88275cccddf39892e01682b39b02292eb74729bdPavel Březina{
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct ipa_srv_plugin_ctx *ctx = NULL;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina ctx = talloc_zero(mem_ctx, struct ipa_srv_plugin_ctx);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (ctx == NULL) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina return NULL;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina ctx->resolv_ctx = resolv_ctx;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina ctx->hostname = talloc_strdup(ctx, hostname);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (ctx->hostname == NULL) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina goto fail;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina ctx->ipa_domain = talloc_strdup(ctx, ipa_domain);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (ctx->ipa_domain == NULL) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina goto fail;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina return ctx;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březinafail:
88275cccddf39892e01682b39b02292eb74729bdPavel Březina talloc_free(ctx);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina return NULL;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina}
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březinastruct ipa_srv_plugin_state {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina char *dns_domain;
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek uint32_t ttl;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct fo_server_info *primary_servers;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina size_t num_primary_servers;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct fo_server_info *backup_servers;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina size_t num_backup_servers;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina};
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březinastatic void ipa_srv_plugin_done(struct tevent_req *subreq);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina/* If IPA server supports sites, we will use
88275cccddf39892e01682b39b02292eb74729bdPavel Březina * _locations.hostname.discovery_domain for primary servers and
88275cccddf39892e01682b39b02292eb74729bdPavel Březina * discovery_domain for backup servers. If the server does not support sites or
88275cccddf39892e01682b39b02292eb74729bdPavel Březina * client's SRV record is not found, we will use the latter for primary
88275cccddf39892e01682b39b02292eb74729bdPavel Březina * servers, setting backup servers to NULL */
88275cccddf39892e01682b39b02292eb74729bdPavel Březinastruct tevent_req *ipa_srv_plugin_send(TALLOC_CTX *mem_ctx,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct tevent_context *ev,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina const char *service,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina const char *protocol,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina const char *discovery_domain,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina void *pvt)
88275cccddf39892e01682b39b02292eb74729bdPavel Březina{
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct ipa_srv_plugin_state *state = NULL;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct ipa_srv_plugin_ctx *ctx = NULL;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct tevent_req *req = NULL;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct tevent_req *subreq = NULL;
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina const char *primary_domain = NULL;
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina const char *backup_domain = NULL;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina errno_t ret;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina req = tevent_req_create(mem_ctx, &state,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct ipa_srv_plugin_state);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (req == NULL) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
88275cccddf39892e01682b39b02292eb74729bdPavel Březina return NULL;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina ctx = talloc_get_type(pvt, struct ipa_srv_plugin_ctx);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (ctx == NULL) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina ret = EINVAL;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina goto immediately;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (discovery_domain != NULL) {
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina backup_domain = talloc_strdup(state, discovery_domain);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina } else {
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina backup_domain = talloc_strdup(state, ctx->ipa_domain);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina if (backup_domain == NULL) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina ret = ENOMEM;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina goto immediately;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (strchr(ctx->hostname, '.') == NULL) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina /* not FQDN, append domain name */
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina primary_domain = talloc_asprintf(state, IPA_DNS_LOCATION ".%s.%s",
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina ctx->hostname, backup_domain);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina } else {
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina primary_domain = talloc_asprintf(state, IPA_DNS_LOCATION ".%s",
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina ctx->hostname);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina if (primary_domain == NULL) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina ret = ENOMEM;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina goto immediately;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "About to discover primary and "
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "backup servers\n");
e653ff7a341dc8003dc12179d983f513c9789a5dPavel Březina
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina subreq = fo_discover_servers_send(state, ev, ctx->resolv_ctx, service,
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina protocol, primary_domain, backup_domain);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (subreq == NULL) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina ret = ENOMEM;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina goto immediately;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina tevent_req_set_callback(subreq, ipa_srv_plugin_done, req);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina return req;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březinaimmediately:
88275cccddf39892e01682b39b02292eb74729bdPavel Březina tevent_req_error(req, ret);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina tevent_req_post(req, ev);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina return req;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina}
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březinastatic void ipa_srv_plugin_done(struct tevent_req *subreq)
88275cccddf39892e01682b39b02292eb74729bdPavel Březina{
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct ipa_srv_plugin_state *state = NULL;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct tevent_req *req = NULL;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina errno_t ret;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina state = tevent_req_data(req, struct ipa_srv_plugin_state);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina ret = fo_discover_servers_recv(state, subreq, &state->dns_domain,
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek &state->ttl,
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina &state->primary_servers,
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina &state->num_primary_servers,
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina &state->backup_servers,
9894b0fabc1720bd083538c2d818fcd88409cad7Pavel Březina &state->num_backup_servers);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina talloc_zfree(subreq);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (ret != EOK) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina tevent_req_error(req, ret);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina return;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "Got %zu primary and %zu backup servers\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov state->num_primary_servers, state->num_backup_servers);
e653ff7a341dc8003dc12179d983f513c9789a5dPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina tevent_req_done(req);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina}
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březinaerrno_t ipa_srv_plugin_recv(TALLOC_CTX *mem_ctx,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct tevent_req *req,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina char **_dns_domain,
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek uint32_t *_ttl,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct fo_server_info **_primary_servers,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina size_t *_num_primary_servers,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct fo_server_info **_backup_servers,
88275cccddf39892e01682b39b02292eb74729bdPavel Březina size_t *_num_backup_servers)
88275cccddf39892e01682b39b02292eb74729bdPavel Březina{
88275cccddf39892e01682b39b02292eb74729bdPavel Březina struct ipa_srv_plugin_state *state = NULL;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina state = tevent_req_data(req, struct ipa_srv_plugin_state);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina TEVENT_REQ_RETURN_ON_ERROR(req);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (_primary_servers) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina *_primary_servers = talloc_steal(mem_ctx, state->primary_servers);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (_num_primary_servers) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina *_num_primary_servers = state->num_primary_servers;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (_backup_servers) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina *_backup_servers = talloc_steal(mem_ctx, state->backup_servers);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (_num_backup_servers) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina *_num_backup_servers = state->num_backup_servers;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (_dns_domain) {
88275cccddf39892e01682b39b02292eb74729bdPavel Březina *_dns_domain = talloc_steal(mem_ctx, state->dns_domain);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek if (_ttl) {
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek *_ttl = state->ttl;
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek }
88275cccddf39892e01682b39b02292eb74729bdPavel Březina
88275cccddf39892e01682b39b02292eb74729bdPavel Březina return EOK;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina}