MEDIUM: resolvers: add supports of TCP nameservers in resolvers.
This patch introduce the new line "server" to set a TCP
nameserver in a "resolvers" section:
server <name> <address> [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
. The current implementation limits to 4 pipelined
The name of the line in configuration is open to discussion
and could be changed before the next release.
diff --git a/src/resolvers.c b/src/resolvers.c
index ded3004..6af6fc5 100644
--- a/src/resolvers.c
+++ b/src/resolvers.c
@@ -2097,6 +2097,15 @@
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 @@
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 @@
free(errmsg);
return err_code;
}
+int cfg_post_parse_resolvers()
+{
+ int err_code = 0;
+ struct server *srv;
+
+ 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, NULL);
+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);