mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 14:07:59 +00:00
3593. [func] Update EDNS processing to better track remote server
capabilities. [RT #30655]
This commit is contained in:
3
CHANGES
3
CHANGES
@@ -1,3 +1,6 @@
|
||||
3593. [func] Update EDNS processing to better track remote server
|
||||
capabilities. [RT #30655]
|
||||
|
||||
3592. [doc] Moved documentation of rndc command options to the
|
||||
rndc man page. [RT #33506]
|
||||
|
||||
|
31
EDNS-9.10
Normal file
31
EDNS-9.10
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
EDNS in BIND 9.10
|
||||
|
||||
The EDNS code in BIND 9.10 records successful plain and EDNS query
|
||||
counts as well at timeouts for plain DNS and EDNS queries at various
|
||||
EDNS buffer sizes: 4096, 1432, 1232 and 512 for each server named
|
||||
talks to. A EDNS timeout for a lower buffer size is also counted
|
||||
against higher buffer sizes. These are held in 8 bit counters and
|
||||
are shifted on overflow of any counter. This will result in false
|
||||
positives due to transitory network problems to be removed from the
|
||||
history.
|
||||
|
||||
The buffer sizes of 1432 and 1232 are choosen to allow for a IPv4/IPv6
|
||||
encapsulated UDP message to be sent without fragmentation at Ethernet
|
||||
and IPv6 network mimimum MTU sizes.
|
||||
|
||||
Named also records the largest successful EDNS response size seen.
|
||||
|
||||
When talking to a new server named will send a EDNS query advertising
|
||||
a 512 byte UDP buffer. This is the most conservative EDNS message
|
||||
that can be sent. If this results in a response with TC=1 being
|
||||
sent a larger EDNS buffer size will be used rather than a immediate
|
||||
fallback to TCP.
|
||||
|
||||
If there are too many timeouts to EDNS queries without a successful EDNS
|
||||
query and with successful plain DNS queries named will fallback to using
|
||||
plain DNS when taking to a server. Named will periodically send a EDNS
|
||||
query to see if the server now supports EDNS.
|
||||
|
||||
When talking to a server using EDNS named will choose a EDNS buffer size
|
||||
based on the history of EDNS timeouts at various advertised sizes.
|
@@ -419,7 +419,7 @@ parse_command_line(int argc, char *argv[]) {
|
||||
|
||||
isc_commandline_errprint = ISC_FALSE;
|
||||
while ((ch = isc_commandline_parse(argc, argv,
|
||||
"46c:C:d:E:fFgi:lm:n:N:p:P:"
|
||||
"46c:C:d:D:E:fFgi:lm:n:N:p:P:"
|
||||
"sS:t:T:U:u:vVx:")) != -1) {
|
||||
switch (ch) {
|
||||
case '4':
|
||||
@@ -455,6 +455,9 @@ parse_command_line(int argc, char *argv[]) {
|
||||
ns_g_debuglevel = parse_int(isc_commandline_argument,
|
||||
"debug level");
|
||||
break;
|
||||
case 'D':
|
||||
/* Descriptive comment for 'ps'. */
|
||||
break;
|
||||
case 'E':
|
||||
ns_g_engine = isc_commandline_argument;
|
||||
break;
|
||||
|
@@ -62,6 +62,7 @@
|
||||
<arg><option>-6</option></arg>
|
||||
<arg><option>-c <replaceable class="parameter">config-file</replaceable></option></arg>
|
||||
<arg><option>-d <replaceable class="parameter">debug-level</replaceable></option></arg>
|
||||
<arg><option>-D <replaceable class="parameter">string</replaceable></option></arg>
|
||||
<arg><option>-E <replaceable class="parameter">engine-name</replaceable></option></arg>
|
||||
<arg><option>-f</option></arg>
|
||||
<arg><option>-g</option></arg>
|
||||
@@ -149,6 +150,18 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-D <replaceable class="parameter">string</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Specifies a string that is used to identify a instance of
|
||||
<command>named</command> in a process listing. The contents
|
||||
of <replaceable class="parameter">string</replaceable> are
|
||||
not examined.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-E <replaceable class="parameter">engine-name</replaceable></term>
|
||||
<listitem>
|
||||
|
15
bin/tests/bigtest/README
Normal file
15
bin/tests/bigtest/README
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
bash buildzones.sh < zones # creates setup, run, servers/* master/*
|
||||
# named.conf
|
||||
sudo sh setup # configure interfaces
|
||||
sh run # setup
|
||||
|
||||
../named/named [-g] -c named.conf
|
||||
|
||||
sh tests.sh < zones
|
||||
|
||||
sudo sh teardown # teardown interfaces
|
||||
|
||||
The test server can controlled with
|
||||
|
||||
rndc -k rndc.key -s 127.127.0.0 -p 5300
|
257
bin/tests/bigtest/buildzones.sh
Normal file
257
bin/tests/bigtest/buildzones.sh
Normal file
@@ -0,0 +1,257 @@
|
||||
#!/bin/bash
|
||||
|
||||
TOP=$( (cd ../../.. && pwd) )
|
||||
|
||||
addr=127.127.0.0
|
||||
ttl=300
|
||||
named=${TOP}/bin/named/named
|
||||
keygen=${TOP}/bin/dnssec/dnssec-keygen
|
||||
dsfromkey=${TOP}/bin/dnssec/dnssec-dsfromkey
|
||||
|
||||
nextaddr() {
|
||||
OLDIF="$IFS"
|
||||
IFS="${IFS}."
|
||||
set $1
|
||||
IFS="$OLDIFS"
|
||||
_a=$1 _b=$2 _c=$3 _d=$4
|
||||
_d=$(($_d + 1))
|
||||
case $_d in
|
||||
256) _c=$(($_c + 1)); _d=0;;
|
||||
esac
|
||||
case $_c in
|
||||
256) _b=$(($_b + 1)); _c=0;;
|
||||
esac
|
||||
echo $_a.$_b.$_c.$_d
|
||||
}
|
||||
|
||||
parent() {
|
||||
OLDIF="$IFS"
|
||||
IFS="${IFS}."
|
||||
set $1
|
||||
IFS="$OLDIFS"
|
||||
shift
|
||||
while [ $# -ne 0 ]
|
||||
do
|
||||
printf %s ${1}
|
||||
shift
|
||||
printf %s ${1:+.}
|
||||
|
||||
done
|
||||
}
|
||||
|
||||
blackhole() {
|
||||
echo 'options {'
|
||||
echo ' port 5300;'
|
||||
echo " listen-on { $1; };"
|
||||
echo " query-source $1;"
|
||||
echo " notify-source $1;"
|
||||
echo " transfer-source $1;"
|
||||
echo ' key-directory "keys";'
|
||||
echo " recursion ${2:-no};"
|
||||
echo ' pid-file "pids/'"${addr}"'.pid";'
|
||||
echo ' blackhole { 127.127.0.0; };'
|
||||
echo '};'
|
||||
}
|
||||
|
||||
refuse() {
|
||||
echo 'options {'
|
||||
echo ' port 5300;'
|
||||
echo " listen-on { $1; };"
|
||||
echo " query-source $1;"
|
||||
echo " notify-source $1;"
|
||||
echo " transfer-source $1;"
|
||||
echo ' key-directory "keys";'
|
||||
echo " recursion ${2:-no};"
|
||||
echo ' pid-file "pids/'"${addr}"'.pid";'
|
||||
echo ' allow-query { !127.127.0.0; any; };'
|
||||
echo '};'
|
||||
}
|
||||
|
||||
options() {
|
||||
echo 'options {'
|
||||
echo ' port 5300;'
|
||||
echo " listen-on { $1; };"
|
||||
echo " query-source $1;"
|
||||
echo " notify-source $1;"
|
||||
echo " transfer-source $1;"
|
||||
echo ' key-directory "keys";'
|
||||
echo " recursion ${2:-no};"
|
||||
echo ' pid-file "pids/'"${addr}"'.pid";'
|
||||
echo '};'
|
||||
}
|
||||
|
||||
controls() {
|
||||
echo 'include "rndc.key";'
|
||||
echo "controls { inet $addr port 9953 allow { any; } keys { "rndc-key"; }; };"
|
||||
}
|
||||
|
||||
delay() {
|
||||
_s=$1
|
||||
OLDIF="$IFS"
|
||||
IFS="${IFS}/"
|
||||
set ${2:-.}
|
||||
IFS="$OLDIFS"
|
||||
|
||||
case $1 in
|
||||
.) _d=;;
|
||||
*) _d=$1;;
|
||||
esac
|
||||
case $_s in
|
||||
1) echo -T delay=${_d:-100};;
|
||||
2) echo -T delay=${2:-50};;
|
||||
3) echo -T delay=${3:-150};;
|
||||
4) echo -T delay=${4:-250};;
|
||||
5) echo -T delay=${5:-125};;
|
||||
6) echo -T delay=${6:-25};;
|
||||
7) echo -T delay=${7:-75};;
|
||||
8) echo -T delay=${8:-125};;
|
||||
9) echo -T delay=${9:-10};;
|
||||
10) echo -T delay=${10:-40};;
|
||||
11) echo -T delay=${11:-80};;
|
||||
12) echo -T delay=${12:-90};;
|
||||
*) echo -T delay=50;;
|
||||
esac
|
||||
}
|
||||
|
||||
trusted-keys () {
|
||||
awk '$3 == "DNSKEY" {
|
||||
b = ""; for (i=7; i <= NF; i++) { b = b $i; };
|
||||
print "trusted-keys { \""$1"\"",$4,$5,$6,"\""b"\"; };" };'
|
||||
}
|
||||
|
||||
signed-zone () {
|
||||
echo "zone "'"'"${1:-.}"'"'" {"
|
||||
echo " type master;"
|
||||
echo " file "'"'"master/${2}.db"'"'";"
|
||||
echo " auto-dnssec maintain;"
|
||||
echo " allow-update { any; };"
|
||||
echo "};"
|
||||
}
|
||||
|
||||
unsigned-zone () {
|
||||
echo "zone "'"'"${1:-.}"'"'" {"
|
||||
echo " type master;"
|
||||
echo " file "'"'"master/${2}.db"'"'";"
|
||||
echo "};"
|
||||
}
|
||||
|
||||
slave-zone () {
|
||||
echo "zone "'"'"${zone:-.}"'"'" {"
|
||||
echo " type slave;"
|
||||
echo " masters { ${master}; };"
|
||||
echo "};"
|
||||
}
|
||||
|
||||
rm -rf servers master keys setup teardown run
|
||||
mkdir -p servers
|
||||
mkdir -p master
|
||||
mkdir -p keys
|
||||
|
||||
echo "ifconfig lo0 $addr netmask 0xffffffff alias" >> setup
|
||||
echo "ifconfig lo0 $addr -alias" >> teardown
|
||||
controls $addr > named.conf
|
||||
options $addr yes >> named.conf
|
||||
echo 'zone "." { type hint; file "master/hint.db"; };' >> named.conf
|
||||
|
||||
while read zone servers nsfmt signed delay blackhole refuse flags
|
||||
do
|
||||
i=1
|
||||
case "${zone}" in
|
||||
.) file=root zone=;;
|
||||
*) file="$zone";;
|
||||
esac
|
||||
if [ "${zone}" != "" ] ; then
|
||||
p=$(parent $zone)
|
||||
case "${p}" in
|
||||
"") p=root;;
|
||||
esac
|
||||
else
|
||||
p=hint
|
||||
fi
|
||||
#echo "zone='${zone}' parent='${p}'"
|
||||
addr=$(nextaddr $addr)
|
||||
ns=$(printf "$nsfmt" ${i} "${zone}")
|
||||
d=$(delay $i ${delay:-.})
|
||||
|
||||
echo "${zone}. ${ttl} soa ${ns}. hostmaster.${zone}${zone:+.} 1 3600 1200 604800 1200" >> master/${file}.db
|
||||
echo "${zone}. ${ttl} ns ${ns}." >> master/${file}.db
|
||||
echo "${ns}. ${ttl} a ${addr}" >> master/${file}.db
|
||||
echo "${zone}. ${ttl} ns ${ns}." >> master/${p}.db
|
||||
echo "${ns}. ${ttl} a ${addr}" >> master/${p}.db
|
||||
if [ $signed = "S" ]; then
|
||||
kskkey=`${keygen} -K keys -f KSK ${zone:-.}`
|
||||
zskkey=`${keygen} -K keys ${zone:-.}`
|
||||
if [ "${zone}" != "" ] ; then
|
||||
${dsfromkey} -T ${ttl} keys/${kskkey}.key >> master/${p}.db
|
||||
else
|
||||
trusted-keys < keys/${kskkey}.key >> named.conf
|
||||
fi
|
||||
fi
|
||||
echo "ifconfig lo0 $addr netmask 0xffffffff alias" >> setup
|
||||
echo "ifconfig lo0 $addr -alias" >> teardown
|
||||
echo "${named} -D bigtest -c servers/${addr}.conf $d $flags" >> run
|
||||
options ${addr} > servers/${addr}.conf
|
||||
case ${signed} in
|
||||
S) signed-zone ${zone:-.} ${file} >> servers/${addr}.conf;;
|
||||
P) unsigned-zone ${zone:-.} ${file} >> servers/${addr}.conf;;
|
||||
*) echo ${signed}; exit 1;;
|
||||
esac
|
||||
|
||||
# slave servers
|
||||
while [ $i -lt $servers ]
|
||||
do
|
||||
master=$addr
|
||||
i=$(($i + 1))
|
||||
ns=$(printf "$nsfmt" ${i} "${zone}")
|
||||
d=$(delay $i ${delay:-.})
|
||||
addr=$(nextaddr $addr)
|
||||
echo "${zone}. ${ttl} ns ${ns}." >> master/${file}.db
|
||||
echo "${ns}. ${ttl} a ${addr}" >> master/${file}.db
|
||||
echo "${zone}. ${ttl} ns ${ns}." >> master/${p}.db
|
||||
echo "${ns}. ${ttl} a ${addr}" >> master/${p}.db
|
||||
echo "ifconfig lo0 $addr netmask 0xffffffff alias" >> setup
|
||||
echo "ifconfig lo0 $addr -alias" >> teardown
|
||||
echo "${named} -D bigtest -c servers/${addr}.conf $d $flags" >> run
|
||||
if [ $i = ${refuse:-.} ]
|
||||
then
|
||||
refuse $addr > servers/${addr}.conf
|
||||
elif [ $i = ${blackhole:-.} ]
|
||||
then
|
||||
blackhole $addr > servers/${addr}.conf
|
||||
else
|
||||
options $addr > servers/${addr}.conf
|
||||
fi
|
||||
slave-zone ${zone:-.} ${master} >> servers/${addr}.conf
|
||||
done
|
||||
if [ "${zone}" != "" ] ; then
|
||||
echo "www.${zone}. ${ttl} a 127.0.0.1" >> master/${file}.db
|
||||
echo "www.${zone}. ${ttl} aaaa ::1" >> master/${file}.db
|
||||
echo "${zone}. ${ttl} mx 10 mail.${zone}." >> master/${file}.db
|
||||
echo "mail.${zone}. ${ttl} a 127.0.0.1" >> master/${file}.db
|
||||
echo "mail.${zone}. ${ttl} aaaa ::1" >> master/${file}.db
|
||||
echo "*.big.${zone}. ${ttl} txt (" >> master/${file}.db
|
||||
i=0
|
||||
while [ $i -lt 150 ]
|
||||
do
|
||||
echo "1234567890" >> master/${file}.db
|
||||
i=$(($i + 1))
|
||||
done
|
||||
echo ")" >> master/${file}.db
|
||||
echo "*.medium.${zone}. ${ttl} txt (" >> master/${file}.db
|
||||
i=0
|
||||
while [ $i -lt 120 ]
|
||||
do
|
||||
echo "1234567890" >> master/${file}.db
|
||||
i=$(($i + 1))
|
||||
done
|
||||
echo ")" >> master/${file}.db
|
||||
echo "*.medium.${zone}. ${ttl} txt (" >> master/${file}.db
|
||||
i=0
|
||||
while [ $i -lt 120 ]
|
||||
do
|
||||
echo "1234567890" >> master/${file}.db
|
||||
i=$(($i + 1))
|
||||
done
|
||||
echo ")" >> master/${file}.db
|
||||
fi
|
||||
done
|
5
bin/tests/bigtest/rndc.key
Normal file
5
bin/tests/bigtest/rndc.key
Normal file
@@ -0,0 +1,5 @@
|
||||
key "rndc-key" {
|
||||
algorithm hmac-md5;
|
||||
secret "xxxxxxxxxxxxxxxxxxxxHg==";
|
||||
};
|
||||
|
67
bin/tests/bigtest/tests.sh
Normal file
67
bin/tests/bigtest/tests.sh
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
|
||||
TOP=$( (cd ../../.. && pwd) )
|
||||
dig=${TOP}/bin/dig/dig
|
||||
|
||||
cmd="${dig} -p 5300 @127.127.0.0 txt"
|
||||
inner() {
|
||||
zone=$1 i=$2 to=$3
|
||||
x=$i
|
||||
dout=dig$x.out
|
||||
tout=time$x.out
|
||||
while [ $i -lt $to ]
|
||||
do
|
||||
case $zone in
|
||||
.) zone=;;
|
||||
esac
|
||||
|
||||
(time -p $cmd $i.${sub}$zone > $dout ) 2> $tout
|
||||
s=`sed -n '/real/s/[^0-9]*\([0-9]*\)\..*/\1/p' $tout`
|
||||
case $s in
|
||||
0);;
|
||||
1) t1=`expr ${t1:-0} + 1`;;
|
||||
2) t2=`expr ${t2:-0} + 1`;;
|
||||
3) t3=`expr ${t3:-0} + 1`;;
|
||||
*) echo $i `grep real $tout`;;
|
||||
esac
|
||||
|
||||
grep "status: \(NXDOMAIN\|NOERROR\)" $dout > /dev/null || {
|
||||
echo $cmd $i.${sub}$zone
|
||||
cat $dout
|
||||
}
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
if test ${t1:-0} -ne 0 -o ${t2:-0} -ne 0 -o ${t3:-0} -ne 0
|
||||
then
|
||||
echo "$x timeouts: t1=${t1:-0} t2=${t2:-0} t3=${t3:-0}"
|
||||
fi
|
||||
}
|
||||
|
||||
while read zone rest
|
||||
do
|
||||
for sub in "" medium. big.
|
||||
do
|
||||
case $zone in
|
||||
.) echo doing ${sub:-.};;
|
||||
*) echo doing $sub$zone;;
|
||||
esac
|
||||
( inner $zone 1 100) &
|
||||
( inner $zone 101 200) &
|
||||
( inner $zone 201 300) &
|
||||
( inner $zone 301 400) &
|
||||
( inner $zone 401 500) &
|
||||
( inner $zone 501 600) &
|
||||
( inner $zone 601 700) &
|
||||
( inner $zone 701 800) &
|
||||
( inner $zone 801 900) &
|
||||
( inner $zone 901 1000) &
|
||||
( inner $zone 1001 1100) &
|
||||
( inner $zone 1101 1200) &
|
||||
( inner $zone 1201 1300) &
|
||||
( inner $zone 1301 1400) &
|
||||
( inner $zone 1401 1500) &
|
||||
( inner $zone 1501 1600) &
|
||||
( inner $zone 1601 1700) &
|
||||
wait
|
||||
done
|
||||
done
|
18
bin/tests/bigtest/zones
Normal file
18
bin/tests/bigtest/zones
Normal file
@@ -0,0 +1,18 @@
|
||||
noedns-1.tld 1 ns%u.%s P . x x -T noedns
|
||||
dropedns-1.tld 1 ns%u.%s P . x x -T dropedns
|
||||
maxudp512-1.tld 1 ns%u.%s S . x x -T maxudp=512
|
||||
maxudp1460-1.tld 1 ns%u.%s S . x x -T maxudp=1460
|
||||
plain-1.tld 1 ns%u.%s S . x x
|
||||
noedns-3.tld 3 ns%u.%s P . 2 x -T noedns
|
||||
dropedns-3.tld 3 ns%u.%s P . 2 x -T dropedns
|
||||
maxudp512-3.tld 3 ns%u.%s S . x x -T maxudp=512
|
||||
maxudp1460-3.tld 3 ns%u.%s S . x x -T maxudp=1460
|
||||
plain-3.tld 3 ns%u.%s S . x 3
|
||||
noedns-5.tld 5 ns%u.%s P . 3 x -T noedns
|
||||
dropedns-5.tld 5 ns%u.%s P . x x -T dropedns
|
||||
maxudp512-5.tld 5 ns%u.%s S . x x -T maxudp=512
|
||||
maxudp1460-5.tld 5 ns%u.%s S . x x -T maxudp=1460
|
||||
400ms-1.tld 5 ns%u.%s S 400/400/400/400/400 2 x
|
||||
plain-5.tld 5 ns%u.%s S . x x
|
||||
tld 12 ns%u.%s S . 5 8
|
||||
. 12 ns%u.root-servers.nil%s S . x x
|
@@ -94,8 +94,8 @@ echo "I:reset and check that records are correctly cached initially"
|
||||
ret=0
|
||||
load_cache
|
||||
dump_cache
|
||||
nrecords=`grep flushtest.example ns2/named_dump.db | grep -v '^;' | wc -l`
|
||||
[ $nrecords -eq 20 ] || ret=1
|
||||
nrecords=`grep flushtest.example ns2/named_dump.db | grep -v '^;' | grep -w '\(TXT\|ANY\)'| wc -l`
|
||||
[ $nrecords -eq 17 ] || { ret=1; echo "I: found $nrecords records expected 17"; }
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
@@ -180,8 +180,8 @@ status=`expr $status + $ret`
|
||||
echo "I:check the number of cached records remaining"
|
||||
ret=0
|
||||
dump_cache
|
||||
nrecords=`grep flushtest.example ns2/named_dump.db | grep -v '^;' | wc -l`
|
||||
[ $nrecords -eq 19 ] || ret=1
|
||||
nrecords=`grep flushtest.example ns2/named_dump.db | grep -v '^;' | grep -w '\(TXT\|ANY\)' | wc -l`
|
||||
[ $nrecords -eq 17 ] || { ret=1; echo "I: found $nrecords records expected 17"; }
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
|
@@ -53,8 +53,8 @@ n=`expr $n + 1`
|
||||
# Entry should exist
|
||||
echo "I: check that 'check-names response warn;' works ($n)"
|
||||
ret=0
|
||||
$DIG $DIGOPTS yy_yy.ignore.example. @10.53.0.1 a > dig.out.ns1.test$n || ret=1
|
||||
$DIG $DIGOPTS yy_yy.ignore.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
|
||||
$DIG $DIGOPTS +noauth yy_yy.ignore.example. @10.53.0.1 a > dig.out.ns1.test$n || ret=1
|
||||
$DIG $DIGOPTS +noauth yy_yy.ignore.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
|
||||
$PERL ../digcomp.pl dig.out.ns1.test$n dig.out.ns2.test$n || ret=1
|
||||
grep "check-names warning yy_yy.ignore.example/A/IN" ns2/named.run > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
|
@@ -76,6 +76,11 @@ israw1 () {
|
||||
return $?
|
||||
}
|
||||
|
||||
# strip NS and RRSIG NS from input
|
||||
stripns () {
|
||||
awk '($4 == "NS") || ($4 == "RRSIG" && $5 == "NS") { next} { print }' $1
|
||||
}
|
||||
|
||||
# Check the example. domain
|
||||
|
||||
echo "I:checking that zone transfer worked ($n)"
|
||||
@@ -193,9 +198,13 @@ fi
|
||||
|
||||
echo "I:checking positive wildcard validation NSEC ($n)"
|
||||
ret=0
|
||||
$DIG $DIGOPTS a.wild.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
|
||||
$DIG $DIGOPTS a.wild.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
|
||||
$DIG $DIGOPTS a.wild.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
|
||||
$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
|
||||
stripns dig.out.ns3.test$n > dig.out.ns3.stripped.test$n
|
||||
stripns dig.out.ns4.test$n > dig.out.ns4.stripped.test$n
|
||||
$PERL ../digcomp.pl dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1
|
||||
grep "\*\.wild\.example\..*RRSIG NSEC" dig.out.ns4.test$n > /dev/null || ret=1
|
||||
grep "\*\.wild\.example\..*NSEC z\.example" dig.out.ns4.test$n > /dev/null || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
|
||||
grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
|
||||
n=`expr $n + 1`
|
||||
@@ -235,7 +244,9 @@ echo "I:checking positive wildcard validation NSEC3 ($n)"
|
||||
ret=0
|
||||
$DIG $DIGOPTS a.wild.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
|
||||
$DIG $DIGOPTS a.wild.nsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
|
||||
$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
|
||||
stripns dig.out.ns3.test$n > dig.out.ns3.stripped.test$n
|
||||
stripns dig.out.ns4.test$n > dig.out.ns4.stripped.test$n
|
||||
$PERL ../digcomp.pl dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
|
||||
grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
|
||||
n=`expr $n + 1`
|
||||
@@ -259,7 +270,9 @@ $DIG $DIGOPTS a.wild.optout.example. \
|
||||
@10.53.0.3 a > dig.out.ns3.test$n || ret=1
|
||||
$DIG $DIGOPTS a.wild.optout.example. \
|
||||
@10.53.0.4 a > dig.out.ns4.test$n || ret=1
|
||||
$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
|
||||
stripns dig.out.ns3.test$n > dig.out.ns3.stripped.test$n
|
||||
stripns dig.out.ns4.test$n > dig.out.ns4.stripped.test$n
|
||||
$PERL ../digcomp.pl dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
|
||||
grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
|
||||
n=`expr $n + 1`
|
||||
|
@@ -27,56 +27,56 @@ status=0
|
||||
|
||||
echo "I:checking that a forward zone overrides global forwarders"
|
||||
ret=0
|
||||
$DIG txt.example1. txt @$hidden -p 5300 > dig.out.hidden || ret=1
|
||||
$DIG txt.example1. txt @$f1 -p 5300 > dig.out.f1 || ret=1
|
||||
$DIG +noadd +noauth txt.example1. txt @$hidden -p 5300 > dig.out.hidden || ret=1
|
||||
$DIG +noadd +noauth txt.example1. txt @$f1 -p 5300 > dig.out.f1 || ret=1
|
||||
$PERL ../digcomp.pl dig.out.hidden dig.out.f1 || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking that a forward first zone no forwarders recurses"
|
||||
ret=0
|
||||
$DIG txt.example2. txt @$root -p 5300 > dig.out.root || ret=1
|
||||
$DIG txt.example2. txt @$f1 -p 5300 > dig.out.f1 || ret=1
|
||||
$DIG +noadd +noauth txt.example2. txt @$root -p 5300 > dig.out.root || ret=1
|
||||
$DIG +noadd +noauth txt.example2. txt @$f1 -p 5300 > dig.out.f1 || ret=1
|
||||
$PERL ../digcomp.pl dig.out.root dig.out.f1 || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking that a forward only zone no forwarders fails"
|
||||
ret=0
|
||||
$DIG txt.example2. txt @$root -p 5300 > dig.out.root || ret=1
|
||||
$DIG txt.example2. txt @$f1 -p 5300 > dig.out.f1 || ret=1
|
||||
$DIG +noadd +noauth txt.example2. txt @$root -p 5300 > dig.out.root || ret=1
|
||||
$DIG +noadd +noauth txt.example2. txt @$f1 -p 5300 > dig.out.f1 || ret=1
|
||||
$PERL ../digcomp.pl dig.out.root dig.out.f1 || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking that global forwarders work"
|
||||
ret=0
|
||||
$DIG txt.example4. txt @$hidden -p 5300 > dig.out.hidden || ret=1
|
||||
$DIG txt.example4. txt @$f1 -p 5300 > dig.out.f1 || ret=1
|
||||
$DIG +noadd +noauth txt.example4. txt @$hidden -p 5300 > dig.out.hidden || ret=1
|
||||
$DIG +noadd +noauth txt.example4. txt @$f1 -p 5300 > dig.out.f1 || ret=1
|
||||
$PERL ../digcomp.pl dig.out.hidden dig.out.f1 || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking that a forward zone works"
|
||||
ret=0
|
||||
$DIG txt.example1. txt @$hidden -p 5300 > dig.out.hidden || ret=1
|
||||
$DIG txt.example1. txt @$f2 -p 5300 > dig.out.f2 || ret=1
|
||||
$DIG +noadd +noauth txt.example1. txt @$hidden -p 5300 > dig.out.hidden || ret=1
|
||||
$DIG +noadd +noauth txt.example1. txt @$f2 -p 5300 > dig.out.f2 || ret=1
|
||||
$PERL ../digcomp.pl dig.out.hidden dig.out.f2 || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking that forwarding doesn't spontaneously happen"
|
||||
ret=0
|
||||
$DIG txt.example2. txt @$root -p 5300 > dig.out.root || ret=1
|
||||
$DIG txt.example2. txt @$f2 -p 5300 > dig.out.f2 || ret=1
|
||||
$DIG +noadd +noauth txt.example2. txt @$root -p 5300 > dig.out.root || ret=1
|
||||
$DIG +noadd +noauth txt.example2. txt @$f2 -p 5300 > dig.out.f2 || ret=1
|
||||
$PERL ../digcomp.pl dig.out.root dig.out.f2 || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking that a forward zone with no specified policy works"
|
||||
ret=0
|
||||
$DIG txt.example3. txt @$hidden -p 5300 > dig.out.hidden || ret=1
|
||||
$DIG txt.example3. txt @$f2 -p 5300 > dig.out.f2 || ret=1
|
||||
$DIG +noadd +noauth txt.example3. txt @$hidden -p 5300 > dig.out.hidden || ret=1
|
||||
$DIG +noadd +noauth txt.example3. txt @$f2 -p 5300 > dig.out.f2 || ret=1
|
||||
$PERL ../digcomp.pl dig.out.hidden dig.out.f2 || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
@@ -764,6 +764,7 @@ main(void) {
|
||||
test_getrrsetbyname("a.example1.", 1, 1, 1, 0, 1);
|
||||
test_getrrsetbyname("e.example1.", 1, 1, 1, 1, 1);
|
||||
test_getrrsetbyname("e.example1.", 1, 255, 1, 1, 0);
|
||||
test_getrrsetbyname("e.example1.", 1, 2, 1, 1, 1);
|
||||
test_getrrsetbyname("e.example1.", 1, 46, 2, 0, 1);
|
||||
test_getrrsetbyname("", 1, 1, 0, 0, 0);
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
# $Id: org.isc.bind.system,v 1.1 2010/08/25 04:51:51 marka Exp $
|
||||
|
||||
for ns in 1 2 3 4 5 6 7
|
||||
for ns in 1 2 3 4 5 6 7 8
|
||||
do
|
||||
/sbin/ifconfig lo0 10.53.0.$ns alias
|
||||
/sbin/ifconfig lo0 inet6 fd92:7065:b8e:ffff::$ns alias
|
||||
|
@@ -155,12 +155,21 @@ sub start_server {
|
||||
close FH;
|
||||
$command .= "$options";
|
||||
} else {
|
||||
$command .= "-D $server ";
|
||||
$command .= "-m record,size,mctx ";
|
||||
$command .= "-T clienttest ";
|
||||
$command .= "-T nosoa "
|
||||
if (-e "$testdir/$server/named.nosoa");
|
||||
$command .= "-T noaa "
|
||||
if (-e "$testdir/$server/named.noaa");
|
||||
$command .= "-T noedns "
|
||||
if (-e "$testdir/$server/named.noedns");
|
||||
$command .= "-T dropedns "
|
||||
if (-e "$testdir/$server/named.dropedns");
|
||||
$command .= "-T maxudp512 "
|
||||
if (-e "$testdir/$server/named.maxudp512");
|
||||
$command .= "-T maxudp1460 "
|
||||
if (-e "$testdir/$server/named.maxudp1460");
|
||||
$command .= "-c named.conf -d 99 -g -U 4 ";
|
||||
}
|
||||
if ($restart) {
|
||||
|
@@ -11,9 +11,6 @@
|
||||
;; ANSWER SECTION:
|
||||
data.example. 5M IN TXT "some" "test" "data"
|
||||
|
||||
;; AUTHORITY SECTION:
|
||||
example. 5M IN NS ns4.example.
|
||||
|
||||
;; Total query time: 8 msec
|
||||
;; FROM: draco to SERVER: 10.53.0.3
|
||||
;; WHEN: Wed Jun 21 10:58:54 2000
|
||||
|
@@ -80,7 +80,7 @@ status=`expr $status + $ret`
|
||||
n=`expr $n + 1`
|
||||
echo "I:look for static-stub zone data with recursion (should be found) ($n)"
|
||||
ret=0
|
||||
$DIG +tcp data.example. @10.53.0.2 txt -p 5300 > dig.out.ns2.test$n || ret=1
|
||||
$DIG +tcp +noauth data.example. @10.53.0.2 txt -p 5300 > dig.out.ns2.test$n || ret=1
|
||||
$PERL ../digcomp.pl knowngood.dig.out.rec dig.out.ns2.test$n || ret=1
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
@@ -11,12 +11,6 @@
|
||||
;; ANSWER SECTION:
|
||||
data.child.example. 5M IN TXT "some" "test" "data"
|
||||
|
||||
;; AUTHORITY SECTION:
|
||||
child.example. 5M IN NS ns2.child.example.
|
||||
|
||||
;; ADDITIONAL SECTION:
|
||||
ns2.child.example. 5M IN A 10.53.0.2
|
||||
|
||||
;; Total query time: 8 msec
|
||||
;; FROM: draco to SERVER: 10.53.0.3
|
||||
;; WHEN: Wed Jun 21 10:58:54 2000
|
||||
|
@@ -53,7 +53,7 @@ $PERL ../digcomp.pl knowngood.dig.out.norec dig.out.ns3 || ret=1
|
||||
|
||||
echo "I:look for stub zone data with recursion (should be found) (pass=$pass)"
|
||||
ret=0
|
||||
$DIG +tcp data.child.example. @10.53.0.3 txt -p 5300 > dig.out.ns3 || ret=1
|
||||
$DIG +tcp +noauth +noadd data.child.example. @10.53.0.3 txt -p 5300 > dig.out.ns3 || ret=1
|
||||
$PERL ../digcomp.pl knowngood.dig.out.rec dig.out.ns3 || ret=1
|
||||
[ $ret = 0 ] || { status=1; echo "I:failed"; }
|
||||
|
||||
|
287
lib/dns/adb.c
287
lib/dns/adb.c
@@ -242,6 +242,18 @@ struct dns_adbentry {
|
||||
|
||||
unsigned int flags;
|
||||
unsigned int srtt;
|
||||
isc_uint16_t udpsize;
|
||||
unsigned char plain;
|
||||
unsigned char plainto;
|
||||
unsigned char edns;
|
||||
unsigned char to4096; /* Our max. */
|
||||
/*
|
||||
* Allow for encapsulated IPv4/IPv6 UDP packet over ethernet.
|
||||
* Ethernet 1500 - IP(20) - IP6(40) - UDP(8) = 1432.
|
||||
*/
|
||||
unsigned char to1432; /* Ethernet */
|
||||
unsigned char to1232; /* IPv6 nofrag */
|
||||
unsigned char to512; /* plain DNS */
|
||||
isc_sockaddr_t sockaddr;
|
||||
|
||||
isc_stdtime_t expires;
|
||||
@@ -255,7 +267,6 @@ struct dns_adbentry {
|
||||
|
||||
ISC_LIST(dns_adblameinfo_t) lameinfo;
|
||||
ISC_LINK(dns_adbentry_t) plink;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -952,12 +963,14 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
|
||||
DP(NCACHE_LEVEL, "expire_v4 set to MIN(%u,%u) import_rdataset",
|
||||
adbname->expire_v4, now + rdataset->ttl);
|
||||
adbname->expire_v4 = ISC_MIN(adbname->expire_v4,
|
||||
now + rdataset->ttl);
|
||||
ISC_MIN(now + ADB_ENTRY_WINDOW,
|
||||
now + rdataset->ttl));
|
||||
} else {
|
||||
DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) import_rdataset",
|
||||
adbname->expire_v6, now + rdataset->ttl);
|
||||
adbname->expire_v6 = ISC_MIN(adbname->expire_v6,
|
||||
now + rdataset->ttl);
|
||||
ISC_MIN(now + ADB_ENTRY_WINDOW,
|
||||
now + rdataset->ttl));
|
||||
}
|
||||
|
||||
if (new_addresses_added) {
|
||||
@@ -1781,6 +1794,14 @@ new_adbentry(dns_adb_t *adb) {
|
||||
e->lock_bucket = DNS_ADB_INVALIDBUCKET;
|
||||
e->refcnt = 0;
|
||||
e->flags = 0;
|
||||
e->udpsize = 0;
|
||||
e->edns = 0;
|
||||
e->plain = 0;
|
||||
e->plainto = 0;
|
||||
e->to4096 = 0;
|
||||
e->to1432 = 0;
|
||||
e->to1232 = 0;
|
||||
e->to512 = 0;
|
||||
isc_random_get(&r);
|
||||
e->srtt = (r & 0x1f) + 1;
|
||||
e->expires = 0;
|
||||
@@ -2043,6 +2064,7 @@ find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp,
|
||||
entry_next = ISC_LIST_NEXT(entry, plink);
|
||||
(void)check_expire_entry(adb, &entry, now);
|
||||
if (entry != NULL &&
|
||||
(entry->expires == 0 || entry->expires > now) &&
|
||||
isc_sockaddr_equal(addr, &entry->sockaddr)) {
|
||||
ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
|
||||
ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
|
||||
@@ -2815,6 +2837,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
unsigned int wanted_addresses;
|
||||
unsigned int wanted_fetches;
|
||||
unsigned int query_pending;
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
|
||||
REQUIRE(DNS_ADB_VALID(adb));
|
||||
if (task != NULL) {
|
||||
@@ -2875,6 +2898,11 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
REQUIRE(task != NULL);
|
||||
}
|
||||
|
||||
if (isc_log_wouldlog(dns_lctx, DEF_LEVEL))
|
||||
dns_name_format(name, namebuf, sizeof(namebuf));
|
||||
else
|
||||
namebuf[0] = 0;
|
||||
|
||||
/*
|
||||
* Try to see if we know anything about this name at all.
|
||||
*/
|
||||
@@ -2932,8 +2960,8 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
* Yes, it is.
|
||||
*/
|
||||
DP(DEF_LEVEL,
|
||||
"dns_adb_createfind: name %p is an alias (cached)",
|
||||
adbname);
|
||||
"dns_adb_createfind: name %s (%p) is an alias (cached)",
|
||||
namebuf, adbname);
|
||||
alias = ISC_TRUE;
|
||||
goto post_copy;
|
||||
}
|
||||
@@ -2948,8 +2976,8 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
result = dbfind_name(adbname, now, dns_rdatatype_a);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
DP(DEF_LEVEL,
|
||||
"dns_adb_createfind: found A for name %p in db",
|
||||
adbname);
|
||||
"dns_adb_createfind: found A for name %s (%p) in db",
|
||||
namebuf, adbname);
|
||||
goto v6;
|
||||
}
|
||||
|
||||
@@ -2958,8 +2986,8 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
*/
|
||||
if (result == DNS_R_ALIAS) {
|
||||
DP(DEF_LEVEL,
|
||||
"dns_adb_createfind: name %p is an alias",
|
||||
adbname);
|
||||
"dns_adb_createfind: name %s (%p) is an alias",
|
||||
namebuf, adbname);
|
||||
alias = ISC_TRUE;
|
||||
goto post_copy;
|
||||
}
|
||||
@@ -2988,8 +3016,8 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
result = dbfind_name(adbname, now, dns_rdatatype_aaaa);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
DP(DEF_LEVEL,
|
||||
"dns_adb_createfind: found AAAA for name %p",
|
||||
adbname);
|
||||
"dns_adb_createfind: found AAAA for name %s (%p)",
|
||||
namebuf, adbname);
|
||||
goto fetch;
|
||||
}
|
||||
|
||||
@@ -2998,8 +3026,8 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
*/
|
||||
if (result == DNS_R_ALIAS) {
|
||||
DP(DEF_LEVEL,
|
||||
"dns_adb_createfind: name %p is an alias",
|
||||
adbname);
|
||||
"dns_adb_createfind: name %s (%p) is an alias",
|
||||
namebuf, adbname);
|
||||
alias = ISC_TRUE;
|
||||
goto post_copy;
|
||||
}
|
||||
@@ -3039,9 +3067,9 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
if (WANT_INET(wanted_fetches) &&
|
||||
fetch_name(adbname, start_at_zone,
|
||||
dns_rdatatype_a) == ISC_R_SUCCESS) {
|
||||
DP(DEF_LEVEL,
|
||||
"dns_adb_createfind: started A fetch for name %p",
|
||||
adbname);
|
||||
DP(DEF_LEVEL, "dns_adb_createfind: "
|
||||
"started A fetch for name %s (%p)",
|
||||
namebuf, adbname);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3050,10 +3078,9 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
|
||||
if (WANT_INET6(wanted_fetches) &&
|
||||
fetch_name(adbname, start_at_zone,
|
||||
dns_rdatatype_aaaa) == ISC_R_SUCCESS) {
|
||||
DP(DEF_LEVEL,
|
||||
"dns_adb_createfind: "
|
||||
"started AAAA fetch for name %p",
|
||||
adbname);
|
||||
DP(DEF_LEVEL, "dns_adb_createfind: "
|
||||
"started AAAA fetch for name %s (%p)",
|
||||
namebuf, adbname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3389,8 +3416,12 @@ dump_entry(FILE *f, dns_adbentry_t *entry, isc_boolean_t debug,
|
||||
if (debug)
|
||||
fprintf(f, ";\t%p: refcnt %u\n", entry, entry->refcnt);
|
||||
|
||||
fprintf(f, ";\t%s [srtt %u] [flags %08x]",
|
||||
addrbuf, entry->srtt, entry->flags);
|
||||
fprintf(f, ";\t%s [srtt %u] [flags %08x] [edns %u/%u/%u/%u/%u] "
|
||||
"[plain %u/%u]", addrbuf, entry->srtt, entry->flags,
|
||||
entry->edns, entry->to4096, entry->to1432, entry->to1232,
|
||||
entry->to512, entry->plain, entry->plainto);
|
||||
if (entry->udpsize != 0U)
|
||||
fprintf(f, " [udpsize %u]", entry->udpsize);
|
||||
if (entry->expires != 0)
|
||||
fprintf(f, " [ttl %d]", entry->expires - now);
|
||||
fprintf(f, "\n");
|
||||
@@ -3949,7 +3980,7 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
|
||||
unsigned int rtt, unsigned int factor)
|
||||
{
|
||||
int bucket;
|
||||
unsigned int new_srtt;
|
||||
isc_uint64_t new_srtt;
|
||||
isc_stdtime_t now;
|
||||
|
||||
REQUIRE(DNS_ADB_VALID(adb));
|
||||
@@ -3959,9 +3990,13 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
|
||||
bucket = addr->entry->lock_bucket;
|
||||
LOCK(&adb->entrylocks[bucket]);
|
||||
|
||||
if (factor == DNS_ADB_RTTADJAGE)
|
||||
new_srtt = addr->entry->srtt * 98 / 100;
|
||||
else
|
||||
|
||||
if (factor == DNS_ADB_RTTADJAGE) {
|
||||
new_srtt = addr->entry->srtt;
|
||||
new_srtt <<= 9;
|
||||
new_srtt -= addr->entry->srtt;
|
||||
new_srtt >>= 9;
|
||||
} else
|
||||
new_srtt = (addr->entry->srtt / 10 * factor)
|
||||
+ (rtt / 10 * (10 - factor));
|
||||
|
||||
@@ -4004,6 +4039,206 @@ dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
|
||||
UNLOCK(&adb->entrylocks[bucket]);
|
||||
}
|
||||
|
||||
#define EDNSTOS 3U
|
||||
isc_boolean_t
|
||||
dns_adb_noedns(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
|
||||
int bucket;
|
||||
isc_boolean_t noedns = ISC_FALSE;
|
||||
|
||||
REQUIRE(DNS_ADB_VALID(adb));
|
||||
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
||||
|
||||
bucket = addr->entry->lock_bucket;
|
||||
LOCK(&adb->entrylocks[bucket]);
|
||||
if (addr->entry->edns == 0U &&
|
||||
(addr->entry->plain > EDNSTOS || addr->entry->to4096 > EDNSTOS)) {
|
||||
if (((addr->entry->plain + addr->entry->to4096) & 0x3f) != 0) {
|
||||
noedns = ISC_TRUE;
|
||||
} else {
|
||||
/*
|
||||
* Increment plain so we don't get stuck.
|
||||
*/
|
||||
addr->entry->plain++;
|
||||
if (addr->entry->plain == 0xff) {
|
||||
addr->entry->edns >>= 1;
|
||||
addr->entry->to4096 >>= 1;
|
||||
addr->entry->to1432 >>= 1;
|
||||
addr->entry->to1232 >>= 1;
|
||||
addr->entry->to512 >>= 1;
|
||||
addr->entry->plain >>= 1;
|
||||
addr->entry->plainto >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
UNLOCK(&adb->entrylocks[bucket]);
|
||||
return (noedns);
|
||||
}
|
||||
|
||||
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]);
|
||||
addr->entry->plain++;
|
||||
if (addr->entry->plain == 0xff) {
|
||||
addr->entry->edns >>= 1;
|
||||
addr->entry->to4096 >>= 1;
|
||||
addr->entry->to1432 >>= 1;
|
||||
addr->entry->to1232 >>= 1;
|
||||
addr->entry->to512 >>= 1;
|
||||
addr->entry->plain >>= 1;
|
||||
addr->entry->plainto >>= 1;
|
||||
}
|
||||
UNLOCK(&adb->entrylocks[bucket]);
|
||||
}
|
||||
|
||||
void
|
||||
dns_adb_timeout(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]);
|
||||
/*
|
||||
* If we have not had a successful query then clear all
|
||||
* edns timeout information.
|
||||
*/
|
||||
if (addr->entry->edns == 0 && addr->entry->plain == 0) {
|
||||
addr->entry->to512 = 0;
|
||||
addr->entry->to1232 = 0;
|
||||
addr->entry->to1432 = 0;
|
||||
addr->entry->to4096 = 0;
|
||||
} else {
|
||||
addr->entry->to512 >>= 1;
|
||||
addr->entry->to1232 >>= 1;
|
||||
addr->entry->to1432 >>= 1;
|
||||
addr->entry->to4096 >>= 1;
|
||||
}
|
||||
addr->entry->plainto++;
|
||||
if (addr->entry->plainto == 0xff) {
|
||||
addr->entry->edns >>= 1;
|
||||
addr->entry->plain >>= 1;
|
||||
addr->entry->plainto >>= 1;
|
||||
}
|
||||
UNLOCK(&adb->entrylocks[bucket]);
|
||||
}
|
||||
|
||||
void
|
||||
dns_adb_ednsto(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size) {
|
||||
int bucket;
|
||||
|
||||
REQUIRE(DNS_ADB_VALID(adb));
|
||||
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
||||
|
||||
bucket = addr->entry->lock_bucket;
|
||||
LOCK(&adb->entrylocks[bucket]);
|
||||
|
||||
if (size <= 512U) {
|
||||
if (addr->entry->to512 <= EDNSTOS) {
|
||||
addr->entry->to512++;
|
||||
addr->entry->to1232++;
|
||||
addr->entry->to1432++;
|
||||
addr->entry->to4096++;
|
||||
}
|
||||
} else if (size <= 1232U) {
|
||||
if (addr->entry->to1232 <= EDNSTOS) {
|
||||
addr->entry->to1232++;
|
||||
addr->entry->to1432++;
|
||||
addr->entry->to4096++;
|
||||
}
|
||||
} else if (size <= 1432U) {
|
||||
if (addr->entry->to1432 <= EDNSTOS) {
|
||||
addr->entry->to1432++;
|
||||
addr->entry->to4096++;
|
||||
}
|
||||
} else {
|
||||
if (addr->entry->to4096 <= EDNSTOS)
|
||||
addr->entry->to4096++;
|
||||
}
|
||||
|
||||
if (addr->entry->to4096 == 0xff) {
|
||||
addr->entry->edns >>= 1;
|
||||
addr->entry->to4096 >>= 1;
|
||||
addr->entry->to1432 >>= 1;
|
||||
addr->entry->to1232 >>= 1;
|
||||
addr->entry->to512 >>= 1;
|
||||
addr->entry->plain >>= 1;
|
||||
addr->entry->plainto >>= 1;
|
||||
}
|
||||
UNLOCK(&adb->entrylocks[bucket]);
|
||||
}
|
||||
|
||||
void
|
||||
dns_adb_setudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size) {
|
||||
int bucket;
|
||||
|
||||
REQUIRE(DNS_ADB_VALID(adb));
|
||||
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
||||
|
||||
bucket = addr->entry->lock_bucket;
|
||||
LOCK(&adb->entrylocks[bucket]);
|
||||
if (size < 512U)
|
||||
size = 512U;
|
||||
if (size > addr->entry->udpsize)
|
||||
addr->entry->udpsize = size;
|
||||
addr->entry->edns++;
|
||||
if (addr->entry->edns == 0xff) {
|
||||
addr->entry->edns >>= 1;
|
||||
addr->entry->to4096 >>= 1;
|
||||
addr->entry->to1432 >>= 1;
|
||||
addr->entry->to1232 >>= 1;
|
||||
addr->entry->to512 >>= 1;
|
||||
addr->entry->plain >>= 1;
|
||||
addr->entry->plainto >>= 1;
|
||||
}
|
||||
UNLOCK(&adb->entrylocks[bucket]);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
dns_adb_getudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
|
||||
int bucket;
|
||||
unsigned int size;
|
||||
|
||||
REQUIRE(DNS_ADB_VALID(adb));
|
||||
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
||||
|
||||
bucket = addr->entry->lock_bucket;
|
||||
LOCK(&adb->entrylocks[bucket]);
|
||||
size = addr->entry->udpsize;
|
||||
UNLOCK(&adb->entrylocks[bucket]);
|
||||
|
||||
return (size);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
dns_adb_probesize(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
|
||||
int bucket;
|
||||
unsigned int size;
|
||||
|
||||
REQUIRE(DNS_ADB_VALID(adb));
|
||||
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
|
||||
|
||||
bucket = addr->entry->lock_bucket;
|
||||
LOCK(&adb->entrylocks[bucket]);
|
||||
if (addr->entry->to1232 > EDNSTOS)
|
||||
size = 512;
|
||||
else if (addr->entry->to1432 > EDNSTOS)
|
||||
size = 1232;
|
||||
else if (addr->entry->to4096 > EDNSTOS)
|
||||
size = 1432;
|
||||
else
|
||||
size = 4096;
|
||||
UNLOCK(&adb->entrylocks[bucket]);
|
||||
|
||||
return (size);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa,
|
||||
dns_adbaddrinfo_t **addrp, isc_stdtime_t now)
|
||||
|
@@ -567,6 +567,93 @@ dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
|
||||
*\li addr be valid.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_adb_setudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size);
|
||||
/*%
|
||||
* Update seen UDP response size. The largest seen will be returned by
|
||||
* dns_adb_getudpsize().
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li adb be valid.
|
||||
*
|
||||
*\li addr be valid.
|
||||
*/
|
||||
|
||||
unsigned int
|
||||
dns_adb_getudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
|
||||
/*%
|
||||
* Return the largest seen UDP response size.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li adb be valid.
|
||||
*
|
||||
*\li addr be valid.
|
||||
*/
|
||||
|
||||
unsigned int
|
||||
dns_adb_probesize(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
|
||||
/*%
|
||||
* Return suggested EDNS UDP size based on observed responses / failures.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li adb be valid.
|
||||
*
|
||||
*\li addr be valid.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
|
||||
/*%
|
||||
* Record a successful plain 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 plain DNS UDP query failed.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li adb be valid.
|
||||
*
|
||||
*\li addr be valid.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_adb_ednsto(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size);
|
||||
/*%
|
||||
* Record a failed EDNS UDP response and the advertised EDNS UDP buffer size
|
||||
* used.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li adb be valid.
|
||||
*
|
||||
*\li addr be valid.
|
||||
*/
|
||||
|
||||
isc_boolean_t
|
||||
dns_adb_noedns(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
|
||||
/*%
|
||||
* Return whether EDNS should be disabled for this server.
|
||||
*
|
||||
* 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);
|
||||
|
@@ -167,9 +167,16 @@ typedef struct query {
|
||||
unsigned int attributes;
|
||||
unsigned int sends;
|
||||
unsigned int connects;
|
||||
unsigned int udpsize;
|
||||
unsigned char data[512];
|
||||
} resquery_t;
|
||||
|
||||
struct tried {
|
||||
isc_sockaddr_t addr;
|
||||
unsigned int count;
|
||||
ISC_LINK(struct tried) link;
|
||||
};
|
||||
|
||||
#define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
|
||||
#define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
|
||||
|
||||
@@ -231,8 +238,8 @@ struct fetchctx {
|
||||
dns_forwarderlist_t forwarders;
|
||||
dns_fwdpolicy_t fwdpolicy;
|
||||
isc_sockaddrlist_t bad;
|
||||
isc_sockaddrlist_t edns;
|
||||
isc_sockaddrlist_t edns512;
|
||||
ISC_LIST(struct tried) edns;
|
||||
ISC_LIST(struct tried) edns512;
|
||||
isc_sockaddrlist_t bad_edns;
|
||||
dns_validator_t *validator;
|
||||
ISC_LIST(dns_validator_t) validators;
|
||||
@@ -452,6 +459,8 @@ struct dns_resolver {
|
||||
#define FCTX_ADDRINFO_MARK 0x0001
|
||||
#define FCTX_ADDRINFO_FORWARDER 0x1000
|
||||
#define FCTX_ADDRINFO_TRIED 0x2000
|
||||
#define FCTX_ADDRINFO_EDNSOK 0x4000
|
||||
|
||||
#define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
|
||||
== 0)
|
||||
#define ISFORWARDER(a) (((a)->flags & \
|
||||
@@ -811,6 +820,10 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
|
||||
|
||||
query->attributes |= RESQUERY_ATTR_CANCELED;
|
||||
|
||||
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
isc_sockaddr_format(&query->addrinfo->sockaddr,
|
||||
addrbuf, sizeof(addrbuf));
|
||||
|
||||
/*
|
||||
* Should we update the RTT?
|
||||
*/
|
||||
@@ -844,14 +857,45 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
|
||||
inc_stats(fctx->res,
|
||||
dns_resstatscounter_queryrtt5);
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
isc_uint32_t value;
|
||||
isc_uint32_t mask;
|
||||
/*
|
||||
* We don't have an RTT for this query. Maybe the
|
||||
* packet was lost, or maybe this server is very
|
||||
* slow. We don't know. Increase the RTT.
|
||||
*/
|
||||
INSIST(no_response);
|
||||
rtt = query->addrinfo->srtt + 200000;
|
||||
isc_random_get(&value);
|
||||
if (query->addrinfo->srtt > 800000)
|
||||
mask = 0x3fff;
|
||||
else if (query->addrinfo->srtt > 400000)
|
||||
mask = 0x7fff;
|
||||
else if (query->addrinfo->srtt > 200000)
|
||||
mask = 0xffff;
|
||||
else if (query->addrinfo->srtt > 100000)
|
||||
mask = 0x1ffff;
|
||||
else if (query->addrinfo->srtt > 50000)
|
||||
mask = 0x3ffff;
|
||||
else if (query->addrinfo->srtt > 25000)
|
||||
mask = 0x7ffff;
|
||||
else
|
||||
mask = 0xfffff;
|
||||
if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0)
|
||||
dns_adb_ednsto(fctx->adb, query->addrinfo,
|
||||
query->udpsize);
|
||||
else
|
||||
dns_adb_timeout(fctx->adb, query->addrinfo);
|
||||
|
||||
/*
|
||||
* Don't adjust timeout on EDNS queries unless we have
|
||||
* seen a EDNS response.
|
||||
*/
|
||||
if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
|
||||
(query->addrinfo->flags & FCTX_ADDRINFO_EDNSOK) == 0) {
|
||||
mask >>= 2;
|
||||
}
|
||||
rtt = query->addrinfo->srtt + (value & mask);
|
||||
if (rtt > MAX_SINGLE_QUERY_TIMEOUT_US)
|
||||
rtt = MAX_SINGLE_QUERY_TIMEOUT_US;
|
||||
/*
|
||||
@@ -1618,62 +1662,70 @@ add_bad_edns(fetchctx_t *fctx, isc_sockaddr_t *address) {
|
||||
ISC_LIST_INITANDAPPEND(fctx->bad_edns, sa, link);
|
||||
}
|
||||
|
||||
static isc_boolean_t
|
||||
static struct tried *
|
||||
triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
|
||||
isc_sockaddr_t *sa;
|
||||
struct tried *tried;
|
||||
|
||||
for (sa = ISC_LIST_HEAD(fctx->edns);
|
||||
sa != NULL;
|
||||
sa = ISC_LIST_NEXT(sa, link)) {
|
||||
if (isc_sockaddr_equal(sa, address))
|
||||
return (ISC_TRUE);
|
||||
for (tried = ISC_LIST_HEAD(fctx->edns);
|
||||
tried != NULL;
|
||||
tried = ISC_LIST_NEXT(tried, link)) {
|
||||
if (isc_sockaddr_equal(&tried->addr, address))
|
||||
return (tried);
|
||||
}
|
||||
|
||||
return (ISC_FALSE);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
add_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
|
||||
isc_sockaddr_t *sa;
|
||||
struct tried *tried;
|
||||
|
||||
if (triededns(fctx, address))
|
||||
tried = triededns(fctx, address);
|
||||
if (tried != NULL) {
|
||||
tried->count++;
|
||||
return;
|
||||
|
||||
sa = isc_mem_get(fctx->mctx, sizeof(*sa));
|
||||
if (sa == NULL)
|
||||
return;
|
||||
|
||||
*sa = *address;
|
||||
ISC_LIST_INITANDAPPEND(fctx->edns, sa, link);
|
||||
}
|
||||
|
||||
static isc_boolean_t
|
||||
triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
|
||||
isc_sockaddr_t *sa;
|
||||
|
||||
for (sa = ISC_LIST_HEAD(fctx->edns512);
|
||||
sa != NULL;
|
||||
sa = ISC_LIST_NEXT(sa, link)) {
|
||||
if (isc_sockaddr_equal(sa, address))
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
return (ISC_FALSE);
|
||||
tried = isc_mem_get(fctx->mctx, sizeof(*tried));
|
||||
if (tried == NULL)
|
||||
return;
|
||||
|
||||
tried->addr = *address;
|
||||
tried->count = 1;
|
||||
ISC_LIST_INITANDAPPEND(fctx->edns, tried, link);
|
||||
}
|
||||
|
||||
static struct tried *
|
||||
triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
|
||||
struct tried *tried;
|
||||
|
||||
for (tried = ISC_LIST_HEAD(fctx->edns512);
|
||||
tried != NULL;
|
||||
tried = ISC_LIST_NEXT(tried, link)) {
|
||||
if (isc_sockaddr_equal(&tried->addr, address))
|
||||
return (tried);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
|
||||
isc_sockaddr_t *sa;
|
||||
struct tried *tried;
|
||||
|
||||
if (triededns512(fctx, address))
|
||||
tried = triededns512(fctx, address);
|
||||
if (tried != NULL) {
|
||||
tried->count++;
|
||||
return;
|
||||
}
|
||||
|
||||
tried = isc_mem_get(fctx->mctx, sizeof(*tried));
|
||||
if (tried == NULL)
|
||||
return;
|
||||
|
||||
sa = isc_mem_get(fctx->mctx, sizeof(*sa));
|
||||
if (sa == NULL)
|
||||
return;
|
||||
|
||||
*sa = *address;
|
||||
ISC_LIST_INITANDAPPEND(fctx->edns512, sa, link);
|
||||
tried->addr = *address;
|
||||
tried->count = 1;
|
||||
ISC_LIST_INITANDAPPEND(fctx->edns512, tried, link);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
@@ -1699,6 +1751,11 @@ resquery_send(resquery_t *query) {
|
||||
isc_boolean_t connecting = ISC_FALSE;
|
||||
dns_ednsopt_t ednsopts[EDNSOPTS];
|
||||
unsigned ednsopt = 0;
|
||||
isc_uint16_t hint = 0, udpsize = 0; /* No EDNS */
|
||||
|
||||
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
isc_sockaddr_format(&query->addrinfo->sockaddr,
|
||||
addrbuf, sizeof(addrbuf));
|
||||
|
||||
fctx = query->fctx;
|
||||
QTRACE("send");
|
||||
@@ -1766,11 +1823,12 @@ resquery_send(resquery_t *query) {
|
||||
|
||||
/*
|
||||
* Set CD if the client says don't validate or the question is
|
||||
* under a secure entry point.
|
||||
* under a secure entry point and it is not a recursive query.
|
||||
*/
|
||||
if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0) {
|
||||
fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
|
||||
} else if (res->view->enablevalidation) {
|
||||
} else if (res->view->enablevalidation &&
|
||||
(fctx->qmessage->flags & DNS_MESSAGEFLAG_RD) != 0) {
|
||||
result = dns_view_issecuredomain(res->view, &fctx->name,
|
||||
&secure_domain);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
@@ -1827,35 +1885,37 @@ resquery_send(resquery_t *query) {
|
||||
if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) != 0)
|
||||
query->options |= DNS_FETCHOPT_NOEDNS0;
|
||||
|
||||
/*
|
||||
* Handle timeouts by reducing the UDP response size to 512 bytes
|
||||
* then if that doesn't work disabling EDNS (includes DO) and CD.
|
||||
*
|
||||
* These timeout can be due to:
|
||||
* * broken nameservers that don't respond to EDNS queries.
|
||||
* * broken/misconfigured firewalls and NAT implementations
|
||||
* that don't handle IP fragmentation.
|
||||
* * broken/misconfigured firewalls that don't handle responses
|
||||
* greater than 512 bytes.
|
||||
* * broken/misconfigured firewalls that don't handle EDNS, DO
|
||||
* or CD.
|
||||
* * packet loss / link outage.
|
||||
*/
|
||||
if (fctx->timeout) {
|
||||
if ((triededns512(fctx, &query->addrinfo->sockaddr) ||
|
||||
fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) &&
|
||||
(query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
|
||||
/* See if response history indicates that EDNS is not supported. */
|
||||
if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
|
||||
dns_adb_noedns(fctx->adb, query->addrinfo))
|
||||
query->options |= DNS_FETCHOPT_NOEDNS0;
|
||||
|
||||
|
||||
if (fctx->timeout && (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
|
||||
isc_sockaddr_t *sockaddr = &query->addrinfo->sockaddr;
|
||||
struct tried *tried;
|
||||
|
||||
if (fctx->timeouts > (MAX_EDNS0_TIMEOUTS * 2) &&
|
||||
(query->addrinfo->flags & FCTX_ADDRINFO_EDNSOK) == 0) {
|
||||
query->options |= DNS_FETCHOPT_NOEDNS0;
|
||||
fctx->reason = "disabling EDNS";
|
||||
} else if ((triededns(fctx, &query->addrinfo->sockaddr) ||
|
||||
fctx->timeouts >= MAX_EDNS0_TIMEOUTS) &&
|
||||
(query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
|
||||
query->options |= DNS_FETCHOPT_EDNS512;
|
||||
fctx->reason = "reducing the advertised EDNS UDP "
|
||||
"packet size to 512 octets";
|
||||
} else if ((tried = triededns512(fctx, sockaddr)) != NULL &&
|
||||
tried->count >= 2U &&
|
||||
(query->addrinfo->flags & FCTX_ADDRINFO_EDNSOK) == 0) {
|
||||
query->options |= DNS_FETCHOPT_NOEDNS0;
|
||||
fctx->reason = "disabling EDNS";
|
||||
} else if ((tried = triededns(fctx, sockaddr)) != NULL) {
|
||||
if (tried->count == 1U) {
|
||||
hint = dns_adb_getudpsize(fctx->adb,
|
||||
query->addrinfo);
|
||||
} else if (tried->count >= 2U) {
|
||||
query->options |= DNS_FETCHOPT_EDNS512;
|
||||
fctx->reason = "reducing the advertised EDNS "
|
||||
"UDP packet size to 512 octets";
|
||||
}
|
||||
}
|
||||
fctx->timeout = ISC_FALSE;
|
||||
}
|
||||
fctx->timeout = ISC_FALSE;
|
||||
|
||||
/*
|
||||
* Use EDNS0, unless the caller doesn't want it, or we know that
|
||||
@@ -1864,19 +1924,46 @@ resquery_send(resquery_t *query) {
|
||||
if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
|
||||
if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {
|
||||
unsigned int version = 0; /* Default version. */
|
||||
unsigned int flags;
|
||||
isc_uint16_t udpsize = res->udpsize;
|
||||
unsigned int flags = query->addrinfo->flags;
|
||||
isc_boolean_t reqnsid = res->view->requestnsid;
|
||||
|
||||
flags = query->addrinfo->flags;
|
||||
if ((flags & FCTX_ADDRINFO_EDNSOK) != 0 &&
|
||||
(query->options & DNS_FETCHOPT_EDNS512) == 0) {
|
||||
udpsize = dns_adb_probesize(fctx->adb,
|
||||
query->addrinfo);
|
||||
if (udpsize > res->udpsize)
|
||||
udpsize = res->udpsize;
|
||||
}
|
||||
|
||||
if (peer != NULL)
|
||||
(void)dns_peer_getudpsize(peer, &udpsize);
|
||||
|
||||
if (udpsize == 0U && res->udpsize == 512U)
|
||||
udpsize = 512;
|
||||
|
||||
/*
|
||||
* Was the size forced to 512 in the configuration?
|
||||
*/
|
||||
if (udpsize == 512U)
|
||||
query->options |= DNS_FETCHOPT_EDNS512;
|
||||
|
||||
/*
|
||||
* We have talked to this server before.
|
||||
*/
|
||||
if (hint != 0U)
|
||||
udpsize = hint;
|
||||
|
||||
/*
|
||||
* We know nothing about the peer's capabilities
|
||||
* so start with minimal EDNS UDP size.
|
||||
*/
|
||||
if (udpsize == 0U)
|
||||
udpsize = 512;
|
||||
|
||||
if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {
|
||||
version = flags & DNS_FETCHOPT_EDNSVERSIONMASK;
|
||||
version >>= DNS_FETCHOPT_EDNSVERSIONSHIFT;
|
||||
}
|
||||
if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
|
||||
udpsize = 512;
|
||||
else if (peer != NULL)
|
||||
(void)dns_peer_getudpsize(peer, &udpsize);
|
||||
|
||||
/* request NSID for current view or peer? */
|
||||
if (peer != NULL)
|
||||
@@ -1899,6 +1986,7 @@ resquery_send(resquery_t *query) {
|
||||
* bit.
|
||||
*/
|
||||
query->options |= DNS_FETCHOPT_NOEDNS0;
|
||||
udpsize = 0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
@@ -1910,6 +1998,11 @@ resquery_send(resquery_t *query) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Record the UDP EDNS size choosen.
|
||||
*/
|
||||
query->udpsize = udpsize;
|
||||
|
||||
/*
|
||||
* If we need EDNS0 to do this query and aren't using it, we lose.
|
||||
*/
|
||||
@@ -1918,10 +2011,10 @@ resquery_send(resquery_t *query) {
|
||||
goto cleanup_message;
|
||||
}
|
||||
|
||||
if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0)
|
||||
if (udpsize > 512U)
|
||||
add_triededns(fctx, &query->addrinfo->sockaddr);
|
||||
|
||||
if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
|
||||
if (udpsize == 512U)
|
||||
add_triededns512(fctx, &query->addrinfo->sockaddr);
|
||||
|
||||
/*
|
||||
@@ -2612,7 +2705,7 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
|
||||
* Don't pound on remote servers. (Failsafe!)
|
||||
*/
|
||||
fctx->restarts++;
|
||||
if (fctx->restarts > 10) {
|
||||
if (fctx->restarts > 100) {
|
||||
FCTXTRACE("too many restarts");
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
@@ -3142,6 +3235,7 @@ fctx_unlink(fetchctx_t *fctx) {
|
||||
static void
|
||||
fctx_destroy(fetchctx_t *fctx) {
|
||||
isc_sockaddr_t *sa, *next_sa;
|
||||
struct tried *tried;
|
||||
|
||||
REQUIRE(VALID_FCTX(fctx));
|
||||
REQUIRE(fctx->state == fetchstate_done ||
|
||||
@@ -3168,20 +3262,18 @@ fctx_destroy(fetchctx_t *fctx) {
|
||||
isc_mem_put(fctx->mctx, sa, sizeof(*sa));
|
||||
}
|
||||
|
||||
for (sa = ISC_LIST_HEAD(fctx->edns);
|
||||
sa != NULL;
|
||||
sa = next_sa) {
|
||||
next_sa = ISC_LIST_NEXT(sa, link);
|
||||
ISC_LIST_UNLINK(fctx->edns, sa, link);
|
||||
isc_mem_put(fctx->mctx, sa, sizeof(*sa));
|
||||
for (tried = ISC_LIST_HEAD(fctx->edns);
|
||||
tried != NULL;
|
||||
tried = ISC_LIST_HEAD(fctx->edns)) {
|
||||
ISC_LIST_UNLINK(fctx->edns, tried, link);
|
||||
isc_mem_put(fctx->mctx, tried, sizeof(*tried));
|
||||
}
|
||||
|
||||
for (sa = ISC_LIST_HEAD(fctx->edns512);
|
||||
sa != NULL;
|
||||
sa = next_sa) {
|
||||
next_sa = ISC_LIST_NEXT(sa, link);
|
||||
ISC_LIST_UNLINK(fctx->edns512, sa, link);
|
||||
isc_mem_put(fctx->mctx, sa, sizeof(*sa));
|
||||
for (tried = ISC_LIST_HEAD(fctx->edns512);
|
||||
tried != NULL;
|
||||
tried = ISC_LIST_HEAD(fctx->edns512)) {
|
||||
ISC_LIST_UNLINK(fctx->edns512, tried, link);
|
||||
isc_mem_put(fctx->mctx, tried, sizeof(*tried));
|
||||
}
|
||||
|
||||
for (sa = ISC_LIST_HEAD(fctx->bad_edns);
|
||||
@@ -6907,6 +6999,13 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((options & DNS_FETCHOPT_TCP) == 0) {
|
||||
if ((options & DNS_FETCHOPT_NOEDNS0) == 0)
|
||||
dns_adb_setudpsize(fctx->adb, query->addrinfo,
|
||||
isc_buffer_usedlength(&devent->buffer));
|
||||
else
|
||||
dns_adb_plainresponse(fctx->adb, query->addrinfo);
|
||||
}
|
||||
result = dns_message_parse(message, &devent->buffer, 0);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
switch (result) {
|
||||
@@ -7019,12 +7118,66 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
message->rcode == dns_rcode_refused ||
|
||||
message->rcode == dns_rcode_yxdomain) &&
|
||||
bad_edns(fctx, &query->addrinfo->sockaddr)) {
|
||||
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
/*
|
||||
* XXXMPA We need to drop/remove the logging here when we have more
|
||||
* experience.
|
||||
*/
|
||||
char buf[4096], addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
|
||||
sizeof(addrbuf));
|
||||
snprintf(buf, sizeof(buf), "received packet from %s "
|
||||
"(bad edns):\n", addrbuf);
|
||||
dns_message_logpacket(message, buf,
|
||||
DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
|
||||
ISC_LOG_NOTICE, fctx->res->mctx);
|
||||
dns_adb_changeflags(fctx->adb, query->addrinfo,
|
||||
DNS_FETCHOPT_NOEDNS0,
|
||||
DNS_FETCHOPT_NOEDNS0);
|
||||
} else if (opt == NULL && (message->flags & DNS_MESSAGEFLAG_TC) == 0 &&
|
||||
(message->rcode == dns_rcode_noerror ||
|
||||
message->rcode == dns_rcode_nxdomain) &&
|
||||
(query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
|
||||
/*
|
||||
* Old versions of named incorrectly drop the OPT record
|
||||
* when there is a signed, truncated response so check that
|
||||
* TC is not set.
|
||||
*/
|
||||
/*
|
||||
* XXXMPA We need to drop/remove the logging here when we have more
|
||||
* experience.
|
||||
*/
|
||||
char buf[4096], addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
/*
|
||||
* We didn't get a OPT record in response to a EDNS query.
|
||||
* Record that the server is not talking EDNS. While this
|
||||
* should be safe to do for any rcode we limit it to NOERROR
|
||||
* and NXDOMAIN.
|
||||
*/
|
||||
isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
|
||||
sizeof(addrbuf));
|
||||
snprintf(buf, sizeof(buf), "received packet from %s (no opt):\n",
|
||||
addrbuf);
|
||||
dns_message_logpacket(message, buf,
|
||||
DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
|
||||
ISC_LOG_NOTICE, fctx->res->mctx);
|
||||
dns_adb_changeflags(fctx->adb, query->addrinfo,
|
||||
DNS_FETCHOPT_NOEDNS0,
|
||||
DNS_FETCHOPT_NOEDNS0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get a non error response to a EDNS query record the fact
|
||||
* so we won't fallback to plain DNS in the future for this server.
|
||||
*/
|
||||
if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
|
||||
(query->addrinfo->flags & FCTX_ADDRINFO_EDNSOK) == 0 &&
|
||||
(message->rcode == dns_rcode_noerror ||
|
||||
message->rcode == dns_rcode_nxdomain ||
|
||||
message->rcode == dns_rcode_refused ||
|
||||
message->rcode == dns_rcode_yxdomain)) {
|
||||
dns_adb_changeflags(fctx->adb, query->addrinfo,
|
||||
FCTX_ADDRINFO_EDNSOK,
|
||||
FCTX_ADDRINFO_EDNSOK);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -7038,6 +7191,10 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
if ((options & DNS_FETCHOPT_TCP) != 0) {
|
||||
broken_server = DNS_R_TRUNCATEDTCP;
|
||||
keep_trying = ISC_TRUE;
|
||||
} else if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0 &&
|
||||
(query->options & DNS_FETCHOPT_EDNS512) == 0 &&
|
||||
!triededns(fctx, &query->addrinfo->sockaddr)) {
|
||||
resend = ISC_TRUE;
|
||||
} else {
|
||||
options |= DNS_FETCHOPT_TCP;
|
||||
resend = ISC_TRUE;
|
||||
|
Reference in New Issue
Block a user