fail_over.c revision 63d85fff72563cb913287ab7785c551fa98fc35d
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder/*
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder SSSD
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
e6d40133bc9f858308654afb1262b8b483ec5922Till Mossakowski Fail over helper functions.
2725abe920f91de62ae5c0b7230c1627cccf5fabChristian Maeder
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescu Authors:
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder Martin Nagy <mnagy@redhat.com>
3f69b6948966979163bdfe8331c38833d5d90ecdChristian Maeder Jakub Hrozek <jhrozek@redhat.com>
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder Copyright (C) Red Hat, Inc 2010
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
f3a94a197960e548ecd6520bb768cb0d547457bbChristian Maeder This program is free software; you can redistribute it and/or modify
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder it under the terms of the GNU General Public License as published by
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder the Free Software Foundation; either version 3 of the License, or
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder (at your option) any later version.
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder This program is distributed in the hope that it will be useful,
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder but WITHOUT ANY WARRANTY; without even the implied warranty of
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder GNU General Public License for more details.
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder You should have received a copy of the GNU General Public License
ea5ccb1c6e89486a54e1f4bd95840147e96093edChristian Maeder along with this program. If not, see <http://www.gnu.org/licenses/>.
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder*/
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder
85e1d54a475bfc30b3eac5ae6c5e42a2d7e93f10Christian Maeder#include <sys/time.h>
85e1d54a475bfc30b3eac5ae6c5e42a2d7e93f10Christian Maeder
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <errno.h>
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <stdbool.h>
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <strings.h>
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <talloc.h>
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include "util/dlinklist.h"
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include "util/refcount.h"
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include "util/util.h"
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include "providers/fail_over.h"
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include "resolv/async_resolv.h"
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#define STATUS_DIFF(p, now) ((now).tv_sec - (p)->last_status_change.tv_sec)
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#define SERVER_NAME(s) ((s)->common ? (s)->common->name : "(no name)")
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#define DEFAULT_PORT_STATUS PORT_NEUTRAL
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#define DEFAULT_SERVER_STATUS SERVER_NAME_NOT_RESOLVED
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder#define DEFAULT_SRV_STATUS SRV_NEUTRAL
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder
a461314c811f4187dff85c8be079a41b2f13f176Christian Maeder#ifndef HOSTNAME_RESOLVE_TIMEOUT
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#define HOSTNAME_RESOLVE_TIMEOUT 7200
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder#endif /* HOSTNAME_RESOLVE_TIMEOUT */
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maederenum srv_lookup_status {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder SRV_NEUTRAL, /* We didn't try this SRV lookup yet */
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder SRV_RESOLVED, /* This SRV lookup is resolved */
f39b8dd9651dfcc38b06191cda23cacbfc298323Christian Maeder SRV_RESOLVE_ERROR, /* Could not resolve this SRV lookup */
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder SRV_EXPIRED /* Need to refresh the SRV query */
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder};
3a9d784341454573b50b32fa1b494e7418df3086Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederstruct fo_ctx {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct fo_service *service_list;
9d6562465b41f17c7967d4e5678f34811d958cb2Christian Maeder struct server_common *server_common_list;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct fo_options *opts;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder};
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maederstruct fo_service {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct fo_service *prev;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct fo_service *next;
38c817b94e0a5b1ae94178b1075c187e07bcc5e1Christian Maeder
38c817b94e0a5b1ae94178b1075c187e07bcc5e1Christian Maeder struct fo_ctx *ctx;
38c817b94e0a5b1ae94178b1075c187e07bcc5e1Christian Maeder char *name;
38c817b94e0a5b1ae94178b1075c187e07bcc5e1Christian Maeder struct fo_server *active_server;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct fo_server *last_tried_server;
2353f65833a3da763392f771223250cd50b8d873Christian Maeder struct fo_server *server_list;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder};
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maederstruct fo_server {
cb2044812811d66efe038d914966e04290be93faChristian Maeder struct fo_server *prev;
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder struct fo_server *next;
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder void *user_data;
d81905a5b924415c524d702df26204683c82c12eChristian Maeder int port;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder int port_status;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct srv_data *srv_data;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct fo_service *service;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct timeval last_status_change;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct server_common *common;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder};
cb2044812811d66efe038d914966e04290be93faChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederstruct server_common {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder REFCOUNT_COMMON;
083bc1972a66d73749760eab3a90bf4eb9ca7951Christian Maeder
0ae7a79e865d4a6022d705d160530682b3c1f825Christian Maeder struct fo_ctx *ctx;
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder
083bc1972a66d73749760eab3a90bf4eb9ca7951Christian Maeder struct server_common *prev;
6352f3c31da3043783a13be6594aacb2147378baRazvan Pascanu struct server_common *next;
fefee7e1dee1ee5f0768a03a4abae88d1ca2c3fdRazvan Pascanu
b324cda6178c49ddeead3ce62b832ccf644cbcabRazvan Pascanu char *name;
fefee7e1dee1ee5f0768a03a4abae88d1ca2c3fdRazvan Pascanu struct hostent *hostent;
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder struct resolve_service_request *request_list;
966519955f5f7111abac20118563132b9dd41165Christian Maeder int server_status;
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder struct timeval last_status_change;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder};
33fcc19ef2b59493b4e91eebf701df95fd230765Christian Maeder
33fcc19ef2b59493b4e91eebf701df95fd230765Christian Maederstruct srv_data {
33fcc19ef2b59493b4e91eebf701df95fd230765Christian Maeder char *dns_domain;
8865728716566f42fa73e7e0bc080ba3225df764Christian Maeder char *discovery_domain;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder char *sssd_domain;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder char *proto;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder char *srv;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
2360728d4185c0c04279c999941c64d36626af79Christian Maeder struct fo_server *meta;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder int srv_lookup_status;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct timeval last_status_change;
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder};
fdac680252d7347858bd67b4c2a2aaa52e623815Christian Maeder
fdac680252d7347858bd67b4c2a2aaa52e623815Christian Maederstruct resolve_service_request {
a9e804dbec424ec36e34bab955cbe90edac5baa6Christian Maeder struct resolve_service_request *prev;
f8cc2399c16fcda7e3bf9d901a0de0cc8a455f86Ewaryst Schulz struct resolve_service_request *next;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b76d27eba526ecac2a20400fa505ec5c642ae7d2Dominik Luecke struct server_common *server_common;
b76d27eba526ecac2a20400fa505ec5c642ae7d2Dominik Luecke struct tevent_req *req;
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich};
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettichstruct status {
2353f65833a3da763392f771223250cd50b8d873Christian Maeder int value;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct timeval last_change;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder};
2353f65833a3da763392f771223250cd50b8d873Christian Maeder
2353f65833a3da763392f771223250cd50b8d873Christian Maederstruct fo_ctx *
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederfo_context_init(TALLOC_CTX *mem_ctx, struct fo_options *opts)
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder{
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct fo_ctx *ctx;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder ctx = talloc_zero(mem_ctx, struct fo_ctx);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (ctx == NULL) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DEBUG(1, ("No memory\n"));
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return NULL;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder ctx->opts = talloc_zero(ctx, struct fo_options);
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder if (ctx->opts == NULL) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DEBUG(1, ("No memory\n"));
cb2044812811d66efe038d914966e04290be93faChristian Maeder return NULL;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder ctx->opts->srv_retry_timeout = opts->srv_retry_timeout;
8d780c893d6df5dab3dcc7d8444b7517f6547f11Christian Maeder ctx->opts->retry_timeout = opts->retry_timeout;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder ctx->opts->family_order = opts->family_order;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DEBUG(3, ("Created new fail over context, retry timeout is %d\n",
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder ctx->opts->retry_timeout));
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return ctx;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder}
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederstatic const char *
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederstr_port_status(enum port_status status)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder{
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder switch (status) {
966519955f5f7111abac20118563132b9dd41165Christian Maeder case PORT_NEUTRAL:
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder return "neutral";
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder case PORT_WORKING:
d96bfd1d7a4595bfff87771b91797330fa939455Christian Maeder return "working";
d96bfd1d7a4595bfff87771b91797330fa939455Christian Maeder case PORT_NOT_WORKING:
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder return "not working";
d27b1887e61f1dc53d77c37f59dbf5019242a686Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return "unknown port status";
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder}
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederstatic const char *
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederstr_srv_data_status(enum srv_lookup_status status)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder{
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder switch (status) {
2360728d4185c0c04279c999941c64d36626af79Christian Maeder case SRV_NEUTRAL:
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return "neutral";
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder case SRV_RESOLVED:
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder return "resolved";
2360728d4185c0c04279c999941c64d36626af79Christian Maeder case SRV_RESOLVE_ERROR:
2360728d4185c0c04279c999941c64d36626af79Christian Maeder return "not resolved";
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder case SRV_EXPIRED:
2360728d4185c0c04279c999941c64d36626af79Christian Maeder return "expired";
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
8d780c893d6df5dab3dcc7d8444b7517f6547f11Christian Maeder
2360728d4185c0c04279c999941c64d36626af79Christian Maeder return "unknown SRV lookup status";
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder}
2360728d4185c0c04279c999941c64d36626af79Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederstatic const char *
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederstr_server_status(enum server_status status)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder{
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder switch (status) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder case SERVER_NAME_NOT_RESOLVED:
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return "name not resolved";
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder case SERVER_RESOLVING_NAME:
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder return "resolving name";
966519955f5f7111abac20118563132b9dd41165Christian Maeder case SERVER_NAME_RESOLVED:
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder return "name resolved";
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder case SERVER_WORKING:
d96bfd1d7a4595bfff87771b91797330fa939455Christian Maeder return "working";
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder case SERVER_NOT_WORKING:
d27b1887e61f1dc53d77c37f59dbf5019242a686Christian Maeder return "not working";
2360728d4185c0c04279c999941c64d36626af79Christian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return "unknown server status";
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder}
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maederint fo_is_srv_lookup(struct fo_server *s)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder{
cb2044812811d66efe038d914966e04290be93faChristian Maeder return s && s->srv_data;
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder}
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederstatic char *
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederget_srv_query(TALLOC_CTX *mem_ctx, struct fo_server *server)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder{
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder char *query;
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder if (!fo_is_srv_lookup(server)) {
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder return NULL;
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder }
33fcc19ef2b59493b4e91eebf701df95fd230765Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder query = talloc_asprintf(mem_ctx, "_%s._%s.%s", server->srv_data->srv,
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder server->srv_data->proto,
8bb80c9684e905de8dcfcfb1291542677e7d77b6Christian Maeder server->srv_data->dns_domain);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return query;
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder}
966519955f5f7111abac20118563132b9dd41165Christian Maeder
8bb80c9684e905de8dcfcfb1291542677e7d77b6Christian Maederstatic struct fo_server *
8bb80c9684e905de8dcfcfb1291542677e7d77b6Christian Maedercollapse_srv_lookup(struct fo_server *server)
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder{
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder struct fo_server *tmp, *meta;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder meta = server->srv_data->meta;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder DEBUG(4, ("Need to refresh SRV lookup for domain %s\n", meta->srv_data->dns_domain))
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (server != meta) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder while (server->prev && server->prev->srv_data == meta->srv_data) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder tmp = server->prev;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DLIST_REMOVE(server->service->server_list, tmp);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder talloc_zfree(tmp);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder while (server->next && server->next->srv_data == meta->srv_data) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder tmp = server->next;
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder DLIST_REMOVE(server->service->server_list, tmp);
966519955f5f7111abac20118563132b9dd41165Christian Maeder talloc_zfree(tmp);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (server == server->service->active_server) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder server->service->active_server = NULL;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
cb2044812811d66efe038d914966e04290be93faChristian Maeder if (server == server->service->last_tried_server) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder server->service->last_tried_server = meta;
8d780c893d6df5dab3dcc7d8444b7517f6547f11Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder /* add back the meta server to denote SRV lookup */
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DLIST_ADD_AFTER(server->service->server_list, meta, server);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DLIST_REMOVE(server->service->server_list, server);
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder talloc_zfree(server);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder meta->srv_data->srv_lookup_status = SRV_NEUTRAL;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder meta->srv_data->last_status_change.tv_sec = 0;
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder return meta;
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder}
33fcc19ef2b59493b4e91eebf701df95fd230765Christian Maeder
d27b1887e61f1dc53d77c37f59dbf5019242a686Christian Maederstatic enum srv_lookup_status
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederget_srv_data_status(struct srv_data *data)
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder{
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct timeval tv;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder time_t timeout;
f39b8dd9651dfcc38b06191cda23cacbfc298323Christian Maeder
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maeder timeout = data->meta->service->ctx->opts->srv_retry_timeout;
2360728d4185c0c04279c999941c64d36626af79Christian Maeder gettimeofday(&tv, NULL);
2360728d4185c0c04279c999941c64d36626af79Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (timeout && STATUS_DIFF(data, tv) > timeout) {
f39b8dd9651dfcc38b06191cda23cacbfc298323Christian Maeder switch(data->srv_lookup_status) {
2360728d4185c0c04279c999941c64d36626af79Christian Maeder case SRV_EXPIRED:
2360728d4185c0c04279c999941c64d36626af79Christian Maeder case SRV_NEUTRAL:
2360728d4185c0c04279c999941c64d36626af79Christian Maeder break;
d81905a5b924415c524d702df26204683c82c12eChristian Maeder case SRV_RESOLVED:
2360728d4185c0c04279c999941c64d36626af79Christian Maeder data->srv_lookup_status = SRV_EXPIRED;
f39b8dd9651dfcc38b06191cda23cacbfc298323Christian Maeder data->last_status_change.tv_sec = 0;
8d780c893d6df5dab3dcc7d8444b7517f6547f11Christian Maeder break;
2360728d4185c0c04279c999941c64d36626af79Christian Maeder case SRV_RESOLVE_ERROR:
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder data->srv_lookup_status = SRV_NEUTRAL;
966519955f5f7111abac20118563132b9dd41165Christian Maeder data->last_status_change.tv_sec = 0;
2360728d4185c0c04279c999941c64d36626af79Christian Maeder break;
2360728d4185c0c04279c999941c64d36626af79Christian Maeder default:
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder DEBUG(1, ("Unknown state for SRV server!\n"));
2360728d4185c0c04279c999941c64d36626af79Christian Maeder }
f39b8dd9651dfcc38b06191cda23cacbfc298323Christian Maeder }
2360728d4185c0c04279c999941c64d36626af79Christian Maeder
2360728d4185c0c04279c999941c64d36626af79Christian Maeder return data->srv_lookup_status;
2360728d4185c0c04279c999941c64d36626af79Christian Maeder}
2360728d4185c0c04279c999941c64d36626af79Christian Maeder
2360728d4185c0c04279c999941c64d36626af79Christian Maederstatic void
d27b1887e61f1dc53d77c37f59dbf5019242a686Christian Maederset_srv_data_status(struct srv_data *data, enum srv_lookup_status status)
8994ef587ce7c7c39ddd20f0f7e4575838a6694aChristian Maeder{
33fcc19ef2b59493b4e91eebf701df95fd230765Christian Maeder DEBUG(4, ("Marking SRV lookup of service '%s' as '%s'\n",
2360728d4185c0c04279c999941c64d36626af79Christian Maeder data->meta->service->name, str_srv_data_status(status)));
2360728d4185c0c04279c999941c64d36626af79Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder gettimeofday(&data->last_status_change, NULL);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder data->srv_lookup_status = status;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder}
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder/*
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * This function will return the status of the server. If the status was
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * last updated a long time ago, we will first reset the status.
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder */
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederstatic enum server_status
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederget_server_status(struct fo_server *server)
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder{
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder struct timeval tv;
d56ece59c372cb887355825901222b9f3377f7e6Thiemo Wiedemeyer time_t timeout;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (server->common == NULL)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return SERVER_NAME_RESOLVED;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
2360728d4185c0c04279c999941c64d36626af79Christian Maeder DEBUG(7, ("Status of server '%s' is '%s'\n", SERVER_NAME(server),
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder str_server_status(server->common->server_status)));
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder timeout = server->service->ctx->opts->retry_timeout;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder gettimeofday(&tv, NULL);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (timeout != 0 && server->common->server_status == SERVER_NOT_WORKING) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (STATUS_DIFF(server->common, tv) > timeout) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DEBUG(4, ("Reseting the server status of '%s'\n",
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder SERVER_NAME(server)));
76d027be764e2ff61bef959efb3ac8f56499e646Christian Maeder server->common->server_status = SERVER_NAME_NOT_RESOLVED;
9f85afecbd79b3df5a0bb17bd28cd0b288dc3213Kristina Sojakova server->common->last_status_change.tv_sec = tv.tv_sec;
a166da43d4e8f9dfa7a2651d033c6bea02627ca6Mihai Codescu }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
63da71bfb4226f504944b293fb77177ebcaea7d4Ewaryst Schulz if (STATUS_DIFF(server->common, tv) > HOSTNAME_RESOLVE_TIMEOUT) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DEBUG(4, ("Hostname resolution expired, reseting the server "
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder "status of '%s'\n", SERVER_NAME(server)));
af6e92e4a9ca308f928f9909acee115f801c5db5Ewaryst Schulz fo_set_server_status(server, SERVER_NAME_NOT_RESOLVED);
4692b8b63985ab174478d389e20a544054e09ce8Karl Luc }
d95f77e19ae3835318a6340d872193fbb3cbab05Karl Luc
26b1c101b72100b69045effdfaab3889de6c8c93Christian Maeder return server->common->server_status;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder}
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder/*
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * This function will return the status of the service. If the status was
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * last updated a long time ago, we will first reset the status.
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder */
2360728d4185c0c04279c999941c64d36626af79Christian Maederstatic enum port_status
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederget_port_status(struct fo_server *server)
63da71bfb4226f504944b293fb77177ebcaea7d4Ewaryst Schulz{
76d027be764e2ff61bef959efb3ac8f56499e646Christian Maeder struct timeval tv;
9f85afecbd79b3df5a0bb17bd28cd0b288dc3213Kristina Sojakova time_t timeout;
a166da43d4e8f9dfa7a2651d033c6bea02627ca6Mihai Codescu
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DEBUG(7, ("Port status of port %d for server '%s' is '%s'\n", server->port,
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder SERVER_NAME(server), str_port_status(server->port_status)));
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder timeout = server->service->ctx->opts->retry_timeout;
af6e92e4a9ca308f928f9909acee115f801c5db5Ewaryst Schulz if (timeout != 0 && server->port_status == PORT_NOT_WORKING) {
4692b8b63985ab174478d389e20a544054e09ce8Karl Luc gettimeofday(&tv, NULL);
d95f77e19ae3835318a6340d872193fbb3cbab05Karl Luc if (STATUS_DIFF(server, tv) > timeout) {
26b1c101b72100b69045effdfaab3889de6c8c93Christian Maeder DEBUG(4, ("Reseting the status of port %d for server '%s'\n",
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder server->port, SERVER_NAME(server)));
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder server->port_status = PORT_NEUTRAL;
2353f65833a3da763392f771223250cd50b8d873Christian Maeder server->last_status_change.tv_sec = tv.tv_sec;
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder }
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder }
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder return server->port_status;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder}
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederstatic int
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederserver_works(struct fo_server *server)
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder{
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (get_server_status(server) == SERVER_NOT_WORKING)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return 0;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return 1;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder}
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maeder
26b1c101b72100b69045effdfaab3889de6c8c93Christian Maederstatic int
26b1c101b72100b69045effdfaab3889de6c8c93Christian Maederservice_works(struct fo_server *server)
af6e92e4a9ca308f928f9909acee115f801c5db5Ewaryst Schulz{
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (!server_works(server))
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return 0;
818b228955ef40dd5a253bd942dd6ab8779ed713Christian Maeder if (get_port_status(server) == PORT_NOT_WORKING)
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return 0;
7ebcceae3d34771cae3bbb8c8060bef0b894376eChristian Maeder
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich return 1;
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich}
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederstatic int
2360728d4185c0c04279c999941c64d36626af79Christian Maederservice_destructor(struct fo_service *service)
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich{
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich DLIST_REMOVE(service->ctx->service_list, service);
7ebcceae3d34771cae3bbb8c8060bef0b894376eChristian Maeder return 0;
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich}
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederint
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederfo_new_service(struct fo_ctx *ctx, const char *name,
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder struct fo_service **_service)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder{
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder struct fo_service *service;
59aa5703ac7f3b99e97cd5926e77088b256c5f40Christian Maeder int ret;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder DEBUG(3, ("Creating new service '%s'\n", name));
f8cc2399c16fcda7e3bf9d901a0de0cc8a455f86Ewaryst Schulz ret = fo_get_service(ctx, name, &service);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (ret == EOK) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DEBUG(5, ("Service '%s' already exists\n", name));
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (_service) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder *_service = service;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return EEXIST;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder } else if (ret != ENOENT) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return ret;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder service = talloc_zero(ctx, struct fo_service);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (service == NULL)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return ENOMEM;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
df86c42574168135e8e2af9cf468fae774874cd0Christian Maeder service->name = talloc_strdup(service, name);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (service->name == NULL) {
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder talloc_free(service);
f8cc2399c16fcda7e3bf9d901a0de0cc8a455f86Ewaryst Schulz return ENOMEM;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder service->ctx = ctx;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DLIST_ADD(ctx->service_list, service);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder talloc_set_destructor(service, service_destructor);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (_service) {
3490b73f69b58ab742417b0867d0e2d4a7778cc0Christian Maeder *_service = service;
3490b73f69b58ab742417b0867d0e2d4a7778cc0Christian Maeder }
59aa5703ac7f3b99e97cd5926e77088b256c5f40Christian Maeder
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder return EOK;
f8cc2399c16fcda7e3bf9d901a0de0cc8a455f86Ewaryst Schulz}
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maederint
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maederfo_get_service(struct fo_ctx *ctx, const char *name,
3490b73f69b58ab742417b0867d0e2d4a7778cc0Christian Maeder struct fo_service **_service)
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder{
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder struct fo_service *service;
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich DLIST_FOR_EACH(service, ctx->service_list) {
b76d27eba526ecac2a20400fa505ec5c642ae7d2Dominik Luecke if (!strcmp(name, service->name)) {
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder *_service = service;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return EOK;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder }
2360728d4185c0c04279c999941c64d36626af79Christian Maeder }
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maeder return ENOENT;
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder}
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederstatic int
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederget_server_common(TALLOC_CTX *mem_ctx, struct fo_ctx *ctx, const char *name,
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder struct server_common **_common)
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder{
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder struct server_common *common;
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder
511284753313165e629cedf508752d6818ccc4d2Christian Maeder DLIST_FOR_EACH(common, ctx->server_common_list) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (!strcasecmp(name, common->name)) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder *_common = rc_reference(mem_ctx, struct server_common, common);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (*_common == NULL)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return ENOMEM;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return EOK;
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder }
511284753313165e629cedf508752d6818ccc4d2Christian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return ENOENT;
511284753313165e629cedf508752d6818ccc4d2Christian Maeder}
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederstatic int server_common_destructor(void *memptr)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder{
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder struct server_common *common;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder common = talloc_get_type(memptr, struct server_common);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (common->request_list) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DEBUG(1, ("BUG: pending requests still associated with this server\n"));
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return -1;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder }
8865728716566f42fa73e7e0bc080ba3225df764Christian Maeder DLIST_REMOVE(common->ctx->server_common_list, common);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder return 0;
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder}
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederstatic struct server_common *
f03420e44d8204b2945edaab5c70a84e7c381892Christian Maedercreate_server_common(TALLOC_CTX *mem_ctx, struct fo_ctx *ctx, const char *name)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder{
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder struct server_common *common;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
8bb80c9684e905de8dcfcfb1291542677e7d77b6Christian Maeder common = rc_alloc(mem_ctx, struct server_common);
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder if (common == NULL)
91ba5d95b2472cb075646b6120a559dc6581a867Christian Maeder return NULL;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder
91ba5d95b2472cb075646b6120a559dc6581a867Christian Maeder common->name = talloc_strdup(common, name);
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder if (common->name == NULL) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder talloc_free(common);
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder return NULL;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder }
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder common->ctx = ctx;
91ba5d95b2472cb075646b6120a559dc6581a867Christian Maeder common->prev = NULL;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder common->next = NULL;
91ba5d95b2472cb075646b6120a559dc6581a867Christian Maeder common->hostent = NULL;
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder common->request_list = NULL;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder common->server_status = DEFAULT_SERVER_STATUS;
f03420e44d8204b2945edaab5c70a84e7c381892Christian Maeder common->last_status_change.tv_sec = 0;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder common->last_status_change.tv_usec = 0;
91ba5d95b2472cb075646b6120a559dc6581a867Christian Maeder
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder talloc_set_destructor((TALLOC_CTX *) common, server_common_destructor);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder DLIST_ADD_END(ctx->server_common_list, common, struct server_common *);
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder return common;
91ba5d95b2472cb075646b6120a559dc6581a867Christian Maeder}
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder
f03420e44d8204b2945edaab5c70a84e7c381892Christian Maederint
f03420e44d8204b2945edaab5c70a84e7c381892Christian Maederfo_add_srv_server(struct fo_service *service, const char *srv,
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder const char *discovery_domain, const char *sssd_domain,
d81905a5b924415c524d702df26204683c82c12eChristian Maeder const char *proto, void *user_data)
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder{
91ba5d95b2472cb075646b6120a559dc6581a867Christian Maeder struct fo_server *server;
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder
d27b1887e61f1dc53d77c37f59dbf5019242a686Christian Maeder DEBUG(3, ("Adding new SRV server in domain '%s', to service '%s' using %s\n",
d27b1887e61f1dc53d77c37f59dbf5019242a686Christian Maeder discovery_domain ? discovery_domain : "unknown",
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder service->name, proto));
f03420e44d8204b2945edaab5c70a84e7c381892Christian Maeder
f03420e44d8204b2945edaab5c70a84e7c381892Christian Maeder DLIST_FOR_EACH(server, service->server_list) {
f03420e44d8204b2945edaab5c70a84e7c381892Christian Maeder if (server->user_data != user_data)
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder continue;
91ba5d95b2472cb075646b6120a559dc6581a867Christian Maeder
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder if (fo_is_srv_lookup(server)) {
f03420e44d8204b2945edaab5c70a84e7c381892Christian Maeder if (((discovery_domain == NULL &&
f03420e44d8204b2945edaab5c70a84e7c381892Christian Maeder server->srv_data->dns_domain == NULL) ||
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder (discovery_domain != NULL &&
818b228955ef40dd5a253bd942dd6ab8779ed713Christian Maeder server->srv_data->dns_domain != NULL &&
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder strcasecmp(server->srv_data->dns_domain, discovery_domain) == 0)) &&
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder strcasecmp(server->srv_data->proto, proto) == 0) {
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder return EEXIST;
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder }
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder }
33fcc19ef2b59493b4e91eebf701df95fd230765Christian Maeder }
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder server = talloc_zero(service, struct fo_server);
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder if (server == NULL)
4a2f7efdf67dfcda0946f1b6373f41976ddea7a4Christian Maeder return ENOMEM;
3490b73f69b58ab742417b0867d0e2d4a7778cc0Christian Maeder
3490b73f69b58ab742417b0867d0e2d4a7778cc0Christian Maeder server->user_data = user_data;
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maeder server->service = service;
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maeder server->port_status = DEFAULT_PORT_STATUS;
3490b73f69b58ab742417b0867d0e2d4a7778cc0Christian Maeder
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder /* add the SRV-specific data */
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder server->srv_data = talloc_zero(service, struct srv_data);
ab2f38d9cd1249f6bc9cc5b838dc2fcd76189c0fChristian Maeder if (server->srv_data == NULL)
974b0baababf2878820de073b8fad8db68bef08aDominik Luecke return ENOMEM;
8d780c893d6df5dab3dcc7d8444b7517f6547f11Christian Maeder
8d780c893d6df5dab3dcc7d8444b7517f6547f11Christian Maeder server->srv_data->proto = talloc_strdup(server->srv_data, proto);
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder server->srv_data->srv = talloc_strdup(server->srv_data, srv);
083bc1972a66d73749760eab3a90bf4eb9ca7951Christian Maeder if (server->srv_data->proto == NULL ||
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder server->srv_data->srv == NULL)
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder return ENOMEM;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder
966519955f5f7111abac20118563132b9dd41165Christian Maeder if (discovery_domain) {
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder server->srv_data->discovery_domain = talloc_strdup(server->srv_data,
f39b8dd9651dfcc38b06191cda23cacbfc298323Christian Maeder discovery_domain);
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder if (server->srv_data->discovery_domain == NULL)
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder return ENOMEM;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder server->srv_data->dns_domain =
0ae7a79e865d4a6022d705d160530682b3c1f825Christian Maeder server->srv_data->discovery_domain;
f03420e44d8204b2945edaab5c70a84e7c381892Christian Maeder }
0ae7a79e865d4a6022d705d160530682b3c1f825Christian Maeder
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder server->srv_data->sssd_domain =
2353f65833a3da763392f771223250cd50b8d873Christian Maeder talloc_strdup(server->srv_data, sssd_domain);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (server->srv_data->sssd_domain == NULL)
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return ENOMEM;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder server->srv_data->meta = server;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder server->srv_data->srv_lookup_status = DEFAULT_SRV_STATUS;
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder server->srv_data->last_status_change.tv_sec = 0;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DLIST_ADD_END(service->server_list, server, struct fo_server *);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return EOK;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder}
2360728d4185c0c04279c999941c64d36626af79Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederstatic struct fo_server *
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maedercreate_fo_server(struct fo_service *service, const char *name,
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder int port, void *user_data)
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder{
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder struct fo_server *server;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder int ret;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder
fefee7e1dee1ee5f0768a03a4abae88d1ca2c3fdRazvan Pascanu server = talloc_zero(service, struct fo_server);
fefee7e1dee1ee5f0768a03a4abae88d1ca2c3fdRazvan Pascanu if (server == NULL)
fefee7e1dee1ee5f0768a03a4abae88d1ca2c3fdRazvan Pascanu return NULL;
fefee7e1dee1ee5f0768a03a4abae88d1ca2c3fdRazvan Pascanu
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder server->port = port;
fefee7e1dee1ee5f0768a03a4abae88d1ca2c3fdRazvan Pascanu server->user_data = user_data;
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder server->service = service;
2360728d4185c0c04279c999941c64d36626af79Christian Maeder server->port_status = DEFAULT_PORT_STATUS;
fefee7e1dee1ee5f0768a03a4abae88d1ca2c3fdRazvan Pascanu
fefee7e1dee1ee5f0768a03a4abae88d1ca2c3fdRazvan Pascanu if (name != NULL) {
fefee7e1dee1ee5f0768a03a4abae88d1ca2c3fdRazvan Pascanu ret = get_server_common(server, service->ctx, name, &server->common);
66a774f13272fde036481edd2298081ab3d04678Razvan Pascanu if (ret == ENOENT) {
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder server->common = create_server_common(server, service->ctx, name);
2360728d4185c0c04279c999941c64d36626af79Christian Maeder if (server->common == NULL) {
66a774f13272fde036481edd2298081ab3d04678Razvan Pascanu talloc_free(server);
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder return NULL;
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder }
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder } else if (ret != EOK) {
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder talloc_free(server);
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder return NULL;
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
9dd71ac51c9a6e72bcb126224f9c64131698b636Christian Maeder return server;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder}
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederint
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maederfo_get_server_count(struct fo_service *service)
0ea2cddb8715a770e646895e16b7b8085f49167cChristian Maeder{
0ea2cddb8715a770e646895e16b7b8085f49167cChristian Maeder struct fo_server *server;
7245138e91992b96b153b8ac527e263d9dc8ff5bChristian Maeder int count = 0;
7245138e91992b96b153b8ac527e263d9dc8ff5bChristian Maeder
7245138e91992b96b153b8ac527e263d9dc8ff5bChristian Maeder DLIST_FOR_EACH(server, service->server_list) {
7245138e91992b96b153b8ac527e263d9dc8ff5bChristian Maeder count++;
7245138e91992b96b153b8ac527e263d9dc8ff5bChristian Maeder }
0ea2cddb8715a770e646895e16b7b8085f49167cChristian Maeder
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maeder return count;
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maeder}
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maeder
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maederint
a461314c811f4187dff85c8be079a41b2f13f176Christian Maederfo_add_server(struct fo_service *service, const char *name, int port,
a461314c811f4187dff85c8be079a41b2f13f176Christian Maeder void *user_data)
a461314c811f4187dff85c8be079a41b2f13f176Christian Maeder{
a461314c811f4187dff85c8be079a41b2f13f176Christian Maeder struct fo_server *server;
a461314c811f4187dff85c8be079a41b2f13f176Christian Maeder
a461314c811f4187dff85c8be079a41b2f13f176Christian Maeder DEBUG(3, ("Adding new server '%s', to service '%s'\n",
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder name ? name : "(no name)", service->name));
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder DLIST_FOR_EACH(server, service->server_list) {
3bcd9d942601d59dd55a6069d8b2d1c33d7ced0eChristian Maeder if (server->port != port || server->user_data != user_data)
3bcd9d942601d59dd55a6069d8b2d1c33d7ced0eChristian Maeder continue;
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder if (name == NULL && server->common == NULL) {
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder return EEXIST;
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder } else if (name != NULL && server->common != NULL) {
a461314c811f4187dff85c8be079a41b2f13f176Christian Maeder if (!strcasecmp(name, server->common->name))
a461314c811f4187dff85c8be079a41b2f13f176Christian Maeder return EEXIST;
a461314c811f4187dff85c8be079a41b2f13f176Christian Maeder }
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder }
3bcd9d942601d59dd55a6069d8b2d1c33d7ced0eChristian Maeder
3bcd9d942601d59dd55a6069d8b2d1c33d7ced0eChristian Maeder server = create_fo_server(service, name, port, user_data);
7245138e91992b96b153b8ac527e263d9dc8ff5bChristian Maeder if (!server) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return ENOMEM;
0a64bfd28dff15bc93e1f7a86e0a8052e879636dChristian Maeder }
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder DLIST_ADD_END(service->server_list, server, struct fo_server *);
9d6562465b41f17c7967d4e5678f34811d958cb2Christian Maeder
9d6562465b41f17c7967d4e5678f34811d958cb2Christian Maeder return EOK;
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder}
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maederstatic int
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maederget_first_server_entity(struct fo_service *service, struct fo_server **_server)
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder{
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder struct fo_server *server;
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder /* If we already have a working server, use that one. */
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder server = service->active_server;
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder if (server != NULL) {
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder if (service_works(server)) {
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder goto done;
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder }
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder service->active_server = NULL;
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder }
daec53c285f692c56db0cefe16061b46ba602cf0Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder /*
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * Otherwise iterate through the server list.
93bc87ee96c68506945dbad8c704badaa42ecf14Christian Maeder */
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder /* First, try servers after the last one we tried. */
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder if (service->last_tried_server != NULL) {
3bcd9d942601d59dd55a6069d8b2d1c33d7ced0eChristian Maeder DLIST_FOR_EACH(server, service->last_tried_server->next) {
0a64bfd28dff15bc93e1f7a86e0a8052e879636dChristian Maeder if (service_works(server)) {
0a64bfd28dff15bc93e1f7a86e0a8052e879636dChristian Maeder goto done;
0a64bfd28dff15bc93e1f7a86e0a8052e879636dChristian Maeder }
0a64bfd28dff15bc93e1f7a86e0a8052e879636dChristian Maeder }
0a64bfd28dff15bc93e1f7a86e0a8052e879636dChristian Maeder }
0a64bfd28dff15bc93e1f7a86e0a8052e879636dChristian Maeder
0a64bfd28dff15bc93e1f7a86e0a8052e879636dChristian Maeder /* If none were found, try at the start. */
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder DLIST_FOR_EACH(server, service->server_list) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (service_works(server)) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder goto done;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (server == service->last_tried_server) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder break;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder }
2353f65833a3da763392f771223250cd50b8d873Christian Maeder }
2353f65833a3da763392f771223250cd50b8d873Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder service->last_tried_server = NULL;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return ENOENT;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederdone:
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder service->last_tried_server = server;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder *_server = server;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return EOK;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder}
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederstatic int
2353f65833a3da763392f771223250cd50b8d873Christian Maederresolve_service_request_destructor(struct resolve_service_request *request)
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder{
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder DLIST_REMOVE(request->server_common->request_list, request);
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder return 0;
f39b8dd9651dfcc38b06191cda23cacbfc298323Christian Maeder}
528539f3d544c24afe14e979fe51f03e50aa6e9cChristian Maeder
0ae7a79e865d4a6022d705d160530682b3c1f825Christian Maederstatic int
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maederset_lookup_hook(struct fo_server *server, struct tevent_req *req)
0ae7a79e865d4a6022d705d160530682b3c1f825Christian Maeder{
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct resolve_service_request *request;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder request = talloc(req, struct resolve_service_request);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (request == NULL) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder DEBUG(1, ("No memory\n"));
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder talloc_free(request);
59a10395caff224b2ec541f94dac5082a506c00fChristian Maeder return ENOMEM;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder }
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder request->server_common = rc_reference(request, struct server_common,
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder server->common);
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder if (request->server_common == NULL) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder talloc_free(request);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return ENOMEM;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder }
2353f65833a3da763392f771223250cd50b8d873Christian Maeder request->req = req;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder DLIST_ADD(server->common->request_list, request);
2353f65833a3da763392f771223250cd50b8d873Christian Maeder talloc_set_destructor(request, resolve_service_request_destructor);
2353f65833a3da763392f771223250cd50b8d873Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return EOK;
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maeder}
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder/*******************************************************************
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder * Get server to connect to. *
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder *******************************************************************/
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederstruct resolve_service_state {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct fo_server *server;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder struct resolv_ctx *resolv;
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder struct tevent_context *ev;
964ee9fff06b8c821e1d00207f6f185301371be8Christian Maeder struct fo_ctx *fo_ctx;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder};
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maeder
964ee9fff06b8c821e1d00207f6f185301371be8Christian Maeder
964ee9fff06b8c821e1d00207f6f185301371be8Christian Maederstatic void fo_resolve_service_cont(struct tevent_req *subreq);
d27b1887e61f1dc53d77c37f59dbf5019242a686Christian Maederstatic void fo_resolve_service_done(struct tevent_req *subreq);
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maederstatic bool fo_resolve_service_server(struct tevent_req *req);
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder
964ee9fff06b8c821e1d00207f6f185301371be8Christian Maeder/* Forward declarations for SRV resolving */
964ee9fff06b8c821e1d00207f6f185301371be8Christian Maederstatic struct tevent_req *
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederresolve_srv_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct resolv_ctx *resolv, struct fo_ctx *ctx,
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct fo_server *server);
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maederstatic int
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maederresolve_srv_recv(struct tevent_req *req, struct fo_server **server);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederstruct tevent_req *
c5a4c5f506ea34fa527065b4187127a18c6e2418Christian Maederfo_resolve_service_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct resolv_ctx *resolv, struct fo_ctx *ctx,
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder struct fo_service *service)
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder{
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder int ret;
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder struct fo_server *server;
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder struct tevent_req *req;
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder struct tevent_req *subreq;
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder struct resolve_service_state *state;
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder DEBUG(4, ("Trying to resolve service '%s'\n", service->name));
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder req = tevent_req_create(mem_ctx, &state, struct resolve_service_state);
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder if (req == NULL)
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return NULL;
59a10395caff224b2ec541f94dac5082a506c00fChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder state->resolv = resolv;
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maeder state->ev = ev;
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maeder state->fo_ctx = ctx;
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maeder
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder ret = get_first_server_entity(service, &server);
0a64bfd28dff15bc93e1f7a86e0a8052e879636dChristian Maeder if (ret != EOK) {
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maeder DEBUG(1, ("No available servers for service '%s'\n", service->name));
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maeder goto done;
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maeder }
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (fo_is_srv_lookup(server)) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder /* Don't know the server yet, must do a SRV lookup */
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder subreq = resolve_srv_send(state, ev, resolv,
2353f65833a3da763392f771223250cd50b8d873Christian Maeder ctx, server);
4b1833c7d3af466e6bcba24f16304e0a78e8da87Christian Maeder if (subreq == NULL) {
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maeder ret = ENOMEM;
e953bea49e7f0e1a43bccf2a66c5e2a2b50848e0Christian Maeder goto done;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder }
4b1833c7d3af466e6bcba24f16304e0a78e8da87Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder tevent_req_set_callback(subreq,
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder fo_resolve_service_cont,
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder req);
2353f65833a3da763392f771223250cd50b8d873Christian Maeder return req;
2353f65833a3da763392f771223250cd50b8d873Christian Maeder }
9d6562465b41f17c7967d4e5678f34811d958cb2Christian Maeder
9d6562465b41f17c7967d4e5678f34811d958cb2Christian Maeder /* This is a regular server, just do hostname lookup */
2353f65833a3da763392f771223250cd50b8d873Christian Maeder state->server = server;
9d6562465b41f17c7967d4e5678f34811d958cb2Christian Maeder if (fo_resolve_service_server(req)) {
9d6562465b41f17c7967d4e5678f34811d958cb2Christian Maeder tevent_req_post(req, ev);
c5a4c5f506ea34fa527065b4187127a18c6e2418Christian Maeder }
c5a4c5f506ea34fa527065b4187127a18c6e2418Christian Maeder
c5a4c5f506ea34fa527065b4187127a18c6e2418Christian Maeder ret = EOK;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maederdone:
9d6562465b41f17c7967d4e5678f34811d958cb2Christian Maeder if (ret != EOK) {
2353f65833a3da763392f771223250cd50b8d873Christian Maeder tevent_req_error(req, ret);
dbc98cd8a9a829e020cfa0a9f3aff89de75caaa9Christian Maeder tevent_req_post(req, ev);
2353f65833a3da763392f771223250cd50b8d873Christian Maeder }
cb2044812811d66efe038d914966e04290be93faChristian Maeder return req;
cb2044812811d66efe038d914966e04290be93faChristian Maeder}
9d6562465b41f17c7967d4e5678f34811d958cb2Christian Maeder
cb2044812811d66efe038d914966e04290be93faChristian Maederstatic void set_server_common_status(struct server_common *common,
2353f65833a3da763392f771223250cd50b8d873Christian Maeder enum server_status status);
cb2044812811d66efe038d914966e04290be93faChristian Maeder
c5a4c5f506ea34fa527065b4187127a18c6e2418Christian Maeder/* SRV resolving finished, see if we got server to work with */
c5a4c5f506ea34fa527065b4187127a18c6e2418Christian Maederstatic void
cb2044812811d66efe038d914966e04290be93faChristian Maederfo_resolve_service_cont(struct tevent_req *subreq)
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder{
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder struct tevent_req *req = tevent_req_callback_data(subreq,
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder struct tevent_req);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct resolve_service_state *state = tevent_req_data(req,
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct resolve_service_state);
c5a4c5f506ea34fa527065b4187127a18c6e2418Christian Maeder int ret;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder ret = resolve_srv_recv(subreq, &state->server);
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder talloc_zfree(subreq);
c5a4c5f506ea34fa527065b4187127a18c6e2418Christian Maeder
c5a4c5f506ea34fa527065b4187127a18c6e2418Christian Maeder if (ret) {
2353f65833a3da763392f771223250cd50b8d873Christian Maeder tevent_req_error(req, ret);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return;
c5a4c5f506ea34fa527065b4187127a18c6e2418Christian Maeder }
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder fo_resolve_service_server(req);
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder}
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
2360728d4185c0c04279c999941c64d36626af79Christian Maederstatic bool
cb2044812811d66efe038d914966e04290be93faChristian Maederfo_resolve_service_server(struct tevent_req *req)
2360728d4185c0c04279c999941c64d36626af79Christian Maeder{
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder struct resolve_service_state *state = tevent_req_data(req,
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder struct resolve_service_state);
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder struct tevent_req *subreq;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder int ret;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder switch (get_server_status(state->server)) {
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder case SERVER_NAME_NOT_RESOLVED: /* Request name resolution. */
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder subreq = resolv_gethostbyname_send(state->server->common,
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder state->ev, state->resolv,
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder state->server->common->name,
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder state->fo_ctx->opts->family_order);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (subreq == NULL) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder tevent_req_error(req, ENOMEM);
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder return true;
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder }
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder tevent_req_set_callback(subreq, fo_resolve_service_done, req);
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder fo_set_server_status(state->server, SERVER_RESOLVING_NAME);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder /* FALLTHROUGH */
c5a4c5f506ea34fa527065b4187127a18c6e2418Christian Maeder case SERVER_RESOLVING_NAME:
c5a4c5f506ea34fa527065b4187127a18c6e2418Christian Maeder /* Name resolution is already under way. Just add ourselves into the
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder * waiting queue so we get notified after the operation is finished. */
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder ret = set_lookup_hook(state->server, req);
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder if (ret != EOK) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder tevent_req_error(req, ret);
c5a4c5f506ea34fa527065b4187127a18c6e2418Christian Maeder return true;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder break;
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder default: /* The name is already resolved. Return immediately. */
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder tevent_req_done(req);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return true;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return false;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder}
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederstatic void
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederfo_resolve_service_done(struct tevent_req *subreq)
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder{
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder struct tevent_req *req = tevent_req_callback_data(subreq,
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct tevent_req);
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder struct resolve_service_state *state = tevent_req_data(req,
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder struct resolve_service_state);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder struct server_common *common;
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder int resolv_status;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder struct resolve_service_request *request;
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maeder int ret;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder if (state->server->common->hostent != NULL) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder talloc_zfree(state->server->common->hostent);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder ret = resolv_gethostbyname_recv(subreq, state->server->common,
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder &resolv_status, NULL,
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder &state->server->common->hostent);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder talloc_zfree(subreq);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (ret != EOK) {
5941ba0b9a99ac98f78a89a9f3303102657e36ccChristian Maeder DEBUG(1, ("Failed to resolve server '%s': %s\n",
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder state->server->common->name,
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder resolv_strerror(resolv_status)));
5941ba0b9a99ac98f78a89a9f3303102657e36ccChristian Maeder set_server_common_status(state->server->common, SERVER_NOT_WORKING);
5941ba0b9a99ac98f78a89a9f3303102657e36ccChristian Maeder } else {
set_server_common_status(state->server->common, SERVER_NAME_RESOLVED);
}
/* Take care of all requests for this server. */
common = state->server->common; /* state can disappear now */
while ((request = common->request_list) != NULL) {
DLIST_REMOVE(common->request_list, request);
if (resolv_status) {
/* FIXME FIXME: resolv_status is an ARES error.
* but any caller will expect classic error codes.
* also the send() function may return ENOENT, so this mix
* IS explosive (ENOENT = 2 = ARES_EFORMER) */
tevent_req_error(request->req, resolv_status);
} else {
tevent_req_done(request->req);
}
}
}
int
fo_resolve_service_recv(struct tevent_req *req, struct fo_server **server)
{
struct resolve_service_state *state;
state = tevent_req_data(req, struct resolve_service_state);
/* always return the server if asked for, otherwise the caller
* cannot mark it as faulty in case we return an error */
if (server)
*server = state->server;
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
}
/*******************************************************************
* Resolve the server to connect to using a SRV query. *
*******************************************************************/
static void resolve_srv_done(struct tevent_req *subreq);
static void resolve_srv_cont(struct tevent_req *req);
struct tevent_req *resolve_get_domain_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct fo_ctx *foctx,
struct resolv_ctx *resolv);
static void resolve_getsrv_domain_done(struct tevent_req *req);
int resolve_get_domain_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
char **dns_domain);
struct resolve_srv_state {
struct fo_server *meta;
struct fo_service *service;
struct fo_server *out;
struct resolv_ctx *resolv;
struct tevent_context *ev;
struct fo_ctx *fo_ctx;
};
static struct tevent_req *
resolve_srv_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
struct resolv_ctx *resolv, struct fo_ctx *ctx,
struct fo_server *server)
{
int ret;
struct tevent_req *req;
struct tevent_req *subreq;
struct resolve_srv_state *state;
int status;
req = tevent_req_create(mem_ctx, &state, struct resolve_srv_state);
if (req == NULL)
return NULL;
state->service = server->service;
state->ev = ev;
state->resolv = resolv;
state->fo_ctx = ctx;
state->meta = server;
status = get_srv_data_status(server->srv_data);
DEBUG(6, ("The status of SRV lookup is %s\n",
str_srv_data_status(status)));
switch(status) {
case SRV_EXPIRED: /* Need a refresh */
state->meta = collapse_srv_lookup(server);
/* FALLTHROUGH */
case SRV_NEUTRAL: /* Request SRV lookup */
if (server->srv_data->dns_domain == NULL) {
/* we need to look up our DNS domain first */
subreq = resolve_get_domain_send(state, ev, ctx, resolv);
if (subreq == NULL) {
ret = ENOMEM;
goto done;
}
tevent_req_set_callback(subreq, resolve_getsrv_domain_done, req);
break;
}
/* we know the DNS domain, just do the lookup */
resolve_srv_cont(req);
break;
case SRV_RESOLVE_ERROR: /* query could not be resolved but don't retry yet */
ret = EIO;
goto done;
case SRV_RESOLVED: /* The query is resolved and valid. Return. */
state->out = server;
tevent_req_done(req);
tevent_req_post(req, state->ev);
return req;
default:
DEBUG(1, ("Unexpected status %d for a SRV server\n", status));
ret = EIO;
goto done;
}
ret = EOK;
done:
if (ret != EOK) {
tevent_req_error(req, ret);
tevent_req_post(req, ev);
}
return req;
}
static void
resolve_getsrv_domain_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct resolve_srv_state *state = tevent_req_data(req,
struct resolve_srv_state);
int ret;
ret = resolve_get_domain_recv(subreq, state->meta->srv_data,
&state->meta->srv_data->dns_domain);
talloc_zfree(subreq);
if (ret) {
tevent_req_error(req, ret);
return;
}
resolve_srv_cont(req);
}
static void
resolve_srv_cont(struct tevent_req *req)
{
struct resolve_srv_state *state = tevent_req_data(req,
struct resolve_srv_state);
char *query;
struct tevent_req *subreq;
query = get_srv_query(state, state->meta);
if (!query) {
tevent_req_error(req, ENOMEM);
return;
}
DEBUG(4, ("Searching for servers via SRV query '%s'\n", query));
subreq = resolv_getsrv_send(state, state->ev, state->resolv, query);
if (subreq == NULL) {
tevent_req_error(req, ENOMEM);
return;
}
tevent_req_set_callback(subreq, resolve_srv_done, req);
}
static void
resolve_srv_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct resolve_srv_state *state = tevent_req_data(req,
struct resolve_srv_state);
struct ares_srv_reply *reply_list;
struct ares_srv_reply *reply;
struct fo_server *server = NULL;
struct fo_server *srv_list = NULL;
int ret;
int resolv_status;
ret = resolv_getsrv_recv(state, subreq,
&resolv_status, NULL, &reply_list);
talloc_free(subreq);
if (ret != EOK) {
DEBUG(1, ("SRV query failed: [%s]\n",
resolv_strerror(resolv_status)));
if (resolv_status == ARES_ENOTFOUND &&
state->meta->srv_data->dns_domain !=
state->meta->srv_data->discovery_domain &&
state->meta->srv_data->dns_domain !=
state->meta->srv_data->sssd_domain) {
/* The domain name could not be identified
* If the domain wasn't specified in the config
* file, also check whether the SSSD domain
* works.
*
* Programming note: It is safe to compare
* pointers here, because we're not copying
* the data, we're just reassigning the pointer
* for the active domain.
*/
talloc_free(state->meta->srv_data->dns_domain);
state->meta->srv_data->dns_domain =
state->meta->srv_data->sssd_domain;
resolve_srv_cont(req);
return;
}
/* We need to make sure we reset this to NULL
* so that if we go online later, we re-check
* the DNS domain
*/
if (!state->meta->srv_data->discovery_domain) {
state->meta->srv_data->dns_domain = NULL;
}
fo_set_port_status(state->meta, PORT_NOT_WORKING);
goto fail;
}
ret = resolv_sort_srv_reply(state, &reply_list);
if (ret != EOK) {
DEBUG(1, ("Could not sort the answers from DNS [%d]: %s\n",
ret, strerror(ret)));
fo_set_port_status(state->meta, PORT_NOT_WORKING);
goto fail;
}
for (reply = reply_list; reply; reply = reply->next) {
ret = EOK;
DLIST_FOR_EACH(server, state->service->server_list) {
if (server->port == reply->port) {
ret = EEXIST;
break;
}
}
if (ret == EEXIST) continue;
server = create_fo_server(state->service, reply->host,
reply->port, state->meta->user_data);
if (!server) {
ret = ENOMEM;
goto fail;
}
server->srv_data = state->meta->srv_data;
DLIST_ADD_END(srv_list, server, struct fo_server *);
DEBUG(6, ("Inserted server '%s:%d' for service %s\n",
server->common->name,
server->port,
state->service->name));
}
if (srv_list) {
DLIST_ADD_LIST_AFTER(state->service->server_list, state->meta,
srv_list, struct fo_server *);
DLIST_REMOVE(state->service->server_list, state->meta);
if (state->service->last_tried_server == state->meta) {
state->service->last_tried_server = srv_list;
}
state->out = srv_list;
set_srv_data_status(state->meta->srv_data, SRV_RESOLVED);
tevent_req_done(req);
return;
} else {
ret = EIO;
goto fail;
}
fail:
state->out = state->meta;
set_srv_data_status(state->meta->srv_data, SRV_RESOLVE_ERROR);
tevent_req_error(req, ret);
}
static int
resolve_srv_recv(struct tevent_req *req, struct fo_server **server)
{
struct resolve_srv_state *state = tevent_req_data(req,
struct resolve_srv_state);
/* always return the server if asked for, otherwise the caller
* cannot mark it as faulty in case we return an error */
if (server) {
*server = state->out;
}
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
}
/*******************************************************************
* Get Fully Qualified Domain Name of the host machine *
*******************************************************************/
struct resolve_get_domain_state {
char *fqdn;
char hostname[HOST_NAME_MAX];
};
static void resolve_get_domain_done(struct tevent_req *subreq);
struct tevent_req *
resolve_get_domain_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct fo_ctx *foctx,
struct resolv_ctx *resolv)
{
int ret;
struct resolve_get_domain_state *state;
struct tevent_req *req, *subreq;
req = tevent_req_create(mem_ctx, &state, struct resolve_get_domain_state);
if (!req) {
return NULL;
}
ret = gethostname(state->hostname, HOST_NAME_MAX);
if (ret) {
ret = errno;
DEBUG(2, ("gethostname() failed: [%d]: %s\n",ret, strerror(ret)));
return NULL;
}
state->hostname[HOST_NAME_MAX-1] = '\0';
DEBUG(7, ("Host name is: %s\n", state->hostname));
subreq = resolv_gethostbyname_send(state, ev, resolv,
state->hostname,
foctx->opts->family_order);
if (!subreq) {
talloc_zfree(req);
return NULL;
}
tevent_req_set_callback(subreq, resolve_get_domain_done, req);
return req;
}
static void resolve_get_domain_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct resolve_get_domain_state *state = tevent_req_data(req,
struct resolve_get_domain_state);
struct hostent *hostent;
int ret;
ret = resolv_gethostbyname_recv(subreq, req, NULL, NULL, &hostent);
talloc_zfree(subreq);
if (ret) {
DEBUG(2, ("Could not get fully qualified name for host name %s "
"resolver returned: [%d]: %s\n",
state->hostname, ret, strerror(ret)));
/* We'll proceed with hostname in this case */
} else {
DEBUG(7, ("The full FQDN is: %s\n", hostent->h_name));
state->fqdn = hostent->h_name;
}
tevent_req_done(req);
}
int resolve_get_domain_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
char **dns_domain)
{
struct resolve_get_domain_state *state = tevent_req_data(req,
struct resolve_get_domain_state);
char *fqdn;
char *domptr;
TEVENT_REQ_RETURN_ON_ERROR(req);
fqdn = state->fqdn ? state->fqdn : state->hostname;
domptr = strchr(fqdn, '.');
if (!domptr || (*(domptr+1) == '\0')) {
/* If the FQDN did not contain a dot or the dot was the last character
* (broken DNS server perhaps */
*dns_domain = talloc_strdup(mem_ctx, fqdn);
} else {
domptr++;
*dns_domain = talloc_strdup(mem_ctx, domptr);
}
if (*dns_domain == NULL) {
return ENOMEM;
}
return EOK;
}
static void
set_server_common_status(struct server_common *common,
enum server_status status)
{
DEBUG(4, ("Marking server '%s' as '%s'\n", common->name,
str_server_status(status)));
common->server_status = status;
gettimeofday(&common->last_status_change, NULL);
}
void
fo_set_server_status(struct fo_server *server, enum server_status status)
{
if (server->common == NULL) {
DEBUG(1, ("Bug: Trying to set server status of a name-less server\n"));
return;
}
set_server_common_status(server->common, status);
}
void
fo_set_port_status(struct fo_server *server, enum port_status status)
{
DEBUG(4, ("Marking port %d of server '%s' as '%s'\n", server->port,
SERVER_NAME(server), str_port_status(status)));
server->port_status = status;
gettimeofday(&server->last_status_change, NULL);
if (status == PORT_WORKING) {
fo_set_server_status(server, SERVER_WORKING);
server->service->active_server = server;
}
}
void fo_try_next_server(struct fo_service *service)
{
struct fo_server *server;
if (!service) {
DEBUG(1, ("Bug: No service supplied\n"));
return;
}
server = service->active_server;
if (!server) {
return;
}
service->active_server = 0;
if (server->port_status == PORT_WORKING) {
server->port_status = PORT_NEUTRAL;
}
}
void *
fo_get_server_user_data(struct fo_server *server)
{
return server->user_data;
}
int
fo_get_server_port(struct fo_server *server)
{
return server->port;
}
const char *fo_get_server_name(struct fo_server *server)
{
if (!server->common) {
if (fo_is_srv_lookup(server)) {
return "SRV lookup meta-server";
}
return "unknown name";
}
return server->common->name;
}
struct hostent *
fo_get_server_hostent(struct fo_server *server)
{
if (server->common == NULL) {
DEBUG(1, ("Bug: Trying to get hostent from a name-less server\n"));
return NULL;
}
return server->common->hostent;
}
time_t
fo_get_server_hostname_last_change(struct fo_server *server)
{
if (server->common == NULL) {
return 0;
}
return server->common->last_status_change.tv_sec;
}
void fo_reset_services(struct fo_ctx *fo_ctx)
{
struct fo_service *service;
struct fo_server *server;
DLIST_FOR_EACH(service, fo_ctx->service_list) {
DLIST_FOR_EACH(server, service->server_list) {
fo_set_server_status(server, SERVER_NAME_NOT_RESOLVED);
fo_set_port_status(server, PORT_NEUTRAL);
if (server->srv_data != NULL) {
set_srv_data_status(server->srv_data, SRV_NEUTRAL);
}
}
}
}