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 nameservers to handle huge DNS responses, you should put this value
to the max: 65535. to the max: 65535.
nameserver <id> <ip>:<port> nameserver <name> <address>[:port] [param*]
UDP DNS server description: Used to configure a nameserver. <name> of the nameserver should ne unique.
<id> : label of the server, should be unique By default the <address> is considered of type datagram. This means if an
<ip> : IP address of the server IPv4 or IPv6 is configured without special address prefixes (paragraph 11.)
<port> : port where the DNS service actually runs 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 <name> <address> [param*] "server" parameters found in 5.2 paragraph which are relevant for DNS
Used to configure a DNS TCP or stream server. This supports for all resolving will be considered. Note: currently, in TCP mode, 4 queries are
"server" parameters found in 5.2 paragraph. Some of these parameters pipelined on the same connections. A batch of idle connections are removed
are irrelevant for DNS resolving. Note: currently 4 queries are pipelined every 5 seconds. "maxconn" can be configured to limit the amount of those
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. concurrent connections and TLS should also usable if the server supports.
parse-resolv-conf parse-resolv-conf
@ -14885,6 +14883,7 @@ timeout <event> <time>
resolvers mydns resolvers mydns
nameserver dns1 10.0.0.1:53 nameserver dns1 10.0.0.1:53
nameserver dns2 10.0.0.2:53 nameserver dns2 10.0.0.2:53
nameserver dns3 tcp@10.0.0.3:53
parse-resolv-conf parse-resolv-conf
resolve_retries 3 resolve_retries 3
timeout resolve 1s 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); LIST_INIT(&curr_resolvers->resolutions.wait);
HA_SPIN_INIT(&curr_resolvers->lock); 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 */ else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
struct dns_nameserver *newnameserver = NULL; struct dns_nameserver *newnameserver = NULL;
struct sockaddr_storage *sk; struct sockaddr_storage *sk;
int port1, port2; int port1, port2;
struct protocol *proto;
if (!*args[2]) { if (!*args[2]) {
ha_alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n", 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, 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); &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) { if (!sk) {
ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
err_code |= ERR_ALERT | ERR_FATAL; 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; 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); ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
err_code |= ERR_ALERT | ERR_ABORT; err_code |= ERR_ALERT | ERR_ABORT;
goto out; goto out;
@ -3316,18 +3327,6 @@ int cfg_post_parse_resolvers()
if (curr_resolvers->px) { if (curr_resolvers->px) {
srv = curr_resolvers->px->srv; srv = curr_resolvers->px->srv;
while (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 */ /* init ssl if needed */
if (srv->use_ssl == 1 && xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv) { if (srv->use_ssl == 1 && xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv) {
if (xprt_get(XPRT_SSL)->prepare_srv(srv)) { if (xprt_get(XPRT_SSL)->prepare_srv(srv)) {
@ -3336,37 +3335,6 @@ int cfg_post_parse_resolvers()
break; 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; srv = srv->next;
} }
} }