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]
#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>
*/
#endif
+
/*% nameserver client manager structure */
struct ns_clientmgr {
/* Unlocked. */
}
if (TCP_CLIENT(client))
isc_stats_increment(ns_g_server->nsstats,
- dns_nsstatscounter_tcp);
+ dns_nsstatscounter_requesttcp);
/*
* It's a request. Parse it.
*/
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;
}
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\
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 */
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,
dns_nsstatscounter_updatefail = 34,
dns_nsstatscounter_updatebadprereq = 35,
- dns_nsstatscounter_rpz_rewrites = 36,
+ dns_nsstatscounter_recursclients = 36,
+
+ dns_nsstatscounter_dns64 = 37,
+
+ 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,
-#ifdef USE_RRL
- dns_nsstatscounter_ratedropped = 37,
- dns_nsstatscounter_rateslipped = 38,
+ 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 = 39
-#else /* USE_RRL */
- dns_nsstatscounter_max = 37
-#endif /* USE_RRL */
+ dns_nsstatscounter_max = 53
};
void
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;
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;
}
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.
*/
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);
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);
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,
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) {
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);
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:
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:
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: statschannel.c,v 1.28 2011/03/12 04:59:46 tbox Exp $ */
-
/*! \file */
#include <config.h>
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);
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");
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 */
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 */
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;
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\
</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
</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>
@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@
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
--- /dev/null
+#!/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;
#include <stdarg.h>
#include <isc/log.h>
+#include <isc/print.h>
#include <isc/result.h>
#include <isc/string.h>
#include <isc/types.h>
--- /dev/null
+# 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}
+
--- /dev/null
+#!/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";
+ }
+}
--- /dev/null
+#!/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.*
--- /dev/null
+/*
+ * 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
+}
--- /dev/null
+#!/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";
+ }
+}
--- /dev/null
+#!/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
--- /dev/null
+/*
+ * 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";
+};
--- /dev/null
+; 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
--- /dev/null
+; 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
--- /dev/null
+/*
+ * 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; };
+};
--- /dev/null
+/*
+ * 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";
+};
--- /dev/null
+/*
+ * 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";
+};
--- /dev/null
+/*
+ * 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";
+};
--- /dev/null
+; 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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+/*
+ * 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";
+};
--- /dev/null
+; 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
--- /dev/null
+; 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
--- /dev/null
+/*
+ * 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; };
+};
--- /dev/null
+# 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
--- /dev/null
+/*
+ * 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";
+};
--- /dev/null
+/*
+ * 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";
+};
--- /dev/null
+/*
+ * 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";
+};
--- /dev/null
+; 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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
--- /dev/null
+#!/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
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id$
-
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
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
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 /'
/* 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
enable_fixed_rrset
enable_rpz_nsip
enable_rpz_nsdname
+enable_fetchlimit
enable_filter_aaaa
with_docbook_xsl
with_idn
[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]
;;
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
;;
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 :
# 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"
#
"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" ;;
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" && \
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)"
;;
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
;;
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
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
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" && \
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)"
<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>
<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>
<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.
- </para>
+ 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>
</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
+ (<qname,qtype,qclass>) 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>
</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
- (<qname,qtype,qclass>) 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>
<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>
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 */
};
/*
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;
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);
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!
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);
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,
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;
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;
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;
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);
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);
}
}
}
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));
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));
}
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;
{
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);
}
}
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)
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 */
+}
* 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.
*\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);
*\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 */
* 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 */
#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
* 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
#include <isc/lang.h>
#include <isc/socket.h>
+#include <isc/stats.h>
#include <dns/types.h>
#include <dns/fixedname.h>
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.
*/
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,
* \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 */
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.
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: log.c,v 1.49 2011/10/13 22:48:24 tbox Exp $ */
-
/*! \file */
/* Principal Authors: DCL */
{ "rpz", 0 },
{ "rate-limit", 0 },
{ "cname", 0 },
+ { "spill", 0 },
{ NULL, 0 }
};
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id$ */
-
/*! \file */
#include <config.h>
#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. */
#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.
*/
dns_rdatatype_t type;
unsigned int options;
unsigned int bucketnum;
+ unsigned int dbucketnum;
char * info;
isc_mem_t * mctx;
unsigned int querysent;
unsigned int referrals;
unsigned int lamecount;
+ unsigned int quotacount;
unsigned int neterr;
unsigned int badresp;
unsigned int adberr;
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 {
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;
unsigned int query_timeout;
unsigned int maxdepth;
unsigned int maxqueries;
+ isc_result_t quotaresp[2];
/* Locked by lock. */
unsigned int references;
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;
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.
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;
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;
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;
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);
/*
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
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");
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 */
}
}
}
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.
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);
}
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)
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 {
/*
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'",
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);
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.
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
}
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);
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;
TIME_NOW(&fctx->start);
fctx->timeouts = 0;
fctx->lamecount = 0;
+ fctx->quotacount = 0;
fctx->adberr = 0;
fctx->neterr = 0;
fctx->badresp = 0;
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));
&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,
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);
* 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);
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");
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);
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.
*/
}
}
+ 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);
fctx->referrals++;
fctx->querysent = 0;
fctx->lamecount = 0;
+ fctx->quotacount = 0;
fctx->neterr = 0;
fctx->badresp = 0;
fctx->adberr = 0;
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);
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);
}
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)
isc_task_t *task = NULL;
char name[16];
unsigned dispattr;
+#ifdef ENABLE_FETCHLIMIT
+ unsigned int dbuckets_created = 0;
+#endif /* ENABLE_FETCHLIMIT */
/*
* Create a resolver.
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,
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,
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);
"%" 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,
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;
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));
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 */
+}
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,
dns_adb_agesrtt
dns_adb_adjustsrtt
dns_adb_attach
+dns_adb_beginudpfetch
dns_adb_cancelfind
dns_adb_changeflags
dns_adb_create
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
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
#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 ...
* \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);
/*%<
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;
/*@}*/
/*@{*/
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
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);
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;
&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.
}
/*
- * 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
*/
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 &&
{ "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 },
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id$ */
-
/*! \file */
#include <config.h>
+#include <stdlib.h>
+
#include <isc/buffer.h>
#include <isc/dir.h>
#include <isc/formatcheck.h>
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.
"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
cfg_map_get
cfg_map_getname
cfg_obj_asboolean
+cfg_obj_asfixedpoint
cfg_obj_asnetprefix
cfg_obj_assockaddr
cfg_obj_asstring
cfg_parse_buffer
cfg_parse_enum
cfg_parse_file
+cfg_parse_fixedpoint
cfg_parse_listelt
cfg_parse_map
cfg_parse_mapbody
cfg_print_bracketed_list
cfg_print_chars
cfg_print_cstr
+cfg_print_fixedpoint
cfg_print_grammar
cfg_print_map
cfg_print_mapbody