mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-12 05:50:03 -04:00
[v9_9] try multiple addresses per server name in nsupdate
3736. [bug] nsupdate: When specifying a server by name,
fall back to alternate addresses if the first
address for that name is not reachable. [RT #25784]
(cherry picked from commit 842a3e6d0e)
This commit is contained in:
parent
f58bb15f49
commit
1a58baf293
3 changed files with 96 additions and 90 deletions
4
CHANGES
4
CHANGES
|
|
@ -1,3 +1,7 @@
|
|||
3736. [bug] nsupdate: When specifying a server by name,
|
||||
fall back to alternate addresses if the first
|
||||
address for that name is not reachable. [RT #25784]
|
||||
|
||||
3734. [bug] Improve building with libtool. [RT #35314]
|
||||
|
||||
3732. [contrib] Fixed a type mismatch causing the ODBC DLZ
|
||||
|
|
|
|||
|
|
@ -118,6 +118,9 @@ extern int h_errno;
|
|||
|
||||
#define DNSDEFAULTPORT 53
|
||||
|
||||
/* Number of addresses to request from bind9_getaddresses() */
|
||||
#define MAX_SERVERADDRS 4
|
||||
|
||||
static isc_uint16_t dnsport = DNSDEFAULTPORT;
|
||||
|
||||
#ifndef RESOLV_CONF
|
||||
|
|
@ -156,13 +159,11 @@ static dns_tsigkey_t *tsigkey = NULL;
|
|||
static dst_key_t *sig0key = NULL;
|
||||
static lwres_context_t *lwctx = NULL;
|
||||
static lwres_conf_t *lwconf;
|
||||
static isc_sockaddr_t *servers;
|
||||
static isc_sockaddr_t *servers = NULL;
|
||||
static isc_boolean_t default_servers = ISC_TRUE;
|
||||
static int ns_inuse = 0;
|
||||
static int ns_total = 0;
|
||||
static isc_sockaddr_t *userserver = NULL;
|
||||
static isc_sockaddr_t *localaddr = NULL;
|
||||
static isc_sockaddr_t *serveraddr = NULL;
|
||||
static isc_sockaddr_t tempaddr;
|
||||
static const char *keyfile = NULL;
|
||||
static char *keystr = NULL;
|
||||
static isc_entropy_t *entropy = NULL;
|
||||
|
|
@ -713,8 +714,8 @@ static void
|
|||
doshutdown(void) {
|
||||
isc_task_detach(&global_task);
|
||||
|
||||
if (userserver != NULL)
|
||||
isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t));
|
||||
if (servers != NULL)
|
||||
isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t));
|
||||
|
||||
if (localaddr != NULL)
|
||||
isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t));
|
||||
|
|
@ -743,8 +744,6 @@ doshutdown(void) {
|
|||
lwres_conf_clear(lwctx);
|
||||
lwres_context_destroy(&lwctx);
|
||||
|
||||
isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t));
|
||||
|
||||
ddebug("Destroying request manager");
|
||||
dns_requestmgr_detach(&requestmgr);
|
||||
|
||||
|
|
@ -825,17 +824,37 @@ setup_system(void) {
|
|||
(void)lwres_conf_parse(lwctx, RESOLV_CONF);
|
||||
lwconf = lwres_conf_get(lwctx);
|
||||
|
||||
ns_total = lwconf->nsnext;
|
||||
if (ns_total <= 0) {
|
||||
/* No name servers in resolv.conf; default to loopback. */
|
||||
struct in_addr localhost;
|
||||
ns_total = 1;
|
||||
ns_inuse = 0;
|
||||
if (local_only || lwconf->nsnext <= 0) {
|
||||
struct in_addr in;
|
||||
struct in6_addr in6;
|
||||
|
||||
if (local_only && keyfile == NULL)
|
||||
keyfile = SESSION_KEYFILE;
|
||||
|
||||
default_servers = ISC_FALSE;
|
||||
|
||||
if (servers != NULL)
|
||||
isc_mem_put(mctx, servers,
|
||||
ns_total * sizeof(isc_sockaddr_t));
|
||||
|
||||
ns_total = (have_ipv4 ? 1 : 0) + (have_ipv6 ? 1 : 0);
|
||||
servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
|
||||
if (servers == NULL)
|
||||
fatal("out of memory");
|
||||
localhost.s_addr = htonl(INADDR_LOOPBACK);
|
||||
isc_sockaddr_fromin(&servers[0], &localhost, dnsport);
|
||||
|
||||
if (have_ipv4) {
|
||||
in.s_addr = htonl(INADDR_LOOPBACK);
|
||||
isc_sockaddr_fromin(&servers[0], &in, dnsport);
|
||||
}
|
||||
if (have_ipv6) {
|
||||
memset(&in6, 0, sizeof(in6));
|
||||
in6.s6_addr[15] = 1;
|
||||
isc_sockaddr_fromin6(&servers[(have_ipv4 ? 1 : 0)],
|
||||
&in6, dnsport);
|
||||
}
|
||||
} else {
|
||||
ns_total = lwconf->nsnext;
|
||||
servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
|
||||
if (servers == NULL)
|
||||
fatal("out of memory");
|
||||
|
|
@ -845,13 +864,14 @@ setup_system(void) {
|
|||
struct in_addr in4;
|
||||
memmove(&in4,
|
||||
lwconf->nameservers[i].address, 4);
|
||||
isc_sockaddr_fromin(&servers[i], &in4, dnsport);
|
||||
isc_sockaddr_fromin(&servers[i],
|
||||
&in4, dnsport);
|
||||
} else {
|
||||
struct in6_addr in6;
|
||||
memmove(&in6,
|
||||
lwconf->nameservers[i].address, 16);
|
||||
isc_sockaddr_fromin6(&servers[i], &in6,
|
||||
dnsport);
|
||||
isc_sockaddr_fromin6(&servers[i],
|
||||
&in6, dnsport);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -928,17 +948,18 @@ setup_system(void) {
|
|||
}
|
||||
|
||||
static void
|
||||
get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
|
||||
get_addresses(char *host, in_port_t port,
|
||||
isc_sockaddr_t *sockaddr, int naddrs)
|
||||
{
|
||||
int count;
|
||||
isc_result_t result;
|
||||
|
||||
isc_app_block();
|
||||
result = bind9_getaddresses(host, port, sockaddr, 1, &count);
|
||||
result = bind9_getaddresses(host, port, sockaddr, naddrs, &count);
|
||||
isc_app_unblock();
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fatal("couldn't get address for '%s': %s",
|
||||
host, isc_result_totext(result));
|
||||
INSIST(count == 1);
|
||||
}
|
||||
|
||||
#define PARSE_ARGS_FMT "dDML:y:ghlovk:p:r:R::t:u:"
|
||||
|
|
@ -1077,22 +1098,6 @@ parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (local_only) {
|
||||
struct in_addr localhost;
|
||||
|
||||
if (keyfile == NULL)
|
||||
keyfile = SESSION_KEYFILE;
|
||||
|
||||
if (userserver == NULL) {
|
||||
userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
|
||||
if (userserver == NULL)
|
||||
fatal("out of memory");
|
||||
}
|
||||
|
||||
localhost.s_addr = htonl(INADDR_LOOPBACK);
|
||||
isc_sockaddr_fromin(userserver, &localhost, dnsport);
|
||||
}
|
||||
|
||||
#ifdef GSSAPI
|
||||
if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
|
||||
fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
|
||||
|
|
@ -1382,13 +1387,18 @@ evaluate_server(char *cmdline) {
|
|||
}
|
||||
}
|
||||
|
||||
if (userserver == NULL) {
|
||||
userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
|
||||
if (userserver == NULL)
|
||||
fatal("out of memory");
|
||||
}
|
||||
if (servers != NULL)
|
||||
isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t));
|
||||
|
||||
get_address(server, (in_port_t)port, userserver);
|
||||
default_servers = ISC_FALSE;
|
||||
|
||||
ns_total = MAX_SERVERADDRS;
|
||||
servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
|
||||
if (servers == NULL)
|
||||
fatal("out of memory");
|
||||
|
||||
memset(servers, 0, ns_total * sizeof(isc_sockaddr_t));
|
||||
get_addresses(server, (in_port_t)port, servers, ns_total);
|
||||
|
||||
return (STATUS_MORE);
|
||||
}
|
||||
|
|
@ -2225,6 +2235,19 @@ send_update(dns_name_t *zonename, isc_sockaddr_t *master,
|
|||
requests++;
|
||||
}
|
||||
|
||||
static void
|
||||
next_server(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) {
|
||||
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
|
||||
isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
|
||||
fprintf(stderr, "; Communication with %s failed: %s\n",
|
||||
addrbuf, isc_result_totext(eresult));
|
||||
if (++ns_inuse >= ns_total)
|
||||
fatal("could not reach any name server");
|
||||
else
|
||||
ddebug("%s: trying next server", caller);
|
||||
}
|
||||
|
||||
static void
|
||||
recvsoa(isc_task_t *task, isc_event_t *event) {
|
||||
dns_requestevent_t *reqev = NULL;
|
||||
|
|
@ -2269,15 +2292,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
|
||||
if (eresult != ISC_R_SUCCESS) {
|
||||
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
|
||||
isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
|
||||
fprintf(stderr, "; Communication with %s failed: %s\n",
|
||||
addrbuf, isc_result_totext(eresult));
|
||||
if (userserver != NULL)
|
||||
fatal("could not talk to specified name server");
|
||||
else if (++ns_inuse >= lwconf->nsnext)
|
||||
fatal("could not talk to any default name server");
|
||||
next_server("recvsoa", addr, eresult);
|
||||
ddebug("Destroying request [%p]", request);
|
||||
dns_request_destroy(&request);
|
||||
dns_message_renderreset(soaquery);
|
||||
|
|
@ -2299,7 +2314,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
|
|||
check_result(result, "dns_message_create");
|
||||
result = dns_request_getresponse(request, rcvmsg,
|
||||
DNS_MESSAGEPARSE_PRESERVEORDER);
|
||||
if (result == DNS_R_TSIGERRORSET && userserver != NULL) {
|
||||
if (result == DNS_R_TSIGERRORSET && servers != NULL) {
|
||||
dns_message_destroy(&rcvmsg);
|
||||
ddebug("Destroying request [%p]", request);
|
||||
dns_request_destroy(&request);
|
||||
|
|
@ -2415,9 +2430,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
|
|||
fprintf(stderr, "The master is: %s\n", namestr);
|
||||
}
|
||||
|
||||
if (userserver != NULL)
|
||||
serveraddr = userserver;
|
||||
else {
|
||||
if (servers == NULL) {
|
||||
char serverstr[DNS_NAME_MAXTEXT+1];
|
||||
isc_buffer_t buf;
|
||||
|
||||
|
|
@ -2425,8 +2438,14 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
|
|||
result = dns_name_totext(&master, ISC_TRUE, &buf);
|
||||
check_result(result, "dns_name_totext");
|
||||
serverstr[isc_buffer_usedlength(&buf)] = 0;
|
||||
get_address(serverstr, dnsport, &tempaddr);
|
||||
serveraddr = &tempaddr;
|
||||
|
||||
ns_total = MAX_SERVERADDRS;
|
||||
servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
|
||||
if (servers == NULL)
|
||||
fatal("out of memory");
|
||||
|
||||
memset(servers, 0, ns_total * sizeof(isc_sockaddr_t));
|
||||
get_addresses(serverstr, dnsport, servers, ns_total);
|
||||
}
|
||||
dns_rdata_freestruct(&soa);
|
||||
|
||||
|
|
@ -2438,11 +2457,11 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
|
|||
dns_name_dup(&master, mctx, &restart_master);
|
||||
start_gssrequest(&master);
|
||||
} else {
|
||||
send_update(zonename, serveraddr, localaddr);
|
||||
send_update(zonename, &servers[ns_inuse], localaddr);
|
||||
setzoneclass(dns_rdataclass_none);
|
||||
}
|
||||
#else
|
||||
send_update(zonename, serveraddr, localaddr);
|
||||
send_update(zonename, &servers[ns_inuse], localaddr);
|
||||
setzoneclass(dns_rdataclass_none);
|
||||
#endif
|
||||
|
||||
|
|
@ -2468,10 +2487,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
|
|||
dns_request_destroy(&request);
|
||||
dns_message_renderreset(soaquery);
|
||||
dns_message_settsigkey(soaquery, NULL);
|
||||
if (userserver != NULL)
|
||||
sendrequest(localaddr, userserver, soaquery, &request);
|
||||
else
|
||||
sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
|
||||
sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -2488,7 +2504,7 @@ sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
|
|||
reqinfo->msg = msg;
|
||||
reqinfo->addr = destaddr;
|
||||
result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0,
|
||||
(userserver != NULL) ? tsigkey : NULL,
|
||||
default_servers ? NULL : tsigkey,
|
||||
FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
|
||||
global_task, recvsoa, reqinfo, request);
|
||||
check_result(result, "dns_request_createvia");
|
||||
|
|
@ -2580,10 +2596,10 @@ start_gssrequest(dns_name_t *master) {
|
|||
if (kserver == NULL)
|
||||
fatal("out of memory");
|
||||
}
|
||||
if (userserver == NULL)
|
||||
get_address(namestr, dnsport, kserver);
|
||||
if (servers == NULL)
|
||||
get_addresses(namestr, dnsport, kserver, 1);
|
||||
else
|
||||
(void)memmove(kserver, userserver, sizeof(isc_sockaddr_t));
|
||||
memmove(kserver, &servers[ns_inuse], sizeof(isc_sockaddr_t));
|
||||
|
||||
dns_fixedname_init(&fname);
|
||||
servname = dns_fixedname_name(&fname);
|
||||
|
|
@ -2712,20 +2728,11 @@ recvgss(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
|
||||
if (eresult != ISC_R_SUCCESS) {
|
||||
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
|
||||
isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
|
||||
fprintf(stderr, "; Communication with %s failed: %s\n",
|
||||
addrbuf, isc_result_totext(eresult));
|
||||
if (userserver != NULL)
|
||||
fatal("could not talk to specified name server");
|
||||
else if (++ns_inuse >= lwconf->nsnext)
|
||||
fatal("could not talk to any default name server");
|
||||
next_server("recvgss", addr, eresult);
|
||||
ddebug("Destroying request [%p]", request);
|
||||
dns_request_destroy(&request);
|
||||
dns_message_renderreset(tsigquery);
|
||||
sendrequest(localaddr, &servers[ns_inuse], tsigquery,
|
||||
&request);
|
||||
sendrequest(localaddr, &servers[ns_inuse], tsigquery, &request);
|
||||
isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
|
||||
isc_event_free(&event);
|
||||
return;
|
||||
|
|
@ -2813,7 +2820,7 @@ recvgss(isc_task_t *task, isc_event_t *event) {
|
|||
check_result(result, "dns_message_checksig");
|
||||
#endif /* 0 */
|
||||
|
||||
send_update(&tmpzonename, serveraddr, localaddr);
|
||||
send_update(&tmpzonename, &servers[ns_inuse], localaddr);
|
||||
setzoneclass(dns_rdataclass_none);
|
||||
break;
|
||||
|
||||
|
|
@ -2847,8 +2854,8 @@ start_update(void) {
|
|||
if (answer != NULL)
|
||||
dns_message_destroy(&answer);
|
||||
|
||||
if (userzone != NULL && userserver != NULL && ! usegsstsig) {
|
||||
send_update(userzone, userserver, localaddr);
|
||||
if (userzone != NULL && ! usegsstsig) {
|
||||
send_update(userzone, &servers[ns_inuse], localaddr);
|
||||
setzoneclass(dns_rdataclass_none);
|
||||
return;
|
||||
}
|
||||
|
|
@ -2857,7 +2864,7 @@ start_update(void) {
|
|||
&soaquery);
|
||||
check_result(result, "dns_message_create");
|
||||
|
||||
if (userserver == NULL)
|
||||
if (default_servers)
|
||||
soaquery->flags |= DNS_MESSAGEFLAG_RD;
|
||||
|
||||
result = dns_message_gettempname(soaquery, &name);
|
||||
|
|
@ -2909,12 +2916,8 @@ start_update(void) {
|
|||
ISC_LIST_APPEND(name->list, rdataset, link);
|
||||
dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
|
||||
|
||||
if (userserver != NULL)
|
||||
sendrequest(localaddr, userserver, soaquery, &request);
|
||||
else {
|
||||
ns_inuse = 0;
|
||||
sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
|
||||
}
|
||||
ns_inuse = 0;
|
||||
sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -129,7 +129,6 @@ bind9_getaddresses(const char *hostname, in_port_t port,
|
|||
|
||||
*addrcount = 1;
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
}
|
||||
}
|
||||
#ifdef USE_GETADDRINFO
|
||||
|
|
|
|||
Loading…
Reference in a new issue