diff --git a/CHANGES b/CHANGES index b8822805d4..69c542329f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +6054. [func] Refactor remote servers (primaries, parental-agents) + in zone.c. Store common code in new source files + remote.c and remote.h. Introduce a new way to set the + source address and port. [GL !7110] + 6053. [bug] Fix an ADB quota management bug in resolver. [GL #3752] 6052. [func] Replace DNS over TCP and DNS over TLS transports diff --git a/bin/named/config.c b/bin/named/config.c index 1824f7da95..6dda569921 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -497,109 +497,6 @@ named_config_getzonetype(const cfg_obj_t *zonetypeobj) { return (ztype); } -isc_result_t -named_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list, - in_port_t defport, isc_mem_t *mctx, - isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp, - uint32_t *countp) { - int count, i = 0; - const cfg_obj_t *addrlist; - const cfg_obj_t *portobj, *dscpobj; - const cfg_listelt_t *element; - isc_sockaddr_t *addrs; - in_port_t port; - isc_dscp_t dscp = -1, *dscps = NULL; - isc_result_t result; - - INSIST(addrsp != NULL && *addrsp == NULL); - INSIST(dscpsp == NULL || *dscpsp == NULL); - INSIST(countp != NULL); - - addrlist = cfg_tuple_get(list, "addresses"); - count = named_config_listcount(addrlist); - - portobj = cfg_tuple_get(list, "port"); - if (cfg_obj_isuint32(portobj)) { - uint32_t val = cfg_obj_asuint32(portobj); - if (val > UINT16_MAX) { - cfg_obj_log(portobj, named_g_lctx, ISC_LOG_ERROR, - "port '%u' out of range", val); - return (ISC_R_RANGE); - } - port = (in_port_t)val; - } else if (defport != 0) { - port = defport; - } else { - result = named_config_getport(config, "port", &port); - if (result != ISC_R_SUCCESS) { - return (result); - } - } - - if (dscpsp != NULL) { - dscpobj = cfg_tuple_get(list, "dscp"); - if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) { - if (cfg_obj_asuint32(dscpobj) > 63) { - cfg_obj_log(dscpobj, named_g_lctx, - ISC_LOG_ERROR, - "dscp value '%u' is out of range", - cfg_obj_asuint32(dscpobj)); - return (ISC_R_RANGE); - } - dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj); - } - - dscps = isc_mem_get(mctx, count * sizeof(isc_dscp_t)); - } - - addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t)); - - for (element = cfg_list_first(addrlist); element != NULL; - element = cfg_list_next(element), i++) - { - const cfg_obj_t *addr; - INSIST(i < count); - addr = cfg_listelt_value(element); - addrs[i] = *cfg_obj_assockaddr(addr); - if (dscpsp != NULL) { - isc_dscp_t innerdscp; - innerdscp = cfg_obj_getdscp(addr); - if (innerdscp == -1) { - innerdscp = dscp; - } - dscps[i] = innerdscp; - } - if (isc_sockaddr_getport(&addrs[i]) == 0) { - isc_sockaddr_setport(&addrs[i], port); - } - } - INSIST(i == count); - - *addrsp = addrs; - *countp = count; - - if (dscpsp != NULL) { - *dscpsp = dscps; - } - - return (ISC_R_SUCCESS); -} - -void -named_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp, - isc_dscp_t **dscpsp, uint32_t count) { - INSIST(addrsp != NULL && *addrsp != NULL); - INSIST(dscpsp == NULL || *dscpsp != NULL); - - isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t)); - *addrsp = NULL; - - if (dscpsp != NULL) { - isc_mem_put(mctx, *dscpsp, count * sizeof(isc_dscp_t)); - *dscpsp = NULL; - } -} - static isc_result_t getremotesdef(const cfg_obj_t *cctx, const char *list, const char *name, const cfg_obj_t **ret) { @@ -702,30 +599,41 @@ isc_result_t named_config_getipandkeylist(const cfg_obj_t *config, const char *listtype, const cfg_obj_t *list, isc_mem_t *mctx, dns_ipkeylist_t *ipkl) { - uint32_t addrcount = 0, dscpcount = 0, keycount = 0, tlscount = 0, - i = 0; - uint32_t listcount = 0, l = 0, j; + uint32_t addrcount = 0, srccount = 0, dscpcount = 0; + uint32_t keycount = 0, tlscount = 0; + uint32_t listcount = 0, l = 0, i = 0; uint32_t stackcount = 0, pushed = 0; isc_result_t result; const cfg_listelt_t *element; const cfg_obj_t *addrlist; const cfg_obj_t *portobj; const cfg_obj_t *dscpobj; + const cfg_obj_t *src4obj; + const cfg_obj_t *src6obj; in_port_t port = (in_port_t)0; in_port_t def_port; in_port_t def_tlsport; + isc_sockaddr_t src4; + isc_sockaddr_t src6; isc_dscp_t dscp = -1; isc_sockaddr_t *addrs = NULL; + isc_sockaddr_t *sources = NULL; isc_dscp_t *dscps = NULL; dns_name_t **keys = NULL; dns_name_t **tlss = NULL; struct { const char *name; + in_port_t port; + isc_dscp_t dscp; + isc_sockaddr_t *src4s; + isc_sockaddr_t *src6s; } *lists = NULL; struct { const cfg_listelt_t *element; in_port_t port; isc_dscp_t dscp; + isc_sockaddr_t src4; + isc_sockaddr_t src6; } *stack = NULL; REQUIRE(ipkl != NULL); @@ -759,6 +667,8 @@ newlist: addrlist = cfg_tuple_get(list, "addresses"); portobj = cfg_tuple_get(list, "port"); dscpobj = cfg_tuple_get(list, "dscp"); + src4obj = cfg_tuple_get(list, "source"); + src6obj = cfg_tuple_get(list, "source-v6"); if (cfg_obj_isuint32(portobj)) { uint32_t val = cfg_obj_asuint32(portobj); @@ -782,6 +692,18 @@ newlist: dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj); } + if (src4obj != NULL && cfg_obj_issockaddr(src4obj)) { + src4 = *cfg_obj_assockaddr(src4obj); + } else { + isc_sockaddr_any(&src4); + } + + if (src6obj != NULL && cfg_obj_issockaddr(src6obj)) { + src6 = *cfg_obj_assockaddr(src6obj); + } else { + isc_sockaddr_any6(&src6); + } + result = ISC_R_NOMEMORY; element = cfg_list_first(addrlist); @@ -799,6 +721,7 @@ resume: if (!cfg_obj_issockaddr(addr)) { const char *listname = cfg_obj_asstring(addr); isc_result_t tresult; + uint32_t j; /* Grow lists? */ grow_array(mctx, lists, l, listcount); @@ -836,6 +759,8 @@ resume: stack[pushed].element = cfg_list_next(element); stack[pushed].port = port; stack[pushed].dscp = dscp; + stack[pushed].src4 = src4; + stack[pushed].src6 = src6; pushed++; goto newlist; } @@ -844,6 +769,7 @@ resume: grow_array(mctx, dscps, i, dscpcount); grow_array(mctx, keys, i, keycount); grow_array(mctx, tlss, i, tlscount); + grow_array(mctx, sources, i, srccount); addrs[i] = *cfg_obj_assockaddr(addr); dscps[i] = cfg_obj_getdscp(addr); @@ -881,6 +807,20 @@ resume: isc_sockaddr_setport(&addrs[i], addr_port); } + switch (isc_sockaddr_pf(&addrs[i])) { + case PF_INET: + sources[i] = src4; + break; + case PF_INET6: + sources[i] = src6; + break; + default: + i++; /* Increment here so that cleanup on error works. + */ + result = ISC_R_NOTIMPLEMENTED; + goto cleanup; + } + i++; } if (pushed != 0) { @@ -888,6 +828,8 @@ resume: element = stack[pushed].element; port = stack[pushed].port; dscp = stack[pushed].dscp; + src4 = stack[pushed].src4; + src6 = stack[pushed].src6; goto resume; } @@ -895,6 +837,7 @@ resume: shrink_array(mctx, dscps, i, dscpcount); shrink_array(mctx, keys, i, keycount); shrink_array(mctx, tlss, i, tlscount); + shrink_array(mctx, sources, i, srccount); if (lists != NULL) { isc_mem_put(mctx, lists, listcount * sizeof(lists[0])); @@ -906,12 +849,14 @@ resume: INSIST(dscpcount == addrcount); INSIST(keycount == addrcount); INSIST(tlscount == addrcount); + INSIST(srccount == addrcount); INSIST(keycount == dscpcount); ipkl->addrs = addrs; ipkl->dscps = dscps; ipkl->keys = keys; ipkl->tlss = tlss; + ipkl->sources = sources; ipkl->count = addrcount; ipkl->allocated = addrcount; @@ -925,7 +870,7 @@ cleanup: isc_mem_put(mctx, dscps, dscpcount * sizeof(dscps[0])); } if (keys != NULL) { - for (j = 0; j < i; j++) { + for (size_t j = 0; j < i; j++) { if (keys[j] == NULL) { continue; } @@ -937,7 +882,7 @@ cleanup: isc_mem_put(mctx, keys, keycount * sizeof(keys[0])); } if (tlss != NULL) { - for (j = 0; j < i; j++) { + for (size_t j = 0; j < i; j++) { if (tlss[j] == NULL) { continue; } @@ -948,6 +893,9 @@ cleanup: } isc_mem_put(mctx, tlss, tlscount * sizeof(tlss[0])); } + if (sources != NULL) { + isc_mem_put(mctx, sources, srccount * sizeof(sources[0])); + } if (lists != NULL) { isc_mem_put(mctx, lists, listcount * sizeof(lists[0])); } diff --git a/bin/named/include/named/config.h b/bin/named/include/named/config.h index 834c53f6e7..509f3bd24c 100644 --- a/bin/named/include/named/config.h +++ b/bin/named/include/named/config.h @@ -52,16 +52,6 @@ named_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype, dns_zonetype_t named_config_getzonetype(const cfg_obj_t *zonetypeobj); -isc_result_t -named_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list, - in_port_t defport, isc_mem_t *mctx, - isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp, - uint32_t *countp); - -void -named_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp, - isc_dscp_t **dscpsp, uint32_t count); - isc_result_t named_config_getremotesdef(const cfg_obj_t *cctx, const char *list, const char *name, const cfg_obj_t **ret); diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 795db7bf6e..af017f3198 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -1268,12 +1268,13 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, RETERR(named_config_getipandkeylist(config, "primaries", obj, mctx, &ipkl)); - dns_zone_setalsonotify(zone, ipkl.addrs, ipkl.dscps, - ipkl.keys, ipkl.tlss, + dns_zone_setalsonotify(zone, ipkl.addrs, ipkl.sources, + ipkl.dscps, ipkl.keys, ipkl.tlss, ipkl.count); dns_ipkeylist_clear(mctx, &ipkl); } else { - dns_zone_setalsonotify(zone, NULL, NULL, NULL, NULL, 0); + dns_zone_setalsonotify(zone, NULL, NULL, NULL, NULL, + NULL, 0); } obj = NULL; @@ -1722,11 +1723,11 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, dns_ipkeylist_init(&ipkl); RETERR(named_config_getipandkeylist( config, "parental-agents", obj, mctx, &ipkl)); - dns_zone_setparentals(zone, ipkl.addrs, ipkl.keys, - ipkl.tlss, ipkl.count); + dns_zone_setparentals(zone, ipkl.addrs, ipkl.sources, + ipkl.keys, ipkl.tlss, ipkl.count); dns_ipkeylist_clear(mctx, &ipkl); } else { - dns_zone_setparentals(zone, NULL, NULL, NULL, 0); + dns_zone_setparentals(zone, NULL, NULL, NULL, NULL, 0); } } @@ -1890,12 +1891,14 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, RETERR(named_config_getipandkeylist(config, "primaries", obj, mctx, &ipkl)); - dns_zone_setprimaries(mayberaw, ipkl.addrs, ipkl.keys, + dns_zone_setprimaries(mayberaw, ipkl.addrs, + ipkl.sources, ipkl.keys, ipkl.tlss, ipkl.count); count = ipkl.count; dns_ipkeylist_clear(mctx, &ipkl); } else { - dns_zone_setprimaries(mayberaw, NULL, NULL, NULL, 0); + dns_zone_setprimaries(mayberaw, NULL, NULL, NULL, NULL, + 0); } multi = false; diff --git a/bin/tests/system/checkconf/good.conf.in b/bin/tests/system/checkconf/good.conf.in index 46b15a8559..8ecf392063 100644 --- a/bin/tests/system/checkconf/good.conf.in +++ b/bin/tests/system/checkconf/good.conf.in @@ -82,9 +82,9 @@ options { transfer-source 0.0.0.0 dscp 63; zone-statistics none; }; -parental-agents "parents" { +parental-agents "parents" port 5353 source 10.10.10.10 port 5354 dscp 54 source-v6 2001:db8::10 port 5355 dscp 55 { 10.10.10.11; - 10.10.10.12; + 2001:db8::11; }; view "first" { match-clients { diff --git a/bin/tests/system/checkds/ns2/named.conf.in b/bin/tests/system/checkds/ns2/named.conf.in index 8086055d75..f49cec8c94 100644 --- a/bin/tests/system/checkds/ns2/named.conf.in +++ b/bin/tests/system/checkds/ns2/named.conf.in @@ -41,5 +41,6 @@ zone "." { zone "checkds" { type primary; + allow-transfer { 10.53.0.2; 10.53.0.4; }; file "checkds.db"; }; diff --git a/bin/tests/system/checkds/ns4/named.conf.in b/bin/tests/system/checkds/ns4/named.conf.in index 84aabde456..e808287b38 100644 --- a/bin/tests/system/checkds/ns4/named.conf.in +++ b/bin/tests/system/checkds/ns4/named.conf.in @@ -37,5 +37,5 @@ controls { zone "checkds" { type secondary; file "checkds.db"; - primaries { 10.53.0.2 port @PORT@; }; + primaries source 10.53.0.4 { 10.53.0.2 port @PORT@; }; }; diff --git a/bin/tests/system/checkds/ns5/named.conf.in b/bin/tests/system/checkds/ns5/named.conf.in index 2a306776cb..dd0f0790d4 100644 --- a/bin/tests/system/checkds/ns5/named.conf.in +++ b/bin/tests/system/checkds/ns5/named.conf.in @@ -41,5 +41,6 @@ zone "." { zone "checkds" { type primary; + allow-transfer { 10.53.0.5; 10.53.0.7; }; file "checkds.db"; }; diff --git a/bin/tests/system/checkds/ns7/named.conf.in b/bin/tests/system/checkds/ns7/named.conf.in index 9b966ccd05..e8ea33306c 100644 --- a/bin/tests/system/checkds/ns7/named.conf.in +++ b/bin/tests/system/checkds/ns7/named.conf.in @@ -42,5 +42,5 @@ zone "." { zone "checkds" { type secondary; file "checkds.db"; - primaries { 10.53.0.5 port @PORT@; }; + primaries source 10.53.0.7 { 10.53.0.5 port @PORT@; }; }; diff --git a/bin/tests/system/xfer/ns1/named.conf.in b/bin/tests/system/xfer/ns1/named.conf.in index 1cd72719f8..26bca1943e 100644 --- a/bin/tests/system/xfer/ns1/named.conf.in +++ b/bin/tests/system/xfer/ns1/named.conf.in @@ -36,6 +36,7 @@ zone "." { zone "secondary" { type primary; + allow-transfer { 10.53.0.1; 10.53.0.2; 10.53.0.6; 10.53.0.7; }; file "sec.db"; }; diff --git a/bin/tests/system/xfer/ns2/named.conf.in b/bin/tests/system/xfer/ns2/named.conf.in index 17e7d8ad4e..7b95f5a621 100644 --- a/bin/tests/system/xfer/ns2/named.conf.in +++ b/bin/tests/system/xfer/ns2/named.conf.in @@ -59,10 +59,14 @@ zone "tsigzone" { allow-transfer { tzkey; }; }; +primaries "ns1" port @PORT@ source 10.53.0.2 { + 10.53.0.1; +}; + zone "secondary" { type secondary; file "sec.db"; - primaries { 10.53.0.1; }; + primaries { ns1; }; masterfile-format text; }; diff --git a/doc/man/named.conf.5in b/doc/man/named.conf.5in index b03ef74839..a1fbfa5d3b 100644 --- a/doc/man/named.conf.5in +++ b/doc/man/named.conf.5in @@ -126,7 +126,7 @@ options { allow\-transfer [ port ] [ transport ] { ; ... }; allow\-update { ; ... }; allow\-update\-forwarding { ; ... }; - also\-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + also\-notify [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt\-transfer\-source ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated alt\-transfer\-source\-v6 ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated answer\-cookie ; @@ -138,7 +138,7 @@ options { avoid\-v6\-udp\-ports { ; ... }; bindkeys\-file ; blackhole { ; ... }; - catalog\-zones { zone [ default\-primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone\-directory ] [ in\-memory ] [ min\-update\-interval ]; ... }; + catalog\-zones { zone [ default\-primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone\-directory ] [ in\-memory ] [ min\-update\-interval ]; ... }; check\-dup\-records ( fail | warn | ignore ); check\-integrity ; check\-mx ( fail | warn | ignore ); @@ -373,11 +373,11 @@ options { zone\-statistics ( full | terse | none | ); }; -parental\-agents [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times +parental\-agents [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times plugin ( query ) [ { } ]; // may occur multiple times -primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times +primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times server { bogus ; @@ -437,13 +437,13 @@ view [ ] { allow\-transfer [ port ] [ transport ] { ; ... }; allow\-update { ; ... }; allow\-update\-forwarding { ; ... }; - also\-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + also\-notify [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt\-transfer\-source ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated alt\-transfer\-source\-v6 ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated attach\-cache ; auth\-nxdomain ; auto\-dnssec ( allow | maintain | off ); // deprecated - catalog\-zones { zone [ default\-primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone\-directory ] [ in\-memory ] [ min\-update\-interval ]; ... }; + catalog\-zones { zone [ default\-primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone\-directory ] [ in\-memory ] [ min\-update\-interval ]; ... }; check\-dup\-records ( fail | warn | ignore ); check\-integrity ; check\-mx ( fail | warn | ignore ); @@ -666,7 +666,7 @@ zone [ ] { allow\-query\-on { ; ... }; allow\-transfer [ port ] [ transport ] { ; ... }; allow\-update { ; ... }; - also\-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + also\-notify [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt\-transfer\-source ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated alt\-transfer\-source\-v6 ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated auto\-dnssec ( allow | maintain | off ); // deprecated @@ -710,7 +710,7 @@ zone [ ] { notify\-source\-v6 ( | * ) [ port ( | * ) ] [ dscp ]; notify\-to\-soa ; nsec3\-test\-zone ; // test only - parental\-agents [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + parental\-agents [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; parental\-source ( | * ) [ port ( | * ) ] [ dscp ]; parental\-source\-v6 ( | * ) [ port ( | * ) ] [ dscp ]; serial\-update\-method ( date | increment | unixtime ); @@ -740,7 +740,7 @@ zone [ ] { allow\-query\-on { ; ... }; allow\-transfer [ port ] [ transport ] { ; ... }; allow\-update\-forwarding { ; ... }; - also\-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + also\-notify [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt\-transfer\-source ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated alt\-transfer\-source\-v6 ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated auto\-dnssec ( allow | maintain | off ); // deprecated @@ -780,10 +780,10 @@ zone [ ] { notify\-source\-v6 ( | * ) [ port ( | * ) ] [ dscp ]; notify\-to\-soa ; nsec3\-test\-zone ; // test only - parental\-agents [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + parental\-agents [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; parental\-source ( | * ) [ port ( | * ) ] [ dscp ]; parental\-source\-v6 ( | * ) [ port ( | * ) ] [ dscp ]; - primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; request\-expire ; request\-ixfr ; sig\-signing\-nodes ; @@ -815,7 +815,7 @@ zone [ ] { allow\-query\-on { ; ... }; allow\-transfer [ port ] [ transport ] { ; ... }; allow\-update\-forwarding { ; ... }; - also\-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + also\-notify [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt\-transfer\-source ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated alt\-transfer\-source\-v6 ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated check\-names ( fail | warn | ignore ); @@ -841,7 +841,7 @@ zone [ ] { notify\-delay ; notify\-source ( | * ) [ port ( | * ) ] [ dscp ]; notify\-source\-v6 ( | * ) [ port ( | * ) ] [ dscp ]; - primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; request\-expire ; request\-ixfr ; transfer\-source ( | * ) [ port ( | * ) ] [ dscp ]; @@ -903,7 +903,7 @@ zone [ ] { masterfile\-style ( full | relative ); max\-records ; max\-zone\-ttl ( unlimited | ); // deprecated - primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; zone\-statistics ( full | terse | none | ); }; @@ -958,7 +958,7 @@ zone [ ] { min\-refresh\-time ; min\-retry\-time ; multi\-master ; - primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source\-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; transfer\-source ( | * ) [ port ( | * ) ] [ dscp ]; transfer\-source\-v6 ( | * ) [ port ( | * ) ] [ dscp ]; use\-alt\-transfer\-source ; // deprecated diff --git a/doc/misc/mirror.zoneopt b/doc/misc/mirror.zoneopt index 90a0b97a59..959a733193 100644 --- a/doc/misc/mirror.zoneopt +++ b/doc/misc/mirror.zoneopt @@ -5,7 +5,7 @@ zone [ ] { allow-query-on { ; ... }; allow-transfer [ port ] [ transport ] { ; ... }; allow-update-forwarding { ; ... }; - also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + also-notify [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated alt-transfer-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated check-names ( fail | warn | ignore ); @@ -31,7 +31,7 @@ zone [ ] { notify-delay ; notify-source ( | * ) [ port ( | * ) ] [ dscp ]; notify-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; - primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; request-expire ; request-ixfr ; transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; diff --git a/doc/misc/options b/doc/misc/options index ce8f20a917..ea1f7d770f 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -69,7 +69,7 @@ options { allow-transfer [ port ] [ transport ] { ; ... }; allow-update { ; ... }; allow-update-forwarding { ; ... }; - also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + also-notify [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated alt-transfer-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated answer-cookie ; @@ -81,7 +81,7 @@ options { avoid-v6-udp-ports { ; ... }; bindkeys-file ; blackhole { ; ... }; - catalog-zones { zone [ default-primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone-directory ] [ in-memory ] [ min-update-interval ]; ... }; + catalog-zones { zone [ default-primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone-directory ] [ in-memory ] [ min-update-interval ]; ... }; check-dup-records ( fail | warn | ignore ); check-integrity ; check-mx ( fail | warn | ignore ); @@ -316,11 +316,11 @@ options { zone-statistics ( full | terse | none | ); }; -parental-agents [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times +parental-agents [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times plugin ( query ) [ { } ]; // may occur multiple times -primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times +primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; // may occur multiple times server { bogus ; @@ -380,13 +380,13 @@ view [ ] { allow-transfer [ port ] [ transport ] { ; ... }; allow-update { ; ... }; allow-update-forwarding { ; ... }; - also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + also-notify [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated alt-transfer-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated attach-cache ; auth-nxdomain ; auto-dnssec ( allow | maintain | off ); // deprecated - catalog-zones { zone [ default-primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone-directory ] [ in-memory ] [ min-update-interval ]; ... }; + catalog-zones { zone [ default-primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... } ] [ zone-directory ] [ in-memory ] [ min-update-interval ]; ... }; check-dup-records ( fail | warn | ignore ); check-integrity ; check-mx ( fail | warn | ignore ); diff --git a/doc/misc/primary.zoneopt b/doc/misc/primary.zoneopt index 78c3293442..75d1bccadf 100644 --- a/doc/misc/primary.zoneopt +++ b/doc/misc/primary.zoneopt @@ -4,7 +4,7 @@ zone [ ] { allow-query-on { ; ... }; allow-transfer [ port ] [ transport ] { ; ... }; allow-update { ; ... }; - also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + also-notify [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated alt-transfer-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated auto-dnssec ( allow | maintain | off ); // deprecated @@ -48,7 +48,7 @@ zone [ ] { notify-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; notify-to-soa ; nsec3-test-zone ; // test only - parental-agents [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + parental-agents [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; parental-source ( | * ) [ port ( | * ) ] [ dscp ]; parental-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; serial-update-method ( date | increment | unixtime ); diff --git a/doc/misc/redirect.zoneopt b/doc/misc/redirect.zoneopt index 845ca96062..5103121cef 100644 --- a/doc/misc/redirect.zoneopt +++ b/doc/misc/redirect.zoneopt @@ -8,6 +8,6 @@ zone [ ] { masterfile-style ( full | relative ); max-records ; max-zone-ttl ( unlimited | ); // deprecated - primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; zone-statistics ( full | terse | none | ); }; diff --git a/doc/misc/secondary.zoneopt b/doc/misc/secondary.zoneopt index 75c99e3973..f20c5d1d0c 100644 --- a/doc/misc/secondary.zoneopt +++ b/doc/misc/secondary.zoneopt @@ -5,7 +5,7 @@ zone [ ] { allow-query-on { ; ... }; allow-transfer [ port ] [ transport ] { ; ... }; allow-update-forwarding { ; ... }; - also-notify [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + also-notify [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; alt-transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated alt-transfer-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; // deprecated auto-dnssec ( allow | maintain | off ); // deprecated @@ -45,10 +45,10 @@ zone [ ] { notify-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; notify-to-soa ; nsec3-test-zone ; // test only - parental-agents [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + parental-agents [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; parental-source ( | * ) [ port ( | * ) ] [ dscp ]; parental-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; - primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; request-expire ; request-ixfr ; sig-signing-nodes ; diff --git a/doc/misc/stub.zoneopt b/doc/misc/stub.zoneopt index d5b0ba5144..74e2c73317 100644 --- a/doc/misc/stub.zoneopt +++ b/doc/misc/stub.zoneopt @@ -19,7 +19,7 @@ zone [ ] { min-refresh-time ; min-retry-time ; multi-master ; - primaries [ port ] [ dscp ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; + primaries [ port ] [ dscp ] [ source ( | * ) [ port ( | * ) ] [ dscp ] ] [ source-v6 ( | * ) [ port ( | * ) ] [ dscp ] ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; transfer-source ( | * ) [ port ( | * ) ] [ dscp ]; transfer-source-v6 ( | * ) [ port ( | * ) ] [ dscp ]; use-alt-transfer-source ; // deprecated diff --git a/doc/notes/notes-current.rst b/doc/notes/notes-current.rst index 89ea907102..99305ea1ee 100644 --- a/doc/notes/notes-current.rst +++ b/doc/notes/notes-current.rst @@ -30,7 +30,9 @@ Removed Features Feature Changes ~~~~~~~~~~~~~~~ -- None. +- Add the ability to configure the preferred source address when talking to + remote servers such as :any:`primaries` and any:`parental-agents`. + :gl:`!7110` - Replace DNS over TCP and DNS over TLS transports code with a new, unified transport implementation. :gl:`#3374` diff --git a/lib/dns/Makefile.am b/lib/dns/Makefile.am index 0fad435ada..4f657192ab 100644 --- a/lib/dns/Makefile.am +++ b/lib/dns/Makefile.am @@ -109,6 +109,7 @@ libdns_la_HEADERS = \ include/dns/rdatasetiter.h \ include/dns/rdataslab.h \ include/dns/rdatatype.h \ + include/dns/remote.h \ include/dns/request.h \ include/dns/resolver.h \ include/dns/result.h \ @@ -211,6 +212,7 @@ libdns_la_SOURCES = \ rdataset.c \ rdatasetiter.c \ rdataslab.c \ + remote.c \ request.c \ resolver.c \ result.c \ diff --git a/lib/dns/include/dns/ipkeylist.h b/lib/dns/include/dns/ipkeylist.h index 5a87cdb11a..e74f293fe8 100644 --- a/lib/dns/include/dns/ipkeylist.h +++ b/lib/dns/include/dns/ipkeylist.h @@ -26,6 +26,7 @@ struct dns_ipkeylist { isc_sockaddr_t *addrs; isc_dscp_t *dscps; + isc_sockaddr_t *sources; dns_name_t **keys; dns_name_t **tlss; dns_name_t **labels; diff --git a/lib/dns/include/dns/remote.h b/lib/dns/include/dns/remote.h new file mode 100644 index 0000000000..bf13767954 --- /dev/null +++ b/lib/dns/include/dns/remote.h @@ -0,0 +1,250 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file dns/remote.h */ + +#include + +#include +#include +#include + +#include + +ISC_LANG_BEGINDECLS + +#define DNS_REMOTE_MAGIC ISC_MAGIC('R', 'm', 't', 'e') +#define DNS_REMOTE_VALID(remote) ISC_MAGIC_VALID(remote, DNS_REMOTE_MAGIC) + +struct dns_remote { + unsigned int magic; + isc_mem_t *mctx; + isc_sockaddr_t *addresses; + isc_sockaddr_t *sources; + isc_dscp_t *dscps; + dns_name_t **keynames; + dns_name_t **tlsnames; + bool *ok; + unsigned int addrcnt; + unsigned int curraddr; +}; + +isc_sockaddr_t * +dns_remote_addresses(dns_remote_t *remote); +/*%< + * Return the addresses of the remote server. + * + * Requires: + * 'remote' is a valid remote structure. + */ + +isc_sockaddr_t * +dns_remote_sources(dns_remote_t *remote); +/*%< + * Return the source addresses to be used for the remote server. + * + * Requires: + * 'remote' is a valid remote structure. + */ + +unsigned int +dns_remote_count(dns_remote_t *remote); +/*%< + * Return the number of addresses of the remote server. + * + * Requires: + * 'remote' is a valid remote structure. + */ + +dns_name_t ** +dns_remote_keynames(dns_remote_t *remote); +/*%< + * Return the keynames of the remote server. + * + * Requires: + * 'remote' is a valid remote structure. + */ + +dns_name_t ** +dns_remote_tlsnames(dns_remote_t *remote); +/*%< + * Return the tlsnames of the remote server. + * + * Requires: + * 'remote' is a valid remote structure. + */ + +void +dns_remote_init(dns_remote_t *remote, unsigned int count, + const isc_sockaddr_t *addrs, const isc_sockaddr_t *srcs, + const isc_dscp_t *dscp, dns_name_t **keynames, + dns_name_t **tlsnames, bool mark, isc_mem_t *mctx); + +/*%< + * Initialize a remote server. Set the provided addresses (addrs), + * source addresses (srcs), dscp's (dscp), key names (keynames) and + * tls names (tlsnames). Use the provided memory context (mctx) for + * allocations. If 'mark' is 'true', set up a list of boolean values to + * mark the server bad or good. + * + * Requires: + * 'remote' is a valid remote structure. + * 'mctx' is not NULL. + * 'addrs' is not NULL, or 'count' equals zero. + * 'keynames' and 'tlsnames' are not NULL, then 'count > 0'. + */ + +void +dns_remote_clear(dns_remote_t *remote); +/*%< + * Clear remote server 'remote', free memory. + * + * Requires: + * 'remote' is a valid remote structure. + */ + +bool +dns_remote_equal(dns_remote_t *a, dns_remote_t *b); +/*%< + * Compare two remote servers 'a' and 'b'. Check if the address + * count, the addresses, the dscps, the key names and the tls names are + * the same. Return 'true' if so, 'false' otherwise. + * + * Requires: + * 'a' and 'b' are valid remote structures. + */ + +void +dns_remote_reset(dns_remote_t *remote, bool clear_ok); +/*%< + * Reset the remote server, set the current address back to the + * first. If 'clear_ok' is 'true', clear any servers marked ok. + * + * Requires: + * 'remote' is a valid remote structure. + */ + +void +dns_remote_next(dns_remote_t *remote, bool skip_good); +/*%< + * Skip to the next address. If 'skip_good' is 'true', skip over + * already addresses already considered good, whatever good means in the + * context of this remote server. + * + * Requires: + * 'remote' is a valid remote structure. + */ + +isc_sockaddr_t +dns_remote_curraddr(dns_remote_t *remote); +/*%< + * Return the currently used address for this remote server. + * + * Requires: + * 'remote' is a valid remote structure. + * 'remote->addresses' is not NULL. + */ + +isc_sockaddr_t +dns_remote_sourceaddr(dns_remote_t *remote); +/*%< + * Return the current source address. + * + * Requires: + * 'remote' is a valid remote structure. + * 'remote->sources' is not NULL. + */ + +isc_sockaddr_t +dns_remote_addr(dns_remote_t *remote, unsigned int i); +/*%< + * Return the address at index 'i'. + * + * Requires: + * 'remote' is a valid remote structure. + * 'remote->addresses' is not NULL. + */ + +isc_dscp_t +dns_remote_dscp(dns_remote_t *remote); +/*%< + * Return the current dscp. Returns -1 if we have iterated over all + * addresses already, or if dscps are not used. + * + * Requires: + * 'remote' is a valid remote structure. + */ + +dns_name_t * +dns_remote_keyname(dns_remote_t *remote); +/*%< + * Return the current key name. Returns NULL if we have iterated + * over all addresses already, or if keynames are not used. + * + * Requires: + * 'remote' is a valid remote structure. + */ + +dns_name_t * +dns_remote_tlsname(dns_remote_t *remote); +/*%< + * Return the current tls name. Returns NULL if we have iterated + * over all addresses already, or if tlsnames are not used. + * + * Requires: + * 'remote' is a valid remote structure. + */ + +bool +dns_remote_allgood(dns_remote_t *remote); +/*%< + * Return 'true' if all the addresses are considered good. + * + * Requires: + * 'remote' is a valid remote structure. + */ + +void +dns_remote_mark(dns_remote_t *remote, bool good); +/*%< + * Mark the current address 'good' (or not good if 'good' is + * 'false'). + * + * Requires: + * 'remote' is a valid remote structure. + * The current address index is lower than the address count. + */ + +bool +dns_remote_addrok(dns_remote_t *remote); +/*%< + * Return 'true' if the current address is marked good, 'false' + * otherwise. Also return 'true' if marking servers is not used. + * + * Requires: + * 'remote' is a valid remote structure. + * The current address index is lower than the address count. + */ + +bool +dns_remote_done(dns_remote_t *remote); +/*%< + * Return 'true' if we iterated over all addresses, 'false' otherwise. + * + * Requires: + * 'remote' is a valid remote structure. + */ + +ISC_LANG_ENDDECLS diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index f2288d3bea..7f0e3b2d39 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -128,6 +128,7 @@ typedef struct dns_rdataset dns_rdataset_t; typedef ISC_LIST(dns_rdataset_t) dns_rdatasetlist_t; typedef struct dns_rdatasetiter dns_rdatasetiter_t; typedef uint16_t dns_rdatatype_t; +typedef struct dns_remote dns_remote_t; typedef struct dns_request dns_request_t; typedef struct dns_requestmgr dns_requestmgr_t; typedef struct dns_resolver dns_resolver_t; diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index a029c6e43f..bbbf84d7e1 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -634,19 +634,19 @@ dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format, */ void -dns_zone_setprimaries(dns_zone_t *zone, const isc_sockaddr_t *primaries, - dns_name_t **keynames, dns_name_t **tlsnames, - uint32_t count); +dns_zone_setprimaries(dns_zone_t *zone, isc_sockaddr_t *addresses, + isc_sockaddr_t *sources, dns_name_t **keynames, + dns_name_t **tlsnames, uint32_t count); /*%< * Set the list of primary servers for the zone. * * Require: *\li 'zone' to be a valid zone. - *\li 'primaries' array of isc_sockaddr_t with port set or NULL. + *\li 'addresses' array of isc_sockaddr_t with port set or NULL. *\li 'count' the number of primaries. *\li 'keynames' array of dns_name_t's for tsig keys or NULL. * - *\li If 'primaries' is NULL then 'count' must be zero. + *\li If 'addresses' is NULL then 'count' must be zero. * * Returns: *\li #ISC_R_SUCCESS @@ -655,19 +655,19 @@ dns_zone_setprimaries(dns_zone_t *zone, const isc_sockaddr_t *primaries, */ void -dns_zone_setparentals(dns_zone_t *zone, const isc_sockaddr_t *parentals, - dns_name_t **keynames, dns_name_t **tlsnames, - uint32_t count); +dns_zone_setparentals(dns_zone_t *zone, isc_sockaddr_t *addresses, + isc_sockaddr_t *sources, dns_name_t **keynames, + dns_name_t **tlsnames, uint32_t count); /*%< * Set the list of parental agents for the zone. * * Require: *\li 'zone' to be a valid zone. - *\li 'parentals' array of isc_sockaddr_t with port set or NULL. + *\li 'addresses' array of isc_sockaddr_t with port set or NULL. *\li 'count' the number of primaries. *\li 'keynames' array of dns_name_t's for tsig keys or NULL. * - *\li If 'parentals' is NULL then 'count' must be zero. + *\li If 'addresses' is NULL then 'count' must be zero. * * Returns: *\li #ISC_R_SUCCESS @@ -676,30 +676,10 @@ dns_zone_setparentals(dns_zone_t *zone, const isc_sockaddr_t *parentals, */ void -dns_zone_setparentals(dns_zone_t *zone, const isc_sockaddr_t *parentals, - dns_name_t **keynames, dns_name_t **tlsnames, - uint32_t count); -/*%< - * Set the list of parental agents for the zone. - * - * Require: - *\li 'zone' to be a valid zone. - *\li 'parentals' array of isc_sockaddr_t with port set or NULL. - *\li 'count' the number of parentals. - *\li 'keynames' array of dns_name_t's for tsig keys or NULL. - * - *\li If 'parentals' is NULL then 'count' must be zero. - * - * Returns: - *\li #ISC_R_SUCCESS - *\li #ISC_R_NOMEMORY - *\li Any result dns_name_dup() can return, if keynames!=NULL - */ - -void -dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify, - const isc_dscp_t *dscps, dns_name_t **keynames, - dns_name_t **tlsnames, uint32_t count); +dns_zone_setalsonotify(dns_zone_t *zone, isc_sockaddr_t *addresses, + isc_sockaddr_t *sources, isc_dscp_t *dscps, + dns_name_t **keynames, dns_name_t **tlsnames, + uint32_t count); /*%< * Set the list of additional servers to be notified when * a zone changes. To clear the list use 'count = 0'. @@ -709,7 +689,7 @@ dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify, * * Require: *\li 'zone' to be a valid zone. - *\li 'notify' to be non-NULL if count != 0. + *\li 'addresses' to be non-NULL if count != 0. *\li 'count' to be the number of notifiees. * * Returns: diff --git a/lib/dns/ipkeylist.c b/lib/dns/ipkeylist.c index f773c1b616..b12656b318 100644 --- a/lib/dns/ipkeylist.c +++ b/lib/dns/ipkeylist.c @@ -26,6 +26,7 @@ dns_ipkeylist_init(dns_ipkeylist_t *ipkl) { ipkl->count = 0; ipkl->allocated = 0; ipkl->addrs = NULL; + ipkl->sources = NULL; ipkl->dscps = NULL; ipkl->keys = NULL; ipkl->tlss = NULL; @@ -47,11 +48,21 @@ dns_ipkeylist_clear(isc_mem_t *mctx, dns_ipkeylist_t *ipkl) { ipkl->allocated * sizeof(isc_sockaddr_t)); } + if (ipkl->sources != NULL) { + isc_mem_put(mctx, ipkl->sources, + ipkl->allocated * sizeof(isc_sockaddr_t)); + } + if (ipkl->dscps != NULL) { isc_mem_put(mctx, ipkl->dscps, ipkl->allocated * sizeof(isc_dscp_t)); } + if (ipkl->addrs != NULL) { + isc_mem_put(mctx, ipkl->addrs, + ipkl->allocated * sizeof(isc_sockaddr_t)); + } + if (ipkl->keys != NULL) { for (i = 0; i < ipkl->allocated; i++) { if (ipkl->keys[i] == NULL) { @@ -118,6 +129,11 @@ dns_ipkeylist_copy(isc_mem_t *mctx, const dns_ipkeylist_t *src, memmove(dst->addrs, src->addrs, src->count * sizeof(isc_sockaddr_t)); + if (src->sources != NULL) { + memmove(dst->sources, src->sources, + src->count * sizeof(isc_sockaddr_t)); + } + if (src->dscps != NULL) { memmove(dst->dscps, src->dscps, src->count * sizeof(isc_dscp_t)); @@ -169,6 +185,7 @@ dns_ipkeylist_copy(isc_mem_t *mctx, const dns_ipkeylist_t *src, isc_result_t dns_ipkeylist_resize(isc_mem_t *mctx, dns_ipkeylist_t *ipkl, unsigned int n) { isc_sockaddr_t *addrs = NULL; + isc_sockaddr_t *sources = NULL; isc_dscp_t *dscps = NULL; dns_name_t **keys = NULL; dns_name_t **tlss = NULL; @@ -182,6 +199,7 @@ dns_ipkeylist_resize(isc_mem_t *mctx, dns_ipkeylist_t *ipkl, unsigned int n) { } addrs = isc_mem_get(mctx, n * sizeof(isc_sockaddr_t)); + sources = isc_mem_get(mctx, n * sizeof(isc_sockaddr_t)); dscps = isc_mem_get(mctx, n * sizeof(isc_dscp_t)); keys = isc_mem_get(mctx, n * sizeof(dns_name_t *)); tlss = isc_mem_get(mctx, n * sizeof(dns_name_t *)); @@ -197,6 +215,16 @@ dns_ipkeylist_resize(isc_mem_t *mctx, dns_ipkeylist_t *ipkl, unsigned int n) { memset(&ipkl->addrs[ipkl->allocated], 0, (n - ipkl->allocated) * sizeof(isc_sockaddr_t)); + if (ipkl->sources != NULL) { + memmove(sources, ipkl->sources, + ipkl->allocated * sizeof(isc_sockaddr_t)); + isc_mem_put(mctx, ipkl->sources, + ipkl->allocated * sizeof(isc_sockaddr_t)); + } + ipkl->sources = sources; + memset(&ipkl->sources[ipkl->allocated], 0, + (n - ipkl->allocated) * sizeof(isc_sockaddr_t)); + if (ipkl->dscps != NULL) { memmove(dscps, ipkl->dscps, ipkl->allocated * sizeof(isc_dscp_t)); @@ -241,6 +269,7 @@ dns_ipkeylist_resize(isc_mem_t *mctx, dns_ipkeylist_t *ipkl, unsigned int n) { return (ISC_R_SUCCESS); isc_mem_put(mctx, addrs, n * sizeof(isc_sockaddr_t)); + isc_mem_put(mctx, sources, n * sizeof(isc_sockaddr_t)); isc_mem_put(mctx, dscps, n * sizeof(isc_dscp_t)); isc_mem_put(mctx, tlss, n * sizeof(dns_name_t *)); isc_mem_put(mctx, keys, n * sizeof(dns_name_t *)); diff --git a/lib/dns/remote.c b/lib/dns/remote.c new file mode 100644 index 0000000000..87974d885c --- /dev/null +++ b/lib/dns/remote.c @@ -0,0 +1,448 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +isc_sockaddr_t * +dns_remote_addresses(dns_remote_t *remote) { + REQUIRE(DNS_REMOTE_VALID(remote)); + return (remote->addresses); +} + +isc_sockaddr_t * +dns_remote_sources(dns_remote_t *remote) { + REQUIRE(DNS_REMOTE_VALID(remote)); + return (remote->sources); +} + +unsigned int +dns_remote_count(dns_remote_t *remote) { + REQUIRE(DNS_REMOTE_VALID(remote)); + return (remote->addrcnt); +} + +dns_name_t ** +dns_remote_keynames(dns_remote_t *remote) { + REQUIRE(DNS_REMOTE_VALID(remote)); + return (remote->keynames); +} + +dns_name_t ** +dns_remote_tlsnames(dns_remote_t *remote) { + REQUIRE(DNS_REMOTE_VALID(remote)); + return (remote->tlsnames); +} + +void +dns_remote_init(dns_remote_t *remote, unsigned int count, + const isc_sockaddr_t *addrs, const isc_sockaddr_t *srcs, + const isc_dscp_t *dscp, dns_name_t **keynames, + dns_name_t **tlsnames, bool mark, isc_mem_t *mctx) { + unsigned int i; + + REQUIRE(DNS_REMOTE_VALID(remote)); + REQUIRE(count == 0 || addrs != NULL); + + if (keynames != NULL || tlsnames != NULL) { + REQUIRE(count != 0); + } + + remote->mctx = mctx; + + if (addrs != NULL) { + remote->addresses = isc_mem_get(mctx, + count * sizeof(isc_sockaddr_t)); + memmove(remote->addresses, addrs, + count * sizeof(isc_sockaddr_t)); + } else { + remote->addresses = NULL; + } + + if (srcs != NULL) { + remote->sources = isc_mem_get(mctx, + count * sizeof(isc_sockaddr_t)); + memmove(remote->sources, srcs, count * sizeof(isc_sockaddr_t)); + } else { + remote->sources = NULL; + } + + if (dscp != NULL) { + remote->dscps = isc_mem_get(mctx, count * sizeof(isc_dscp_t)); + memmove(remote->dscps, dscp, count * sizeof(isc_dscp_t)); + } else { + remote->dscps = NULL; + } + + if (keynames != NULL) { + remote->keynames = isc_mem_get(mctx, count * sizeof(keynames)); + for (i = 0; i < count; i++) { + remote->keynames[i] = NULL; + } + for (i = 0; i < count; i++) { + if (keynames[i] != NULL) { + remote->keynames[i] = + isc_mem_get(mctx, sizeof(dns_name_t)); + dns_name_init(remote->keynames[i], NULL); + dns_name_dup(keynames[i], mctx, + remote->keynames[i]); + } + } + } else { + remote->keynames = NULL; + } + + if (tlsnames != NULL) { + remote->tlsnames = isc_mem_get(mctx, count * sizeof(tlsnames)); + for (i = 0; i < count; i++) { + remote->tlsnames[i] = NULL; + } + for (i = 0; i < count; i++) { + if (tlsnames[i] != NULL) { + remote->tlsnames[i] = + isc_mem_get(mctx, sizeof(dns_name_t)); + dns_name_init(remote->tlsnames[i], NULL); + dns_name_dup(tlsnames[i], mctx, + remote->tlsnames[i]); + } + } + } else { + remote->tlsnames = NULL; + } + + if (mark) { + remote->ok = isc_mem_get(mctx, count * sizeof(bool)); + for (i = 0; i < count; i++) { + remote->ok[i] = false; + } + } else { + remote->ok = NULL; + } + + remote->addrcnt = count; + remote->curraddr = 0; +} + +static bool +same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist, + uint32_t count) { + unsigned int i; + + if (oldlist == NULL && newlist == NULL) { + return (true); + } + if (oldlist == NULL || newlist == NULL) { + return (false); + } + + for (i = 0; i < count; i++) { + if (!isc_sockaddr_equal(&oldlist[i], &newlist[i])) { + return (false); + } + } + return (true); +} + +static bool +same_names(dns_name_t *const *oldlist, dns_name_t *const *newlist, + uint32_t count) { + unsigned int i; + + if (oldlist == NULL && newlist == NULL) { + return (true); + } + if (oldlist == NULL || newlist == NULL) { + return (false); + } + + for (i = 0; i < count; i++) { + if (oldlist[i] == NULL && newlist[i] == NULL) { + continue; + } + if (oldlist[i] == NULL || newlist[i] == NULL || + !dns_name_equal(oldlist[i], newlist[i])) + { + return (false); + } + } + return (true); +} + +static bool +same_dscp(isc_dscp_t *oldlist, isc_dscp_t *newlist, uint32_t count) { + unsigned int i; + + if (oldlist == NULL && newlist == NULL) { + return (true); + } + if (oldlist == NULL || newlist == NULL) { + return (false); + } + + for (i = 0; i < count; i++) { + if (oldlist[i] != newlist[i]) { + return (false); + } + } + return (true); +} + +void +dns_remote_clear(dns_remote_t *remote) { + unsigned int count; + isc_mem_t *mctx; + + REQUIRE(DNS_REMOTE_VALID(remote)); + + count = remote->addrcnt; + mctx = remote->mctx; + + if (mctx == NULL) { + return; + } + + if (remote->ok != NULL) { + isc_mem_put(mctx, remote->ok, count * sizeof(bool)); + remote->ok = NULL; + } + + if (remote->addresses != NULL) { + isc_mem_put(mctx, remote->addresses, + count * sizeof(isc_sockaddr_t)); + remote->addresses = NULL; + } + + if (remote->sources != NULL) { + isc_mem_put(mctx, remote->sources, + count * sizeof(isc_sockaddr_t)); + remote->sources = NULL; + } + + if (remote->dscps != NULL) { + isc_mem_put(mctx, remote->dscps, count * sizeof(isc_dscp_t)); + remote->dscps = NULL; + } + + if (remote->keynames != NULL) { + unsigned int i; + for (i = 0; i < count; i++) { + if (remote->keynames[i] != NULL) { + dns_name_free(remote->keynames[i], mctx); + isc_mem_put(mctx, remote->keynames[i], + sizeof(dns_name_t)); + remote->keynames[i] = NULL; + } + } + isc_mem_put(mctx, remote->keynames, + count * sizeof(dns_name_t *)); + remote->keynames = NULL; + } + + if (remote->tlsnames != NULL) { + unsigned int i; + for (i = 0; i < count; i++) { + if (remote->tlsnames[i] != NULL) { + dns_name_free(remote->tlsnames[i], mctx); + isc_mem_put(mctx, remote->tlsnames[i], + sizeof(dns_name_t)); + remote->tlsnames[i] = NULL; + } + } + isc_mem_put(mctx, remote->tlsnames, + count * sizeof(dns_name_t *)); + remote->tlsnames = NULL; + } + + remote->curraddr = 0; + remote->addrcnt = 0; + remote->mctx = NULL; +} + +bool +dns_remote_equal(dns_remote_t *a, dns_remote_t *b) { + REQUIRE(DNS_REMOTE_VALID(a)); + REQUIRE(DNS_REMOTE_VALID(b)); + + if (a->addrcnt != b->addrcnt) { + return (false); + } + + if (!same_addrs(a->addresses, b->addresses, a->addrcnt)) { + return (false); + } + if (!same_dscp(a->dscps, b->dscps, a->addrcnt)) { + return (false); + } + + if (!same_names(a->keynames, b->keynames, a->addrcnt)) { + return (false); + } + if (!same_names(a->tlsnames, b->tlsnames, a->addrcnt)) { + return (false); + } + + return (true); +} + +void +dns_remote_reset(dns_remote_t *remote, bool clear_ok) { + REQUIRE(DNS_REMOTE_VALID(remote)); + + remote->curraddr = 0; + + if (clear_ok && remote->ok != NULL) { + for (unsigned int i = 0; i < remote->addrcnt; i++) { + remote->ok[i] = false; + } + } +} + +isc_sockaddr_t +dns_remote_curraddr(dns_remote_t *remote) { + REQUIRE(DNS_REMOTE_VALID(remote)); + REQUIRE(remote->addresses != NULL); + REQUIRE(remote->curraddr < remote->addrcnt); + + return (remote->addresses[remote->curraddr]); +} + +isc_sockaddr_t +dns_remote_addr(dns_remote_t *remote, unsigned int i) { + REQUIRE(DNS_REMOTE_VALID(remote)); + REQUIRE(remote->addresses != NULL); + REQUIRE(i < remote->addrcnt); + + return (remote->addresses[i]); +} + +isc_sockaddr_t +dns_remote_sourceaddr(dns_remote_t *remote) { + REQUIRE(DNS_REMOTE_VALID(remote)); + REQUIRE(remote->sources != NULL); + REQUIRE(remote->curraddr < remote->addrcnt); + + return (remote->sources[remote->curraddr]); +} + +isc_dscp_t +dns_remote_dscp(dns_remote_t *remote) { + REQUIRE(DNS_REMOTE_VALID(remote)); + + if (remote->dscps == NULL) { + return -1; + } + if (remote->curraddr >= remote->addrcnt) { + return -1; + } + + return (remote->dscps[remote->curraddr]); +} + +dns_name_t * +dns_remote_keyname(dns_remote_t *remote) { + REQUIRE(DNS_REMOTE_VALID(remote)); + + if (remote->keynames == NULL) { + return (NULL); + } + if (remote->curraddr >= remote->addrcnt) { + return (NULL); + } + + return (remote->keynames[remote->curraddr]); +} + +dns_name_t * +dns_remote_tlsname(dns_remote_t *remote) { + REQUIRE(DNS_REMOTE_VALID(remote)); + + if (remote->tlsnames == NULL) { + return (NULL); + } + if (remote->curraddr >= remote->addrcnt) { + return (NULL); + } + + return (remote->tlsnames[remote->curraddr]); +} + +void +dns_remote_next(dns_remote_t *remote, bool skip_good) { + REQUIRE(DNS_REMOTE_VALID(remote)); + +skip_to_next: + remote->curraddr++; + + if (remote->curraddr >= remote->addrcnt) { + return; + } + + if (skip_good && remote->ok != NULL && remote->ok[remote->curraddr]) { + goto skip_to_next; + } +} + +bool +dns_remote_done(dns_remote_t *remote) { + REQUIRE(DNS_REMOTE_VALID(remote)); + + return (remote->curraddr >= remote->addrcnt); +} + +bool +dns_remote_allgood(dns_remote_t *remote) { + REQUIRE(DNS_REMOTE_VALID(remote)); + + if (remote->ok == NULL) { + return (true); + } + + for (unsigned int i = 0; i < remote->addrcnt; i++) { + if (!remote->ok[i]) { + return (false); + } + } + + return (true); +} + +bool +dns_remote_addrok(dns_remote_t *remote) { + REQUIRE(DNS_REMOTE_VALID(remote)); + REQUIRE(remote->curraddr < remote->addrcnt); + + if (remote->ok == NULL) { + return (true); + } + + return (remote->ok[remote->curraddr]); +} + +void +dns_remote_mark(dns_remote_t *remote, bool good) { + REQUIRE(DNS_REMOTE_VALID(remote)); + REQUIRE(remote->curraddr < remote->addrcnt); + + remote->ok[remote->curraddr] = good; +} diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 9b4455d3cf..3198a8fd3d 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -77,6 +77,7 @@ #include #include #include +#include #include #include #include @@ -315,32 +316,18 @@ struct dns_zone { uint32_t maxrecords; - isc_sockaddr_t *primaries; - isc_dscp_t *primarydscps; - dns_name_t **primarykeynames; - dns_name_t **primarytlsnames; - bool *primariesok; - unsigned int primariescnt; - unsigned int curprimary; - isc_sockaddr_t primaryaddr; + dns_remote_t primaries; - isc_sockaddr_t *parentals; - isc_dscp_t *parentaldscps; - dns_name_t **parentalkeynames; - dns_name_t **parentaltlsnames; + dns_remote_t parentals; dns_dnsseckeylist_t checkds_ok; - unsigned int parentalscnt; - isc_sockaddr_t parentaladdr; + dns_remote_t notify; dns_notifytype_t notifytype; - isc_sockaddr_t *notify; - dns_name_t **notifykeynames; - dns_name_t **notifytlsnames; - isc_dscp_t *notifydscp; - unsigned int notifycnt; isc_sockaddr_t notifyfrom; + isc_task_t *task; isc_task_t *loadtask; + isc_sockaddr_t notifysrc4; isc_sockaddr_t notifysrc6; isc_sockaddr_t parentalsrc4; @@ -358,6 +345,7 @@ struct dns_zone { isc_dscp_t xfrsource6dscp; isc_dscp_t altxfrsource4dscp; isc_dscp_t altxfrsource6dscp; + dns_xfrin_ctx_t *xfr; /* task locked */ dns_tsigkey_t *tsigkey; /* key used for xfr */ dns_transport_t *transport; /* transport used for xfr */ @@ -680,6 +668,7 @@ struct dns_notify { dns_adbfind_t *find; dns_request_t *request; dns_name_t ns; + isc_sockaddr_t src; isc_sockaddr_t dst; dns_tsigkey_t *key; dns_transport_t *transport; @@ -700,6 +689,7 @@ struct dns_checkds { isc_mem_t *mctx; dns_zone_t *zone; dns_request_t *request; + isc_sockaddr_t src; isc_sockaddr_t dst; dns_tsigkey_t *key; dns_transport_t *transport; @@ -1156,6 +1146,9 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx, unsigned int tid) { .updatemethod = dns_updatemethod_increment, .tid = tid, }; + dns_remote_t r = { + .magic = DNS_REMOTE_MAGIC, + }; REQUIRE(zonep != NULL && *zonep == NULL); REQUIRE(mctx != NULL); @@ -1211,6 +1204,10 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx, unsigned int tid) { ISC_LIST_INIT(zone->rss_events); ISC_LIST_INIT(zone->rss_post); + zone->primaries = r; + zone->parentals = r; + zone->notify = r; + result = isc_stats_create(mctx, &zone->gluecachestats, dns_gluecachestatscounter_max); if (result != ISC_R_SUCCESS) { @@ -1371,9 +1368,11 @@ zone_free(dns_zone_t *zone) { dns_catz_catzs_detach(&zone->catzs); } zone_freedbargs(zone); - dns_zone_setparentals(zone, NULL, NULL, NULL, 0); - dns_zone_setprimaries(zone, NULL, NULL, NULL, 0); - dns_zone_setalsonotify(zone, NULL, NULL, NULL, NULL, 0); + + dns_zone_setparentals(zone, NULL, NULL, NULL, NULL, 0); + dns_zone_setprimaries(zone, NULL, NULL, NULL, NULL, 0); + dns_zone_setalsonotify(zone, NULL, NULL, NULL, NULL, NULL, 0); + zone->check_names = dns_severity_ignore; if (zone->update_acl != NULL) { dns_acl_detach(&zone->update_acl); @@ -1900,7 +1899,8 @@ dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) { if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror || zone->type == dns_zone_stub || zone->type == dns_zone_key || - (zone->type == dns_zone_redirect && zone->primaries != NULL)) + (zone->type == dns_zone_redirect && + dns_remote_addresses(&zone->primaries) != NULL)) { return (true); } @@ -2326,7 +2326,8 @@ zone_load(dns_zone_t *zone, unsigned int flags, bool locked) { if ((zone->type == dns_zone_secondary || zone->type == dns_zone_mirror || zone->type == dns_zone_stub || - (zone->type == dns_zone_redirect && zone->primaries != NULL)) && + (zone->type == dns_zone_redirect && + dns_remote_addresses(&zone->primaries) != NULL)) && rbt) { if (zone->stream == NULL && @@ -2383,7 +2384,7 @@ zone_load(dns_zone_t *zone, unsigned int flags, bool locked) { result = DNS_R_NOMASTERFILE; if (zone->type == dns_zone_primary || (zone->type == dns_zone_redirect && - zone->primaries == NULL)) + dns_remote_addresses(&zone->primaries) == NULL)) { dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR, @@ -2535,7 +2536,8 @@ get_primary_options(dns_zone_t *zone) { options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN; if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror || - (zone->type == dns_zone_redirect && zone->primaries == NULL)) + (zone->type == dns_zone_redirect && + dns_remote_addresses(&zone->primaries) == NULL)) { options |= DNS_MASTER_SECONDARY; } @@ -4938,7 +4940,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, zone->type == dns_zone_mirror || zone->type == dns_zone_stub || (zone->type == dns_zone_redirect && - zone->primaries == NULL)) + dns_remote_addresses(&zone->primaries) == NULL)) { if (result == ISC_R_FILENOTFOUND) { dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, @@ -5247,7 +5249,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, zone->type == dns_zone_mirror || zone->type == dns_zone_stub || (zone->type == dns_zone_redirect && - zone->primaries != NULL)) + dns_remote_addresses(&zone->primaries) != NULL)) { isc_time_t t; uint32_t delay; @@ -5459,7 +5461,8 @@ cleanup: } if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror || zone->type == dns_zone_stub || zone->type == dns_zone_key || - (zone->type == dns_zone_redirect && zone->primaries != NULL)) + (zone->type == dns_zone_redirect && + dns_remote_addresses(&zone->primaries) != NULL)) { if (result != ISC_R_NOMEMORY) { if (zone->journal != NULL) { @@ -6257,249 +6260,73 @@ dns_zone_getnotifysrc6dscp(dns_zone_t *zone) { return (zone->notifysrc6dscp); } -static bool -same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist, - uint32_t count) { - unsigned int i; - - for (i = 0; i < count; i++) { - if (!isc_sockaddr_equal(&oldlist[i], &newlist[i])) { - return (false); - } - } - return (true); -} - -static bool -same_names(dns_name_t *const *oldlist, dns_name_t *const *newlist, - uint32_t count) { - unsigned int i; - - if (oldlist == NULL && newlist == NULL) { - return (true); - } - if (oldlist == NULL || newlist == NULL) { - return (false); - } - - for (i = 0; i < count; i++) { - if (oldlist[i] == NULL && newlist[i] == NULL) { - continue; - } - if (oldlist[i] == NULL || newlist[i] == NULL || - !dns_name_equal(oldlist[i], newlist[i])) - { - return (false); - } - } - return (true); -} - -static void -clear_serverslist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp, - dns_name_t ***keynamesp, dns_name_t ***tlsnamesp, - unsigned int *countp, isc_mem_t *mctx) { - unsigned int count; - isc_sockaddr_t *addrs; - isc_dscp_t *dscps; - dns_name_t **keynames; - dns_name_t **tlsnames; - - REQUIRE(countp != NULL); - REQUIRE(addrsp != NULL); - REQUIRE(dscpsp != NULL); - REQUIRE(keynamesp != NULL); - REQUIRE(tlsnamesp != NULL); - - count = *countp; - *countp = 0; - addrs = *addrsp; - *addrsp = NULL; - dscps = *dscpsp; - *dscpsp = NULL; - keynames = *keynamesp; - *keynamesp = NULL; - tlsnames = *tlsnamesp; - *tlsnamesp = NULL; - - if (addrs != NULL) { - isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t)); - } - - if (dscps != NULL) { - isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t)); - } - - if (keynames != NULL) { - unsigned int i; - for (i = 0; i < count; i++) { - if (keynames[i] != NULL) { - dns_name_free(keynames[i], mctx); - isc_mem_put(mctx, keynames[i], - sizeof(dns_name_t)); - keynames[i] = NULL; - } - } - isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *)); - } - - if (tlsnames != NULL) { - unsigned int i; - for (i = 0; i < count; i++) { - if (tlsnames[i] != NULL) { - dns_name_free(tlsnames[i], mctx); - isc_mem_put(mctx, tlsnames[i], - sizeof(dns_name_t)); - tlsnames[i] = NULL; - } - } - isc_mem_put(mctx, tlsnames, count * sizeof(dns_name_t *)); - } -} - -static void -set_serverslist(unsigned int count, const isc_sockaddr_t *addrs, - isc_sockaddr_t **newaddrsp, const isc_dscp_t *dscp, - isc_dscp_t **newdscpp, dns_name_t **keynames, - dns_name_t ***newkeynamesp, dns_name_t **tlsnames, - dns_name_t ***newtlsnamesp, isc_mem_t *mctx) { - isc_sockaddr_t *newaddrs = NULL; - isc_dscp_t *newdscp = NULL; - dns_name_t **newkeynames = NULL; - dns_name_t **newtlsnames = NULL; - unsigned int i; - - REQUIRE(newaddrsp != NULL && *newaddrsp == NULL); - REQUIRE(newdscpp != NULL && *newdscpp == NULL); - REQUIRE(newkeynamesp != NULL && *newkeynamesp == NULL); - REQUIRE(newtlsnamesp != NULL && *newtlsnamesp == NULL); - - newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs)); - memmove(newaddrs, addrs, count * sizeof(*newaddrs)); - - if (dscp != NULL) { - newdscp = isc_mem_get(mctx, count * sizeof(*newdscp)); - memmove(newdscp, dscp, count * sizeof(*newdscp)); - } else { - newdscp = NULL; - } - - if (keynames != NULL) { - newkeynames = isc_mem_get(mctx, count * sizeof(*newkeynames)); - for (i = 0; i < count; i++) { - newkeynames[i] = NULL; - } - for (i = 0; i < count; i++) { - if (keynames[i] != NULL) { - newkeynames[i] = - isc_mem_get(mctx, sizeof(dns_name_t)); - dns_name_init(newkeynames[i], NULL); - dns_name_dup(keynames[i], mctx, newkeynames[i]); - } - } - } - - if (tlsnames != NULL) { - newtlsnames = isc_mem_get(mctx, count * sizeof(*newtlsnames)); - for (i = 0; i < count; i++) { - newtlsnames[i] = NULL; - } - for (i = 0; i < count; i++) { - if (tlsnames[i] != NULL) { - newtlsnames[i] = - isc_mem_get(mctx, sizeof(dns_name_t)); - dns_name_init(newtlsnames[i], NULL); - dns_name_dup(tlsnames[i], mctx, newtlsnames[i]); - } - } - } - - *newdscpp = newdscp; - *newaddrsp = newaddrs; - *newkeynamesp = newkeynames; - *newtlsnamesp = newtlsnames; -} - void -dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify, - const isc_dscp_t *dscps, dns_name_t **keynames, - dns_name_t **tlsnames, uint32_t count) { - isc_sockaddr_t *newaddrs = NULL; - isc_dscp_t *newdscps = NULL; - dns_name_t **newkeynames = NULL; - dns_name_t **newtlsnames = NULL; +dns_zone_setalsonotify(dns_zone_t *zone, isc_sockaddr_t *addresses, + isc_sockaddr_t *sources, isc_dscp_t *dscps, + dns_name_t **keynames, dns_name_t **tlsnames, + uint32_t count) { + dns_remote_t remote; REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(count == 0 || notify != NULL); - if (keynames != NULL) { - REQUIRE(count != 0); - } LOCK_ZONE(zone); - if (count == zone->notifycnt && - same_addrs(zone->notify, notify, count) && - same_names(zone->notifykeynames, keynames, count) && - same_names(zone->notifytlsnames, tlsnames, count)) - { + remote.magic = DNS_REMOTE_MAGIC; + remote.addresses = addresses; + remote.sources = sources; + remote.dscps = dscps; + remote.keynames = keynames; + remote.tlsnames = tlsnames; + remote.addrcnt = count; + + if (dns_remote_equal(&zone->notify, &remote)) { goto unlock; } - clear_serverslist(&zone->notify, &zone->notifydscp, - &zone->notifykeynames, &zone->notifytlsnames, - &zone->notifycnt, zone->mctx); + dns_remote_clear(&zone->notify); + /* + * If count == 0, don't allocate any space for servers to notify. + */ if (count == 0) { goto unlock; } /* - * Set up the notify and notifykey lists + * Now set up the notify address and key lists. */ - set_serverslist(count, notify, &newaddrs, dscps, &newdscps, keynames, - &newkeynames, tlsnames, &newtlsnames, zone->mctx); + dns_remote_init(&zone->notify, count, addresses, sources, dscps, + keynames, tlsnames, true, zone->mctx); - /* - * Everything is ok so attach to the zone. - */ - zone->notify = newaddrs; - zone->notifydscp = newdscps; - zone->notifykeynames = newkeynames; - zone->notifytlsnames = newtlsnames; - zone->notifycnt = count; unlock: UNLOCK_ZONE(zone); } void -dns_zone_setprimaries(dns_zone_t *zone, const isc_sockaddr_t *primaries, - dns_name_t **keynames, dns_name_t **tlsnames, - uint32_t count) { - isc_sockaddr_t *newaddrs = NULL; - isc_dscp_t *newdscps = NULL; - dns_name_t **newkeynames = NULL; - dns_name_t **newtlsnames = NULL; - bool *newok; - unsigned int i; +dns_zone_setprimaries(dns_zone_t *zone, isc_sockaddr_t *addresses, + isc_sockaddr_t *sources, dns_name_t **keynames, + dns_name_t **tlsnames, uint32_t count) { + dns_remote_t remote; REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(count == 0 || primaries != NULL); - if (keynames != NULL || tlsnames != NULL) { - REQUIRE(count != 0); - } LOCK_ZONE(zone); + + remote.magic = DNS_REMOTE_MAGIC; + remote.addresses = addresses; + remote.sources = sources; + remote.dscps = NULL; + remote.keynames = keynames; + remote.tlsnames = tlsnames; + remote.addrcnt = count; + /* * The refresh code assumes that 'primaries' wouldn't change under it. * If it will change then kill off any current refresh in progress * and update the primaries info. If it won't change then we can just * unlock and exit. */ - if (count != zone->primariescnt || - !same_addrs(zone->primaries, primaries, count) || - !same_names(zone->primarykeynames, keynames, count) || - !same_names(zone->primarytlsnames, tlsnames, count)) - { + if (!dns_remote_equal(&zone->primaries, &remote)) { if (zone->request != NULL) { dns_request_cancel(zone->request); } @@ -6507,51 +6334,21 @@ dns_zone_setprimaries(dns_zone_t *zone, const isc_sockaddr_t *primaries, goto unlock; } + dns_remote_clear(&zone->primaries); + /* - * This needs to happen before clear_addresskeylist() sets - * zone->primariescnt to 0: - */ - if (zone->primariesok != NULL) { - isc_mem_put(zone->mctx, zone->primariesok, - zone->primariescnt * sizeof(bool)); - zone->primariesok = NULL; - } - clear_serverslist(&zone->primaries, &zone->primarydscps, - &zone->primarykeynames, &zone->primarytlsnames, - &zone->primariescnt, zone->mctx); - /* - * If count == 0, don't allocate any space for primaries, primariesok or - * keynames so internally, those pointers are NULL if count == 0 + * If count == 0, don't allocate any space for primaries. */ if (count == 0) { goto unlock; } /* - * primariesok must contain count elements + * Now set up the primaries and primary key lists. */ - newok = isc_mem_get(zone->mctx, count * sizeof(*newok)); - for (i = 0; i < count; i++) { - newok[i] = false; - } + dns_remote_init(&zone->primaries, count, addresses, sources, NULL, + keynames, tlsnames, true, zone->mctx); - /* - * Now set up the primaries and primary key lists - */ - set_serverslist(count, primaries, &newaddrs, NULL, &newdscps, keynames, - &newkeynames, tlsnames, &newtlsnames, zone->mctx); - INSIST(newdscps == NULL); - - /* - * Everything is ok so attach to the zone. - */ - zone->curprimary = 0; - zone->primariesok = newok; - zone->primaries = newaddrs; - zone->primarydscps = newdscps; - zone->primarykeynames = newkeynames; - zone->primarytlsnames = newtlsnames; - zone->primariescnt = count; DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOPRIMARIES); unlock: @@ -6559,48 +6356,41 @@ unlock: } void -dns_zone_setparentals(dns_zone_t *zone, const isc_sockaddr_t *parentals, - dns_name_t **keynames, dns_name_t **tlsnames, - uint32_t count) { - isc_sockaddr_t *newaddrs = NULL; - isc_dscp_t *newdscps = NULL; - dns_name_t **newkeynames = NULL; - dns_name_t **newtlsnames = NULL; +dns_zone_setparentals(dns_zone_t *zone, isc_sockaddr_t *addresses, + isc_sockaddr_t *sources, dns_name_t **keynames, + dns_name_t **tlsnames, uint32_t count) { + dns_remote_t remote; REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(count == 0 || parentals != NULL); - if (keynames != NULL || tlsnames != NULL) { - REQUIRE(count != 0); - } LOCK_ZONE(zone); - clear_serverslist(&zone->parentals, &zone->parentaldscps, - &zone->parentalkeynames, &zone->parentaltlsnames, - &zone->parentalscnt, zone->mctx); + remote.magic = DNS_REMOTE_MAGIC; + remote.addresses = addresses; + remote.sources = sources; + remote.dscps = NULL; + remote.keynames = keynames; + remote.tlsnames = tlsnames; + remote.addrcnt = count; + + if (dns_remote_equal(&zone->parentals, &remote)) { + goto unlock; + } + + dns_remote_clear(&zone->parentals); + /* - * If count == 0, don't allocate any space for parentals, or keynames - * so internally, those pointers are NULL if count == 0 + * If count == 0, don't allocate any space for parentals. */ if (count == 0) { goto unlock; } /* - * Now set up the parentals and parental key lists + * Now set up the parentals and parental key lists. */ - set_serverslist(count, parentals, &newaddrs, NULL, &newdscps, keynames, - &newkeynames, tlsnames, &newtlsnames, zone->mctx); - INSIST(newdscps == NULL); - - /* - * Everything is ok so attach to the zone. - */ - zone->parentals = newaddrs; - zone->parentaldscps = newdscps; - zone->parentalkeynames = newkeynames; - zone->parentaltlsnames = newtlsnames; - zone->parentalscnt = count; + dns_remote_init(&zone->parentals, count, addresses, sources, NULL, + keynames, tlsnames, true, zone->mctx); dns_zone_log(zone, ISC_LOG_NOTICE, "checkds: set %u parentals", count); @@ -11519,7 +11309,7 @@ zone_maintenance(dns_zone_t *zone) { */ switch (zone->type) { case dns_zone_redirect: - if (zone->primaries == NULL) { + if (dns_remote_addresses(&zone->primaries) == NULL) { break; } FALLTHROUGH; @@ -11544,7 +11334,7 @@ zone_maintenance(dns_zone_t *zone) { */ switch (zone->type) { case dns_zone_redirect: - if (zone->primaries == NULL) { + if (dns_remote_addresses(&zone->primaries) == NULL) { break; } FALLTHROUGH; @@ -11829,7 +11619,6 @@ static void zone_refresh(dns_zone_t *zone) { isc_interval_t i; uint32_t oldflags; - unsigned int j; isc_result_t result; REQUIRE(DNS_ZONE_VALID(zone)); @@ -11845,7 +11634,7 @@ zone_refresh(dns_zone_t *zone) { */ oldflags = atomic_load(&zone->flags); - if (zone->primariescnt == 0) { + if (dns_remote_addresses(&zone->primaries) == NULL) { DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOPRIMARIES); if ((oldflags & DNS_ZONEFLG_NOPRIMARIES) == 0) { dns_zone_log(zone, ISC_LOG_ERROR, @@ -11883,10 +11672,8 @@ zone_refresh(dns_zone_t *zone) { zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600); } - zone->curprimary = 0; - for (j = 0; j < zone->primariescnt; j++) { - zone->primariesok[j] = false; - } + dns_remote_reset(&zone->primaries, true); + /* initiate soa query */ queue_soa_query(zone); } @@ -12684,6 +12471,7 @@ notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) { }; isc_mem_attach(mctx, ¬ify->mctx); + isc_sockaddr_any(¬ify->src); isc_sockaddr_any(¬ify->dst); dns_name_init(¬ify->ns, NULL); ISC_LINK_INIT(notify, link); @@ -12889,7 +12677,13 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) { switch (isc_sockaddr_pf(¬ify->dst)) { case PF_INET: if (!have_notifysource) { - src = notify->zone->notifysrc4; + isc_sockaddr_t any; + isc_sockaddr_any(&any); + + src = notify->src; + if (isc_sockaddr_equal(&src, &any)) { + src = notify->zone->notifysrc4; + } } if (!have_notifydscp) { dscp = notify->zone->notifysrc4dscp; @@ -12897,7 +12691,13 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) { break; case PF_INET6: if (!have_notifysource) { - src = notify->zone->notifysrc6; + isc_sockaddr_t any; + isc_sockaddr_any6(&any); + + src = notify->src; + if (isc_sockaddr_equal(&src, &any)) { + src = notify->zone->notifysrc6; + } } if (!have_notifydscp) { dscp = notify->zone->notifysrc6dscp; @@ -13021,7 +12821,7 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { dns_rdataset_t nsrdset; dns_rdataset_t soardset; isc_result_t result; - unsigned int i; + isc_sockaddr_t src; isc_sockaddr_t dst; bool isqueued; dns_notifytype_t notifytype; @@ -13116,23 +12916,21 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { * Enqueue notify requests for 'also-notify' servers. */ LOCK_ZONE(zone); - for (i = 0; i < zone->notifycnt; i++) { + + dns_remote_reset(&zone->notify, false); + while (!dns_remote_done(&zone->notify)) { dns_tsigkey_t *key = NULL; dns_transport_t *transport = NULL; dns_notify_t *notify = NULL; dns_view_t *view = dns_zone_getview(zone); - if ((zone->notifykeynames != NULL) && - (zone->notifykeynames[i] != NULL)) - { - dns_name_t *keyname = zone->notifykeynames[i]; + if (dns_remote_keyname(&zone->notify) != NULL) { + dns_name_t *keyname = dns_remote_keyname(&zone->notify); (void)dns_view_gettsig(view, keyname, &key); } - if ((zone->notifytlsnames != NULL) && - (zone->notifytlsnames[i] != NULL)) - { - dns_name_t *tlsname = zone->notifytlsnames[i]; + if (dns_remote_tlsname(&zone->notify) != NULL) { + dns_name_t *tlsname = dns_remote_tlsname(&zone->notify); (void)dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname, &transport); @@ -13143,7 +12941,10 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { /* TODO: glue the transport to the notify */ - dst = zone->notify[i]; + dst = dns_remote_curraddr(&zone->notify); + src = dns_remote_sourceaddr(&zone->notify); + INSIST(isc_sockaddr_pf(&src) == isc_sockaddr_pf(&dst)); + if (notify_isqueued(zone, flags, NULL, &dst, key, transport)) { if (key != NULL) { dns_tsigkey_detach(&key); @@ -13151,7 +12952,7 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { if (transport != NULL) { dns_transport_detach(&transport); } - continue; + goto next; } result = notify_create(zone->mctx, flags, ¬ify); @@ -13162,10 +12963,11 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { if (transport != NULL) { dns_transport_detach(&transport); } - continue; + goto next; } zone_iattach(zone, ¬ify->zone); + notify->src = src; notify->dst = dst; INSIST(notify->key == NULL); @@ -13191,6 +12993,8 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { "sending notifies (serial %u)", serial); loggednotify = true; } + next: + dns_remote_next(&zone->notify, false); } UNLOCK_ZONE(zone); @@ -13392,6 +13196,7 @@ stub_glue_response_cb(isc_task_t *task, isc_event_t *event) { char source[ISC_SOCKADDR_FORMATSIZE]; uint32_t addr_count, cnamecnt; isc_result_t result; + isc_sockaddr_t curraddr; isc_time_t now; struct stub_glue_request *request; struct stub_cb_args *cb_args; @@ -13418,11 +13223,12 @@ stub_glue_response_cb(isc_task_t *task, isc_event_t *event) { goto cleanup; } - isc_sockaddr_format(&zone->primaryaddr, primary, sizeof(primary)); + curraddr = dns_remote_curraddr(&zone->primaries); + isc_sockaddr_format(&curraddr, primary, sizeof(primary)); isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source)); if (revent->result != ISC_R_SUCCESS) { - dns_zonemgr_unreachableadd(zone->zmgr, &zone->primaryaddr, + dns_zonemgr_unreachableadd(zone->zmgr, &curraddr, &zone->sourceaddr, &now); dns_zone_log(zone, ISC_LOG_INFO, "could not refresh stub from primary %s" @@ -13599,6 +13405,7 @@ stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4, dns_zone_t *zone; isc_result_t result; struct stub_glue_request *request; + isc_sockaddr_t curraddr; zone = args->stub->zone; request = isc_mem_get(zone->mctx, sizeof(*request)); @@ -13623,10 +13430,11 @@ stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4, atomic_fetch_add_release(&args->stub->pending_requests, 1); + curraddr = dns_remote_curraddr(&zone->primaries); result = dns_request_create( - zone->view->requestmgr, message, &zone->sourceaddr, - &zone->primaryaddr, NULL, NULL, args->dscp, DNS_REQUESTOPT_TCP, - args->tsig_key, args->timeout * 3, args->timeout, 2, zone->task, + zone->view->requestmgr, message, &zone->sourceaddr, &curraddr, + NULL, NULL, args->dscp, DNS_REQUESTOPT_TCP, args->tsig_key, + args->timeout * 3, args->timeout, 2, zone->task, stub_glue_response_cb, request, &request->request); if (result != ISC_R_SUCCESS) { @@ -13814,9 +13622,9 @@ stub_callback(isc_task_t *task, isc_event_t *event) { char source[ISC_SOCKADDR_FORMATSIZE]; uint32_t nscnt, cnamecnt; isc_result_t result; + isc_sockaddr_t curraddr; isc_time_t now; bool exiting = false; - unsigned int j; struct stub_cb_args *cb_args; cb_args = revent->ev_arg; @@ -13837,7 +13645,8 @@ stub_callback(isc_task_t *task, isc_event_t *event) { goto exiting; } - isc_sockaddr_format(&zone->primaryaddr, primary, sizeof(primary)); + curraddr = dns_remote_curraddr(&zone->primaries); + isc_sockaddr_format(&curraddr, primary, sizeof(primary)); isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source)); switch (revent->result) { @@ -13856,7 +13665,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) { } FALLTHROUGH; default: - dns_zonemgr_unreachableadd(zone->zmgr, &zone->primaryaddr, + dns_zonemgr_unreachableadd(zone->zmgr, &curraddr, &zone->sourceaddr, &now); dns_zone_log(zone, ISC_LOG_INFO, "could not refresh stub from primary " @@ -14021,12 +13830,9 @@ next_primary: /* * Skip to next failed / untried primary. */ - do { - zone->curprimary++; - } while (zone->curprimary < zone->primariescnt && - zone->primariesok[zone->curprimary]); + dns_remote_next(&zone->primaries, true); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS); - if (exiting || zone->curprimary >= zone->primariescnt) { + if (exiting || dns_remote_done(&zone->primaries)) { bool done = true; if (!exiting && DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) && @@ -14035,26 +13841,16 @@ next_primary: /* * Did we get a good answer from all the primaries? */ - for (j = 0; j < zone->primariescnt; j++) { - if (!zone->primariesok[j]) { - { - done = false; - break; - } - } - } - } else { - done = true; + done = dns_remote_allgood(&zone->primaries); } if (!done) { - zone->curprimary = 0; + dns_remote_reset(&zone->primaries, false); + /* * Find the next failed primary. */ - while (zone->curprimary < zone->primariescnt && - zone->primariesok[zone->curprimary]) - { - zone->curprimary++; + if (dns_remote_addrok(&zone->primaries)) { + dns_remote_next(&zone->primaries, true); } DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); } else { @@ -14197,8 +13993,8 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_soa_t soa; isc_result_t result; + isc_sockaddr_t curraddr; uint32_t serial, oldserial = 0; - unsigned int j; bool do_queue_xfrin = false; zone = revent->ev_arg; @@ -14219,7 +14015,8 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { /* * If timeout, log and try the next primary */ - isc_sockaddr_format(&zone->primaryaddr, primary, sizeof(primary)); + curraddr = dns_remote_curraddr(&zone->primaries); + isc_sockaddr_format(&curraddr, primary, sizeof(primary)); isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source)); switch (revent->result) { @@ -14247,7 +14044,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) { if (!dns_zonemgr_unreachable( - zone->zmgr, &zone->primaryaddr, + zone->zmgr, &curraddr, &zone->sourceaddr, &now)) { DNS_ZONE_SETFLAG( @@ -14484,7 +14281,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) || isc_serial_gt(serial, oldserial)) { - if (dns_zonemgr_unreachable(zone->zmgr, &zone->primaryaddr, + if (dns_zonemgr_unreachable(zone->zmgr, &curraddr, &zone->sourceaddr, &now)) { dns_zone_log(zone, ISC_LOG_INFO, @@ -14535,7 +14332,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { } DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime); - zone->primariesok[zone->curprimary] = true; + dns_remote_mark(&zone->primaries, true); goto next_primary; } else { if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) { @@ -14546,7 +14343,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { } else { zone_debuglog(zone, __func__, 1, "ahead"); } - zone->primariesok[zone->curprimary] = true; + dns_remote_mark(&zone->primaries, true); goto next_primary; } if (msg != NULL) { @@ -14563,12 +14360,9 @@ next_primary: /* * Skip to next failed / untried primary. */ - do { - zone->curprimary++; - } while (zone->curprimary < zone->primariescnt && - zone->primariesok[zone->curprimary]); + dns_remote_next(&zone->primaries, true); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS); - if (zone->curprimary >= zone->primariescnt) { + if (dns_remote_done(&zone->primaries)) { bool done = true; if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) @@ -14576,27 +14370,16 @@ next_primary: /* * Did we get a good answer from all the primaries? */ - for (j = 0; j < zone->primariescnt; j++) { - if (!zone->primariesok[j]) { - { - done = false; - break; - } - } - } - } else { - done = true; + done = dns_remote_allgood(&zone->primaries); } if (!done) { DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); - zone->curprimary = 0; + dns_remote_reset(&zone->primaries, false); /* * Find the next failed primary. */ - while (zone->curprimary < zone->primariescnt && - zone->primariesok[zone->curprimary]) - { - zone->curprimary++; + if (dns_remote_addrok(&zone->primaries)) { + dns_remote_next(&zone->primaries, true); } goto requeue; } @@ -14687,6 +14470,7 @@ soa_query(isc_task_t *task, isc_event_t *event) { bool have_xfrsource, have_xfrdscp, reqnsid, reqexpire; uint16_t udpsize = SEND_BUFFER_SIZE; isc_dscp_t dscp = -1; + isc_sockaddr_t curraddr, sourceaddr; bool do_queue_xfrin = false; REQUIRE(DNS_ZONE_VALID(zone)); @@ -14707,21 +14491,24 @@ soa_query(isc_task_t *task, isc_event_t *event) { } again: - INSIST(zone->primariescnt > 0); - INSIST(zone->curprimary < zone->primariescnt); + dns_zone_log( + zone, ISC_LOG_DEBUG(3), + "soa_query: remote server current address index %d count %d", + zone->primaries.curraddr, zone->primaries.addrcnt); + INSIST(dns_remote_count(&zone->primaries) > 0); + INSIST(!dns_remote_done(&zone->primaries)); - zone->primaryaddr = zone->primaries[zone->curprimary]; + sourceaddr = dns_remote_sourceaddr(&zone->primaries); + curraddr = dns_remote_curraddr(&zone->primaries); + isc_netaddr_fromsockaddr(&primaryip, &curraddr); - isc_netaddr_fromsockaddr(&primaryip, &zone->primaryaddr); /* * First, look for a tsig key in the primaries statement, then * try for a server key. */ - if ((zone->primarykeynames != NULL) && - (zone->primarykeynames[zone->curprimary] != NULL)) - { + if (dns_remote_keyname(&zone->primaries) != NULL) { dns_view_t *view = dns_zone_getview(zone); - dns_name_t *keyname = zone->primarykeynames[zone->curprimary]; + dns_name_t *keyname = dns_remote_keyname(&zone->primaries); result = dns_view_gettsig(view, keyname, &key); if (result != ISC_R_SUCCESS) { char namebuf[DNS_NAME_FORMATSIZE]; @@ -14743,11 +14530,9 @@ again: } } - if ((zone->primarytlsnames != NULL) && - (zone->primarytlsnames[zone->curprimary] != NULL)) - { + if (dns_remote_tlsname(&zone->primaries) != NULL) { dns_view_t *view = dns_zone_getview(zone); - dns_name_t *tlsname = zone->primarytlsnames[zone->curprimary]; + dns_name_t *tlsname = dns_remote_tlsname(&zone->primaries); result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname, &transport); if (result != ISC_R_SUCCESS) { @@ -14795,42 +14580,34 @@ again: } } - switch (isc_sockaddr_pf(&zone->primaryaddr)) { + switch (isc_sockaddr_pf(&curraddr)) { case PF_INET: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { - if (isc_sockaddr_equal(&zone->altxfrsource4, - &zone->xfrsource4)) - { - goto skip_primary; - } - zone->sourceaddr = zone->altxfrsource4; - if (!have_xfrdscp) { - dscp = zone->altxfrsource4dscp; - } - } else if (!have_xfrsource) { - zone->sourceaddr = zone->xfrsource4; - if (!have_xfrdscp) { - dscp = zone->xfrsource4dscp; + if (!have_xfrsource) { + isc_sockaddr_t any; + isc_sockaddr_any(&any); + + zone->sourceaddr = sourceaddr; + if (isc_sockaddr_equal(&sourceaddr, &any)) { + zone->sourceaddr = zone->xfrsource4; } } + if (!have_xfrdscp) { + dscp = zone->xfrsource4dscp; + } break; case PF_INET6: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { - if (isc_sockaddr_equal(&zone->altxfrsource6, - &zone->xfrsource6)) - { - goto skip_primary; - } - zone->sourceaddr = zone->altxfrsource6; - if (!have_xfrdscp) { - dscp = zone->altxfrsource6dscp; - } - } else if (!have_xfrsource) { - zone->sourceaddr = zone->xfrsource6; - if (!have_xfrdscp) { - dscp = zone->xfrsource6dscp; + if (!have_xfrsource) { + isc_sockaddr_t any; + isc_sockaddr_any6(&any); + + zone->sourceaddr = sourceaddr; + if (isc_sockaddr_equal(&zone->sourceaddr, &any)) { + zone->sourceaddr = zone->xfrsource6; } } + if (!have_xfrdscp) { + dscp = zone->xfrsource6dscp; + } break; default: result = ISC_R_NOTIMPLEMENTED; @@ -14867,9 +14644,9 @@ again: timeout = 30; } result = dns_request_create( - zone->view->requestmgr, message, &zone->sourceaddr, - &zone->primaryaddr, NULL, NULL, dscp, options, key, timeout * 3, - timeout, 2, zone->task, refresh_callback, zone, &zone->request); + zone->view->requestmgr, message, &zone->sourceaddr, &curraddr, + NULL, NULL, dscp, options, key, timeout * 3, timeout, 2, + zone->task, refresh_callback, zone, &zone->request); if (result != ISC_R_SUCCESS) { zone_idetach(&dummy); zone_debuglog(zone, __func__, 1, @@ -14877,7 +14654,7 @@ again: isc_result_totext(result)); goto skip_primary; } else { - if (isc_sockaddr_pf(&zone->primaryaddr) == PF_INET) { + if (isc_sockaddr_pf(&curraddr) == PF_INET) { inc_stats(zone, dns_zonestatscounter_soaoutv4); } else { inc_stats(zone, dns_zonestatscounter_soaoutv6); @@ -14921,14 +14698,11 @@ skip_primary: /* * Skip to next failed / untried primary. */ - do { - zone->curprimary++; - } while (zone->curprimary < zone->primariescnt && - zone->primariesok[zone->curprimary]); - if (zone->curprimary < zone->primariescnt) { + dns_remote_next(&zone->primaries, true); + if (!dns_remote_done(&zone->primaries)) { goto again; } - zone->curprimary = 0; + dns_remote_reset(&zone->primaries, false); goto cleanup; } @@ -14944,6 +14718,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { bool reqnsid; uint16_t udpsize = SEND_BUFFER_SIZE; isc_dscp_t dscp = -1; + isc_sockaddr_t curraddr, sourceaddr; struct stub_cb_args *cb_args; REQUIRE(DNS_ZONE_VALID(zone)); @@ -15034,20 +14809,19 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { */ create_query(zone, dns_rdatatype_ns, &zone->origin, &message); - INSIST(zone->primariescnt > 0); - INSIST(zone->curprimary < zone->primariescnt); - zone->primaryaddr = zone->primaries[zone->curprimary]; + INSIST(dns_remote_count(&zone->primaries) > 0); + INSIST(!dns_remote_done(&zone->primaries)); - isc_netaddr_fromsockaddr(&primaryip, &zone->primaryaddr); + sourceaddr = dns_remote_sourceaddr(&zone->primaries); + curraddr = dns_remote_curraddr(&zone->primaries); + isc_netaddr_fromsockaddr(&primaryip, &curraddr); /* * First, look for a tsig key in the primaries statement, then * try for a server key. */ - if ((zone->primarykeynames != NULL) && - (zone->primarykeynames[zone->curprimary] != NULL)) - { + if (dns_remote_keyname(&zone->primaries) != NULL) { dns_view_t *view = dns_zone_getview(zone); - dns_name_t *keyname = zone->primarykeynames[zone->curprimary]; + dns_name_t *keyname = dns_remote_keyname(&zone->primaries); result = dns_view_gettsig(view, keyname, &key); if (result != ISC_R_SUCCESS) { char namebuf[DNS_NAME_FORMATSIZE]; @@ -15099,32 +14873,34 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { /* * Always use TCP so that we shouldn't truncate in additional section. */ - switch (isc_sockaddr_pf(&zone->primaryaddr)) { + switch (isc_sockaddr_pf(&curraddr)) { case PF_INET: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { - zone->sourceaddr = zone->altxfrsource4; - if (!have_xfrdscp) { - dscp = zone->altxfrsource4dscp; - } - } else if (!have_xfrsource) { - zone->sourceaddr = zone->xfrsource4; - if (!have_xfrdscp) { - dscp = zone->xfrsource4dscp; + if (!have_xfrsource) { + isc_sockaddr_t any; + isc_sockaddr_any(&any); + + zone->sourceaddr = sourceaddr; + if (isc_sockaddr_equal(&zone->sourceaddr, &any)) { + zone->sourceaddr = zone->xfrsource4; } } + if (!have_xfrdscp) { + dscp = zone->xfrsource4dscp; + } break; case PF_INET6: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { - zone->sourceaddr = zone->altxfrsource6; - if (!have_xfrdscp) { - dscp = zone->altxfrsource6dscp; - } - } else if (!have_xfrsource) { - zone->sourceaddr = zone->xfrsource6; - if (!have_xfrdscp) { - dscp = zone->xfrsource6dscp; + if (!have_xfrsource) { + isc_sockaddr_t any; + isc_sockaddr_any6(&any); + + zone->sourceaddr = sourceaddr; + if (isc_sockaddr_equal(&zone->sourceaddr, &any)) { + zone->sourceaddr = zone->xfrsource6; } } + if (!have_xfrdscp) { + dscp = zone->xfrsource6dscp; + } break; default: result = ISC_R_NOTIMPLEMENTED; @@ -15148,11 +14924,10 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { cb_args->timeout = timeout; cb_args->reqnsid = reqnsid; - result = dns_request_create(zone->view->requestmgr, message, - &zone->sourceaddr, &zone->primaryaddr, NULL, - NULL, dscp, DNS_REQUESTOPT_TCP, key, - timeout * 3, timeout, 2, zone->task, - stub_callback, cb_args, &zone->request); + result = dns_request_create( + zone->view->requestmgr, message, &zone->sourceaddr, &curraddr, + NULL, NULL, dscp, DNS_REQUESTOPT_TCP, key, timeout * 3, timeout, + 2, zone->task, stub_callback, cb_args, &zone->request); if (result != ISC_R_SUCCESS) { zone_debuglog(zone, __func__, 1, "dns_request_create() failed: %s", @@ -15362,7 +15137,7 @@ zone__settimer(void *arg) { switch (zone->type) { case dns_zone_redirect: - if (zone->primaries != NULL) { + if (dns_remote_addresses(&zone->primaries) != NULL) { goto treat_as_secondary; } FALLTHROUGH; @@ -15755,17 +15530,18 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, } isc_netaddr_fromsockaddr(&netaddr, from); - for (i = 0; i < zone->primariescnt; i++) { - if (isc_sockaddr_eqaddr(from, &zone->primaries[i])) { + for (i = 0; i < dns_remote_count(&zone->primaries); i++) { + isc_sockaddr_t sockaddr = dns_remote_addr(&zone->primaries, i); + if (isc_sockaddr_eqaddr(from, &sockaddr)) { break; } if (zone->view->aclenv->match_mapped && IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) && - isc_sockaddr_pf(&zone->primaries[i]) == AF_INET) + isc_sockaddr_pf(&sockaddr) == AF_INET) { isc_netaddr_t na1, na2; isc_netaddr_fromv4mapped(&na1, &netaddr); - isc_netaddr_fromsockaddr(&na2, &zone->primaries[i]); + isc_netaddr_fromsockaddr(&na2, &sockaddr); if (isc_netaddr_equal(&na1, &na2)) { break; } @@ -15778,13 +15554,14 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, */ tsigkey = dns_message_gettsigkey(msg); tsig = dns_tsigkey_identity(tsigkey); - if (i >= zone->primariescnt && zone->notify_acl != NULL && + if (i >= dns_remote_count(&zone->primaries) && + zone->notify_acl != NULL && (dns_acl_match(&netaddr, tsig, zone->notify_acl, zone->view->aclenv, &match, NULL) == ISC_R_SUCCESS) && match > 0) { /* Accept notify. */ - } else if (i >= zone->primariescnt) { + } else if (i >= dns_remote_count(&zone->primaries)) { UNLOCK_ZONE(zone); dns_zone_log(zone, ISC_LOG_INFO, "refused notify from non-primary: %s", fromtext); @@ -16405,8 +16182,9 @@ dns_zone_getredirecttype(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(zone->type == dns_zone_redirect); - return (zone->primaries == NULL ? dns_zone_primary - : dns_zone_secondary); + return (dns_remote_addresses(&zone->primaries) == NULL + ? dns_zone_primary + : dns_zone_secondary); } dns_name_t * @@ -17583,7 +17361,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) { RUNTIME_CHECK(soacount > 0U); if ((zone->type == dns_zone_secondary || (zone->type == dns_zone_redirect && - zone->primaries != NULL)) && + dns_remote_addresses(&zone->primaries) != NULL)) && !isc_serial_gt(serial, oldserial)) { uint32_t serialmin, serialmax; @@ -17905,23 +17683,18 @@ again: /* * Skip to next failed / untried primary. */ - do { - zone->curprimary++; - } while (zone->curprimary < zone->primariescnt && - zone->primariesok[zone->curprimary]); + dns_remote_next(&zone->primaries, true); same_primary: - if (zone->curprimary >= zone->primariescnt) { - zone->curprimary = 0; + if (dns_remote_done(&zone->primaries)) { + dns_remote_reset(&zone->primaries, false); if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) { DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); - while (zone->curprimary < zone->primariescnt && - zone->primariesok[zone->curprimary]) - { - zone->curprimary++; + if (dns_remote_addrok(&zone->primaries)) { + dns_remote_next(&zone->primaries, true); } again = true; } else { @@ -18195,8 +17968,8 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) { dns_rdatatype_t xfrtype; dns_zone_t *zone = event->ev_arg; isc_netaddr_t primaryip; - isc_sockaddr_t sourceaddr; isc_sockaddr_t primaryaddr; + isc_sockaddr_t sourceaddr; isc_time_t now; const char *soa_before = ""; isc_dscp_t dscp = -1; @@ -18212,9 +17985,10 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) { TIME_NOW(&now); - isc_sockaddr_format(&zone->primaryaddr, primary, sizeof(primary)); - if (dns_zonemgr_unreachable(zone->zmgr, &zone->primaryaddr, - &zone->sourceaddr, &now)) + primaryaddr = dns_remote_curraddr(&zone->primaries); + isc_sockaddr_format(&primaryaddr, primary, sizeof(primary)); + if (dns_zonemgr_unreachable(zone->zmgr, &primaryaddr, &zone->sourceaddr, + &now)) { isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source)); dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO, @@ -18224,7 +17998,7 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) { CHECK(ISC_R_CANCELED); } - isc_netaddr_fromsockaddr(&primaryip, &zone->primaryaddr); + isc_netaddr_fromsockaddr(&primaryip, &primaryaddr); (void)dns_peerlist_peerbyaddr(zone->view->peers, &primaryip, &peer); if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) { @@ -18294,11 +18068,9 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) { * First, look for a tsig key in the primaries statement, then * try for a server key. */ - if ((zone->primarykeynames != NULL) && - (zone->primarykeynames[zone->curprimary] != NULL)) - { + if (dns_remote_keyname(&zone->primaries) != NULL) { dns_view_t *view = dns_zone_getview(zone); - dns_name_t *keyname = zone->primarykeynames[zone->curprimary]; + dns_name_t *keyname = dns_remote_keyname(&zone->primaries); result = dns_view_gettsig(view, keyname, &zone->tsigkey); } if (zone->tsigkey == NULL) { @@ -18312,11 +18084,9 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) { isc_result_totext(result)); } - if ((zone->primarytlsnames != NULL) && - (zone->primarytlsnames[zone->curprimary] != NULL)) - { + if (dns_remote_tlsname(&zone->primaries) != NULL) { dns_view_t *view = dns_zone_getview(zone); - dns_name_t *tlsname = zone->primarytlsnames[zone->curprimary]; + dns_name_t *tlsname = dns_remote_tlsname(&zone->primaries); result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname, &zone->transport); @@ -18332,12 +18102,9 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) { isc_result_totext(result)); } - if (zone->primarydscps != NULL) { - dscp = zone->primarydscps[zone->curprimary]; - } + dscp = dns_remote_dscp(&zone->primaries); LOCK_ZONE(zone); - primaryaddr = zone->primaryaddr; sourceaddr = zone->sourceaddr; switch (isc_sockaddr_pf(&primaryaddr)) { case PF_INET: @@ -18423,7 +18190,7 @@ forward_destroy(dns_forward_t *forward) { static isc_result_t sendtoprimary(dns_forward_t *forward) { isc_result_t result; - isc_sockaddr_t src; + isc_sockaddr_t src, any; isc_dscp_t dscp = -1; dns_zone_t *zone = forward->zone; bool tls_transport_invalid = false; @@ -18435,12 +18202,12 @@ sendtoprimary(dns_forward_t *forward) { return (ISC_R_CANCELED); } - if (forward->which >= zone->primariescnt) { + if (forward->which >= dns_remote_count(&forward->zone->primaries)) { UNLOCK_ZONE(zone); return (ISC_R_NOMORE); } - forward->addr = zone->primaries[forward->which]; + forward->addr = dns_remote_addr(&zone->primaries, forward->which); /* * Always use TCP regardless of whether the original update * used TCP. @@ -18449,11 +18216,19 @@ sendtoprimary(dns_forward_t *forward) { */ switch (isc_sockaddr_pf(&forward->addr)) { case PF_INET: - src = zone->xfrsource4; + isc_sockaddr_any(&any); + src = zone->primaries.sources[forward->which]; + if (isc_sockaddr_equal(&src, &any)) { + src = zone->xfrsource4; + } dscp = zone->xfrsource4dscp; break; case PF_INET6: - src = zone->xfrsource6; + isc_sockaddr_any6(&any); + src = zone->primaries.sources[forward->which]; + if (isc_sockaddr_equal(&src, &any)) { + src = zone->xfrsource6; + } dscp = zone->xfrsource6dscp; break; default: @@ -18465,11 +18240,11 @@ sendtoprimary(dns_forward_t *forward) { dns_transport_detach(&forward->transport); } - if (zone->primarytlsnames != NULL && - zone->primarytlsnames[forward->which] != NULL) + if (dns_remote_tlsname(&zone->primaries) != NULL && + zone->primaries.tlsnames[forward->which] != NULL) { dns_view_t *view = dns_zone_getview(zone); - dns_name_t *tlsname = zone->primarytlsnames[forward->which]; + dns_name_t *tlsname = zone->primaries.tlsnames[forward->which]; result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname, &forward->transport); @@ -19288,6 +19063,7 @@ static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) { dns_peer_t *peer = NULL; isc_netaddr_t primaryip; + isc_sockaddr_t curraddr; uint32_t nxfrsin, nxfrsperns; dns_zone_t *x; uint32_t maxtransfersin, maxtransfersperns; @@ -19307,7 +19083,8 @@ zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) { * Find any configured information about the server we'd * like to transfer this zone from. */ - isc_netaddr_fromsockaddr(&primaryip, &zone->primaryaddr); + curraddr = dns_remote_curraddr(&zone->primaries); + isc_netaddr_fromsockaddr(&primaryip, &curraddr); (void)dns_peerlist_peerbyaddr(zone->view->peers, &primaryip, &peer); UNLOCK_ZONE(zone); @@ -19333,9 +19110,11 @@ zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) { x = ISC_LIST_NEXT(x, statelink)) { isc_netaddr_t xip; + isc_sockaddr_t xaddr; LOCK_ZONE(x); - isc_netaddr_fromsockaddr(&xip, &x->primaryaddr); + xaddr = dns_remote_curraddr(&x->primaries); + isc_netaddr_fromsockaddr(&xip, &xaddr); UNLOCK_ZONE(x); nxfrsin++; @@ -19730,7 +19509,8 @@ dns_zone_forcereload(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); if (zone->type == dns_zone_primary || - (zone->type == dns_zone_redirect && zone->primaries == NULL)) + (zone->type == dns_zone_redirect && + dns_remote_addresses(&zone->primaries) == NULL)) { return; } @@ -19867,7 +19647,8 @@ dns_zone_dialup(dns_zone_t *zone) { if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) { dns_zone_notify(zone); } - if (zone->type != dns_zone_primary && zone->primaries != NULL && + if (zone->type != dns_zone_primary && + dns_remote_addresses(&zone->primaries) != NULL && DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) { dns_zone_refresh(zone); @@ -20717,7 +20498,7 @@ do_checkds(dns_zone_t *zone, dst_key_t *key, isc_stdtime_t now, "for key %u", count, dst_key_id(key)); - if (count != zone->parentalscnt) { + if (count != dns_remote_count(&zone->parentals)) { return false; } } else { @@ -20729,7 +20510,7 @@ do_checkds(dns_zone_t *zone, dst_key_t *key, isc_stdtime_t now, "for key %u", count, dst_key_id(key)); - if (count != zone->parentalscnt) { + if (count != dns_remote_count(&zone->parentals)) { return false; } } @@ -21182,7 +20963,13 @@ checkds_send_toaddr(isc_task_t *task, isc_event_t *event) { switch (isc_sockaddr_pf(&checkds->dst)) { case PF_INET: if (!have_checkdssource) { - src = checkds->zone->parentalsrc4; + isc_sockaddr_t any; + isc_sockaddr_any(&any); + + src = checkds->src; + if (isc_sockaddr_equal(&src, &any)) { + src = checkds->zone->parentalsrc4; + } } if (!have_checkdsdscp) { dscp = checkds->zone->parentalsrc4dscp; @@ -21190,7 +20977,13 @@ checkds_send_toaddr(isc_task_t *task, isc_event_t *event) { break; case PF_INET6: if (!have_checkdssource) { - src = checkds->zone->parentalsrc6; + isc_sockaddr_t any; + isc_sockaddr_any6(&any); + + src = checkds->src; + if (isc_sockaddr_equal(&src, &any)) { + src = checkds->zone->parentalsrc6; + } } if (!have_checkdsdscp) { dscp = checkds->zone->parentalsrc6dscp; @@ -21255,6 +21048,7 @@ checkds_send(dns_zone_t *zone) { dns_view_t *view = dns_zone_getview(zone); isc_result_t result; unsigned int flags = 0; + unsigned int i = 0; /* * Zone lock held by caller. @@ -21263,7 +21057,7 @@ checkds_send(dns_zone_t *zone) { dns_zone_log(zone, ISC_LOG_DEBUG(3), "checkds: start sending DS queries to %u parentals", - zone->parentalscnt); + dns_remote_count(&zone->parentals)); if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) { dns_zone_log(zone, ISC_LOG_DEBUG(3), @@ -21271,23 +21065,24 @@ checkds_send(dns_zone_t *zone) { return; } - for (unsigned int i = 0; i < zone->parentalscnt; i++) { + dns_remote_reset(&zone->parentals, false); + while (!dns_remote_done(&zone->parentals)) { dns_tsigkey_t *key = NULL; dns_transport_t *transport = NULL; - isc_sockaddr_t dst; + isc_sockaddr_t src, dst; dns_checkds_t *checkds = NULL; - if ((zone->parentalkeynames != NULL) && - (zone->parentalkeynames[i] != NULL)) - { - dns_name_t *keyname = zone->parentalkeynames[i]; + i++; + + if (dns_remote_keyname(&zone->parentals) != NULL) { + dns_name_t *keyname = + dns_remote_keyname(&zone->parentals); (void)dns_view_gettsig(view, keyname, &key); } - if ((zone->parentaltlsnames != NULL) && - (zone->parentaltlsnames[i] != NULL)) - { - dns_name_t *tlsname = zone->parentaltlsnames[i]; + if (dns_remote_tlsname(&zone->parentals) != NULL) { + dns_name_t *tlsname = + dns_remote_tlsname(&zone->parentals); (void)dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname, &transport); dns_zone_logc( @@ -21295,7 +21090,9 @@ checkds_send(dns_zone_t *zone) { "got TLS configuration for zone transfer"); } - dst = zone->parentals[i]; + dst = dns_remote_curraddr(&zone->parentals); + src = dns_remote_sourceaddr(&zone->parentals); + INSIST(isc_sockaddr_pf(&src) == isc_sockaddr_pf(&dst)); /* TODO: glue the transport to the checkds request */ @@ -21310,7 +21107,7 @@ checkds_send(dns_zone_t *zone) { if (transport != NULL) { dns_transport_detach(&transport); } - continue; + goto next; } dns_zone_log(zone, ISC_LOG_DEBUG(3), @@ -21324,9 +21121,10 @@ checkds_send(dns_zone_t *zone) { "checkds: create DS query for " "parent %d failed", i); - continue; + goto next; } zone_iattach(zone, &checkds->zone); + checkds->src = src; checkds->dst = dst; INSIST(checkds->key == NULL); @@ -21350,6 +21148,9 @@ checkds_send(dns_zone_t *zone) { i); checkds_destroy(checkds, true); } + + next: + dns_remote_next(&zone->parentals, false); } } diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 0ea0cf151f..0f2cdd224b 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -121,6 +121,8 @@ static cfg_type_t cfg_type_optional_dscp; static cfg_type_t cfg_type_optional_facility; static cfg_type_t cfg_type_optional_keyref; static cfg_type_t cfg_type_optional_port; +static cfg_type_t cfg_type_optional_sourceaddr4; +static cfg_type_t cfg_type_optional_sourceaddr6; static cfg_type_t cfg_type_optional_uint32; static cfg_type_t cfg_type_optional_tls; static cfg_type_t cfg_type_options; @@ -234,6 +236,8 @@ static cfg_tuplefielddef_t remotes_fields[] = { { "name", &cfg_type_astring, 0 }, { "port", &cfg_type_optional_port, 0 }, { "dscp", &cfg_type_optional_dscp, 0 }, + { "source", &cfg_type_optional_sourceaddr4, 0 }, + { "source-v6", &cfg_type_optional_sourceaddr6, 0 }, { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 }, { NULL, NULL, 0 } }; @@ -273,6 +277,8 @@ static cfg_type_t cfg_type_bracketed_namesockaddrkeylist = { static cfg_tuplefielddef_t namesockaddrkeylist_fields[] = { { "port", &cfg_type_optional_port, 0 }, { "dscp", &cfg_type_optional_dscp, 0 }, + { "source", &cfg_type_optional_sourceaddr4, 0 }, + { "source-v6", &cfg_type_optional_sourceaddr6, 0 }, { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 }, { NULL, NULL, 0 } }; @@ -3573,6 +3579,20 @@ static cfg_type_t cfg_type_sockaddr6wild = { cfg_doc_sockaddr, &cfg_rep_sockaddr, &sockaddr6wild_flags }; +static keyword_type_t sourceaddr4_kw = { "source", &cfg_type_sockaddr4wild }; + +static cfg_type_t cfg_type_optional_sourceaddr4 = { + "optional_sourceaddr4", parse_optional_keyvalue, print_keyvalue, + doc_optional_keyvalue, &cfg_rep_sockaddr, &sourceaddr4_kw +}; + +static keyword_type_t sourceaddr6_kw = { "source-v6", &cfg_type_sockaddr6wild }; + +static cfg_type_t cfg_type_optional_sourceaddr6 = { + "optional_sourceaddr6", parse_optional_keyvalue, print_keyvalue, + doc_optional_keyvalue, &cfg_rep_sockaddr, &sourceaddr6_kw +}; + /*% * rndc */