- Sort out test runs when the build directory isn't the project

root directory.
- Add config tcp-idle-timeout (default 30s). This applies to
  client connections only; the timeout on TCP connections upstream
  is unaffected.


git-svn-id: file:///svn/unbound/trunk@4802 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2018-07-31 07:15:12 +00:00
parent 10c085f81d
commit 007123ee2c
23 changed files with 315 additions and 56 deletions

View file

@ -57,7 +57,7 @@ STRIP=@STRIP@
CC=@CC@ CC=@CC@
CPPFLAGS=-I. @CPPFLAGS@ CPPFLAGS=-I. @CPPFLAGS@
PYTHON_CPPFLAGS=-I. @PYTHON_CPPFLAGS@ PYTHON_CPPFLAGS=-I. @PYTHON_CPPFLAGS@
CFLAGS=@CFLAGS@ CFLAGS=-DSRCDIR=$(srcdir) @CFLAGS@
LDFLAGS=@LDFLAGS@ LDFLAGS=@LDFLAGS@
LIBS=@LIBS@ LIBS=@LIBS@
LIBOBJS=@LIBOBJS@ LIBOBJS=@LIBOBJS@
@ -306,10 +306,11 @@ longcheck: longtest
test: unittest$(EXEEXT) testbound$(EXEEXT) test: unittest$(EXEEXT) testbound$(EXEEXT)
./unittest$(EXEEXT) ./unittest$(EXEEXT)
./testbound$(EXEEXT) -s ./testbound$(EXEEXT) -s
for x in testdata/*.rpl; do echo -n "$$x "; if ./testbound$(EXEEXT) -p $$x >/dev/null 2>&1; then echo OK; else echo failed; exit 1; fi done for x in $(srcdir)/testdata/*.rpl; do echo -n "$$x "; if ./testbound$(EXEEXT) -p $$x >/dev/null 2>&1; then echo OK; else echo failed; exit 1; fi done
@echo test OK @echo test OK
longtest: tests longtest: tests
if test ! $(srcdir)/testdata -ef ./testdata; then rm -rf testcode testdata; mkdir testcode testdata; cp -R $(srcdir)/testdata/*.sh $(srcdir)/testdata/*.tdir testdata; cp $(srcdir)/testcode/*.sh testcode; fi
if test -x "`which bash`"; then bash testcode/do-tests.sh; else sh testcode/do-tests.sh; fi if test -x "`which bash`"; then bash testcode/do-tests.sh; else sh testcode/do-tests.sh; fi
lib: libunbound.la unbound.h lib: libunbound.la unbound.h

View file

@ -1708,9 +1708,9 @@ worker_init(struct worker* worker, struct config_file *cfg,
worker->comsig = NULL; worker->comsig = NULL;
} }
worker->front = listen_create(worker->base, ports, worker->front = listen_create(worker->base, ports,
cfg->msg_buffer_size, (int)cfg->incoming_num_tcp, cfg->msg_buffer_size, (int)cfg->incoming_num_tcp,
worker->daemon->listen_sslctx, dtenv, worker_handle_request, cfg->tcp_idle_timeout, worker->daemon->listen_sslctx,
worker); dtenv, worker_handle_request, worker);
if(!worker->front) { if(!worker->front) {
log_err("could not create listening sockets"); log_err("could not create listening sockets");
worker_delete(worker); worker_delete(worker);

View file

@ -1,3 +1,16 @@
31 July 2018: Wouter
- Patches from Jim Hague (Sinodun) for EDNS KeepAlive.
- Sort out test runs when the build directory isn't the project
root directory.
- Add config tcp-idle-timeout (default 30s). This applies to
client connections only; the timeout on TCP connections upstream
is unaffected.
- Error if EDNS Keepalive received over UDP.
- Add edns-tcp-keepalive and edns-tcp-keepalive timeout options
and implement option in client responses.
- Correct and expand manual page entries for keepalive and idle timeout.
- Implement progressive backoff of TCP idle/keepalive timeout.
30 July 2018: Wouter 30 July 2018: Wouter
- Fix #4136: insufficiency from mismatch of FLEX capability between - Fix #4136: insufficiency from mismatch of FLEX capability between
released tarball and build host. released tarball and build host.

View file

@ -389,6 +389,11 @@ Note that not all platform supports socket option to set MSS (TCP_MAXSEG).
Default is system default MSS determined by interface MTU and Default is system default MSS determined by interface MTU and
negotiation between Unbound and other servers. negotiation between Unbound and other servers.
.TP .TP
.B tcp-idle-timeout: \fI<msec>\fR
The period Unbound will wait for a query on a TCP connection.
If this timeout expires Unbound closes the connection.
This option defaults to 30000 milliseconds.
.TP
.B tcp\-upstream: \fI<yes or no> .B tcp\-upstream: \fI<yes or no>
Enable or disable whether the upstream queries use TCP only for transport. Enable or disable whether the upstream queries use TCP only for transport.
Default is no. Useful in tunneling scenarios. Default is no. Useful in tunneling scenarios.

View file

@ -1227,8 +1227,9 @@ listen_cp_insert(struct comm_point* c, struct listen_dnsport* front)
struct listen_dnsport* struct listen_dnsport*
listen_create(struct comm_base* base, struct listen_port* ports, listen_create(struct comm_base* base, struct listen_port* ports,
size_t bufsize, int tcp_accept_count, void* sslctx, size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
struct dt_env* dtenv, comm_point_callback_type* cb, void *cb_arg) void* sslctx, struct dt_env* dtenv,
comm_point_callback_type* cb, void *cb_arg)
{ {
struct listen_dnsport* front = (struct listen_dnsport*) struct listen_dnsport* front = (struct listen_dnsport*)
malloc(sizeof(struct listen_dnsport)); malloc(sizeof(struct listen_dnsport));
@ -1254,10 +1255,12 @@ listen_create(struct comm_base* base, struct listen_port* ports,
else if(ports->ftype == listen_type_tcp || else if(ports->ftype == listen_type_tcp ||
ports->ftype == listen_type_tcp_dnscrypt) ports->ftype == listen_type_tcp_dnscrypt)
cp = comm_point_create_tcp(base, ports->fd, cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, bufsize, cb, cb_arg); tcp_accept_count, tcp_idle_timeout,
bufsize, cb, cb_arg);
else if(ports->ftype == listen_type_ssl) { else if(ports->ftype == listen_type_ssl) {
cp = comm_point_create_tcp(base, ports->fd, cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, bufsize, cb, cb_arg); tcp_accept_count, tcp_idle_timeout,
bufsize, cb, cb_arg);
cp->ssl = sslctx; cp->ssl = sslctx;
} else if(ports->ftype == listen_type_udpancil || } else if(ports->ftype == listen_type_udpancil ||
ports->ftype == listen_type_udpancil_dnscrypt) ports->ftype == listen_type_udpancil_dnscrypt)

View file

@ -145,7 +145,8 @@ void listening_ports_free(struct listen_port* list);
* @return: the malloced listening structure, ready for use. NULL on error. * @return: the malloced listening structure, ready for use. NULL on error.
*/ */
struct listen_dnsport* listen_create(struct comm_base* base, struct listen_dnsport* listen_create(struct comm_base* base,
struct listen_port* ports, size_t bufsize, int tcp_accept_count, struct listen_port* ports, size_t bufsize,
int tcp_accept_count, int tcp_idle_timeout,
void* sslctx, struct dt_env *dtenv, comm_point_callback_type* cb, void* sslctx, struct dt_env *dtenv, comm_point_callback_type* cb,
void* cb_arg); void* cb_arg);

View file

@ -856,6 +856,7 @@ run_scenario(struct replay_runtime* runtime)
struct listen_dnsport* struct listen_dnsport*
listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports), listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
size_t bufsize, int ATTR_UNUSED(tcp_accept_count), size_t bufsize, int ATTR_UNUSED(tcp_accept_count),
int ATTR_UNUSED(tcp_idle_timeout),
void* ATTR_UNUSED(sslctx), struct dt_env* ATTR_UNUSED(dtenv), void* ATTR_UNUSED(sslctx), struct dt_env* ATTR_UNUSED(dtenv),
comm_point_callback_type* cb, void* cb_arg) comm_point_callback_type* cb, void* cb_arg)
{ {

View file

@ -44,6 +44,8 @@
#include <getopt.h> #include <getopt.h>
#endif #endif
#include <signal.h> #include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include "util/locks.h" #include "util/locks.h"
#include "util/log.h" #include "util/log.h"
#include "util/net_help.h" #include "util/net_help.h"
@ -71,6 +73,7 @@ static void usage(char* argv[])
printf("-f server what ipaddr@portnr to send the queries to\n"); printf("-f server what ipaddr@portnr to send the queries to\n");
printf("-u use UDP. No retries are attempted.\n"); printf("-u use UDP. No retries are attempted.\n");
printf("-n do not wait for an answer.\n"); printf("-n do not wait for an answer.\n");
printf("-d secs delay after connection before sending query\n");
printf("-s use ssl\n"); printf("-s use ssl\n");
printf("-h this help text\n"); printf("-h this help text\n");
exit(1); exit(1);
@ -275,7 +278,8 @@ static int get_random(void)
/** send the TCP queries and print answers */ /** send the TCP queries and print answers */
static void static void
send_em(const char* svr, int udp, int usessl, int noanswer, int num, char** qs) send_em(const char* svr, int udp, int usessl, int noanswer, int delay,
int num, char** qs)
{ {
sldns_buffer* buf = sldns_buffer_new(65553); sldns_buffer* buf = sldns_buffer_new(65553);
int fd = open_svr(svr, udp); int fd = open_svr(svr, udp);
@ -310,6 +314,8 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int num, char** qs)
} }
} }
for(i=0; i<num; i+=3) { for(i=0; i<num; i+=3) {
if (delay != 0)
sleep(delay);
printf("\nNext query is %s %s %s\n", qs[i], qs[i+1], qs[i+2]); printf("\nNext query is %s %s %s\n", qs[i], qs[i+1], qs[i+2]);
write_q(fd, udp, ssl, buf, (uint16_t)get_random(), qs[i], write_q(fd, udp, ssl, buf, (uint16_t)get_random(), qs[i],
qs[i+1], qs[i+2]); qs[i+1], qs[i+2]);
@ -358,6 +364,7 @@ int main(int argc, char** argv)
int udp = 0; int udp = 0;
int noanswer = 0; int noanswer = 0;
int usessl = 0; int usessl = 0;
int delay = 0;
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
WSADATA wsa_data; WSADATA wsa_data;
@ -382,7 +389,7 @@ int main(int argc, char** argv)
if(argc == 1) { if(argc == 1) {
usage(argv); usage(argv);
} }
while( (c=getopt(argc, argv, "f:hnsu")) != -1) { while( (c=getopt(argc, argv, "f:hnsud:")) != -1) {
switch(c) { switch(c) {
case 'f': case 'f':
svr = optarg; svr = optarg;
@ -396,6 +403,13 @@ int main(int argc, char** argv)
case 's': case 's':
usessl = 1; usessl = 1;
break; break;
case 'd':
if(atoi(optarg)==0 && strcmp(optarg,"0")!=0) {
printf("bad delay: %s\n", optarg);
return 1;
}
delay = atoi(optarg);
break;
case 'h': case 'h':
case '?': case '?':
default: default:
@ -426,7 +440,7 @@ int main(int argc, char** argv)
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); (void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
#endif #endif
} }
send_em(svr, udp, usessl, noanswer, argc, argv); send_em(svr, udp, usessl, noanswer, delay, argc, argv);
checklock_stop(); checklock_stop();
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
WSACleanup(); WSACleanup();

View file

@ -199,15 +199,25 @@ rr_test_file(const char* input, const char* check)
free(back); free(back);
} }
#define xstr(s) str(s)
#define str(s) #s
#define SRCDIRSTR xstr(SRCDIR)
/** read rrs to and from string, to and from wireformat */ /** read rrs to and from string, to and from wireformat */
static void static void
rr_tests(void) rr_tests(void)
{ {
rr_test_file("testdata/test_ldnsrr.1", "testdata/test_ldnsrr.c1"); rr_test_file(SRCDIRSTR "/testdata/test_ldnsrr.1",
rr_test_file("testdata/test_ldnsrr.2", "testdata/test_ldnsrr.c2"); SRCDIRSTR "/testdata/test_ldnsrr.c1");
rr_test_file("testdata/test_ldnsrr.3", "testdata/test_ldnsrr.c3"); rr_test_file(SRCDIRSTR "/testdata/test_ldnsrr.2",
rr_test_file("testdata/test_ldnsrr.4", "testdata/test_ldnsrr.c4"); SRCDIRSTR "/testdata/test_ldnsrr.c2");
rr_test_file("testdata/test_ldnsrr.5", "testdata/test_ldnsrr.c5"); rr_test_file(SRCDIRSTR "/testdata/test_ldnsrr.3",
SRCDIRSTR "/testdata/test_ldnsrr.c3");
rr_test_file(SRCDIRSTR "/testdata/test_ldnsrr.4",
SRCDIRSTR "/testdata/test_ldnsrr.c4");
rr_test_file(SRCDIRSTR "/testdata/test_ldnsrr.5",
SRCDIRSTR "/testdata/test_ldnsrr.c5");
} }
void void

View file

@ -495,6 +495,11 @@ testfromdrillfile(sldns_buffer* pkt, struct alloc_cache* alloc,
fclose(in); fclose(in);
} }
#define xstr(s) str(s)
#define str(s) #s
#define SRCDIRSTR xstr(SRCDIR)
void msgparse_test(void) void msgparse_test(void)
{ {
time_t origttl = MAX_NEG_TTL; time_t origttl = MAX_NEG_TTL;
@ -509,27 +514,27 @@ void msgparse_test(void)
unit_show_feature("message parse"); unit_show_feature("message parse");
simpletest(pkt, &alloc, out); simpletest(pkt, &alloc, out);
/* plain hex dumps, like pcat */ /* plain hex dumps, like pcat */
testfromfile(pkt, &alloc, out, "testdata/test_packets.1"); testfromfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.1");
testfromfile(pkt, &alloc, out, "testdata/test_packets.2"); testfromfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.2");
testfromfile(pkt, &alloc, out, "testdata/test_packets.3"); testfromfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.3");
/* like from drill -w - */ /* like from drill -w - */
testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.4"); testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.4");
testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.5"); testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.5");
matches_nolocation = 1; /* RR order not important for the next test */ matches_nolocation = 1; /* RR order not important for the next test */
testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.6"); testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.6");
check_rrsigs = 1; check_rrsigs = 1;
testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.7"); testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.7");
check_rrsigs = 0; check_rrsigs = 0;
matches_nolocation = 0; matches_nolocation = 0;
check_formerr_gone = 1; check_formerr_gone = 1;
testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.8"); testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.8");
check_formerr_gone = 0; check_formerr_gone = 0;
check_rrsigs = 1; check_rrsigs = 1;
check_nosameness = 1; check_nosameness = 1;
testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.9"); testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.9");
check_nosameness = 0; check_nosameness = 0;
check_rrsigs = 0; check_rrsigs = 0;

View file

@ -497,65 +497,70 @@ nsec3_hash_test(const char* fname)
sldns_buffer_free(buf); sldns_buffer_free(buf);
} }
#define xstr(s) str(s)
#define str(s) #s
#define SRCDIRSTR xstr(SRCDIR)
void void
verify_test(void) verify_test(void)
{ {
unit_show_feature("signature verify"); unit_show_feature("signature verify");
#ifdef USE_SHA1 #ifdef USE_SHA1
verifytest_file("testdata/test_signatures.1", "20070818005004"); verifytest_file(SRCDIRSTR "/testdata/test_signatures.1", "20070818005004");
#endif #endif
#if defined(USE_DSA) && defined(USE_SHA1) #if defined(USE_DSA) && defined(USE_SHA1)
verifytest_file("testdata/test_signatures.2", "20080414005004"); verifytest_file(SRCDIRSTR "/testdata/test_signatures.2", "20080414005004");
verifytest_file("testdata/test_signatures.3", "20080416005004"); verifytest_file(SRCDIRSTR "/testdata/test_signatures.3", "20080416005004");
verifytest_file("testdata/test_signatures.4", "20080416005004"); verifytest_file(SRCDIRSTR "/testdata/test_signatures.4", "20080416005004");
verifytest_file("testdata/test_signatures.5", "20080416005004"); verifytest_file(SRCDIRSTR "/testdata/test_signatures.5", "20080416005004");
verifytest_file("testdata/test_signatures.6", "20080416005004"); verifytest_file(SRCDIRSTR "/testdata/test_signatures.6", "20080416005004");
verifytest_file("testdata/test_signatures.7", "20070829144150"); verifytest_file(SRCDIRSTR "/testdata/test_signatures.7", "20070829144150");
#endif /* USE_DSA */ #endif /* USE_DSA */
#ifdef USE_SHA1 #ifdef USE_SHA1
verifytest_file("testdata/test_signatures.8", "20070829144150"); verifytest_file(SRCDIRSTR "/testdata/test_signatures.8", "20070829144150");
#endif #endif
#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2) #if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
verifytest_file("testdata/test_sigs.rsasha256", "20070829144150"); verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha256", "20070829144150");
# ifdef USE_SHA1 # ifdef USE_SHA1
verifytest_file("testdata/test_sigs.sha1_and_256", "20070829144150"); verifytest_file(SRCDIRSTR "/testdata/test_sigs.sha1_and_256", "20070829144150");
# endif # endif
verifytest_file("testdata/test_sigs.rsasha256_draft", "20090101000000"); verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha256_draft", "20090101000000");
#endif #endif
#if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2) #if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
verifytest_file("testdata/test_sigs.rsasha512_draft", "20070829144150"); verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha512_draft", "20070829144150");
verifytest_file("testdata/test_signatures.9", "20171215000000"); verifytest_file(SRCDIRSTR "/testdata/test_signatures.9", "20171215000000");
#endif #endif
#ifdef USE_SHA1 #ifdef USE_SHA1
verifytest_file("testdata/test_sigs.hinfo", "20090107100022"); verifytest_file(SRCDIRSTR "/testdata/test_sigs.hinfo", "20090107100022");
verifytest_file("testdata/test_sigs.revoked", "20080414005004"); verifytest_file(SRCDIRSTR "/testdata/test_sigs.revoked", "20080414005004");
#endif #endif
#ifdef USE_GOST #ifdef USE_GOST
if(sldns_key_EVP_load_gost_id()) if(sldns_key_EVP_load_gost_id())
verifytest_file("testdata/test_sigs.gost", "20090807060504"); verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost", "20090807060504");
else printf("Warning: skipped GOST, openssl does not provide gost.\n"); else printf("Warning: skipped GOST, openssl does not provide gost.\n");
#endif #endif
#ifdef USE_ECDSA #ifdef USE_ECDSA
/* test for support in case we use libNSS and ECC is removed */ /* test for support in case we use libNSS and ECC is removed */
if(dnskey_algo_id_is_supported(LDNS_ECDSAP256SHA256)) { if(dnskey_algo_id_is_supported(LDNS_ECDSAP256SHA256)) {
verifytest_file("testdata/test_sigs.ecdsa_p256", "20100908100439"); verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p256", "20100908100439");
verifytest_file("testdata/test_sigs.ecdsa_p384", "20100908100439"); verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p384", "20100908100439");
} }
dstest_file("testdata/test_ds.sha384"); dstest_file(SRCDIRSTR "/testdata/test_ds.sha384");
#endif #endif
#ifdef USE_ED25519 #ifdef USE_ED25519
if(dnskey_algo_id_is_supported(LDNS_ED25519)) { if(dnskey_algo_id_is_supported(LDNS_ED25519)) {
verifytest_file("testdata/test_sigs.ed25519", "20170530140439"); verifytest_file(SRCDIRSTR "/testdata/test_sigs.ed25519", "20170530140439");
} }
#endif #endif
#ifdef USE_ED448 #ifdef USE_ED448
if(dnskey_algo_id_is_supported(LDNS_ED448)) { if(dnskey_algo_id_is_supported(LDNS_ED448)) {
verifytest_file("testdata/test_sigs.ed448", "20180408143630"); verifytest_file(SRCDIRSTR "/testdata/test_sigs.ed448", "20180408143630");
} }
#endif #endif
#ifdef USE_SHA1 #ifdef USE_SHA1
dstest_file("testdata/test_ds.sha1"); dstest_file(SRCDIRSTR "/testdata/test_ds.sha1");
#endif #endif
nsectest(); nsectest();
nsec3_hash_test("testdata/test_nsec3_hash.1"); nsec3_hash_test(SRCDIRSTR "/testdata/test_nsec3_hash.1");
} }

View file

@ -0,0 +1,16 @@
server:
verbosity: 2
# num-threads: 1
interface: 127.0.0.1
port: @PORT@
use-syslog: no
directory: .
pidfile: "unbound.pid"
chroot: ""
username: ""
do-not-query-localhost: no
tcp-idle-timeout: 2
forward-zone:
name: "."
forward-addr: "127.0.0.1@@TOPORT@"

View file

@ -0,0 +1,16 @@
BaseName: tcp_idle_timeout
Version: 1.0
Description: Test tcp-idle-timeout setting.
CreationDate: Thu Jul 12 13:55:00 BST 2018
Maintainer: dr. J. Hague
Category:
Component:
CmdDepends:
Depends:
Help:
Pre: tcp_idle_timeout.pre
Post: tcp_idle_timeout.post
Test: tcp_idle_timeout.test
AuxFiles:
Passed:
Failure:

View file

@ -0,0 +1,10 @@
# #-- tcp_idle_timeout.post --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# source the test var file when it's there
[ -f .tpkg.var.test ] && source .tpkg.var.test
#
# do your teardown here
. ../common.sh
kill_pid $FWD_PID
kill_pid $UNBOUND_PID

View file

@ -0,0 +1,31 @@
# #-- tcp_idle_timeout.pre--#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
. ../common.sh
get_random_port 2
UNBOUND_PORT=$RND_PORT
FWD_PORT=$(($RND_PORT + 1))
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test
# start forwarder
get_ldns_testns
$LDNS_TESTNS -p $FWD_PORT tcp_idle_timeout.testns >fwd.log 2>&1 &
FWD_PID=$!
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
# make config file
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' < tcp_idle_timeout.conf > ub.conf
# start unbound in the background
PRE="../.."
$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
UNBOUND_PID=$!
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
cat .tpkg.var.test
wait_ldns_testns_up fwd.log
wait_unbound_up unbound.log

View file

@ -0,0 +1,63 @@
# #-- tcp_idle_timeout.test --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
if uname | grep MINGW >/dev/null; then
echo "no job control in shell on windows. end test"
exit 0
fi
PRE="../.."
. ../common.sh
get_make
(cd $PRE; $MAKE streamtcp)
# first test a single TCP query with no delay.
echo "> query www.example.com."
$PRE/streamtcp -f 127.0.0.1@$UNBOUND_PORT www.example.com. A IN >outfile 2>&1
if test "$?" -ne 0; then
echo "exit status not OK"
echo "> cat logfiles"
cat outfile
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
else
echo "exit status OK"
fi
echo "> cat logfiles"
cat outfile
cat fwd.log
cat unbound.log
echo "> check answer"
if grep "10.20.30.40" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
# now test query with delay should fail.
echo "> query www.example.com."
$PRE/streamtcp -d 4 -f 127.0.0.1@$UNBOUND_PORT www.example.com. A IN >outfile 2>&1
if test "$?" -eq 0; then
echo "exit status OK"
echo "> cat logfiles"
cat outfile
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
else
echo "exit status not OK"
fi
echo "> cat logfiles"
cat outfile
cat fwd.log
cat unbound.log
echo "OK"
exit 0

View file

@ -0,0 +1,42 @@
; nameserver test file
$ORIGIN example.com.
$TTL 3600
ENTRY_BEGIN
MATCH UDP opcode qtype qname
REPLY QR AA NOERROR TC
ADJUST copy_id
SECTION QUESTION
www IN A
ENTRY_END
ENTRY_BEGIN
MATCH TCP opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id sleep=2
SECTION QUESTION
www IN A
SECTION ANSWER
www IN A 10.20.30.40
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
www2 IN A
SECTION ANSWER
www2 IN A 10.20.30.42
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
www3 IN A
SECTION ANSWER
www3 IN A 10.20.30.43
ENTRY_END

View file

@ -104,6 +104,7 @@ config_create(void)
cfg->udp_upstream_without_downstream = 0; cfg->udp_upstream_without_downstream = 0;
cfg->tcp_mss = 0; cfg->tcp_mss = 0;
cfg->outgoing_tcp_mss = 0; cfg->outgoing_tcp_mss = 0;
cfg->tcp_idle_timeout = 30 * 1000; /* 30s in millisecs */
cfg->ssl_service_key = NULL; cfg->ssl_service_key = NULL;
cfg->ssl_service_pem = NULL; cfg->ssl_service_pem = NULL;
cfg->ssl_port = UNBOUND_DNS_OVER_TLS_PORT; cfg->ssl_port = UNBOUND_DNS_OVER_TLS_PORT;
@ -455,6 +456,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
udp_upstream_without_downstream) udp_upstream_without_downstream)
else S_NUMBER_NONZERO("tcp-mss:", tcp_mss) else S_NUMBER_NONZERO("tcp-mss:", tcp_mss)
else S_NUMBER_NONZERO("outgoing-tcp-mss:", outgoing_tcp_mss) else S_NUMBER_NONZERO("outgoing-tcp-mss:", outgoing_tcp_mss)
else S_NUMBER_NONZERO("tcp-idle-timeout:", tcp_idle_timeout)
else S_YNO("ssl-upstream:", ssl_upstream) else S_YNO("ssl-upstream:", ssl_upstream)
else S_STR("ssl-service-key:", ssl_service_key) else S_STR("ssl-service-key:", ssl_service_key)
else S_STR("ssl-service-pem:", ssl_service_pem) else S_STR("ssl-service-pem:", ssl_service_pem)
@ -878,6 +880,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "udp-upstream-without-downstream", udp_upstream_without_downstream) else O_YNO(opt, "udp-upstream-without-downstream", udp_upstream_without_downstream)
else O_DEC(opt, "tcp-mss", tcp_mss) else O_DEC(opt, "tcp-mss", tcp_mss)
else O_DEC(opt, "outgoing-tcp-mss", outgoing_tcp_mss) else O_DEC(opt, "outgoing-tcp-mss", outgoing_tcp_mss)
else O_DEC(opt, "tcp-idle-timeout", tcp_idle_timeout)
else O_YNO(opt, "ssl-upstream", ssl_upstream) else O_YNO(opt, "ssl-upstream", ssl_upstream)
else O_STR(opt, "ssl-service-key", ssl_service_key) else O_STR(opt, "ssl-service-key", ssl_service_key)
else O_STR(opt, "ssl-service-pem", ssl_service_pem) else O_STR(opt, "ssl-service-pem", ssl_service_pem)

View file

@ -99,6 +99,8 @@ struct config_file {
int tcp_mss; int tcp_mss;
/** maximum segment size of tcp socket for outgoing queries */ /** maximum segment size of tcp socket for outgoing queries */
int outgoing_tcp_mss; int outgoing_tcp_mss;
/** tcp idle timeout */
int tcp_idle_timeout;
/** private key file for dnstcp-ssl service (enabled if not NULL) */ /** private key file for dnstcp-ssl service (enabled if not NULL) */
char* ssl_service_key; char* ssl_service_key;

View file

@ -233,6 +233,7 @@ do-tcp{COLON} { YDVAR(1, VAR_DO_TCP) }
tcp-upstream{COLON} { YDVAR(1, VAR_TCP_UPSTREAM) } tcp-upstream{COLON} { YDVAR(1, VAR_TCP_UPSTREAM) }
tcp-mss{COLON} { YDVAR(1, VAR_TCP_MSS) } tcp-mss{COLON} { YDVAR(1, VAR_TCP_MSS) }
outgoing-tcp-mss{COLON} { YDVAR(1, VAR_OUTGOING_TCP_MSS) } outgoing-tcp-mss{COLON} { YDVAR(1, VAR_OUTGOING_TCP_MSS) }
tcp-idle-timeout{COLON} { YDVAR(1, VAR_TCP_IDLE_TIMEOUT) }
ssl-upstream{COLON} { YDVAR(1, VAR_SSL_UPSTREAM) } ssl-upstream{COLON} { YDVAR(1, VAR_SSL_UPSTREAM) }
tls-upstream{COLON} { YDVAR(1, VAR_SSL_UPSTREAM) } tls-upstream{COLON} { YDVAR(1, VAR_SSL_UPSTREAM) }
ssl-service-key{COLON} { YDVAR(1, VAR_SSL_SERVICE_KEY) } ssl-service-key{COLON} { YDVAR(1, VAR_SSL_SERVICE_KEY) }

View file

@ -72,7 +72,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_SERVER VAR_VERBOSITY VAR_NUM_THREADS VAR_PORT %token VAR_SERVER VAR_VERBOSITY VAR_NUM_THREADS VAR_PORT
%token VAR_OUTGOING_RANGE VAR_INTERFACE %token VAR_OUTGOING_RANGE VAR_INTERFACE
%token VAR_DO_IP4 VAR_DO_IP6 VAR_PREFER_IP6 VAR_DO_UDP VAR_DO_TCP %token VAR_DO_IP4 VAR_DO_IP6 VAR_PREFER_IP6 VAR_DO_UDP VAR_DO_TCP
%token VAR_TCP_MSS VAR_OUTGOING_TCP_MSS %token VAR_TCP_MSS VAR_OUTGOING_TCP_MSS VAR_TCP_IDLE_TIMEOUT
%token VAR_CHROOT VAR_USERNAME VAR_DIRECTORY VAR_LOGFILE VAR_PIDFILE %token VAR_CHROOT VAR_USERNAME VAR_DIRECTORY VAR_LOGFILE VAR_PIDFILE
%token VAR_MSG_CACHE_SIZE VAR_MSG_CACHE_SLABS VAR_NUM_QUERIES_PER_THREAD %token VAR_MSG_CACHE_SIZE VAR_MSG_CACHE_SLABS VAR_NUM_QUERIES_PER_THREAD
%token VAR_RRSET_CACHE_SIZE VAR_RRSET_CACHE_SLABS VAR_OUTGOING_NUM_TCP %token VAR_RRSET_CACHE_SIZE VAR_RRSET_CACHE_SLABS VAR_OUTGOING_NUM_TCP
@ -180,7 +180,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_outgoing_range | server_do_ip4 | server_outgoing_range | server_do_ip4 |
server_do_ip6 | server_prefer_ip6 | server_do_ip6 | server_prefer_ip6 |
server_do_udp | server_do_tcp | server_do_udp | server_do_tcp |
server_tcp_mss | server_outgoing_tcp_mss | server_tcp_mss | server_outgoing_tcp_mss | server_tcp_idle_timeout |
server_interface | server_chroot | server_username | server_interface | server_chroot | server_username |
server_directory | server_logfile | server_pidfile | server_directory | server_logfile | server_pidfile |
server_msg_cache_size | server_msg_cache_slabs | server_msg_cache_size | server_msg_cache_slabs |
@ -631,6 +631,19 @@ server_outgoing_tcp_mss: VAR_OUTGOING_TCP_MSS STRING_ARG
free($2); free($2);
} }
; ;
server_tcp_idle_timeout: VAR_TCP_IDLE_TIMEOUT STRING_ARG
{
OUTYY(("P(server_tcp_idle_timeout:%s)\n", $2));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("number expected");
else if (atoi($2) > 120000)
cfg_parser->cfg->tcp_idle_timeout = 120000;
else if (atoi($2) < 1)
cfg_parser->cfg->tcp_idle_timeout = 1;
else cfg_parser->cfg->tcp_idle_timeout = atoi($2);
free($2);
}
;
server_tcp_upstream: VAR_TCP_UPSTREAM STRING_ARG server_tcp_upstream: VAR_TCP_UPSTREAM STRING_ARG
{ {
OUTYY(("P(server_tcp_upstream:%s)\n", $2)); OUTYY(("P(server_tcp_upstream:%s)\n", $2));

View file

@ -82,7 +82,7 @@
# endif # endif
#endif #endif
/** The TCP reading or writing query timeout in milliseconds */ /** The TCP writing query timeout in milliseconds */
#define TCP_QUERY_TIMEOUT 120000 #define TCP_QUERY_TIMEOUT 120000
/** The TCP timeout in msec for fast queries, above half are used */ /** The TCP timeout in msec for fast queries, above half are used */
#define TCP_QUERY_TIMEOUT_FAST 200 #define TCP_QUERY_TIMEOUT_FAST 200
@ -737,7 +737,6 @@ setup_tcp_handler(struct comm_point* c, int fd, int cur, int max)
#endif #endif
c->tcp_is_reading = 1; c->tcp_is_reading = 1;
c->tcp_byte_count = 0; c->tcp_byte_count = 0;
c->tcp_timeout_msec = TCP_QUERY_TIMEOUT;
/* if more than half the tcp handlers are in use, use a shorter /* if more than half the tcp handlers are in use, use a shorter
* timeout for this TCP connection, we need to make space for * timeout for this TCP connection, we need to make space for
* other connections to be able to get attention */ * other connections to be able to get attention */
@ -2525,6 +2524,7 @@ comm_point_create_tcp_handler(struct comm_base *base,
c->tcp_is_reading = 0; c->tcp_is_reading = 0;
c->tcp_byte_count = 0; c->tcp_byte_count = 0;
c->tcp_parent = parent; c->tcp_parent = parent;
c->tcp_timeout_msec = parent->tcp_timeout_msec;
c->max_tcp_count = 0; c->max_tcp_count = 0;
c->cur_tcp_count = 0; c->cur_tcp_count = 0;
c->tcp_handlers = NULL; c->tcp_handlers = NULL;
@ -2565,7 +2565,8 @@ comm_point_create_tcp_handler(struct comm_base *base,
} }
struct comm_point* struct comm_point*
comm_point_create_tcp(struct comm_base *base, int fd, int num, size_t bufsize, comm_point_create_tcp(struct comm_base *base, int fd, int num,
int idle_timeout, size_t bufsize,
comm_point_callback_type* callback, void* callback_arg) comm_point_callback_type* callback, void* callback_arg)
{ {
struct comm_point* c = (struct comm_point*)calloc(1, struct comm_point* c = (struct comm_point*)calloc(1,
@ -2587,6 +2588,7 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num, size_t bufsize,
c->timeout = NULL; c->timeout = NULL;
c->tcp_is_reading = 0; c->tcp_is_reading = 0;
c->tcp_byte_count = 0; c->tcp_byte_count = 0;
c->tcp_timeout_msec = idle_timeout;
c->tcp_parent = NULL; c->tcp_parent = NULL;
c->max_tcp_count = num; c->max_tcp_count = num;
c->cur_tcp_count = 0; c->cur_tcp_count = 0;
@ -2665,6 +2667,7 @@ comm_point_create_tcp_out(struct comm_base *base, size_t bufsize,
c->timeout = NULL; c->timeout = NULL;
c->tcp_is_reading = 0; c->tcp_is_reading = 0;
c->tcp_byte_count = 0; c->tcp_byte_count = 0;
c->tcp_timeout_msec = TCP_QUERY_TIMEOUT;
c->tcp_parent = NULL; c->tcp_parent = NULL;
c->max_tcp_count = 0; c->max_tcp_count = 0;
c->cur_tcp_count = 0; c->cur_tcp_count = 0;

View file

@ -443,6 +443,7 @@ struct comm_point* comm_point_create_udp_ancil(struct comm_base* base,
* @param fd: file descriptor of open TCP socket set to listen nonblocking. * @param fd: file descriptor of open TCP socket set to listen nonblocking.
* @param num: becomes max_tcp_count, the routine allocates that * @param num: becomes max_tcp_count, the routine allocates that
* many tcp handler commpoints. * many tcp handler commpoints.
* @param idle_timeout: TCP idle timeout in ms.
* @param bufsize: size of buffer to create for handlers. * @param bufsize: size of buffer to create for handlers.
* @param callback: callback function pointer for TCP handlers. * @param callback: callback function pointer for TCP handlers.
* @param callback_arg: will be passed to your callback function. * @param callback_arg: will be passed to your callback function.
@ -452,7 +453,7 @@ struct comm_point* comm_point_create_udp_ancil(struct comm_base* base,
* Inits timeout to NULL. All handlers are on the free list. * Inits timeout to NULL. All handlers are on the free list.
*/ */
struct comm_point* comm_point_create_tcp(struct comm_base* base, struct comm_point* comm_point_create_tcp(struct comm_base* base,
int fd, int num, size_t bufsize, int fd, int num, int idle_timeout, size_t bufsize,
comm_point_callback_type* callback, void* callback_arg); comm_point_callback_type* callback, void* callback_arg);
/** /**