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);
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);
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);
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);
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;
}
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);
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) {
element = stack[pushed].element;
port = stack[pushed].port;
dscp = stack[pushed].dscp;
+ src4 = stack[pushed].src4;
+ src6 = stack[pushed].src6;
goto 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]));
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;
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;
}
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;
}
}
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]));
}
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;
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);
}
}
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;
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;
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;
* '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);
/*%<
void
dns_remote_init(dns_remote_t *remote, unsigned int count,
- const isc_sockaddr_t *addrs, const isc_dscp_t *dscp,
- dns_name_t **keynames, dns_name_t **tlsnames, bool mark,
- isc_mem_t *mctx);
+ 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),
- * 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.
+ * 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.
* '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);
/*%<
void
dns_zone_setprimaries(dns_zone_t *zone, isc_sockaddr_t *addresses,
- dns_name_t **keynames, dns_name_t **tlsnames,
- uint32_t count);
+ isc_sockaddr_t *sources, dns_name_t **keynames,
+ dns_name_t **tlsnames, uint32_t count);
/*%<
* Set the list of primary servers for the zone.
*
void
dns_zone_setparentals(dns_zone_t *zone, isc_sockaddr_t *addresses,
- dns_name_t **keynames, dns_name_t **tlsnames,
- uint32_t count);
+ isc_sockaddr_t *sources, dns_name_t **keynames,
+ dns_name_t **tlsnames, uint32_t count);
/*%<
* Set the list of parental agents for the zone.
*
void
dns_zone_setalsonotify(dns_zone_t *zone, isc_sockaddr_t *addresses,
- isc_dscp_t *dscps, dns_name_t **keynames,
- dns_name_t **tlsnames, uint32_t count);
+ 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'.
ipkl->count = 0;
ipkl->allocated = 0;
ipkl->addrs = NULL;
+ ipkl->sources = NULL;
ipkl->dscps = NULL;
ipkl->keys = NULL;
ipkl->tlss = NULL;
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) {
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));
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;
}
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 *));
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));
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 *));
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));
void
dns_remote_init(dns_remote_t *remote, unsigned int count,
- const isc_sockaddr_t *addrs, const isc_dscp_t *dscp,
- dns_name_t **keynames, dns_name_t **tlsnames, bool mark,
- isc_mem_t *mctx) {
+ 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));
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));
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;
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));
void
dns_zone_setalsonotify(dns_zone_t *zone, isc_sockaddr_t *addresses,
- isc_dscp_t *dscps, dns_name_t **keynames,
- dns_name_t **tlsnames, uint32_t count) {
+ 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));
remote.magic = DNS_REMOTE_MAGIC;
remote.addresses = addresses;
+ remote.sources = sources;
remote.dscps = dscps;
remote.keynames = keynames;
remote.tlsnames = tlsnames;
/*
* Now set up the notify address and key lists.
*/
- dns_remote_init(&zone->notify, count, addresses, dscps, keynames,
- tlsnames, true, zone->mctx);
+ dns_remote_init(&zone->notify, count, addresses, sources, dscps,
+ keynames, tlsnames, true, zone->mctx);
unlock:
UNLOCK_ZONE(zone);
void
dns_zone_setprimaries(dns_zone_t *zone, isc_sockaddr_t *addresses,
- dns_name_t **keynames, dns_name_t **tlsnames,
- uint32_t count) {
+ isc_sockaddr_t *sources, dns_name_t **keynames,
+ dns_name_t **tlsnames, uint32_t count) {
dns_remote_t remote;
REQUIRE(DNS_ZONE_VALID(zone));
remote.magic = DNS_REMOTE_MAGIC;
remote.addresses = addresses;
+ remote.sources = sources;
remote.dscps = NULL;
remote.keynames = keynames;
remote.tlsnames = tlsnames;
/*
* Now set up the primaries and primary key lists.
*/
- dns_remote_init(&zone->primaries, count, addresses, NULL, keynames,
- tlsnames, true, zone->mctx);
+ dns_remote_init(&zone->primaries, count, addresses, sources, NULL,
+ keynames, tlsnames, true, zone->mctx);
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOPRIMARIES);
void
dns_zone_setparentals(dns_zone_t *zone, isc_sockaddr_t *addresses,
- dns_name_t **keynames, dns_name_t **tlsnames,
- uint32_t count) {
+ isc_sockaddr_t *sources, dns_name_t **keynames,
+ dns_name_t **tlsnames, uint32_t count) {
dns_remote_t remote;
REQUIRE(DNS_ZONE_VALID(zone));
remote.magic = DNS_REMOTE_MAGIC;
remote.addresses = addresses;
+ remote.sources = sources;
remote.dscps = NULL;
remote.keynames = keynames;
remote.tlsnames = tlsnames;
/*
* Now set up the parentals and parental key lists.
*/
- dns_remote_init(&zone->parentals, count, addresses, NULL, keynames,
- tlsnames, true, zone->mctx);
+ 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);