MEDIUM: resolvers: add support of tcp address on nameserver line.

This patch re-works configuration parsing, it removes the "server"
lines from "resolvers" sections introduced in commit 56fc5d9eb:
MEDIUM: resolvers: add supports of TCP nameservers in resolvers.

It also extends the nameserver lines to support stream server
addresses such as:

resolvers
  nameserver localhost tcp@127.0.0.1:53

Doing so, a part of nameserver's init code was factorized in
function 'parse_resolvers' and removed from 'post_parse_resolvers'.
This commit is contained in:
Emeric Brun 2021-04-07 16:04:54 +02:00 committed by Willy Tarreau
parent 98272253d8
commit c8f3e45c6a
2 changed files with 29 additions and 62 deletions

View File

@ -14828,18 +14828,16 @@ accepted_payload_size <nb>
nameservers to handle huge DNS responses, you should put this value
to the max: 65535.
nameserver <id> <ip>:<port>
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
nameserver <name> <address>[:port] [param*]
Used to configure a nameserver. <name> of the nameserver should ne unique.
By default the <address> is considered of type datagram. This means if an
IPv4 or IPv6 is configured without special address prefixes (paragraph 11.)
the UDP protocol will be used. If an stream protocol address prefix is used,
the nameserver will be considered as a stream server (TCP for instance) and
"server" parameters found in 5.2 paragraph which are relevant for DNS
resolving will be considered. Note: currently, in TCP mode, 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
@ -14885,6 +14883,7 @@ timeout <event> <time>
resolvers mydns
nameserver dns1 10.0.0.1:53
nameserver dns2 10.0.0.2:53
nameserver dns3 tcp@10.0.0.3:53
parse-resolv-conf
resolve_retries 3
timeout resolve 1s

View File

@ -2968,14 +2968,11 @@ 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,
SRV_PARSE_PARSE_ADDR|SRV_PARSE_INITIAL_RESOLVE);
}
else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
struct dns_nameserver *newnameserver = NULL;
struct sockaddr_storage *sk;
int port1, port2;
struct protocol *proto;
if (!*args[2]) {
ha_alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
@ -3001,8 +2998,8 @@ int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
}
}
sk = str2sa_range(args[2], NULL, &port1, &port2, NULL, NULL,
&errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_DGRAM);
sk = str2sa_range(args[2], NULL, &port1, &port2, NULL, &proto,
&errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_DGRAM | PA_O_STREAM | PA_O_DEFAULT_DGRAM);
if (!sk) {
ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
@ -3015,7 +3012,21 @@ int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
goto out;
}
if (dns_dgram_init(newnameserver, sk) < 0) {
if (proto && proto->ctrl_type == SOCK_STREAM) {
err_code |= parse_server(file, linenum, args, curr_resolvers->px, NULL,
SRV_PARSE_PARSE_ADDR|SRV_PARSE_INITIAL_RESOLVE);
if (err_code & (ERR_FATAL|ERR_ABORT)) {
err_code |= ERR_ABORT;
goto out;
}
if (dns_stream_init(newnameserver, curr_resolvers->px->srv) < 0) {
ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
err_code |= ERR_ALERT|ERR_ABORT;
goto out;
}
}
else if (dns_dgram_init(newnameserver, sk) < 0) {
ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
err_code |= ERR_ALERT | ERR_ABORT;
goto out;
@ -3316,18 +3327,6 @@ int cfg_post_parse_resolvers()
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)) {
@ -3336,37 +3335,6 @@ int cfg_post_parse_resolvers()
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;
}
}