aboutsummaryrefslogtreecommitdiff
path: root/testcode
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2022-10-16 19:24:20 +0000
committerCy Schubert <cy@FreeBSD.org>2022-10-16 19:24:20 +0000
commit643f9a0581e8aac7eb790ced1164748939829826 (patch)
tree426d366252d838c8c61b439342ab32eccd181425 /testcode
parent0dde6f4f8e604df8c6fbdab8b4aadb5ddf80c76f (diff)
Diffstat (limited to 'testcode')
-rw-r--r--testcode/delayer.c2
-rwxr-xr-xtestcode/do-tests.sh2
-rw-r--r--testcode/fake_event.c21
-rwxr-xr-xtestcode/mini_tdir.sh38
-rwxr-xr-xtestcode/mini_tpkg.sh128
-rw-r--r--testcode/perf.c2
-rw-r--r--testcode/replay.c11
-rw-r--r--testcode/streamtcp.c128
-rw-r--r--testcode/unitecs.c6
-rw-r--r--testcode/unittcpreuse.c253
10 files changed, 407 insertions, 184 deletions
diff --git a/testcode/delayer.c b/testcode/delayer.c
index e915961f5ae7..647a4e24c469 100644
--- a/testcode/delayer.c
+++ b/testcode/delayer.c
@@ -974,7 +974,7 @@ service(const char* bind_str, int bindport, const char* serv_str,
dl_tv_add(&reuse, &delay);
if(reuse.tv_sec == 0)
reuse.tv_sec = 1;
- if(!extstrtoaddr(serv_str, &srv_addr, &srv_len)) {
+ if(!extstrtoaddr(serv_str, &srv_addr, &srv_len, UNBOUND_DNS_PORT)) {
printf("cannot parse forward address: %s\n", serv_str);
exit(1);
}
diff --git a/testcode/do-tests.sh b/testcode/do-tests.sh
index 2a1cfc4c96e8..6599f9f66594 100755
--- a/testcode/do-tests.sh
+++ b/testcode/do-tests.sh
@@ -16,6 +16,7 @@ NEED_WHOAMI='07-confroot.tdir'
NEED_IPV6='fwd_ancil.tdir fwd_tcp_tc6.tdir stub_udp6.tdir edns_cache.tdir'
NEED_NOMINGW='tcp_sigpipe.tdir 07-confroot.tdir 08-host-lib.tdir fwd_ancil.tdir'
NEED_DNSCRYPT_PROXY='dnscrypt_queries.tdir dnscrypt_queries_chacha.tdir'
+NEED_UNSHARE='acl_interface.tdir proxy_protocol.tdir'
# test if dig and ldns-testns are available.
test_tool_avail "dig"
@@ -50,6 +51,7 @@ for test in `ls -d *.tdir`; do
skip_if_in_list $test "$NEED_NC" "nc"
skip_if_in_list $test "$NEED_WHOAMI" "whoami"
skip_if_in_list $test "$NEED_DNSCRYPT_PROXY" "dnscrypt-proxy"
+ skip_if_in_list $test "$NEED_UNSHARE" "unshare"
if echo $NEED_IPV6 | grep $test >/dev/null; then
if test "$HAVE_IPV6" = no; then
diff --git a/testcode/fake_event.c b/testcode/fake_event.c
index be06a4721c21..efb22a6fb634 100644
--- a/testcode/fake_event.c
+++ b/testcode/fake_event.c
@@ -384,8 +384,8 @@ answer_callback_from_entry(struct replay_runtime* runtime,
fill_buffer_with_reply(c.buffer, entry, pend->pkt, pend->pkt_len,
pend->tcp_pkt_counter);
repinfo.c = &c;
- repinfo.addrlen = pend->addrlen;
- memcpy(&repinfo.addr, &pend->addr, pend->addrlen);
+ repinfo.remote_addrlen = pend->addrlen;
+ memcpy(&repinfo.remote_addr, &pend->addr, pend->addrlen);
if(!pend->serviced) {
if(entry && entry->reply_list->next &&
pend->tcp_pkt_counter < count_reply_packets(entry)) {
@@ -415,7 +415,7 @@ answer_check_it(struct replay_runtime* runtime)
tr = transport_udp;
if((runtime->now->addrlen == 0 || sockaddr_cmp(
&runtime->now->addr, runtime->now->addrlen,
- &ans->repinfo.addr, ans->repinfo.addrlen) == 0) &&
+ &ans->repinfo.remote_addr, ans->repinfo.remote_addrlen) == 0) &&
find_match(runtime->now->match, ans->pkt,
ans->pkt_len, tr)) {
log_info("testbound matched event entry from line %d",
@@ -453,10 +453,12 @@ fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
repinfo.c = (struct comm_point*)calloc(1, sizeof(struct comm_point));
if(!repinfo.c)
fatal_exit("out of memory in fake_front_query");
- repinfo.addrlen = (socklen_t)sizeof(struct sockaddr_in);
+ repinfo.remote_addrlen = (socklen_t)sizeof(struct sockaddr_in);
if(todo->addrlen != 0) {
- repinfo.addrlen = todo->addrlen;
- memcpy(&repinfo.addr, &todo->addr, todo->addrlen);
+ repinfo.remote_addrlen = todo->addrlen;
+ memcpy(&repinfo.remote_addr, &todo->addr, todo->addrlen);
+ repinfo.client_addrlen = todo->addrlen;
+ memcpy(&repinfo.client_addr, &todo->addr, todo->addrlen);
}
repinfo.c->fd = -1;
repinfo.c->ev = (struct internal_event*)runtime;
@@ -510,8 +512,8 @@ fake_pending_callback(struct replay_runtime* runtime,
p->pkt_len, p->tcp_pkt_counter);
}
repinfo.c = &c;
- repinfo.addrlen = p->addrlen;
- memcpy(&repinfo.addr, &p->addr, p->addrlen);
+ repinfo.remote_addrlen = p->addrlen;
+ memcpy(&repinfo.remote_addr, &p->addr, p->addrlen);
if(!p->serviced) {
if(todo->match && todo->match->reply_list->next && !error &&
p->tcp_pkt_counter < count_reply_packets(todo->match)) {
@@ -1344,7 +1346,7 @@ struct listen_port* listening_ports_open(struct config_file* ATTR_UNUSED(cfg),
char** ATTR_UNUSED(ifs), int ATTR_UNUSED(num_ifs),
int* ATTR_UNUSED(reuseport))
{
- return calloc(1, 1);
+ return calloc(1, sizeof(struct listen_port));
}
void listening_ports_free(struct listen_port* list)
@@ -1663,6 +1665,7 @@ int create_udp_sock(int ATTR_UNUSED(family), int ATTR_UNUSED(socktype),
struct comm_point* comm_point_create_udp(struct comm_base *ATTR_UNUSED(base),
int ATTR_UNUSED(fd), sldns_buffer* ATTR_UNUSED(buffer),
+ int ATTR_UNUSED(pp2_enabled),
comm_point_callback_type* ATTR_UNUSED(callback),
void* ATTR_UNUSED(callback_arg),
struct unbound_socket* ATTR_UNUSED(socket))
diff --git a/testcode/mini_tdir.sh b/testcode/mini_tdir.sh
index 6bbece8d9368..624ecdf7fe5b 100755
--- a/testcode/mini_tdir.sh
+++ b/testcode/mini_tdir.sh
@@ -8,6 +8,7 @@ fi
# This will keep the temporary directory around and return 1 when the test failed.
DEBUG=0
+test -n "$DEBUG_TDIR" && DEBUG=1
quiet=0
if test "$1" = "-q"; then
@@ -17,9 +18,9 @@ fi
if test "$1" = "clean"; then
if test $quiet = 0; then
- echo "rm -f result.* .done* .tdir.var.master .tdir.var.test"
+ echo "rm -f result.* .done* .skip* .tdir.var.master .tdir.var.test"
fi
- rm -f result.* .done* .tdir.var.master .tdir.var.test
+ rm -f result.* .done* .skip* .tdir.var.master .tdir.var.test
exit 0
fi
if test "$1" = "fake"; then
@@ -54,12 +55,15 @@ if test "$1" = "-f" && test "$2" = "report"; then
echo "** PASSED ** $timelen $name: $desc"
pass=`expr $pass + 1`
fi
+ elif test -f ".skip-$name"; then
+ echo ".. SKIPPED.. $timelen $name: $desc"
+ skip=`expr $skip + 1`
else
if test -f "result.$name"; then
echo "!! FAILED !! $timelen $name: $desc"
fail=`expr $fail + 1`
else
- echo ".> SKIPPED<< $timelen $name: $desc"
+ echo ".. SKIPPED.. $timelen $name: $desc"
skip=`expr $skip + 1`
fi
fi
@@ -81,11 +85,17 @@ if test "$1" = "report" || test "$2" = "report"; then
if test $quiet = 0; then
echo "** PASSED ** : $name"
fi
+ elif test -f ".skip-$name"; then
+ if test $quiet = 0; then
+ echo ".. SKIPPED.. : $name"
+ fi
else
if test -f "result.$name"; then
echo "!! FAILED !! : $name"
else
- echo ">> SKIPPED<< : $name"
+ if test $quiet = 0; then
+ echo ".. SKIPPED.. : $name"
+ fi
fi
fi
done
@@ -116,6 +126,7 @@ name=`basename $1 .tdir`
dir=$name.$$
result=result.$name
done=.done-$name
+skip=.skip-$name
success="no"
if test -x "`which bash`"; then
shell="bash"
@@ -124,8 +135,8 @@ else
fi
# check already done
-if test -f .done-$name; then
- echo "minitdir .done-$name exists. skip test."
+if test -f $done; then
+ echo "minitdir $done exists. skip test."
exit 0
fi
@@ -151,11 +162,16 @@ if test -f $name.pre; then
fi
echo "minitdir exe $name.pre" >> $result
$shell $name.pre $args >> $result
- if test $? -ne 0; then
+ exit_value=$?
+ if test $exit_value -eq 3; then
+ echo "$name: SKIPPED" >> $result
+ echo "$name: SKIPPED" > ../$skip
+ echo "$name: SKIPPED"
+ elif test $exit_value -ne 0; then
echo "Warning: $name.pre did not exit successfully"
fi
fi
-if test -f $name.test; then
+if test -f $name.test -a ! -f ../$skip; then
if test $quiet = 0; then
echo "minitdir exe $name.test"
fi
@@ -167,14 +183,14 @@ if test -f $name.test; then
success="no"
else
echo "$name: PASSED" >> $result
- echo "$name: PASSED" > ../.done-$name
+ echo "$name: PASSED" > ../$done
if test $quiet = 0; then
echo "$name: PASSED"
fi
success="yes"
fi
fi
-if test -f $name.post; then
+if test -f $name.post -a ! -f ../$skip; then
if test $quiet = 0; then
echo "minitdir exe $name.post"
fi
@@ -198,7 +214,7 @@ if test $DEBUG -eq 0; then
rm -rf $dir
fi
else
- if test $success == "no"; then
+ if test $success = "no"; then
exit 1
fi
exit 0
diff --git a/testcode/mini_tpkg.sh b/testcode/mini_tpkg.sh
deleted file mode 100755
index ebf27a7d48a1..000000000000
--- a/testcode/mini_tpkg.sh
+++ /dev/null
@@ -1,128 +0,0 @@
-# tpkg that only exes the files.
-args="../.."
-if test "$1" = "-a"; then
- args=$2
- shift
- shift
-fi
-
-if test "$1" = "clean"; then
- echo "rm -f result.* .done* .tpkg.var.master .tpkg.var.test"
- rm -f result.* .done* .tpkg.var.master .tpkg.var.test
- exit 0
-fi
-if test "$1" = "fake"; then
- echo "minitpkg fake $2"
- echo "fake" > .done-`basename $2 .tpkg`
- exit 0
-fi
-if test "$1" = "report" || test "$2" = "report"; then
- echo "Minitpkg Report"
- for result in *.tpkg; do
- name=`basename $result .tpkg`
- if test -f ".done-$name"; then
- if test "$1" != "-q"; then
- echo "** PASSED ** : $name"
- fi
- else
- if test -f "result.$name"; then
- echo "!! FAILED !! : $name"
- else
- echo ">> SKIPPED<< : $name"
- fi
- fi
- done
- exit 0
-fi
-
-if test "$1" != 'exe'; then
- # usage
- echo "mini tpkg. Reduced functionality for old shells."
- echo " tpkg exe <file>"
- echo " tpkg fake <file>"
- echo " tpkg clean"
- echo " tpkg [-q] report"
- exit 1
-fi
-shift
-
-# do not execute if the disk is too full
-#DISKLIMIT=100000
-# This check is not portable (to Solaris 10).
-#avail=`df . | tail -1 | awk '{print $4}'`
-#if test "$avail" -lt "$DISKLIMIT"; then
- #echo "minitpkg: The disk is too full! Only $avail."
- #exit 1
-#fi
-
-name=`basename $1 .tpkg`
-dir=$name.$$
-result=result.$name
-done=.done-$name
-success="no"
-if test -x "`which bash`"; then
- shell="bash"
-else
- shell="sh"
-fi
-
-# check already done
-if test -f .done-$name; then
- echo "minitpkg .done-$name exists. skip test."
- exit 0
-fi
-
-# Extract
-echo "minitpkg extract $1 to $dir"
-mkdir $dir
-gzip -cd $name.tpkg | (cd $dir; tar xf -)
-cd $dir
-mv $name.dir/* .
-
-# EXE
-echo "minitpkg exe $name" > $result
-grep "Description:" $name.dsc >> $result 2>&1
-echo "DateRunStart: "`date "+%s" 2>/dev/null` >> $result
-if test -f $name.pre; then
- echo "minitpkg exe $name.pre"
- echo "minitpkg exe $name.pre" >> $result
- $shell $name.pre $args >> $result
- if test $? -ne 0; then
- echo "Warning: $name.pre did not exit successfully"
- fi
-fi
-if test -f $name.test; then
- echo "minitpkg exe $name.test"
- echo "minitpkg exe $name.test" >> $result
- $shell $name.test $args >>$result 2>&1
- if test $? -ne 0; then
- echo "$name: FAILED" >> $result
- echo "$name: FAILED"
- success="no"
- else
- echo "$name: PASSED" >> $result
- echo "$name: PASSED" > ../.done-$name
- echo "$name: PASSED"
- success="yes"
- fi
-fi
-if test -f $name.post; then
- echo "minitpkg exe $name.post"
- echo "minitpkg exe $name.post" >> $result
- $shell $name.post $args >> $result
- if test $? -ne 0; then
- echo "Warning: $name.post did not exit successfully"
- fi
-fi
-echo "DateRunEnd: "`date "+%s" 2>/dev/null` >> $result
-
-mv $result ..
-cd ..
-rm -rf $dir
-# compat for windows where deletion may not succeed initially (files locked
-# by processes that still have to exit).
-if test $? -eq 1; then
- echo "minitpkg waiting for processes to terminate"
- sleep 2 # some time to exit, and try again
- rm -rf $dir
-fi
diff --git a/testcode/perf.c b/testcode/perf.c
index 55d6483c7cf9..7fb524e22d94 100644
--- a/testcode/perf.c
+++ b/testcode/perf.c
@@ -618,7 +618,7 @@ int main(int argc, char* argv[])
printf("error: pass server IP address on commandline.\n");
usage(nm);
}
- if(!extstrtoaddr(argv[0], &info.dest, &info.destlen)) {
+ if(!extstrtoaddr(argv[0], &info.dest, &info.destlen, UNBOUND_DNS_PORT)) {
printf("Could not parse ip: %s\n", argv[0]);
exit(1);
}
diff --git a/testcode/replay.c b/testcode/replay.c
index 2487c146f7a8..43101d6acec6 100644
--- a/testcode/replay.c
+++ b/testcode/replay.c
@@ -179,7 +179,8 @@ replay_range_read(char* remain, FILE* in, const char* name,
while(isspace((unsigned char)*parse))
parse++;
strip_end_white(parse);
- if(!extstrtoaddr(parse, &rng->addr, &rng->addrlen)) {
+ if(!extstrtoaddr(parse, &rng->addr, &rng->addrlen,
+ UNBOUND_DNS_PORT)) {
log_err("Line %d: could not read ADDRESS: %s",
pstate->lineno, parse);
free(rng);
@@ -287,7 +288,8 @@ replay_moment_read(char* remain, FILE* in, const char* name,
} else if(parse_keyword(&remain, "QUERY")) {
mom->evt_type = repevt_front_query;
readentry = 1;
- if(!extstrtoaddr("127.0.0.1", &mom->addr, &mom->addrlen))
+ if(!extstrtoaddr("127.0.0.1", &mom->addr, &mom->addrlen,
+ UNBOUND_DNS_PORT))
fatal_exit("internal error");
} else if(parse_keyword(&remain, "CHECK_ANSWER")) {
mom->evt_type = repevt_front_reply;
@@ -354,7 +356,7 @@ replay_moment_read(char* remain, FILE* in, const char* name,
m++;
while(isspace((unsigned char)*m))
m++;
- if(!extstrtoaddr(s, &mom->addr, &mom->addrlen))
+ if(!extstrtoaddr(s, &mom->addr, &mom->addrlen, UNBOUND_DNS_PORT))
fatal_exit("bad infra_rtt address %s", s);
strip_end_white(m);
mom->variable = strdup(remain);
@@ -372,7 +374,8 @@ replay_moment_read(char* remain, FILE* in, const char* name,
while(isspace((unsigned char)*remain))
remain++;
strip_end_white(remain);
- if(!extstrtoaddr(remain, &mom->addr, &mom->addrlen)) {
+ if(!extstrtoaddr(remain, &mom->addr, &mom->addrlen,
+ UNBOUND_DNS_PORT)) {
log_err("line %d: could not parse ADDRESS: %s",
pstate->lineno, remain);
free(mom);
diff --git a/testcode/streamtcp.c b/testcode/streamtcp.c
index ecc83c1cff30..b2c0d5328bb7 100644
--- a/testcode/streamtcp.c
+++ b/testcode/streamtcp.c
@@ -49,6 +49,7 @@
#include "util/locks.h"
#include "util/log.h"
#include "util/net_help.h"
+#include "util/proxy_protocol.h"
#include "util/data/msgencode.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
@@ -71,6 +72,7 @@ static void usage(char* argv[])
printf("usage: %s [options] name type class ...\n", argv[0]);
printf(" sends the name-type-class queries over TCP.\n");
printf("-f server what ipaddr@portnr to send the queries to\n");
+ printf("-p client what ipaddr@portnr to include in PROXYv2\n");
printf("-u use UDP. No retries are attempted.\n");
printf("-n do not wait for an answer.\n");
printf("-a print answers as they arrive.\n");
@@ -82,18 +84,17 @@ static void usage(char* argv[])
/** open TCP socket to svr */
static int
-open_svr(const char* svr, int udp)
+open_svr(const char* svr, int udp, struct sockaddr_storage* addr,
+ socklen_t* addrlen)
{
- struct sockaddr_storage addr;
- socklen_t addrlen;
int fd = -1;
/* svr can be ip@port */
- memset(&addr, 0, sizeof(addr));
- if(!extstrtoaddr(svr, &addr, &addrlen)) {
+ memset(addr, 0, sizeof(*addr));
+ if(!extstrtoaddr(svr, addr, addrlen, UNBOUND_DNS_PORT)) {
printf("fatal: bad server specs '%s'\n", svr);
exit(1);
}
- fd = socket(addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET,
+ fd = socket(addr_is_ip6(addr, *addrlen)?PF_INET6:PF_INET,
udp?SOCK_DGRAM:SOCK_STREAM, 0);
if(fd == -1) {
#ifndef USE_WINSOCK
@@ -103,7 +104,7 @@ open_svr(const char* svr, int udp)
#endif
exit(1);
}
- if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
+ if(connect(fd, (struct sockaddr*)addr, *addrlen) < 0) {
#ifndef USE_WINSOCK
perror("connect() error");
#else
@@ -116,11 +117,12 @@ open_svr(const char* svr, int udp)
/** write a query over the TCP fd */
static void
-write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
+write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
+ sldns_buffer* proxy_buf, int pp2_parsed,
const char* strname, const char* strtype, const char* strclass)
{
struct query_info qinfo;
- uint16_t len;
+ size_t proxy_buf_limit = sldns_buffer_limit(proxy_buf);
/* qname */
qinfo.qname = sldns_str2wire_dname(strname, &qinfo.qname_len);
if(!qinfo.qname) {
@@ -152,9 +154,27 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
attach_edns_record(buf, &edns);
}
+ /* we need to send the PROXYv2 information in every UDP message */
+ if(udp && pp2_parsed) {
+ /* append the proxy_buf with the buf's content
+ * and use that for sending */
+ if(sldns_buffer_capacity(proxy_buf) <
+ sldns_buffer_limit(proxy_buf) +
+ sldns_buffer_limit(buf)) {
+ printf("buffer too small for packet + proxy");
+ exit(1);
+ }
+ sldns_buffer_clear(proxy_buf);
+ sldns_buffer_skip(proxy_buf, proxy_buf_limit);
+ sldns_buffer_write(proxy_buf, sldns_buffer_begin(buf),
+ sldns_buffer_limit(buf));
+ sldns_buffer_flip(proxy_buf);
+ buf = proxy_buf;
+ }
+
/* send it */
if(!udp) {
- len = (uint16_t)sldns_buffer_limit(buf);
+ uint16_t len = (uint16_t)sldns_buffer_limit(buf);
len = htons(len);
if(ssl) {
if(SSL_write(ssl, (void*)&len, (int)sizeof(len)) <= 0) {
@@ -167,7 +187,7 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
#ifndef USE_WINSOCK
perror("send() len failed");
#else
- printf("send len: %s\n",
+ printf("send len: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@@ -182,17 +202,20 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
}
} else {
if(send(fd, (void*)sldns_buffer_begin(buf),
- sldns_buffer_limit(buf), 0) <
+ sldns_buffer_limit(buf), 0) <
(ssize_t)sldns_buffer_limit(buf)) {
#ifndef USE_WINSOCK
perror("send() data failed");
#else
- printf("send data: %s\n", wsa_strerror(WSAGetLastError()));
+ printf("send data: %s\n",
+ wsa_strerror(WSAGetLastError()));
#endif
exit(1);
}
}
+ /* reset the proxy_buf for next packet */
+ sldns_buffer_set_limit(proxy_buf, proxy_buf_limit);
free(qinfo.qname);
}
@@ -224,7 +247,7 @@ recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
#ifndef USE_WINSOCK
perror("read() len failed");
#else
- printf("read len: %s\n",
+ printf("read len: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@@ -243,12 +266,12 @@ recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
if(r != (int)len)
fatal_exit("ssl_read %d of %d", r, len);
} else {
- if(recv(fd, (void*)sldns_buffer_begin(buf), len, 0) <
+ if(recv(fd, (void*)sldns_buffer_begin(buf), len, 0) <
(ssize_t)len) {
#ifndef USE_WINSOCK
perror("read() data failed");
#else
- printf("read data: %s\n",
+ printf("read data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@@ -257,12 +280,12 @@ recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
} else {
ssize_t l;
sldns_buffer_clear(buf);
- if((l=recv(fd, (void*)sldns_buffer_begin(buf),
+ if((l=recv(fd, (void*)sldns_buffer_begin(buf),
sldns_buffer_capacity(buf), 0)) < 0) {
#ifndef USE_WINSOCK
perror("read() data failed");
#else
- printf("read data: %s\n",
+ printf("read data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
@@ -324,17 +347,40 @@ static int get_random(void)
return (int)arc4random();
}
+/* parse the pp2_client and populate the proxy_buffer
+ * It doesn't populate the destination parts. */
+static int parse_pp2_client(const char* pp2_client, int udp,
+ sldns_buffer* proxy_buf)
+{
+ struct sockaddr_storage pp2_addr;
+ socklen_t pp2_addrlen = 0;
+ memset(&pp2_addr, 0, sizeof(pp2_addr));
+ if(*pp2_client == 0) return 0;
+ if(!extstrtoaddr(pp2_client, &pp2_addr, &pp2_addrlen, UNBOUND_DNS_PORT)) {
+ printf("fatal: bad proxy client specs '%s'\n", pp2_client);
+ exit(1);
+ }
+ sldns_buffer_clear(proxy_buf);
+ pp2_write_to_buf(proxy_buf, &pp2_addr, !udp);
+ sldns_buffer_flip(proxy_buf);
+ return 1;
+}
+
/** send the TCP queries and print answers */
static void
-send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
- int delay, int num, char** qs)
+send_em(const char* svr, const char* pp2_client, int udp, int usessl,
+ int noanswer, int onarrival, int delay, int num, char** qs)
{
sldns_buffer* buf = sldns_buffer_new(65553);
- int fd = open_svr(svr, udp);
- int i, wait_results = 0;
+ sldns_buffer* proxy_buf = sldns_buffer_new(65553);
+ struct sockaddr_storage svr_addr;
+ socklen_t svr_addrlen;
+ int fd = open_svr(svr, udp, &svr_addr, &svr_addrlen);
+ int i, wait_results = 0, pp2_parsed;
SSL_CTX* ctx = NULL;
SSL* ssl = NULL;
if(!buf) fatal_exit("out of memory");
+ pp2_parsed = parse_pp2_client(pp2_client, udp, proxy_buf);
if(usessl) {
ctx = connect_sslctx_create(NULL, NULL, NULL, 0);
if(!ctx) fatal_exit("cannot create ssl ctx");
@@ -361,6 +407,28 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
}
}
}
+ /* Send the PROXYv2 information once per stream */
+ if(!udp && pp2_parsed) {
+ if(ssl) {
+ if(SSL_write(ssl, (void*)sldns_buffer_begin(proxy_buf),
+ (int)sldns_buffer_limit(proxy_buf)) <= 0) {
+ log_crypto_err("cannot SSL_write");
+ exit(1);
+ }
+ } else {
+ if(send(fd, (void*)sldns_buffer_begin(proxy_buf),
+ sldns_buffer_limit(proxy_buf), 0) <
+ (ssize_t)sldns_buffer_limit(proxy_buf)) {
+#ifndef USE_WINSOCK
+ perror("send() data failed");
+#else
+ printf("send data: %s\n",
+ wsa_strerror(WSAGetLastError()));
+#endif
+ exit(1);
+ }
+ }
+ }
for(i=0; i<num; i+=3) {
if (delay != 0) {
#ifdef HAVE_SLEEP
@@ -370,8 +438,9 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
#endif
}
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]);
+ write_q(fd, udp, ssl, buf, (uint16_t)get_random(), proxy_buf,
+ pp2_parsed,
+ qs[i], qs[i+1], qs[i+2]);
/* print at least one result */
if(onarrival) {
wait_results += 1; /* one more answer to fetch */
@@ -390,6 +459,7 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
}
sock_close(fd);
sldns_buffer_free(buf);
+ sldns_buffer_free(proxy_buf);
printf("orderly exit\n");
}
@@ -418,10 +488,11 @@ extern int optind;
extern char* optarg;
/** main program for streamtcp */
-int main(int argc, char** argv)
+int main(int argc, char** argv)
{
int c;
const char* svr = "127.0.0.1";
+ const char* pp2_client = "";
int udp = 0;
int noanswer = 0;
int onarrival = 0;
@@ -451,11 +522,14 @@ int main(int argc, char** argv)
if(argc == 1) {
usage(argv);
}
- while( (c=getopt(argc, argv, "af:hnsud:")) != -1) {
+ while( (c=getopt(argc, argv, "af:p:hnsud:")) != -1) {
switch(c) {
case 'f':
svr = optarg;
break;
+ case 'p':
+ pp2_client = optarg;
+ break;
case 'a':
onarrival = 1;
break;
@@ -508,7 +582,7 @@ int main(int argc, char** argv)
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
#endif
}
- send_em(svr, udp, usessl, noanswer, onarrival, delay, argc, argv);
+ send_em(svr, pp2_client, udp, usessl, noanswer, onarrival, delay, argc, argv);
checklock_stop();
#ifdef USE_WINSOCK
WSACleanup();
diff --git a/testcode/unitecs.c b/testcode/unitecs.c
index b240bfcc666e..68d6907f81a7 100644
--- a/testcode/unitecs.c
+++ b/testcode/unitecs.c
@@ -173,7 +173,7 @@ static void consistency_test(void)
for (i = 0; i < 1000; i++) {
l = randomkey(&k, 128);
elem = (struct reply_info *) calloc(1, sizeof(struct reply_info));
- addrtree_insert(t, k, l, 64, elem, timenow + 10, timenow);
+ addrtree_insert(t, k, l, 64, elem, timenow + 10, timenow, 0);
/* This should always hold because no items ever expire. They
* could be overwritten, though. */
unit_assert( count <= t->node_count );
@@ -189,7 +189,7 @@ static void consistency_test(void)
for (i = 0; i < 1000; i++) {
l = randomkey(&k, 128);
elem = (struct reply_info *) calloc(1, sizeof(struct reply_info));
- addrtree_insert(t, k, l, 64, elem, i + 10, i);
+ addrtree_insert(t, k, l, 64, elem, i + 10, i, 0);
free(k);
unit_assert( !addrtree_inconsistent(t) );
}
@@ -201,7 +201,7 @@ static void consistency_test(void)
for (i = 0; i < 1000; i++) {
l = randomkey(&k, 128);
elem = (struct reply_info *) calloc(1, sizeof(struct reply_info));
- addrtree_insert(t, k, l, 64, elem, i + 10, i);
+ addrtree_insert(t, k, l, 64, elem, i + 10, i, 0);
unit_assert( t->node_count <= 27);
free(k);
unit_assert( !addrtree_inconsistent(t) );
diff --git a/testcode/unittcpreuse.c b/testcode/unittcpreuse.c
index 087c6c1b9d50..5f45a4b456f1 100644
--- a/testcode/unittcpreuse.c
+++ b/testcode/unittcpreuse.c
@@ -44,6 +44,8 @@
#include "util/random.h"
#include "services/outside_network.h"
+#define MAX_TCP_WAITING_NODES 5
+
/** add number of new IDs to the reuse tree, randomly chosen */
static void tcpid_addmore(struct reuse_tcp* reuse,
struct outside_network* outnet, unsigned int addnum)
@@ -228,9 +230,260 @@ static void tcp_reuse_tree_list_test(void)
free(outnet.tcp_conns);
}
+static void check_waiting_tcp_list(struct outside_network* outnet,
+ struct waiting_tcp* first, struct waiting_tcp* last, size_t total)
+{
+ size_t i, j;
+ struct waiting_tcp* w = outnet->tcp_wait_first;
+ struct waiting_tcp* n = NULL;
+ if(first) unit_assert(outnet->tcp_wait_first == first);
+ if(last) unit_assert(outnet->tcp_wait_last == last && !last->next_waiting);
+ for(i=0; w; i++) {
+ unit_assert(i<total); /* otherwise we are looping */
+ unit_assert(w->on_tcp_waiting_list);
+ n = w->next_waiting;
+ for(j=0; n; j++) {
+ unit_assert(j<total-i-1); /* otherwise we are looping */
+ unit_assert(n != w);
+ n = n->next_waiting;
+ }
+ w = w->next_waiting;
+ }
+}
+
+/** clear the tcp waiting list */
+static void waiting_tcp_list_clear(struct outside_network* outnet)
+{
+ struct waiting_tcp* w = outnet->tcp_wait_first, *n = NULL;
+ if(!w) return;
+ unit_assert(outnet->tcp_wait_first);
+ unit_assert(outnet->tcp_wait_last);
+ while(w) {
+ n = w->next_waiting;
+ w->on_tcp_waiting_list = 0;
+ w->next_waiting = (struct waiting_tcp*)1; /* In purpose faux value */
+ w = n;
+ }
+ outnet->tcp_wait_first = NULL;
+ outnet->tcp_wait_last = NULL;
+}
+
+/** check removal of the waiting_tcp element on the given position of total
+ * elements */
+static void check_waiting_tcp_removal(int is_pop,
+ struct outside_network* outnet, struct waiting_tcp* store,
+ size_t position, size_t total)
+{
+ size_t i;
+ struct waiting_tcp* w;
+ waiting_tcp_list_clear(outnet);
+ for(i=0; i<total; i++) {
+ outnet_waiting_tcp_list_add(outnet, &store[i], 0);
+ }
+ check_waiting_tcp_list(outnet, &store[0], &store[total-1], total);
+
+ if(is_pop) {
+ w = outnet_waiting_tcp_list_pop(outnet);
+ unit_assert(w); /* please clang-analyser */
+ } else {
+ w = outnet->tcp_wait_first;
+ for(i=0; i<position; i++) {
+ unit_assert(w); /* please clang-analyser */
+ w = w->next_waiting;
+ }
+ unit_assert(w); /* please clang-analyser */
+ outnet_waiting_tcp_list_remove(outnet, w);
+ }
+ unit_assert(!(w->on_tcp_waiting_list || w->next_waiting));
+
+ if(position == 0 && total == 1) {
+ /* the list should be empty */
+ check_waiting_tcp_list(outnet, NULL, NULL, total-1);
+ } else if(position == 0) {
+ /* first element should be gone */
+ check_waiting_tcp_list(outnet, &store[1], &store[total-1], total-1);
+ } else if(position == total - 1) {
+ /* last element should be gone */
+ check_waiting_tcp_list(outnet, &store[0], &store[total-2], total-1);
+ } else {
+ /* an element should be gone */
+ check_waiting_tcp_list(outnet, &store[0], &store[total-1], total-1);
+ }
+}
+
+static void waiting_tcp_list_test(void)
+{
+ size_t i = 0;
+ struct outside_network outnet;
+ struct waiting_tcp* w, *t = NULL;
+ struct waiting_tcp store[MAX_TCP_WAITING_NODES];
+ memset(&outnet, 0, sizeof(outnet));
+ memset(&store, 0, sizeof(store));
+
+ /* Check add first on empty list */
+ unit_show_func("services/outside_network.c", "outnet_waiting_tcp_list_add_first");
+ t = &store[i];
+ outnet_waiting_tcp_list_add_first(&outnet, t, 0);
+ check_waiting_tcp_list(&outnet, t, t, 1);
+
+ /* Check add */
+ unit_show_func("services/outside_network.c", "outnet_waiting_tcp_list_add");
+ for(i=1; i<MAX_TCP_WAITING_NODES-1; i++) {
+ w = &store[i];
+ outnet_waiting_tcp_list_add(&outnet, w, 0);
+ }
+ check_waiting_tcp_list(&outnet, t, w, MAX_TCP_WAITING_NODES-1);
+
+ /* Check add first on populated list */
+ unit_show_func("services/outside_network.c", "outnet_waiting_tcp_list_add_first");
+ w = &store[i];
+ t = outnet.tcp_wait_last;
+ outnet_waiting_tcp_list_add_first(&outnet, w, 0);
+ check_waiting_tcp_list(&outnet, w, t, MAX_TCP_WAITING_NODES);
+
+ /* Check removal */
+ unit_show_func("services/outside_network.c", "outnet_waiting_tcp_list_remove");
+ check_waiting_tcp_removal(0, &outnet, store, 2, 5);
+ check_waiting_tcp_removal(0, &outnet, store, 1, 3);
+ check_waiting_tcp_removal(0, &outnet, store, 0, 2);
+ check_waiting_tcp_removal(0, &outnet, store, 1, 2);
+ check_waiting_tcp_removal(0, &outnet, store, 0, 1);
+
+ /* Check pop */
+ unit_show_func("services/outside_network.c", "outnet_waiting_tcp_list_pop");
+ check_waiting_tcp_removal(1, &outnet, store, 0, 3);
+ check_waiting_tcp_removal(1, &outnet, store, 0, 2);
+ check_waiting_tcp_removal(1, &outnet, store, 0, 1);
+}
+
+static void check_reuse_write_wait(struct reuse_tcp* reuse,
+ struct waiting_tcp* first, struct waiting_tcp* last, size_t total)
+{
+ size_t i, j;
+ struct waiting_tcp* w = reuse->write_wait_first;
+ struct waiting_tcp* n = NULL;
+ if(first) unit_assert(reuse->write_wait_first == first && !first->write_wait_prev);
+ if(last) unit_assert(reuse->write_wait_last == last && !last->write_wait_next);
+ /* check one way */
+ for(i=0; w; i++) {
+ unit_assert(i<total); /* otherwise we are looping */
+ unit_assert(w->write_wait_queued);
+ n = w->write_wait_next;
+ for(j=0; n; j++) {
+ unit_assert(j<total-i-1); /* otherwise we are looping */
+ unit_assert(n != w);
+ n = n->write_wait_next;
+ }
+ w = w->write_wait_next;
+ }
+ /* check the other way */
+ w = reuse->write_wait_last;
+ for(i=0; w; i++) {
+ unit_assert(i<total); /* otherwise we are looping */
+ unit_assert(w->write_wait_queued);
+ n = w->write_wait_prev;
+ for(j=0; n; j++) {
+ unit_assert(j<total-i-1); /* otherwise we are looping */
+ unit_assert(n != w);
+ n = n->write_wait_prev;
+ }
+ w = w->write_wait_prev;
+ }
+}
+
+/** clear the tcp waiting list */
+static void reuse_write_wait_clear(struct reuse_tcp* reuse)
+{
+ struct waiting_tcp* w = reuse->write_wait_first, *n = NULL;
+ if(!w) return;
+ unit_assert(reuse->write_wait_first);
+ unit_assert(reuse->write_wait_last);
+ while(w) {
+ n = w->write_wait_next;
+ w->write_wait_queued = 0;
+ w->write_wait_next = (struct waiting_tcp*)1; /* In purpose faux value */
+ w->write_wait_prev = (struct waiting_tcp*)1; /* In purpose faux value */
+ w = n;
+ }
+ reuse->write_wait_first = NULL;
+ reuse->write_wait_last = NULL;
+}
+
+/** check removal of the reuse_write_wait element on the given position of total
+ * elements */
+static void check_reuse_write_wait_removal(int is_pop,
+ struct reuse_tcp* reuse, struct waiting_tcp* store,
+ size_t position, size_t total)
+{
+ size_t i;
+ struct waiting_tcp* w;
+ reuse_write_wait_clear(reuse);
+ for(i=0; i<total; i++) {
+ reuse_write_wait_push_back(reuse, &store[i]);
+ }
+ check_reuse_write_wait(reuse, &store[0], &store[total-1], total);
+
+ if(is_pop) {
+ w = reuse_write_wait_pop(reuse);
+ } else {
+ w = reuse->write_wait_first;
+ for(i=0; i<position; i++) w = w->write_wait_next;
+ reuse_write_wait_remove(reuse, w);
+ }
+ unit_assert(!(w->write_wait_queued || w->write_wait_next || w->write_wait_prev));
+
+ if(position == 0 && total == 1) {
+ /* the list should be empty */
+ check_reuse_write_wait(reuse, NULL, NULL, total-1);
+ } else if(position == 0) {
+ /* first element should be gone */
+ check_reuse_write_wait(reuse, &store[1], &store[total-1], total-1);
+ } else if(position == total - 1) {
+ /* last element should be gone */
+ check_reuse_write_wait(reuse, &store[0], &store[total-2], total-1);
+ } else {
+ /* an element should be gone */
+ check_reuse_write_wait(reuse, &store[0], &store[total-1], total-1);
+ }
+}
+
+static void reuse_write_wait_test(void)
+{
+ size_t i;
+ struct reuse_tcp reuse;
+ struct waiting_tcp store[MAX_TCP_WAITING_NODES];
+ struct waiting_tcp* w;
+ memset(&reuse, 0, sizeof(reuse));
+ memset(&store, 0, sizeof(store));
+
+ /* Check adding */
+ unit_show_func("services/outside_network.c", "reuse_write_wait_push_back");
+ for(i=0; i<MAX_TCP_WAITING_NODES; i++) {
+ w = &store[i];
+ reuse_write_wait_push_back(&reuse, w);
+ }
+ check_reuse_write_wait(&reuse, &store[0], w, MAX_TCP_WAITING_NODES);
+
+ /* Check removal */
+ unit_show_func("services/outside_network.c", "reuse_write_wait_remove");
+ check_reuse_write_wait_removal(0, &reuse, store, 2, 5);
+ check_reuse_write_wait_removal(0, &reuse, store, 1, 3);
+ check_reuse_write_wait_removal(0, &reuse, store, 0, 2);
+ check_reuse_write_wait_removal(0, &reuse, store, 1, 2);
+ check_reuse_write_wait_removal(0, &reuse, store, 0, 1);
+
+ /* Check pop */
+ unit_show_func("services/outside_network.c", "reuse_write_wait_pop");
+ check_reuse_write_wait_removal(1, &reuse, store, 0, 3);
+ check_reuse_write_wait_removal(1, &reuse, store, 0, 2);
+ check_reuse_write_wait_removal(1, &reuse, store, 0, 1);
+}
+
void tcpreuse_test(void)
{
unit_show_feature("tcp_reuse");
tcpid_test();
tcp_reuse_tree_list_test();
+ waiting_tcp_list_test();
+ reuse_write_wait_test();
}