#include <string.h>
+#include <isc/buffer.h>
+#include <isc/mem.h>
#include <isc/netaddr.h>
#include <isc/print.h>
#include <isc/util.h>
#include <dns/ecs.h>
+#include <dns/nsec.h>
+#include <dns/rbt.h>
+#include <dns/rdata.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
#include <dns/types.h>
void
dns_ecs_init(dns_ecs_t *ecs) {
isc_netaddr_unspec(&ecs->addr);
ecs->source = 0;
+ ecs->scope = 0xff;
+}
+
+bool
+dns_ecs_equals(const dns_ecs_t *ecs1, const dns_ecs_t *ecs2) {
+ const unsigned char *addr1, *addr2;
+ uint8_t mask;
+ size_t alen;
+
+ REQUIRE(ecs1 != NULL && ecs2 != NULL);
+
+ if (ecs1->source != ecs2->source ||
+ ecs1->addr.family != ecs2->addr.family) {
+ return (false);
+ }
+
+ alen = (ecs1->source + 7) / 8;
+ if (alen == 0) {
+ return (true);
+ }
+
+ switch (ecs1->addr.family) {
+ case AF_INET:
+ INSIST(alen <= 4);
+ addr1 = (const unsigned char *)&ecs1->addr.type.in;
+ addr2 = (const unsigned char *)&ecs2->addr.type.in;
+ break;
+ case AF_INET6:
+ INSIST(alen <= 16);
+ addr1 = (const unsigned char *)&ecs1->addr.type.in6;
+ addr2 = (const unsigned char *)&ecs2->addr.type.in6;
+ break;
+ default:
+ INSIST(0);
+ ISC_UNREACHABLE();
+ }
+
+ /*
+ * Compare all octets except the final octet of the address
+ * prefix.
+ */
+ if (alen > 1 && memcmp(addr1, addr2, alen - 1) != 0) {
+ return (false);
+ }
+
/*
- * XXXMUKS: Fix me when resolver ECS gets merged where scope
- * gets initialized to 0xff.
+ * It should not be necessary to mask the final octet; all
+ * bits past the source prefix length are supposed to be 0.
+ * However, it seems prudent not to omit them from the
+ * comparison anyway.
*/
- ecs->scope = 0;
+ mask = (~0U << (8 - (ecs1->source % 8))) & 0xff;
+ if (mask == 0) {
+ mask = 0xff;
+ }
+
+ if ((addr1[alen - 1] & mask) != (addr2[alen - 1] & mask)) {
+ return (false);
+ }
+
+ return (true);
}
void
-dns_ecs_format(dns_ecs_t *ecs, char *buf, size_t size) {
+dns_ecs_format(const dns_ecs_t *ecs, char *buf, size_t size) {
size_t len;
+ char *p;
REQUIRE(ecs != NULL);
REQUIRE(buf != NULL);
REQUIRE(size >= DNS_ECS_FORMATSIZE);
- isc_netaddr_format(&ecs->addr, buf, (unsigned int)size);
+ isc_netaddr_format(&ecs->addr, buf, size);
len = strlen(buf);
- INSIST(size >= len);
- buf += len;
- size -= len;
- snprintf(buf, size, "/%u/%u", ecs->source, ecs->scope);
+ p = buf + len;
+ snprintf(p, size - len, "/%d/%d", ecs->source,
+ ecs->scope == 0xff ? 0 : ecs->scope);
}
dns_db_t *tdbp;
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, &client->ecs, NULL);
tdbp = NULL;
tresult = dns_view_searchdlz(client->view, name, zonelabels,
isc_result_t result;
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, NULL, NULL);
/*
* Since we are looking for authoritative data, we do not set
CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb");
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, NULL, NULL);
/*
* We treat type A additional section processing as if it
rdataset->trust = dns_trust_secure;
sigrdataset->trust = dns_trust_secure;
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, NULL, NULL);
/*
* Save the updated secure state. Ignore failures.
dns_clientinfo_t ci;
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, NULL, NULL);
if (!dns_rdataset_isassociated(keyrdataset)) {
result = dns_db_findnodeext(db, &rrsig->signer, false, &cm, &ci,
node = NULL;
found = dns_fixedname_initname(&fixed);
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, NULL, NULL);
result = dns_db_findext(*dbp, name, version, type, DNS_DBFIND_GLUEOK,
client->now, &node, found, &cm, &ci, *rdatasetp,
NULL);
CTRACE(ISC_LOG_DEBUG(3), "rpz_find_p");
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, NULL, NULL);
/*
* Try to find either a CNAME or the type of record demanded by the
dns_name_clone(qname, &name);
labels = dns_name_countlabels(&name);
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, NULL, NULL);
/*
* Map unknown algorithm to known value.
dns_rdataset_init(&trdataset);
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, &client->ecs, NULL);
if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
{
dns_rdataset_init(&trdataset);
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, &client->ecs, NULL);
if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
{
CALL_HOOK(NS_QUERY_LOOKUP_BEGIN, qctx);
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, qctx->client, NULL);
+ dns_clientinfo_init(&ci, qctx->client,
+ HAVEECS(qctx->client) ? &qctx->client->ecs : NULL,
+ NULL);
/*
* We'll need some resources...
dns_clientinfo_t ci;
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, qctx->client, NULL);
+ dns_clientinfo_init(&ci, qctx->client, NULL, NULL);
dns_db_attach(qctx->view->hints, &qctx->db);
result = dns_db_findext(qctx->db, dns_rootname, NULL,
nowild = dns_fixedname_initname(&fnowild);
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, qctx->client, NULL);
+ dns_clientinfo_init(&ci, qctx->client, NULL, NULL);
/*
* All signer names must be the same to accept.
node = NULL;
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, NULL, NULL);
/*
* Don't add the SOA record for test which set "-T nosoa".
fname = dns_fixedname_initname(&foundname);
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, NULL, NULL);
/*
* Get resources and make 'name' be the database origin.
CTRACE(ISC_LOG_DEBUG(3), "query_addbestns");
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, NULL, NULL);
/*
* Find the right database.
CTRACE(ISC_LOG_DEBUG(3), "query_addwildcardproof");
dns_clientinfomethods_init(&cm, ns_client_sourceip);
- dns_clientinfo_init(&ci, client, NULL);
+ dns_clientinfo_init(&ci, client, NULL, NULL);
/*
* If a name has been specifically flagged as needing