[v9_9] DDoS mitigation features

3938.	[func]		Added quotas to be used in recursive resolvers
			that are under high query load for names in zones
			whose authoritative servers are nonresponsive or
			are experiencing a denial of service attack.

			- "fetches-per-server" limits the number of
			  simultaneous queries that can be sent to any
			  single authoritative server.  The configured
			  value is a starting point; it is automatically
			  adjusted downward if the server is partially or
			  completely non-responsive. The algorithm used to
			  adjust the quota can be configured via the
			  "fetch-quota-params" option.
			- "fetches-per-zone" limits the number of
			  simultaneous queries that can be sent for names
			  within a single domain.  (Note: Unlike
			  "fetches-per-server", this value is not
			  self-tuning.)
			- New stats counters have been added to count
			  queries spilled due to these quotas.

			These options are not available by default;
			use "configure --enable-fetchlimit" (or
			--enable-developer) to include them in the build.

			See the ARM for details of these options. [RT #37125]
This commit is contained in:
Evan Hunt 2015-07-08 23:00:58 -07:00
parent 1ffb96f3dd
commit ea36796f82
61 changed files with 3060 additions and 172 deletions

27
CHANGES
View file

@ -189,6 +189,33 @@
during operation. If the read failed, named
could segfault. [RT #38559]
3938. [func] Added quotas to be used in recursive resolvers
that are under high query load for names in zones
whose authoritative servers are nonresponsive or
are experiencing a denial of service attack.
- "fetches-per-server" limits the number of
simultaneous queries that can be sent to any
single authoritative server. The configured
value is a starting point; it is automatically
adjusted downward if the server is partially or
completely non-responsive. The algorithm used to
adjust the quota can be configured via the
"fetch-quota-params" option.
- "fetches-per-zone" limits the number of
simultaneous queries that can be sent for names
within a single domain. (Note: Unlike
"fetches-per-server", this value is not
self-tuning.)
- New stats counters have been added to count
queries spilled due to these quotas.
These options are not available by default;
use "configure --enable-fetchlimit" (or
--enable-developer) to include them in the build.
See the ARM for details of these options. [RT #37125]
3937. [func] Added some debug logging to better indicate the
conditions causing SERVFAILs when resolving.
[RT #35538]

View file

@ -23,6 +23,7 @@
#include <isc/platform.h>
#include <isc/print.h>
#include <isc/queue.h>
#include <isc/random.h>
#include <isc/stats.h>
#include <isc/stdio.h>
#include <isc/string.h>
@ -111,6 +112,7 @@
*/
#endif
/*% nameserver client manager structure */
struct ns_clientmgr {
/* Unlocked. */
@ -1649,7 +1651,7 @@ client_request(isc_task_t *task, isc_event_t *event) {
}
if (TCP_CLIENT(client))
isc_stats_increment(ns_g_server->nsstats,
dns_nsstatscounter_tcp);
dns_nsstatscounter_requesttcp);
/*
* It's a request. Parse it.
@ -1662,6 +1664,11 @@ client_request(isc_task_t *task, isc_event_t *event) {
*/
if (result == DNS_R_OPTERR)
(void)client_addopt(client);
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
"message parsing failed: %s",
isc_result_totext(result));
ns_client_error(client, result);
goto cleanup;
}

View file

@ -156,7 +156,14 @@ options {\n\
dnssec-enable yes;\n\
dnssec-validation yes; \n\
dnssec-accept-expired no;\n\
clients-per-query 10;\n\
"
#ifdef ENABLE_FETCHLIMIT
" fetches-per-server 0;\n\
fetches-per-zone 0;\n\
fetch-quota-params 100 0.1 0.3 0.7;\n\
"
#endif /* ENABLE_FETCHLIMIT */
" clients-per-query 10;\n\
max-clients-per-query 100;\n\
max-recursion-depth 7;\n\
max-recursion-queries 50;\n\

View file

@ -51,6 +51,7 @@ struct ns_server {
isc_quota_t xfroutquota;
isc_quota_t tcpquota;
isc_quota_t recursionquota;
dns_acl_t *blackholeacl;
char * statsfile; /*%< Statistics file name */
char * dumpfile; /*%< Dump file name */
@ -130,7 +131,7 @@ enum {
dns_nsstatscounter_tsigin = 4,
dns_nsstatscounter_sig0in = 5,
dns_nsstatscounter_invalidsig = 6,
dns_nsstatscounter_tcp = 7,
dns_nsstatscounter_requesttcp = 7,
dns_nsstatscounter_authrej = 8,
dns_nsstatscounter_recurserej = 9,
@ -165,16 +166,31 @@ enum {
dns_nsstatscounter_updatefail = 34,
dns_nsstatscounter_updatebadprereq = 35,
dns_nsstatscounter_rpz_rewrites = 36,
dns_nsstatscounter_recursclients = 36,
#ifdef USE_RRL
dns_nsstatscounter_ratedropped = 37,
dns_nsstatscounter_rateslipped = 38,
dns_nsstatscounter_dns64 = 37,
dns_nsstatscounter_max = 39
#else /* USE_RRL */
dns_nsstatscounter_max = 37
#endif /* USE_RRL */
dns_nsstatscounter_ratedropped = 38,
dns_nsstatscounter_rateslipped = 39,
dns_nsstatscounter_rpz_rewrites = 40,
dns_nsstatscounter_udp = 41,
dns_nsstatscounter_tcp = 42,
dns_nsstatscounter_nsidopt = 43,
dns_nsstatscounter_expireopt = 44,
dns_nsstatscounter_otheropt = 45,
dns_nsstatscounter_ecsopt = 46,
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 = 53
};
void

View file

@ -195,6 +195,8 @@ struct dumpcontext {
isc_mem_t *mctx;
isc_boolean_t dumpcache;
isc_boolean_t dumpzones;
isc_boolean_t dumpadb;
isc_boolean_t dumpbad;
FILE *fp;
ISC_LIST(struct viewlistentry) viewlist;
struct viewlistentry *view;
@ -2093,6 +2095,9 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
char **dlzargv;
const cfg_obj_t *disabled;
const cfg_obj_t *obj;
#ifdef ENABLE_FETCHLIMIT
const cfg_obj_t *obj2;
#endif /* ENABLE_FETCHLIMIT */
const cfg_listelt_t *element;
in_port_t port;
dns_cache_t *cache = NULL;
@ -2749,6 +2754,55 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
}
dns_adb_setadbsize(view->adb, max_adb_size);
#ifdef ENABLE_FETCHLIMIT
/*
* Set up ADB quotas
*/
{
isc_uint32_t fps, freq;
double low, high, discount;
obj = NULL;
result = ns_config_get(maps, "fetches-per-server", &obj);
INSIST(result == ISC_R_SUCCESS);
obj2 = cfg_tuple_get(obj, "fetches");
fps = cfg_obj_asuint32(obj2);
obj2 = cfg_tuple_get(obj, "response");
if (!cfg_obj_isvoid(obj2)) {
const char *resp = cfg_obj_asstring(obj2);
isc_result_t r;
if (strcasecmp(resp, "drop") == 0)
r = DNS_R_DROP;
else if (strcasecmp(resp, "fail") == 0)
r = DNS_R_SERVFAIL;
else
INSIST(0);
dns_resolver_setquotaresponse(view->resolver,
dns_quotatype_server, r);
}
obj = NULL;
result = ns_config_get(maps, "fetch-quota-params", &obj);
INSIST(result == ISC_R_SUCCESS);
obj2 = cfg_tuple_get(obj, "frequency");
freq = cfg_obj_asuint32(obj2);
obj2 = cfg_tuple_get(obj, "low");
low = (double) cfg_obj_asfixedpoint(obj2) / 100.0;
obj2 = cfg_tuple_get(obj, "high");
high = (double) cfg_obj_asfixedpoint(obj2) / 100.0;
obj2 = cfg_tuple_get(obj, "discount");
discount = (double) cfg_obj_asfixedpoint(obj2) / 100.0;
dns_adb_setquota(view->adb, fps, freq, low, high, discount);
}
#endif /* ENABLE_FETCHLIMIT */
/*
* Set resolver's lame-ttl.
*/
@ -3176,6 +3230,29 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
INSIST(result == ISC_R_SUCCESS);
dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj));
#ifdef ENABLE_FETCHLIMIT
obj = NULL;
result = ns_config_get(maps, "fetches-per-zone", &obj);
INSIST(result == ISC_R_SUCCESS);
obj2 = cfg_tuple_get(obj, "fetches");
dns_resolver_setfetchesperzone(view->resolver, cfg_obj_asuint32(obj2));
obj2 = cfg_tuple_get(obj, "response");
if (!cfg_obj_isvoid(obj2)) {
const char *resp = cfg_obj_asstring(obj2);
isc_result_t r;
if (strcasecmp(resp, "drop") == 0)
r = DNS_R_DROP;
else if (strcasecmp(resp, "fail") == 0)
r = DNS_R_SERVFAIL;
else
INSIST(0);
dns_resolver_setquotaresponse(view->resolver,
dns_quotatype_zone, r);
}
#endif /* ENABLE_FETCHLIMIT */
#ifdef ALLOW_FILTER_AAAA_ON_V4
obj = NULL;
result = ns_config_get(maps, "filter-aaaa-on-v4", &obj);
@ -4929,6 +5006,9 @@ load_configuration(const char *filename, ns_server_t *server,
ns_cachelist_t cachelist, tmpcachelist;
struct cfg_context *nzctx;
unsigned int maxsocks;
#ifdef ENABLE_FETCHLIMIT
isc_uint32_t softquota = 0;
#endif /* ENABLE_FETCHLIMIT */
ISC_LIST_INIT(viewlist);
ISC_LIST_INIT(builtin_viewlist);
@ -5090,11 +5170,30 @@ load_configuration(const char *filename, ns_server_t *server,
configure_server_quota(maps, "tcp-clients", &server->tcpquota);
configure_server_quota(maps, "recursive-clients",
&server->recursionquota);
if (server->recursionquota.max > 1000)
#ifdef ENABLE_FETCHLIMIT
if (server->recursionquota.max > 1000) {
int margin = ISC_MAX(100, ns_g_cpus + 1);
if (margin > server->recursionquota.max - 100) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"'recursive-clients %d' too low when "
"running with %d worker threads",
server->recursionquota.max, ns_g_cpus);
CHECK(ISC_R_RANGE);
}
softquota = server->recursionquota.max - margin;
} else
softquota = (server->recursionquota.max * 90) / 100;
isc_quota_soft(&server->recursionquota, softquota);
#else
if (server->recursionquota.max > 1000) {
isc_quota_soft(&server->recursionquota,
server->recursionquota.max - 100);
else
} else
isc_quota_soft(&server->recursionquota, 0);
#endif /* !ENABLE_FETCHLIMIT */
CHECK(configure_view_acl(NULL, config, "blackhole", NULL,
ns_g_aclconfctx, ns_g_mctx,
@ -7064,10 +7163,17 @@ dumpdone(void *arg, isc_result_t result) {
goto cleanup;
}
}
if ((dctx->dumpadb || dctx->dumpbad) &&
dctx->cache == NULL && dctx->view->view->cachedb != NULL)
dns_db_attach(dctx->view->view->cachedb, &dctx->cache);
if (dctx->cache != NULL) {
dns_adb_dump(dctx->view->view->adb, dctx->fp);
dns_resolver_printbadcache(dctx->view->view->resolver,
dctx->fp);
if (dctx->dumpadb)
dns_adb_dump(dctx->view->view->adb, dctx->fp);
if (dctx->dumpbad)
dns_resolver_printbadcache(dctx->view->view->resolver,
dctx->fp);
dns_db_detach(&dctx->cache);
}
if (dctx->dumpzones) {
@ -7151,6 +7257,8 @@ ns_server_dumpdb(ns_server_t *server, char *args) {
dctx->mctx = server->mctx;
dctx->dumpcache = ISC_TRUE;
dctx->dumpadb = ISC_TRUE;
dctx->dumpbad = ISC_TRUE;
dctx->dumpzones = ISC_FALSE;
dctx->fp = NULL;
ISC_LIST_INIT(dctx->viewlist);
@ -7174,17 +7282,31 @@ ns_server_dumpdb(ns_server_t *server, char *args) {
ptr = next_token(&args, " \t");
if (ptr != NULL && strcmp(ptr, "-all") == 0) {
/* also dump zones */
dctx->dumpzones = ISC_TRUE;
dctx->dumpcache = ISC_TRUE;
ptr = next_token(&args, " \t");
} else if (ptr != NULL && strcmp(ptr, "-cache") == 0) {
dctx->dumpzones = ISC_FALSE;
dctx->dumpcache = ISC_TRUE;
/* this is the default */
ptr = next_token(&args, " \t");
} else if (ptr != NULL && strcmp(ptr, "-zones") == 0) {
/* only dump zones, suppress caches */
dctx->dumpadb = ISC_FALSE;
dctx->dumpbad = ISC_FALSE;
dctx->dumpcache = ISC_FALSE;
dctx->dumpzones = ISC_TRUE;
ptr = next_token(&args, " \t");
#ifdef ENABLE_FETCHLIMIT
} else if (ptr != NULL && strcmp(ptr, "-adb") == 0) {
/* only dump adb, suppress other caches */
dctx->dumpbad = ISC_FALSE;
dctx->dumpcache = ISC_FALSE;
ptr = next_token(&args, " \t");
} else if (ptr != NULL && strcmp(ptr, "-bad") == 0) {
/* only dump badcache, suppress other caches */
dctx->dumpadb = ISC_FALSE;
dctx->dumpcache = ISC_FALSE;
ptr = next_token(&args, " \t");
#endif /* ENABLE_FETCHLIMIT */
}
nextview:
@ -7278,11 +7400,26 @@ isc_result_t
ns_server_dumprecursing(ns_server_t *server) {
FILE *fp = NULL;
isc_result_t result;
#ifdef ENABLE_FETCHLIMIT
dns_view_t *view;
#endif /* ENABLE_FETCHLIMIT */
CHECKMF(isc_stdio_open(server->recfile, "w", &fp),
"could not open dump file", server->recfile);
fprintf(fp,";\n; Recursing Queries\n;\n");
fprintf(fp, ";\n; Recursing Queries\n;\n");
ns_interfacemgr_dumprecursing(fp, server->interfacemgr);
#ifdef ENABLE_FETCHLIMIT
for (view = ISC_LIST_HEAD(server->viewlist);
view != NULL;
view = ISC_LIST_NEXT(view, link))
{
fprintf(fp, ";\n; Active fetch domains [view: %s]\n;\n",
view->name);
dns_resolver_dumpfetches(view->resolver, fp);
}
#endif /* ENABLE_FETCHLIMIT */
fprintf(fp, "; Dump complete\n");
cleanup:

View file

@ -14,8 +14,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: statschannel.c,v 1.28 2011/03/12 04:59:46 tbox Exp $ */
/*! \file */
#include <config.h>
@ -123,6 +121,8 @@ set_desc(int counter, int maxcounter, const char *fdesc, const char **fdescs,
const char *xdesc, const char **xdescs)
{
REQUIRE(counter < maxcounter);
if (fdescs[counter] != NULL)
fprintf(stderr, "fdescs[%d] == %s\n", counter, fdescs[counter]);
REQUIRE(fdescs[counter] == NULL);
#ifdef HAVE_LIBXML2
REQUIRE(xdescs[counter] == NULL);
@ -168,7 +168,7 @@ init_desc(void) {
SET_NSSTATDESC(sig0in, "requests with SIG(0) received", "ReqSIG0");
SET_NSSTATDESC(invalidsig, "requests with invalid signature",
"ReqBadSIG");
SET_NSSTATDESC(tcp, "TCP requests received", "ReqTCP");
SET_NSSTATDESC(requesttcp, "TCP requests received", "ReqTCP");
SET_NSSTATDESC(authrej, "auth queries rejected", "AuthQryRej");
SET_NSSTATDESC(recurserej, "recursive queries rejected", "RecQryRej");
SET_NSSTATDESC(xfrrej, "transfer requests rejected", "XfrRej");
@ -207,14 +207,32 @@ init_desc(void) {
SET_NSSTATDESC(updatebadprereq,
"updates rejected due to prerequisite failure",
"UpdateBadPrereq");
SET_NSSTATDESC(rpz_rewrites, "response policy zone rewrites",
"RPZRewrites");
#ifdef USE_RRL
SET_NSSTATDESC(recursclients, "recursing clients",
"RecursClients");
SET_NSSTATDESC(dns64, "queries answered by DNS64", "DNS64");
SET_NSSTATDESC(ratedropped, "responses dropped for rate limits",
"RateDropped");
SET_NSSTATDESC(rateslipped, "responses truncated for rate limits",
"RateSlipped");
#endif /* USE_RRL */
SET_NSSTATDESC(rpz_rewrites, "response policy zone rewrites",
"RPZRewrites");
SET_NSSTATDESC(udp, "UDP queries received", "QryUDP");
SET_NSSTATDESC(tcp, "TCP queries received", "QryTCP");
SET_NSSTATDESC(nsidopt, "NSID option received", "NSIDOpt");
SET_NSSTATDESC(expireopt, "Expire option received", "ExpireOpt");
SET_NSSTATDESC(otheropt, "Other EDNS option received", "OtherOpt");
SET_NSSTATDESC(sitopt, "source identity token option received",
"SitOpt");
SET_NSSTATDESC(sitnew, "new source identity token requested",
"SitNew");
SET_NSSTATDESC(sitbadsize, "source identity token - bad size",
"SitBadSize");
SET_NSSTATDESC(sitbadtime, "source identity token - bad time",
"SitBadTime");
SET_NSSTATDESC(sitnomatch, "source identity token - no match",
"SitNoMatch");
SET_NSSTATDESC(sitmatch, "source identity token - match", "SitMatch");
SET_NSSTATDESC(ecsopt, "EDNS client subnet option recieved", "ECSOpt");
INSIST(i == dns_nsstatscounter_max);
/* Initialize resolver statistics */
@ -285,6 +303,10 @@ init_desc(void) {
SET_RESSTATDESC(queryrtt5, "queries with RTT > "
DNS_RESOLVER_QRYRTTCLASS4STR "ms",
"QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR "+");
SET_RESSTATDESC(zonequota, "spilled due to zone quota", "ZoneQuota");
SET_RESSTATDESC(serverquota, "spilled due to server quota",
"ServerQuota");
INSIST(i == dns_resstatscounter_max);
/* Initialize zone statistics */
@ -1055,7 +1077,7 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) {
ISC_XMLCHAR "type=\"text/xsl\" href=\"/bind9.ver3.xsl\""));
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics"));
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version",
ISC_XMLCHAR "3.3"));
ISC_XMLCHAR "3.6"));
/* Set common fields for statistics dump */
dumparg.type = statsformat_xml;

View file

@ -104,7 +104,7 @@ command is one of the following:\n\
Add zone to given view. Requires new-zone-file option.\n\
delzone zone [class [view]]\n\
Removes zone from given view. Requires new-zone-file option.\n\
dumpdb [-all|-cache|-zones] [view ...]\n\
dumpdb [-all|-cache|-zones|-adb|-bad|-fail] [view ...]\n\
Dump cache(s) to the dump file (named_dump.db).\n\
flush Flushes all of the server's caches.\n\
flush [view] Flushes the server's cache for a view.\n\

View file

@ -267,7 +267,7 @@
</varlistentry>
<varlistentry>
<term><userinput>dumpdb <optional>-all|-cache|-zone</optional> <optional><replaceable>view ...</replaceable></optional></userinput></term>
<term><userinput>dumpdb <optional>-all|-cache|-zone|-adb|-bad</optional> <optional><replaceable>view ...</replaceable></optional></userinput></term>
<listitem>
<para>
Dump the server's caches (default) and/or zones to
@ -432,13 +432,17 @@
</varlistentry>
<varlistentry>
<term><userinput>recursing</userinput></term>
<listitem>
<para>
Dump the list of queries <command>named</command> is currently
recursing on.
</para>
</listitem>
<term><userinput>recursing</userinput></term>
<listitem>
<para>
Dump the list of queries <command>named</command> is currently
recursing on, and the list of domains to which iterative
queries are currently being sent. (The second list includes
the number of fetches currently active for the given domain,
and how many have been passed or dropped because of the
<option>fetches-per-zone</option> option.)
</para>
</listitem>
</varlistentry>
<varlistentry>

View file

@ -19,8 +19,8 @@ top_srcdir = @top_srcdir@
@BIND9_MAKE_INCLUDES@
SUBDIRS = builtin dlzexternal filter-aaaa lwresd statistics rpz rrl \
rsabigexponent tkey tsiggss
SUBDIRS = builtin dlzexternal fetchlimit filter-aaaa lwresd \
statistics rpz rrl rsabigexponent tkey tsiggss
TARGETS =
@BIND9_MAKE_RULES@

View file

@ -65,8 +65,9 @@ RANDFILE=$TOP/bin/tests/system/random.data
SUBDIRS="acl additional allow_query addzone autosign builtin
cacheclean case checkconf @CHECKDS@ checknames checkzone
@COVERAGE@ database dlv dlvauto dlz dlzexternal dname dns64
dnssec ecdsa emptyzones filter-aaaa formerr forward glue
gost ixfr inline legacy limits logfileconfig lwresd masterfile
dnssec ecdsa emptyzones
fetchlimit filter-aaaa formerr forward glue gost ixfr inline
legacy limits logfileconfig lwresd masterfile
masterformat metadata notify nslookup nsupdate pending pkcs11
reclimit redirect resolver rndc rpz rrl rrsetorder rsabigexponent
smartsign sortlist spf staticstub stub tkey tsig tsiggss

90
bin/tests/system/ditch.pl Normal file
View file

@ -0,0 +1,90 @@
#!/usr/bin/perl
#
# Copyright (C) 2011, 2012 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.
# This is a tool for sending queries via UDP to specified address and
# port, then exiting without waiting for a response.
#
# Usage: ditch.pl [-s <address>] [-p <port>] [filename]
#
# Input (in filename, if specified, otherwise stdin) is a series of one
# or more DNS names and types to send as queries, e.g.:
#
# www.example.com A
# www.example.org MX
#
# If not specified, address defaults to 127.0.0.1, port to 53.
require 5.006.001;
use strict;
use Getopt::Std;
use Net::DNS;
use Net::DNS::Packet;
use IO::File;
use IO::Socket;
sub usage {
print ("Usage: ditch.pl [-s address] [-p port] [file]\n");
exit 1;
}
my %options={};
getopts("s:p:t:", \%options);
my $addr = "127.0.0.1";
$addr = $options{s} if defined $options{s};
my $port = 53;
$port = $options{p} if defined $options{p};
my $file = "STDIN";
if (@ARGV >= 1) {
my $filename = shift @ARGV;
open FH, "<$filename" or die "$filename: $!";
$file = "FH";
}
my $input = "";
while (defined(my $line = <$file>) ) {
chomp $line;
next if ($line =~ m/^ *#/);
my @tokens = split (' ', $line);
my $packet;
if ($Net::DNS::VERSION > 0.68) {
$packet = new Net::DNS::Packet();
$@ and die $@;
} else {
my $err;
($packet, $err) = new Net::DNS::Packet();
$err and die $err;
}
my $q = new Net::DNS::Question($tokens[0], $tokens[1], "IN");
$packet->header->rd(1);
$packet->push(question => $q);
my $sock = IO::Socket::INET->new(PeerAddr => $addr, PeerPort => $port,
Proto => "udp",) or die "$!";
my $bytes = $sock->send($packet->data);
#print ("sent $bytes bytes to $addr:$port:\n");
#print (" ", unpack("H* ", $packet->data), "\n");
$sock->close;
}
close $file;

View file

@ -26,6 +26,7 @@
#include <stdarg.h>
#include <isc/log.h>
#include <isc/print.h>
#include <isc/result.h>
#include <isc/string.h>
#include <isc/types.h>

View file

@ -0,0 +1,53 @@
# Copyright (C) 2010-2012 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.
srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
@BIND9_VERSION@
@BIND9_MAKE_INCLUDES@
CINCLUDES = ${ISC_INCLUDES}
CDEFINES =
CWARNINGS =
DNSLIBS =
ISCLIBS = .
DNSDEPLIBS =
ISCDEPLIBS =
DEPLIBS =
LIBS = @LIBS@
TARGETS = fetchlimit@EXEEXT@
FILTEROBJS = fetchlimit.@O@
SRCS = fetchlimit.c
@BIND9_MAKE_RULES@
all: fetchlimit@EXEEXT@
fetchlimit@EXEEXT@: ${FILTEROBJS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${FILTEROBJS} ${LIBS}
clean distclean::
rm -f ${TARGETS}

View file

@ -0,0 +1,86 @@
#!/usr/bin/perl -w
#
# 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.
#
# Don't respond if the "norespond" file exists; otherwise respond to
# any A or AAAA query.
#
use IO::File;
use IO::Socket;
use Net::DNS;
use Net::DNS::Packet;
my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.4",
LocalPort => 5300, Proto => "udp") or die "$!";
my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
print $pidf "$$\n" or die "cannot write pid file: $!";
$pidf->close or die "cannot close pid file: $!";
sub rmpid { unlink "ans.pid"; exit 1; };
$SIG{INT} = \&rmpid;
$SIG{TERM} = \&rmpid;
for (;;) {
$sock->recv($buf, 512);
print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
my $packet;
if ($Net::DNS::VERSION > 0.68) {
$packet = new Net::DNS::Packet(\$buf, 0);
$@ and die $@;
} else {
my $err;
($packet, $err) = new Net::DNS::Packet(\$buf, 0);
$err and die $err;
}
print "REQUEST:\n";
$packet->print;
$packet->header->qr(1);
my @questions = $packet->question;
my $qname = $questions[0]->qname;
my $qtype = $questions[0]->qtype;
my $donotrespond = 0;
if (-e 'norespond') {
$donotrespond = 1;
} else {
$packet->header->aa(1);
if ($qtype eq "A") {
$packet->push("answer",
new Net::DNS::RR($qname .
" 300 A 192.0.2.1"));
} elsif ($qtype eq "AAAA") {
$packet->push("answer",
new Net::DNS::RR($qname .
" 300 AAAA 2001:db8:beef::1"));
}
}
if ($donotrespond == 0) {
$sock->send($packet->data);
print "RESPONSE:\n";
$packet->print;
print "\n";
}
}

View file

@ -0,0 +1,21 @@
#!/bin/sh
#
# 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.
rm -f */named.memstats */ans.run */named.recursing
rm -f dig.out*
rm -f ans4/norespond
rm -f ns3/named.conf ns3/named.stats ns3/named_dump.db
rm -f burst.input.*

View file

@ -0,0 +1,31 @@
/*
* Copyright (C) 2015 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.
*/
#include <config.h>
#include <isc/util.h>
int
main(int argc, char **argv) {
UNUSED(argc);
UNUSED(argv);
#ifdef ENABLE_FETCHLIMIT
return (0);
#else
return (1);
#endif
}

View file

@ -0,0 +1,86 @@
#!/usr/bin/perl -w
#
# 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.
#
# Don't respond if the "norespond" file exists; otherwise respond to
# any A or AAAA query.
#
use IO::File;
use IO::Socket;
use Net::DNS;
use Net::DNS::Packet;
my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.4",
LocalPort => 5300, Proto => "udp") or die "$!";
my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
print $pidf "$$\n" or die "cannot write pid file: $!";
$pidf->close or die "cannot close pid file: $!";
sub rmpid { unlink "ans.pid"; exit 1; };
$SIG{INT} = \&rmpid;
$SIG{TERM} = \&rmpid;
for (;;) {
$sock->recv($buf, 512);
print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
my $packet;
if ($Net::DNS::VERSION > 0.68) {
$packet = new Net::DNS::Packet(\$buf, 0);
$@ and die $@;
} else {
my $err;
($packet, $err) = new Net::DNS::Packet(\$buf, 0);
$err and die $err;
}
print "REQUEST:\n";
$packet->print;
$packet->header->qr(1);
my @questions = $packet->question;
my $qname = $questions[0]->qname;
my $qtype = $questions[0]->qtype;
my $donotrespond = 0;
if (-e 'norespond') {
$donotrespond = 1;
} else {
$packet->header->aa(1);
if ($qtype eq "A") {
$packet->push("answer",
new Net::DNS::RR($qname .
" 300 A 192.0.2.1"));
} elsif ($qtype eq "AAAA") {
$packet->push("answer",
new Net::DNS::RR($qname .
" 300 AAAA 2001:db8:beef::1"));
}
}
if ($donotrespond == 0) {
$sock->send($packet->data);
print "RESPONSE:\n";
$packet->print;
print "\n";
}
}

View file

@ -0,0 +1,20 @@
#!/bin/sh
#
# 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.
rm -f */named.memstats */ans.run */named.recursing
rm -f dig.out*
rm -f ans4/norespond
rm -f ns3/named.conf ns3/named.stats ns3/named_dump.db

View file

@ -0,0 +1,39 @@
/*
* 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.
*/
controls { /* empty */ };
options {
query-source address 10.53.0.1;
notify-source 10.53.0.1;
transfer-source 10.53.0.1;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.1; };
listen-on-v6 { none; };
recursion no;
notify yes;
};
zone "." {
type master;
file "root.db";
};
zone "example.info." {
type master;
file "example-info.db";
};

View file

@ -0,0 +1,29 @@
; 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.
; $Id$
$TTL 300
. IN SOA gson.nominum.com. a.root.servers.nil. (
2000042100 ; serial
600 ; refresh
600 ; retry
1200 ; expire
600 ; minimum
)
. NS a.root-servers.nil.
a.root-servers.nil. A 10.53.0.1
example. NS ns2.example.
ns2.example. A 10.53.0.2

View file

@ -0,0 +1,40 @@
; 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.
$ORIGIN .
$TTL 300 ; 5 minutes
example IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
example NS ns2.example.
ns2.example. A 10.53.0.2
a.example. A 10.0.0.1
MX 10 mail.example.
mail.example. A 10.0.0.2
lamesub.example. NS ns4.example.
ns4.example. A 10.53.0.4
0.example. A 10.53.1.0
1.example. A 10.53.1.1
2.example. A 10.53.1.2
3.example. A 10.53.1.3
4.example. A 10.53.1.4
5.example. A 10.53.1.5

View file

@ -0,0 +1,37 @@
/*
* 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.
*/
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;
};
include "../../common/controls.conf";
zone "example" {
type master;
file "example.db";
allow-update { any; };
};

View file

@ -0,0 +1,45 @@
/*
* 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.
*/
controls { /* empty */ };
options {
query-source address 10.53.0.3;
notify-source 10.53.0.3;
transfer-source 10.53.0.3;
port 5300;
directory ".";
pid-file "named.pid";
listen-on { 10.53.0.3; };
listen-on-v6 { none; };
recursion yes;
notify yes;
fetches-per-server 400;
};
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
};
zone "." {
type hint;
file "root.hint";
};

View file

@ -0,0 +1,45 @@
/*
* 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.
*/
controls { /* empty */ };
options {
query-source address 10.53.0.3;
notify-source 10.53.0.3;
transfer-source 10.53.0.3;
port 5300;
directory ".";
pid-file "named.pid";
listen-on { 10.53.0.3; };
listen-on-v6 { none; };
recursion yes;
notify yes;
fetches-per-zone 40;
};
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
};
zone "." {
type hint;
file "root.hint";
};

View file

@ -0,0 +1,45 @@
/*
* 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.
*/
controls { /* empty */ };
options {
query-source address 10.53.0.3;
notify-source 10.53.0.3;
transfer-source 10.53.0.3;
port 5300;
directory ".";
pid-file "named.pid";
listen-on { 10.53.0.3; };
listen-on-v6 { none; };
recursion yes;
notify yes;
recursive-clients 400;
};
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
};
zone "." {
type hint;
file "root.hint";
};

View file

@ -0,0 +1,19 @@
; 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.
; $Id$
$TTL 999999
. IN NS a.root-servers.nil.
a.root-servers.nil. IN A 10.53.0.1

View file

@ -0,0 +1,22 @@
#!/bin/sh
#
# 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.
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
$SHELL clean.sh
cp -f ns3/named1.conf ns3/named.conf

View file

@ -0,0 +1,183 @@
#!/bin/sh
#
# 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.
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
DIGCMD="$DIG @10.53.0.3 -p 5300 +tries=1 +time=1"
RNDCCMD="$RNDC -p 9953 -s 10.53.0.3 -c ../common/rndc.conf"
burst() {
num=${3:-20}
while [ $num -gt 0 ]; do
num=`expr $num - 1`
$DIGCMD ${num}${1}${2}.lamesub.example a > /dev/null 2>&1 &
done
}
stat() {
clients=`$RNDCCMD status | grep "recursive clients" |
sed 's;.*: \([^/][^/]*\)/.*;\1;'`
echo "I: clients: $clients"
[ "$clients" = "" ] && return 1
[ "$clients" -le $1 ]
}
status=0
echo "I: checking recursing clients are dropped at the per-server limit"
ret=0
# make the server lame and restart
$RNDCCMD flush
touch ans4/norespond
for try in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
burst a $try
# fetches-per-server is at 400, but at 20qps against a lame server,
# we'll reach 200 at the tenth second, and the quota should have been
# tuned to less than that by then
stat 200 || ret=1
[ $ret -eq 1 ] && break
sleep 1
done
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
echo "I: dumping ADB data"
$RNDCCMD dumpdb -adb
info=`grep '10.53.0.4' ns3/named_dump.db | sed 's/.*\(atr [.0-9]*\).*\(quota [0-9]*\).*/I: \1 \2/'`
echo $info
set -- $info
quota=$5
[ $5 -lt 200 ] || ret=1
echo "I: checking servfail statistics"
rm -f ns3/named.stats
$RNDCCMD stats
for try in 1 2 3 4 5; do
[ -f ns3/named.stats ] && break
sleep 1
done
sspill=`grep 'spilled due to server' ns3/named.stats | sed 's/\([0-9][0-9]*\) spilled.*/\1/'`
[ -z "$sspill" ] && sspill=0
fails=`grep 'queries resulted in SERVFAIL' ns3/named.stats | sed 's/\([0-9][0-9]*\) queries.*/\1/'`
[ -z "$fails" ] && fails=0
[ "$fails" -ge "$sspill" ] || ret=1
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
echo "I: checking lame server recovery"
ret=0
rm -f ans4/norespond
for try in 1 2 3 4 5; do
burst b $try
stat 200 || ret=1
[ $ret -eq 1 ] && break
sleep 1
done
echo "I: dumping ADB data"
$RNDCCMD dumpdb -adb
info=`grep '10.53.0.4' ns3/named_dump.db | sed 's/.*\(atr [.0-9]*\).*\(quota [0-9]*\).*/I: \1 \2/'`
echo $info
set -- $info
[ $5 -lt $quota ] || ret=1
quota=$5
for try in 1 2 3 4 5 6 7 8 9 10; do
burst c $try
stat 20 || ret=1
[ $ret -eq 1 ] && break
sleep 1
done
echo "I: dumping ADB data"
$RNDCCMD dumpdb -adb
info=`grep '10.53.0.4' ns3/named_dump.db | sed 's/.*\(atr [.0-9]*\).*\(quota [0-9]*\).*/I: \1 \2/'`
echo $info
set -- $info
[ $5 -gt $quota ] || ret=1
quota=$5
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
cp -f ns3/named2.conf ns3/named.conf
$RNDCCMD reconfig 2>&1 | sed 's/^/I:ns3 /'
echo "I: checking lame server clients are dropped at the per-domain limit"
ret=0
fail=0
success=0
touch ans4/norespond
for try in 1 2 3 4 5; do
burst b $try 300
$DIGCMD a ${try}.example > dig.out.ns3.$try
grep "status: NOERROR" dig.out.ns3.$try > /dev/null 2>&1 && \
success=`expr $success + 1`
grep "status: SERVFAIL" dig.out.ns3.$try > /dev/null 2>&1 && \
fail=`expr $fail + 1`
stat 50 || ret=1
[ $ret -eq 1 ] && break
$RNDCCMD recursing 2>&1 | sed 's/^/I:ns3 /'
sleep 1
done
echo "I: $success successful valid queries, $fail SERVFAIL"
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
echo "I: checking drop statsistics"
rm -f ns3/named.stats
$RNDCCMD stats
for try in 1 2 3 4 5; do
[ -f ns3/named.stats ] && break
sleep 1
done
zspill=`grep 'spilled due to zone' ns3/named.stats | sed 's/\([0-9][0-9]*\) spilled.*/\1/'`
[ -z "$zspill" ] && zspill=0
drops=`grep 'queries dropped' ns3/named.stats | sed 's/\([0-9][0-9]*\) queries.*/\1/'`
[ -z "$drops" ] && drops=0
[ "$drops" -ge "$zspill" ] || ret=1
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
cp -f ns3/named3.conf ns3/named.conf
$RNDCCMD reconfig 2>&1 | sed 's/^/I:ns3 /'
echo "I: checking lame server clients are dropped at the soft limit"
ret=0
fail=0
success=0
touch ans4/norespond
for try in 1 2 3 4 5; do
burst b $try 400
$DIGCMD a ${try}.example > dig.out.ns3.$try
stat 360 || ret=1
grep "status: NOERROR" dig.out.ns3.$try > /dev/null 2>&1 && \
success=`expr $success + 1`
grep "status: SERVFAIL" dig.out.ns3.$try > /dev/null 2>&1 && \
fail=`expr $fail + 1`
[ $ret -eq 1 ] && break
sleep 1
done
echo "I: $success successful valid queries, $fail SERVFAIL"
[ "$success" -eq 5 ] || ret=1
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
echo "I:exit status: $status"
exit $status

View file

@ -0,0 +1,39 @@
/*
* 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.
*/
controls { /* empty */ };
options {
query-source address 10.53.0.1;
notify-source 10.53.0.1;
transfer-source 10.53.0.1;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.1; };
listen-on-v6 { none; };
recursion no;
notify yes;
};
zone "." {
type master;
file "root.db";
};
zone "example.info." {
type master;
file "example-info.db";
};

View file

@ -0,0 +1,29 @@
; 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.
; $Id$
$TTL 300
. IN SOA gson.nominum.com. a.root.servers.nil. (
2000042100 ; serial
600 ; refresh
600 ; retry
1200 ; expire
600 ; minimum
)
. NS a.root-servers.nil.
a.root-servers.nil. A 10.53.0.1
example. NS ns2.example.
ns2.example. A 10.53.0.2

View file

@ -0,0 +1,40 @@
; 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.
$ORIGIN .
$TTL 300 ; 5 minutes
example IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
example NS ns2.example.
ns2.example. A 10.53.0.2
a.example. A 10.0.0.1
MX 10 mail.example.
mail.example. A 10.0.0.2
lamesub.example. NS ns4.example.
ns4.example. A 10.53.0.4
0.example. A 10.53.1.0
1.example. A 10.53.1.1
2.example. A 10.53.1.2
3.example. A 10.53.1.3
4.example. A 10.53.1.4
5.example. A 10.53.1.5

View file

@ -0,0 +1,37 @@
/*
* 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.
*/
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;
};
include "../../common/controls.conf";
zone "example" {
type master;
file "example.db";
allow-update { any; };
};

View file

@ -0,0 +1,2 @@
# Don't specify '-T clienttest' as it consumes lots of memory with this test
-m record,size,mctx -c named.conf -d 99 -g -U 4

View file

@ -0,0 +1,45 @@
/*
* 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.
*/
controls { /* empty */ };
options {
query-source address 10.53.0.3;
notify-source 10.53.0.3;
transfer-source 10.53.0.3;
port 5300;
directory ".";
pid-file "named.pid";
listen-on { 10.53.0.3; };
listen-on-v6 { none; };
recursion yes;
notify yes;
fetches-per-server 400;
};
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
};
zone "." {
type hint;
file "root.hint";
};

View file

@ -0,0 +1,45 @@
/*
* 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.
*/
controls { /* empty */ };
options {
query-source address 10.53.0.3;
notify-source 10.53.0.3;
transfer-source 10.53.0.3;
port 5300;
directory ".";
pid-file "named.pid";
listen-on { 10.53.0.3; };
listen-on-v6 { none; };
recursion yes;
notify yes;
fetches-per-zone 40;
};
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
};
zone "." {
type hint;
file "root.hint";
};

View file

@ -0,0 +1,45 @@
/*
* 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.
*/
controls { /* empty */ };
options {
query-source address 10.53.0.3;
notify-source 10.53.0.3;
transfer-source 10.53.0.3;
port 5300;
directory ".";
pid-file "named.pid";
listen-on { 10.53.0.3; };
listen-on-v6 { none; };
recursion yes;
notify yes;
recursive-clients 400;
};
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
};
zone "." {
type hint;
file "root.hint";
};

View file

@ -0,0 +1,19 @@
; 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.
; $Id$
$TTL 999999
. IN NS a.root-servers.nil.
a.root-servers.nil. IN A 10.53.0.1

View file

@ -0,0 +1,40 @@
#!/bin/sh
#
# Copyright (C) 2015 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.
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
if ./fetchlimit
then
:
else
echo "I:This test requires --enable-fetchlimit at compile time." >&2
exit 255
fi
if $PERL -e 'use Net::DNS;' 2>/dev/null
then
if $PERL -e 'use Net::DNS; die if ($Net::DNS::VERSION >= 0.76 && $Net::DNS::VERSION <= 0.77);' 2>/dev/null
then
:
else
echo "I:Net::DNS version 0.76 and 0.77 have a bug that causes this test to fail: please update." >&2
exit 1
fi
else
echo "I:This test requires the Net::DNS library." >&2
exit 1
fi

View file

@ -0,0 +1,22 @@
#!/bin/sh
#
# 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.
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
$SHELL clean.sh
cp -f ns3/named1.conf ns3/named.conf

View file

@ -0,0 +1,186 @@
#!/bin/sh
#
# 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.
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
DIGCMD="$DIG @10.53.0.3 -p 5300 +tries=1 +time=1"
RNDCCMD="$RNDC -p 9953 -s 10.53.0.3 -c ../common/rndc.conf"
burst() {
num=${3:-20}
rm -f burst.input.$$
while [ $num -gt 0 ]; do
num=`expr $num - 1`
echo "${num}${1}${2}.lamesub.example A" >> burst.input.$$
done
$PERL ../ditch.pl -p 5300 -s 10.53.0.3 burst.input.$$
rm -f burst.input.$$
}
stat() {
clients=`$RNDCCMD status | grep "recursive clients" |
sed 's;.*: \([^/][^/]*\)/.*;\1;'`
echo "I: clients: $clients"
[ "$clients" = "" ] && return 1
[ "$clients" -le $1 ]
}
status=0
echo "I: checking recursing clients are dropped at the per-server limit"
ret=0
# make the server lame and restart
$RNDCCMD flush
touch ans4/norespond
for try in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
burst a $try
# fetches-per-server is at 400, but at 20qps against a lame server,
# we'll reach 200 at the tenth second, and the quota should have been
# tuned to less than that by then
stat 200 || ret=1
[ $ret -eq 1 ] && break
sleep 1
done
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
echo "I: dumping ADB data"
$RNDCCMD dumpdb -adb
info=`grep '10.53.0.4' ns3/named_dump.db | sed 's/.*\(atr [.0-9]*\).*\(quota [0-9]*\).*/I: \1 \2/'`
echo $info
set -- $info
quota=$5
[ ${5:-200} -lt 200 ] || ret=1
echo "I: checking servfail statistics"
rm -f ns3/named.stats
$RNDCCMD stats
for try in 1 2 3 4 5; do
[ -f ns3/named.stats ] && break
sleep 1
done
sspill=`grep 'spilled due to server' ns3/named.stats | sed 's/\([0-9][0-9]*\) spilled.*/\1/'`
[ -z "$sspill" ] && sspill=0
fails=`grep 'queries resulted in SERVFAIL' ns3/named.stats | sed 's/\([0-9][0-9]*\) queries.*/\1/'`
[ -z "$fails" ] && fails=0
[ "$fails" -ge "$sspill" ] || ret=1
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
echo "I: checking lame server recovery"
ret=0
rm -f ans4/norespond
for try in 1 2 3 4 5; do
burst b $try
stat 200 || ret=1
[ $ret -eq 1 ] && break
sleep 1
done
echo "I: dumping ADB data"
$RNDCCMD dumpdb -adb
info=`grep '10.53.0.4' ns3/named_dump.db | sed 's/.*\(atr [.0-9]*\).*\(quota [0-9]*\).*/I: \1 \2/'`
echo $info
set -- $info
[ ${5:-${quota}} -lt $quota ] || ret=1
quota=$5
for try in 1 2 3 4 5 6 7 8 9 10; do
burst c $try
stat 20 || ret=1
[ $ret -eq 1 ] && break
sleep 1
done
echo "I: dumping ADB data"
$RNDCCMD dumpdb -adb
info=`grep '10.53.0.4' ns3/named_dump.db | sed 's/.*\(atr [.0-9]*\).*\(quota [0-9]*\).*/I: \1 \2/'`
echo $info
set -- $info
[ ${5:-${quota}} -gt $quota ] || ret=1
quota=$5
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
cp -f ns3/named2.conf ns3/named.conf
$RNDCCMD reconfig 2>&1 | sed 's/^/I:ns3 /'
echo "I: checking lame server clients are dropped at the per-domain limit"
ret=0
fail=0
success=0
touch ans4/norespond
for try in 1 2 3 4 5; do
burst b $try 300
$DIGCMD a ${try}.example > dig.out.ns3.$try
grep "status: NOERROR" dig.out.ns3.$try > /dev/null 2>&1 && \
success=`expr $success + 1`
grep "status: SERVFAIL" dig.out.ns3.$try > /dev/null 2>&1 && \
fail=`expr $fail + 1`
stat 50 || ret=1
[ $ret -eq 1 ] && break
$RNDCCMD recursing 2>&1 | sed 's/^/I:ns3 /'
sleep 1
done
echo "I: $success successful valid queries, $fail SERVFAIL"
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
echo "I: checking drop statistics"
rm -f ns3/named.stats
$RNDCCMD stats
for try in 1 2 3 4 5; do
[ -f ns3/named.stats ] && break
sleep 1
done
zspill=`grep 'spilled due to zone' ns3/named.stats | sed 's/\([0-9][0-9]*\) spilled.*/\1/'`
[ -z "$zspill" ] && zspill=0
drops=`grep 'queries dropped' ns3/named.stats | sed 's/\([0-9][0-9]*\) queries.*/\1/'`
[ -z "$drops" ] && drops=0
[ "$drops" -ge "$zspill" ] || ret=1
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
cp -f ns3/named3.conf ns3/named.conf
$RNDCCMD reconfig 2>&1 | sed 's/^/I:ns3 /'
echo "I: checking lame server clients are dropped at the soft limit"
ret=0
fail=0
success=0
touch ans4/norespond
for try in 1 2 3 4 5; do
burst b $try 400
$DIG @10.53.0.3 -p 5300 a ${try}.example > dig.out.ns3.$try
stat 360 || ret=1
grep "status: NOERROR" dig.out.ns3.$try > /dev/null 2>&1 && \
success=`expr $success + 1`
grep "status: SERVFAIL" dig.out.ns3.$try > /dev/null 2>&1 && \
fail=`expr $fail + 1`
[ $ret -eq 1 ] && break
sleep 1
done
echo "I: $success successful valid queries, $fail SERVFAIL"
[ "$success" -eq 5 ] || ret=1
if [ $ret != 0 ]; then echo "I: failed"; fi
status=`expr $status + $ret`
echo "I:exit status: $status"
exit $status

View file

@ -15,8 +15,6 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id$
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
@ -63,7 +61,7 @@ if [ -x ${SAMPLE} ] ; then
echo "I:checking handling of bogus referrals using dns_client"
ret=0
${SAMPLE} -p 5300 -t a 10.53.0.1 www.example.com 2> sample.out || ret=1
grep "resolution failed: failure" sample.out > /dev/null || ret=1
egrep "resolution failed: (failure|SERVFAIL)" sample.out > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
fi
@ -387,7 +385,6 @@ grep "not subdomain of zone" ns1/named.run > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
#HERE <<<
cp ns7/named2.conf ns7/named.conf
$RNDC -c ../common/rndc.conf -s 10.53.0.7 -p 9953 reconfig 2>&1 | sed 's/^/I:ns7 /'

View file

@ -169,6 +169,10 @@ int sigwait(const unsigned int *set, int *sig);
/* Define to enable "rrset-order fixed" syntax. */
#undef DNS_RDATASET_FIXED
/* Define to enable the "fetches-per-server" and "fetches-per-zone" options.
*/
#undef ENABLE_FETCHLIMIT
/* Define to enable rpz-nsdname rules. */
#undef ENABLE_RPZ_NSDNAME

34
configure vendored
View file

@ -1002,6 +1002,7 @@ enable_atomic
enable_fixed_rrset
enable_rpz_nsip
enable_rpz_nsdname
enable_fetchlimit
enable_filter_aaaa
with_docbook_xsl
with_idn
@ -1681,6 +1682,7 @@ Optional Features:
[default=no]
--disable-rpz-nsip disable rpz-nsip rules [default=enabled]
--disable-rpz-nsdname disable rpz-nsdname rules [default=enabled]
--enable-fetchlimit enable recursive fetch limits [default=no]
--enable-filter-aaaa enable filtering of AAAA records over IPv4
[default=no]
--enable-querytrace enable very verbose query trace logging [default=no]
@ -11434,6 +11436,7 @@ yes)
;;
esac
test "${enable_symtable+set}" = set || enable_symtable=all
test "${enable_fetchlimit+set}" = set || enable_fetchlimit=yes
test "${enable_warn_error+set}" = set || enable_warn_error=yes
test "${enable_warn_shadow+set}" = set || enable_warn_shadow=yes
;;
@ -18761,7 +18764,29 @@ $as_echo "#define ENABLE_RPZ_NSDNAME 1" >>confdefs.h
esac
#
# Activate "filter-aaaa-on-v4" or not?
# Activate recursive fetch limits
#
# Check whether --enable-fetchlimit was given.
if test "${enable_fetchlimit+set}" = set; then :
enableval=$enable_fetchlimit; enable_fetchlimit="$enableval"
else
enable_fetchlimit="no"
fi
case "$enable_fetchlimit" in
yes)
$as_echo "#define ENABLE_FETCHLIMIT 1" >>confdefs.h
;;
no)
;;
*)
;;
esac
#
# Activate "filter-aaaa" or not?
#
# Check whether --enable-filter-aaaa was given.
if test "${enable_filter_aaaa+set}" = set; then :
@ -20882,7 +20907,7 @@ ac_config_commands="$ac_config_commands chmod"
# elsewhere if there's a good reason for doing so.
#
ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/python/dnssec-coverage.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/builtin/Makefile bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/filter-aaaa/Makefile bin/tests/system/inline/checkdsa.sh bin/tests/system/lwresd/Makefile bin/tests/system/statistics/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rrl/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/check-secure-delegation.pl contrib/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl doc/xsl/isc-notes-html.xsl doc/xsl/isc-notes-latex.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/export/Makefile lib/export/dns/Makefile lib/export/dns/include/Makefile lib/export/dns/include/dns/Makefile lib/export/dns/include/dst/Makefile lib/export/irs/Makefile lib/export/irs/include/Makefile lib/export/irs/include/irs/Makefile lib/export/isc/$thread_dir/Makefile lib/export/isc/$thread_dir/include/Makefile lib/export/isc/$thread_dir/include/isc/Makefile lib/export/isc/Makefile lib/export/isc/include/Makefile lib/export/isc/include/isc/Makefile lib/export/isc/nls/Makefile lib/export/isc/unix/Makefile lib/export/isc/unix/include/Makefile lib/export/isc/unix/include/isc/Makefile lib/export/isccfg/Makefile lib/export/isccfg/include/Makefile lib/export/isccfg/include/isccfg/Makefile lib/export/samples/Makefile lib/export/samples/Makefile-postinstall lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/tests/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile unit/Makefile unit/unittest.sh"
ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/python/dnssec-coverage.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/builtin/Makefile bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/fetchlimit/Makefile bin/tests/system/filter-aaaa/Makefile bin/tests/system/inline/checkdsa.sh bin/tests/system/lwresd/Makefile bin/tests/system/statistics/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rrl/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/check-secure-delegation.pl contrib/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl doc/xsl/isc-notes-html.xsl doc/xsl/isc-notes-latex.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/export/Makefile lib/export/dns/Makefile lib/export/dns/include/Makefile lib/export/dns/include/dns/Makefile lib/export/dns/include/dst/Makefile lib/export/irs/Makefile lib/export/irs/include/Makefile lib/export/irs/include/irs/Makefile lib/export/isc/$thread_dir/Makefile lib/export/isc/$thread_dir/include/Makefile lib/export/isc/$thread_dir/include/isc/Makefile lib/export/isc/Makefile lib/export/isc/include/Makefile lib/export/isc/include/isc/Makefile lib/export/isc/nls/Makefile lib/export/isc/unix/Makefile lib/export/isc/unix/include/Makefile lib/export/isc/unix/include/isc/Makefile lib/export/isccfg/Makefile lib/export/isccfg/include/Makefile lib/export/isccfg/include/isccfg/Makefile lib/export/samples/Makefile lib/export/samples/Makefile-postinstall lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/tests/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile unit/Makefile unit/unittest.sh"
#
@ -21927,6 +21952,7 @@ do
"bin/tests/system/dlz/prereq.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dlz/prereq.sh" ;;
"bin/tests/system/dlzexternal/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dlzexternal/Makefile" ;;
"bin/tests/system/dlzexternal/ns1/named.conf") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dlzexternal/ns1/named.conf" ;;
"bin/tests/system/fetchlimit/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/fetchlimit/Makefile" ;;
"bin/tests/system/filter-aaaa/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/filter-aaaa/Makefile" ;;
"bin/tests/system/inline/checkdsa.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/inline/checkdsa.sh" ;;
"bin/tests/system/lwresd/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/lwresd/Makefile" ;;
@ -23334,6 +23360,8 @@ $use_threads && echo " Multiprocessing support (--enable-threads)"
test "$enable_rrl" = "yes" && \
echo " Response Rate Limiting (--enable-rrl)"
test "$enable_fetchlimit" = "yes" && \
echo " Recursive fetch limits for DoS attack mitigation (--enable-fetchlimit)"
test "$use_gssapi" = "no" || echo " GSS-API (--with-gssapi)"
test "$use_pkcs11" = "no" || echo " PKCS#11/Cryptoki support (--with-pkcs11)"
test "$enable_newstats" = "yes" && \
@ -23390,6 +23418,8 @@ test "$enable_ipv6" = "no" -o "$found_ipv6" = "no" && \
echo " IPv6 support (--enable-ipv6)"
test "$enable_rrl" = "yes" || \
echo " Response Rate Limiting (--enable-rrl)"
test "$enable_fetchlimit" = "no" && \
echo " Recursive fetch limits for DoS attack mitigation (--enable-fetchlimit)"
test "$use_gssapi" = "no" && echo " GSS-API (--with-gssapi)"
test "$use_pkcs11" = "no" && echo " PKCS#11/Cryptoki support (--with-pkcs11)"
test "X$enable_newstats" = "X" && echo " New statistics (--enable-newstats)"

View file

@ -86,6 +86,7 @@ yes)
;;
esac
test "${enable_symtable+set}" = set || enable_symtable=all
test "${enable_fetchlimit+set}" = set || enable_fetchlimit=yes
test "${enable_warn_error+set}" = set || enable_warn_error=yes
test "${enable_warn_shadow+set}" = set || enable_warn_shadow=yes
;;
@ -3282,7 +3283,25 @@ case "$enable_nsdname" in
esac
#
# Activate "filter-aaaa-on-v4" or not?
# Activate recursive fetch limits
#
AC_ARG_ENABLE(fetchlimit,
[ --enable-fetchlimit enable recursive fetch limits [[default=no]]],
enable_fetchlimit="$enableval",
enable_fetchlimit="no")
case "$enable_fetchlimit" in
yes)
AC_DEFINE(ENABLE_FETCHLIMIT, 1,
[Define to enable the "fetches-per-server" and "fetches-per-zone" options.])
;;
no)
;;
*)
;;
esac
#
# Activate "filter-aaaa" or not?
#
AC_ARG_ENABLE(filter-aaaa,
[ --enable-filter-aaaa enable filtering of AAAA records over IPv4
@ -4022,6 +4041,7 @@ AC_CONFIG_FILES([
bin/tests/system/dlz/prereq.sh
bin/tests/system/dlzexternal/Makefile
bin/tests/system/dlzexternal/ns1/named.conf
bin/tests/system/fetchlimit/Makefile
bin/tests/system/filter-aaaa/Makefile
bin/tests/system/inline/checkdsa.sh
bin/tests/system/lwresd/Makefile
@ -4156,6 +4176,8 @@ $use_threads && echo " Multiprocessing support (--enable-threads)"
test "$enable_rrl" = "yes" && \
echo " Response Rate Limiting (--enable-rrl)"
test "$enable_fetchlimit" = "yes" && \
echo " Recursive fetch limits for DoS attack mitigation (--enable-fetchlimit)"
test "$use_gssapi" = "no" || echo " GSS-API (--with-gssapi)"
test "$use_pkcs11" = "no" || echo " PKCS#11/Cryptoki support (--with-pkcs11)"
test "$enable_newstats" = "yes" && \
@ -4212,6 +4234,8 @@ test "$enable_ipv6" = "no" -o "$found_ipv6" = "no" && \
echo " IPv6 support (--enable-ipv6)"
test "$enable_rrl" = "yes" || \
echo " Response Rate Limiting (--enable-rrl)"
test "$enable_fetchlimit" = "no" && \
echo " Recursive fetch limits for DoS attack mitigation (--enable-fetchlimit)"
test "$use_gssapi" = "no" && echo " GSS-API (--with-gssapi)"
test "$use_pkcs11" = "no" && echo " PKCS#11/Cryptoki support (--with-pkcs11)"
test "X$enable_newstats" = "X" && echo " New statistics (--enable-newstats)"

View file

@ -4784,9 +4784,14 @@ badresp:1,adberr:0,findfail:0,valfail:0]
<optional> max-transfer-time-out <replaceable>number</replaceable>; </optional>
<optional> max-transfer-idle-in <replaceable>number</replaceable>; </optional>
<optional> max-transfer-idle-out <replaceable>number</replaceable>; </optional>
<optional> tcp-clients <replaceable>number</replaceable>; </optional>
<optional> reserved-sockets <replaceable>number</replaceable>; </optional>
<optional> recursive-clients <replaceable>number</replaceable>; </optional>
<optional> tcp-clients <replaceable>number</replaceable>; </optional>
<optional> clients-per-query <replaceable>number</replaceable> ; </optional>
<optional> max-clients-per-query <replaceable>number</replaceable> ; </optional>
<optional> fetches-per-server <replaceable>number</replaceable> <optional><replaceable>(drop | fail)</replaceable></optional>; </optional>
<optional> fetch-quota-params <replaceable>number fixedpoint fixedpoint fixedpoint</replaceable> ; </optional>
<optional> fetches-per-zone<replaceable>number</replaceable> <optional><replaceable>(drop | fail)</replaceable></optional>; </optional>
<optional> serial-query-rate <replaceable>number</replaceable>; </optional>
<optional> serial-queries <replaceable>number</replaceable>; </optional>
<optional> tcp-listen-queue <replaceable>number</replaceable>; </optional>
@ -4865,8 +4870,6 @@ badresp:1,adberr:0,findfail:0,valfail:0]
<optional> acache-enable <replaceable>yes_or_no</replaceable> ; </optional>
<optional> acache-cleaning-interval <replaceable>number</replaceable>; </optional>
<optional> max-acache-size <replaceable>size_spec</replaceable> ; </optional>
<optional> clients-per-query <replaceable>number</replaceable> ; </optional>
<optional> max-clients-per-query <replaceable>number</replaceable> ; </optional>
<optional> max-recursion-depth <replaceable>number</replaceable> ; </optional>
<optional> max-recursion-queries <replaceable>number</replaceable> ; </optional>
<optional> masterfile-format (<constant>text</constant>|<constant>raw</constant>) ; </optional>
@ -7933,17 +7936,33 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
<term><command>recursive-clients</command></term>
<listitem>
<para>
The maximum number of simultaneous recursive lookups
the server will perform on behalf of clients. The default
is
The maximum number ("hard quota") of simultaneous
recursive lookups the server will perform on behalf
of clients. The default is
<literal>1000</literal>. Because each recursing
client uses a fair
bit of memory, on the order of 20 kilobytes, the value of
the
bit of memory (on the order of 20 kilobytes), the
value of the
<command>recursive-clients</command> option may
have to be decreased
on hosts with limited memory.
have to be decreased on hosts with limited memory.
</para>
<para>
<option>recursive-clients</option> defines a "hard
quota" limit for pending recursive clients: when more
clients than this are pending, new incoming requests
will not be accepted, and for each incoming request
a previous pending request will also be dropped.
</para>
<para>
A "soft quota" is also set. When this lower
quota is exceeded, incoming requests are accepted, but
for each one, a pending request will be dropped.
If <option>recursive-clients</option> is greater than
1000, the soft quota is set to
<option>recursive-clients</option> minus 100;
otherwise it is set to 90% of
<option>recursive-clients</option>.
</para>
</listitem>
</varlistentry>
@ -7958,6 +7977,187 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
</listitem>
</varlistentry>
<varlistentry id="clients-per-query">
<term><command>clients-per-query</command></term>
<term><command>max-clients-per-query</command></term>
<listitem>
<para>These set the
initial value (minimum) and maximum number of recursive
simultaneous clients for any given query
(&lt;qname,qtype,qclass&gt;) that the server will accept
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>
<para>
This value should reflect how many queries come in for
a given name in the time it takes to resolve that name.
If the number of queries exceed this value, <command>named</command> will
assume that it is dealing with a non-responsive zone
and will drop additional queries. If it gets a response
after dropping queries, it will raise the estimate. The
estimate will then be lowered in 20 minutes if it has
remained unchanged.
</para>
<para>
If <command>clients-per-query</command> is set to zero,
then there is no limit on the number of clients per query
and no queries will be dropped.
</para>
<para>
If <command>max-clients-per-query</command> is set to zero,
then there is no upper bound other than imposed by
<command>recursive-clients</command>.
</para>
</listitem>
</varlistentry>
<varlistentry id="fetches-per-zone">
<term><command>fetches-per-zone</command></term>
<listitem>
<para>
The maximum number of simultaneous iterative
queries to any one domain that the server will
permit before blocking new queries for data
in or beneath that zone.
This value should reflect how many fetches would
normally be sent to any one zone in the time it
would take to resolve them. It should be smaller
than <option>recursive-clients</option>.
</para>
<para>
When many clients simultaneously query for the
same name and type, the clients will all be attached
to the same fetch, up to the
<option>max-clients-per-query</option> limit,
and only one iterative query will be sent.
However, when clients are simultaneously
querying for <emphasis>different</emphasis> names
or types, multiple queries will be sent and
<option>max-clients-per-query</option> is not
effective as a limit.
</para>
<para>
Optionally, this value may be followed by the keyword
<literal>drop</literal> or <literal>fail</literal>,
indicating whether queries which exceed the fetch
quota for a zone will be dropped with no response,
or answered with SERVFAIL. The default is
<literal>drop</literal>.
</para>
<para>
If <command>fetches-per-zone</command> is set to zero,
then there is no limit on the number of fetches per query
and no queries will be dropped. The default is zero.
</para>
<para>
The current list of active fetches can be dumped by
running <command>rndc recursing</command>. The list
includes the number of active fetches for each
domain and the number of queries that have been
passed or dropped as a result of the
<option>fetches-per-zone</option> limit. (Note:
these counters are not cumulative over time; whenever
the number of active fetches for a domain drops to
zero, the counter for that domain is deleted, and the
next time a fetch is sent to that domain, it is
recreated with the counters set to zero.)
</para>
<para>
(Note: This option is only available when BIND is
built with <command>configure --enable-fetchlimit</command>.)
</para>
</listitem>
</varlistentry>
<varlistentry id="fetches-per-server">
<term><command>fetches-per-server</command></term>
<listitem>
<para>
The maximum number of simultaneous iterative
queries that the server will allow to be sent to
a single upstream name server before blocking
additional queries.
This value should reflect how many fetches would
normally be sent to any one server in the time it
would take to resolve them. It should be smaller
than <option>recursive-clients</option>.
</para>
<para>
Optionally, this value may be followed by the keyword
<literal>drop</literal> or <literal>fail</literal>,
indicating whether queries will be dropped with no
response, or answered with SERVFAIL, when all of the
servers authoritative for a zone are found to have
exceeded the per-server quota. The default is
<literal>fail</literal>.
</para>
<para>
If <command>fetches-per-server</command> is set to zero,
then there is no limit on the number of fetches per query
and no queries will be dropped. The default is zero.
</para>
<para>
The <command>fetches-per-server</command> quota is
dynamically adjusted in response to detected
congestion. As queries are sent to a server
and are either answered or time out, an
exponentially weighted moving average is calculated
of the ratio of timeouts to responses. If the
current average timeout ratio rises above a "high"
threshold, then <command>fetches-per-server</command>
is reduced for that server. If the timeout ratio
drops below a "low" threshold, then
<command>fetches-per-server</command> is increased.
The <command>fetch-quota-params</command> options
can be used to adjust the parameters for this
calculation.
</para>
<para>
(Note: This option is only available when BIND is
built with <command>configure --enable-fetchlimit</command>.)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>fetch-quota-params</command></term>
<listitem>
<para>
Sets the parameters to use for dynamic resizing of
the <option>fetches-per-server</option> quota in
response to detected congestion.
</para>
<para>
The first argument is an integer value indicating
how frequently to recalculate the moving average
of the ratio of timeouts to responses for each
server. The default is 100, meaning we recalculate
the average ratio after every 100 queries have either
been answered or timed out.
</para>
<para>
The remaining three arguments represent the "low"
threshold (defaulting to a timeout ratio of 0.1),
the "high" threshold (defaulting to a timeout
ratio of 0.3), and the discount rate for
the moving average (defaulting to 0.7).
A higher discount rate causes recent events to
weigh more heavily when calculating the moving
average; a lower discount rate causes past
events to weigh more heavily, smoothing out
short-term blips in the timeout ratio.
These arguments are all fixed-point numbers with
precision of 1/100: at most two places after
the decimal point are significant.
</para>
<para>
(Note: This option is only available when BIND is
built with <command>configure --enable-fetchlimit</command>.)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>reserved-sockets</command></term>
<listitem>
@ -8658,72 +8858,6 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
</listitem>
</varlistentry>
<varlistentry id="clients-per-query">
<term><command>clients-per-query</command></term>
<term><command>max-clients-per-query</command></term>
<listitem>
<para>These set the
initial value (minimum) and maximum number of recursive
simultaneous clients for any given query
(&lt;qname,qtype,qclass&gt;) that the server will accept
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>
<para>
This value should reflect how many queries come in for
a given name in the time it takes to resolve that name.
If the number of queries exceed this value, <command>named</command> will
assume that it is dealing with a non-responsive zone
and will drop additional queries. If it gets a response
after dropping queries, it will raise the estimate. The
estimate will then be lowered in 20 minutes if it has
remained unchanged.
</para>
<para>
If <command>clients-per-query</command> is set to zero,
then there is no limit on the number of clients per query
and no queries will be dropped.
</para>
<para>
If <command>max-clients-per-query</command> is set to zero,
then there is no upper bound other than imposed by
<command>recursive-clients</command>.
</para>
</listitem>
</varlistentry>
<varlistentry id="max-recursion-depth">
<term><command>max-recursion-depth</command></term>
<listitem>
<para>
Sets the maximum number of levels of recursion
that are permitted at any one time while servicing
a recursive query. Resolving a name may require
looking up a name server address, which in turn
requires resolving another name, etc; if the number
of indirections exceeds this value, the recursive
query is terminated and returns SERVFAIL. The
default is 7.
</para>
</listitem>
</varlistentry>
<varlistentry id="max-recursion-queries">
<term><command>max-recursion-queries</command></term>
<listitem>
<para>
Sets the maximum number of iterative queries that
may be sent while servicing a recursive query.
If more queries are sent, the recursive query
is terminated and returns SERVFAIL. Queries to
look up top level comains such as "com" and "net"
and the DNS root zone are exempt from this limitation.
The default is 50.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>notify-delay</command></term>
<listitem>

View file

@ -55,7 +55,45 @@
<title>New Features</title>
<itemizedlist>
<listitem>
<para>None</para>
<para>
New quotas have been added to limit the queries that are
sent by recursive resolvers to authoritative servers
experiencing denial-of-service attacks. When configured,
these options can both reduce the harm done to authoritative
servers and also avoid the resource exhaustion that can be
experienced by recursives when they are being used as a
vehicle for such an attack.
</para>
<para>
NOTE: These options are not available by default; use
<command>configure --enable-fetchlimit</command> to include
them in the build.
</para>
<itemizedlist>
<listitem>
<para>
<option>fetches-per-server</option> limits the number of
simultaneous queries that can be sent to any single
authoritative server. The configured value is a starting
point; it is automatically adjusted downward if the server is
partially or completely non-responsive. The algorithm used to
adjust the quota can be configured via the
<option>fetch-quota-params</option> option.
</para>
</listitem>
<listitem>
<para>
<option>fetches-per-zone</option> limits the number of
simultaneous queries that can be sent for names within a
single domain. (Note: Unlike "fetches-per-server", this
value is not self-tuning.)
</para>
</listitem>
</itemizedlist>
<para>
Statistics counters have also been added to track the number
of queries affected by these quotas.
</para>
</listitem>
<listitem>
<para>

View file

@ -163,6 +163,14 @@ struct dns_adb {
isc_boolean_t growentries_sent;
isc_event_t grownames;
isc_boolean_t grownames_sent;
#ifdef ENABLE_FETCHLIMIT
isc_uint32_t quota;
isc_uint32_t atr_freq;
double atr_low;
double atr_high;
double atr_discount;
#endif /* ENABLE_FETCHLIMIT */
};
/*
@ -243,6 +251,17 @@ struct dns_adbentry {
unsigned int flags;
unsigned int srtt;
unsigned int timeouts;
unsigned int completed;
#ifdef ENABLE_FETCHLIMIT
isc_uint8_t mode;
isc_uint32_t quota;
isc_uint32_t active;
double atr;
#endif /* ENABLE_FETCHLIMIT */
isc_sockaddr_t sockaddr;
isc_stdtime_t expires;
@ -287,6 +306,7 @@ static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
static void dump_adb(dns_adb_t *, FILE *, isc_boolean_t debug, isc_stdtime_t);
static void print_dns_name(FILE *, dns_name_t *);
static void print_namehook_list(FILE *, const char *legend,
dns_adb_t *adb,
dns_adbnamehooklist_t *list,
isc_boolean_t debug,
isc_stdtime_t now);
@ -322,10 +342,15 @@ static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *);
static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *);
static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t);
static void water(void *, int);
static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
static void dump_entry(FILE *, dns_adb_t *, dns_adbentry_t *,
isc_boolean_t, isc_stdtime_t);
static void adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt,
unsigned int factor, isc_stdtime_t now);
static void shutdown_task(isc_task_t *task, isc_event_t *ev);
#ifdef ENABLE_FETCHLIMIT
static void log_quota(dns_adbentry_t *entry, const char *fmt, ...)
ISC_FORMAT_PRINTF(2, 3);
#endif /* ENABLE_FETCHLIMIT */
/*
* MUST NOT overlap DNS_ADBFIND_* flags!
@ -1767,10 +1792,18 @@ new_adbentry(dns_adb_t *adb) {
e->refcnt = 0;
e->nh = 0;
e->flags = 0;
e->completed = 0;
e->timeouts = 0;
isc_random_get(&r);
e->srtt = (r & 0x1f) + 1;
e->lastage = 0;
e->expires = 0;
#ifdef ENABLE_FETCHLIMIT
e->active = 0;
e->mode = 0;
e->quota = adb->quota;
e->atr = 0.0;
#endif /* ENABLE_FETCHLIMIT */
ISC_LIST_INIT(e->lameinfo);
ISC_LINK_INIT(e, plink);
LOCK(&adb->entriescntlock);
@ -2079,6 +2112,27 @@ entry_is_lame(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *qname,
return (is_bad);
}
#ifdef ENABLE_FETCHLIMIT
static void
log_quota(dns_adbentry_t *entry, const char *fmt, ...) {
va_list ap;
char msgbuf[2048];
char addrbuf[ISC_NETADDR_FORMATSIZE];
isc_netaddr_t netaddr;
va_start(ap, fmt);
vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
va_end(ap);
isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr);
isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
ISC_LOG_INFO, "adb: quota %s (%d/%d): %s",
addrbuf, entry->active, entry->quota, msgbuf);
}
#endif /* ENABLE_FETCHLIMIT */
static void
copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
dns_rdatatype_t qtype, dns_adbname_t *name,
@ -2099,6 +2153,17 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
INSIST(bucket != DNS_ADB_INVALIDBUCKET);
LOCK(&adb->entrylocks[bucket]);
#ifdef ENABLE_FETCHLIMIT
if (entry->quota != 0 &&
entry->active >= entry->quota)
{
find->options |=
(DNS_ADBFIND_LAMEPRUNED|
DNS_ADBFIND_OVERQUOTA);
goto nextv4;
}
#endif /* ENABLE_FETCHLIMIT */
if (!FIND_RETURNLAME(find)
&& entry_is_lame(adb, entry, qname, qtype, now)) {
find->options |= DNS_ADBFIND_LAMEPRUNED;
@ -2130,6 +2195,17 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
INSIST(bucket != DNS_ADB_INVALIDBUCKET);
LOCK(&adb->entrylocks[bucket]);
#ifdef ENABLE_FETCHLIMIT
if (entry->quota != 0 &&
entry->active >= entry->quota)
{
find->options |=
(DNS_ADBFIND_LAMEPRUNED|
DNS_ADBFIND_OVERQUOTA);
goto nextv6;
}
#endif /* ENABLE_FETCHLIMIT */
if (!FIND_RETURNLAME(find)
&& entry_is_lame(adb, entry, qname, qtype, now)) {
find->options |= DNS_ADBFIND_LAMEPRUNED;
@ -2462,6 +2538,14 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
adb, NULL, NULL);
adb->growentries_sent = ISC_FALSE;
#ifdef ENABLE_FETCHLIMIT
adb->quota = 0;
adb->atr_freq = 0;
adb->atr_low = 0.0;
adb->atr_high = 0.0;
adb->atr_discount = 0.0;
#endif /* ENABLE_FETCHLIMIT */
adb->nnames = nbuckets[0];
adb->namescnt = 0;
adb->names = NULL;
@ -3357,8 +3441,10 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
fprintf(f, "\n");
print_namehook_list(f, "v4", &name->v4, debug, now);
print_namehook_list(f, "v6", &name->v6, debug, now);
print_namehook_list(f, "v4", adb,
&name->v4, debug, now);
print_namehook_list(f, "v6", adb,
&name->v6, debug, now);
if (debug)
print_fetch_list(f, name);
@ -3373,7 +3459,7 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
entry = ISC_LIST_HEAD(adb->entries[i]);
while (entry != NULL) {
if (entry->nh == 0)
dump_entry(f, entry, debug, now);
dump_entry(f, adb, entry, debug, now);
entry = ISC_LIST_NEXT(entry, plink);
}
}
@ -3388,14 +3474,18 @@ dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
}
static void
dump_entry(FILE *f, dns_adbentry_t *entry, isc_boolean_t debug,
isc_stdtime_t now)
dump_entry(FILE *f, dns_adb_t *adb, dns_adbentry_t *entry,
isc_boolean_t debug, isc_stdtime_t now)
{
char addrbuf[ISC_NETADDR_FORMATSIZE];
char typebuf[DNS_RDATATYPE_FORMATSIZE];
isc_netaddr_t netaddr;
dns_adblameinfo_t *li;
#ifndef ENABLE_FETCHLIMIT
UNUSED(adb);
#endif /* !ENABLE_FETCHLIMIT */
isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr);
isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
@ -3406,10 +3496,19 @@ dump_entry(FILE *f, dns_adbentry_t *entry, isc_boolean_t debug,
addrbuf, entry->srtt, entry->flags);
if (entry->expires != 0)
fprintf(f, " [ttl %d]", entry->expires - now);
#ifdef ENABLE_FETCHLIMIT
if (adb != NULL && adb->quota != 0 && adb->atr_freq != 0) {
fprintf(f, " [atr %0.2f] [quota %d]",
entry->atr, entry->quota);
}
#endif /* ENABLE_FETCHLIMIT */
fprintf(f, "\n");
for (li = ISC_LIST_HEAD(entry->lameinfo);
li != NULL;
li = ISC_LIST_NEXT(li, plink)) {
li = ISC_LIST_NEXT(li, plink))
{
fprintf(f, ";\t\t");
print_dns_name(f, &li->qname);
dns_rdatatype_format(li->qtype, typebuf, sizeof(typebuf));
@ -3481,7 +3580,8 @@ print_dns_name(FILE *f, dns_name_t *name) {
}
static void
print_namehook_list(FILE *f, const char *legend, dns_adbnamehooklist_t *list,
print_namehook_list(FILE *f, const char *legend,
dns_adb_t *adb, dns_adbnamehooklist_t *list,
isc_boolean_t debug, isc_stdtime_t now)
{
dns_adbnamehook_t *nh;
@ -3492,7 +3592,7 @@ print_namehook_list(FILE *f, const char *legend, dns_adbnamehooklist_t *list,
{
if (debug)
fprintf(f, ";\tHook(%s) %p\n", legend, nh);
dump_entry(f, nh->entry, debug, now);
dump_entry(f, adb, nh->entry, debug, now);
}
}
@ -4058,6 +4158,114 @@ dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
UNLOCK(&adb->entrylocks[bucket]);
}
#ifdef ENABLE_FETCHLIMIT
/*
* (10000 / ((10 + n) / 10)^(3/2)) for n in 0..99.
* These will be used to make quota adjustments.
*/
static int quota_adj[] = {
10000, 8668, 7607, 6747, 6037, 5443, 4941, 4512, 4141,
3818, 3536, 3286, 3065, 2867, 2690, 2530, 2385, 2254,
2134, 2025, 1925, 1832, 1747, 1668, 1595, 1527, 1464,
1405, 1350, 1298, 1250, 1205, 1162, 1121, 1083, 1048,
1014, 981, 922, 894, 868, 843, 820, 797, 775, 755,
735, 716, 698, 680, 664, 648, 632, 618, 603, 590, 577,
564, 552, 540, 529, 518, 507, 497, 487, 477, 468, 459,
450, 442, 434, 426, 418, 411, 404, 397, 390, 383, 377,
370, 364, 358, 353, 347, 342, 336, 331, 326, 321, 316,
312, 307, 303, 298, 294, 290, 286, 282, 278
};
/*
* Caller must hold adbentry lock
*/
static void
maybe_adjust_quota(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
isc_boolean_t timeout)
{
double tr;
UNUSED(adb);
if (adb->quota == 0 || adb->atr_freq == 0)
return;
if (timeout)
addr->entry->timeouts++;
if (addr->entry->completed++ <= adb->atr_freq)
return;
/*
* Calculate an exponential rolling average of the timeout ratio
*
* XXX: Integer arithmetic might be better than floating point
*/
tr = (double) addr->entry->timeouts / addr->entry->completed;
addr->entry->timeouts = addr->entry->completed = 0;
INSIST(addr->entry->atr >= 0.0);
INSIST(addr->entry->atr <= 1.0);
INSIST(adb->atr_discount >= 0.0);
INSIST(adb->atr_discount <= 1.0);
addr->entry->atr *= 1.0 - adb->atr_discount;
addr->entry->atr += tr * adb->atr_discount;
addr->entry->atr = ISC_CLAMP(addr->entry->atr, 0.0, 1.0);
if (addr->entry->atr < adb->atr_low && addr->entry->mode > 0) {
addr->entry->quota = adb->quota *
quota_adj[--addr->entry->mode] / 10000;
log_quota(addr->entry, "atr %0.2f, quota increased to %d",
addr->entry->atr, addr->entry->quota);
} else if (addr->entry->atr > adb->atr_high && addr->entry->mode < 99) {
addr->entry->quota = adb->quota *
quota_adj[++addr->entry->mode] / 10000;
log_quota(addr->entry, "atr %0.2f, quota decreased to %d",
addr->entry->atr, addr->entry->quota);
}
/* Ensure we don't drop to zero */
if (addr->entry->quota == 0)
addr->entry->quota = 1;
}
#endif /* ENABLE_FETCHLIMIT */
void
dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
int bucket;
REQUIRE(DNS_ADB_VALID(adb));
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
bucket = addr->entry->lock_bucket;
LOCK(&adb->entrylocks[bucket]);
#ifdef ENABLE_FETCHLIMIT
maybe_adjust_quota(adb, addr, ISC_FALSE);
#endif /* ENABLE_FETCHLIMIT */
UNLOCK(&adb->entrylocks[bucket]);
}
void
dns_adb_timeout(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
#ifdef ENABLE_FETCHLIMIT
int bucket;
REQUIRE(DNS_ADB_VALID(adb));
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
bucket = addr->entry->lock_bucket;
LOCK(&adb->entrylocks[bucket]);
maybe_adjust_quota(adb, addr, ISC_TRUE);
UNLOCK(&adb->entrylocks[bucket]);
#else
UNUSED(adb);
UNUSED(addr);
return;
#endif /* !ENABLE_FETCHLIMIT */
}
isc_result_t
dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa,
dns_adbaddrinfo_t **addrp, isc_stdtime_t now)
@ -4237,3 +4445,84 @@ dns_adb_setadbsize(dns_adb_t *adb, size_t size) {
else
isc_mem_setwater(adb->mctx, water, adb, hiwater, lowater);
}
void
dns_adb_setquota(dns_adb_t *adb, isc_uint32_t quota, isc_uint32_t freq,
double low, double high, double discount)
{
#ifdef ENABLE_FETCHLIMIT
REQUIRE(DNS_ADB_VALID(adb));
adb->quota = quota;
adb->atr_freq = freq;
adb->atr_low = low;
adb->atr_high = high;
adb->atr_discount = discount;
#else
UNUSED(adb);
UNUSED(quota);
UNUSED(freq);
UNUSED(low);
UNUSED(high);
UNUSED(discount);
return;
#endif /* !ENABLE_FETCHLIMIT */
}
isc_boolean_t
dns_adbentry_overquota(dns_adbentry_t *entry) {
#ifdef ENABLE_FETCHLIMIT
isc_boolean_t block;
REQUIRE(DNS_ADBENTRY_VALID(entry));
block = ISC_TF(entry->quota != 0 && entry->active >= entry->quota);
return (block);
#else
UNUSED(entry);
return (ISC_FALSE);
#endif /* !ENABLE_FETCHLIMIT */
}
void
dns_adb_beginudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
#ifdef ENABLE_FETCHLIMIT
int bucket;
REQUIRE(DNS_ADB_VALID(adb));
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
bucket = addr->entry->lock_bucket;
LOCK(&adb->entrylocks[bucket]);
addr->entry->active++;
UNLOCK(&adb->entrylocks[bucket]);
#else
UNUSED(adb);
UNUSED(addr);
return;
#endif /* !ENABLE_FETCHLIMIT */
}
void
dns_adb_endudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
#ifdef ENABLE_FETCHLIMIT
int bucket;
REQUIRE(DNS_ADB_VALID(adb));
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
bucket = addr->entry->lock_bucket;
LOCK(&adb->entrylocks[bucket]);
if (addr->entry->active > 0)
addr->entry->active--;
UNLOCK(&adb->entrylocks[bucket]);
#else
UNUSED(adb);
UNUSED(addr);
return;
#endif /* !ENABLE_FETCHLIMIT */
}

View file

@ -206,6 +206,11 @@ struct dns_adbfind {
* Must set _WANTEVENT for this to be meaningful.
*/
#define DNS_ADBFIND_LAMEPRUNED 0x00000200
/*%
* The server's fetch quota is exceeded; it will be treated as
* lame for this query.
*/
#define DNS_ADBFIND_OVERQUOTA 0x00000400
/*%
* The answers to queries come back as a list of these.
@ -583,6 +588,30 @@ dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
*\li addr be valid.
*/
void
dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
/*%
* Record a successful DNS response.
*
* Requires:
*
*\li adb be valid.
*
*\li addr be valid.
*/
void
dns_adb_timeout(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
/*%
* Record a DNS UDP query failed.
*
* Requires:
*
*\li adb be valid.
*
*\li addr be valid.
*/
isc_result_t
dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa,
dns_adbaddrinfo_t **addrp, isc_stdtime_t now);
@ -647,6 +676,64 @@ dns_adb_flushname(dns_adb_t *adb, dns_name_t *name);
*\li 'name' is valid.
*/
void
dns_adb_setquota(dns_adb_t *adb, isc_uint32_t quota, isc_uint32_t freq,
double low, double high, double discount);
/*%<
* Set the baseline ADB quota, and configure parameters for the
* quota adjustment algorithm.
*
* If the number of fetches currently waiting for responses from this
* address exceeds the current quota, then additional fetches are spilled.
*
* 'quota' is the highest permissible quota; it will adjust itself
* downward in response to detected congestion.
*
* After every 'freq' fetches have either completed or timed out, an
* exponentially weighted moving average of the ratio of timeouts
* to responses is calculated. If the EWMA goes above a 'high'
* threshold, then the quota is adjusted down one step; if it drops
* below a 'low' threshold, then the quota is adjusted back up one
* step.
*
* The quota adjustment is based on the function (1 / 1 + (n/10)^(3/2)),
* for values of n from 0 to 99. It starts at 100% of the baseline
* quota, and descends after 100 steps to 2%.
*
* 'discount' represents the discount rate of the moving average. Higher
* values cause older values to be discounted sooner, providing a faster
* response to changes in the timeout ratio.
*
* Requires:
*\li 'adb' is valid.
*/
isc_boolean_t
dns_adbentry_overquota(dns_adbentry_t *entry);
/*%<
* Returns true if the specified ADB has too many active fetches.
*
* Requires:
*\li 'entry' is valid.
*/
void
dns_adb_beginudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
void
dns_adb_endudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
/*%
* Begin/end a UDP fetch on a particular address.
*
* These functions increment or decrement the fetch counter for
* the ADB entry so that the fetch quota can be enforced.
*
* Requires:
*
*\li adb be valid.
*
*\li addr be valid.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_ADB_H */

View file

@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: log.h,v 1.47 2011/10/13 22:48:24 tbox Exp $ */
/*! \file dns/log.h
* \author Principal Authors: DCL */
@ -45,6 +43,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[];
#define DNS_LOGCATEGORY_RPZ (&dns_categories[12])
#define DNS_LOGCATEGORY_RRL (&dns_categories[13])
#define DNS_LOGCATEGORY_CNAME (&dns_categories[14])
#define DNS_LOGCATEGORY_SPILL (&dns_categories[15])
/* Backwards compatibility. */
#define DNS_LOGCATEGORY_GENERAL ISC_LOGCATEGORY_GENERAL

View file

@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: resolver.h,v 1.72 2011/12/05 17:10:51 each Exp $ */
#ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1
@ -54,6 +52,7 @@
#include <isc/lang.h>
#include <isc/socket.h>
#include <isc/stats.h>
#include <dns/types.h>
#include <dns/fixedname.h>
@ -84,6 +83,14 @@ typedef struct dns_fetchevent {
isc_result_t vresult;
} dns_fetchevent_t;
/*%
* The two quota types (fetches-per-zone and fetches-per-server)
*/
typedef enum {
dns_quotatype_zone = 0,
dns_quotatype_server
} dns_quotatype_t;
/*
* Options that modify how a 'fetch' is done.
*/
@ -532,6 +539,8 @@ dns_resolver_gettimeout(dns_resolver_t *resolver);
void
dns_resolver_setclientsperquery(dns_resolver_t *resolver,
isc_uint32_t min, isc_uint32_t max);
void
dns_resolver_setfetchesperzone(dns_resolver_t *resolver, isc_uint32_t clients);
void
dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
@ -612,6 +621,30 @@ dns_resolver_getmaxqueries(dns_resolver_t *resolver);
* \li resolver to be valid.
*/
void
dns_resolver_dumpfetches(dns_resolver_t *resolver, FILE *fp);
void
dns_resolver_setquotaresponse(dns_resolver_t *resolver,
dns_quotatype_t which, isc_result_t resp);
isc_result_t
dns_resolver_getquotaresponse(dns_resolver_t *resolver, dns_quotatype_t which);
/*%
* Get and set the result code that will be used when quotas
* are exceeded. If 'which' is set to quotatype "zone", then the
* result specified in 'resp' will be used when the fetches-per-zone
* quota is exceeded by a fetch. If 'which' is set to quotatype "server",
* then the reuslt specified in 'resp' will be used when the
* fetches-per-server quota has been exceeded for all the
* authoritative servers for a zone. Valid choices are
* DNS_R_DROP or DNS_R_SERVFAIL.
*
* Requires:
* \li 'resolver' to be valid.
* \li 'which' to be dns_quotatype_zone or dns_quotatype_server
* \li 'resp' to be DNS_R_DROP or DNS_R_SERVFAIL.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_RESOLVER_H */

View file

@ -61,8 +61,10 @@ enum {
dns_resstatscounter_queryrtt3 = 27,
dns_resstatscounter_queryrtt4 = 28,
dns_resstatscounter_queryrtt5 = 29,
dns_resstatscounter_zonequota = 30,
dns_resstatscounter_serverquota = 31,
dns_resstatscounter_max = 30,
dns_resstatscounter_max = 32,
/*
* DNSSEC stats.

View file

@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: log.c,v 1.49 2011/10/13 22:48:24 tbox Exp $ */
/*! \file */
/* Principal Authors: DCL */
@ -47,6 +45,7 @@ LIBDNS_EXTERNAL_DATA isc_logcategory_t dns_categories[] = {
{ "rpz", 0 },
{ "rate-limit", 0 },
{ "cname", 0 },
{ "spill", 0 },
{ NULL, 0 }
};

View file

@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id$ */
/*! \file */
#include <config.h>
@ -148,8 +146,9 @@
#define DEFAULT_QUERY_TIMEOUT MINIMUM_QUERY_TIMEOUT
#endif
/* The maximum time in seconds for the whole query to live. */
#ifndef MAXIMUM_QUERY_TIMEOUT
#define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */
#define MAXIMUM_QUERY_TIMEOUT 30
#endif
/* The default maximum number of recursions to follow before giving up. */
@ -162,6 +161,12 @@
#define DEFAULT_MAX_QUERIES 50
#endif
/* Number of hash buckets for zone counters */
#ifndef RES_DOMAIN_BUCKETS
#define RES_DOMAIN_BUCKETS 523
#endif
#define RES_NOBUCKET 0xffffffff
/*%
* Maximum EDNS0 input packet size.
*/
@ -231,6 +236,7 @@ struct fetchctx {
dns_rdatatype_t type;
unsigned int options;
unsigned int bucketnum;
unsigned int dbucketnum;
char * info;
isc_mem_t * mctx;
@ -331,6 +337,7 @@ struct fetchctx {
unsigned int querysent;
unsigned int referrals;
unsigned int lamecount;
unsigned int quotacount;
unsigned int neterr;
unsigned int badresp;
unsigned int adberr;
@ -391,6 +398,25 @@ typedef struct fctxbucket {
isc_mem_t * mctx;
} fctxbucket_t;
#ifdef ENABLE_FETCHLIMIT
typedef struct fctxcount fctxcount_t;
struct fctxcount {
dns_fixedname_t fdname;
dns_name_t *domain;
isc_uint32_t count;
isc_uint32_t allowed;
isc_uint32_t dropped;
isc_stdtime_t logged;
ISC_LINK(fctxcount_t) link;
};
typedef struct zonebucket {
isc_mutex_t lock;
isc_mem_t *mctx;
ISC_LIST(fctxcount_t) list;
} zonebucket_t;
#endif /* ENABLE_FETCHLIMIT */
typedef struct alternate {
isc_boolean_t isaddress;
union {
@ -436,6 +462,9 @@ struct dns_resolver {
isc_boolean_t exclusivev6;
unsigned int nbuckets;
fctxbucket_t * buckets;
#ifdef ENABLE_FETCHLIMIT
zonebucket_t * dbuckets;
#endif /* ENABLE_FETCHLIMIT */
isc_uint32_t lame_ttl;
ISC_LIST(alternate_t) alternates;
isc_uint16_t udpsize;
@ -454,6 +483,7 @@ struct dns_resolver {
unsigned int query_timeout;
unsigned int maxdepth;
unsigned int maxqueries;
isc_result_t quotaresp[2];
/* Locked by lock. */
unsigned int references;
@ -462,6 +492,7 @@ struct dns_resolver {
unsigned int activebuckets;
isc_boolean_t priming;
unsigned int spillat; /* clients-per-query */
unsigned int zspill; /* fetches-per-zone */
/* Bad cache. */
dns_badcache_t ** badcache;
@ -898,19 +929,20 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
rtt = query->addrinfo->srtt + 200000;
if (rtt > MAX_SINGLE_QUERY_TIMEOUT_US)
rtt = MAX_SINGLE_QUERY_TIMEOUT_US;
/*
* Replace the current RTT with our value.
*/
factor = DNS_ADB_RTTADJREPLACE;
dns_adb_timeout(fctx->adb, query->addrinfo);
}
dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
}
/* Remember that the server has been tried. */
if (!TRIED(query->addrinfo)) {
dns_adb_changeflags(fctx->adb, query->addrinfo,
FCTX_ADDRINFO_TRIED, FCTX_ADDRINFO_TRIED);
}
#ifdef ENABLE_FETCHLIMIT
dns_adb_endudpfetch(fctx->adb, query->addrinfo);
#endif /* ENABLE_FETCHLIMIT */
/*
* Age RTTs of servers not tried.
@ -1091,6 +1123,128 @@ fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {
fctx_stoptimer(fctx);
}
#ifdef ENABLE_FETCHLIMIT
static void
fcount_logspill(fetchctx_t *fctx, fctxcount_t *counter) {
char dbuf[DNS_NAME_FORMATSIZE];
isc_stdtime_t now;
if (! isc_log_wouldlog(dns_lctx, ISC_LOG_INFO))
return;
isc_stdtime_get(&now);
if (counter->logged > now - 60)
return;
dns_name_format(&fctx->domain, dbuf, sizeof(dbuf));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_SPILL,
DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
"too many simultaneous fetches for %s "
"(allowed %d spilled %d)",
dbuf, counter->allowed, counter->dropped);
counter->logged = now;
}
static isc_result_t
fcount_incr(fetchctx_t *fctx, isc_boolean_t force) {
isc_result_t result = ISC_R_SUCCESS;
zonebucket_t *dbucket;
fctxcount_t *counter;
unsigned int bucketnum, spill;
REQUIRE(fctx != NULL);
REQUIRE(fctx->res != NULL);
INSIST(fctx->dbucketnum == RES_NOBUCKET);
bucketnum = dns_name_fullhash(&fctx->domain, ISC_FALSE)
% RES_DOMAIN_BUCKETS;
LOCK(&fctx->res->lock);
spill = fctx->res->zspill;
UNLOCK(&fctx->res->lock);
dbucket = &fctx->res->dbuckets[bucketnum];
LOCK(&dbucket->lock);
for (counter = ISC_LIST_HEAD(dbucket->list);
counter != NULL;
counter = ISC_LIST_NEXT(counter, link))
{
if (dns_name_equal(counter->domain, &fctx->domain))
break;
}
if (counter == NULL) {
counter = isc_mem_get(dbucket->mctx, sizeof(fctxcount_t));
if (counter == NULL)
result = ISC_R_NOMEMORY;
else {
ISC_LINK_INIT(counter, link);
counter->count = 1;
counter->logged = 0;
counter->allowed = 1;
counter->dropped = 0;
dns_fixedname_init(&counter->fdname);
counter->domain = dns_fixedname_name(&counter->fdname);
dns_name_copy(&fctx->domain, counter->domain, NULL);
ISC_LIST_APPEND(dbucket->list, counter, link);
}
} else {
if (!force && spill != 0 && counter->count >= spill) {
counter->dropped++;
fcount_logspill(fctx, counter);
result = ISC_R_QUOTA;
} else {
counter->count++;
counter->allowed++;
}
}
UNLOCK(&dbucket->lock);
if (result == ISC_R_SUCCESS)
fctx->dbucketnum = bucketnum;
return (result);
}
static void
fcount_decr(fetchctx_t *fctx) {
zonebucket_t *dbucket;
fctxcount_t *counter;
REQUIRE(fctx != NULL);
if (fctx->dbucketnum == RES_NOBUCKET)
return;
dbucket = &fctx->res->dbuckets[fctx->dbucketnum];
LOCK(&dbucket->lock);
for (counter = ISC_LIST_HEAD(dbucket->list);
counter != NULL;
counter = ISC_LIST_NEXT(counter, link))
{
if (dns_name_equal(counter->domain, &fctx->domain))
break;
}
if (counter != NULL) {
INSIST(counter->count != 0);
counter->count--;
fctx->dbucketnum = RES_NOBUCKET;
if (counter->count == 0) {
ISC_LIST_UNLINK(dbucket->list, counter, link);
isc_mem_put(dbucket->mctx, counter, sizeof(*counter));
}
}
UNLOCK(&dbucket->lock);
}
#endif /* ENABLE_FETCHLIMIT */
static inline void
fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) {
dns_fetchevent_t *event, *next_event;
@ -1592,6 +1746,14 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
query->connects++;
QTRACE("connecting via TCP");
} else {
#ifdef ENABLE_FETCHLIMIT
if (dns_adbentry_overquota(addrinfo->entry))
goto cleanup_dispatch;
/* Inform the ADB that we're starting a fetch */
dns_adb_beginudpfetch(fctx->adb, addrinfo);
#endif /* ENABLE_FETCHLIMIT */
result = resquery_send(query);
if (result != ISC_R_SUCCESS)
goto cleanup_dispatch;
@ -2552,7 +2714,7 @@ sort_finds(dns_adbfindlist_t *findlist) {
static void
findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
unsigned int options, unsigned int flags, isc_stdtime_t now,
isc_boolean_t *need_alternate)
isc_boolean_t *overquota, isc_boolean_t *need_alternate)
{
dns_adbaddrinfo_t *ai;
dns_adbfind_t *find;
@ -2560,6 +2722,10 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
isc_boolean_t unshared;
isc_result_t result;
#ifndef ENABLE_FETCHLIMIT
UNUSED(overquota);
#endif /* !ENABLE_FETCHLIMIT */
res = fctx->res;
unshared = ISC_TF((fctx->options & DNS_FETCHOPT_UNSHARED) != 0);
/*
@ -2643,6 +2809,14 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
find->result_v4 != DNS_R_NXDOMAIN)))
*need_alternate = ISC_TRUE;
} else {
#ifdef ENABLE_FETCHLIMIT
if ((find->options & DNS_ADBFIND_OVERQUOTA) != 0) {
if (overquota != NULL)
*overquota = ISC_TRUE;
fctx->quotacount++; /* quota exceeded */
}
else
#endif /* ENABLE_FETCHLIMIT */
if ((find->options & DNS_ADBFIND_LAMEPRUNED) != 0)
fctx->lamecount++; /* cached lame server */
else
@ -2686,6 +2860,9 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
isc_boolean_t all_bad;
dns_rdata_ns_t ns;
isc_boolean_t need_alternate = ISC_FALSE;
#ifdef ENABLE_FETCHLIMIT
isc_boolean_t all_spilled = ISC_TRUE;
#endif /* ENABLE_FETCHLIMIT */
FCTXTRACE("getaddresses");
@ -2743,19 +2920,27 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
dns_fixedname_init(&fixed);
domain = dns_fixedname_name(&fixed);
result = dns_fwdtable_find2(fctx->res->view->fwdtable, name,
result = dns_fwdtable_find2(res->view->fwdtable, name,
domain, &forwarders);
if (result == ISC_R_SUCCESS) {
sa = ISC_LIST_HEAD(forwarders->addrs);
fctx->fwdpolicy = forwarders->fwdpolicy;
if (fctx->fwdpolicy == dns_fwdpolicy_only &&
isstrictsubdomain(domain, &fctx->domain)) {
#ifdef ENABLE_FETCHLIMIT
fcount_decr(fctx);
#endif /* ENABLE_FETCHLIMIT */
dns_name_free(&fctx->domain, fctx->mctx);
dns_name_init(&fctx->domain, NULL);
result = dns_name_dup(domain, fctx->mctx,
&fctx->domain);
if (result != ISC_R_SUCCESS)
return (result);
#ifdef ENABLE_FETCHLIMIT
result = fcount_incr(fctx, ISC_TRUE);
if (result != ISC_R_SUCCESS)
return (result);
#endif /* ENABLE_FETCHLIMIT */
}
}
}
@ -2829,6 +3014,8 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&fctx->nameservers))
{
isc_boolean_t overquota = ISC_FALSE;
dns_rdataset_current(&fctx->nameservers, &rdata);
/*
* Extract the name from the NS record.
@ -2838,7 +3025,13 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
continue;
findname(fctx, &ns.name, 0, stdoptions, 0, now,
&need_alternate);
&overquota, &need_alternate);
#ifdef ENABLE_FETCHLIMIT
if (!overquota)
all_spilled = ISC_FALSE;
#endif /* ENABLE_FETCHLIMIT */
dns_rdata_reset(&rdata);
dns_rdata_freestruct(&ns);
}
@ -2852,13 +3045,13 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
int family;
alternate_t *a;
family = (res->dispatches6 != NULL) ? AF_INET6 : AF_INET;
for (a = ISC_LIST_HEAD(fctx->res->alternates);
for (a = ISC_LIST_HEAD(res->alternates);
a != NULL;
a = ISC_LIST_NEXT(a, link)) {
if (!a->isaddress) {
findname(fctx, &a->_u._n.name, a->_u._n.port,
stdoptions, FCTX_ADDRINFO_FORWARDER,
now, NULL);
now, NULL, NULL);
continue;
}
if (isc_sockaddr_pf(&a->_u.addr) != family)
@ -2917,10 +3110,21 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
fctx->type == dns_rdatatype_dlv ||
fctx->type == dns_rdatatype_ds) &&
result == ISC_R_SUCCESS)
dns_resolver_addbadcache(fctx->res,
&fctx->name,
dns_resolver_addbadcache(res, &fctx->name,
fctx->type, &expire);
result = ISC_R_FAILURE;
#ifdef ENABLE_FETCHLIMIT
/*
* If all of the addresses found were over the
* fetches-per-server quota, return the configured
* response.
*/
if (all_spilled) {
result = res->quotaresp[dns_quotatype_server];
inc_stats(res, dns_resstatscounter_serverquota);
} else
result = ISC_R_FAILURE;
#endif /* ENABLE_FETCHLIMIT */
}
} else {
/*
@ -3144,14 +3348,17 @@ fctx_nextaddress(fetchctx_t *fctx) {
static void
fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
isc_result_t result;
dns_adbaddrinfo_t *addrinfo;
dns_adbaddrinfo_t *addrinfo = NULL;
dns_resolver_t *res;
FCTXTRACE("try");
REQUIRE(!ADDRWAIT(fctx));
res = fctx->res;
/* We've already exceeded maximum query count */
if (isc_counter_used(fctx->qc) > fctx->res->maxqueries) {
if (isc_counter_used(fctx->qc) > res->maxqueries) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
"exceeded max queries resolving '%s'",
@ -3160,11 +3367,15 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
return;
}
addrinfo = fctx_nextaddress(fctx);
#ifdef ENABLE_FETCHLIMIT
/* Try to find an address that isn't over quota */
while ((addrinfo = fctx_nextaddress(fctx)) != NULL)
if (! dns_adbentry_overquota(addrinfo->entry))
break;
#endif /* ENABLE_FETCHLIMIT */
if (addrinfo == NULL) {
/*
* We have no more addresses. Start over.
*/
/* We have no more addresses. Start over. */
fctx_cancelqueries(fctx, ISC_TRUE);
fctx_cleanupfinds(fctx);
fctx_cleanupaltfinds(fctx);
@ -3186,7 +3397,15 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
return;
}
#ifdef ENABLE_FETCHLIMIT
while ((addrinfo = fctx_nextaddress(fctx)) != NULL) {
if (! dns_adbentry_overquota(addrinfo->entry))
break;
}
#else
addrinfo = fctx_nextaddress(fctx);
#endif /* !ENABLE_FETCHLIMIT */
/*
* While we may have addresses from the ADB, they
* might be bad ones. In this case, return SERVFAIL.
@ -3213,7 +3432,7 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
if (result != ISC_R_SUCCESS)
fctx_done(fctx, result, __LINE__);
else if (retrying)
inc_stats(fctx->res, dns_resstatscounter_retry);
inc_stats(res, dns_resstatscounter_retry);
}
static isc_boolean_t
@ -3308,6 +3527,11 @@ fctx_destroy(fetchctx_t *fctx) {
}
isc_counter_detach(&fctx->qc);
#ifdef ENABLE_FETCHLIMIT
fcount_decr(fctx);
#endif /* ENABLE_FETCHLIMIT */
isc_timer_detach(&fctx->timer);
dns_message_destroy(&fctx->rmessage);
dns_message_destroy(&fctx->qmessage);
@ -3705,6 +3929,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
fctx->res = res;
fctx->references = 0;
fctx->bucketnum = bucketnum;
fctx->dbucketnum = RES_NOBUCKET;
fctx->state = fetchstate_init;
fctx->want_shutdown = ISC_FALSE;
fctx->cloned = ISC_FALSE;
@ -3731,6 +3956,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
TIME_NOW(&fctx->start);
fctx->timeouts = 0;
fctx->lamecount = 0;
fctx->quotacount = 0;
fctx->adberr = 0;
fctx->neterr = 0;
fctx->badresp = 0;
@ -3823,6 +4049,18 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
fctx->ns_ttl_ok = ISC_TRUE;
}
#ifdef ENABLE_FETCHLIMIT
/*
* Are there too many simultaneous queries for this domain?
*/
result = fcount_incr(fctx, ISC_FALSE);
if (result != ISC_R_SUCCESS) {
result = fctx->res->quotaresp[dns_quotatype_zone];
inc_stats(res, dns_resstatscounter_zonequota);
goto cleanup_domain;
}
#endif /* ENABLE_FETCHLIMIT */
log_ns_ttl(fctx, "fctx_create");
INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
@ -3832,7 +4070,11 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
&fctx->qmessage);
if (result != ISC_R_SUCCESS)
#ifdef ENABLE_FETCHLIMIT
goto cleanup_fcount;
#else
goto cleanup_domain;
#endif /* !ENABLE_FETCHLIMIT */
fctx->rmessage = NULL;
result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
@ -3908,6 +4150,11 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
cleanup_qmessage:
dns_message_destroy(&fctx->qmessage);
#ifdef ENABLE_FETCHLIMIT
cleanup_fcount:
fcount_decr(fctx);
#endif /* ENABLE_FETCHLIMIT */
cleanup_domain:
if (dns_name_countlabels(&fctx->domain) > 0)
dns_name_free(&fctx->domain, mctx);
@ -6165,6 +6412,11 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
* if so we should bail out.
*/
INSIST(dns_name_countlabels(&fctx->domain) > 0);
#ifdef ENABLE_FETCHLIMIT
fcount_decr(fctx);
#endif /* ENABLE_FETCHLIMIT */
dns_name_free(&fctx->domain, fctx->mctx);
if (dns_rdataset_isassociated(&fctx->nameservers))
dns_rdataset_disassociate(&fctx->nameservers);
@ -6172,6 +6424,13 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
result = dns_name_dup(ns_name, fctx->mctx, &fctx->domain);
if (result != ISC_R_SUCCESS)
return (result);
#ifdef ENABLE_FETCHLIMIT
result = fcount_incr(fctx, ISC_TRUE);
if (result != ISC_R_SUCCESS)
return (result);
#endif /* ENABLE_FETCHLIMIT */
fctx->attributes |= FCTX_ATTR_WANTCACHE;
fctx->ns_ttl_ok = ISC_FALSE;
log_ns_ttl(fctx, "DELEGATION");
@ -6738,6 +6997,11 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
fctx->ns_ttl = fctx->nameservers.ttl;
fctx->ns_ttl_ok = ISC_TRUE;
log_ns_ttl(fctx, "resume_dslookup");
#ifdef ENABLE_FETCHLIMIT
fcount_decr(fctx);
#endif /* ENABLE_FETCHLIMIT */
dns_name_free(&fctx->domain, fctx->mctx);
dns_name_init(&fctx->domain, NULL);
result = dns_name_dup(&fctx->nsname, fctx->mctx, &fctx->domain);
@ -6745,6 +7009,15 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
goto cleanup;
}
#ifdef ENABLE_FETCHLIMIT
result = fcount_incr(fctx, ISC_TRUE);
if (result != ISC_R_SUCCESS) {
fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
goto cleanup;
}
#endif /* ENABLE_FETCHLIMIT */
/*
* Try again.
*/
@ -7119,6 +7392,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
}
}
if ((options & DNS_FETCHOPT_TCP) == 0)
dns_adb_plainresponse(fctx->adb, query->addrinfo);
result = dns_message_parse(message, &devent->buffer, 0);
if (result != ISC_R_SUCCESS) {
FCTXTRACE3("message failed to parse", result);
@ -7600,6 +7875,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
fctx->referrals++;
fctx->querysent = 0;
fctx->lamecount = 0;
fctx->quotacount = 0;
fctx->neterr = 0;
fctx->badresp = 0;
fctx->adberr = 0;
@ -7731,6 +8007,11 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
return;
}
#ifdef ENABLE_FETCHLIMIT
fcount_decr(fctx);
#endif /* ENABLE_FETCHLIMIT */
dns_name_free(&fctx->domain, fctx->mctx);
dns_name_init(&fctx->domain, NULL);
result = dns_name_dup(fname, fctx->mctx, &fctx->domain);
@ -7738,6 +8019,15 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
return;
}
#ifdef ENABLE_FETCHLIMIT
result = fcount_incr(fctx, ISC_TRUE);
if (result != ISC_R_SUCCESS) {
fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
return;
}
#endif /* ENABLE_FETCHLIMIT */
fctx->ns_ttl = fctx->nameservers.ttl;
fctx->ns_ttl_ok = ISC_TRUE;
fctx_cancelqueries(fctx, ISC_TRUE);
@ -7858,6 +8148,15 @@ destroy(dns_resolver_t *res) {
}
isc_mem_put(res->mctx, res->buckets,
res->nbuckets * sizeof(fctxbucket_t));
#ifdef ENABLE_FETCHLIMIT
for (i = 0; i < RES_DOMAIN_BUCKETS; i++) {
INSIST(ISC_LIST_EMPTY(res->dbuckets[i].list));
isc_mem_detach(&res->dbuckets[i].mctx);
DESTROYLOCK(&res->dbuckets[i].lock);
}
isc_mem_put(res->mctx, res->dbuckets,
RES_DOMAIN_BUCKETS * sizeof(zonebucket_t));
#endif /* ENABLE_FETCHLIMIT */
if (res->dispatches4 != NULL)
dns_dispatchset_destroy(&res->dispatches4);
if (res->dispatches6 != NULL)
@ -7967,6 +8266,9 @@ dns_resolver_create(dns_view_t *view,
isc_task_t *task = NULL;
char name[16];
unsigned dispattr;
#ifdef ENABLE_FETCHLIMIT
unsigned int dbuckets_created = 0;
#endif /* ENABLE_FETCHLIMIT */
/*
* Create a resolver.
@ -8003,10 +8305,13 @@ dns_resolver_create(dns_view_t *view,
res->spillatmin = res->spillat = 10;
res->spillatmax = 100;
res->spillattimer = NULL;
res->zspill = 0;
res->zero_no_soa_ttl = ISC_FALSE;
res->query_timeout = DEFAULT_QUERY_TIMEOUT;
res->maxdepth = DEFAULT_RECURSION_DEPTH;
res->maxqueries = DEFAULT_MAX_QUERIES;
res->quotaresp[dns_quotatype_zone] = DNS_R_DROP;
res->quotaresp[dns_quotatype_server] = DNS_R_SERVFAIL;
res->nbuckets = ntasks;
res->activebuckets = ntasks;
res->buckets = isc_mem_get(view->mctx,
@ -8049,6 +8354,26 @@ dns_resolver_create(dns_view_t *view,
buckets_created++;
}
#ifdef ENABLE_FETCHLIMIT
res->dbuckets = isc_mem_get(view->mctx,
RES_DOMAIN_BUCKETS * sizeof(zonebucket_t));
if (res->dbuckets == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup_buckets;
}
for (i = 0; i < RES_DOMAIN_BUCKETS; i++) {
ISC_LIST_INIT(res->dbuckets[i].list);
res->dbuckets[i].mctx = NULL;
isc_mem_attach(view->mctx, &res->dbuckets[i].mctx);
result = isc_mutex_init(&res->dbuckets[i].lock);
if (result != ISC_R_SUCCESS) {
isc_mem_detach(&res->dbuckets[i].mctx);
goto cleanup_dbuckets;
}
dbuckets_created++;
}
#endif /* ENABLE_FETCHLIMIT */
res->dispatches4 = NULL;
if (dispatchv4 != NULL) {
dns_dispatchset_create(view->mctx, socketmgr, taskmgr,
@ -8142,6 +8467,16 @@ dns_resolver_create(dns_view_t *view,
if (res->dispatches4 != NULL)
dns_dispatchset_destroy(&res->dispatches4);
#ifdef ENABLE_FETCHLIMIT
cleanup_dbuckets:
for (i = 0; i < dbuckets_created; i++) {
DESTROYLOCK(&res->dbuckets[i].lock);
isc_mem_detach(&res->dbuckets[i].mctx);
}
isc_mem_put(view->mctx, res->dbuckets,
RES_DOMAIN_BUCKETS * sizeof(zonebucket_t));
#endif /* ENABLE_FETCHLIMIT*/
cleanup_buckets:
for (i = 0; i < buckets_created; i++) {
isc_mem_detach(&res->buckets[i].mctx);
@ -8736,8 +9071,12 @@ dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
"%" ISC_PRINT_QUADFORMAT "u."
"%06" ISC_PRINT_QUADFORMAT "u: %s/%s "
"[domain:%s,referral:%u,restart:%u,qrysent:%u,"
"timeout:%u,lame:%u,neterr:%u,badresp:%u,"
"adberr:%u,findfail:%u,valfail:%u]",
"timeout:%u,lame:%u,"
#ifdef ENABLE_FETCHLIMIT
"quota:%u,"
#endif /* ENABLE_FETCHLIMIT */
"neterr:%u,"
"badresp:%u,adberr:%u,findfail:%u,valfail:%u]",
__FILE__, fctx->exitline, fctx->info,
fctx->duration / US_PER_SEC,
fctx->duration % US_PER_SEC,
@ -8745,6 +9084,9 @@ dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
isc_result_totext(fctx->vresult), domainbuf,
fctx->referrals, fctx->restarts,
fctx->querysent, fctx->timeouts, fctx->lamecount,
#ifdef ENABLE_FETCHLIMIT
fctx->quotacount,
#endif /* ENABLE_FETCHLIMIT */
fctx->neterr, fctx->badresp, fctx->adberr,
fctx->findfail, fctx->valfail);
fctx->logged = ISC_TRUE;
@ -9366,6 +9708,24 @@ dns_resolver_setclientsperquery(dns_resolver_t *resolver, isc_uint32_t min,
UNLOCK(&resolver->lock);
}
void
dns_resolver_setfetchesperzone(dns_resolver_t *resolver, isc_uint32_t clients)
{
#ifdef ENABLE_FETCHLIMIT
REQUIRE(VALID_RESOLVER(resolver));
LOCK(&resolver->lock);
resolver->zspill = clients;
UNLOCK(&resolver->lock);
#else
UNUSED(resolver);
UNUSED(clients);
return;
#endif /* !ENABLE_FETCHLIMIT */
}
isc_boolean_t
dns_resolver_getzeronosoattl(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));
@ -9431,3 +9791,67 @@ dns_resolver_getmaxqueries(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));
return (resolver->maxqueries);
}
void
dns_resolver_dumpfetches(dns_resolver_t *resolver, FILE *fp) {
#ifdef ENABLE_FETCHLIMIT
int i;
REQUIRE(VALID_RESOLVER(resolver));
REQUIRE(fp != NULL);
for (i = 0; i < RES_DOMAIN_BUCKETS; i++) {
fctxcount_t *fc;
LOCK(&resolver->dbuckets[i].lock);
for (fc = ISC_LIST_HEAD(resolver->dbuckets[i].list);
fc != NULL;
fc = ISC_LIST_NEXT(fc, link))
{
dns_name_print(fc->domain, fp);
fprintf(fp, ": %d active (%d spilled, %d allowed)\n",
fc->count, fc->dropped, fc->allowed);
}
UNLOCK(&resolver->dbuckets[i].lock);
}
#else
UNUSED(resolver);
UNUSED(fp);
return;
#endif /* !ENABLE_FETCHLIMIT */
}
void
dns_resolver_setquotaresponse(dns_resolver_t *resolver,
dns_quotatype_t which, isc_result_t resp)
{
#ifdef ENABLE_FETCHLIMIT
REQUIRE(VALID_RESOLVER(resolver));
REQUIRE(which == dns_quotatype_zone || which == dns_quotatype_server);
REQUIRE(resp == DNS_R_DROP || resp == DNS_R_SERVFAIL);
resolver->quotaresp[which] = resp;
#else
UNUSED(resolver);
UNUSED(which);
UNUSED(resp);
return;
#endif /* !ENABLE_FETCHLIMIT */
}
isc_result_t
dns_resolver_getquotaresponse(dns_resolver_t *resolver, dns_quotatype_t which)
{
#ifdef ENABLE_FETCHLIMIT
REQUIRE(VALID_RESOLVER(resolver));
REQUIRE(which == dns_quotatype_zone || which == dns_quotatype_server);
return (resolver->quotaresp[which]);
#else
UNUSED(resolver);
UNUSED(which);
return (ISC_R_NOTIMPLEMENTED);
#endif /* !ENABLE_FETCHLIMIT */
}

View file

@ -686,7 +686,8 @@ req_shutdown(isc_task_t *task, isc_event_t *event) {
isc_result_t
dns_view_createresolver(dns_view_t *view,
isc_taskmgr_t *taskmgr,
unsigned int ntasks, unsigned int ndisp,
unsigned int ntasks,
unsigned int ndisp,
isc_socketmgr_t *socketmgr,
isc_timermgr_t *timermgr,
unsigned int options,

View file

@ -35,6 +35,7 @@ dns_aclenv_init
dns_adb_agesrtt
dns_adb_adjustsrtt
dns_adb_attach
dns_adb_beginudpfetch
dns_adb_cancelfind
dns_adb_changeflags
dns_adb_create
@ -44,14 +45,17 @@ dns_adb_destroyfind
dns_adb_detach
dns_adb_dump
dns_adb_dumpfind
dns_adb_endudpfetch
dns_adb_findaddrinfo
dns_adb_flush
dns_adb_flushname
dns_adb_freeaddrinfo
dns_adb_marklame
dns_adb_setadbsize
dns_adb_setquota
dns_adb_shutdown
dns_adb_whenshutdown
dns_adbentry_overquota
dns_byaddr_cancel
dns_byaddr_create
dns_byaddr_createptrname
@ -741,10 +745,14 @@ dns_resolver_printbadcache
dns_resolver_reset_algorithms
dns_resolver_resetmustbesecure
dns_resolver_setclientsperquery
dns_resolver_setfetchesperzone
dns_resolver_setlamettl
dns_resolver_setmustbesecure
dns_resolver_setmaxdepth
dns_resolver_setmaxqueries
dns_resolver_setquerydscp4
dns_resolver_setquerydscp6
dns_resolver_setquotaresponse
dns_resolver_settimeout
dns_resolver_setudpsize
dns_resolver_setzeronosoattl

View file

@ -56,6 +56,8 @@
#define ISC_MAX(a, b) ((a) > (b) ? (a) : (b))
#define ISC_MIN(a, b) ((a) < (b) ? (a) : (b))
#define ISC_CLAMP(v, x, y) ((v) < (x) ? (x) : ((v) > (y) ? (y) : (v)))
/*%
* Use this to remove the const qualifier of a variable to assign it to
* a non-const variable or pass it as a non-const function argument ...

View file

@ -247,6 +247,18 @@ cfg_obj_asuint64(const cfg_obj_t *obj);
* \li A 64-bit unsigned integer.
*/
isc_uint32_t
cfg_obj_asfixedpoint(const cfg_obj_t *obj);
/*%<
* Returns the value of a configuration object of fixed point number.
*
* Requires:
* \li 'obj' points to a valid configuration object of fixed point type.
*
* Returns:
* \li A 32-bit unsigned integer.
*/
isc_boolean_t
cfg_obj_isstring(const cfg_obj_t *obj);
/*%<

View file

@ -255,6 +255,7 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_tuple;
LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_sockaddr;
LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_netprefix;
LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_void;
LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_fixedpoint;
/*@}*/
/*@{*/
@ -278,6 +279,7 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netprefix;
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_void;
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_token;
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_unsupported;
LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_fixedpoint;
/*@}*/
isc_result_t
@ -437,6 +439,12 @@ cfg_print_void(cfg_printer_t *pctx, const cfg_obj_t *obj);
void
cfg_doc_void(cfg_printer_t *pctx, const cfg_type_t *type);
isc_result_t
cfg_parse_fixedpoint(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
void
cfg_print_fixedpoint(cfg_printer_t *pctx, const cfg_obj_t *obj);
isc_result_t
cfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);

View file

@ -105,6 +105,7 @@ static cfg_type_t cfg_type_optional_class;
static cfg_type_t cfg_type_optional_facility;
static cfg_type_t cfg_type_optional_keyref;
static cfg_type_t cfg_type_optional_port;
static cfg_type_t cfg_type_optional_uint32;
static cfg_type_t cfg_type_options;
static cfg_type_t cfg_type_portiplist;
static cfg_type_t cfg_type_querysource4;
@ -844,6 +845,58 @@ static cfg_type_t cfg_type_bracketed_portlist = {
&cfg_rep_list, &cfg_type_portrange
};
#ifdef ENABLE_FETCHLIMIT
/*%
* fetch-quota-params
*/
static cfg_tuplefielddef_t fetchquota_fields[] = {
{ "frequency", &cfg_type_uint32, 0 },
{ "low", &cfg_type_fixedpoint, 0 },
{ "high", &cfg_type_fixedpoint, 0 },
{ "discount", &cfg_type_fixedpoint, 0 },
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_fetchquota = {
"fetchquota", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
&cfg_rep_tuple, fetchquota_fields
};
/*%
* fetches-per-server or fetches-per-zone
*/
static const char *response_enums[] = { "drop", "fail", NULL };
static isc_result_t
parse_optional_response(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret)
{
return (parse_enum_or_other(pctx, type, &cfg_type_void, ret));
}
static void
doc_optional_response(cfg_printer_t *pctx, const cfg_type_t *type) {
UNUSED(type);
cfg_print_cstr(pctx, "[ ( drop | fail ) ]");
}
static cfg_type_t cfg_type_responsetype = {
"responsetype", parse_optional_response, cfg_print_ustring,
doc_optional_response, &cfg_rep_string, response_enums
};
static cfg_tuplefielddef_t fetchesper_fields[] = {
{ "fetches", &cfg_type_uint32, 0 },
{ "response", &cfg_type_responsetype, 0 },
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_fetchesper = {
"fetchesper", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
&cfg_rep_tuple, fetchesper_fields
};
#endif /* ENABLE_FETCHLIMIT */
/*%
* Clauses that can be found within the top level of the named.conf
* file only.
@ -1091,7 +1144,7 @@ cleanup:
}
/*
* Parse a tuple consisting of any kind of required field followed
* Parse a tuple consisting of any kind of required field followed
* by 2 or more optional keyvalues that can be in any order.
*/
static isc_result_t
@ -1283,8 +1336,7 @@ static cfg_type_t cfg_type_rrl = {
*/
static void
print_lookaside(cfg_printer_t *pctx, const cfg_obj_t *obj)
{
print_lookaside(cfg_printer_t *pctx, const cfg_obj_t *obj) {
const cfg_obj_t *domain = obj->value.tuple[0];
if (domain->value.string.length == 4 &&
@ -1387,6 +1439,11 @@ view_clauses[] = {
{ "empty-server", &cfg_type_astring, 0 },
{ "empty-zones-enable", &cfg_type_boolean, 0 },
{ "fetch-glue", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
#ifdef ENABLE_FETCHLIMIT
{ "fetch-quota-params", &cfg_type_fetchquota, 0 },
{ "fetches-per-server", &cfg_type_fetchesper, 0 },
{ "fetches-per-zone", &cfg_type_fetchesper, 0 },
#endif /* ENABLE_FETCHLIMIT */
{ "ixfr-from-differences", &cfg_type_ixfrdifftype, 0 },
{ "lame-ttl", &cfg_type_uint32, 0 },
{ "max-acache-size", &cfg_type_sizenodefault, 0 },

View file

@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id$ */
/*! \file */
#include <config.h>
#include <stdlib.h>
#include <isc/buffer.h>
#include <isc/dir.h>
#include <isc/formatcheck.h>
@ -122,6 +122,7 @@ cfg_rep_t cfg_rep_tuple = { "tuple", free_tuple };
cfg_rep_t cfg_rep_sockaddr = { "sockaddr", free_noop };
cfg_rep_t cfg_rep_netprefix = { "netprefix", free_noop };
cfg_rep_t cfg_rep_void = { "void", free_noop };
cfg_rep_t cfg_rep_fixedpoint = { "fixedpoint", free_noop };
/*
* Configuration type definitions.
@ -601,6 +602,80 @@ cfg_type_t cfg_type_void = {
"void", cfg_parse_void, cfg_print_void, cfg_doc_void, &cfg_rep_void,
NULL };
/*
* Fixed point
*/
isc_result_t
cfg_parse_fixedpoint(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret)
{
isc_result_t result;
cfg_obj_t *obj = NULL;
UNUSED(type);
size_t n1, n2, n3, l;
const char *p;
UNUSED(type);
CHECK(cfg_gettoken(pctx, 0));
if (pctx->token.type != isc_tokentype_string) {
cfg_parser_error(pctx, CFG_LOG_NEAR,
"expected fixed point number");
return (ISC_R_UNEXPECTEDTOKEN);
}
p = TOKEN_STRING(pctx);
l = strlen(p);
n1 = strspn(p, "0123456789");
n2 = strspn(p + n1, ".");
n3 = strspn(p + n1 + n2, "0123456789");
if ((n1 + n2 + n3 != l) || (n1 + n3 == 0) ||
n1 > 5 || n2 > 1 || n3 > 2) {
cfg_parser_error(pctx, CFG_LOG_NEAR,
"expected fixed point number");
return (ISC_R_UNEXPECTEDTOKEN);
}
CHECK(cfg_create_obj(pctx, &cfg_type_fixedpoint, &obj));
obj->value.uint32 = strtoul(p, NULL, 10) * 100;
switch (n3) {
case 2:
obj->value.uint32 += strtoul(p + n1 + n2, NULL, 10);
break;
case 1:
obj->value.uint32 += strtoul(p + n1 + n2, NULL, 10) * 10;
break;
}
*ret = obj;
cleanup:
return (result);
}
void
cfg_print_fixedpoint(cfg_printer_t *pctx, const cfg_obj_t *obj) {
char buf[64];
int n;
n = snprintf(buf, sizeof(buf), "%u.%02u",
obj->value.uint32/100, obj->value.uint32%100);
INSIST(n > 0 && (size_t)n < sizeof(buf));
cfg_print_chars(pctx, buf, strlen(buf));
}
isc_uint32_t
cfg_obj_asfixedpoint(const cfg_obj_t *obj) {
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_fixedpoint);
return (obj->value.uint32);
}
cfg_type_t cfg_type_fixedpoint = {
"fixedpoint", cfg_parse_fixedpoint, cfg_print_fixedpoint,
cfg_doc_terminal, &cfg_rep_fixedpoint, NULL
};
/*
* uint32

View file

@ -31,6 +31,7 @@ cfg_lookingat_netaddr
cfg_map_get
cfg_map_getname
cfg_obj_asboolean
cfg_obj_asfixedpoint
cfg_obj_asnetprefix
cfg_obj_assockaddr
cfg_obj_asstring
@ -59,6 +60,7 @@ cfg_parse_bracketed_list
cfg_parse_buffer
cfg_parse_enum
cfg_parse_file
cfg_parse_fixedpoint
cfg_parse_listelt
cfg_parse_map
cfg_parse_mapbody
@ -88,6 +90,7 @@ cfg_print_boolean
cfg_print_bracketed_list
cfg_print_chars
cfg_print_cstr
cfg_print_fixedpoint
cfg_print_grammar
cfg_print_map
cfg_print_mapbody