CC=@CC@
CPPFLAGS=-I. @CPPFLAGS@
PYTHON_CPPFLAGS=-I. @PYTHON_CPPFLAGS@
-CFLAGS=@CFLAGS@
+CFLAGS=-DSRCDIR=$(srcdir) @CFLAGS@
LDFLAGS=@LDFLAGS@
LIBS=@LIBS@
LIBOBJS=@LIBOBJS@
test: unittest$(EXEEXT) testbound$(EXEEXT)
./unittest$(EXEEXT)
./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
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
lib: libunbound.la unbound.h
worker->comsig = NULL;
}
worker->front = listen_create(worker->base, ports,
- cfg->msg_buffer_size, (int)cfg->incoming_num_tcp,
- worker->daemon->listen_sslctx, dtenv, worker_handle_request,
- worker);
+ cfg->msg_buffer_size, (int)cfg->incoming_num_tcp,
+ cfg->tcp_idle_timeout, worker->daemon->listen_sslctx,
+ dtenv, worker_handle_request, worker);
if(!worker->front) {
log_err("could not create listening sockets");
worker_delete(worker);
+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
- Fix #4136: insufficiency from mismatch of FLEX capability between
released tarball and build host.
Default is system default MSS determined by interface MTU and
negotiation between Unbound and other servers.
.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>
Enable or disable whether the upstream queries use TCP only for transport.
Default is no. Useful in tunneling scenarios.
struct listen_dnsport*
listen_create(struct comm_base* base, struct listen_port* ports,
- size_t bufsize, int tcp_accept_count, void* sslctx,
- struct dt_env* dtenv, comm_point_callback_type* cb, void *cb_arg)
+ size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
+ void* sslctx, struct dt_env* dtenv,
+ comm_point_callback_type* cb, void *cb_arg)
{
struct listen_dnsport* front = (struct listen_dnsport*)
malloc(sizeof(struct listen_dnsport));
else if(ports->ftype == listen_type_tcp ||
ports->ftype == listen_type_tcp_dnscrypt)
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) {
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;
} else if(ports->ftype == listen_type_udpancil ||
ports->ftype == listen_type_udpancil_dnscrypt)
* @return: the malloced listening structure, ready for use. NULL on error.
*/
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* cb_arg);
struct listen_dnsport*
listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
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),
comm_point_callback_type* cb, void* cb_arg)
{
#include <getopt.h>
#endif
#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
#include "util/locks.h"
#include "util/log.h"
#include "util/net_help.h"
printf("-f server what ipaddr@portnr to send the queries to\n");
printf("-u use UDP. No retries are attempted.\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("-h this help text\n");
exit(1);
/** send the TCP queries and print answers */
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);
int fd = open_svr(svr, udp);
}
}
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]);
write_q(fd, udp, ssl, buf, (uint16_t)get_random(), qs[i],
qs[i+1], qs[i+2]);
int udp = 0;
int noanswer = 0;
int usessl = 0;
+ int delay = 0;
#ifdef USE_WINSOCK
WSADATA wsa_data;
if(argc == 1) {
usage(argv);
}
- while( (c=getopt(argc, argv, "f:hnsu")) != -1) {
+ while( (c=getopt(argc, argv, "f:hnsud:")) != -1) {
switch(c) {
case 'f':
svr = optarg;
case 's':
usessl = 1;
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 '?':
default:
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
#endif
}
- send_em(svr, udp, usessl, noanswer, argc, argv);
+ send_em(svr, udp, usessl, noanswer, delay, argc, argv);
checklock_stop();
#ifdef USE_WINSOCK
WSACleanup();
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 */
static void
rr_tests(void)
{
- rr_test_file("testdata/test_ldnsrr.1", "testdata/test_ldnsrr.c1");
- rr_test_file("testdata/test_ldnsrr.2", "testdata/test_ldnsrr.c2");
- rr_test_file("testdata/test_ldnsrr.3", "testdata/test_ldnsrr.c3");
- rr_test_file("testdata/test_ldnsrr.4", "testdata/test_ldnsrr.c4");
- rr_test_file("testdata/test_ldnsrr.5", "testdata/test_ldnsrr.c5");
+ rr_test_file(SRCDIRSTR "/testdata/test_ldnsrr.1",
+ SRCDIRSTR "/testdata/test_ldnsrr.c1");
+ rr_test_file(SRCDIRSTR "/testdata/test_ldnsrr.2",
+ SRCDIRSTR "/testdata/test_ldnsrr.c2");
+ 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
fclose(in);
}
+#define xstr(s) str(s)
+#define str(s) #s
+
+#define SRCDIRSTR xstr(SRCDIR)
+
void msgparse_test(void)
{
time_t origttl = MAX_NEG_TTL;
unit_show_feature("message parse");
simpletest(pkt, &alloc, out);
/* plain hex dumps, like pcat */
- testfromfile(pkt, &alloc, out, "testdata/test_packets.1");
- testfromfile(pkt, &alloc, out, "testdata/test_packets.2");
- testfromfile(pkt, &alloc, out, "testdata/test_packets.3");
+ testfromfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.1");
+ testfromfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.2");
+ testfromfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.3");
/* like from drill -w - */
- testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.4");
- testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.5");
+ testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.4");
+ testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.5");
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;
- testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.7");
+ testfromdrillfile(pkt, &alloc, out, SRCDIRSTR "/testdata/test_packets.7");
check_rrsigs = 0;
matches_nolocation = 0;
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_rrsigs = 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_rrsigs = 0;
sldns_buffer_free(buf);
}
+#define xstr(s) str(s)
+#define str(s) #s
+
+#define SRCDIRSTR xstr(SRCDIR)
+
void
verify_test(void)
{
unit_show_feature("signature verify");
#ifdef USE_SHA1
- verifytest_file("testdata/test_signatures.1", "20070818005004");
+ verifytest_file(SRCDIRSTR "/testdata/test_signatures.1", "20070818005004");
#endif
#if defined(USE_DSA) && defined(USE_SHA1)
- verifytest_file("testdata/test_signatures.2", "20080414005004");
- verifytest_file("testdata/test_signatures.3", "20080416005004");
- verifytest_file("testdata/test_signatures.4", "20080416005004");
- verifytest_file("testdata/test_signatures.5", "20080416005004");
- verifytest_file("testdata/test_signatures.6", "20080416005004");
- verifytest_file("testdata/test_signatures.7", "20070829144150");
+ verifytest_file(SRCDIRSTR "/testdata/test_signatures.2", "20080414005004");
+ verifytest_file(SRCDIRSTR "/testdata/test_signatures.3", "20080416005004");
+ verifytest_file(SRCDIRSTR "/testdata/test_signatures.4", "20080416005004");
+ verifytest_file(SRCDIRSTR "/testdata/test_signatures.5", "20080416005004");
+ verifytest_file(SRCDIRSTR "/testdata/test_signatures.6", "20080416005004");
+ verifytest_file(SRCDIRSTR "/testdata/test_signatures.7", "20070829144150");
#endif /* USE_DSA */
#ifdef USE_SHA1
- verifytest_file("testdata/test_signatures.8", "20070829144150");
+ verifytest_file(SRCDIRSTR "/testdata/test_signatures.8", "20070829144150");
#endif
#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
- verifytest_file("testdata/test_sigs.sha1_and_256", "20070829144150");
+ verifytest_file(SRCDIRSTR "/testdata/test_sigs.sha1_and_256", "20070829144150");
# endif
- verifytest_file("testdata/test_sigs.rsasha256_draft", "20090101000000");
+ verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha256_draft", "20090101000000");
#endif
#if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
- verifytest_file("testdata/test_sigs.rsasha512_draft", "20070829144150");
- verifytest_file("testdata/test_signatures.9", "20171215000000");
+ verifytest_file(SRCDIRSTR "/testdata/test_sigs.rsasha512_draft", "20070829144150");
+ verifytest_file(SRCDIRSTR "/testdata/test_signatures.9", "20171215000000");
#endif
#ifdef USE_SHA1
- verifytest_file("testdata/test_sigs.hinfo", "20090107100022");
- verifytest_file("testdata/test_sigs.revoked", "20080414005004");
+ verifytest_file(SRCDIRSTR "/testdata/test_sigs.hinfo", "20090107100022");
+ verifytest_file(SRCDIRSTR "/testdata/test_sigs.revoked", "20080414005004");
#endif
#ifdef USE_GOST
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");
#endif
#ifdef USE_ECDSA
/* test for support in case we use libNSS and ECC is removed */
if(dnskey_algo_id_is_supported(LDNS_ECDSAP256SHA256)) {
- verifytest_file("testdata/test_sigs.ecdsa_p256", "20100908100439");
- verifytest_file("testdata/test_sigs.ecdsa_p384", "20100908100439");
+ verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p256", "20100908100439");
+ verifytest_file(SRCDIRSTR "/testdata/test_sigs.ecdsa_p384", "20100908100439");
}
- dstest_file("testdata/test_ds.sha384");
+ dstest_file(SRCDIRSTR "/testdata/test_ds.sha384");
#endif
#ifdef USE_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
#ifdef USE_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
#ifdef USE_SHA1
- dstest_file("testdata/test_ds.sha1");
+ dstest_file(SRCDIRSTR "/testdata/test_ds.sha1");
#endif
nsectest();
- nsec3_hash_test("testdata/test_nsec3_hash.1");
+ nsec3_hash_test(SRCDIRSTR "/testdata/test_nsec3_hash.1");
}
--- /dev/null
+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@"
--- /dev/null
+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:
--- /dev/null
+# #-- 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
--- /dev/null
+# #-- 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
+
--- /dev/null
+# #-- 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
--- /dev/null
+; 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
+
cfg->udp_upstream_without_downstream = 0;
cfg->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_pem = NULL;
cfg->ssl_port = UNBOUND_DNS_OVER_TLS_PORT;
udp_upstream_without_downstream)
else S_NUMBER_NONZERO("tcp-mss:", 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_STR("ssl-service-key:", ssl_service_key)
else S_STR("ssl-service-pem:", ssl_service_pem)
else O_YNO(opt, "udp-upstream-without-downstream", udp_upstream_without_downstream)
else O_DEC(opt, "tcp-mss", 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_STR(opt, "ssl-service-key", ssl_service_key)
else O_STR(opt, "ssl-service-pem", ssl_service_pem)
int tcp_mss;
/** maximum segment size of tcp socket for outgoing queries */
int outgoing_tcp_mss;
+ /** tcp idle timeout */
+ int tcp_idle_timeout;
/** private key file for dnstcp-ssl service (enabled if not NULL) */
char* ssl_service_key;
tcp-upstream{COLON} { YDVAR(1, VAR_TCP_UPSTREAM) }
tcp-mss{COLON} { YDVAR(1, VAR_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) }
tls-upstream{COLON} { YDVAR(1, VAR_SSL_UPSTREAM) }
ssl-service-key{COLON} { YDVAR(1, VAR_SSL_SERVICE_KEY) }
%token VAR_SERVER VAR_VERBOSITY VAR_NUM_THREADS VAR_PORT
%token VAR_OUTGOING_RANGE VAR_INTERFACE
%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_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
server_outgoing_range | server_do_ip4 |
server_do_ip6 | server_prefer_ip6 |
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_directory | server_logfile | server_pidfile |
server_msg_cache_size | server_msg_cache_slabs |
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
{
OUTYY(("P(server_tcp_upstream:%s)\n", $2));
# endif
#endif
-/** The TCP reading or writing query timeout in milliseconds */
+/** The TCP writing query timeout in milliseconds */
#define TCP_QUERY_TIMEOUT 120000
/** The TCP timeout in msec for fast queries, above half are used */
#define TCP_QUERY_TIMEOUT_FAST 200
#endif
c->tcp_is_reading = 1;
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
* timeout for this TCP connection, we need to make space for
* other connections to be able to get attention */
c->tcp_is_reading = 0;
c->tcp_byte_count = 0;
c->tcp_parent = parent;
+ c->tcp_timeout_msec = parent->tcp_timeout_msec;
c->max_tcp_count = 0;
c->cur_tcp_count = 0;
c->tcp_handlers = NULL;
}
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)
{
struct comm_point* c = (struct comm_point*)calloc(1,
c->timeout = NULL;
c->tcp_is_reading = 0;
c->tcp_byte_count = 0;
+ c->tcp_timeout_msec = idle_timeout;
c->tcp_parent = NULL;
c->max_tcp_count = num;
c->cur_tcp_count = 0;
c->timeout = NULL;
c->tcp_is_reading = 0;
c->tcp_byte_count = 0;
+ c->tcp_timeout_msec = TCP_QUERY_TIMEOUT;
c->tcp_parent = NULL;
c->max_tcp_count = 0;
c->cur_tcp_count = 0;
* @param fd: file descriptor of open TCP socket set to listen nonblocking.
* @param num: becomes max_tcp_count, the routine allocates that
* many tcp handler commpoints.
+ * @param idle_timeout: TCP idle timeout in ms.
* @param bufsize: size of buffer to create for handlers.
* @param callback: callback function pointer for TCP handlers.
* @param callback_arg: will be passed to your callback function.
* Inits timeout to NULL. All handlers are on the free list.
*/
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);
/**