mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 01:59:26 +00:00
[master] refactor max-recursion-queries
- the counters weren't set correctly when fetches timed out. instead we now pass down a counter object.
This commit is contained in:
parent
795beed720
commit
05e448935c
@ -3908,7 +3908,7 @@ query_prefetch(ns_client_t *client, dns_name_t *qname,
|
||||
result = dns_resolver_createfetch3(client->view->resolver,
|
||||
qname, rdataset->type, NULL, NULL,
|
||||
NULL, peeraddr, client->message->id,
|
||||
options, 0, client->task,
|
||||
options, 0, NULL, client->task,
|
||||
prefetch_done, client,
|
||||
tmprdataset, NULL,
|
||||
&client->query.prefetch);
|
||||
@ -4029,7 +4029,7 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
|
||||
result = dns_resolver_createfetch3(client->view->resolver,
|
||||
qname, qtype, qdomain, nameservers,
|
||||
NULL, peeraddr, client->message->id,
|
||||
client->query.fetchoptions, 0,
|
||||
client->query.fetchoptions, 0, NULL,
|
||||
client->task, query_resume, client,
|
||||
rdataset, sigrdataset,
|
||||
&client->query.fetch);
|
||||
|
@ -5,5 +5,7 @@ system test for recursion limits
|
||||
|
||||
ns1 -- root server
|
||||
ans2 -- delegate to ns1.(n+1).example.com for all n, up to
|
||||
the value specified in ans.limit
|
||||
the value specified in ans.limit (or forever if limit is 0)
|
||||
ns3 -- resolver under test
|
||||
ans4 -- delegates every query to 16 more name servers, with "victim" address
|
||||
ans7 -- "victim" server
|
||||
|
@ -34,13 +34,13 @@ my $send_response = 0;
|
||||
|
||||
sub getlimit {
|
||||
if ( -e "ans.limit") {
|
||||
open(FH, "<", "ans.limit");
|
||||
my $line = <FH>;
|
||||
chomp $line;
|
||||
close FH;
|
||||
if ($line =~ /^\d+$/) {
|
||||
return $line;
|
||||
}
|
||||
open(FH, "<", "ans.limit");
|
||||
my $line = <FH>;
|
||||
chomp $line;
|
||||
close FH;
|
||||
if ($line =~ /^\d+$/) {
|
||||
return $line;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -61,53 +61,53 @@ sub reply_handler {
|
||||
$count += 1;
|
||||
|
||||
if ($qname eq "count" ) {
|
||||
if ($qtype eq "TXT") {
|
||||
my ($ttl, $rdata) = (0, "$count");
|
||||
my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
|
||||
push @ans, $rr;
|
||||
print ("\tcount: $count\n");
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
if ($qtype eq "TXT") {
|
||||
my ($ttl, $rdata) = (0, "$count");
|
||||
my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
|
||||
push @ans, $rr;
|
||||
print ("\tcount: $count\n");
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
} elsif ($qname eq "reset" ) {
|
||||
$count = 0;
|
||||
$send_response = 0;
|
||||
$limit = getlimit();
|
||||
$rcode = "NOERROR";
|
||||
print ("\tlimit: $limit\n");
|
||||
$count = 0;
|
||||
$send_response = 0;
|
||||
$limit = getlimit();
|
||||
$rcode = "NOERROR";
|
||||
print ("\tlimit: $limit\n");
|
||||
} elsif ($qname eq "direct.example.org" ) {
|
||||
if ($qtype eq "A") {
|
||||
my ($ttl, $rdata) = (3600, $localaddr);
|
||||
my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
|
||||
push @ans, $rr;
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
if ($qtype eq "A") {
|
||||
my ($ttl, $rdata) = (3600, $localaddr);
|
||||
my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
|
||||
push @ans, $rr;
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
} elsif ($qname eq "indirect.example.org") {
|
||||
if (! $send_response) {
|
||||
my $rr = new Net::DNS::RR("indirect.example.org 86400 $qclass NS ns1.1.example.org");
|
||||
push @auth, $rr;
|
||||
} elsif ($qtype eq "A") {
|
||||
my ($ttl, $rdata) = (3600, $localaddr);
|
||||
my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
|
||||
push @ans, $rr;
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
if (! $send_response) {
|
||||
my $rr = new Net::DNS::RR("indirect.example.org 86400 $qclass NS ns1.1.example.org");
|
||||
push @auth, $rr;
|
||||
} elsif ($qtype eq "A") {
|
||||
my ($ttl, $rdata) = (3600, $localaddr);
|
||||
my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
|
||||
push @ans, $rr;
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
} elsif ($qname =~ /^ns1\.(\d+)\.example\.org$/) {
|
||||
my $next = $1 + 1;
|
||||
if ($limit == 0 || (! $send_response && $next <= $limit)) {
|
||||
my $rr = new Net::DNS::RR("$1.example.org 86400 $qclass NS ns1.$next.example.org");
|
||||
push @auth, $rr;
|
||||
} else {
|
||||
$send_response = 1;
|
||||
if ($qtype eq "A") {
|
||||
my ($ttl, $rdata) = (3600, $localaddr);
|
||||
my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
|
||||
print("\tresponse: $qname $ttl $qclass $qtype $rdata\n");
|
||||
push @ans, $rr;
|
||||
}
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
my $next = $1 + 1;
|
||||
if ($limit == 0 || (! $send_response && $next <= $limit)) {
|
||||
my $rr = new Net::DNS::RR("$1.example.org 86400 $qclass NS ns1.$next.example.org");
|
||||
push @auth, $rr;
|
||||
} else {
|
||||
$send_response = 1;
|
||||
if ($qtype eq "A") {
|
||||
my ($ttl, $rdata) = (3600, $localaddr);
|
||||
my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
|
||||
print("\tresponse: $qname $ttl $qclass $qtype $rdata\n");
|
||||
push @ans, $rr;
|
||||
}
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
} else {
|
||||
$rcode = "NXDOMAIN";
|
||||
$rcode = "NXDOMAIN";
|
||||
}
|
||||
|
||||
# mark the answer as authoritive (by setting the 'aa' flag
|
||||
|
83
bin/tests/system/reclimit/ans4/ans.pl
Normal file
83
bin/tests/system/reclimit/ans4/ans.pl
Normal file
@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use IO::File;
|
||||
use Getopt::Long;
|
||||
use Net::DNS::Nameserver;
|
||||
|
||||
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;
|
||||
|
||||
my $count = 0;
|
||||
my $send_response = 0;
|
||||
|
||||
my $localaddr = "10.53.0.4";
|
||||
my $localport = 5300;
|
||||
my $verbose = 0;
|
||||
|
||||
sub reply_handler {
|
||||
my ($qname, $qclass, $qtype, $peerhost, $query, $conn) = @_;
|
||||
my ($rcode, @ans, @auth, @add);
|
||||
|
||||
print ("request: $qname/$qtype\n");
|
||||
STDOUT->flush();
|
||||
|
||||
$count += 1;
|
||||
|
||||
if ($qname eq "count" ) {
|
||||
if ($qtype eq "TXT") {
|
||||
my ($ttl, $rdata) = (0, "$count");
|
||||
my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
|
||||
push @ans, $rr;
|
||||
print ("\tcount: $count\n");
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
} elsif ($qname eq "reset" ) {
|
||||
$count = 0;
|
||||
$send_response = 0;
|
||||
$rcode = "NOERROR";
|
||||
} elsif ($qname eq "direct.example.net" ) {
|
||||
if ($qtype eq "A") {
|
||||
my ($ttl, $rdata) = (3600, $localaddr);
|
||||
my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
|
||||
push @ans, $rr;
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
} elsif( $qname =~ /^ns1\.(\d+)\.example\.net$/ ) {
|
||||
my $next = ($1 + 1) * 16;
|
||||
for (my $i = 1; $i < 16; $i++) {
|
||||
my $s = $next + $i;
|
||||
my $rr = new Net::DNS::RR("$1.example.net 86400 $qclass NS ns1.$s.example.net");
|
||||
push @auth, $rr;
|
||||
$rr = new Net::DNS::RR("ns1.$s.example.net 86400 $qclass A 10.53.0.7");
|
||||
push @add, $rr;
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
} else {
|
||||
$rcode = "NXDOMAIN";
|
||||
}
|
||||
|
||||
# mark the answer as authoritive (by setting the 'aa' flag
|
||||
return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
|
||||
}
|
||||
|
||||
GetOptions(
|
||||
'port=i' => \$localport,
|
||||
'verbose!' => \$verbose,
|
||||
);
|
||||
|
||||
my $ns = Net::DNS::Nameserver->new(
|
||||
LocalAddr => $localaddr,
|
||||
LocalPort => $localport,
|
||||
ReplyHandler => \&reply_handler,
|
||||
Verbose => $verbose,
|
||||
);
|
||||
|
||||
$ns->main_loop;
|
64
bin/tests/system/reclimit/ans7/ans.pl
Normal file
64
bin/tests/system/reclimit/ans7/ans.pl
Normal file
@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use IO::File;
|
||||
use Getopt::Long;
|
||||
use Net::DNS::Nameserver;
|
||||
|
||||
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;
|
||||
|
||||
my $count = 0;
|
||||
|
||||
my $localaddr = "10.53.0.7";
|
||||
my $localport = 5300;
|
||||
my $verbose = 0;
|
||||
|
||||
sub reply_handler {
|
||||
my ($qname, $qclass, $qtype, $peerhost, $query, $conn) = @_;
|
||||
my ($rcode, @ans, @auth, @add);
|
||||
|
||||
print ("request: $qname/$qtype\n");
|
||||
STDOUT->flush();
|
||||
|
||||
$count += 1;
|
||||
|
||||
if ($qname eq "count" ) {
|
||||
if ($qtype eq "TXT") {
|
||||
my ($ttl, $rdata) = (0, "$count");
|
||||
my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
|
||||
push @ans, $rr;
|
||||
print ("\tcount: $count\n");
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
} elsif ($qname eq "reset") {
|
||||
$count = 0;
|
||||
$rcode = "NOERROR";
|
||||
} else {
|
||||
$rcode = "REFUSED";
|
||||
}
|
||||
|
||||
# mark the answer as authoritive (by setting the 'aa' flag
|
||||
return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
|
||||
}
|
||||
|
||||
GetOptions(
|
||||
'port=i' => \$localport,
|
||||
'verbose!' => \$verbose,
|
||||
);
|
||||
|
||||
my $ns = Net::DNS::Nameserver->new(
|
||||
LocalAddr => $localaddr,
|
||||
LocalPort => $localport,
|
||||
ReplyHandler => \&reply_handler,
|
||||
Verbose => $verbose,
|
||||
);
|
||||
|
||||
$ns->main_loop;
|
@ -18,3 +18,5 @@ ns.nil. 60 IN A 10.53.0.1
|
||||
ns.tld1. 60 IN A 10.53.0.1
|
||||
example.org. 60 IN NS direct.example.org.
|
||||
direct.example.org. 60 IN A 10.53.0.2
|
||||
example.net. 60 IN NS direct.example.net.
|
||||
direct.example.net. 60 IN A 10.53.0.4
|
||||
|
@ -90,29 +90,28 @@ sleep 2
|
||||
n=`expr $n + 1`
|
||||
echo "I: attempt excessive-queries lookup ($n)"
|
||||
ret=0
|
||||
echo "25" > ans2/ans.limit
|
||||
echo "13" > ans2/ans.limit
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 flush 2>&1 | sed 's/^/I:ns1 /'
|
||||
$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.3 indirect.example.org > dig.out.1.test$n || ret=1
|
||||
grep "status: SERVFAIL" dig.out.1.test$n > /dev/null || ret=1
|
||||
grep "exceeded max queries resolving 'indirect.example.org/A'" ns3/named.run > /dev/null || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1
|
||||
eval count=`cat dig.out.2.test$n`
|
||||
[ $count -eq 100 ] || ret=1
|
||||
[ $count -le 50 ] || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I: attempt permissible lookup ($n)"
|
||||
ret=0
|
||||
echo "24" > ans2/ans.limit
|
||||
echo "12" > ans2/ans.limit
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 flush 2>&1 | sed 's/^/I:ns1 /'
|
||||
$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.3 indirect.example.org > dig.out.1.test$n || ret=1
|
||||
grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1
|
||||
eval count=`cat dig.out.2.test$n`
|
||||
[ $count -eq 97 ] || ret=1
|
||||
[ $count -le 50 ] || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
@ -124,29 +123,43 @@ sleep 2
|
||||
n=`expr $n + 1`
|
||||
echo "I: attempt excessive-queries lookup ($n)"
|
||||
ret=0
|
||||
echo "21" > ans2/ans.limit
|
||||
echo "10" > ans2/ans.limit
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 flush 2>&1 | sed 's/^/I:ns1 /'
|
||||
$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.3 indirect.example.org > dig.out.1.test$n || ret=1
|
||||
grep "status: SERVFAIL" dig.out.1.test$n > /dev/null || ret=1
|
||||
grep "exceeded max queries resolving 'indirect.example.org/A'" ns3/named.run > /dev/null || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1
|
||||
eval count=`cat dig.out.2.test$n`
|
||||
[ $count -eq 84 ] || ret=1
|
||||
[ $count -le 40 ] || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I: attempt permissible lookup ($n)"
|
||||
ret=0
|
||||
echo "19" > ans2/ans.limit
|
||||
echo "9" > ans2/ans.limit
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 flush 2>&1 | sed 's/^/I:ns1 /'
|
||||
$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.3 indirect.example.org > dig.out.1.test$n || ret=1
|
||||
grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1
|
||||
eval count=`cat dig.out.2.test$n`
|
||||
[ $count -eq 77 ] || ret=1
|
||||
[ $count -le 40 ] || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo "I: attempting NS explosion ($n)"
|
||||
ret=0
|
||||
$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 flush 2>&1 | sed 's/^/I:ns1 /'
|
||||
$DIG $DIGOPTS +short @10.53.0.3 ns1.1.example.net > dig.out.1.test$n || ret=1
|
||||
sleep 2
|
||||
$DIG $DIGOPTS +short @10.53.0.4 count txt > dig.out.2.test$n || ret=1
|
||||
eval count=`cat dig.out.2.test$n`
|
||||
[ $count -lt 50 ] || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.7 count txt > dig.out.3.test$n || ret=1
|
||||
eval count=`cat dig.out.3.test$n`
|
||||
[ $count -lt 50 ] || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
|
@ -313,8 +313,7 @@ static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, isc_boolean_t,
|
||||
static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
|
||||
static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
|
||||
static void clean_target(dns_adb_t *, dns_name_t *);
|
||||
static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
|
||||
isc_uint32_t, unsigned int);
|
||||
static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int);
|
||||
static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
|
||||
static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **,
|
||||
isc_stdtime_t);
|
||||
@ -322,7 +321,8 @@ static void cancel_fetches_at_name(dns_adbname_t *);
|
||||
static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
|
||||
dns_rdatatype_t);
|
||||
static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
|
||||
unsigned int, dns_rdatatype_t);
|
||||
unsigned int, isc_counter_t *qc,
|
||||
dns_rdatatype_t);
|
||||
static inline void check_exit(dns_adb_t *);
|
||||
static void destroy(dns_adb_t *);
|
||||
static isc_boolean_t shutdown_names(dns_adb_t *);
|
||||
@ -1025,7 +1025,7 @@ kill_name(dns_adbname_t **n, isc_eventtype_t ev) {
|
||||
* Clean up the name's various lists. These two are destructive
|
||||
* in that they will always empty the list.
|
||||
*/
|
||||
clean_finds_at_name(name, ev, 0, DNS_ADBFIND_ADDRESSMASK);
|
||||
clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK);
|
||||
result4 = clean_namehooks(adb, &name->v4);
|
||||
result6 = clean_namehooks(adb, &name->v6);
|
||||
clean_target(adb, &name->target);
|
||||
@ -1450,7 +1450,7 @@ event_free(isc_event_t *event) {
|
||||
*/
|
||||
static void
|
||||
clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
|
||||
isc_uint32_t qtotal, unsigned int addrs)
|
||||
unsigned int addrs)
|
||||
{
|
||||
isc_event_t *ev;
|
||||
isc_task_t *task;
|
||||
@ -1510,7 +1510,6 @@ clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
|
||||
ev->ev_sender = find;
|
||||
find->result_v4 = find_err_map[name->fetch_err];
|
||||
find->result_v6 = find_err_map[name->fetch6_err];
|
||||
find->qtotal += qtotal;
|
||||
ev->ev_type = evtype;
|
||||
ev->ev_destroy = event_free;
|
||||
ev->ev_destroy_arg = find;
|
||||
@ -1886,7 +1885,6 @@ new_adbfind(dns_adb_t *adb) {
|
||||
h->flags = 0;
|
||||
h->result_v4 = ISC_R_UNEXPECTED;
|
||||
h->result_v6 = ISC_R_UNEXPECTED;
|
||||
h->qtotal = 0;
|
||||
ISC_LINK_INIT(h, publink);
|
||||
ISC_LINK_INIT(h, plink);
|
||||
ISC_LIST_INIT(h->list);
|
||||
@ -2870,7 +2868,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
{
|
||||
return (dns_adb_createfind2(adb, task, action, arg, name,
|
||||
qname, qtype, options, now,
|
||||
target, port, 0, findp));
|
||||
target, port, 0, NULL, findp));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
@ -2878,7 +2876,7 @@ dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
void *arg, dns_name_t *name, dns_name_t *qname,
|
||||
dns_rdatatype_t qtype, unsigned int options,
|
||||
isc_stdtime_t now, dns_name_t *target,
|
||||
in_port_t port, unsigned int depth,
|
||||
in_port_t port, unsigned int depth, isc_counter_t *qc,
|
||||
dns_adbfind_t **findp)
|
||||
{
|
||||
dns_adbfind_t *find;
|
||||
@ -3117,7 +3115,7 @@ dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
* Start V4.
|
||||
*/
|
||||
if (WANT_INET(wanted_fetches) &&
|
||||
fetch_name(adbname, start_at_zone, depth,
|
||||
fetch_name(adbname, start_at_zone, depth, qc,
|
||||
dns_rdatatype_a) == ISC_R_SUCCESS) {
|
||||
DP(DEF_LEVEL, "dns_adb_createfind: "
|
||||
"started A fetch for name %s (%p)",
|
||||
@ -3128,7 +3126,7 @@ dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
* Start V6.
|
||||
*/
|
||||
if (WANT_INET6(wanted_fetches) &&
|
||||
fetch_name(adbname, start_at_zone, depth,
|
||||
fetch_name(adbname, start_at_zone, depth, qc,
|
||||
dns_rdatatype_aaaa) == ISC_R_SUCCESS) {
|
||||
DP(DEF_LEVEL, "dns_adb_createfind: "
|
||||
"started AAAA fetch for name %s (%p)",
|
||||
@ -3760,7 +3758,6 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
|
||||
isc_result_t result;
|
||||
unsigned int address_type;
|
||||
isc_boolean_t want_check_exit = ISC_FALSE;
|
||||
isc_uint32_t qtotal = 0;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
@ -3771,8 +3768,6 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
|
||||
adb = name->adb;
|
||||
INSIST(DNS_ADB_VALID(adb));
|
||||
|
||||
qtotal = dev->qtotal;
|
||||
|
||||
bucket = name->lock_bucket;
|
||||
LOCK(&adb->namelocks[bucket]);
|
||||
|
||||
@ -3927,14 +3922,14 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
|
||||
free_adbfetch(adb, &fetch);
|
||||
isc_event_free(&ev);
|
||||
|
||||
clean_finds_at_name(name, ev_status, qtotal, address_type);
|
||||
clean_finds_at_name(name, ev_status, address_type);
|
||||
|
||||
UNLOCK(&adb->namelocks[bucket]);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone,
|
||||
unsigned int depth, dns_rdatatype_t type)
|
||||
unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type)
|
||||
{
|
||||
isc_result_t result;
|
||||
dns_adbfetch_t *fetch = NULL;
|
||||
@ -3983,8 +3978,8 @@ fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone,
|
||||
|
||||
result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name,
|
||||
type, name, nameservers, NULL,
|
||||
NULL, 0, options, depth, adb->task,
|
||||
fetch_callback, adbname,
|
||||
NULL, 0, options, depth, qc,
|
||||
adb->task, fetch_callback, adbname,
|
||||
&fetch->rdataset, NULL,
|
||||
&fetch->fetch);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
|
@ -118,8 +118,6 @@ struct dns_adbfind {
|
||||
isc_result_t result_v6; /*%< RO: v6 result */
|
||||
ISC_LINK(dns_adbfind_t) publink; /*%< RW: client use */
|
||||
|
||||
isc_uint32_t qtotal;
|
||||
|
||||
/* Private */
|
||||
isc_mutex_t lock; /* locks all below */
|
||||
in_port_t port;
|
||||
@ -343,7 +341,8 @@ dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
void *arg, dns_name_t *name, dns_name_t *qname,
|
||||
dns_rdatatype_t qtype, unsigned int options,
|
||||
isc_stdtime_t now, dns_name_t *target, in_port_t port,
|
||||
unsigned int depth, dns_adbfind_t **find);
|
||||
unsigned int depth, isc_counter_t *qc,
|
||||
dns_adbfind_t **find);
|
||||
/*%<
|
||||
* Main interface for clients. The adb will look up the name given in
|
||||
* "name" and will build up a list of found addresses, and perhaps start
|
||||
|
@ -82,7 +82,6 @@ typedef struct dns_fetchevent {
|
||||
isc_sockaddr_t * client;
|
||||
dns_messageid_t id;
|
||||
isc_result_t vresult;
|
||||
isc_uint32_t qtotal;
|
||||
} dns_fetchevent_t;
|
||||
|
||||
/*
|
||||
@ -286,7 +285,7 @@ dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name,
|
||||
dns_forwarders_t *forwarders,
|
||||
isc_sockaddr_t *client, isc_uint16_t id,
|
||||
unsigned int options, unsigned int depth,
|
||||
isc_task_t *task,
|
||||
isc_counter_t *qc, isc_task_t *task,
|
||||
isc_taskaction_t action, void *arg,
|
||||
dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *sigrdataset,
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <config.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <isc/counter.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/platform.h>
|
||||
#include <isc/print.h>
|
||||
@ -281,12 +282,13 @@ struct fetchctx {
|
||||
ISC_LIST(struct tried) edns;
|
||||
ISC_LIST(struct tried) edns512;
|
||||
isc_sockaddrlist_t bad_edns;
|
||||
dns_validator_t *validator;
|
||||
dns_validator_t * validator;
|
||||
ISC_LIST(dns_validator_t) validators;
|
||||
dns_db_t * cache;
|
||||
dns_adb_t * adb;
|
||||
isc_boolean_t ns_ttl_ok;
|
||||
isc_uint32_t ns_ttl;
|
||||
isc_counter_t * qc;
|
||||
|
||||
/*%
|
||||
* The number of events we're waiting for.
|
||||
@ -344,7 +346,6 @@ struct fetchctx {
|
||||
isc_uint64_t duration;
|
||||
isc_boolean_t logged;
|
||||
unsigned int querysent;
|
||||
unsigned int totalqueries;
|
||||
unsigned int referrals;
|
||||
unsigned int lamecount;
|
||||
unsigned int neterr;
|
||||
@ -1176,7 +1177,6 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result, int line) {
|
||||
event->result == DNS_R_NCACHENXRRSET);
|
||||
}
|
||||
|
||||
event->qtotal = fctx->totalqueries;
|
||||
isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
|
||||
count++;
|
||||
}
|
||||
@ -1643,7 +1643,6 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
|
||||
}
|
||||
|
||||
fctx->querysent++;
|
||||
fctx->totalqueries++;
|
||||
|
||||
ISC_LIST_APPEND(fctx->queries, query, link);
|
||||
query->fctx->nqueries++;
|
||||
@ -2540,7 +2539,6 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
|
||||
*/
|
||||
INSIST(!SHUTTINGDOWN(fctx));
|
||||
fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
|
||||
fctx->totalqueries += find->qtotal;
|
||||
if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) {
|
||||
want_try = ISC_TRUE;
|
||||
} else {
|
||||
@ -2833,7 +2831,7 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
|
||||
&fctx->name, fctx->type,
|
||||
options, now, NULL,
|
||||
res->view->dstport,
|
||||
fctx->depth + 1, &find);
|
||||
fctx->depth + 1, fctx->qc, &find);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (result == DNS_R_ALIAS) {
|
||||
/*
|
||||
@ -3386,15 +3384,6 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
|
||||
|
||||
REQUIRE(!ADDRWAIT(fctx));
|
||||
|
||||
if (fctx->totalqueries > fctx->res->maxqueries) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
|
||||
"exceeded max queries resolving '%s'",
|
||||
fctx->info);
|
||||
fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
addrinfo = fctx_nextaddress(fctx);
|
||||
if (addrinfo == NULL) {
|
||||
/*
|
||||
@ -3432,6 +3421,16 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
|
||||
}
|
||||
}
|
||||
|
||||
result = isc_counter_increment(fctx->qc);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
|
||||
"exceeded max queries resolving '%s'",
|
||||
fctx->info);
|
||||
fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
result = fctx_query(fctx, addrinfo, fctx->options);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fctx_done(fctx, result, __LINE__);
|
||||
@ -3530,6 +3529,7 @@ fctx_destroy(fetchctx_t *fctx) {
|
||||
isc_mem_put(fctx->mctx, sa, sizeof(*sa));
|
||||
}
|
||||
|
||||
isc_counter_detach(&fctx->qc);
|
||||
isc_timer_detach(&fctx->timer);
|
||||
dns_message_destroy(&fctx->rmessage);
|
||||
dns_message_destroy(&fctx->qmessage);
|
||||
@ -3757,7 +3757,6 @@ fctx_start(isc_task_t *task, isc_event_t *event) {
|
||||
* Normal fctx startup.
|
||||
*/
|
||||
fctx->state = fetchstate_active;
|
||||
fctx->totalqueries = 0;
|
||||
/*
|
||||
* Reset the control event for later use in shutting down
|
||||
* the fctx.
|
||||
@ -3827,7 +3826,6 @@ fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_sockaddr_t *client,
|
||||
event->fetch = fetch;
|
||||
event->client = client;
|
||||
event->id = id;
|
||||
event->qtotal = 0;
|
||||
dns_fixedname_init(&event->foundname);
|
||||
|
||||
/*
|
||||
@ -3865,7 +3863,7 @@ static isc_result_t
|
||||
fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
|
||||
dns_name_t *domain, dns_rdataset_t *nameservers,
|
||||
unsigned int options, unsigned int bucketnum, unsigned int depth,
|
||||
fetchctx_t **fctxp)
|
||||
isc_counter_t *qc, fetchctx_t **fctxp)
|
||||
{
|
||||
fetchctx_t *fctx;
|
||||
isc_result_t result;
|
||||
@ -3887,6 +3885,16 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
|
||||
if (fctx == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
fctx->qc = NULL;
|
||||
if (qc != NULL) {
|
||||
isc_counter_attach(qc, &fctx->qc);
|
||||
} else {
|
||||
result = isc_counter_create(res->mctx,
|
||||
res->maxqueries, &fctx->qc);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_fetch;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make fctx->info point to a copy of a formatted string
|
||||
* "name/type".
|
||||
@ -3898,7 +3906,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
|
||||
fctx->info = isc_mem_strdup(mctx, buf);
|
||||
if (fctx->info == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup_fetch;
|
||||
goto cleanup_counter;
|
||||
}
|
||||
|
||||
FCTXTRACE("create");
|
||||
@ -3941,7 +3949,6 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
|
||||
fctx->pending = 0;
|
||||
fctx->restarts = 0;
|
||||
fctx->querysent = 0;
|
||||
fctx->totalqueries = 0;
|
||||
fctx->referrals = 0;
|
||||
TIME_NOW(&fctx->start);
|
||||
fctx->timeouts = 0;
|
||||
@ -4136,6 +4143,9 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
|
||||
cleanup_info:
|
||||
isc_mem_free(mctx, fctx->info);
|
||||
|
||||
cleanup_counter:
|
||||
isc_counter_detach(&fctx->qc);
|
||||
|
||||
cleanup_fetch:
|
||||
isc_mem_put(mctx, fctx, sizeof(*fctx));
|
||||
|
||||
@ -8793,7 +8803,7 @@ dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
|
||||
{
|
||||
return (dns_resolver_createfetch3(res, name, type, domain,
|
||||
nameservers, forwarders, NULL, 0,
|
||||
options, 0, task, action, arg,
|
||||
options, 0, NULL, task, action, arg,
|
||||
rdataset, sigrdataset, fetchp));
|
||||
}
|
||||
|
||||
@ -8811,7 +8821,7 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
|
||||
{
|
||||
return (dns_resolver_createfetch3(res, name, type, domain,
|
||||
nameservers, forwarders, client, id,
|
||||
options, 0, task, action, arg,
|
||||
options, 0, NULL, task, action, arg,
|
||||
rdataset, sigrdataset, fetchp));
|
||||
}
|
||||
|
||||
@ -8822,7 +8832,7 @@ dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name,
|
||||
dns_forwarders_t *forwarders,
|
||||
isc_sockaddr_t *client, dns_messageid_t id,
|
||||
unsigned int options, unsigned int depth,
|
||||
isc_task_t *task,
|
||||
isc_counter_t *qc, isc_task_t *task,
|
||||
isc_taskaction_t action, void *arg,
|
||||
dns_rdataset_t *rdataset,
|
||||
dns_rdataset_t *sigrdataset,
|
||||
@ -8916,7 +8926,7 @@ dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name,
|
||||
|
||||
if (fctx == NULL) {
|
||||
result = fctx_create(res, name, type, domain, nameservers,
|
||||
options, bucketnum, depth, &fctx);
|
||||
options, bucketnum, depth, qc, &fctx);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto unlock;
|
||||
new_fctx = ISC_TRUE;
|
||||
|
@ -13,8 +13,6 @@
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id$
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
@ -57,7 +55,7 @@ WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \
|
||||
OBJS = @ISC_EXTRA_OBJS@ @ISC_PK11_O@ @ISC_PK11_RESULT_O@ \
|
||||
aes.@O@ assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \
|
||||
bind9.@O@ buffer.@O@ bufferlist.@O@ \
|
||||
commandline.@O@ crc64.@O@ error.@O@ event.@O@ \
|
||||
commandline.@O@ counter.@O@ crc64.@O@ error.@O@ event.@O@ \
|
||||
hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \
|
||||
httpd.@O@ inet_aton.@O@ iterated_hash.@O@ \
|
||||
lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \
|
||||
@ -77,7 +75,7 @@ CHACHASRCS = chacha_private.h
|
||||
# Alphabetically
|
||||
SRCS = @ISC_EXTRA_SRCS@ @ISC_PK11_C@ @ISC_PK11_RESULT_C@ \
|
||||
aes.c assertions.c backtrace.c base32.c base64.c bind9.c \
|
||||
buffer.c bufferlist.c commandline.c crc64.c \
|
||||
buffer.c bufferlist.c commandline.c counter.c crc64.c \
|
||||
error.c event.c heap.c hex.c hmacmd5.c hmacsha.c \
|
||||
httpd.c inet_aton.c iterated_hash.c \
|
||||
lex.c lfsr.c lib.c log.c \
|
||||
|
138
lib/isc/counter.c
Normal file
138
lib/isc/counter.c
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <isc/counter.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#define COUNTER_MAGIC ISC_MAGIC('C', 'n', 't', 'r')
|
||||
#define VALID_COUNTER(r) ISC_MAGIC_VALID(r, COUNTER_MAGIC)
|
||||
|
||||
struct isc_counter {
|
||||
unsigned int magic;
|
||||
isc_mem_t *mctx;
|
||||
isc_mutex_t lock;
|
||||
unsigned int references;
|
||||
unsigned int limit;
|
||||
unsigned int used;
|
||||
};
|
||||
|
||||
isc_result_t
|
||||
isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp) {
|
||||
isc_result_t result;
|
||||
isc_counter_t *counter;
|
||||
|
||||
REQUIRE(counterp != NULL && *counterp == NULL);
|
||||
|
||||
counter = isc_mem_get(mctx, sizeof(*counter));
|
||||
if (counter == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
result = isc_mutex_init(&counter->lock);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(mctx, counter, sizeof(*counter));
|
||||
return (result);
|
||||
}
|
||||
|
||||
counter->mctx = NULL;
|
||||
isc_mem_attach(mctx, &counter->mctx);
|
||||
|
||||
counter->references = 1;
|
||||
counter->limit = limit;
|
||||
counter->used = 0;
|
||||
|
||||
counter->magic = COUNTER_MAGIC;
|
||||
*counterp = counter;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_counter_increment(isc_counter_t *counter) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
LOCK(&counter->lock);
|
||||
counter->used++;
|
||||
if (counter->limit != 0 && counter->used >= counter->limit)
|
||||
result = ISC_R_QUOTA;
|
||||
UNLOCK(&counter->lock);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
isc_counter_used(isc_counter_t *counter) {
|
||||
REQUIRE(VALID_COUNTER(counter));
|
||||
|
||||
return (counter->used);
|
||||
}
|
||||
|
||||
void
|
||||
isc_counter_setlimit(isc_counter_t *counter, int limit) {
|
||||
REQUIRE(VALID_COUNTER(counter));
|
||||
|
||||
LOCK(&counter->lock);
|
||||
counter->limit = limit;
|
||||
UNLOCK(&counter->lock);
|
||||
}
|
||||
|
||||
void
|
||||
isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp) {
|
||||
REQUIRE(VALID_COUNTER(source));
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
LOCK(&source->lock);
|
||||
source->references++;
|
||||
INSIST(source->references > 0);
|
||||
UNLOCK(&source->lock);
|
||||
|
||||
*targetp = source;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy(isc_counter_t *counter) {
|
||||
counter->magic = 0;
|
||||
isc_mutex_destroy(&counter->lock);
|
||||
isc_mem_putanddetach(&counter->mctx, counter, sizeof(*counter));
|
||||
}
|
||||
|
||||
void
|
||||
isc_counter_detach(isc_counter_t **counterp) {
|
||||
isc_counter_t *counter;
|
||||
isc_boolean_t want_destroy = ISC_FALSE;
|
||||
|
||||
REQUIRE(counterp != NULL && *counterp != NULL);
|
||||
counter = *counterp;
|
||||
REQUIRE(VALID_COUNTER(counter));
|
||||
|
||||
*counterp = NULL;
|
||||
|
||||
LOCK(&counter->lock);
|
||||
INSIST(counter->references > 0);
|
||||
counter->references--;
|
||||
if (counter->references == 0)
|
||||
want_destroy = ISC_TRUE;
|
||||
UNLOCK(&counter->lock);
|
||||
|
||||
if (want_destroy)
|
||||
destroy(counter);
|
||||
}
|
@ -13,8 +13,6 @@
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id$
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
@ -28,7 +26,7 @@ top_srcdir = @top_srcdir@
|
||||
#
|
||||
HEADERS = aes.h app.h assertions.h backtrace.h base32.h base64.h \
|
||||
bind9.h boolean.h buffer.h bufferlist.h \
|
||||
commandline.h crc64.h entropy.h error.h event.h \
|
||||
commandline.h counter.h crc64.h entropy.h error.h event.h \
|
||||
eventclass.h file.h formatcheck.h fsaccess.h \
|
||||
hash.h heap.h hex.h hmacmd5.h hmacsha.h httpd.h \
|
||||
interfaceiter.h @ISC_IPV6_H@ iterated_hash.h json.h \
|
||||
|
130
lib/isc/include/isc/counter.h
Normal file
130
lib/isc/include/isc/counter.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ISC_COUNTER_H
|
||||
#define ISC_COUNTER_H 1
|
||||
|
||||
/*****
|
||||
***** Module Info
|
||||
*****/
|
||||
|
||||
/*! \file isc/quota.h
|
||||
*
|
||||
* \brief The isc_quota_t object is a simple helper object for implementing
|
||||
* quotas on things like the number of simultaneous connections to
|
||||
* a server. It keeps track of the amount of quota in use, and
|
||||
* encapsulates the locking necessary to allow multiple tasks to
|
||||
* share a quota.
|
||||
*/
|
||||
|
||||
/***
|
||||
*** Imports.
|
||||
***/
|
||||
|
||||
#include <isc/lang.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
/*****
|
||||
***** Types.
|
||||
*****/
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
void
|
||||
isc_quota_soft(isc_quota_t *quota, int soft);
|
||||
/*%<
|
||||
* Set a soft quota.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_quota_max(isc_quota_t *quota, int max);
|
||||
/*%<
|
||||
* Re-set a maximum quota.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_quota_reserve(isc_quota_t *quota);
|
||||
/*%<
|
||||
* Attempt to reserve one unit of 'quota'.
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_SUCCESS Success
|
||||
* \li #ISC_R_SOFTQUOTA Success soft quota reached
|
||||
* \li #ISC_R_QUOTA Quota is full
|
||||
*/
|
||||
|
||||
void
|
||||
isc_quota_release(isc_quota_t *quota);
|
||||
|
||||
isc_result_t
|
||||
isc_quota_attach(isc_quota_t *quota, isc_quota_t **p);
|
||||
/*%<
|
||||
* Like isc_quota_reserve, and also attaches '*p' to the
|
||||
* quota if successful (ISC_R_SUCCESS or ISC_R_SOFTQUOTA).
|
||||
*/
|
||||
|
||||
void
|
||||
isc_quota_detach(isc_quota_t **p);
|
||||
/*%<
|
||||
* Like isc_quota_release, and also detaches '*p' from the
|
||||
* quota.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp);
|
||||
/*%<
|
||||
* Allocate and initialize a counter object.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_counter_increment(isc_counter_t *counter);
|
||||
/*%<
|
||||
* Increment the counter.
|
||||
*
|
||||
* If the counter limit is nonzero and has been reached, then
|
||||
* return ISC_R_QUOTA, otherwise ISC_R_SUCCESS. (The counter is
|
||||
* incremented regardless of return value.)
|
||||
*/
|
||||
|
||||
unsigned int
|
||||
isc_counter_used(isc_counter_t *counter);
|
||||
/*%<
|
||||
* Return the current counter value.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_counter_setlimit(isc_counter_t *counter, int limit);
|
||||
/*%<
|
||||
* Set the counter limit.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp);
|
||||
/*%<
|
||||
* Attach to a counter object, increasing its reference counter.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_counter_detach(isc_counter_t **counterp);
|
||||
/*%<
|
||||
* Detach (and destroy if reference counter has dropped to zero)
|
||||
* a counter object.
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* ISC_COUNTER_H */
|
@ -48,6 +48,7 @@ typedef struct isc_buffer isc_buffer_t; /*%< Buffer */
|
||||
typedef ISC_LIST(isc_buffer_t) isc_bufferlist_t; /*%< Buffer List */
|
||||
typedef struct isc_constregion isc_constregion_t; /*%< Const region */
|
||||
typedef struct isc_consttextregion isc_consttextregion_t; /*%< Const Text Region */
|
||||
typedef struct isc_counter isc_counter_t; /*%< Counter */
|
||||
typedef isc_int16_t isc_dscp_t; /*%< Diffserv code point */
|
||||
typedef struct isc_entropy isc_entropy_t; /*%< Entropy */
|
||||
typedef struct isc_entropysource isc_entropysource_t; /*%< Entropy Source */
|
||||
|
@ -40,7 +40,7 @@ SRCS = isctest.c taskpool_test.c socket_test.c hash_test.c \
|
||||
sockaddr_test.c symtab_test.c task_test.c queue_test.c \
|
||||
parse_test.c pool_test.c print_test.c regex_test.c \
|
||||
socket_test.c safe_test.c time_test.c aes_test.c \
|
||||
file_test.c buffer_test.c
|
||||
file_test.c buffer_test.c counter_test.c
|
||||
|
||||
SUBDIRS =
|
||||
TARGETS = taskpool_test@EXEEXT@ socket_test@EXEEXT@ hash_test@EXEEXT@ \
|
||||
@ -49,7 +49,7 @@ TARGETS = taskpool_test@EXEEXT@ socket_test@EXEEXT@ hash_test@EXEEXT@ \
|
||||
queue_test@EXEEXT@ parse_test@EXEEXT@ pool_test@EXEEXT@ \
|
||||
print_test@EXEEXT@ regex_test@EXEEXT@ socket_test@EXEEXT@ \
|
||||
safe_test@EXEEXT@ time_test@EXEEXT@ aes_test@EXEEXT@ \
|
||||
file_test@EXEEXT@ buffer_test@EXEEXT@
|
||||
file_test@EXEEXT@ buffer_test@EXEEXT@ counter_test@EXEEXT@
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
@ -129,6 +129,10 @@ buffer_test@EXEEXT@: buffer_test.@O@ ${ISCDEPLIBS}
|
||||
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
|
||||
buffer_test.@O@ isctest.@O@ ${ISCLIBS} ${LIBS}
|
||||
|
||||
counter_test@EXEEXT@: counter_test.@O@ ${ISCDEPLIBS}
|
||||
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
|
||||
counter_test.@O@ isctest.@O@ ${ISCLIBS} ${LIBS}
|
||||
|
||||
unit::
|
||||
sh ${top_srcdir}/unit/unittest.sh
|
||||
|
||||
|
69
lib/isc/tests/counter_test.c
Normal file
69
lib/isc/tests/counter_test.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
#include <isc/counter.h>
|
||||
#include <isc/result.h>
|
||||
|
||||
#include "isctest.h"
|
||||
|
||||
ATF_TC(isc_counter);
|
||||
ATF_TC_HEAD(isc_counter, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "isc counter object");
|
||||
}
|
||||
ATF_TC_BODY(isc_counter, tc) {
|
||||
isc_result_t result;
|
||||
isc_counter_t *counter = NULL;
|
||||
int i;
|
||||
|
||||
result = isc_test_begin(NULL, ISC_TRUE);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_counter_create(mctx, 0, &counter);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
result = isc_counter_increment(counter);
|
||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
ATF_CHECK_EQ(isc_counter_used(counter), 10);
|
||||
|
||||
isc_counter_setlimit(counter, 15);
|
||||
for (i = 0; i < 10; i++) {
|
||||
result = isc_counter_increment(counter);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
break;
|
||||
}
|
||||
|
||||
ATF_CHECK_EQ(isc_counter_used(counter), 15);
|
||||
|
||||
isc_counter_detach(&counter);
|
||||
isc_test_end();
|
||||
}
|
||||
|
||||
/*
|
||||
* Main
|
||||
*/
|
||||
ATF_TP_ADD_TCS(tp) {
|
||||
ATF_TP_ADD_TC(tp, isc_counter);
|
||||
return (atf_no_error());
|
||||
}
|
||||
|
@ -170,6 +170,12 @@ isc_condition_init
|
||||
isc_condition_signal
|
||||
isc_condition_wait
|
||||
isc_condition_waituntil
|
||||
isc_counter_attach
|
||||
isc_counter_create
|
||||
isc_counter_detach
|
||||
isc_counter_increment
|
||||
isc_counter_setlimit
|
||||
isc_counter_used
|
||||
isc_crc64_final
|
||||
isc_crc64_init
|
||||
isc_crc64_update
|
||||
|
@ -265,6 +265,10 @@ SOURCE=..\include\isc\commandline.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\include\isc\counter.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\isc\condition.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -693,6 +697,10 @@ SOURCE=..\commandline.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\counter.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\crc64.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -127,6 +127,7 @@ CLEAN :
|
||||
-@erase "$(INTDIR)\buffer.obj"
|
||||
-@erase "$(INTDIR)\bufferlist.obj"
|
||||
-@erase "$(INTDIR)\commandline.obj"
|
||||
-@erase "$(INTDIR)\counter.obj"
|
||||
-@erase "$(INTDIR)\condition.obj"
|
||||
-@erase "$(INTDIR)\crc64.obj"
|
||||
-@erase "$(INTDIR)\dir.obj"
|
||||
@ -269,6 +270,7 @@ LINK32_OBJS= \
|
||||
"$(INTDIR)\buffer.obj" \
|
||||
"$(INTDIR)\bufferlist.obj" \
|
||||
"$(INTDIR)\commandline.obj" \
|
||||
"$(INTDIR)\counter.obj" \
|
||||
"$(INTDIR)\crc64.obj" \
|
||||
"$(INTDIR)\error.obj" \
|
||||
"$(INTDIR)\event.obj" \
|
||||
@ -363,6 +365,8 @@ CLEAN :
|
||||
-@erase "$(INTDIR)\bufferlist.sbr"
|
||||
-@erase "$(INTDIR)\commandline.obj"
|
||||
-@erase "$(INTDIR)\commandline.sbr"
|
||||
-@erase "$(INTDIR)\counter.obj"
|
||||
-@erase "$(INTDIR)\counter.sbr"
|
||||
-@erase "$(INTDIR)\condition.obj"
|
||||
-@erase "$(INTDIR)\condition.sbr"
|
||||
-@erase "$(INTDIR)\crc64.obj"
|
||||
@ -576,6 +580,7 @@ BSC32_SBRS= \
|
||||
"$(INTDIR)\buffer.sbr" \
|
||||
"$(INTDIR)\bufferlist.sbr" \
|
||||
"$(INTDIR)\commandline.sbr" \
|
||||
"$(INTDIR)\counter.sbr" \
|
||||
"$(INTDIR)\crc64.sbr" \
|
||||
"$(INTDIR)\error.sbr" \
|
||||
"$(INTDIR)\event.sbr" \
|
||||
@ -679,6 +684,7 @@ LINK32_OBJS= \
|
||||
"$(INTDIR)\buffer.obj" \
|
||||
"$(INTDIR)\bufferlist.obj" \
|
||||
"$(INTDIR)\commandline.obj" \
|
||||
"$(INTDIR)\counter.obj" \
|
||||
"$(INTDIR)\crc64.obj" \
|
||||
"$(INTDIR)\error.obj" \
|
||||
"$(INTDIR)\event.obj" \
|
||||
@ -1377,6 +1383,24 @@ SOURCE=..\commandline.c
|
||||
$(CPP) $(CPP_PROJ) $(SOURCE)
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
SOURCE=..\counter.c
|
||||
|
||||
!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
|
||||
|
||||
|
||||
"$(INTDIR)\counter.obj" : $(SOURCE) "$(INTDIR)"
|
||||
$(CPP) $(CPP_PROJ) $(SOURCE)
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
|
||||
|
||||
|
||||
"$(INTDIR)\counter.obj" "$(INTDIR)\counter.sbr" : $(SOURCE) "$(INTDIR)"
|
||||
$(CPP) $(CPP_PROJ) $(SOURCE)
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
SOURCE=..\crc64.c
|
||||
|
@ -61,6 +61,9 @@
|
||||
<ClInclude Include="..\include\isc\commandline.h">
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\isc\counter.h">
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\isc\crc64.h">
|
||||
<Filter>Library Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -492,6 +495,9 @@
|
||||
<ClCompile Include="..\commandline.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\counter.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\crc64.c">
|
||||
<Filter>Library Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -276,6 +276,7 @@ copy /Y @VCREDIST_PATH@ ..\Build\Release\
|
||||
<ClInclude Include="..\include\isc\buffer.h" />
|
||||
<ClInclude Include="..\include\isc\bufferlist.h" />
|
||||
<ClInclude Include="..\include\isc\commandline.h" />
|
||||
<ClInclude Include="..\include\isc\counter.h" />
|
||||
<ClInclude Include="..\include\isc\crc64.h" />
|
||||
<ClInclude Include="..\include\isc\entropy.h" />
|
||||
<ClInclude Include="..\include\isc\error.h" />
|
||||
@ -400,6 +401,7 @@ copy /Y @VCREDIST_PATH@ ..\Build\Release\
|
||||
<ClCompile Include="..\buffer.c" />
|
||||
<ClCompile Include="..\bufferlist.c" />
|
||||
<ClCompile Include="..\commandline.c" />
|
||||
<ClCompile Include="..\counter.c" />
|
||||
<ClCompile Include="..\crc64.c" />
|
||||
<ClCompile Include="..\error.c" />
|
||||
<ClCompile Include="..\event.c" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user