mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 05:57:52 +00:00
Merge branch 'master' of ssh://repo.isc.org/proj/git/prod/bind9
This commit is contained in:
commit
2272d9a445
33
CHANGES
33
CHANGES
@ -1,3 +1,36 @@
|
||||
3937. [func] Added some debug logging to better indicate the
|
||||
conditions causing SERVFAILs when resolving.
|
||||
[RT #35538]
|
||||
|
||||
3936. [func] Added authoritative support for the EDNS Client
|
||||
Subnet (ECS) option.
|
||||
|
||||
ACLs can now include "ecs" elements which specify
|
||||
an address or network prefix; if an ECS option is
|
||||
included in a DNS query, then the address encoded
|
||||
in the option will be matched against "ecs" ACL
|
||||
elements.
|
||||
|
||||
Also, if an ECS address is included in a query,
|
||||
then it will be used instead of the client source
|
||||
address when matching "geoip" ACL elements. This
|
||||
behavior can be overridden with "geoip-use-ecs no;".
|
||||
|
||||
When "ecs" or "geoip" ACL elements are used to
|
||||
select a view for a query, the response will include
|
||||
an ECS option to indicate which client network the
|
||||
answer is valid for.
|
||||
|
||||
(Thanks to Vincent Bernat.) [RT #36781]
|
||||
|
||||
3935. [bug] "geoip asnum" ACL elements would not match unless
|
||||
the full organization name was specified. They
|
||||
can now match against the AS number alone (e.g.,
|
||||
AS1234). [RT #36945]
|
||||
|
||||
3934. [bug] Catch bad 'sit-secret' in named-checkconf. Improve
|
||||
sit-secret documentation. [RT #36980]
|
||||
|
||||
3933. [bug] Corrected the implementation of dns_rdata_casecompare()
|
||||
for the HIP rdata type. [RT #36911]
|
||||
|
||||
|
6
README
6
README
@ -56,6 +56,12 @@ BIND 9.11.0
|
||||
BIND 9.11.0 includes a number of changes from BIND 9.10 and earlier
|
||||
releases. New features include:
|
||||
|
||||
- The EDNS Client Subnet (ECS) option is now supported for
|
||||
authoritative servers; if a query contains an ECS option
|
||||
then ACLs containing "geoip" or "ecs" elements can match
|
||||
against the the address encoded in the option. This can be
|
||||
used to select a view for a query, so that different answers
|
||||
can be provided depending on the client network.
|
||||
- The EDNS EXPIRE option has been implemented on the client
|
||||
side, allowing a slave server to set the expiration timer
|
||||
correctly when transferring zone data from another slave
|
||||
|
@ -122,6 +122,7 @@
|
||||
#endif
|
||||
|
||||
#define SIT_SIZE 24U /* 8 + 4 + 4 + 8 */
|
||||
#define ECS_SIZE 20U /* 2 + 1 + 1 + [0..16] */
|
||||
|
||||
/*% nameserver client manager structure */
|
||||
struct ns_clientmgr {
|
||||
@ -244,7 +245,8 @@ static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
|
||||
static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,
|
||||
dns_dispatch_t *disp, isc_boolean_t tcp);
|
||||
static inline isc_boolean_t
|
||||
allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl);
|
||||
allowed(isc_netaddr_t *addr, dns_name_t *signer, isc_netaddr_t *ecs_addr,
|
||||
isc_uint8_t ecs_addrlen, isc_uint8_t *ecs_scope, dns_acl_t *acl);
|
||||
#ifdef ISC_PLATFORM_USESIT
|
||||
static void compute_sit(ns_client_t *client, isc_uint32_t when,
|
||||
isc_uint32_t nonce, isc_buffer_t *buf);
|
||||
@ -1042,7 +1044,8 @@ client_send(ns_client_t *client) {
|
||||
if (client->message->tsigkey != NULL)
|
||||
name = &client->message->tsigkey->name;
|
||||
if (client->view->nocasecompress == NULL ||
|
||||
!allowed(&netaddr, name, client->view->nocasecompress))
|
||||
!allowed(&netaddr, name, NULL, 0, NULL,
|
||||
client->view->nocasecompress))
|
||||
{
|
||||
dns_compress_setsensitive(&cctx, ISC_TRUE);
|
||||
}
|
||||
@ -1381,6 +1384,7 @@ isc_result_t
|
||||
ns_client_addopt(ns_client_t *client, dns_message_t *message,
|
||||
dns_rdataset_t **opt)
|
||||
{
|
||||
unsigned char ecs[ECS_SIZE];
|
||||
char nsid[BUFSIZ], *nsidp;
|
||||
#ifdef ISC_PLATFORM_USESIT
|
||||
unsigned char sit[SIT_SIZE];
|
||||
@ -1459,6 +1463,38 @@ ns_client_addopt(ns_client_t *client, dns_message_t *message,
|
||||
ednsopts[count].value = expire;
|
||||
count++;
|
||||
}
|
||||
if (((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) &&
|
||||
(client->ecs_addr.family == AF_INET ||
|
||||
client->ecs_addr.family == AF_INET6))
|
||||
{
|
||||
int i, addrbytes = (client->ecs_addrlen + 7) / 8;
|
||||
isc_uint8_t *paddr;
|
||||
isc_buffer_t buf;
|
||||
|
||||
/* Add client subnet option. */
|
||||
isc_buffer_init(&buf, ecs, sizeof(ecs));
|
||||
if (client->ecs_addr.family == AF_INET)
|
||||
isc_buffer_putuint16(&buf, 1);
|
||||
else
|
||||
isc_buffer_putuint16(&buf, 2);
|
||||
isc_buffer_putuint8(&buf, client->ecs_addrlen);
|
||||
isc_buffer_putuint8(&buf, client->ecs_scope);
|
||||
|
||||
paddr = (isc_uint8_t *) &client->ecs_addr.type;
|
||||
for (i = 0; i < addrbytes; i++) {
|
||||
unsigned char uc;
|
||||
uc = paddr[i];
|
||||
if (i == addrbytes - 1 &&
|
||||
((client->ecs_addrlen % 8) != 0))
|
||||
uc &= (1U << (8 - (client->ecs_addrlen % 8)));
|
||||
isc_buffer_putuint8(&buf, uc);
|
||||
}
|
||||
|
||||
ednsopts[count].code = DNS_OPT_CLIENT_SUBNET;
|
||||
ednsopts[count].length = addrbytes + 4;
|
||||
ednsopts[count].value = ecs;
|
||||
count++;
|
||||
}
|
||||
|
||||
result = dns_message_buildopt(message, opt, 0, udpsize, flags,
|
||||
ednsopts, count);
|
||||
@ -1466,14 +1502,17 @@ ns_client_addopt(ns_client_t *client, dns_message_t *message,
|
||||
}
|
||||
|
||||
static inline isc_boolean_t
|
||||
allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl) {
|
||||
allowed(isc_netaddr_t *addr, dns_name_t *signer,
|
||||
isc_netaddr_t *ecs_addr, isc_uint8_t ecs_addrlen,
|
||||
isc_uint8_t *ecs_scope, dns_acl_t *acl)
|
||||
{
|
||||
int match;
|
||||
isc_result_t result;
|
||||
|
||||
if (acl == NULL)
|
||||
return (ISC_TRUE);
|
||||
result = dns_acl_match(addr, signer, acl, &ns_g_server->aclenv,
|
||||
&match, NULL);
|
||||
result = dns_acl_match2(addr, signer, ecs_addr, ecs_addrlen, ecs_scope,
|
||||
acl, &ns_g_server->aclenv, &match, NULL);
|
||||
if (result == ISC_R_SUCCESS && match > 0)
|
||||
return (ISC_TRUE);
|
||||
return (ISC_FALSE);
|
||||
@ -1536,8 +1575,10 @@ ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
|
||||
tsig = dns_tsigkey_identity(mykey);
|
||||
}
|
||||
|
||||
if (allowed(&netsrc, tsig, view->matchclients) &&
|
||||
allowed(&netdst, tsig, view->matchdestinations))
|
||||
if (allowed(&netsrc, tsig, NULL, 0, NULL,
|
||||
view->matchclients) &&
|
||||
allowed(&netdst, tsig, NULL, 0, NULL,
|
||||
view->matchdestinations))
|
||||
break;
|
||||
}
|
||||
return (ISC_TF(view == myview));
|
||||
@ -1718,6 +1759,81 @@ process_sit(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static isc_result_t
|
||||
process_ecs(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
|
||||
isc_uint16_t family;
|
||||
isc_uint8_t addrlen, addrbytes, scope, *paddr;
|
||||
isc_netaddr_t caddr;
|
||||
int i;
|
||||
|
||||
if (optlen < 4) {
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
|
||||
"EDNS client subnet option too short");
|
||||
return (DNS_R_FORMERR);
|
||||
}
|
||||
|
||||
family = isc_buffer_getuint16(buf);
|
||||
addrlen = isc_buffer_getuint8(buf);
|
||||
scope = isc_buffer_getuint8(buf);
|
||||
optlen -= 4;
|
||||
|
||||
if (scope != 0U) {
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
|
||||
"EDNS client subnet option: invalid scope");
|
||||
return (DNS_R_FORMERR);
|
||||
}
|
||||
|
||||
memset(&caddr, 0, sizeof(caddr));
|
||||
switch (family) {
|
||||
case 1:
|
||||
if (addrlen > 32U)
|
||||
goto invalid_length;
|
||||
caddr.family = AF_INET;
|
||||
break;
|
||||
case 2:
|
||||
if (addrlen > 128U) {
|
||||
invalid_length:
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
|
||||
"EDNS client subnet option: invalid "
|
||||
"address length (%u) for %s",
|
||||
addrlen, family == 1 ? "IPv4" : "IPv6");
|
||||
return (DNS_R_FORMERR);
|
||||
}
|
||||
caddr.family = AF_INET6;
|
||||
break;
|
||||
default:
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
|
||||
"EDNS client subnet option: invalid family");
|
||||
return (DNS_R_FORMERR);
|
||||
}
|
||||
|
||||
addrbytes = (addrlen + 7) / 8;
|
||||
if (isc_buffer_remaininglength(buf) < addrbytes) {
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
|
||||
"EDNS client subnet option: address too short");
|
||||
return (DNS_R_FORMERR);
|
||||
}
|
||||
|
||||
paddr = (isc_uint8_t *) &caddr.type;
|
||||
for (i = 0; i < addrbytes; i++) {
|
||||
paddr[i] = isc_buffer_getuint8(buf);
|
||||
optlen--;
|
||||
}
|
||||
|
||||
memmove(&client->ecs_addr, &caddr, sizeof(caddr));
|
||||
client->ecs_addrlen = addrlen;
|
||||
client->ecs_scope = 0;
|
||||
client->attributes |= NS_CLIENTATTR_HAVEECS;
|
||||
|
||||
isc_buffer_forward(buf, optlen);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
process_opt(ns_client_t *client, dns_rdataset_t *opt) {
|
||||
dns_rdata_t rdata;
|
||||
@ -1788,6 +1904,15 @@ process_opt(ns_client_t *client, dns_rdataset_t *opt) {
|
||||
client->attributes |= NS_CLIENTATTR_WANTEXPIRE;
|
||||
isc_buffer_forward(&optbuf, optlen);
|
||||
break;
|
||||
case DNS_OPT_CLIENT_SUBNET:
|
||||
result = process_ecs(client, &optbuf, optlen);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_client_error(client, result);
|
||||
goto cleanup;
|
||||
}
|
||||
isc_stats_increment(ns_g_server->nsstats,
|
||||
dns_nsstatscounter_ecsopt);
|
||||
break;
|
||||
default:
|
||||
isc_stats_increment(ns_g_server->nsstats,
|
||||
dns_nsstatscounter_otheropt);
|
||||
@ -1925,7 +2050,6 @@ client_request(isc_task_t *task, isc_event_t *event) {
|
||||
* client_newconn.
|
||||
*/
|
||||
if (!TCP_CLIENT(client)) {
|
||||
|
||||
if (ns_g_server->blackholeacl != NULL &&
|
||||
dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
|
||||
&ns_g_server->aclenv,
|
||||
@ -2033,6 +2157,10 @@ client_request(isc_task_t *task, isc_event_t *event) {
|
||||
opt = NULL;
|
||||
else
|
||||
opt = dns_message_getopt(client->message);
|
||||
|
||||
client->ecs_addrlen = 0;
|
||||
client->ecs_scope = 0;
|
||||
|
||||
if (opt != NULL) {
|
||||
/*
|
||||
* Are we dropping all EDNS queries?
|
||||
@ -2117,17 +2245,29 @@ client_request(isc_task_t *task, isc_event_t *event) {
|
||||
client->message->rdclass == dns_rdataclass_any)
|
||||
{
|
||||
dns_name_t *tsig = NULL;
|
||||
isc_netaddr_t *addr = NULL;
|
||||
isc_uint8_t *scope = NULL;
|
||||
|
||||
sigresult = dns_message_rechecksig(client->message,
|
||||
view);
|
||||
if (sigresult == ISC_R_SUCCESS)
|
||||
tsig = dns_tsigkey_identity(client->message->tsigkey);
|
||||
if (sigresult == ISC_R_SUCCESS) {
|
||||
dns_tsigkey_t *tsigkey;
|
||||
|
||||
if (allowed(&netaddr, tsig, view->matchclients) &&
|
||||
allowed(&client->destaddr, tsig,
|
||||
view->matchdestinations) &&
|
||||
!((client->message->flags & DNS_MESSAGEFLAG_RD)
|
||||
== 0 && view->matchrecursiveonly))
|
||||
tsigkey = client->message->tsigkey;
|
||||
tsig = dns_tsigkey_identity(tsigkey);
|
||||
}
|
||||
|
||||
if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) {
|
||||
addr = &client->ecs_addr;
|
||||
scope = &client->ecs_scope;
|
||||
}
|
||||
|
||||
if (allowed(&netaddr, tsig, addr, client->ecs_addrlen,
|
||||
scope, view->matchclients) &&
|
||||
allowed(&client->destaddr, tsig, NULL,
|
||||
0, NULL, view->matchdestinations) &&
|
||||
!(view->matchrecursiveonly &&
|
||||
(client->message->flags & DNS_MESSAGEFLAG_RD) == 0))
|
||||
{
|
||||
dns_view_attach(view, &client->view);
|
||||
break;
|
||||
@ -2519,6 +2659,8 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
|
||||
client->recursionquota = NULL;
|
||||
client->interface = NULL;
|
||||
client->peeraddr_valid = ISC_FALSE;
|
||||
client->ecs_addrlen = 0;
|
||||
client->ecs_scope = 0;
|
||||
#ifdef ALLOW_FILTER_AAAA
|
||||
client->filter_aaaa = dns_aaaa_ok;
|
||||
#endif
|
||||
@ -3055,6 +3197,8 @@ ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
|
||||
{
|
||||
isc_result_t result;
|
||||
isc_netaddr_t tmpnetaddr;
|
||||
isc_netaddr_t *ecs_addr = NULL;
|
||||
isc_uint8_t ecs_addrlen = 0;
|
||||
int match;
|
||||
|
||||
if (acl == NULL) {
|
||||
@ -3069,11 +3213,18 @@ ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
|
||||
netaddr = &tmpnetaddr;
|
||||
}
|
||||
|
||||
result = dns_acl_match(netaddr, client->signer, acl,
|
||||
&ns_g_server->aclenv, &match, NULL);
|
||||
if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) {
|
||||
ecs_addr = &client->ecs_addr;
|
||||
ecs_addrlen = client->ecs_addrlen;
|
||||
}
|
||||
|
||||
result = dns_acl_match2(netaddr, client->signer,
|
||||
ecs_addr, ecs_addrlen, NULL, acl,
|
||||
&ns_g_server->aclenv, &match, NULL);
|
||||
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto deny; /* Internal error, already logged. */
|
||||
|
||||
if (match > 0)
|
||||
goto allow;
|
||||
goto deny; /* Negative match or no match. */
|
||||
|
@ -177,6 +177,11 @@ options {\n\
|
||||
nsec3-test-zone no;\n\
|
||||
allow-new-zones no;\n\
|
||||
"
|
||||
#ifdef HAVE_GEOIP
|
||||
"\
|
||||
geoip-use-ecs yes;\n\
|
||||
"
|
||||
#endif
|
||||
#ifdef ALLOW_FILTER_AAAA
|
||||
" filter-aaaa-on-v4 no;\n\
|
||||
filter-aaaa-on-v6 no;\n\
|
||||
|
@ -137,9 +137,15 @@ struct ns_client {
|
||||
isc_quota_t *tcpquota;
|
||||
isc_quota_t *recursionquota;
|
||||
ns_interface_t *interface;
|
||||
|
||||
isc_sockaddr_t peeraddr;
|
||||
isc_boolean_t peeraddr_valid;
|
||||
isc_netaddr_t destaddr;
|
||||
|
||||
isc_netaddr_t ecs_addr; /*%< EDNS client subnet */
|
||||
isc_uint8_t ecs_addrlen;
|
||||
isc_uint8_t ecs_scope;
|
||||
|
||||
struct in6_pktinfo pktinfo;
|
||||
isc_dscp_t dscp;
|
||||
isc_event_t ctlevent;
|
||||
@ -187,6 +193,7 @@ typedef ISC_LIST(ns_client_t) client_list_t;
|
||||
#define NS_CLIENTATTR_WANTEXPIRE 0x0800 /*%< return seconds to expire */
|
||||
#define NS_CLIENTATTR_HAVEEXPIRE 0x1000 /*%< return seconds to expire */
|
||||
#define NS_CLIENTATTR_WANTOPT 0x2000 /*%< add opt to reply */
|
||||
#define NS_CLIENTATTR_HAVEECS 0x4000 /*%< sent an ECS option */
|
||||
|
||||
extern unsigned int ns_client_requests;
|
||||
|
||||
|
@ -182,18 +182,19 @@ enum {
|
||||
dns_nsstatscounter_nsidopt = 43,
|
||||
dns_nsstatscounter_expireopt = 44,
|
||||
dns_nsstatscounter_otheropt = 45,
|
||||
dns_nsstatscounter_ecsopt = 46,
|
||||
|
||||
#ifdef ISC_PLATFORM_USESIT
|
||||
dns_nsstatscounter_sitopt = 46,
|
||||
dns_nsstatscounter_sitbadsize = 47,
|
||||
dns_nsstatscounter_sitbadtime = 48,
|
||||
dns_nsstatscounter_sitnomatch = 49,
|
||||
dns_nsstatscounter_sitmatch = 50,
|
||||
dns_nsstatscounter_sitnew = 51,
|
||||
dns_nsstatscounter_sitopt = 47,
|
||||
dns_nsstatscounter_sitbadsize = 48,
|
||||
dns_nsstatscounter_sitbadtime = 49,
|
||||
dns_nsstatscounter_sitnomatch = 50,
|
||||
dns_nsstatscounter_sitmatch = 51,
|
||||
dns_nsstatscounter_sitnew = 52,
|
||||
|
||||
dns_nsstatscounter_max = 52
|
||||
dns_nsstatscounter_max = 53
|
||||
#else
|
||||
dns_nsstatscounter_max = 46
|
||||
dns_nsstatscounter_max = 47
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include <isc/hex.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/serial.h>
|
||||
#include <isc/stats.h>
|
||||
#include <isc/util.h>
|
||||
@ -125,21 +126,25 @@
|
||||
DNS_RDATASETATTR_NOQNAME) != 0)
|
||||
|
||||
#if 0
|
||||
#define CTRACE(m) isc_log_write(ns_g_lctx, \
|
||||
NS_LOGCATEGORY_CLIENT, \
|
||||
NS_LOGMODULE_QUERY, \
|
||||
ISC_LOG_DEBUG(3), \
|
||||
"client %p: %s", client, (m))
|
||||
#define QTRACE(m) isc_log_write(ns_g_lctx, \
|
||||
NS_LOGCATEGORY_GENERAL, \
|
||||
NS_LOGMODULE_QUERY, \
|
||||
ISC_LOG_DEBUG(3), \
|
||||
"query %p: %s", query, (m))
|
||||
#define CTRACE(l,m) do { \
|
||||
if (client != NULL && client->query.qname != NULL) { \
|
||||
char qbuf[DNS_NAME_FORMATSIZE]; \
|
||||
dns_name_format(client->query.qname, qbuf, sizeof(qbuf)); \
|
||||
isc_log_write(ns_g_lctx, \
|
||||
NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, \
|
||||
l, "client %p (%s): %s", client, qbuf, (m)); \
|
||||
} else { \
|
||||
isc_log_write(ns_g_lctx, \
|
||||
NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, \
|
||||
l, "client %p (<unknown-name>): %s", \
|
||||
client, (m)); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define CTRACE(m) ((void)m)
|
||||
#define QTRACE(m) ((void)m)
|
||||
#define CTRACE(l,m) ((void)m)
|
||||
#endif
|
||||
|
||||
|
||||
#define DNS_GETDB_NOEXACT 0x01U
|
||||
#define DNS_GETDB_NOLOG 0x02U
|
||||
#define DNS_GETDB_PARTIAL 0x04U
|
||||
@ -312,13 +317,13 @@ static inline void
|
||||
query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
|
||||
dns_rdataset_t *rdataset = *rdatasetp;
|
||||
|
||||
CTRACE("query_putrdataset");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_putrdataset");
|
||||
if (rdataset != NULL) {
|
||||
if (dns_rdataset_isassociated(rdataset))
|
||||
dns_rdataset_disassociate(rdataset);
|
||||
dns_message_puttemprdataset(client->message, rdatasetp);
|
||||
}
|
||||
CTRACE("query_putrdataset: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_putrdataset: done");
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -425,7 +430,7 @@ query_newnamebuf(ns_client_t *client) {
|
||||
isc_buffer_t *dbuf;
|
||||
isc_result_t result;
|
||||
|
||||
CTRACE("query_newnamebuf");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_newnamebuf");
|
||||
/*%
|
||||
* Allocate a name buffer.
|
||||
*/
|
||||
@ -433,12 +438,13 @@ query_newnamebuf(ns_client_t *client) {
|
||||
dbuf = NULL;
|
||||
result = isc_buffer_allocate(client->mctx, &dbuf, 1024);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
CTRACE("query_newnamebuf: isc_buffer_allocate failed: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_newnamebuf: isc_buffer_allocate failed: done");
|
||||
return (result);
|
||||
}
|
||||
ISC_LIST_APPEND(client->query.namebufs, dbuf, link);
|
||||
|
||||
CTRACE("query_newnamebuf: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_newnamebuf: done");
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
@ -448,7 +454,7 @@ query_getnamebuf(ns_client_t *client) {
|
||||
isc_result_t result;
|
||||
isc_region_t r;
|
||||
|
||||
CTRACE("query_getnamebuf");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_getnamebuf");
|
||||
/*%
|
||||
* Return a name buffer with space for a maximal name, allocating
|
||||
* a new one if necessary.
|
||||
@ -457,7 +463,8 @@ query_getnamebuf(ns_client_t *client) {
|
||||
if (ISC_LIST_EMPTY(client->query.namebufs)) {
|
||||
result = query_newnamebuf(client);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
CTRACE("query_getnamebuf: query_newnamebuf failed: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_getnamebuf: query_newnamebuf failed: done");
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
@ -468,7 +475,8 @@ query_getnamebuf(ns_client_t *client) {
|
||||
if (r.length < 255) {
|
||||
result = query_newnamebuf(client);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
CTRACE("query_getnamebuf: query_newnamebuf failed: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_getnamebuf: query_newnamebuf failed: done");
|
||||
return (NULL);
|
||||
|
||||
}
|
||||
@ -476,7 +484,7 @@ query_getnamebuf(ns_client_t *client) {
|
||||
isc_buffer_availableregion(dbuf, &r);
|
||||
INSIST(r.length >= 255);
|
||||
}
|
||||
CTRACE("query_getnamebuf: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_getnamebuf: done");
|
||||
return (dbuf);
|
||||
}
|
||||
|
||||
@ -484,7 +492,7 @@ static inline void
|
||||
query_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) {
|
||||
isc_region_t r;
|
||||
|
||||
CTRACE("query_keepname");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_keepname");
|
||||
/*%
|
||||
* 'name' is using space in 'dbuf', but 'dbuf' has not yet been
|
||||
* adjusted to take account of that. We do the adjustment.
|
||||
@ -508,14 +516,14 @@ query_releasename(ns_client_t *client, dns_name_t **namep) {
|
||||
* rights on the buffer.
|
||||
*/
|
||||
|
||||
CTRACE("query_releasename");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_releasename");
|
||||
if (dns_name_hasbuffer(name)) {
|
||||
INSIST((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED)
|
||||
!= 0);
|
||||
client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
|
||||
}
|
||||
dns_message_puttempname(client->message, namep);
|
||||
CTRACE("query_releasename: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_releasename: done");
|
||||
}
|
||||
|
||||
static inline dns_name_t *
|
||||
@ -528,11 +536,12 @@ query_newname(ns_client_t *client, isc_buffer_t *dbuf,
|
||||
|
||||
REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0);
|
||||
|
||||
CTRACE("query_newname");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_newname");
|
||||
name = NULL;
|
||||
result = dns_message_gettempname(client->message, &name);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
CTRACE("query_newname: dns_message_gettempname failed: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_newname: dns_message_gettempname failed: done");
|
||||
return (NULL);
|
||||
}
|
||||
isc_buffer_availableregion(dbuf, &r);
|
||||
@ -541,7 +550,7 @@ query_newname(ns_client_t *client, isc_buffer_t *dbuf,
|
||||
dns_name_setbuffer(name, nbuf);
|
||||
client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED;
|
||||
|
||||
CTRACE("query_newname: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_newname: done");
|
||||
return (name);
|
||||
}
|
||||
|
||||
@ -550,17 +559,18 @@ query_newrdataset(ns_client_t *client) {
|
||||
dns_rdataset_t *rdataset;
|
||||
isc_result_t result;
|
||||
|
||||
CTRACE("query_newrdataset");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_newrdataset");
|
||||
rdataset = NULL;
|
||||
result = dns_message_gettemprdataset(client->message, &rdataset);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
CTRACE("query_newrdataset: "
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_newrdataset: "
|
||||
"dns_message_gettemprdataset failed: done");
|
||||
return (NULL);
|
||||
}
|
||||
dns_rdataset_init(rdataset);
|
||||
|
||||
CTRACE("query_newrdataset: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_newrdataset: done");
|
||||
return (rdataset);
|
||||
}
|
||||
|
||||
@ -727,8 +737,10 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name,
|
||||
* Get the current version of this database.
|
||||
*/
|
||||
dbversion = query_findversion(client, db);
|
||||
if (dbversion == NULL)
|
||||
if (dbversion == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR, "unable to get db version");
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
|
||||
if ((options & DNS_GETDB_IGNOREACL) != 0)
|
||||
goto approved;
|
||||
@ -1191,7 +1203,7 @@ query_isduplicate(ns_client_t *client, dns_name_t *name,
|
||||
dns_name_t *mname = NULL;
|
||||
isc_result_t result;
|
||||
|
||||
CTRACE("query_isduplicate");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate");
|
||||
|
||||
for (section = DNS_SECTION_ANSWER;
|
||||
section <= DNS_SECTION_ADDITIONAL;
|
||||
@ -1202,7 +1214,8 @@ query_isduplicate(ns_client_t *client, dns_name_t *name,
|
||||
/*
|
||||
* We've already got this RRset in the response.
|
||||
*/
|
||||
CTRACE("query_isduplicate: true: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_isduplicate: true: done");
|
||||
return (ISC_TRUE);
|
||||
} else if (result == DNS_R_NXRRSET) {
|
||||
/*
|
||||
@ -1218,7 +1231,7 @@ query_isduplicate(ns_client_t *client, dns_name_t *name,
|
||||
if (mnamep != NULL)
|
||||
*mnamep = mname;
|
||||
|
||||
CTRACE("query_isduplicate: false: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: false: done");
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
@ -1245,7 +1258,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype))
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
CTRACE("query_addadditional");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional");
|
||||
|
||||
/*
|
||||
* Initialization.
|
||||
@ -1301,7 +1314,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto try_cache;
|
||||
|
||||
CTRACE("query_addadditional: db_find");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: db_find");
|
||||
|
||||
/*
|
||||
* Since we are looking for authoritative data, we do not set
|
||||
@ -1573,7 +1586,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
}
|
||||
|
||||
addname:
|
||||
CTRACE("query_addadditional: addname");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: addname");
|
||||
/*
|
||||
* If we haven't added anything, then we're done.
|
||||
*/
|
||||
@ -1613,7 +1626,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
}
|
||||
|
||||
cleanup:
|
||||
CTRACE("query_addadditional: cleanup");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: cleanup");
|
||||
query_putrdataset(client, &rdataset);
|
||||
if (sigrdataset != NULL)
|
||||
query_putrdataset(client, &sigrdataset);
|
||||
@ -1626,7 +1639,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
if (zone != NULL)
|
||||
dns_zone_detach(&zone);
|
||||
|
||||
CTRACE("query_addadditional: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: done");
|
||||
return (eresult);
|
||||
}
|
||||
|
||||
@ -1744,7 +1757,7 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
dns_clientinfomethods_init(&cm, ns_client_sourceip);
|
||||
dns_clientinfo_init(&ci, client, NULL);
|
||||
|
||||
CTRACE("query_addadditional2");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2");
|
||||
|
||||
/*
|
||||
* We treat type A additional section processing as if it
|
||||
@ -1776,14 +1789,16 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto findauthdb;
|
||||
if (zone == NULL) {
|
||||
CTRACE("query_addadditional2: auth zone not found");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_addadditional2: auth zone not found");
|
||||
goto try_cache;
|
||||
}
|
||||
|
||||
/* Is the cached DB up-to-date? */
|
||||
result = query_iscachevalid(zone, cdb, NULL, cversion);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
CTRACE("query_addadditional2: old auth additional cache");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_addadditional2: old auth additional cache");
|
||||
query_discardcache(client, rdataset_base, additionaltype,
|
||||
type, &zone, &cdb, &cversion, &cnode,
|
||||
&cfname);
|
||||
@ -1796,7 +1811,8 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
* ACL, since the result (not using this zone) would be same
|
||||
* regardless of the result.
|
||||
*/
|
||||
CTRACE("query_addadditional2: negative auth additional cache");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_addadditional2: negative auth additional cache");
|
||||
dns_db_closeversion(cdb, &cversion, ISC_FALSE);
|
||||
dns_db_detach(&cdb);
|
||||
dns_zone_detach(&zone);
|
||||
@ -1813,7 +1829,8 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
}
|
||||
|
||||
/* We've got an active cache. */
|
||||
CTRACE("query_addadditional2: auth additional cache");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_addadditional2: auth additional cache");
|
||||
dns_db_closeversion(cdb, &cversion, ISC_FALSE);
|
||||
db = cdb;
|
||||
node = cnode;
|
||||
@ -1837,7 +1854,7 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
goto try_cache;
|
||||
}
|
||||
|
||||
CTRACE("query_addadditional2: db_find");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: db_find");
|
||||
|
||||
/*
|
||||
* Since we are looking for authoritative data, we do not set
|
||||
@ -1922,7 +1939,8 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
|
||||
result = query_iscachevalid(zone, cdb, client->query.gluedb, cversion);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
CTRACE("query_addadditional2: old glue additional cache");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_addadditional2: old glue additional cache");
|
||||
query_discardcache(client, rdataset_base, additionaltype,
|
||||
type, &zone, &cdb, &cversion, &cnode,
|
||||
&cfname);
|
||||
@ -1931,14 +1949,15 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
|
||||
if (cnode == NULL) {
|
||||
/* We have a negative cache. */
|
||||
CTRACE("query_addadditional2: negative glue additional cache");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_addadditional2: negative glue additional cache");
|
||||
dns_db_closeversion(cdb, &cversion, ISC_FALSE);
|
||||
dns_db_detach(&cdb);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Cache hit. */
|
||||
CTRACE("query_addadditional2: glue additional cache");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: glue additional cache");
|
||||
dns_db_closeversion(cdb, &cversion, ISC_FALSE);
|
||||
db = cdb;
|
||||
node = cnode;
|
||||
@ -2121,7 +2140,7 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
}
|
||||
}
|
||||
|
||||
CTRACE("query_addadditional2: addname");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: addname");
|
||||
|
||||
/*
|
||||
* If we haven't added anything, then we're done.
|
||||
@ -2140,7 +2159,7 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
fname = NULL;
|
||||
|
||||
cleanup:
|
||||
CTRACE("query_addadditional2: cleanup");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: cleanup");
|
||||
|
||||
if (rdataset != NULL)
|
||||
query_putrdataset(client, &rdataset);
|
||||
@ -2159,7 +2178,7 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
|
||||
if (zone != NULL)
|
||||
dns_zone_detach(&zone);
|
||||
|
||||
CTRACE("query_addadditional2: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: done");
|
||||
return (eresult);
|
||||
}
|
||||
|
||||
@ -2174,7 +2193,7 @@ query_addrdataset(ns_client_t *client, dns_name_t *fname,
|
||||
* 'fname', a name in the response message for 'client'.
|
||||
*/
|
||||
|
||||
CTRACE("query_addrdataset");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addrdataset");
|
||||
|
||||
ISC_LIST_APPEND(fname->list, rdataset, link);
|
||||
|
||||
@ -2196,7 +2215,7 @@ query_addrdataset(ns_client_t *client, dns_name_t *fname,
|
||||
additionalctx.rdataset = rdataset;
|
||||
(void)dns_rdataset_additionaldata(rdataset, query_addadditional2,
|
||||
&additionalctx);
|
||||
CTRACE("query_addrdataset: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addrdataset: done");
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
@ -2228,7 +2247,7 @@ query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset,
|
||||
* stored in 'dbuf'. In this case, query_addrrset() guarantees that
|
||||
* when it returns the name will either have been kept or released.
|
||||
*/
|
||||
CTRACE("query_dns64");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_dns64");
|
||||
name = *namep;
|
||||
mname = NULL;
|
||||
mrdataset = NULL;
|
||||
@ -2245,7 +2264,8 @@ query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset,
|
||||
* We've already got an RRset of the given name and type.
|
||||
* There's nothing else to do;
|
||||
*/
|
||||
CTRACE("query_dns64: dns_message_findname succeeded: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_dns64: dns_message_findname succeeded: done");
|
||||
if (dbuf != NULL)
|
||||
query_releasename(client, namep);
|
||||
return (ISC_R_SUCCESS);
|
||||
@ -2376,7 +2396,7 @@ query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset,
|
||||
dns_message_puttemprdatalist(client->message, &dns64_rdatalist);
|
||||
}
|
||||
|
||||
CTRACE("query_dns64: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_dns64: done");
|
||||
return (result);
|
||||
}
|
||||
|
||||
@ -2395,7 +2415,7 @@ query_filter64(ns_client_t *client, dns_name_t **namep,
|
||||
isc_result_t result;
|
||||
unsigned int i;
|
||||
|
||||
CTRACE("query_filter64");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_filter64");
|
||||
|
||||
INSIST(client->query.dns64_aaaaok != NULL);
|
||||
INSIST(client->query.dns64_aaaaoklen == dns_rdataset_count(rdataset));
|
||||
@ -2415,7 +2435,8 @@ query_filter64(ns_client_t *client, dns_name_t **namep,
|
||||
* We've already got an RRset of the given name and type.
|
||||
* There's nothing else to do;
|
||||
*/
|
||||
CTRACE("query_filter64: dns_message_findname succeeded: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_filter64: dns_message_findname succeeded: done");
|
||||
if (dbuf != NULL)
|
||||
query_releasename(client, namep);
|
||||
return;
|
||||
@ -2514,7 +2535,7 @@ query_filter64(ns_client_t *client, dns_name_t **namep,
|
||||
if (dbuf != NULL)
|
||||
query_releasename(client, &name);
|
||||
|
||||
CTRACE("query_filter64: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_filter64: done");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2536,7 +2557,7 @@ query_addrrset(ns_client_t *client, dns_name_t **namep,
|
||||
* stored in 'dbuf'. In this case, query_addrrset() guarantees that
|
||||
* when it returns the name will either have been kept or released.
|
||||
*/
|
||||
CTRACE("query_addrrset");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addrrset");
|
||||
name = *namep;
|
||||
rdataset = *rdatasetp;
|
||||
if (sigrdatasetp != NULL)
|
||||
@ -2552,7 +2573,8 @@ query_addrrset(ns_client_t *client, dns_name_t **namep,
|
||||
/*
|
||||
* We've already got an RRset of the given name and type.
|
||||
*/
|
||||
CTRACE("query_addrrset: dns_message_findname succeeded: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_addrrset: dns_message_findname succeeded: done");
|
||||
if (dbuf != NULL)
|
||||
query_releasename(client, namep);
|
||||
if ((rdataset->attributes & DNS_RDATASETATTR_REQUIRED) != 0)
|
||||
@ -2591,7 +2613,7 @@ query_addrrset(ns_client_t *client, dns_name_t **namep,
|
||||
ISC_LIST_APPEND(mname->list, sigrdataset, link);
|
||||
*sigrdatasetp = NULL;
|
||||
}
|
||||
CTRACE("query_addrrset: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: done");
|
||||
}
|
||||
|
||||
static inline isc_result_t
|
||||
@ -2607,7 +2629,7 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
|
||||
dns_clientinfomethods_t cm;
|
||||
dns_clientinfo_t ci;
|
||||
|
||||
CTRACE("query_addsoa");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addsoa");
|
||||
/*
|
||||
* Initialization.
|
||||
*/
|
||||
@ -2635,12 +2657,14 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
|
||||
dns_name_clone(dns_db_origin(db), name);
|
||||
rdataset = query_newrdataset(client);
|
||||
if (rdataset == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR, "unable to allocate rdataset");
|
||||
eresult = DNS_R_SERVFAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
if (WANTDNSSEC(client) && dns_db_issecure(db)) {
|
||||
sigrdataset = query_newrdataset(client);
|
||||
if (sigrdataset == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR, "unable to allocate sigrdataset");
|
||||
eresult = DNS_R_SERVFAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -2670,6 +2694,7 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
|
||||
* This is bad. We tried to get the SOA RR at the zone top
|
||||
* and it didn't work!
|
||||
*/
|
||||
CTRACE(ISC_LOG_ERROR, "unable to find SOA RR at zone apex");
|
||||
eresult = DNS_R_SERVFAIL;
|
||||
} else {
|
||||
/*
|
||||
@ -2734,7 +2759,7 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
|
||||
dns_clientinfomethods_t cm;
|
||||
dns_clientinfo_t ci;
|
||||
|
||||
CTRACE("query_addns");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addns");
|
||||
/*
|
||||
* Initialization.
|
||||
*/
|
||||
@ -2752,21 +2777,24 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
|
||||
*/
|
||||
result = dns_message_gettempname(client->message, &name);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
CTRACE("query_addns: dns_message_gettempname failed: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3),
|
||||
"query_addns: dns_message_gettempname failed: done");
|
||||
return (result);
|
||||
}
|
||||
dns_name_init(name, NULL);
|
||||
dns_name_clone(dns_db_origin(db), name);
|
||||
rdataset = query_newrdataset(client);
|
||||
if (rdataset == NULL) {
|
||||
CTRACE("query_addns: query_newrdataset failed");
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_addns: query_newrdataset failed");
|
||||
eresult = DNS_R_SERVFAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
if (WANTDNSSEC(client) && dns_db_issecure(db)) {
|
||||
sigrdataset = query_newrdataset(client);
|
||||
if (sigrdataset == NULL) {
|
||||
CTRACE("query_addns: query_newrdataset failed");
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_addns: query_newrdataset failed");
|
||||
eresult = DNS_R_SERVFAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -2781,14 +2809,15 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
|
||||
dns_rdatatype_ns, 0, client->now,
|
||||
rdataset, sigrdataset);
|
||||
} else {
|
||||
CTRACE("query_addns: calling dns_db_find");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addns: calling dns_db_find");
|
||||
result = dns_db_findext(db, name, NULL, dns_rdatatype_ns,
|
||||
client->query.dboptions, 0, &node,
|
||||
fname, &cm, &ci, rdataset, sigrdataset);
|
||||
CTRACE("query_addns: dns_db_find complete");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addns: dns_db_find complete");
|
||||
}
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
CTRACE("query_addns: "
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_addns: "
|
||||
"dns_db_findrdataset or dns_db_find failed");
|
||||
/*
|
||||
* This is bad. We tried to get the NS rdataset at the zone
|
||||
@ -2805,7 +2834,7 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
|
||||
}
|
||||
|
||||
cleanup:
|
||||
CTRACE("query_addns: cleanup");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addns: cleanup");
|
||||
query_putrdataset(client, &rdataset);
|
||||
if (sigrdataset != NULL)
|
||||
query_putrdataset(client, &sigrdataset);
|
||||
@ -2814,7 +2843,7 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
|
||||
if (node != NULL)
|
||||
dns_db_detachnode(db, &node);
|
||||
|
||||
CTRACE("query_addns: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addns: done");
|
||||
return (eresult);
|
||||
}
|
||||
|
||||
@ -3082,7 +3111,7 @@ query_addbestns(ns_client_t *client) {
|
||||
dns_clientinfomethods_t cm;
|
||||
dns_clientinfo_t ci;
|
||||
|
||||
CTRACE("query_addbestns");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addbestns");
|
||||
fname = NULL;
|
||||
zfname = NULL;
|
||||
rdataset = NULL;
|
||||
@ -3287,7 +3316,7 @@ query_addds(ns_client_t *client, dns_db_t *db, dns_dbnode_t *node,
|
||||
isc_result_t result;
|
||||
unsigned int count;
|
||||
|
||||
CTRACE("query_addds");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addds");
|
||||
rname = NULL;
|
||||
rdataset = NULL;
|
||||
sigrdataset = NULL;
|
||||
@ -3417,7 +3446,7 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db,
|
||||
dns_clientinfomethods_t cm;
|
||||
dns_clientinfo_t ci;
|
||||
|
||||
CTRACE("query_addwildcardproof");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addwildcardproof");
|
||||
fname = NULL;
|
||||
rdataset = NULL;
|
||||
sigrdataset = NULL;
|
||||
@ -3781,9 +3810,10 @@ query_resume(isc_task_t *task, isc_event_t *event) {
|
||||
if (devent->sigrdataset != NULL)
|
||||
query_putrdataset(client, &devent->sigrdataset);
|
||||
isc_event_free(&event);
|
||||
if (fetch_canceled)
|
||||
if (fetch_canceled) {
|
||||
CTRACE(ISC_LOG_ERROR, "fetch cancelled");
|
||||
query_error(client, DNS_R_SERVFAIL, __LINE__);
|
||||
else
|
||||
} else
|
||||
query_next(client, ISC_R_CANCELED);
|
||||
/*
|
||||
* This may destroy the client.
|
||||
@ -4047,8 +4077,11 @@ rpz_ready(ns_client_t *client, dns_rdataset_t **rdatasetp)
|
||||
|
||||
if (*rdatasetp == NULL) {
|
||||
*rdatasetp = query_newrdataset(client);
|
||||
if (*rdatasetp == NULL)
|
||||
if (*rdatasetp == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"rpz_ready: query_newrdataset failed");
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
} else if (dns_rdataset_isassociated(*rdatasetp)) {
|
||||
dns_rdataset_disassociate(*rdatasetp);
|
||||
}
|
||||
@ -4187,6 +4220,7 @@ rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
|
||||
st->r.r_rdataset = NULL;
|
||||
result = st->r.r_result;
|
||||
if (result == DNS_R_DELEGATION) {
|
||||
CTRACE(ISC_LOG_ERROR, "RPZ recursing");
|
||||
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
|
||||
rpz_type, " rpz_rrset_find(1)", result);
|
||||
st->m.policy = DNS_RPZ_POLICY_ERROR;
|
||||
@ -4372,8 +4406,10 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
|
||||
*/
|
||||
rpz_clean(zonep, dbp, nodep, rdatasetp);
|
||||
result = rpz_ready(client, rdatasetp);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
CTRACE(ISC_LOG_ERROR, "rpz_ready() failed");
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
*versionp = NULL;
|
||||
result = rpz_getdb(client, p_name, rpz_type, zonep, dbp, versionp);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
@ -4396,6 +4432,8 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name,
|
||||
rpz_type, " allrdatasets()", result);
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"rpz_find_p: allrdatasets failed");
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
for (result = dns_rdatasetiter_first(rdsiter);
|
||||
@ -4413,6 +4451,9 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
|
||||
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
|
||||
p_name, rpz_type,
|
||||
" rdatasetiter", result);
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"rpz_find_p: rdatasetiter_destroy "
|
||||
"failed");
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
/*
|
||||
@ -4467,6 +4508,8 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
|
||||
default:
|
||||
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type,
|
||||
"", result);
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"rpz_find_p: unexpected result");
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
}
|
||||
@ -4696,6 +4739,8 @@ rpz_rewrite_ip_rrset(ns_client_t *client,
|
||||
rpz_type, " NS address rewrite rrset",
|
||||
result);
|
||||
}
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"rpz_rewrite_ip_rrset: unexpected result");
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
|
||||
@ -5330,6 +5375,7 @@ cleanup:
|
||||
rpz_match_clear(st);
|
||||
}
|
||||
if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
|
||||
CTRACE(ISC_LOG_ERROR, "SERVFAIL due to RPZ policy");
|
||||
st->m.type = DNS_RPZ_TYPE_BAD;
|
||||
result = DNS_R_SERVFAIL;
|
||||
}
|
||||
@ -5563,7 +5609,7 @@ query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) {
|
||||
dns_rdataset_t *neg, *negsig;
|
||||
isc_result_t result = ISC_R_NOMEMORY;
|
||||
|
||||
CTRACE("query_addnoqnameproof");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_addnoqnameproof");
|
||||
|
||||
fname = NULL;
|
||||
neg = NULL;
|
||||
@ -5977,7 +6023,7 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
|
||||
dns_clientinfo_t ci;
|
||||
ns_dbversion_t *dbversion;
|
||||
|
||||
CTRACE("redirect");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "redirect");
|
||||
|
||||
if (client->view->redirect == NULL)
|
||||
return (ISC_FALSE);
|
||||
@ -6044,7 +6090,7 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
|
||||
dns_db_detach(&db);
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
CTRACE("redirect: found data: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "redirect: found data: done");
|
||||
|
||||
dns_name_copy(found, name, NULL);
|
||||
if (dns_rdataset_isassociated(rdataset))
|
||||
@ -6109,11 +6155,12 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
isc_boolean_t nxrewrite = ISC_FALSE;
|
||||
dns_clientinfomethods_t cm;
|
||||
dns_clientinfo_t ci;
|
||||
char errmsg[256];
|
||||
isc_boolean_t associated;
|
||||
dns_section_t section;
|
||||
dns_ttl_t ttl;
|
||||
|
||||
CTRACE("query_find");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_find");
|
||||
|
||||
/*
|
||||
* One-time initialization.
|
||||
@ -6205,11 +6252,15 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
*/
|
||||
dbuf = query_getnamebuf(client);
|
||||
if (dbuf == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: query_getnamebuf failed (1)");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
fname = query_newname(client, dbuf, &b);
|
||||
if (fname == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: query_newname failed (1)");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
@ -6221,6 +6272,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
}
|
||||
result = dns_name_copy(tname, fname, NULL);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: dns_name_copy failed");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
@ -6249,7 +6302,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
type = qtype;
|
||||
|
||||
restart:
|
||||
CTRACE("query_find: restart");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_find: restart");
|
||||
want_restart = ISC_FALSE;
|
||||
authoritative = ISC_FALSE;
|
||||
version = NULL;
|
||||
@ -6326,8 +6379,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
inc_stats(client, dns_nsstatscounter_authrej);
|
||||
if (!PARTIALANSWER(client))
|
||||
QUERY_ERROR(DNS_R_REFUSED);
|
||||
} else
|
||||
} else {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: query_getdb failed");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -6360,24 +6416,30 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
}
|
||||
|
||||
db_find:
|
||||
CTRACE("query_find: db_find");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_find: db_find");
|
||||
/*
|
||||
* We'll need some resources...
|
||||
*/
|
||||
dbuf = query_getnamebuf(client);
|
||||
if (dbuf == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: query_getnamebuf failed (2)");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
fname = query_newname(client, dbuf, &b);
|
||||
rdataset = query_newrdataset(client);
|
||||
if (fname == NULL || rdataset == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: query_newname failed (2)");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
if (WANTDNSSEC(client) && (!is_zone || dns_db_issecure(db))) {
|
||||
sigrdataset = query_newrdataset(client);
|
||||
if (sigrdataset == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: query_newrdataset failed (2)");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
@ -6394,7 +6456,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
dns_cache_updatestats(client->view->cache, result);
|
||||
|
||||
resume:
|
||||
CTRACE("query_find: resume");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_find: resume");
|
||||
|
||||
/*
|
||||
* Rate limit these responses to this client.
|
||||
@ -6759,6 +6821,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
goto cleanup;
|
||||
} else {
|
||||
/* Unable to give root server referral. */
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"unable to give root server referral");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
@ -7025,11 +7089,17 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
if (fname == NULL) {
|
||||
dbuf = query_getnamebuf(client);
|
||||
if (dbuf == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: "
|
||||
"query_getnamebuf failed (3)");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
fname = query_newname(client, dbuf, &b);
|
||||
if (fname == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: "
|
||||
"query_newname failed (3)");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
@ -7128,6 +7198,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
if (fname == NULL ||
|
||||
rdataset == NULL ||
|
||||
sigrdataset == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: "
|
||||
"failure getting "
|
||||
"closest encloser");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
@ -7306,11 +7380,17 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
if (fname == NULL) {
|
||||
dbuf = query_getnamebuf(client);
|
||||
if (dbuf == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: "
|
||||
"query_getnamebuf failed (4)");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
fname = query_newname(client, dbuf, &b);
|
||||
if (fname == NULL) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: "
|
||||
"query_newname failed (4)");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
@ -7567,6 +7647,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
/*
|
||||
* Something has gone wrong.
|
||||
*/
|
||||
snprintf(errmsg, sizeof(errmsg) - 1,
|
||||
"query_find: unexpected error after resuming: %s",
|
||||
isc_result_totext(result));
|
||||
CTRACE(ISC_LOG_ERROR, errmsg);
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
@ -7625,6 +7709,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
rdsiter = NULL;
|
||||
result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: type any; allrdatasets failed");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
@ -7759,12 +7845,18 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
dns_rdatasetiter_destroy(&rdsiter);
|
||||
fname = query_newname(client, dbuf, &b);
|
||||
goto nxrrset_rrsig;
|
||||
} else
|
||||
} else {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: no matching rdatasets "
|
||||
"in cache");
|
||||
result = DNS_R_SERVFAIL;
|
||||
}
|
||||
}
|
||||
|
||||
dns_rdatasetiter_destroy(&rdsiter);
|
||||
if (result != ISC_R_NOMORE) {
|
||||
CTRACE(ISC_LOG_ERROR,
|
||||
"query_find: dns_rdatasetiter_destroy failed");
|
||||
QUERY_ERROR(DNS_R_SERVFAIL);
|
||||
goto cleanup;
|
||||
}
|
||||
@ -7988,7 +8080,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
}
|
||||
|
||||
addauth:
|
||||
CTRACE("query_find: addauth");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_find: addauth");
|
||||
/*
|
||||
* Add NS records to the authority section (if we haven't already
|
||||
* added them to the answer section).
|
||||
@ -8016,7 +8108,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
dns_fixedname_name(&wildcardname),
|
||||
ISC_TRUE, ISC_FALSE);
|
||||
cleanup:
|
||||
CTRACE("query_find: cleanup");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_find: cleanup");
|
||||
/*
|
||||
* General cleanup.
|
||||
*/
|
||||
@ -8124,7 +8216,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
|
||||
query_send(client);
|
||||
ns_client_detach(&client);
|
||||
}
|
||||
CTRACE("query_find: done");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "query_find: done");
|
||||
|
||||
return (eresult);
|
||||
}
|
||||
@ -8212,7 +8304,7 @@ ns_query_start(ns_client_t *client) {
|
||||
unsigned int saved_extflags = client->extflags;
|
||||
unsigned int saved_flags = client->message->flags;
|
||||
|
||||
CTRACE("ns_query_start");
|
||||
CTRACE(ISC_LOG_DEBUG(3), "ns_query_start");
|
||||
|
||||
/*
|
||||
* Test only.
|
||||
|
@ -4684,6 +4684,9 @@ directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) {
|
||||
static void
|
||||
scan_interfaces(ns_server_t *server, isc_boolean_t verbose) {
|
||||
isc_boolean_t match_mapped = server->aclenv.match_mapped;
|
||||
#ifdef HAVE_GEOIP
|
||||
isc_boolean_t use_ecs = server->aclenv.geoip_use_ecs;
|
||||
#endif
|
||||
|
||||
ns_interfacemgr_scan(server->interfacemgr, verbose);
|
||||
/*
|
||||
@ -4694,6 +4697,9 @@ scan_interfaces(ns_server_t *server, isc_boolean_t verbose) {
|
||||
ns_interfacemgr_getaclenv(server->interfacemgr));
|
||||
|
||||
server->aclenv.match_mapped = match_mapped;
|
||||
#ifdef HAVE_GEOIP
|
||||
server->aclenv.geoip_use_ecs = use_ecs;
|
||||
#endif
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
@ -5554,6 +5560,11 @@ load_configuration(const char *filename, ns_server_t *server,
|
||||
} else
|
||||
ns_geoip_load(NULL);
|
||||
ns_g_aclconfctx->geoip = ns_g_geoip;
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "geoip-use-ecs", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
ns_g_server->aclenv.geoip_use_ecs = cfg_obj_asboolean(obj);
|
||||
#endif /* HAVE_GEOIP */
|
||||
|
||||
/*
|
||||
|
@ -242,6 +242,7 @@ init_desc(void) {
|
||||
"SitNoMatch");
|
||||
SET_NSSTATDESC(sitmatch, "source identity token - match", "SitMatch");
|
||||
#endif
|
||||
SET_NSSTATDESC(ecsopt, "EDNS client subnet option recieved", "ECSOpt");
|
||||
INSIST(i == dns_nsstatscounter_max);
|
||||
|
||||
/* Initialize resolver statistics */
|
||||
|
50
bin/tests/system/acl/ns2/named6.conf
Normal file
50
bin/tests/system/acl/ns2/named6.conf
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
controls { /* empty */ };
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.2;
|
||||
notify-source 10.53.0.2;
|
||||
transfer-source 10.53.0.2;
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.2; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
notify yes;
|
||||
ixfr-from-differences yes;
|
||||
check-integrity no;
|
||||
allow-query-on { 10.53.0.2; };
|
||||
};
|
||||
|
||||
include "../../common/controls.conf";
|
||||
|
||||
zone "." {
|
||||
type hint;
|
||||
file "../../common/root.hint";
|
||||
};
|
||||
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example.db";
|
||||
};
|
||||
|
||||
zone "tsigzone" {
|
||||
type master;
|
||||
file "tsigzone.db";
|
||||
allow-transfer { ecs 10.53/16; !10/8; };
|
||||
};
|
60
bin/tests/system/acl/ns2/named7.conf
Normal file
60
bin/tests/system/acl/ns2/named7.conf
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
controls { /* empty */ };
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.2;
|
||||
notify-source 10.53.0.2;
|
||||
transfer-source 10.53.0.2;
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.2; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
notify yes;
|
||||
ixfr-from-differences yes;
|
||||
check-integrity no;
|
||||
allow-query-on { 10.53.0.2; };
|
||||
};
|
||||
|
||||
include "../../common/controls.conf";
|
||||
|
||||
view one {
|
||||
match-clients { ecs 192.0.2/24; };
|
||||
|
||||
zone "." {
|
||||
type hint;
|
||||
file "../../common/root.hint";
|
||||
};
|
||||
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example.db";
|
||||
};
|
||||
};
|
||||
|
||||
view two {
|
||||
zone "." {
|
||||
type hint;
|
||||
file "../../common/root.hint";
|
||||
};
|
||||
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example.db";
|
||||
};
|
||||
};
|
@ -150,5 +150,35 @@ $DIG +tcp soa example. \
|
||||
@10.53.0.2 -b 10.53.0.3 -p 5300 > dig.out.${t}
|
||||
grep "status: NOERROR" dig.out.${t} > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; }
|
||||
|
||||
echo "I:testing EDNS client-subnet ACL processing"
|
||||
cp -f ns2/named6.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
|
||||
sleep 5
|
||||
|
||||
# should fail
|
||||
t=`expr $t + 1`
|
||||
$DIG $DIGOPTS tsigzone. \
|
||||
@10.53.0.2 -b 10.53.0.2 axfr -p 5300 > dig.out.${t}
|
||||
grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; }
|
||||
|
||||
# should succeed
|
||||
t=`expr $t + 1`
|
||||
$DIG $DIGOPTS tsigzone. \
|
||||
@10.53.0.2 -b 10.53.0.2 +subnet="10.53.0/24" axfr -p 5300 > dig.out.${t}
|
||||
grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; }
|
||||
|
||||
echo "I:testing EDNS client-subnet response scope"
|
||||
cp -f ns2/named7.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
|
||||
sleep 5
|
||||
|
||||
t=`expr $t + 1`
|
||||
$DIG example. soa @10.53.0.2 +subnet="10.53.0.1/32" -p 5300 > dig.out.${t}
|
||||
grep "CLIENT-SUBNET.*10.53.0.1/32/0" dig.out.${t} > /dev/null || { echo "I:test $t failed" ; status=1; }
|
||||
|
||||
t=`expr $t + 1`
|
||||
$DIG example. soa @10.53.0.2 +subnet="192.0.2.128/32" -p 5300 > dig.out.${t}
|
||||
grep "CLIENT-SUBNET.*192.0.2.128/32/24" dig.out.${t} > /dev/null || { echo "I:test $t failed" ; status=1; }
|
||||
|
||||
echo "I:exit status: $status"
|
||||
exit $status
|
||||
|
@ -15,5 +15,5 @@
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
rm -f ns2/named.conf
|
||||
rm -f ns2/example[1234567].db
|
||||
rm -f ns2/example*.db
|
||||
rm -f dig.out.* rndc.out.*
|
||||
|
@ -5,3 +5,4 @@
|
||||
10.53.0.5/32 CL
|
||||
10.53.0.6/32 DE
|
||||
10.53.0.7/32 EH
|
||||
192.0.2/24 O1
|
||||
|
|
Binary file not shown.
@ -18,8 +18,8 @@ GeoIPDoain.dat: Domain Name
|
||||
GeoIPASNum.dat: AS Number
|
||||
GeoIPNetSpeed.dat: Net Speed
|
||||
|
||||
GeoIP.dat can also be generated using the open source 'geoip-csv-to-dat'
|
||||
utility:
|
||||
GeoIP.dat can also be egenerated using the open source 'geoip-csv-to-dat'
|
||||
utility (also known in some packages as "geoip-generator"):
|
||||
|
||||
$ geoip-csv-to-dat -i "BIND9 geoip test data v1" -o GeoIP.dat << EOF
|
||||
"10.53.0.1","10.53.0.1","171245569","171245569","AU","Australia"
|
||||
@ -29,4 +29,5 @@ $ geoip-csv-to-dat -i "BIND9 geoip test data v1" -o GeoIP.dat << EOF
|
||||
"10.53.0.5","10.53.0.5","171245573","171245573","CL","Chile"
|
||||
"10.53.0.6","10.53.0.6","171245574","171245574","DE","Germany"
|
||||
"10.53.0.7","10.53.0.7","171245575","171245575","EH","Western Sahara"
|
||||
"192.0.2.0","192.0.2.255","3221225984","3221226239","O1","Other"
|
||||
EOF
|
||||
|
@ -95,6 +95,14 @@ view seven {
|
||||
};
|
||||
};
|
||||
|
||||
view other {
|
||||
match-clients { geoip db country country O1; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "exampleother.db";
|
||||
};
|
||||
};
|
||||
|
||||
view none {
|
||||
match-clients { any; };
|
||||
zone "example" {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -40,7 +40,7 @@ controls {
|
||||
};
|
||||
|
||||
view one {
|
||||
match-clients { geoip domain one.de; };
|
||||
match-clients { geoip asnum "AS100001"; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example1.db";
|
||||
@ -48,7 +48,7 @@ view one {
|
||||
};
|
||||
|
||||
view two {
|
||||
match-clients { geoip domain two.com; };
|
||||
match-clients { geoip asnum "AS100002"; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example2.db";
|
||||
@ -56,7 +56,7 @@ view two {
|
||||
};
|
||||
|
||||
view three {
|
||||
match-clients { geoip domain three.com; };
|
||||
match-clients { geoip asnum "AS100003"; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example3.db";
|
||||
@ -64,7 +64,7 @@ view three {
|
||||
};
|
||||
|
||||
view four {
|
||||
match-clients { geoip domain four.com; };
|
||||
match-clients { geoip asnum "AS100004"; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example4.db";
|
||||
@ -72,7 +72,7 @@ view four {
|
||||
};
|
||||
|
||||
view five {
|
||||
match-clients { geoip domain five.es; };
|
||||
match-clients { geoip asnum "AS100005"; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example5.db";
|
||||
@ -80,7 +80,7 @@ view five {
|
||||
};
|
||||
|
||||
view six {
|
||||
match-clients { geoip domain six.it; };
|
||||
match-clients { geoip asnum "AS100006"; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example6.db";
|
||||
@ -88,7 +88,7 @@ view six {
|
||||
};
|
||||
|
||||
view seven {
|
||||
match-clients { geoip domain seven.org; };
|
||||
match-clients { geoip asnum "AS100007"; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example7.db";
|
||||
|
@ -40,7 +40,7 @@ controls {
|
||||
};
|
||||
|
||||
view one {
|
||||
match-clients { geoip netspeed 0; };
|
||||
match-clients { geoip domain one.de; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example1.db";
|
||||
@ -48,7 +48,7 @@ view one {
|
||||
};
|
||||
|
||||
view two {
|
||||
match-clients { geoip netspeed 1; };
|
||||
match-clients { geoip domain two.com; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example2.db";
|
||||
@ -56,7 +56,7 @@ view two {
|
||||
};
|
||||
|
||||
view three {
|
||||
match-clients { geoip netspeed 2; };
|
||||
match-clients { geoip domain three.com; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example3.db";
|
||||
@ -64,13 +64,37 @@ view three {
|
||||
};
|
||||
|
||||
view four {
|
||||
match-clients { geoip netspeed 3; };
|
||||
match-clients { geoip domain four.com; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example4.db";
|
||||
};
|
||||
};
|
||||
|
||||
view five {
|
||||
match-clients { geoip domain five.es; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example5.db";
|
||||
};
|
||||
};
|
||||
|
||||
view six {
|
||||
match-clients { geoip domain six.it; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example6.db";
|
||||
};
|
||||
};
|
||||
|
||||
view seven {
|
||||
match-clients { geoip domain seven.org; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example7.db";
|
||||
};
|
||||
};
|
||||
|
||||
view none {
|
||||
match-clients { any; };
|
||||
zone "example" {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -18,10 +18,6 @@
|
||||
|
||||
controls { /* empty */ };
|
||||
|
||||
acl blocking {
|
||||
geoip db country country AU;
|
||||
};
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.2;
|
||||
notify-source 10.53.0.2;
|
||||
@ -32,7 +28,6 @@ options {
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
geoip-directory "../data";
|
||||
blackhole { blocking; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
@ -43,3 +38,43 @@ key rndc_key {
|
||||
controls {
|
||||
inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
view one {
|
||||
match-clients { geoip netspeed 0; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example1.db";
|
||||
};
|
||||
};
|
||||
|
||||
view two {
|
||||
match-clients { geoip netspeed 1; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example2.db";
|
||||
};
|
||||
};
|
||||
|
||||
view three {
|
||||
match-clients { geoip netspeed 2; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example3.db";
|
||||
};
|
||||
};
|
||||
|
||||
view four {
|
||||
match-clients { geoip netspeed 3; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example4.db";
|
||||
};
|
||||
};
|
||||
|
||||
view none {
|
||||
match-clients { any; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example.db.in";
|
||||
};
|
||||
};
|
||||
|
@ -18,6 +18,10 @@
|
||||
|
||||
controls { /* empty */ };
|
||||
|
||||
acl blocking {
|
||||
geoip db country country AU;
|
||||
};
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.2;
|
||||
notify-source 10.53.0.2;
|
||||
@ -28,6 +32,7 @@ options {
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
geoip-directory "../data";
|
||||
blackhole { blocking; };
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
@ -38,75 +43,3 @@ key rndc_key {
|
||||
controls {
|
||||
inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
acl gAU { geoip db country country AU; };
|
||||
acl gUS { geoip db country country US; };
|
||||
acl gGB { geoip db country country GB; };
|
||||
acl gCA { geoip db country country CA; };
|
||||
acl gCL { geoip db country country CL; };
|
||||
acl gDE { geoip db country country DE; };
|
||||
acl gEH { geoip db country country EH; };
|
||||
|
||||
view one {
|
||||
match-clients { gAU; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example1.db";
|
||||
};
|
||||
};
|
||||
|
||||
view two {
|
||||
match-clients { gUS; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example2.db";
|
||||
};
|
||||
};
|
||||
|
||||
view three {
|
||||
match-clients { gGB; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example3.db";
|
||||
};
|
||||
};
|
||||
|
||||
view four {
|
||||
match-clients { gCA; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example4.db";
|
||||
};
|
||||
};
|
||||
|
||||
view five {
|
||||
match-clients { gCL; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example5.db";
|
||||
};
|
||||
};
|
||||
|
||||
view six {
|
||||
match-clients { gDE; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example6.db";
|
||||
};
|
||||
};
|
||||
|
||||
view seven {
|
||||
match-clients { gEH; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example7.db";
|
||||
};
|
||||
};
|
||||
|
||||
view none {
|
||||
match-clients { any; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example.db.in";
|
||||
};
|
||||
};
|
||||
|
113
bin/tests/system/geoip/ns2/named14.conf
Normal file
113
bin/tests/system/geoip/ns2/named14.conf
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
// NS2
|
||||
|
||||
controls { /* empty */ };
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.2;
|
||||
notify-source 10.53.0.2;
|
||||
transfer-source 10.53.0.2;
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
listen-on { 127.0.0.1; 10.53.0.2; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
geoip-directory "../data";
|
||||
geoip-use-ecs no;
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-sha256;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
acl gAU { geoip db country country AU; };
|
||||
acl gUS { geoip db country country US; };
|
||||
acl gGB { geoip db country country GB; };
|
||||
acl gCA { geoip db country country CA; };
|
||||
acl gCL { geoip db country country CL; };
|
||||
acl gDE { geoip db country country DE; };
|
||||
acl gEH { geoip db country country EH; };
|
||||
|
||||
view one {
|
||||
match-clients { gAU; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example1.db";
|
||||
};
|
||||
};
|
||||
|
||||
view two {
|
||||
match-clients { gUS; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example2.db";
|
||||
};
|
||||
};
|
||||
|
||||
view three {
|
||||
match-clients { gGB; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example3.db";
|
||||
};
|
||||
};
|
||||
|
||||
view four {
|
||||
match-clients { gCA; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example4.db";
|
||||
};
|
||||
};
|
||||
|
||||
view five {
|
||||
match-clients { gCL; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example5.db";
|
||||
};
|
||||
};
|
||||
|
||||
view six {
|
||||
match-clients { gDE; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example6.db";
|
||||
};
|
||||
};
|
||||
|
||||
view seven {
|
||||
match-clients { gEH; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "example7.db";
|
||||
};
|
||||
};
|
||||
|
||||
view none {
|
||||
match-clients { any; };
|
||||
zone "example" {
|
||||
type master;
|
||||
file "examplebogus.db";
|
||||
};
|
||||
};
|
@ -21,7 +21,7 @@ $SHELL clean.sh
|
||||
|
||||
cp ns2/named1.conf ns2/named.conf
|
||||
|
||||
for i in 1 2 3 4 5 6 7; do
|
||||
for i in 1 2 3 4 5 6 7 other bogus; do
|
||||
cp ns2/example.db.in ns2/example${i}.db
|
||||
echo "@ IN TXT \"$i\"" >> ns2/example$i.db
|
||||
done
|
||||
|
@ -38,6 +38,30 @@ done
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking GeoIP country database by code (using client subnet) ($n)"
|
||||
ret=0
|
||||
lret=0
|
||||
for i in 1 2 3 4 5 6 7; do
|
||||
$DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/0" > dig.out.ns2.test$n.$i || lret=1
|
||||
j=`cat dig.out.ns2.test$n.$i | tr -d '"'`
|
||||
[ "$i" = "$j" ] || lret=1
|
||||
[ $lret -eq 1 ] && break
|
||||
done
|
||||
[ $lret -eq 1 ] && ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking response scope using client subnet ($n)"
|
||||
ret=0
|
||||
$DIG +tcp -p5300 @10.53.0.2 txt example -b 127.0.0.1 +subnet="10.53.0.1/32" > dig.out.ns2.test$n.1 || ret=1
|
||||
grep 'CLIENT-SUBNET.*10.53.0.1/32/32' dig.out.ns2.test$n.1 > /dev/null || ret=1
|
||||
$DIG +tcp -p5300 @10.53.0.2 txt example -b 127.0.0.1 +subnet="192.0.2.64/32" > dig.out.ns2.test$n.2 || ret=1
|
||||
grep 'CLIENT-SUBNET.*192.0.2.64/32/24' dig.out.ns2.test$n.2 > /dev/null || ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:reloading server"
|
||||
cp -f ns2/named2.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
|
||||
@ -115,6 +139,21 @@ done
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking GeoIP region database (using client subnet) ($n)"
|
||||
ret=0
|
||||
lret=0
|
||||
for i in 1 2 3 4 5 6 7; do
|
||||
$DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > dig.out.ns2.test$n.$i || lret=1
|
||||
j=`cat dig.out.ns2.test$n.$i | tr -d '"'`
|
||||
[ "$i" = "$j" ] || lret=1
|
||||
[ $lret -eq 1 ] && break
|
||||
done
|
||||
[ $lret -eq 1 ] && ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
|
||||
echo "I:reloading server"
|
||||
cp -f ns2/named6.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
|
||||
@ -134,6 +173,20 @@ done
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking GeoIP city database (using client subnet) ($n)"
|
||||
ret=0
|
||||
lret=0
|
||||
for i in 1 2 3 4 5 6 7; do
|
||||
$DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > dig.out.ns2.test$n.$i || lret=1
|
||||
j=`cat dig.out.ns2.test$n.$i | tr -d '"'`
|
||||
[ "$i" = "$j" ] || lret=1
|
||||
[ $lret -eq 1 ] && break
|
||||
done
|
||||
[ $lret -eq 1 ] && ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:reloading server"
|
||||
cp -f ns2/named7.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
|
||||
@ -153,6 +206,20 @@ done
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking GeoIP isp database (using client subnet) ($n)"
|
||||
ret=0
|
||||
lret=0
|
||||
for i in 1 2 3 4 5 6 7; do
|
||||
$DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > dig.out.ns2.test$n.$i || lret=1
|
||||
j=`cat dig.out.ns2.test$n.$i | tr -d '"'`
|
||||
[ "$i" = "$j" ] || lret=1
|
||||
[ $lret -eq 1 ] && break
|
||||
done
|
||||
[ $lret -eq 1 ] && ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:reloading server"
|
||||
cp -f ns2/named8.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
|
||||
@ -172,6 +239,20 @@ done
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking GeoIP org database (using client subnet) ($n)"
|
||||
ret=0
|
||||
lret=0
|
||||
for i in 1 2 3 4 5 6 7; do
|
||||
$DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > dig.out.ns2.test$n.$i || lret=1
|
||||
j=`cat dig.out.ns2.test$n.$i | tr -d '"'`
|
||||
[ "$i" = "$j" ] || lret=1
|
||||
[ $lret -eq 1 ] && break
|
||||
done
|
||||
[ $lret -eq 1 ] && ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:reloading server"
|
||||
cp -f ns2/named9.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
|
||||
@ -191,11 +272,58 @@ done
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking GeoIP asnum database (using client subnet) ($n)"
|
||||
ret=0
|
||||
lret=0
|
||||
for i in 1 2 3 4 5 6 7; do
|
||||
$DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > dig.out.ns2.test$n.$i || lret=1
|
||||
j=`cat dig.out.ns2.test$n.$i | tr -d '"'`
|
||||
[ "$i" = "$j" ] || lret=1
|
||||
[ $lret -eq 1 ] && break
|
||||
done
|
||||
[ $lret -eq 1 ] && ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:reloading server"
|
||||
cp -f ns2/named10.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
|
||||
sleep 3
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking GeoIP asnum database - ASNNNN only ($n)"
|
||||
ret=0
|
||||
lret=0
|
||||
for i in 1 2 3 4 5 6 7; do
|
||||
$DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1
|
||||
j=`cat dig.out.ns2.test$n.$i | tr -d '"'`
|
||||
[ "$i" = "$j" ] || lret=1
|
||||
[ $lret -eq 1 ] && break
|
||||
done
|
||||
[ $lret -eq 1 ] && ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking GeoIP domain database (using client subnet) ($n)"
|
||||
ret=0
|
||||
lret=0
|
||||
for i in 1 2 3 4 5 6 7; do
|
||||
$DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > dig.out.ns2.test$n.$i || lret=1
|
||||
j=`cat dig.out.ns2.test$n.$i | tr -d '"'`
|
||||
[ "$i" = "$j" ] || lret=1
|
||||
[ $lret -eq 1 ] && break
|
||||
done
|
||||
[ $lret -eq 1 ] && ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:reloading server"
|
||||
cp -f ns2/named11.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
|
||||
sleep 3
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking GeoIP domain database ($n)"
|
||||
ret=0
|
||||
@ -211,7 +339,7 @@ done
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:reloading server"
|
||||
cp -f ns2/named11.conf ns2/named.conf
|
||||
cp -f ns2/named12.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
|
||||
sleep 3
|
||||
|
||||
@ -229,8 +357,22 @@ done
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking GeoIP netspeed database (using client subnet) ($n)"
|
||||
ret=0
|
||||
lret=0
|
||||
for i in 1 2 3 4; do
|
||||
$DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > dig.out.ns2.test$n.$i || lret=1
|
||||
j=`cat dig.out.ns2.test$n.$i | tr -d '"'`
|
||||
[ "$i" = "$j" ] || lret=1
|
||||
[ $lret -eq 1 ] && break
|
||||
done
|
||||
[ $lret -eq 1 ] && ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:reloading server"
|
||||
cp -f ns2/named12.conf ns2/named.conf
|
||||
cp -f ns2/named13.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
|
||||
sleep 3
|
||||
|
||||
@ -243,7 +385,7 @@ $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 status 2>&1 > rndc.out.ns2.tes
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:reloading server"
|
||||
cp -f ns2/named13.conf ns2/named.conf
|
||||
cp -f ns2/named14.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
|
||||
sleep 3
|
||||
|
||||
@ -261,5 +403,29 @@ done
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:reloading server"
|
||||
cp -f ns2/named14.conf ns2/named.conf
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
|
||||
sleep 3
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking geoip-use-ecs ($n)"
|
||||
ret=0
|
||||
lret=0
|
||||
for i in 1 2 3 4 5 6 7; do
|
||||
$DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1
|
||||
j=`cat dig.out.ns2.test$n.$i | tr -d '"'`
|
||||
[ "$i" = "$j" ] || lret=1
|
||||
[ $lret -eq 1 ] && break
|
||||
|
||||
$DIG $DIGOPTS txt example -b 127.0.0.1 +subnet="10.53.0.$i/32" > dig.out.ns2.test$n.ecs.$i || lret=1
|
||||
j=`cat dig.out.ns2.test$n.ecs.$i | tr -d '"'`
|
||||
[ "$j" = "bogus" ] || lret=1
|
||||
[ $lret -eq 1 ] && break
|
||||
done
|
||||
[ $lret -eq 1 ] && ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:exit status: $status"
|
||||
exit $status
|
||||
|
3
bin/tests/system/sit/bad-sit-badhex.conf
Normal file
3
bin/tests/system/sit/bad-sit-badhex.conf
Normal file
@ -0,0 +1,3 @@
|
||||
options {
|
||||
sit-secret "012345678901234567890123456789012345678901234567890123456789012";
|
||||
};
|
3
bin/tests/system/sit/bad-sit-toolong.conf
Normal file
3
bin/tests/system/sit/bad-sit-toolong.conf
Normal file
@ -0,0 +1,3 @@
|
||||
options {
|
||||
sit-secret "01234567890123456789012345678901234567890123456789012345678901234567890";
|
||||
};
|
@ -32,6 +32,15 @@ havetc() {
|
||||
grep 'flags:.* tc[^;]*;' $1 > /dev/null
|
||||
}
|
||||
|
||||
for bad in bad*.conf
|
||||
do
|
||||
ret=0
|
||||
echo "I:checking that named-checkconf detects error in $bad"
|
||||
$CHECKCONF $bad > /dev/null 2>&1
|
||||
if [ $? != 1 ]; then echo "I:failed"; ret=1; fi
|
||||
status=`expr $status + $ret`
|
||||
done
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I:checking SIT token returned to empty SIT option ($n)"
|
||||
ret=0
|
||||
|
@ -2564,10 +2564,10 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
|
||||
<command>lwres</command> statement in <filename>named.conf</filename>.
|
||||
</para>
|
||||
<para>
|
||||
The number of client queries that the <command>lwresd</command>
|
||||
daemon is able to serve can be set using the
|
||||
<option>lwres-tasks</option> and <option>lwres-clients</option>
|
||||
statements in the configuration.
|
||||
The number of client queries that the <command>lwresd</command>
|
||||
daemon is able to serve can be set using the
|
||||
<option>lwres-tasks</option> and <option>lwres-clients</option>
|
||||
statements in the configuration.
|
||||
</para>
|
||||
</sect1>
|
||||
</chapter>
|
||||
@ -3444,63 +3444,6 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
|
||||
<para>
|
||||
When <acronym>BIND</acronym> 9 is built with GeoIP support,
|
||||
ACLs can also be used for geographic access restrictions.
|
||||
This is done by specifying an ACL element of the form:
|
||||
<command>geoip <optional>db <replaceable>database</replaceable></optional> <replaceable>field</replaceable> <replaceable>value</replaceable></command>
|
||||
</para>
|
||||
<para>
|
||||
The <replaceable>field</replaceable> indicates which field
|
||||
to search for a match. Available fields are "country",
|
||||
"region", "city", "continent", "postal" (postal code),
|
||||
"metro" (metro code), "area" (area code), "tz" (timezone),
|
||||
"isp", "org", "asnum", "domain" and "netspeed".
|
||||
</para>
|
||||
<para>
|
||||
<replaceable>value</replaceable> is the value to searched for
|
||||
within the database. A string may be quoted if it contains
|
||||
spaces or other special characters. If this is a "country"
|
||||
search and the string is two characters long, then it must be a
|
||||
standard ISO-3166-1 two-letter country code, and if it is three
|
||||
characters long then it must be an ISO-3166-1 three-letter
|
||||
country code; otherwise it is the full name of the country.
|
||||
Similarly, if this is a "region" search and the string is
|
||||
two characters long, then it must be a standard two-letter state
|
||||
or province abbreviation; otherwise it is the full name of the
|
||||
state or province.
|
||||
</para>
|
||||
<para>
|
||||
The <replaceable>database</replaceable> field indicates which
|
||||
GeoIP database to search for a match. In most cases this is
|
||||
unnecessary, because most search fields can only be found in
|
||||
a single database. However, searches for country can be
|
||||
answered from the "city", "region", or "country" databases,
|
||||
and searches for region (i.e., state or province) can be
|
||||
answered from the "city" or "region" databases. For these
|
||||
search types, specifying a <replaceable>database</replaceable>
|
||||
will force the query to be answered from that database and no
|
||||
other. If <replaceable>database</replaceable> is not
|
||||
specified, then these queries will be answered from the "city",
|
||||
database if it is installed, or the "region" database if it is
|
||||
installed, or the "country" database, in that order.
|
||||
</para>
|
||||
<para>
|
||||
Some example GeoIP ACLs:
|
||||
</para>
|
||||
<programlisting>geoip country US;
|
||||
geoip country JAP;
|
||||
geoip db country country Canada;
|
||||
geoip db region region WA;
|
||||
geoip city "San Francisco";
|
||||
geoip region Oklahoma;
|
||||
geoip postal 95062;
|
||||
geoip tz "America/Los_Angeles";
|
||||
geoip org "Internet Systems Consortium";
|
||||
</programlisting>
|
||||
|
||||
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title><command>controls</command> Statement Grammar</title>
|
||||
@ -4718,32 +4661,32 @@ badresp:1,adberr:0,findfail:0,valfail:0]
|
||||
minimum
|
||||
number of dots in a relative domain name that should result in an
|
||||
exact match lookup before search path elements are appended.
|
||||
</para>
|
||||
<para>
|
||||
The <option>lwres-tasks</option> statement specifies the number
|
||||
of worker threads the lightweight resolver will dedicate to serving
|
||||
clients. By default the number is the same as the number of CPUs on
|
||||
the system; this can be overridden using the <option>-n</option>
|
||||
command line option when starting the server.
|
||||
</para>
|
||||
<para>
|
||||
The <option>lwres-clients</option> specifies
|
||||
the number of client objects per thread the lightweight
|
||||
resolver should create to serve client queries.
|
||||
By default, if the lightweight resolver runs as a part
|
||||
of <command>named</command>, 256 client objects are
|
||||
created for each task; if it runs as <command>lwresd</command>,
|
||||
1024 client objects are created for each thread. The maximum
|
||||
value is 32768; higher values will be silently ignored and
|
||||
the maximum will be used instead.
|
||||
Note that setting too high a value may overconsume
|
||||
system resources.
|
||||
</para>
|
||||
<para>
|
||||
The maximum number of client queries that the lightweight
|
||||
resolver can handle at any one time equals
|
||||
<option>lwres-tasks</option> times <option>lwres-clients</option>.
|
||||
</para>
|
||||
</para>
|
||||
<para>
|
||||
The <option>lwres-tasks</option> statement specifies the number
|
||||
of worker threads the lightweight resolver will dedicate to serving
|
||||
clients. By default the number is the same as the number of CPUs on
|
||||
the system; this can be overridden using the <option>-n</option>
|
||||
command line option when starting the server.
|
||||
</para>
|
||||
<para>
|
||||
The <option>lwres-clients</option> specifies
|
||||
the number of client objects per thread the lightweight
|
||||
resolver should create to serve client queries.
|
||||
By default, if the lightweight resolver runs as a part
|
||||
of <command>named</command>, 256 client objects are
|
||||
created for each task; if it runs as <command>lwresd</command>,
|
||||
1024 client objects are created for each thread. The maximum
|
||||
value is 32768; higher values will be silently ignored and
|
||||
the maximum will be used instead.
|
||||
Note that setting too high a value may overconsume
|
||||
system resources.
|
||||
</para>
|
||||
<para>
|
||||
The maximum number of client queries that the lightweight
|
||||
resolver can handle at any one time equals
|
||||
<option>lwres-tasks</option> times <option>lwres-clients</option>.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title><command>masters</command> Statement Grammar</title>
|
||||
@ -4855,6 +4798,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
|
||||
<optional> allow-update { <replaceable>address_match_list</replaceable> }; </optional>
|
||||
<optional> allow-update-forwarding { <replaceable>address_match_list</replaceable> }; </optional>
|
||||
<optional> automatic-interface-scan { <replaceable>yes_or_no</replaceable> }; </optional>
|
||||
<optional> geoip-use-ecs <replaceable>yes_or_no</replaceable>;</optional>
|
||||
<optional> update-check-ksk <replaceable>yes_or_no</replaceable>; </optional>
|
||||
<optional> dnssec-update-mode ( <replaceable>maintain</replaceable> | <replaceable>no-resign</replaceable> ); </optional>
|
||||
<optional> dnssec-dnskey-kskonly <replaceable>yes_or_no</replaceable>; </optional>
|
||||
@ -5793,7 +5737,7 @@ options {
|
||||
For convenience, TTL-style time unit suffixes can be
|
||||
used to specify the NTA lifetime in seconds, minutes
|
||||
or hours. <option>nta-lifetime</option> defaults to
|
||||
one hour. It cannot exceed one day.
|
||||
one hour. It cannot exceed one day.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -5802,31 +5746,31 @@ options {
|
||||
<term><command>nta-recheck</command></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Species how often to check whether negative
|
||||
trust anchors added via <command>rndc nta</command>
|
||||
are still necessary.
|
||||
Species how often to check whether negative
|
||||
trust anchors added via <command>rndc nta</command>
|
||||
are still necessary.
|
||||
</para>
|
||||
<para>
|
||||
A negative trust anchor is normally used when a
|
||||
domain has stopped validating due to operator error;
|
||||
it temporarily disables DNSSEC validation for that
|
||||
domain. In the interest of ensuring that DNSSEC
|
||||
validation is turned back on as soon as possible,
|
||||
<command>named</command> will periodically send a
|
||||
query to the domain, ignoring negative trust anchors,
|
||||
to find out whether it can now be validated. If so,
|
||||
the negative trust anchor is allowed to expire early.
|
||||
A negative trust anchor is normally used when a
|
||||
domain has stopped validating due to operator error;
|
||||
it temporarily disables DNSSEC validation for that
|
||||
domain. In the interest of ensuring that DNSSEC
|
||||
validation is turned back on as soon as possible,
|
||||
<command>named</command> will periodically send a
|
||||
query to the domain, ignoring negative trust anchors,
|
||||
to find out whether it can now be validated. If so,
|
||||
the negative trust anchor is allowed to expire early.
|
||||
</para>
|
||||
<para>
|
||||
Validity checks can be disabled for an individual
|
||||
NTA by using <command>rndc nta -f</command>, or
|
||||
for all NTA's by setting <option>nta-recheck</option>
|
||||
to zero.
|
||||
Validity checks can be disabled for an individual
|
||||
NTA by using <command>rndc nta -f</command>, or
|
||||
for all NTA's by setting <option>nta-recheck</option>
|
||||
to zero.
|
||||
</para>
|
||||
<para>
|
||||
For convenience, TTL-style time unit suffixes can be
|
||||
used to specify the NTA recheck interval in seconds,
|
||||
minutes or hours. The default is five minutes.
|
||||
used to specify the NTA recheck interval in seconds,
|
||||
minutes or hours. The default is five minutes.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -6237,6 +6181,20 @@ options {
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>geoip-use-ecs</command></term>
|
||||
<listitem>
|
||||
<para>
|
||||
When BIND is compiled with GeoIP support and configured
|
||||
with "geoip" ACL elements, this option indicates whether
|
||||
the EDNS Client Subnet option, if present in a request,
|
||||
should be used for matching against the GeoIP database.
|
||||
The default is
|
||||
<command>geoip-use-ecs</command> <userinput>yes</userinput>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>has-old-clients</command></term>
|
||||
<listitem>
|
||||
@ -6421,12 +6379,16 @@ options {
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>sit-secret</command></term> <listitem>
|
||||
<term><command>sit-secret</command></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If set, this is a shared secret used for generating
|
||||
and verifying Source Identity Token EDNS options
|
||||
within a anycast cluster. If not set the system
|
||||
will generate a random secret at startup.
|
||||
will generate a random secret at startup. The
|
||||
shared secret is encoded as a hex string and needs
|
||||
to be 128 bits for AES128, 160 bits for SHA1 and
|
||||
256 bits for SHA256.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -9016,24 +8978,24 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
|
||||
<varlistentry>
|
||||
<term><command>masterfile-style</command></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Specifies the formatting of zone files during dump
|
||||
when the <option>masterfile-format</option> is
|
||||
<constant>text</constant>. (This option is ignored
|
||||
with any other <option>masterfile-format</option>.)
|
||||
</para>
|
||||
<para>
|
||||
When set to <constant>relative</constant>,
|
||||
records are printed in a multi-line format with owner
|
||||
names expressed relative to a shared origin. When set
|
||||
to <constant>full</constant>, records are printed in
|
||||
a single-line format with absolute owner names.
|
||||
The <constant>full</constant> format is most suitable
|
||||
when a zone file needs to be processed automatically
|
||||
by a script. The <constant>relative</constant> format
|
||||
is more human-readable, and is thus suitable when a
|
||||
zone is to be edited by hand. The default is
|
||||
<constant>relative</constant>.
|
||||
<para>
|
||||
Specifies the formatting of zone files during dump
|
||||
when the <option>masterfile-format</option> is
|
||||
<constant>text</constant>. (This option is ignored
|
||||
with any other <option>masterfile-format</option>.)
|
||||
</para>
|
||||
<para>
|
||||
When set to <constant>relative</constant>,
|
||||
records are printed in a multi-line format with owner
|
||||
names expressed relative to a shared origin. When set
|
||||
to <constant>full</constant>, records are printed in
|
||||
a single-line format with absolute owner names.
|
||||
The <constant>full</constant> format is most suitable
|
||||
when a zone file needs to be processed automatically
|
||||
by a script. The <constant>relative</constant> format
|
||||
is more human-readable, and is thus suitable when a
|
||||
zone is to be edited by hand. The default is
|
||||
<constant>relative</constant>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -9046,8 +9008,8 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
|
||||
initial value (minimum) and maximum number of recursive
|
||||
simultaneous clients for any given query
|
||||
(<qname,qtype,qclass>) that the server will accept
|
||||
before dropping additional clients.
|
||||
<command>named</command> will attempt to
|
||||
before dropping additional clients.
|
||||
<command>named</command> will attempt to
|
||||
self tune this value and changes will be logged. The
|
||||
default values are 10 and 100.
|
||||
</para>
|
||||
@ -10560,15 +10522,15 @@ rate-limit {
|
||||
|
||||
<para>
|
||||
The <command>request-expire</command> clause determines
|
||||
whether the local server, when acting as a slave, will
|
||||
request the EDNS EXPIRE value. The EDNS EXPIRE value
|
||||
indicates the remaining time before the zone data will
|
||||
expire and need to be be refreshed. This is used
|
||||
when a secondary server transfers a zone from another
|
||||
secondary server; when transferring from the primary, the
|
||||
expiration timer is set from the EXPIRE field of the SOA
|
||||
record instead.
|
||||
The default is <command>yes</command>.
|
||||
whether the local server, when acting as a slave, will
|
||||
request the EDNS EXPIRE value. The EDNS EXPIRE value
|
||||
indicates the remaining time before the zone data will
|
||||
expire and need to be be refreshed. This is used
|
||||
when a secondary server transfers a zone from another
|
||||
secondary server; when transferring from the primary, the
|
||||
expiration timer is set from the EXPIRE field of the SOA
|
||||
record instead.
|
||||
The default is <command>yes</command>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -12455,11 +12417,11 @@ example.com. NS ns2.example.net.
|
||||
<para>
|
||||
When set to
|
||||
<command>serial-update-method date;</command>, the
|
||||
new SOA serial number will be the current date
|
||||
in the form "YYYYMMDD", followed by two zeroes,
|
||||
unless the existing serial number is already greater
|
||||
than or equal to that value, in which case it is
|
||||
incremented by one.
|
||||
new SOA serial number will be the current date
|
||||
in the form "YYYYMMDD", followed by two zeroes,
|
||||
unless the existing serial number is already greater
|
||||
than or equal to that value, in which case it is
|
||||
incremented by one.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -16181,11 +16143,11 @@ HOST-127.EXAMPLE. MX 0 .
|
||||
<title>Access Control Lists</title>
|
||||
<para>
|
||||
Access Control Lists (ACLs) are address match lists that
|
||||
you can set up and nickname for future use in <command>allow-notify</command>,
|
||||
<command>allow-query</command>, <command>allow-query-on</command>,
|
||||
<command>allow-recursion</command>, <command>allow-recursion-on</command>,
|
||||
you can set up and nickname for future use in
|
||||
<command>allow-notify</command>, <command>allow-query</command>,
|
||||
<command>allow-query-on</command>, <command>allow-recursion</command>,
|
||||
<command>blackhole</command>, <command>allow-transfer</command>,
|
||||
etc.
|
||||
<command>match-clients</command>, etc.
|
||||
</para>
|
||||
<para>
|
||||
Using ACLs allows you to have finer control over who can access
|
||||
@ -16195,11 +16157,19 @@ HOST-127.EXAMPLE. MX 0 .
|
||||
<para>
|
||||
It is a <emphasis>good idea</emphasis> to use ACLs, and to
|
||||
control access to your server. Limiting access to your server by
|
||||
outside parties can help prevent spoofing and denial of service (DoS) attacks against
|
||||
your server.
|
||||
outside parties can help prevent spoofing and denial of service
|
||||
(DoS) attacks against your server.
|
||||
</para>
|
||||
<para>
|
||||
Here is an example of how to properly apply ACLs:
|
||||
ACLs match clients on the basis of up to three characteristics:
|
||||
1) The client's IP address; 2) the TSIG or SIG(0) key that was
|
||||
used to sign the request, if any; and 3) an address prefix
|
||||
encoded in an EDNS Client Subnet option, if any.
|
||||
</para>
|
||||
<para>
|
||||
ACLs
|
||||
<para>
|
||||
Here is an example of ACLs based on client addresses:
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
@ -16232,10 +16202,137 @@ zone "example.com" {
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
This allows recursive queries of the server from the outside
|
||||
unless recursion has been previously disabled.
|
||||
This allows authoritative queries for "example.com" from any
|
||||
address, but recursive queries only from the networks specified
|
||||
in "our-nets", and no queries at all from the networks
|
||||
specified in "bogusnets".
|
||||
</para>
|
||||
<para>
|
||||
In addition to network addresses and prefixes, which are
|
||||
matched against the source address of the DNS request, ACLs
|
||||
may include <option>key</option> elements, which specify the
|
||||
name of a TSIG or SIG(0) key, or <option>ecs</option>
|
||||
elements, which specify a network prefix but are only matched
|
||||
if that prefix matches an EDNS client subnet option included
|
||||
in the request.
|
||||
</para>
|
||||
<para>
|
||||
The EDNS Client Subnet (ECS) option is used by a recursive
|
||||
resolver to inform an authoritative name server of the network
|
||||
address block from which the original query was received, enabling
|
||||
authoritative servers to give different answers to the same
|
||||
resolver for different resolver clients. An ACL containing
|
||||
an element of the form
|
||||
<command>ecs <replaceable>prefix</replaceable></command>
|
||||
will match if a request arrives in containing an ECS option
|
||||
encoding an address within that prefix. If the request has no
|
||||
ECS option, then "ecs" elements are simply ignored. Addresses
|
||||
in ACLs that are not prefixed with "ecs" are matched only
|
||||
against the source address.
|
||||
</para>
|
||||
<para>
|
||||
When <acronym>BIND</acronym> 9 is built with GeoIP support,
|
||||
ACLs can also be used for geographic access restrictions.
|
||||
This is done by specifying an ACL element of the form:
|
||||
<command>geoip <optional>db <replaceable>database</replaceable></optional> <replaceable>field</replaceable> <replaceable>value</replaceable></command>
|
||||
</para>
|
||||
<para>
|
||||
The <replaceable>field</replaceable> indicates which field
|
||||
to search for a match. Available fields are "country",
|
||||
"region", "city", "continent", "postal" (postal code),
|
||||
"metro" (metro code), "area" (area code), "tz" (timezone),
|
||||
"isp", "org", "asnum", "domain" and "netspeed".
|
||||
</para>
|
||||
<para>
|
||||
<replaceable>value</replaceable> is the value to search
|
||||
for within the database. A string may be quoted if it
|
||||
contains spaces or other special characters. If this is
|
||||
an "asnum" search, then the leading "ASNNNN" string can be
|
||||
used, otherwise the full description must be used (e.g.
|
||||
"ASNNNN Example Company Name"). If this is a "country"
|
||||
search and the string is two characters long, then it must
|
||||
be a standard ISO-3166-1 two-letter country code, and if it
|
||||
is three characters long then it must be an ISO-3166-1
|
||||
three-letter country code; otherwise it is the full name
|
||||
of the country. Similarly, if this is a "region" search
|
||||
and the string is two characters long, then it must be a
|
||||
standard two-letter state or province abbreviation;
|
||||
otherwise it is the full name of the state or province.
|
||||
</para>
|
||||
<para>
|
||||
The <replaceable>database</replaceable> field indicates which
|
||||
GeoIP database to search for a match. In most cases this is
|
||||
unnecessary, because most search fields can only be found in
|
||||
a single database. However, searches for country can be
|
||||
answered from the "city", "region", or "country" databases,
|
||||
and searches for region (i.e., state or province) can be
|
||||
answered from the "city" or "region" databases. For these
|
||||
search types, specifying a <replaceable>database</replaceable>
|
||||
will force the query to be answered from that database and no
|
||||
other. If <replaceable>database</replaceable> is not
|
||||
specified, then these queries will be answered from the "city",
|
||||
database if it is installed, or the "region" database if it is
|
||||
installed, or the "country" database, in that order.
|
||||
</para>
|
||||
<para>
|
||||
By default, if a DNS query includes an EDNS Client Subnet (ECS)
|
||||
option which encodes a non-zero address prefix, then GeoIP ACLs
|
||||
will be matched against that address prefix. Otherwise, they
|
||||
are matched against the source address of the query. To
|
||||
prevent GeoIP ACLs from matching against ECS options, set
|
||||
the <command>geoip-use-ecs</option> to <literal>no</literal>.
|
||||
</para>
|
||||
<para>
|
||||
Some example GeoIP ACLs:
|
||||
</para>
|
||||
<programlisting>geoip country US;
|
||||
geoip country JAP;
|
||||
geoip db country country Canada;
|
||||
geoip db region region WA;
|
||||
geoip city "San Francisco";
|
||||
geoip region Oklahoma;
|
||||
geoip postal 95062;
|
||||
geoip tz "America/Los_Angeles";
|
||||
geoip org "Internet Systems Consortium";
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
ACLs use a "first-match" logic rather than "best-match":
|
||||
if an address prefix matches an ACL element, then that ACL
|
||||
is considered to have matched even if a later element would
|
||||
have matched more specifically. For example, the ACL
|
||||
<command> { 10/8; !10.0.0.1; }</command> would actually
|
||||
match a query from 10.0.0.1, because the first element
|
||||
indicated that the query should be accepted, and the second
|
||||
element is ignored.
|
||||
</para>
|
||||
<para>
|
||||
When using "nested" ACLs (that is, ACLs included or referenced
|
||||
within other ACLs), a negative match of a nested ACL will
|
||||
the containing ACL to continue looking for matches. This
|
||||
enables complex ACLs to be constructed, in which multiple
|
||||
client characteristics can be checked at the same time. For
|
||||
example, to construct an ACL which allows queries only when
|
||||
it originates from a particular network <emphasis>and</emphasis>
|
||||
only when it is signed with a particular key, use:
|
||||
</para>
|
||||
<programlisting>
|
||||
allow-query { !{ !10/8; any; }; key example; };
|
||||
</programlisting>
|
||||
<para>
|
||||
Within the nested ACL, any address that is
|
||||
<emphasis>not</emphasis> in the 10/8 network prefix will
|
||||
be rejected, and this will terminate processing of the
|
||||
ACL. Any address that <emphasis>is</emphasis> in the 10/8
|
||||
network prefix will be accepted, but this causes a negative
|
||||
match of the nested ACL, so the containing ACL continues
|
||||
processing. The query will then be accepted if it is signed
|
||||
by the key "example", and rejected otherwise. The ACL, then,
|
||||
will only matches when <emphasis>both</emphasis> conditions
|
||||
are true.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title><command>Chroot</command> and <command>Setuid</command></title>
|
||||
<para>
|
||||
|
@ -24,10 +24,12 @@
|
||||
#include <isc/base64.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/file.h>
|
||||
#include <isc/hex.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/netaddr.h>
|
||||
#include <isc/parseint.h>
|
||||
#include <isc/platform.h>
|
||||
#include <isc/region.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/sockaddr.h>
|
||||
@ -35,6 +37,18 @@
|
||||
#include <isc/symtab.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#ifdef ISC_PLATFORM_USESIT
|
||||
#ifdef AES_SIT
|
||||
#include <isc/aes.h>
|
||||
#endif
|
||||
#ifdef HMAC_SHA1_SIT
|
||||
#include <isc/sha1.h>
|
||||
#endif
|
||||
#ifdef HMAC_SHA256_SIT
|
||||
#include <isc/sha2.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <dns/acl.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/rdataclass.h>
|
||||
@ -1186,6 +1200,52 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
|
||||
"(%d seconds)", recheck, lifetime);
|
||||
}
|
||||
|
||||
#ifdef ISC_PLATFORM_USESIT
|
||||
obj = NULL;
|
||||
(void) cfg_map_get(options, "sit-secret", &obj);
|
||||
if (obj != NULL) {
|
||||
isc_buffer_t b;
|
||||
unsigned char secret[32];
|
||||
|
||||
memset(secret, 0, sizeof(secret));
|
||||
isc_buffer_init(&b, secret, sizeof(secret));
|
||||
tresult = isc_hex_decodestring(cfg_obj_asstring(obj), &b);
|
||||
if (tresult == ISC_R_NOSPACE) {
|
||||
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
||||
"sit-secret: too long");
|
||||
} else if (tresult != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
||||
"sit-secret: invalid hex string");
|
||||
}
|
||||
if (tresult != ISC_R_SUCCESS)
|
||||
result = tresult;
|
||||
#ifdef AES_SIT
|
||||
if (tresult == ISC_R_SUCCESS &&
|
||||
isc_buffer_usedlength(&b) != ISC_AES128_KEYLENGTH) {
|
||||
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
||||
"AES sit-secret must be on 128 bits");
|
||||
result = ISC_R_RANGE;
|
||||
}
|
||||
#endif
|
||||
#ifdef HMAC_SHA1_SIT
|
||||
if (tresult == ISC_R_SUCCESS &&
|
||||
isc_buffer_usedlength(&b) != ISC_SHA1_DIGESTLENGTH) {
|
||||
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
||||
"SHA1 sit-secret must be on 160 bits");
|
||||
result = ISC_R_RANGE;
|
||||
}
|
||||
#endif
|
||||
#ifdef HMAC_SHA256_SIT
|
||||
if (tresult == ISC_R_SUCCESS &&
|
||||
isc_buffer_usedlength(&b) != ISC_SHA256_DIGESTLENGTH) {
|
||||
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
|
||||
"SHA256 sit-secret must be on 256 bits");
|
||||
result = ISC_R_RANGE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
139
lib/dns/acl.c
139
lib/dns/acl.c
@ -15,8 +15,6 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: acl.c,v 1.55 2011/06/17 23:47:49 tbox Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include <config.h>
|
||||
@ -194,10 +192,25 @@ dns_acl_match(const isc_netaddr_t *reqaddr,
|
||||
int *match,
|
||||
const dns_aclelement_t **matchelt)
|
||||
{
|
||||
isc_uint16_t bitlen, family;
|
||||
return (dns_acl_match2(reqaddr, reqsigner, NULL, 0, NULL, acl, env,
|
||||
match, matchelt));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_acl_match2(const isc_netaddr_t *reqaddr,
|
||||
const dns_name_t *reqsigner,
|
||||
const isc_netaddr_t *ecs,
|
||||
isc_uint8_t ecslen,
|
||||
isc_uint8_t *scope,
|
||||
const dns_acl_t *acl,
|
||||
const dns_aclenv_t *env,
|
||||
int *match,
|
||||
const dns_aclelement_t **matchelt)
|
||||
{
|
||||
isc_uint16_t bitlen;
|
||||
isc_prefix_t pfx;
|
||||
isc_radix_node_t *node = NULL;
|
||||
const isc_netaddr_t *addr;
|
||||
const isc_netaddr_t *addr = reqaddr;
|
||||
isc_netaddr_t v4addr;
|
||||
isc_result_t result;
|
||||
int match_num = -1;
|
||||
@ -205,20 +218,19 @@ dns_acl_match(const isc_netaddr_t *reqaddr,
|
||||
|
||||
REQUIRE(reqaddr != NULL);
|
||||
REQUIRE(matchelt == NULL || *matchelt == NULL);
|
||||
REQUIRE(ecs != NULL || scope == NULL);
|
||||
|
||||
if (env == NULL || env->match_mapped == ISC_FALSE ||
|
||||
reqaddr->family != AF_INET6 ||
|
||||
!IN6_IS_ADDR_V4MAPPED(&reqaddr->type.in6))
|
||||
addr = reqaddr;
|
||||
else {
|
||||
isc_netaddr_fromv4mapped(&v4addr, reqaddr);
|
||||
if (env != NULL && env->match_mapped &&
|
||||
addr->family == AF_INET6 &&
|
||||
IN6_IS_ADDR_V4MAPPED(&addr->type.in6))
|
||||
{
|
||||
isc_netaddr_fromv4mapped(&v4addr, addr);
|
||||
addr = &v4addr;
|
||||
}
|
||||
|
||||
/* Always match with host addresses. */
|
||||
family = addr->family;
|
||||
bitlen = family == AF_INET6 ? 128 : 32;
|
||||
NETADDR_TO_PREFIX_T(addr, pfx, bitlen);
|
||||
bitlen = (addr->family == AF_INET6) ? 128 : 32;
|
||||
NETADDR_TO_PREFIX_T(addr, pfx, bitlen, ISC_FALSE);
|
||||
|
||||
/* Assume no match. */
|
||||
*match = 0;
|
||||
@ -228,37 +240,75 @@ dns_acl_match(const isc_netaddr_t *reqaddr,
|
||||
|
||||
/* Found a match. */
|
||||
if (result == ISC_R_SUCCESS && node != NULL) {
|
||||
match_num = node->node_num[ISC_IS6(family)];
|
||||
if (*(isc_boolean_t *) node->data[ISC_IS6(family)] == ISC_TRUE)
|
||||
int off = ISC_RADIX_OFF(&pfx);
|
||||
match_num = node->node_num[off];
|
||||
if (*(isc_boolean_t *) node->data[off])
|
||||
*match = match_num;
|
||||
else
|
||||
*match = -match_num;
|
||||
}
|
||||
|
||||
isc_refcount_destroy(&pfx.refcount);
|
||||
|
||||
/*
|
||||
* If ecs is not NULL, we search the radix tree again to
|
||||
* see if we find a better match on an ECS node
|
||||
*/
|
||||
if (ecs != NULL) {
|
||||
node = NULL;
|
||||
addr = ecs;
|
||||
|
||||
if (env != NULL && env->match_mapped &&
|
||||
addr->family == AF_INET6 &&
|
||||
IN6_IS_ADDR_V4MAPPED(&addr->type.in6))
|
||||
{
|
||||
isc_netaddr_fromv4mapped(&v4addr, addr);
|
||||
addr = &v4addr;
|
||||
}
|
||||
|
||||
NETADDR_TO_PREFIX_T(addr, pfx, ecslen, ISC_TRUE);
|
||||
|
||||
result = isc_radix_search(acl->iptable->radix, &node, &pfx);
|
||||
if (result == ISC_R_SUCCESS && node != NULL) {
|
||||
int off = ISC_RADIX_OFF(&pfx);
|
||||
if (match_num == -1 ||
|
||||
node->node_num[off] < match_num)
|
||||
{
|
||||
match_num = node->node_num[off];
|
||||
if (scope != NULL)
|
||||
*scope = node->bit;
|
||||
if (*(isc_boolean_t *) node->data[off])
|
||||
*match = match_num;
|
||||
else
|
||||
*match = -match_num;
|
||||
}
|
||||
}
|
||||
|
||||
isc_refcount_destroy(&pfx.refcount);
|
||||
}
|
||||
|
||||
/* Now search non-radix elements for a match with a lower node_num. */
|
||||
for (i = 0; i < acl->length; i++) {
|
||||
dns_aclelement_t *e = &acl->elements[i];
|
||||
|
||||
/* Already found a better match? */
|
||||
if (match_num != -1 && match_num < e->node_num) {
|
||||
isc_refcount_destroy(&pfx.refcount);
|
||||
return (ISC_R_SUCCESS);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dns_aclelement_match(reqaddr, reqsigner,
|
||||
e, env, matchelt)) {
|
||||
if (dns_aclelement_match2(reqaddr, reqsigner, ecs, ecslen,
|
||||
scope, e, env, matchelt))
|
||||
{
|
||||
if (match_num == -1 || e->node_num < match_num) {
|
||||
if (e->negative == ISC_TRUE)
|
||||
if (e->negative)
|
||||
*match = -e->node_num;
|
||||
else
|
||||
*match = e->node_num;
|
||||
}
|
||||
isc_refcount_destroy(&pfx.refcount);
|
||||
return (ISC_R_SUCCESS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
isc_refcount_destroy(&pfx.refcount);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
@ -349,7 +399,7 @@ dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos)
|
||||
#endif
|
||||
|
||||
/* reverse sense of positives if this is a negative acl */
|
||||
if (!pos && source->elements[i].negative == ISC_FALSE) {
|
||||
if (!pos && !source->elements[i].negative) {
|
||||
dest->elements[nelem + i].negative = ISC_TRUE;
|
||||
} else {
|
||||
dest->elements[nelem + i].negative =
|
||||
@ -386,10 +436,29 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr,
|
||||
const dns_aclelement_t *e,
|
||||
const dns_aclenv_t *env,
|
||||
const dns_aclelement_t **matchelt)
|
||||
{
|
||||
return (dns_aclelement_match2(reqaddr, reqsigner, NULL, 0, NULL,
|
||||
e, env, matchelt));
|
||||
}
|
||||
|
||||
isc_boolean_t
|
||||
dns_aclelement_match2(const isc_netaddr_t *reqaddr,
|
||||
const dns_name_t *reqsigner,
|
||||
const isc_netaddr_t *ecs,
|
||||
isc_uint8_t ecslen,
|
||||
isc_uint8_t *scope,
|
||||
const dns_aclelement_t *e,
|
||||
const dns_aclenv_t *env,
|
||||
const dns_aclelement_t **matchelt)
|
||||
{
|
||||
dns_acl_t *inner = NULL;
|
||||
int indirectmatch;
|
||||
isc_result_t result;
|
||||
#ifdef HAVE_GEOIP
|
||||
const isc_netaddr_t *addr = NULL;
|
||||
#endif
|
||||
|
||||
REQUIRE(ecs != NULL || scope == NULL);
|
||||
|
||||
switch (e->type) {
|
||||
case dns_aclelementtype_keyname:
|
||||
@ -421,15 +490,17 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr,
|
||||
case dns_aclelementtype_geoip:
|
||||
if (env == NULL || env->geoip == NULL)
|
||||
return (ISC_FALSE);
|
||||
return (dns_geoip_match(reqaddr, env->geoip, &e->geoip_elem));
|
||||
addr = (env->geoip_use_ecs && ecs != NULL) ? ecs : reqaddr;
|
||||
return (dns_geoip_match(addr, scope, env->geoip,
|
||||
&e->geoip_elem));
|
||||
#endif
|
||||
default:
|
||||
/* Should be impossible. */
|
||||
INSIST(0);
|
||||
}
|
||||
|
||||
result = dns_acl_match(reqaddr, reqsigner, inner, env,
|
||||
&indirectmatch, matchelt);
|
||||
result = dns_acl_match2(reqaddr, reqsigner, ecs, ecslen, scope,
|
||||
inner, env, &indirectmatch, matchelt);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
@ -438,7 +509,6 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr,
|
||||
* surprise positive match through double negation.
|
||||
* XXXDCL this should be documented.
|
||||
*/
|
||||
|
||||
if (indirectmatch > 0) {
|
||||
if (matchelt != NULL)
|
||||
*matchelt = e;
|
||||
@ -449,7 +519,6 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr,
|
||||
* A negative indirect match may have set *matchelt, but we don't
|
||||
* want it set when we return.
|
||||
*/
|
||||
|
||||
if (matchelt != NULL)
|
||||
*matchelt = NULL;
|
||||
|
||||
@ -519,17 +588,15 @@ initialize_action(void) {
|
||||
*/
|
||||
static void
|
||||
is_insecure(isc_prefix_t *prefix, void **data) {
|
||||
isc_boolean_t secure;
|
||||
int bitlen, family;
|
||||
int bitlen, family, off;
|
||||
|
||||
bitlen = prefix->bitlen;
|
||||
family = prefix->family;
|
||||
|
||||
/* Negated entries are always secure. */
|
||||
secure = * (isc_boolean_t *)data[ISC_IS6(family)];
|
||||
if (!secure) {
|
||||
off = ISC_RADIX_OFF(prefix);
|
||||
if (data[off] != NULL && * (isc_boolean_t *) data[off])
|
||||
return;
|
||||
}
|
||||
|
||||
/* If loopback prefix found, return */
|
||||
switch (family) {
|
||||
@ -628,6 +695,7 @@ dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) {
|
||||
env->match_mapped = ISC_FALSE;
|
||||
#ifdef HAVE_GEOIP
|
||||
env->geoip = NULL;
|
||||
env->geoip_use_ecs = ISC_FALSE;
|
||||
#endif
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
@ -644,6 +712,9 @@ dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s) {
|
||||
dns_acl_detach(&t->localnets);
|
||||
dns_acl_attach(s->localnets, &t->localnets);
|
||||
t->match_mapped = s->match_mapped;
|
||||
#ifdef HAVE_GEOIP
|
||||
t->geoip_use_ecs = s->geoip_use_ecs;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
142
lib/dns/geoip.c
142
lib/dns/geoip.c
@ -72,6 +72,7 @@ typedef struct geoip_state {
|
||||
unsigned int family;
|
||||
isc_uint32_t ipnum;
|
||||
geoipv6_t ipnum6;
|
||||
isc_uint8_t scope;
|
||||
GeoIPRecord *record;
|
||||
GeoIPRegion *region;
|
||||
const char *text;
|
||||
@ -157,7 +158,7 @@ clean_state(geoip_state_t *state) {
|
||||
|
||||
static isc_result_t
|
||||
set_state(unsigned int family, isc_uint32_t ipnum, const geoipv6_t *ipnum6,
|
||||
dns_geoip_subtype_t subtype, GeoIPRecord *record,
|
||||
isc_uint8_t scope, dns_geoip_subtype_t subtype, GeoIPRecord *record,
|
||||
GeoIPRegion *region, char *name, const char *text, int id)
|
||||
{
|
||||
isc_result_t result;
|
||||
@ -198,6 +199,7 @@ set_state(unsigned int family, isc_uint32_t ipnum, const geoipv6_t *ipnum6,
|
||||
|
||||
state->family = family;
|
||||
state->subtype = subtype;
|
||||
state->scope = scope;
|
||||
state->record = record;
|
||||
state->region = region;
|
||||
state->name = name;
|
||||
@ -232,10 +234,12 @@ get_state(void) {
|
||||
static const char *
|
||||
country_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
|
||||
unsigned int family,
|
||||
isc_uint32_t ipnum, const geoipv6_t *ipnum6)
|
||||
isc_uint32_t ipnum, const geoipv6_t *ipnum6,
|
||||
isc_uint8_t *scope)
|
||||
{
|
||||
geoip_state_t *prev_state = NULL;
|
||||
const char *text = NULL;
|
||||
GeoIPLookup gl;
|
||||
|
||||
REQUIRE(db != NULL);
|
||||
|
||||
@ -253,42 +257,55 @@ country_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
|
||||
((prev_state->family == AF_INET && prev_state->ipnum == ipnum) ||
|
||||
(prev_state->family == AF_INET6 && ipnum6 != NULL &&
|
||||
memcmp(prev_state->ipnum6.s6_addr, ipnum6->s6_addr, 16) == 0)))
|
||||
{
|
||||
text = prev_state->text;
|
||||
if (scope != NULL)
|
||||
*scope = prev_state->scope;
|
||||
}
|
||||
|
||||
if (text == NULL) {
|
||||
switch (subtype) {
|
||||
case dns_geoip_country_code:
|
||||
if (family == AF_INET)
|
||||
text = GeoIP_country_code_by_ipnum(db, ipnum);
|
||||
text = GeoIP_country_code_by_ipnum_gl(db,
|
||||
ipnum, &gl);
|
||||
#ifdef HAVE_GEOIP_V6
|
||||
else
|
||||
text = GeoIP_country_code_by_ipnum_v6(db,
|
||||
*ipnum6);
|
||||
text = GeoIP_country_code_by_ipnum_v6_gl(db,
|
||||
*ipnum6, &gl);
|
||||
#endif
|
||||
break;
|
||||
case dns_geoip_country_code3:
|
||||
if (family == AF_INET)
|
||||
text = GeoIP_country_code3_by_ipnum(db, ipnum);
|
||||
text = GeoIP_country_code3_by_ipnum_gl(db,
|
||||
ipnum, &gl);
|
||||
#ifdef HAVE_GEOIP_V6
|
||||
else
|
||||
text = GeoIP_country_code3_by_ipnum_v6(db,
|
||||
*ipnum6);
|
||||
text = GeoIP_country_code3_by_ipnum_v6_gl(db,
|
||||
*ipnum6, &gl);
|
||||
#endif
|
||||
break;
|
||||
case dns_geoip_country_name:
|
||||
if (family == AF_INET)
|
||||
text = GeoIP_country_name_by_ipnum(db, ipnum);
|
||||
text = GeoIP_country_name_by_ipnum_gl(db,
|
||||
ipnum, &gl);
|
||||
#ifdef HAVE_GEOIP_V6
|
||||
else
|
||||
text = GeoIP_country_name_by_ipnum_v6(db,
|
||||
*ipnum6);
|
||||
text = GeoIP_country_name_by_ipnum_v6_gl(db,
|
||||
*ipnum6, &gl);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
}
|
||||
|
||||
set_state(family, ipnum, ipnum6, subtype,
|
||||
if (text == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (scope != NULL)
|
||||
*scope = gl.netmask;
|
||||
|
||||
set_state(family, ipnum, ipnum6, gl.netmask, subtype,
|
||||
NULL, NULL, NULL, text, 0);
|
||||
}
|
||||
|
||||
@ -377,7 +394,9 @@ is_city(dns_geoip_subtype_t subtype) {
|
||||
*/
|
||||
static GeoIPRecord *
|
||||
city_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
|
||||
unsigned int family, isc_uint32_t ipnum, const geoipv6_t *ipnum6)
|
||||
unsigned int family, isc_uint32_t ipnum,
|
||||
const geoipv6_t *ipnum6,
|
||||
isc_uint8_t *scope)
|
||||
{
|
||||
GeoIPRecord *record = NULL;
|
||||
geoip_state_t *prev_state = NULL;
|
||||
@ -397,7 +416,11 @@ city_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
|
||||
((prev_state->family == AF_INET && prev_state->ipnum == ipnum) ||
|
||||
(prev_state->family == AF_INET6 &&
|
||||
memcmp(prev_state->ipnum6.s6_addr, ipnum6->s6_addr, 16) == 0)))
|
||||
{
|
||||
record = prev_state->record;
|
||||
if (scope != NULL)
|
||||
*scope = record->netmask;
|
||||
}
|
||||
|
||||
if (record == NULL) {
|
||||
if (family == AF_INET)
|
||||
@ -409,15 +432,17 @@ city_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
|
||||
if (record == NULL)
|
||||
return (NULL);
|
||||
|
||||
set_state(family, ipnum, ipnum6, subtype,
|
||||
if (scope != NULL)
|
||||
*scope = record->netmask;
|
||||
|
||||
set_state(family, ipnum, ipnum6, record->netmask, subtype,
|
||||
record, NULL, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
return (record);
|
||||
}
|
||||
|
||||
static char *
|
||||
region_string(GeoIPRegion *region, dns_geoip_subtype_t subtype, int *maxlen) {
|
||||
static char * region_string(GeoIPRegion *region, dns_geoip_subtype_t subtype, int *maxlen) {
|
||||
const char *s;
|
||||
char *deconst;
|
||||
|
||||
@ -459,9 +484,12 @@ is_region(dns_geoip_subtype_t subtype) {
|
||||
* outside the Region database.
|
||||
*/
|
||||
static GeoIPRegion *
|
||||
region_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) {
|
||||
region_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
|
||||
isc_uint32_t ipnum, isc_uint8_t *scope)
|
||||
{
|
||||
GeoIPRegion *region = NULL;
|
||||
geoip_state_t *prev_state = NULL;
|
||||
GeoIPLookup gl;
|
||||
|
||||
REQUIRE(db != NULL);
|
||||
|
||||
@ -469,14 +497,21 @@ region_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) {
|
||||
|
||||
if (prev_state != NULL && prev_state->ipnum == ipnum &&
|
||||
is_region(prev_state->subtype))
|
||||
{
|
||||
region = prev_state->region;
|
||||
if (scope != NULL)
|
||||
*scope = prev_state->scope;
|
||||
}
|
||||
|
||||
if (region == NULL) {
|
||||
region = GeoIP_region_by_ipnum(db, ipnum);
|
||||
region = GeoIP_region_by_ipnum_gl(db, ipnum, &gl);
|
||||
if (region == NULL)
|
||||
return (NULL);
|
||||
|
||||
set_state(AF_INET, ipnum, NULL,
|
||||
if (scope != NULL)
|
||||
*scope = gl.netmask;
|
||||
|
||||
set_state(AF_INET, ipnum, NULL, gl.netmask,
|
||||
subtype, NULL, region, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
@ -489,9 +524,12 @@ region_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) {
|
||||
* or was for a search of a different subtype.
|
||||
*/
|
||||
static char *
|
||||
name_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) {
|
||||
name_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
|
||||
isc_uint32_t ipnum, isc_uint8_t *scope)
|
||||
{
|
||||
char *name = NULL;
|
||||
geoip_state_t *prev_state = NULL;
|
||||
GeoIPLookup gl;
|
||||
|
||||
REQUIRE(db != NULL);
|
||||
|
||||
@ -499,14 +537,21 @@ name_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) {
|
||||
|
||||
if (prev_state != NULL && prev_state->ipnum == ipnum &&
|
||||
prev_state->subtype == subtype)
|
||||
{
|
||||
name = prev_state->name;
|
||||
if (scope != NULL)
|
||||
*scope = prev_state->scope;
|
||||
}
|
||||
|
||||
if (name == NULL) {
|
||||
name = GeoIP_name_by_ipnum(db, ipnum);
|
||||
name = GeoIP_name_by_ipnum_gl(db, ipnum, &gl);
|
||||
if (name == NULL)
|
||||
return (NULL);
|
||||
|
||||
set_state(AF_INET, ipnum, NULL,
|
||||
if (scope != NULL)
|
||||
*scope = gl.netmask;
|
||||
|
||||
set_state(AF_INET, ipnum, NULL, gl.netmask,
|
||||
subtype, NULL, NULL, name, NULL, 0);
|
||||
}
|
||||
|
||||
@ -519,9 +564,12 @@ name_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) {
|
||||
* different subtype.
|
||||
*/
|
||||
static int
|
||||
netspeed_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) {
|
||||
netspeed_lookup(GeoIP *db, dns_geoip_subtype_t subtype,
|
||||
isc_uint32_t ipnum, isc_uint8_t *scope)
|
||||
{
|
||||
geoip_state_t *prev_state = NULL;
|
||||
isc_boolean_t found = ISC_FALSE;
|
||||
GeoIPLookup gl;
|
||||
int id = -1;
|
||||
|
||||
REQUIRE(db != NULL);
|
||||
@ -531,12 +579,20 @@ netspeed_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) {
|
||||
if (prev_state != NULL && prev_state->ipnum == ipnum &&
|
||||
prev_state->subtype == subtype) {
|
||||
id = prev_state->id;
|
||||
if (scope != NULL)
|
||||
*scope = prev_state->scope;
|
||||
found = ISC_TRUE;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
id = GeoIP_id_by_ipnum(db, ipnum);
|
||||
set_state(AF_INET, ipnum, NULL,
|
||||
id = GeoIP_id_by_ipnum_gl(db, ipnum, &gl);
|
||||
if (id == 0)
|
||||
return (0);
|
||||
|
||||
if (scope != NULL)
|
||||
*scope = gl.netmask;
|
||||
|
||||
set_state(AF_INET, ipnum, NULL, gl.netmask,
|
||||
subtype, NULL, NULL, NULL, NULL, id);
|
||||
}
|
||||
|
||||
@ -599,7 +655,7 @@ fix_subtype(const isc_netaddr_t *reqaddr, const dns_geoip_databases_t *geoip,
|
||||
#endif /* HAVE_GEOIP */
|
||||
|
||||
isc_boolean_t
|
||||
dns_geoip_match(const isc_netaddr_t *reqaddr,
|
||||
dns_geoip_match(const isc_netaddr_t *reqaddr, isc_uint8_t *scope,
|
||||
const dns_geoip_databases_t *geoip,
|
||||
const dns_geoip_elem_t *elt)
|
||||
{
|
||||
@ -662,7 +718,7 @@ dns_geoip_match(const isc_netaddr_t *reqaddr,
|
||||
|
||||
INSIST(elt->as_string != NULL);
|
||||
|
||||
cs = country_lookup(db, subtype, family, ipnum, ipnum6);
|
||||
cs = country_lookup(db, subtype, family, ipnum, ipnum6, scope);
|
||||
if (cs != NULL && strncasecmp(elt->as_string, cs, maxlen) == 0)
|
||||
return (ISC_TRUE);
|
||||
break;
|
||||
@ -682,7 +738,8 @@ dns_geoip_match(const isc_netaddr_t *reqaddr,
|
||||
if (db == NULL)
|
||||
return (ISC_FALSE);
|
||||
|
||||
record = city_lookup(db, subtype, family, ipnum, ipnum6);
|
||||
record = city_lookup(db, subtype, family,
|
||||
ipnum, ipnum6, scope);
|
||||
if (record == NULL)
|
||||
break;
|
||||
|
||||
@ -697,7 +754,8 @@ dns_geoip_match(const isc_netaddr_t *reqaddr,
|
||||
if (db == NULL)
|
||||
return (ISC_FALSE);
|
||||
|
||||
record = city_lookup(db, subtype, family, ipnum, ipnum6);
|
||||
record = city_lookup(db, subtype, family,
|
||||
ipnum, ipnum6, scope);
|
||||
if (record == NULL)
|
||||
break;
|
||||
|
||||
@ -710,7 +768,8 @@ dns_geoip_match(const isc_netaddr_t *reqaddr,
|
||||
if (db == NULL)
|
||||
return (ISC_FALSE);
|
||||
|
||||
record = city_lookup(db, subtype, family, ipnum, ipnum6);
|
||||
record = city_lookup(db, subtype, family,
|
||||
ipnum, ipnum6, scope);
|
||||
if (record == NULL)
|
||||
break;
|
||||
|
||||
@ -731,7 +790,7 @@ dns_geoip_match(const isc_netaddr_t *reqaddr,
|
||||
if (family == AF_INET6)
|
||||
return (ISC_FALSE);
|
||||
|
||||
region = region_lookup(geoip->region, subtype, ipnum);
|
||||
region = region_lookup(geoip->region, subtype, ipnum, scope);
|
||||
if (region == NULL)
|
||||
break;
|
||||
|
||||
@ -765,9 +824,22 @@ dns_geoip_match(const isc_netaddr_t *reqaddr,
|
||||
if (family == AF_INET6)
|
||||
return (ISC_FALSE);
|
||||
|
||||
s = name_lookup(db, subtype, ipnum);
|
||||
if (s != NULL && strcasecmp(elt->as_string, s) == 0)
|
||||
return (ISC_TRUE);
|
||||
s = name_lookup(db, subtype, ipnum, scope);
|
||||
if (s != NULL) {
|
||||
size_t l;
|
||||
if (strcasecmp(elt->as_string, s) == 0)
|
||||
return (ISC_TRUE);
|
||||
if (subtype != dns_geoip_as_asnum)
|
||||
break;
|
||||
/*
|
||||
* Just check if the ASNNNN value matches.
|
||||
*/
|
||||
l = strlen(elt->as_string);
|
||||
if (l > 0U && strchr(elt->as_string, ' ') == NULL &&
|
||||
strncasecmp(elt->as_string, s, l) == 0 &&
|
||||
s[l] == ' ')
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
break;
|
||||
|
||||
case dns_geoip_netspeed_id:
|
||||
@ -777,7 +849,7 @@ dns_geoip_match(const isc_netaddr_t *reqaddr,
|
||||
if (family == AF_INET6)
|
||||
return (ISC_FALSE);
|
||||
|
||||
id = netspeed_lookup(geoip->netspeed, subtype, ipnum);
|
||||
id = netspeed_lookup(geoip->netspeed, subtype, ipnum, scope);
|
||||
if (id == elt->as_int)
|
||||
return (ISC_TRUE);
|
||||
break;
|
||||
|
@ -103,6 +103,7 @@ struct dns_aclenv {
|
||||
isc_boolean_t match_mapped;
|
||||
#ifdef HAVE_GEOIP
|
||||
dns_geoip_databases_t *geoip;
|
||||
isc_boolean_t geoip_use_ecs;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -212,12 +213,28 @@ dns_acl_match(const isc_netaddr_t *reqaddr,
|
||||
const dns_aclenv_t *env,
|
||||
int *match,
|
||||
const dns_aclelement_t **matchelt);
|
||||
|
||||
isc_result_t
|
||||
dns_acl_match2(const isc_netaddr_t *reqaddr,
|
||||
const dns_name_t *reqsigner,
|
||||
const isc_netaddr_t *ecs,
|
||||
isc_uint8_t ecslen,
|
||||
isc_uint8_t *scope,
|
||||
const dns_acl_t *acl,
|
||||
const dns_aclenv_t *env,
|
||||
int *match,
|
||||
const dns_aclelement_t **matchelt);
|
||||
/*%<
|
||||
* General, low-level ACL matching. This is expected to
|
||||
* be useful even for weird stuff like the topology and sortlist statements.
|
||||
*
|
||||
* Match the address 'reqaddr', and optionally the key name 'reqsigner',
|
||||
* against 'acl'. 'reqsigner' may be NULL.
|
||||
* and optionally the client prefix 'ecs' of length 'ecslen'
|
||||
* (reported via EDNS client subnet option) against 'acl'.
|
||||
*
|
||||
* 'reqsigner' and 'ecs' may be NULL. If an ACL matches against 'ecs'
|
||||
* and 'ecslen', then 'scope' will be set to indicate the netmask that
|
||||
* matched.
|
||||
*
|
||||
* If there is a match, '*match' will be set to an integer whose absolute
|
||||
* value corresponds to the order in which the matching value was inserted
|
||||
@ -244,6 +261,16 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr,
|
||||
const dns_aclelement_t *e,
|
||||
const dns_aclenv_t *env,
|
||||
const dns_aclelement_t **matchelt);
|
||||
|
||||
isc_boolean_t
|
||||
dns_aclelement_match2(const isc_netaddr_t *reqaddr,
|
||||
const dns_name_t *reqsigner,
|
||||
const isc_netaddr_t *ecs,
|
||||
isc_uint8_t ecslen,
|
||||
isc_uint8_t *scope,
|
||||
const dns_aclelement_t *e,
|
||||
const dns_aclenv_t *env,
|
||||
const dns_aclelement_t **matchelt);
|
||||
/*%<
|
||||
* Like dns_acl_match, but matches against the single ACL element 'e'
|
||||
* rather than a complete ACL, and returns ISC_TRUE iff it matched.
|
||||
|
@ -108,7 +108,7 @@ typedef struct dns_geoip_databases {
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
isc_boolean_t
|
||||
dns_geoip_match(const isc_netaddr_t *reqaddr,
|
||||
dns_geoip_match(const isc_netaddr_t *reqaddr, isc_uint8_t *scope,
|
||||
const dns_geoip_databases_t *geoip,
|
||||
const dns_geoip_elem_t *elt);
|
||||
|
||||
|
@ -51,6 +51,10 @@ dns_iptable_create(isc_mem_t *mctx, dns_iptable_t **target);
|
||||
isc_result_t
|
||||
dns_iptable_addprefix(dns_iptable_t *tab, isc_netaddr_t *addr,
|
||||
isc_uint16_t bitlen, isc_boolean_t pos);
|
||||
isc_result_t
|
||||
dns_iptable_addprefix2(dns_iptable_t *tab, isc_netaddr_t *addr,
|
||||
isc_uint16_t bitlen, isc_boolean_t pos,
|
||||
isc_boolean_t is_ecs);
|
||||
/*
|
||||
* Add an IP prefix to an existing IP table
|
||||
*/
|
||||
|
@ -112,7 +112,7 @@
|
||||
#define DNS_OPT_SIT 65001 /*%< SIT opt code */
|
||||
|
||||
/*%< The number of EDNS options we know about. */
|
||||
#define DNS_EDNSOPTIONS 4
|
||||
#define DNS_EDNSOPTIONS 5
|
||||
|
||||
#define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD|DNS_MESSAGEFLAG_CD)
|
||||
#define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO)
|
||||
|
@ -14,8 +14,6 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: iptable.c,v 1.15 2009/02/18 23:47:48 tbox Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <isc/mem.h>
|
||||
@ -63,16 +61,24 @@ isc_boolean_t dns_iptable_pos = ISC_TRUE;
|
||||
isc_result_t
|
||||
dns_iptable_addprefix(dns_iptable_t *tab, isc_netaddr_t *addr,
|
||||
isc_uint16_t bitlen, isc_boolean_t pos)
|
||||
{
|
||||
return(dns_iptable_addprefix2(tab, addr, bitlen, pos, ISC_FALSE));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_iptable_addprefix2(dns_iptable_t *tab, isc_netaddr_t *addr,
|
||||
isc_uint16_t bitlen, isc_boolean_t pos,
|
||||
isc_boolean_t is_ecs)
|
||||
{
|
||||
isc_result_t result;
|
||||
isc_prefix_t pfx;
|
||||
isc_radix_node_t *node = NULL;
|
||||
int family;
|
||||
int i;
|
||||
|
||||
INSIST(DNS_IPTABLE_VALID(tab));
|
||||
INSIST(tab->radix);
|
||||
|
||||
NETADDR_TO_PREFIX_T(addr, pfx, bitlen);
|
||||
NETADDR_TO_PREFIX_T(addr, pfx, bitlen, is_ecs);
|
||||
|
||||
result = isc_radix_insert(tab->radix, &node, NULL, &pfx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
@ -81,28 +87,20 @@ dns_iptable_addprefix(dns_iptable_t *tab, isc_netaddr_t *addr,
|
||||
}
|
||||
|
||||
/* If a node already contains data, don't overwrite it */
|
||||
family = pfx.family;
|
||||
if (family == AF_UNSPEC) {
|
||||
if (pfx.family == AF_UNSPEC) {
|
||||
/* "any" or "none" */
|
||||
INSIST(pfx.bitlen == 0);
|
||||
if (pos) {
|
||||
if (node->data[0] == NULL)
|
||||
node->data[0] = &dns_iptable_pos;
|
||||
if (node->data[1] == NULL)
|
||||
node->data[1] = &dns_iptable_pos;
|
||||
} else {
|
||||
if (node->data[0] == NULL)
|
||||
node->data[0] = &dns_iptable_neg;
|
||||
if (node->data[1] == NULL)
|
||||
node->data[1] = &dns_iptable_neg;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (node->data[i] == NULL)
|
||||
node->data[i] = pos ? &dns_iptable_pos
|
||||
: &dns_iptable_neg;
|
||||
}
|
||||
} else {
|
||||
/* any other prefix */
|
||||
if (node->data[ISC_IS6(family)] == NULL) {
|
||||
if (pos)
|
||||
node->data[ISC_IS6(family)] = &dns_iptable_pos;
|
||||
else
|
||||
node->data[ISC_IS6(family)] = &dns_iptable_neg;
|
||||
int offset = ISC_RADIX_OFF(&pfx);
|
||||
if (node->data[offset] == NULL) {
|
||||
node->data[offset] = pos ? &dns_iptable_pos
|
||||
: &dns_iptable_neg;
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,7 +116,7 @@ dns_iptable_merge(dns_iptable_t *tab, dns_iptable_t *source, isc_boolean_t pos)
|
||||
{
|
||||
isc_result_t result;
|
||||
isc_radix_node_t *node, *new_node;
|
||||
int max_node = 0;
|
||||
int i, max_node = 0;
|
||||
|
||||
RADIX_WALK (source->radix->head, node) {
|
||||
new_node = NULL;
|
||||
@ -135,20 +133,15 @@ dns_iptable_merge(dns_iptable_t *tab, dns_iptable_t *source, isc_boolean_t pos)
|
||||
* could be a security risk. To prevent this, we
|
||||
* just leave the negative nodes negative.
|
||||
*/
|
||||
if (!pos) {
|
||||
if (node->data[0] &&
|
||||
*(isc_boolean_t *) node->data[0] == ISC_TRUE)
|
||||
new_node->data[0] = &dns_iptable_neg;
|
||||
|
||||
if (node->data[1] &&
|
||||
*(isc_boolean_t *) node->data[1] == ISC_TRUE)
|
||||
new_node->data[1] = &dns_iptable_neg;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (!pos) {
|
||||
if (node->data[i] &&
|
||||
*(isc_boolean_t *) node->data[i])
|
||||
new_node->data[i] = &dns_iptable_neg;
|
||||
}
|
||||
if (node->node_num[i] > max_node)
|
||||
max_node = node->node_num[i];
|
||||
}
|
||||
|
||||
if (node->node_num[0] > max_node)
|
||||
max_node = node->node_num[0];
|
||||
if (node->node_num[1] > max_node)
|
||||
max_node = node->node_num[1];
|
||||
} RADIX_WALK_END;
|
||||
|
||||
tab->radix->num_added_node += max_node;
|
||||
|
@ -15,8 +15,6 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
/***
|
||||
|
@ -80,11 +80,13 @@
|
||||
DNS_LOGMODULE_RESOLVER, \
|
||||
ISC_LOG_DEBUG(3), \
|
||||
"res %p: %s", (r), (m))
|
||||
#define FCTXTRACE(m) isc_log_write(dns_lctx, \
|
||||
#define FCTXTRACE(m) \
|
||||
isc_log_write(dns_lctx, \
|
||||
DNS_LOGCATEGORY_RESOLVER, \
|
||||
DNS_LOGMODULE_RESOLVER, \
|
||||
ISC_LOG_DEBUG(3), \
|
||||
"fctx %p(%s): %s", fctx, fctx->info, (m))
|
||||
"fctx %p(%s): %s", \
|
||||
fctx, fctx->info, (m))
|
||||
#define FCTXTRACE2(m1, m2) \
|
||||
isc_log_write(dns_lctx, \
|
||||
DNS_LOGCATEGORY_RESOLVER, \
|
||||
@ -92,6 +94,22 @@
|
||||
ISC_LOG_DEBUG(3), \
|
||||
"fctx %p(%s): %s %s", \
|
||||
fctx, fctx->info, (m1), (m2))
|
||||
#define FCTXTRACE3(m, res) \
|
||||
isc_log_write(dns_lctx, \
|
||||
DNS_LOGCATEGORY_RESOLVER, \
|
||||
DNS_LOGMODULE_RESOLVER, \
|
||||
ISC_LOG_DEBUG(3), \
|
||||
"fctx %p(%s): [result: %s] %s", \
|
||||
fctx, fctx->info, \
|
||||
isc_result_totext(res), (m))
|
||||
#define FCTXTRACE4(m1, m2, res) \
|
||||
isc_log_write(dns_lctx, \
|
||||
DNS_LOGCATEGORY_RESOLVER, \
|
||||
DNS_LOGMODULE_RESOLVER, \
|
||||
ISC_LOG_DEBUG(3), \
|
||||
"fctx %p(%s): [result: %s] %s %s", \
|
||||
fctx, fctx->info, \
|
||||
isc_result_totext(res), (m1), (m2))
|
||||
#define FTRACE(m) isc_log_write(dns_lctx, \
|
||||
DNS_LOGCATEGORY_RESOLVER, \
|
||||
DNS_LOGMODULE_RESOLVER, \
|
||||
@ -1268,6 +1286,9 @@ process_sendevent(resquery_t *query, isc_event_t *event) {
|
||||
case ISC_R_NOPERM:
|
||||
case ISC_R_ADDRNOTAVAIL:
|
||||
case ISC_R_CONNREFUSED:
|
||||
FCTXTRACE3("query canceled in sendevent(): "
|
||||
"no route to host; no response",
|
||||
sevent->result);
|
||||
|
||||
/*
|
||||
* No route to remote.
|
||||
@ -1279,6 +1300,10 @@ process_sendevent(resquery_t *query, isc_event_t *event) {
|
||||
break;
|
||||
|
||||
default:
|
||||
FCTXTRACE3("query canceled in sendevent() due to "
|
||||
"unexpected event result; responding",
|
||||
sevent->result);
|
||||
|
||||
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
|
||||
break;
|
||||
}
|
||||
@ -2359,6 +2384,9 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
|
||||
isc_interval_set(&interval, 20, 0);
|
||||
result = fctx_startidletimer(query->fctx, &interval);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
FCTXTRACE("query canceled: idle timer failed; "
|
||||
"responding");
|
||||
|
||||
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
|
||||
fctx_done(fctx, result, __LINE__);
|
||||
break;
|
||||
@ -2395,6 +2423,9 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
|
||||
result = resquery_send(query);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
FCTXTRACE("query canceled: "
|
||||
"resquery_send() failed; responding");
|
||||
|
||||
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
|
||||
fctx_done(fctx, result, __LINE__);
|
||||
}
|
||||
@ -2406,6 +2437,10 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
|
||||
case ISC_R_NOPERM:
|
||||
case ISC_R_ADDRNOTAVAIL:
|
||||
case ISC_R_CONNECTIONRESET:
|
||||
FCTXTRACE3("query canceled in connected(): "
|
||||
"no route to host; no response",
|
||||
sevent->result);
|
||||
|
||||
/*
|
||||
* No route to remote.
|
||||
*/
|
||||
@ -2415,6 +2450,10 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
|
||||
break;
|
||||
|
||||
default:
|
||||
FCTXTRACE3("query canceled in connected() due to "
|
||||
"unexpected event result; responding",
|
||||
sevent->result);
|
||||
|
||||
isc_socket_detach(&query->tcpsocket);
|
||||
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
|
||||
break;
|
||||
@ -2495,11 +2534,12 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
|
||||
isc_event_free(&event);
|
||||
dns_adb_destroyfind(&find);
|
||||
|
||||
if (want_try)
|
||||
if (want_try) {
|
||||
fctx_try(fctx, ISC_TRUE, ISC_FALSE);
|
||||
else if (want_done)
|
||||
} else if (want_done) {
|
||||
FCTXTRACE("fetch failed in finddone(); return ISC_R_FAILURE");
|
||||
fctx_done(fctx, ISC_R_FAILURE, __LINE__);
|
||||
else if (destroy) {
|
||||
} else if (destroy) {
|
||||
fctx_destroy(fctx);
|
||||
if (bucket_empty)
|
||||
empty_bucket(res);
|
||||
@ -3479,6 +3519,7 @@ fctx_timeout(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
fctx->timeouts++;
|
||||
fctx->timeout = ISC_TRUE;
|
||||
|
||||
/*
|
||||
* We could cancel the running queries here, or we could let
|
||||
* them keep going. Since we normally use separate sockets for
|
||||
@ -3490,10 +3531,13 @@ fctx_timeout(isc_task_t *task, isc_event_t *event) {
|
||||
*/
|
||||
query = ISC_LIST_HEAD(fctx->queries);
|
||||
if (query != NULL &&
|
||||
isc_time_compare(&tevent->due, &query->start) >= 0) {
|
||||
isc_time_compare(&tevent->due, &query->start) >= 0)
|
||||
{
|
||||
FCTXTRACE("query timed out; no response");
|
||||
fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
|
||||
}
|
||||
fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
|
||||
|
||||
/*
|
||||
* Our timer has triggered. Reestablish the fctx lifetime
|
||||
* timer.
|
||||
@ -3777,7 +3821,6 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
|
||||
unsigned int findoptions = 0;
|
||||
char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
|
||||
char typebuf[DNS_RDATATYPE_FORMATSIZE];
|
||||
dns_name_t suffix;
|
||||
isc_mem_t *mctx;
|
||||
|
||||
/*
|
||||
@ -3789,6 +3832,11 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
|
||||
fctx = isc_mem_get(mctx, sizeof(*fctx));
|
||||
if (fctx == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
/*
|
||||
* Make fctx->info point to a copy of a formatted string
|
||||
* "name/type".
|
||||
*/
|
||||
dns_name_format(name, buf, sizeof(buf));
|
||||
dns_rdatatype_format(type, typebuf, sizeof(typebuf));
|
||||
strcat(buf, "/"); /* checked */
|
||||
@ -3798,6 +3846,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup_fetch;
|
||||
}
|
||||
|
||||
FCTXTRACE("create");
|
||||
dns_name_init(&fctx->name, NULL);
|
||||
result = dns_name_dup(name, mctx, &fctx->name);
|
||||
@ -3870,10 +3919,12 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
|
||||
dns_forwarders_t *forwarders = NULL;
|
||||
unsigned int labels;
|
||||
dns_name_t *fwdname = name;
|
||||
dns_name_t suffix;
|
||||
|
||||
/*
|
||||
* DS records are found in the parent server.
|
||||
* Strip label to get the correct forwarder (if any).
|
||||
* DS records are found in the parent server. Strip one
|
||||
* leading label from the name (to be used in finding
|
||||
* the forwarder).
|
||||
*/
|
||||
if (dns_rdatatype_atparent(fctx->type) &&
|
||||
dns_name_countlabels(name) > 1) {
|
||||
@ -3882,6 +3933,8 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
|
||||
dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
|
||||
fwdname = &suffix;
|
||||
}
|
||||
|
||||
/* Find the forwarder for this name. */
|
||||
dns_fixedname_init(&fixed);
|
||||
domain = dns_fixedname_name(&fixed);
|
||||
result = dns_fwdtable_find2(fctx->res->view->fwdtable, fwdname,
|
||||
@ -7170,6 +7223,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
if (fctx->res->exiting) {
|
||||
result = ISC_R_SHUTTINGDOWN;
|
||||
FCTXTRACE("resolver shutting down");
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -7224,6 +7278,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
no_response = ISC_TRUE;
|
||||
}
|
||||
}
|
||||
FCTXTRACE3("dispatcher failure", devent->result);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -7231,14 +7286,18 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
if (query->tsig != NULL) {
|
||||
result = dns_message_setquerytsig(message, query->tsig);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
FCTXTRACE3("unable to set query tsig", result);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (query->tsigkey) {
|
||||
result = dns_message_settsigkey(message, query->tsigkey);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
FCTXTRACE3("unable to set tsig key", result);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if ((options & DNS_FETCHOPT_TCP) == 0) {
|
||||
@ -7250,6 +7309,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
}
|
||||
result = dns_message_parse(message, &devent->buffer, 0);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
FCTXTRACE3("message failed to parse", result);
|
||||
switch (result) {
|
||||
case ISC_R_UNEXPECTEDEND:
|
||||
if (!message->question_ok ||
|
||||
@ -7338,6 +7398,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
*/
|
||||
resend = ISC_TRUE;
|
||||
/* XXXMPA log it */
|
||||
FCTXTRACE("bad sit");
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
@ -7348,8 +7409,10 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
* returns success anyway.
|
||||
*/
|
||||
result = dns_message_checksig(message, fctx->res->view);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
FCTXTRACE3("signature check failed", result);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* The dispatcher should ensure we only get responses with QR set.
|
||||
@ -7453,6 +7516,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
options |= DNS_FETCHOPT_TCP;
|
||||
resend = ISC_TRUE;
|
||||
}
|
||||
FCTXTRACE3("message truncated", result);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -7463,6 +7527,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
/* XXXRTH Log */
|
||||
broken_server = DNS_R_UNEXPECTEDOPCODE;
|
||||
keep_trying = ISC_TRUE;
|
||||
FCTXTRACE("invalid message opcode");
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -7497,6 +7562,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
*/
|
||||
if (message->rcode != dns_rcode_noerror &&
|
||||
message->rcode != dns_rcode_nxdomain) {
|
||||
isc_buffer_t b;
|
||||
char code[64];
|
||||
#ifdef ISC_PLATFORM_USESIT
|
||||
unsigned char sit[64];
|
||||
|
||||
@ -7623,6 +7690,11 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
INSIST(broken_server != ISC_R_SUCCESS);
|
||||
keep_trying = ISC_TRUE;
|
||||
}
|
||||
|
||||
isc_buffer_init(&b, code, sizeof(code) - 1);
|
||||
dns_rcode_totext(fctx->rmessage->rcode, &b);
|
||||
code[isc_buffer_usedlength(&b)] = '\0';
|
||||
FCTXTRACE2("remote server broken: returned ", code);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -7634,6 +7706,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
/* XXXRTH Log */
|
||||
if (result == DNS_R_FORMERR)
|
||||
keep_trying = ISC_TRUE;
|
||||
FCTXTRACE3("response did not match question", result);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -7654,6 +7727,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
isc_result_totext(result));
|
||||
broken_server = DNS_R_LAME;
|
||||
keep_trying = ISC_TRUE;
|
||||
FCTXTRACE("lame server");
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -7706,22 +7780,32 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
*/
|
||||
if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 ||
|
||||
ISFORWARDER(query->addrinfo))
|
||||
{
|
||||
result = answer_response(fctx);
|
||||
else if (iscname(fctx) &&
|
||||
if (result != ISC_R_SUCCESS)
|
||||
FCTXTRACE3("answer_response (AA/fwd)", result);
|
||||
} else if (iscname(fctx) &&
|
||||
fctx->type != dns_rdatatype_any &&
|
||||
fctx->type != dns_rdatatype_cname) {
|
||||
fctx->type != dns_rdatatype_cname)
|
||||
{
|
||||
/*
|
||||
* A BIND8 server could return a non-authoritative
|
||||
* answer when a CNAME is followed. We should treat
|
||||
* it as a valid answer.
|
||||
*/
|
||||
result = answer_response(fctx);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
FCTXTRACE3("answer_response (!ANY/!CNAME)",
|
||||
result);
|
||||
} else if (fctx->type != dns_rdatatype_ns &&
|
||||
!betterreferral(fctx)) {
|
||||
/*
|
||||
* Lame response !!!.
|
||||
*/
|
||||
result = answer_response(fctx);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
FCTXTRACE("answer_response (!NS)");
|
||||
FCTXTRACE3("answer_response (!NS)", result);
|
||||
} else {
|
||||
if (fctx->type == dns_rdatatype_ns) {
|
||||
/*
|
||||
@ -7734,6 +7818,9 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
*/
|
||||
result = noanswer_response(fctx, NULL,
|
||||
LOOK_FOR_NS_IN_ANSWER);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
FCTXTRACE3("noanswer_response (NS)",
|
||||
result);
|
||||
} else {
|
||||
/*
|
||||
* Some other servers may still somehow include
|
||||
@ -7749,6 +7836,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
*/
|
||||
result = noanswer_response(fctx, NULL,
|
||||
LOOK_FOR_GLUE_IN_ANSWER);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
FCTXTRACE3("noanswer_response", result);
|
||||
}
|
||||
if (result != DNS_R_DELEGATION) {
|
||||
/*
|
||||
@ -7813,6 +7902,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
*/
|
||||
if (result == DNS_R_FORMERR)
|
||||
keep_trying = ISC_TRUE;
|
||||
FCTXTRACE3("noanswer_response", result);
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
@ -7822,6 +7912,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
/* XXXRTH Log */
|
||||
broken_server = DNS_R_UNEXPECTEDRCODE;
|
||||
keep_trying = ISC_TRUE;
|
||||
FCTXTRACE("broken server: unexpected rcode");
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -7836,8 +7927,10 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
*/
|
||||
if (WANTCACHE(fctx)) {
|
||||
result = cache_message(fctx, query->addrinfo, now);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
FCTXTRACE3("cache_message complete", result);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -7855,6 +7948,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
* Cache any negative cache entries in the message.
|
||||
*/
|
||||
result = ncache_message(fctx, query->addrinfo, covers, now);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
FCTXTRACE3("ncache_message complete", result);
|
||||
}
|
||||
|
||||
done:
|
||||
@ -7864,6 +7959,10 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
*/
|
||||
addrinfo = query->addrinfo;
|
||||
|
||||
FCTXTRACE4("query canceled in response(); ",
|
||||
no_response ? "no response" : "responding",
|
||||
result);
|
||||
|
||||
/*
|
||||
* Cancel the query.
|
||||
*
|
||||
@ -8616,6 +8715,10 @@ log_fetch(dns_name_t *name, dns_rdatatype_t type) {
|
||||
char typebuf[DNS_RDATATYPE_FORMATSIZE];
|
||||
int level = ISC_LOG_DEBUG(1);
|
||||
|
||||
/*
|
||||
* If there's no chance of logging it, don't render (format) the
|
||||
* name and RDATA type (further below), and return early.
|
||||
*/
|
||||
if (! isc_log_wouldlog(dns_lctx, level))
|
||||
return;
|
||||
|
||||
@ -9022,6 +9125,11 @@ dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name) {
|
||||
unsigned int i;
|
||||
dns_badcache_t *bad, *prev, *next;
|
||||
|
||||
/*
|
||||
* Drop all entries that match the name, and also all expired
|
||||
* entries from the badcache.
|
||||
*/
|
||||
|
||||
REQUIRE(VALID_RESOLVER(resolver));
|
||||
|
||||
LOCK(&resolver->lock);
|
||||
@ -9066,6 +9174,8 @@ dns_resolver_flushbadnames(dns_resolver_t *resolver, dns_name_t *name) {
|
||||
isc_time_t now;
|
||||
isc_result_t result;
|
||||
|
||||
/* Drop all expired entries from the badcache. */
|
||||
|
||||
REQUIRE(VALID_RESOLVER(resolver));
|
||||
REQUIRE(name != NULL);
|
||||
|
||||
@ -9105,6 +9215,13 @@ resizehash(dns_resolver_t *resolver, isc_time_t *now, isc_boolean_t grow) {
|
||||
dns_badcache_t **new, *bad, *next;
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* The number of buckets in the hashtable is modified in this
|
||||
* function. Afterwards, all the entries are remapped into the
|
||||
* corresponding new slot. Rehashing (hash computation) is
|
||||
* unnecessary as the hash values had been saved.
|
||||
*/
|
||||
|
||||
if (grow)
|
||||
newsize = resolver->badhash * 2 + 1;
|
||||
else
|
||||
@ -9115,6 +9232,13 @@ resizehash(dns_resolver_t *resolver, isc_time_t *now, isc_boolean_t grow) {
|
||||
if (new == NULL)
|
||||
return;
|
||||
memset(new, 0, sizeof(*resolver->badcache) * newsize);
|
||||
|
||||
/*
|
||||
* Because the hashtable implements a simple modulus mapping
|
||||
* from hash to bucket (no extendible hashing is used), every
|
||||
* name in the hashtable has to be remapped to its new slot.
|
||||
* Entries that have expired (time) are dropped.
|
||||
*/
|
||||
for (i = 0; i < resolver->badhash; i++) {
|
||||
for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
|
||||
next = bad->next;
|
||||
@ -9143,6 +9267,18 @@ dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
|
||||
unsigned int i, hashval;
|
||||
dns_badcache_t *bad, *prev, *next;
|
||||
|
||||
/*
|
||||
* The badcache is implemented as a hashtable keyed on the name,
|
||||
* and each bucket slot points to a linked list (separate
|
||||
* chaining).
|
||||
*
|
||||
* To avoid long list chains, if the number of entries in the
|
||||
* hashtable goes over number-of-buckets * 8, the
|
||||
* number-of-buckets is doubled. Similarly, if the number of
|
||||
* entries goes below number-of-buckets * 2, the number-of-buckets
|
||||
* is halved. See resizehash().
|
||||
*/
|
||||
|
||||
REQUIRE(VALID_RESOLVER(resolver));
|
||||
|
||||
LOCK(&resolver->lock);
|
||||
@ -9167,6 +9303,7 @@ dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
|
||||
next = bad->next;
|
||||
if (bad->type == type && dns_name_equal(name, &bad->name))
|
||||
break;
|
||||
/* Drop expired entries when walking the chain. */
|
||||
if (isc_time_compare(&bad->expire, &now) < 0) {
|
||||
if (prev == NULL)
|
||||
resolver->badcache[i] = bad->next;
|
||||
@ -9179,6 +9316,12 @@ dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
|
||||
prev = bad;
|
||||
}
|
||||
if (bad == NULL) {
|
||||
/*
|
||||
* Insert the name into the badcache hashtable at the
|
||||
* head of the linked list at the appropriate slot. The
|
||||
* name data follows right after the allocation for the
|
||||
* linked list node.
|
||||
*/
|
||||
isc_buffer_t buffer;
|
||||
bad = isc_mem_get(resolver->mctx, sizeof(*bad) + name->length);
|
||||
if (bad == NULL)
|
||||
@ -9337,6 +9480,12 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
|
||||
isc_result_t result;
|
||||
dns_rbtnode_t *node = NULL;
|
||||
|
||||
/*
|
||||
* Whether an algorithm is disabled (or not) is stored in a
|
||||
* per-name bitfield that is stored as the node data of an
|
||||
* RBT.
|
||||
*/
|
||||
|
||||
REQUIRE(VALID_RESOLVER(resolver));
|
||||
if (alg > 255)
|
||||
return (ISC_R_RANGE);
|
||||
@ -9358,7 +9507,17 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
|
||||
|
||||
if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
|
||||
algorithms = node->data;
|
||||
/*
|
||||
* If algorithms is set, algorithms[0] contains its
|
||||
* length.
|
||||
*/
|
||||
if (algorithms == NULL || len > *algorithms) {
|
||||
/*
|
||||
* If no bitfield exists in the node data, or if
|
||||
* it is not long enough, allocate a new
|
||||
* bitfield and copy the old (smaller) bitfield
|
||||
* into it if one exists.
|
||||
*/
|
||||
new = isc_mem_get(resolver->mctx, len);
|
||||
if (new == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
@ -9368,8 +9527,10 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
|
||||
if (algorithms != NULL)
|
||||
memmove(new, algorithms, *algorithms);
|
||||
new[len-1] |= mask;
|
||||
/* new[0] should contain the length of new. */
|
||||
*new = len;
|
||||
node->data = new;
|
||||
/* Free the older bitfield. */
|
||||
if (algorithms != NULL)
|
||||
isc_mem_put(resolver->mctx, algorithms,
|
||||
*algorithms);
|
||||
@ -9451,6 +9612,11 @@ dns_resolver_disable_ds_digest(dns_resolver_t *resolver, dns_name_t *name,
|
||||
isc_result_t result;
|
||||
dns_rbtnode_t *node = NULL;
|
||||
|
||||
/*
|
||||
* Whether a digest is disabled (or not) is stored in a per-name
|
||||
* bitfield that is stored as the node data of an RBT.
|
||||
*/
|
||||
|
||||
REQUIRE(VALID_RESOLVER(resolver));
|
||||
if (digest_type > 255)
|
||||
return (ISC_R_RANGE);
|
||||
@ -9472,7 +9638,14 @@ dns_resolver_disable_ds_digest(dns_resolver_t *resolver, dns_name_t *name,
|
||||
|
||||
if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
|
||||
digests = node->data;
|
||||
/* If digests is set, digests[0] contains its length. */
|
||||
if (digests == NULL || len > *digests) {
|
||||
/*
|
||||
* If no bitfield exists in the node data, or if
|
||||
* it is not long enough, allocate a new
|
||||
* bitfield and copy the old (smaller) bitfield
|
||||
* into it if one exists.
|
||||
*/
|
||||
new = isc_mem_get(resolver->mctx, len);
|
||||
if (new == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
@ -9482,8 +9655,10 @@ dns_resolver_disable_ds_digest(dns_resolver_t *resolver, dns_name_t *name,
|
||||
if (digests != NULL)
|
||||
memmove(new, digests, *digests);
|
||||
new[len-1] |= mask;
|
||||
/* new[0] should contain the length of new. */
|
||||
*new = len;
|
||||
node->data = new;
|
||||
/* Free the older bitfield. */
|
||||
if (digests != NULL)
|
||||
isc_mem_put(resolver->mctx, digests,
|
||||
*digests);
|
||||
|
@ -136,8 +136,8 @@ load_geoip(const char *dir) {
|
||||
}
|
||||
|
||||
static isc_boolean_t
|
||||
do_lookup_string(const char *addr, dns_geoip_subtype_t subtype,
|
||||
const char *string)
|
||||
do_lookup_string(const char *addr, isc_uint8_t *scope,
|
||||
dns_geoip_subtype_t subtype, const char *string)
|
||||
{
|
||||
dns_geoip_elem_t elt;
|
||||
struct in_addr in4;
|
||||
@ -149,12 +149,12 @@ do_lookup_string(const char *addr, dns_geoip_subtype_t subtype,
|
||||
elt.subtype = subtype;
|
||||
strcpy(elt.as_string, string);
|
||||
|
||||
return (dns_geoip_match(&na, &geoip, &elt));
|
||||
return (dns_geoip_match(&na, scope, &geoip, &elt));
|
||||
}
|
||||
|
||||
static isc_boolean_t
|
||||
do_lookup_string_v6(const char *addr, dns_geoip_subtype_t subtype,
|
||||
const char *string)
|
||||
do_lookup_string_v6(const char *addr, isc_uint8_t *scope,
|
||||
dns_geoip_subtype_t subtype, const char *string)
|
||||
{
|
||||
dns_geoip_elem_t elt;
|
||||
struct in6_addr in6;
|
||||
@ -166,11 +166,13 @@ do_lookup_string_v6(const char *addr, dns_geoip_subtype_t subtype,
|
||||
elt.subtype = subtype;
|
||||
strcpy(elt.as_string, string);
|
||||
|
||||
return (dns_geoip_match(&na, &geoip, &elt));
|
||||
return (dns_geoip_match(&na, scope, &geoip, &elt));
|
||||
}
|
||||
|
||||
static isc_boolean_t
|
||||
do_lookup_int(const char *addr, dns_geoip_subtype_t subtype, int id) {
|
||||
do_lookup_int(const char *addr, isc_uint8_t *scope,
|
||||
dns_geoip_subtype_t subtype, int id)
|
||||
{
|
||||
dns_geoip_elem_t elt;
|
||||
struct in_addr in4;
|
||||
isc_netaddr_t na;
|
||||
@ -181,7 +183,7 @@ do_lookup_int(const char *addr, dns_geoip_subtype_t subtype, int id) {
|
||||
elt.subtype = subtype;
|
||||
elt.as_int = id;
|
||||
|
||||
return (dns_geoip_match(&na, &geoip, &elt));
|
||||
return (dns_geoip_match(&na, scope, &geoip, &elt));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -196,6 +198,7 @@ ATF_TC_HEAD(country, tc) {
|
||||
ATF_TC_BODY(country, tc) {
|
||||
isc_result_t result;
|
||||
isc_boolean_t match;
|
||||
isc_uint8_t scope;
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
@ -210,16 +213,30 @@ ATF_TC_BODY(country, tc) {
|
||||
atf_tc_skip("Database not available");
|
||||
}
|
||||
|
||||
match = do_lookup_string("10.53.0.1", dns_geoip_country_code, "AU");
|
||||
match = do_lookup_string("10.53.0.1", &scope,
|
||||
dns_geoip_country_code, "AU");
|
||||
ATF_CHECK(match);
|
||||
ATF_CHECK_EQ(scope, 32);
|
||||
|
||||
match = do_lookup_string("10.53.0.1",
|
||||
match = do_lookup_string("10.53.0.1", &scope,
|
||||
dns_geoip_country_code3, "AUS");
|
||||
ATF_CHECK(match);
|
||||
ATF_CHECK_EQ(scope, 32);
|
||||
|
||||
match = do_lookup_string("10.53.0.1",
|
||||
match = do_lookup_string("10.53.0.1", &scope,
|
||||
dns_geoip_country_name, "Australia");
|
||||
ATF_CHECK(match);
|
||||
ATF_CHECK_EQ(scope, 32);
|
||||
|
||||
match = do_lookup_string("192.0.2.128", &scope,
|
||||
dns_geoip_country_code, "O1");
|
||||
ATF_CHECK(match);
|
||||
ATF_CHECK_EQ(scope, 24);
|
||||
|
||||
match = do_lookup_string("192.0.2.128", &scope,
|
||||
dns_geoip_country_name, "Other");
|
||||
ATF_CHECK(match);
|
||||
ATF_CHECK_EQ(scope, 24);
|
||||
|
||||
dns_test_end();
|
||||
}
|
||||
@ -232,6 +249,7 @@ ATF_TC_HEAD(country_v6, tc) {
|
||||
ATF_TC_BODY(country_v6, tc) {
|
||||
isc_result_t result;
|
||||
isc_boolean_t match;
|
||||
isc_uint8_t scope;
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
@ -246,17 +264,20 @@ ATF_TC_BODY(country_v6, tc) {
|
||||
atf_tc_skip("Database not available");
|
||||
}
|
||||
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1",
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", &scope,
|
||||
dns_geoip_country_code, "AU");
|
||||
ATF_CHECK(match);
|
||||
ATF_CHECK_EQ(scope, 128);
|
||||
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1",
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", &scope,
|
||||
dns_geoip_country_code3, "AUS");
|
||||
ATF_CHECK(match);
|
||||
ATF_CHECK_EQ(scope, 128);
|
||||
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1",
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", &scope,
|
||||
dns_geoip_country_name, "Australia");
|
||||
ATF_CHECK(match);
|
||||
ATF_CHECK_EQ(scope, 128);
|
||||
|
||||
dns_test_end();
|
||||
}
|
||||
@ -283,42 +304,42 @@ ATF_TC_BODY(city, tc) {
|
||||
atf_tc_skip("Database not available");
|
||||
}
|
||||
|
||||
match = do_lookup_string("10.53.0.1",
|
||||
match = do_lookup_string("10.53.0.1", NULL,
|
||||
dns_geoip_city_continentcode, "NA");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.1",
|
||||
match = do_lookup_string("10.53.0.1", NULL,
|
||||
dns_geoip_city_countrycode, "US");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.1",
|
||||
match = do_lookup_string("10.53.0.1", NULL,
|
||||
dns_geoip_city_countrycode3, "USA");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.1",
|
||||
match = do_lookup_string("10.53.0.1", NULL,
|
||||
dns_geoip_city_countryname, "United States");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.1",
|
||||
match = do_lookup_string("10.53.0.1", NULL,
|
||||
dns_geoip_city_region, "CA");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.1",
|
||||
match = do_lookup_string("10.53.0.1", NULL,
|
||||
dns_geoip_city_regionname, "California");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.1",
|
||||
match = do_lookup_string("10.53.0.1", NULL,
|
||||
dns_geoip_city_name, "Redwood City");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.1",
|
||||
match = do_lookup_string("10.53.0.1", NULL,
|
||||
dns_geoip_city_postalcode, "94063");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_int("10.53.0.1", dns_geoip_city_areacode, 650);
|
||||
match = do_lookup_int("10.53.0.1", NULL, dns_geoip_city_areacode, 650);
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_int("10.53.0.1", dns_geoip_city_metrocode, 807);
|
||||
match = do_lookup_int("10.53.0.1", NULL, dns_geoip_city_metrocode, 807);
|
||||
ATF_CHECK(match);
|
||||
|
||||
dns_test_end();
|
||||
@ -346,36 +367,36 @@ ATF_TC_BODY(city_v6, tc) {
|
||||
atf_tc_skip("Database not available");
|
||||
}
|
||||
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1",
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
|
||||
dns_geoip_city_continentcode, "NA");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1",
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
|
||||
dns_geoip_city_countrycode, "US");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1",
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
|
||||
dns_geoip_city_countrycode3, "USA");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1",
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
|
||||
dns_geoip_city_countryname,
|
||||
"United States");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1",
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
|
||||
dns_geoip_city_region, "CA");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1",
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
|
||||
dns_geoip_city_regionname, "California");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1",
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
|
||||
dns_geoip_city_name, "Redwood City");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1",
|
||||
match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", NULL,
|
||||
dns_geoip_city_postalcode, "94063");
|
||||
ATF_CHECK(match);
|
||||
|
||||
@ -405,15 +426,15 @@ ATF_TC_BODY(region, tc) {
|
||||
atf_tc_skip("Database not available");
|
||||
}
|
||||
|
||||
match = do_lookup_string("10.53.0.1",
|
||||
match = do_lookup_string("10.53.0.1", NULL,
|
||||
dns_geoip_region_code, "CA");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.1",
|
||||
match = do_lookup_string("10.53.0.1", NULL,
|
||||
dns_geoip_region_name, "California");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.1",
|
||||
match = do_lookup_string("10.53.0.1", NULL,
|
||||
dns_geoip_region_countrycode, "US");
|
||||
ATF_CHECK(match);
|
||||
|
||||
@ -447,30 +468,30 @@ ATF_TC_BODY(best, tc) {
|
||||
atf_tc_skip("Database not available");
|
||||
}
|
||||
|
||||
match = do_lookup_string("10.53.0.4",
|
||||
match = do_lookup_string("10.53.0.4", NULL,
|
||||
dns_geoip_countrycode, "US");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.4",
|
||||
match = do_lookup_string("10.53.0.4", NULL,
|
||||
dns_geoip_countrycode3, "USA");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.4",
|
||||
match = do_lookup_string("10.53.0.4", NULL,
|
||||
dns_geoip_countryname, "United States");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.4",
|
||||
match = do_lookup_string("10.53.0.4", NULL,
|
||||
dns_geoip_regionname, "Virginia");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.4",
|
||||
match = do_lookup_string("10.53.0.4", NULL,
|
||||
dns_geoip_region, "VA");
|
||||
ATF_CHECK(match);
|
||||
|
||||
GeoIP_delete(geoip.city_v4);
|
||||
geoip.city_v4 = NULL;
|
||||
|
||||
match = do_lookup_string("10.53.0.4",
|
||||
match = do_lookup_string("10.53.0.4", NULL,
|
||||
dns_geoip_countrycode, "AU");
|
||||
ATF_CHECK(match);
|
||||
|
||||
@ -478,26 +499,26 @@ ATF_TC_BODY(best, tc) {
|
||||
* Note, region doesn't support code3 or countryname, so
|
||||
* the next two would be answered from the country database instead
|
||||
*/
|
||||
match = do_lookup_string("10.53.0.4",
|
||||
match = do_lookup_string("10.53.0.4", NULL,
|
||||
dns_geoip_countrycode3, "CAN");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.4",
|
||||
match = do_lookup_string("10.53.0.4", NULL,
|
||||
dns_geoip_countryname, "Canada");
|
||||
ATF_CHECK(match);
|
||||
|
||||
GeoIP_delete(geoip.region);
|
||||
geoip.region = NULL;
|
||||
|
||||
match = do_lookup_string("10.53.0.4",
|
||||
match = do_lookup_string("10.53.0.4", NULL,
|
||||
dns_geoip_countrycode, "CA");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.4",
|
||||
match = do_lookup_string("10.53.0.4", NULL,
|
||||
dns_geoip_countrycode3, "CAN");
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_string("10.53.0.4",
|
||||
match = do_lookup_string("10.53.0.4", NULL,
|
||||
dns_geoip_countryname, "Canada");
|
||||
ATF_CHECK(match);
|
||||
|
||||
@ -528,7 +549,7 @@ ATF_TC_BODY(asnum, tc) {
|
||||
}
|
||||
|
||||
|
||||
match = do_lookup_string("10.53.0.3", dns_geoip_as_asnum,
|
||||
match = do_lookup_string("10.53.0.3", NULL, dns_geoip_as_asnum,
|
||||
"AS100003 Three Network Labs");
|
||||
ATF_CHECK(match);
|
||||
|
||||
@ -557,7 +578,7 @@ ATF_TC_BODY(isp, tc) {
|
||||
atf_tc_skip("Database not available");
|
||||
}
|
||||
|
||||
match = do_lookup_string("10.53.0.1", dns_geoip_isp_name,
|
||||
match = do_lookup_string("10.53.0.1", NULL, dns_geoip_isp_name,
|
||||
"One Systems, Inc.");
|
||||
ATF_CHECK(match);
|
||||
|
||||
@ -586,7 +607,7 @@ ATF_TC_BODY(org, tc) {
|
||||
atf_tc_skip("Database not available");
|
||||
}
|
||||
|
||||
match = do_lookup_string("10.53.0.2", dns_geoip_org_name,
|
||||
match = do_lookup_string("10.53.0.2", NULL, dns_geoip_org_name,
|
||||
"Two Technology Ltd.");
|
||||
ATF_CHECK(match);
|
||||
|
||||
@ -615,7 +636,7 @@ ATF_TC_BODY(domain, tc) {
|
||||
atf_tc_skip("Database not available");
|
||||
}
|
||||
|
||||
match = do_lookup_string("10.53.0.4",
|
||||
match = do_lookup_string("10.53.0.4", NULL,
|
||||
dns_geoip_domain_name, "four.com");
|
||||
ATF_CHECK(match);
|
||||
|
||||
@ -644,16 +665,16 @@ ATF_TC_BODY(netspeed, tc) {
|
||||
atf_tc_skip("Database not available");
|
||||
}
|
||||
|
||||
match = do_lookup_int("10.53.0.1", dns_geoip_netspeed_id, 0);
|
||||
match = do_lookup_int("10.53.0.1", NULL, dns_geoip_netspeed_id, 0);
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_int("10.53.0.2", dns_geoip_netspeed_id, 1);
|
||||
match = do_lookup_int("10.53.0.2", NULL, dns_geoip_netspeed_id, 1);
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_int("10.53.0.3", dns_geoip_netspeed_id, 2);
|
||||
match = do_lookup_int("10.53.0.3", NULL, dns_geoip_netspeed_id, 2);
|
||||
ATF_CHECK(match);
|
||||
|
||||
match = do_lookup_int("10.53.0.4", dns_geoip_netspeed_id, 3);
|
||||
match = do_lookup_int("10.53.0.4", NULL, dns_geoip_netspeed_id, 3);
|
||||
ATF_CHECK(match);
|
||||
|
||||
dns_test_end();
|
||||
|
@ -25,9 +25,11 @@ dns_acl_isany
|
||||
dns_acl_isinsecure
|
||||
dns_acl_isnone
|
||||
dns_acl_match
|
||||
dns_acl_match2
|
||||
dns_acl_merge
|
||||
dns_acl_none
|
||||
dns_aclelement_match
|
||||
dns_aclelement_match2
|
||||
dns_aclenv_copy
|
||||
dns_aclenv_destroy
|
||||
dns_aclenv_init
|
||||
|
@ -14,8 +14,6 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: radix.h,v 1.13 2008/12/01 23:47:45 tbox Exp $ */
|
||||
|
||||
/*
|
||||
* This source was adapted from MRT's RCS Ids:
|
||||
* Id: radix.h,v 1.6 1999/08/03 03:32:53 masaki Exp
|
||||
@ -34,7 +32,7 @@
|
||||
#ifndef _RADIX_H
|
||||
#define _RADIX_H
|
||||
|
||||
#define NETADDR_TO_PREFIX_T(na,pt,bits) \
|
||||
#define NETADDR_TO_PREFIX_T(na,pt,bits,isecs) \
|
||||
do { \
|
||||
memset(&(pt), 0, sizeof(pt)); \
|
||||
if((na) != NULL) { \
|
||||
@ -50,6 +48,7 @@
|
||||
(pt).family = AF_UNSPEC; \
|
||||
(pt).bitlen = 0; \
|
||||
} \
|
||||
(pt).ecs = isecs; \
|
||||
isc_refcount_init(&(pt).refcount, 0); \
|
||||
} while(0)
|
||||
|
||||
@ -57,6 +56,7 @@ typedef struct isc_prefix {
|
||||
isc_mem_t *mctx;
|
||||
unsigned int family; /* AF_INET | AF_INET6, or AF_UNSPEC for "any" */
|
||||
unsigned int bitlen; /* 0 for "any" */
|
||||
isc_boolean_t ecs; /* ISC_TRUE for an EDNS client subnet address */
|
||||
isc_refcount_t refcount;
|
||||
union {
|
||||
struct in_addr sin;
|
||||
@ -81,23 +81,32 @@ typedef void (*isc_radix_processfunc_t)(isc_prefix_t *, void **);
|
||||
* return the one that was added first.
|
||||
*
|
||||
* An IPv4 prefix and an IPv6 prefix may share a radix tree node if they
|
||||
* have the same length and bit pattern (e.g., 127/8 and 7f::/8). To
|
||||
* disambiguate between them, node_num and data are two-element arrays;
|
||||
* node_num[0] and data[0] are used for IPv4 addresses, node_num[1]
|
||||
* and data[1] for IPv6 addresses. The only exception is a prefix of
|
||||
* 0/0 (aka "any" or "none"), which is always stored as IPv4 but matches
|
||||
* IPv6 addresses too.
|
||||
* have the same length and bit pattern (e.g., 127/8 and 7f::/8). Also,
|
||||
* a node that matches a client address may also match an EDNS client
|
||||
* subnet address. To disambiguate between these, node_num and data
|
||||
* are four-element arrays;
|
||||
*
|
||||
* - node_num[0] and data[0] are used for IPv4 client addresses
|
||||
* - node_num[1] and data[1] for IPv4 client subnet addresses
|
||||
* - node_num[2] and data[2] are used for IPv6 client addresses
|
||||
* - node_num[3] and data[3] for IPv6 client subnet addresses
|
||||
*
|
||||
* A prefix of 0/0 (aka "any" or "none"), is always stored as IPv4,
|
||||
* but matches IPv6 addresses too, as well as all client subnet
|
||||
* addresses.
|
||||
*/
|
||||
|
||||
#define ISC_IS6(family) ((family) == AF_INET6 ? 1 : 0)
|
||||
#define ISC_RADIX_OFF(p) \
|
||||
((((p)->family == AF_INET6) ? 1 : 0) + ((p)->ecs ? 2 : 0))
|
||||
|
||||
typedef struct isc_radix_node {
|
||||
isc_mem_t *mctx;
|
||||
isc_uint32_t bit; /* bit length of the prefix */
|
||||
isc_prefix_t *prefix; /* who we are in radix tree */
|
||||
struct isc_radix_node *l, *r; /* left and right children */
|
||||
struct isc_radix_node *parent; /* may be used */
|
||||
void *data[2]; /* pointers to IPv4 and IPV6 data */
|
||||
int node_num[2]; /* which node this was in the tree,
|
||||
void *data[4]; /* pointers to IPv4 and IPV6 data */
|
||||
int node_num[4]; /* which node this was in the tree,
|
||||
or -1 for glue nodes */
|
||||
} isc_radix_node_t;
|
||||
|
||||
|
165
lib/isc/radix.c
165
lib/isc/radix.c
@ -70,6 +70,7 @@ _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest,
|
||||
}
|
||||
|
||||
prefix->family = family;
|
||||
prefix->ecs = ISC_FALSE;
|
||||
prefix->mctx = NULL;
|
||||
isc_mem_attach(mctx, &prefix->mctx);
|
||||
|
||||
@ -182,12 +183,13 @@ _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
|
||||
|
||||
if (Xrn->prefix != NULL) {
|
||||
_deref_prefix(Xrn->prefix);
|
||||
if (func != NULL && (Xrn->data[0] != NULL ||
|
||||
Xrn->data[1] != NULL))
|
||||
if (func != NULL)
|
||||
func(Xrn->data);
|
||||
} else {
|
||||
INSIST(Xrn->data[0] == NULL &&
|
||||
Xrn->data[1] == NULL);
|
||||
Xrn->data[1] == NULL &&
|
||||
Xrn->data[2] == NULL &&
|
||||
Xrn->data[3] == NULL);
|
||||
}
|
||||
|
||||
isc_mem_put(radix->mctx, Xrn, sizeof(*Xrn));
|
||||
@ -242,8 +244,7 @@ isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
|
||||
isc_radix_node_t *stack[RADIX_MAXBITS + 1];
|
||||
u_char *addr;
|
||||
isc_uint32_t bitlen;
|
||||
int tfamily = -1;
|
||||
int cnt = 0;
|
||||
int toff = -1, cnt = 0;
|
||||
|
||||
REQUIRE(radix != NULL);
|
||||
REQUIRE(prefix != NULL);
|
||||
@ -281,13 +282,15 @@ isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
|
||||
|
||||
if (_comp_with_mask(isc_prefix_tochar(node->prefix),
|
||||
isc_prefix_tochar(prefix),
|
||||
node->prefix->bitlen)) {
|
||||
if (node->node_num[ISC_IS6(prefix->family)] != -1 &&
|
||||
((*target == NULL) ||
|
||||
(*target)->node_num[ISC_IS6(tfamily)] >
|
||||
node->node_num[ISC_IS6(prefix->family)])) {
|
||||
node->prefix->bitlen))
|
||||
{
|
||||
int off = ISC_RADIX_OFF(prefix);
|
||||
if (node->node_num[off] != -1 &&
|
||||
((*target == NULL) ||
|
||||
(*target)->node_num[toff] > node->node_num[off]))
|
||||
{
|
||||
*target = node;
|
||||
tfamily = prefix->family;
|
||||
toff = off;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -327,7 +330,8 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
|
||||
if (node == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
node->bit = bitlen;
|
||||
node->node_num[0] = node->node_num[1] = -1;
|
||||
for (i = 0; i < 4; i++)
|
||||
node->node_num[i] = -1;
|
||||
node->prefix = NULL;
|
||||
result = _ref_prefix(radix->mctx, &node->prefix, prefix);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
@ -346,25 +350,24 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
|
||||
* added to num_added_node at the end of
|
||||
* the merge operation--we don't do it here.
|
||||
*/
|
||||
if (source->node_num[0] != -1)
|
||||
node->node_num[0] = radix->num_added_node +
|
||||
source->node_num[0];
|
||||
if (source->node_num[1] != -1)
|
||||
node->node_num[1] = radix->num_added_node +
|
||||
source->node_num[1];
|
||||
node->data[0] = source->data[0];
|
||||
node->data[1] = source->data[1];
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (source->node_num[i] != -1)
|
||||
node->node_num[i] =
|
||||
radix->num_added_node +
|
||||
source->node_num[i];
|
||||
node->data[i] = source->data[i];
|
||||
}
|
||||
} else {
|
||||
int next = ++radix->num_added_node;
|
||||
if (fam == AF_UNSPEC) {
|
||||
/* "any" or "none" */
|
||||
node->node_num[0] = node->node_num[1] =
|
||||
++radix->num_added_node;
|
||||
for (i = 0; i < 4; i++)
|
||||
node->node_num[i] = next;
|
||||
} else {
|
||||
node->node_num[ISC_IS6(fam)] =
|
||||
++radix->num_added_node;
|
||||
node->node_num[ISC_RADIX_OFF(prefix)] = next;
|
||||
}
|
||||
node->data[0] = NULL;
|
||||
node->data[1] = NULL;
|
||||
|
||||
memset(node->data, 0, sizeof(node->data));
|
||||
}
|
||||
radix->head = node;
|
||||
radix->num_active_node++;
|
||||
@ -426,37 +429,33 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
|
||||
if (node->prefix != NULL) {
|
||||
/* Set node_num only if it hasn't been set before */
|
||||
if (source != NULL) {
|
||||
/* Merging node */
|
||||
if (node->node_num[0] == -1 &&
|
||||
source->node_num[0] != -1) {
|
||||
node->node_num[0] =
|
||||
radix->num_added_node +
|
||||
source->node_num[0];
|
||||
node->data[0] = source->data[0];
|
||||
}
|
||||
if (node->node_num[1] == -1 &&
|
||||
source->node_num[0] != -1) {
|
||||
node->node_num[1] =
|
||||
radix->num_added_node +
|
||||
source->node_num[1];
|
||||
node->data[1] = source->data[1];
|
||||
/* Merging nodes */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (node->node_num[i] == -1 &&
|
||||
source->node_num[i] != -1) {
|
||||
node->node_num[i] =
|
||||
radix->num_added_node +
|
||||
source->node_num[i];
|
||||
node->data[i] = source->data[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (fam == AF_UNSPEC) {
|
||||
/* "any" or "none" */
|
||||
int next = radix->num_added_node + 1;
|
||||
if (node->node_num[0] == -1) {
|
||||
node->node_num[0] = next;
|
||||
radix->num_added_node = next;
|
||||
}
|
||||
if (node->node_num[1] == -1) {
|
||||
node->node_num[1] = next;
|
||||
radix->num_added_node = next;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (node->node_num[i] == -1) {
|
||||
node->node_num[i] =
|
||||
next;
|
||||
radix->num_added_node =
|
||||
next;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (node->node_num[ISC_IS6(fam)] == -1)
|
||||
node->node_num[ISC_IS6(fam)]
|
||||
= ++radix->num_added_node;
|
||||
int off = ISC_RADIX_OFF(prefix);
|
||||
if (node->node_num[off] == -1)
|
||||
node->node_num[off] =
|
||||
++radix->num_added_node;
|
||||
}
|
||||
}
|
||||
*target = node;
|
||||
@ -468,27 +467,27 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
|
||||
return (result);
|
||||
}
|
||||
INSIST(node->data[0] == NULL && node->node_num[0] == -1 &&
|
||||
node->data[1] == NULL && node->node_num[1] == -1);
|
||||
node->data[1] == NULL && node->node_num[1] == -1 &&
|
||||
node->data[2] == NULL && node->node_num[2] == -1 &&
|
||||
node->data[3] == NULL && node->node_num[3] == -1);
|
||||
if (source != NULL) {
|
||||
/* Merging node */
|
||||
if (source->node_num[0] != -1) {
|
||||
node->node_num[0] = radix->num_added_node +
|
||||
source->node_num[0];
|
||||
node->data[0] = source->data[0];
|
||||
}
|
||||
if (source->node_num[1] != -1) {
|
||||
node->node_num[1] = radix->num_added_node +
|
||||
source->node_num[1];
|
||||
node->data[1] = source->data[1];
|
||||
for (i = 0; i < 4; i++) {
|
||||
int cur = radix->num_added_node;
|
||||
if (source->node_num[i] != -1) {
|
||||
node->node_num[i] =
|
||||
source->node_num[i] + cur;
|
||||
node->data[i] = source->data[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int next = ++radix->num_added_node;
|
||||
if (fam == AF_UNSPEC) {
|
||||
/* "any" or "none" */
|
||||
node->node_num[0] = node->node_num[1] =
|
||||
++radix->num_added_node;
|
||||
for (i = 0; i < 4; i++)
|
||||
node->node_num[i] = next;
|
||||
} else {
|
||||
node->node_num[ISC_IS6(fam)] =
|
||||
++radix->num_added_node;
|
||||
node->node_num[ISC_RADIX_OFF(prefix)] = next;
|
||||
}
|
||||
}
|
||||
*target = node;
|
||||
@ -518,30 +517,30 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
|
||||
}
|
||||
new_node->parent = NULL;
|
||||
new_node->l = new_node->r = NULL;
|
||||
new_node->node_num[0] = new_node->node_num[1] = -1;
|
||||
for (i = 0; i < 4; i++)
|
||||
new_node->node_num[i] = -1;
|
||||
radix->num_active_node++;
|
||||
|
||||
if (source != NULL) {
|
||||
/* Merging node */
|
||||
if (source->node_num[0] != -1)
|
||||
new_node->node_num[0] = radix->num_added_node +
|
||||
source->node_num[0];
|
||||
if (source->node_num[1] != -1)
|
||||
new_node->node_num[1] = radix->num_added_node +
|
||||
source->node_num[1];
|
||||
new_node->data[0] = source->data[0];
|
||||
new_node->data[1] = source->data[1];
|
||||
for (i = 0; i < 4; i++) {
|
||||
int cur = radix->num_added_node;
|
||||
if (source->node_num[i] != -1) {
|
||||
new_node->node_num[i] =
|
||||
source->node_num[i] + cur;
|
||||
new_node->data[i] = source->data[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int next = ++radix->num_added_node;
|
||||
if (fam == AF_UNSPEC) {
|
||||
/* "any" or "none" */
|
||||
new_node->node_num[0] = new_node->node_num[1] =
|
||||
++radix->num_added_node;
|
||||
for (i = 0; i < 4; i++)
|
||||
new_node->node_num[i] = next;
|
||||
} else {
|
||||
new_node->node_num[ISC_IS6(fam)] =
|
||||
++radix->num_added_node;
|
||||
new_node->node_num[ISC_RADIX_OFF(prefix)] = next;
|
||||
}
|
||||
new_node->data[0] = NULL;
|
||||
new_node->data[1] = NULL;
|
||||
memset(new_node->data, 0, sizeof(new_node->data));
|
||||
}
|
||||
|
||||
if (node->bit == differ_bit) {
|
||||
@ -583,8 +582,10 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
|
||||
glue->bit = differ_bit;
|
||||
glue->prefix = NULL;
|
||||
glue->parent = node->parent;
|
||||
glue->data[0] = glue->data[1] = NULL;
|
||||
glue->node_num[0] = glue->node_num[1] = -1;
|
||||
for (i = 0; i < 4; i++) {
|
||||
glue->data[i] = NULL;
|
||||
glue->node_num[i] = -1;
|
||||
}
|
||||
radix->num_active_node++;
|
||||
if (differ_bit < radix->maxbits &&
|
||||
BIT_TEST(addr[differ_bit>>3], 0x80 >> (differ_bit & 07))) {
|
||||
@ -627,7 +628,7 @@ isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) {
|
||||
_deref_prefix(node->prefix);
|
||||
|
||||
node->prefix = NULL;
|
||||
node->data[0] = node->data[1] = NULL;
|
||||
memset(node->data, 0, sizeof(node->data));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -482,6 +482,7 @@ parse_geoip_element(const cfg_obj_t *obj, isc_log_t *lctx,
|
||||
const char *stype, *search;
|
||||
dns_geoip_subtype_t subtype;
|
||||
dns_aclelement_t de;
|
||||
size_t len;
|
||||
|
||||
REQUIRE(dep != NULL);
|
||||
|
||||
@ -493,35 +494,52 @@ parse_geoip_element(const cfg_obj_t *obj, isc_log_t *lctx,
|
||||
|
||||
stype = cfg_obj_asstring(cfg_tuple_get(obj, "subtype"));
|
||||
search = cfg_obj_asstring(cfg_tuple_get(obj, "search"));
|
||||
len = strlen(search);
|
||||
|
||||
if (strcasecmp(stype, "country") == 0 && strlen(search) == 2) {
|
||||
if (len == 0) {
|
||||
cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
|
||||
"zero-length geoip search field");
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (strcasecmp(stype, "country") == 0 && len == 2) {
|
||||
/* Two-letter country code */
|
||||
subtype = dns_geoip_countrycode;
|
||||
strncpy(de.geoip_elem.as_string, search, 2);
|
||||
} else if (strcasecmp(stype, "country") == 0 && strlen(search) == 3) {
|
||||
strlcpy(de.geoip_elem.as_string, search,
|
||||
sizeof(de.geoip_elem.as_string));
|
||||
} else if (strcasecmp(stype, "country") == 0 && len == 3) {
|
||||
/* Three-letter country code */
|
||||
subtype = dns_geoip_countrycode3;
|
||||
strncpy(de.geoip_elem.as_string, search, 3);
|
||||
strlcpy(de.geoip_elem.as_string, search,
|
||||
sizeof(de.geoip_elem.as_string));
|
||||
} else if (strcasecmp(stype, "country") == 0) {
|
||||
/* Country name */
|
||||
subtype = dns_geoip_countryname;
|
||||
strncpy(de.geoip_elem.as_string, search, 255);
|
||||
} else if (strcasecmp(stype, "region") == 0 && strlen(search) == 2) {
|
||||
strlcpy(de.geoip_elem.as_string, search,
|
||||
sizeof(de.geoip_elem.as_string));
|
||||
} else if (strcasecmp(stype, "region") == 0 && len == 2) {
|
||||
/* Two-letter region code */
|
||||
subtype = dns_geoip_region;
|
||||
strncpy(de.geoip_elem.as_string, search, 2);
|
||||
strlcpy(de.geoip_elem.as_string, search,
|
||||
sizeof(de.geoip_elem.as_string));
|
||||
} else if (strcasecmp(stype, "region") == 0) {
|
||||
/* Region name */
|
||||
subtype = dns_geoip_regionname;
|
||||
strncpy(de.geoip_elem.as_string, search, 255);
|
||||
strlcpy(de.geoip_elem.as_string, search,
|
||||
sizeof(de.geoip_elem.as_string));
|
||||
} else if (strcasecmp(stype, "city") == 0) {
|
||||
/* City name */
|
||||
subtype = dns_geoip_city_name;
|
||||
strncpy(de.geoip_elem.as_string, search, 255);
|
||||
} else if (strcasecmp(stype, "postal") == 0 && strlen(search) < 7) {
|
||||
strlcpy(de.geoip_elem.as_string, search,
|
||||
sizeof(de.geoip_elem.as_string));
|
||||
} else if (strcasecmp(stype, "postal") == 0 && len < 7) {
|
||||
subtype = dns_geoip_city_postalcode;
|
||||
strncpy(de.geoip_elem.as_string, search, 6);
|
||||
de.geoip_elem.as_string[6] = '\0';
|
||||
strlcpy(de.geoip_elem.as_string, search,
|
||||
sizeof(de.geoip_elem.as_string));
|
||||
} else if (strcasecmp(stype, "postal") == 0) {
|
||||
cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
|
||||
"geoiop postal code (%s) too long", search);
|
||||
return (ISC_R_FAILURE);
|
||||
} else if (strcasecmp(stype, "metro") == 0) {
|
||||
subtype = dns_geoip_city_metrocode;
|
||||
de.geoip_elem.as_int = atoi(search);
|
||||
@ -530,23 +548,33 @@ parse_geoip_element(const cfg_obj_t *obj, isc_log_t *lctx,
|
||||
de.geoip_elem.as_int = atoi(search);
|
||||
} else if (strcasecmp(stype, "tz") == 0) {
|
||||
subtype = dns_geoip_city_timezonecode;
|
||||
strncpy(de.geoip_elem.as_string, search, 255);
|
||||
} else if (strcasecmp(stype, "continent") == 0 && strlen(search) == 2) {
|
||||
strlcpy(de.geoip_elem.as_string, search,
|
||||
sizeof(de.geoip_elem.as_string));
|
||||
} else if (strcasecmp(stype, "continent") == 0 && len == 2) {
|
||||
/* Two-letter continent code */
|
||||
subtype = dns_geoip_city_continentcode;
|
||||
strncpy(de.geoip_elem.as_string, search, 2);
|
||||
strlcpy(de.geoip_elem.as_string, search,
|
||||
sizeof(de.geoip_elem.as_string));
|
||||
} else if (strcasecmp(stype, "continent") == 0) {
|
||||
cfg_obj_log(obj, lctx, ISC_LOG_ERROR,
|
||||
"geoiop continent code (%s) too long", search);
|
||||
return (ISC_R_FAILURE);
|
||||
} else if (strcasecmp(stype, "isp") == 0) {
|
||||
subtype = dns_geoip_isp_name;
|
||||
strncpy(de.geoip_elem.as_string, search, 255);
|
||||
strlcpy(de.geoip_elem.as_string, search,
|
||||
sizeof(de.geoip_elem.as_string));
|
||||
} else if (strcasecmp(stype, "asnum") == 0) {
|
||||
subtype = dns_geoip_as_asnum;
|
||||
strncpy(de.geoip_elem.as_string, search, 255);
|
||||
strlcpy(de.geoip_elem.as_string, search,
|
||||
sizeof(de.geoip_elem.as_string));
|
||||
} else if (strcasecmp(stype, "org") == 0) {
|
||||
subtype = dns_geoip_org_name;
|
||||
strncpy(de.geoip_elem.as_string, search, 255);
|
||||
strlcpy(de.geoip_elem.as_string, search,
|
||||
sizeof(de.geoip_elem.as_string));
|
||||
} else if (strcasecmp(stype, "domain") == 0) {
|
||||
subtype = dns_geoip_domain_name;
|
||||
strncpy(de.geoip_elem.as_string, search, 255);
|
||||
strlcpy(de.geoip_elem.as_string, search,
|
||||
sizeof(de.geoip_elem.as_string));
|
||||
} else if (strcasecmp(stype, "netspeed") == 0) {
|
||||
subtype = dns_geoip_netspeed_id;
|
||||
de.geoip_elem.as_int = atoi(search);
|
||||
@ -668,6 +696,7 @@ cfg_acl_fromconfig2(const cfg_obj_t *caml, const cfg_obj_t *cctx,
|
||||
/* Network prefix */
|
||||
isc_netaddr_t addr;
|
||||
unsigned int bitlen;
|
||||
isc_boolean_t setpos, setecs;
|
||||
|
||||
cfg_obj_asnetprefix(ce, &addr, &bitlen);
|
||||
if (family != 0 && family != addr.family) {
|
||||
@ -685,8 +714,10 @@ cfg_acl_fromconfig2(const cfg_obj_t *caml, const cfg_obj_t *cctx,
|
||||
* If nesting ACLs (nest_level != 0), we negate
|
||||
* the nestedacl element, not the iptable entry.
|
||||
*/
|
||||
result = dns_iptable_addprefix(iptab, &addr, bitlen,
|
||||
ISC_TF(nest_level != 0 || !neg));
|
||||
setpos = ISC_TF(nest_level != 0 || !neg);
|
||||
setecs = cfg_obj_istype(ce, &cfg_type_ecsprefix);
|
||||
result = dns_iptable_addprefix2(iptab, &addr, bitlen,
|
||||
setpos, setecs);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
|
@ -54,4 +54,7 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sessionkey;
|
||||
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_keyref;
|
||||
/*%< A key reference, used as an ACL element */
|
||||
|
||||
/*%< An EDNS client subnet address, used as an ACL element */
|
||||
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_ecsprefix;
|
||||
|
||||
#endif /* ISCCFG_NAMEDCONF_H */
|
||||
|
@ -950,9 +950,12 @@ options_clauses[] = {
|
||||
{ "flush-zones-on-shutdown", &cfg_type_boolean, 0 },
|
||||
#ifdef HAVE_GEOIP
|
||||
{ "geoip-directory", &cfg_type_qstringornone, 0 },
|
||||
{ "geoip-use-ecs", &cfg_type_boolean, 0 },
|
||||
#else
|
||||
{ "geoip-directory", &cfg_type_qstringornone,
|
||||
CFG_CLAUSEFLAG_NOTCONFIGURED },
|
||||
{ "geoip-use-ecs", &cfg_type_qstringornone,
|
||||
CFG_CLAUSEFLAG_NOTCONFIGURED },
|
||||
#endif /* HAVE_GEOIP */
|
||||
{ "has-old-clients", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
|
||||
{ "heartbeat-interval", &cfg_type_uint32, 0 },
|
||||
@ -2281,6 +2284,16 @@ doc_geoip(cfg_printer_t *pctx, const cfg_type_t *type) {
|
||||
}
|
||||
#endif /* HAVE_GEOIP */
|
||||
|
||||
/*%
|
||||
* An EDNS client subnet address
|
||||
*/
|
||||
|
||||
static keyword_type_t ecs_kw = { "ecs", &cfg_type_netprefix };
|
||||
LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_ecsprefix = {
|
||||
"edns_client_subnet", parse_keyvalue, print_keyvalue, doc_keyvalue,
|
||||
&cfg_rep_netprefix, &ecs_kw
|
||||
};
|
||||
|
||||
/*%
|
||||
* A "controls" statement is represented as a map with the multivalued
|
||||
* "inet" and "unix" clauses.
|
||||
@ -2570,6 +2583,9 @@ parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
|
||||
if (pctx->token.type == isc_tokentype_string &&
|
||||
(strcasecmp(TOKEN_STRING(pctx), "key") == 0)) {
|
||||
CHECK(cfg_parse_obj(pctx, &cfg_type_keyref, ret));
|
||||
} else if (pctx->token.type == isc_tokentype_string &&
|
||||
(strcasecmp(TOKEN_STRING(pctx), "ecs") == 0)) {
|
||||
CHECK(cfg_parse_obj(pctx, &cfg_type_ecsprefix, ret));
|
||||
} else if (pctx->token.type == isc_tokentype_string &&
|
||||
(strcasecmp(TOKEN_STRING(pctx), "geoip") == 0)) {
|
||||
#ifdef HAVE_GEOIP
|
||||
|
@ -1313,10 +1313,11 @@
|
||||
./bin/tests/system/geoip/geoip.c C 2013
|
||||
./bin/tests/system/geoip/ns2/example.db.in ZONE 2013
|
||||
./bin/tests/system/geoip/ns2/named1.conf CONF-C 2013
|
||||
./bin/tests/system/geoip/ns2/named10.conf CONF-C 2013
|
||||
./bin/tests/system/geoip/ns2/named10.conf CONF-C 2014
|
||||
./bin/tests/system/geoip/ns2/named11.conf CONF-C 2013
|
||||
./bin/tests/system/geoip/ns2/named12.conf CONF-C 2014
|
||||
./bin/tests/system/geoip/ns2/named12.conf CONF-C 2013
|
||||
./bin/tests/system/geoip/ns2/named13.conf CONF-C 2014
|
||||
./bin/tests/system/geoip/ns2/named14.conf CONF-C 2014
|
||||
./bin/tests/system/geoip/ns2/named2.conf CONF-C 2013
|
||||
./bin/tests/system/geoip/ns2/named3.conf CONF-C 2013
|
||||
./bin/tests/system/geoip/ns2/named4.conf CONF-C 2013
|
||||
|
Loading…
x
Reference in New Issue
Block a user