allow dns_clientinfo to store client ECS data

this brings DNS_CLIENTINFO_VERSION into line with the subscription
branch so that fixes applied to clientinfo processing can also be
applied to the main branch without diverging.
This commit is contained in:
Evan Hunt 2021-11-02 22:38:45 -07:00
parent 3b53680458
commit 737e658602
6 changed files with 136 additions and 39 deletions

View file

@ -14,6 +14,7 @@
/*! \file */
#include <dns/clientinfo.h>
#include <dns/ecs.h>
void
dns_clientinfomethods_init(dns_clientinfomethods_t *methods,
@ -24,8 +25,14 @@ dns_clientinfomethods_init(dns_clientinfomethods_t *methods,
}
void
dns_clientinfo_init(dns_clientinfo_t *ci, void *data, void *versionp) {
dns_clientinfo_init(dns_clientinfo_t *ci, void *data, dns_ecs_t *ecs,
void *versionp) {
ci->version = DNS_CLIENTINFO_VERSION;
ci->data = data;
ci->dbversion = versionp;
if (ecs != NULL) {
ci->ecs = *ecs;
} else {
dns_ecs_init(&ci->ecs);
}
}

View file

@ -15,36 +15,99 @@
#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();
}
/*
* XXXMUKS: Fix me when resolver ECS gets merged where scope
* gets initialized to 0xff.
* Compare all octets except the final octet of the address
* prefix.
*/
ecs->scope = 0;
if (alen > 1 && memcmp(addr1, addr2, alen - 1) != 0) {
return (false);
}
/*
* 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.
*/
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);
}

View file

@ -42,17 +42,20 @@
#include <isc/sockaddr.h>
#include <isc/types.h>
#include <dns/ecs.h>
ISC_LANG_BEGINDECLS
/*****
***** Types
*****/
#define DNS_CLIENTINFO_VERSION 2
#define DNS_CLIENTINFO_VERSION 3
typedef struct dns_clientinfo {
uint16_t version;
void *data;
void *dbversion;
uint16_t version;
void *data;
void *dbversion;
dns_ecs_t ecs;
} dns_clientinfo_t;
typedef isc_result_t (*dns_clientinfo_sourceip_t)(dns_clientinfo_t *client,
@ -75,6 +78,7 @@ dns_clientinfomethods_init(dns_clientinfomethods_t *methods,
dns_clientinfo_sourceip_t sourceip);
void
dns_clientinfo_init(dns_clientinfo_t *ci, void *data, void *versionp);
dns_clientinfo_init(dns_clientinfo_t *ci, void *data, dns_ecs_t *ecs,
void *versionp);
ISC_LANG_ENDDECLS

View file

@ -19,17 +19,28 @@
#include <isc/netaddr.h>
#include <isc/types.h>
#include <dns/rdatatype.h>
#include <dns/types.h>
/*%
* Maximum scope values for IPv4 and IPv6.
*/
#ifndef ECS_MAX_V4_SCOPE
#define ECS_MAX_V4_SCOPE 24
#endif
#ifndef ECS_MAX_V6_SCOPE
#define ECS_MAX_V6_SCOPE 56
#endif
struct dns_ecs {
isc_netaddr_t addr;
uint8_t source;
uint8_t scope;
};
#define DNS_ECS_FORMATSIZE \
(ISC_NETADDR_FORMATSIZE + 8) /* <address>/NNN/NNN \
*/
/* <address>/NNN/NNN */
#define DNS_ECS_FORMATSIZE (ISC_NETADDR_FORMATSIZE + 9)
ISC_LANG_BEGINDECLS
@ -42,8 +53,19 @@ dns_ecs_init(dns_ecs_t *ecs);
* \li 'ecs' is not NULL and points to a valid dns_ecs structure.
*/
bool
dns_ecs_equals(const dns_ecs_t *ecs1, const dns_ecs_t *ecs2);
/*%<
* Determine whether two ECS address prefixes are equal (except the
* scope prefix-length field).
*
* 'ecs1->source' must exactly match 'ecs2->source'; the address families
* must match; and the first 'ecs1->source' bits of the addresses must
* match. Subsequent address bits and the 'scope' values are ignored.
*/
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);
/*%<
* Format an ECS record as text. Result is guaranteed to be null-terminated.
*
@ -52,5 +74,4 @@ dns_ecs_format(dns_ecs_t *ecs, char *buf, size_t size);
* \li 'buf' is not NULL.
* \li 'size' is at least DNS_ECS_FORMATSIZE
*/
ISC_LANG_ENDDECLS

View file

@ -1389,7 +1389,7 @@ query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
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,
@ -1530,7 +1530,7 @@ query_additionalauthfind(dns_db_t *db, dns_dbversion_t *version,
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
@ -1693,7 +1693,7 @@ query_additional_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
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
@ -2285,7 +2285,7 @@ mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,
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.
@ -2322,7 +2322,7 @@ get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
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,
@ -2876,7 +2876,7 @@ rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
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);
@ -3025,7 +3025,7 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
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
@ -4628,7 +4628,7 @@ query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
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.
@ -4828,7 +4828,7 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
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))
{
@ -4966,7 +4966,7 @@ redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
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))
{
@ -5787,7 +5787,9 @@ query_lookup(query_ctx_t *qctx) {
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...
@ -8596,7 +8598,7 @@ query_notfound(query_ctx_t *qctx) {
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,
@ -10065,7 +10067,7 @@ query_coveringnsec(query_ctx_t *qctx) {
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.
@ -10788,7 +10790,7 @@ query_addsoa(query_ctx_t *qctx, unsigned int override_ttl,
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".
@ -10937,7 +10939,7 @@ query_addns(query_ctx_t *qctx) {
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.
@ -11039,7 +11041,7 @@ query_addbestns(query_ctx_t *qctx) {
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.
@ -11244,7 +11246,7 @@ query_addwildcardproof(query_ctx_t *qctx, bool ispositive, bool nodata) {
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

View file

@ -594,7 +594,7 @@ foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
* different from the current version
*/
dns_db_currentversion(db, &oldver);
dns_clientinfo_init(&ci, NULL, (ver != oldver) ? ver : NULL);
dns_clientinfo_init(&ci, NULL, NULL, (ver != oldver) ? ver : NULL);
dns_db_closeversion(db, &oldver, false);
node = NULL;
@ -685,7 +685,7 @@ foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
* different from the current version
*/
dns_db_currentversion(db, &oldver);
dns_clientinfo_init(&ci, NULL, (ver != oldver) ? ver : NULL);
dns_clientinfo_init(&ci, NULL, NULL, (ver != oldver) ? ver : NULL);
dns_db_closeversion(db, &oldver, false);
if (type == dns_rdatatype_any) {