diff --git a/doc/configuration.txt b/doc/configuration.txt index b30b52f51..8baf325d7 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -14621,11 +14621,19 @@ accepted_payload_size Note: the maximum allowed value is 8192. nameserver : - DNS server description: + UDP DNS server description: : label of the server, should be unique : IP address of the server : port where the DNS service actually runs +server
[param*] + Used to configure a DNS TCP or stream server. This supports for all + "server" parameters found in 5.2 paragraph. Some of these parameters + are irrelevant for DNS resolving. Note: currently 4 queries are pipelined + on the same connections. A batch of idle connections are removed every + 5 seconds. "maxconn" can be configured to limit the amount of those + concurrent connections and TLS should also usable if the server supports. + parse-resolv-conf Adds all nameservers found in /etc/resolv.conf to this resolvers nameservers list. Ordered as if each nameserver in /etc/resolv.conf was individually diff --git a/src/resolvers.c b/src/resolvers.c index ded30044d..6af6fc513 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -2097,6 +2097,15 @@ static void resolvers_deinit(void) ring_free(ns->dgram->ring_req); free(ns->dgram); } + if (ns->stream) { + if (ns->stream->ring_req) + ring_free(ns->stream->ring_req); + if (ns->stream->task_req) + task_destroy(ns->stream->task_req); + if (ns->stream->task_rsp) + task_destroy(ns->stream->task_rsp); + free(ns->stream); + } LIST_DEL(&ns->list); EXTRA_COUNTERS_FREE(ns->extra_counters); free(ns); @@ -2881,6 +2890,9 @@ int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm) LIST_INIT(&curr_resolvers->resolutions.wait); HA_SPIN_INIT(&curr_resolvers->lock); } + else if (strcmp(args[0],"server") == 0) { + err_code |= parse_server(file, linenum, args, curr_resolvers->px, NULL, 1, 0, 1); + } else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */ struct dns_nameserver *newnameserver = NULL; struct sockaddr_storage *sk; @@ -3214,7 +3226,76 @@ resolv_out: free(errmsg); return err_code; } +int cfg_post_parse_resolvers() +{ + int err_code = 0; + struct server *srv; -REGISTER_CONFIG_SECTION("resolvers", cfg_parse_resolvers, NULL); + if (curr_resolvers) { + + /* prepare forward server descriptors */ + if (curr_resolvers->px) { + srv = curr_resolvers->px->srv; + while (srv) { + struct dns_nameserver *ns; + + list_for_each_entry(ns, &curr_resolvers->nameservers, list) { + /* Error if two resolvers owns the same name */ + if (strcmp(ns->id, srv->id) == 0) { + ha_alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n", + srv->conf.file, srv->conf.line, srv->id, ns->conf.file, ns->conf.line); + err_code |= ERR_ALERT | ERR_FATAL; + break; + } + } + + /* init ssl if needed */ + if (srv->use_ssl == 1 && xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv) { + if (xprt_get(XPRT_SSL)->prepare_srv(srv)) { + ha_alert("unable to prepare SSL for server '%s' in resolvers section '%s'.\n", srv->id, curr_resolvers->id); + err_code |= ERR_ALERT | ERR_FATAL; + break; + } + } + + /* allocate nameserver */ + ns = calloc(1, sizeof(*ns)); + if (!ns) { + ha_alert("memory allocation error initializing tcp server '%s' in resolvers section '%s'.\n", srv->id, curr_resolvers->id); + err_code |= ERR_ALERT | ERR_FATAL; + break; + } + + if (dns_stream_init(ns, srv) < 0) { + ha_alert("memory allocation error initializing tcp server '%s' in resolvers section '%s'.\n", srv->id, curr_resolvers->id); + err_code |= ERR_ALERT|ERR_ABORT; + break; + } + + ns->conf.file = strdup(srv->conf.file); + if (!ns->conf.file) { + ha_alert("memory allocation error initializing tcp server '%s' in resolvers section '%s'.\n", srv->id, curr_resolvers->id); + err_code |= ERR_ALERT|ERR_ABORT; + break; + } + ns->id = strdup(srv->id); + if (!ns->id) { + ha_alert("memory allocation error initializing tcp server '%s' in resolvers section '%s'.\n", srv->id, curr_resolvers->id); + err_code |= ERR_ALERT|ERR_ABORT; + break; + } + ns->conf.line = srv->conf.line; + ns->process_responses = resolv_process_responses; + ns->parent = curr_resolvers; + LIST_ADDQ(&curr_resolvers->nameservers, &ns->list); + srv = srv->next; + } + } + } + curr_resolvers = NULL; + return err_code; +} + +REGISTER_CONFIG_SECTION("resolvers", cfg_parse_resolvers, cfg_post_parse_resolvers); REGISTER_POST_DEINIT(resolvers_deinit); REGISTER_CONFIG_POSTPARSER("dns runtime resolver", resolvers_finalize_config);