mirror of
https://github.com/isc-projects/bind9.git
synced 2026-03-09 01:30:39 -04:00
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:
parent
3b53680458
commit
737e658602
6 changed files with 136 additions and 39 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue