]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: resolvers: add supports of TCP nameservers in resolvers.
authorEmeric Brun <ebrun@haproxy.com>
Fri, 12 Feb 2021 19:05:45 +0000 (20:05 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 13 Feb 2021 09:03:46 +0000 (10:03 +0100)
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.

doc/configuration.txt
src/resolvers.c

index b30b52f5161237df01e77a0c41d8edd544cc859f..8baf325d7b9734e00954ca5d97d2454049e5ce16 100644 (file)
@@ -14621,11 +14621,19 @@ accepted_payload_size <nb>
   Note: the maximum allowed value is 8192.
 
 nameserver <id> <ip>:<port>
-  DNS server description:
+  UDP DNS server description:
     <id>   : label of the server, should be unique
     <ip>   : IP address of the server
     <port> : port where the DNS service actually runs
 
+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.
+
 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
index ded30044dc8dcb29e1c2e0641c5cee596c6f5606..6af6fc5136e7465da64a7431610db6befd5e2b62 100644 (file)
@@ -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;
+
+       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);