diff options
| author | Cy Schubert <cy@FreeBSD.org> | 2022-10-16 19:24:20 +0000 |
|---|---|---|
| committer | Cy Schubert <cy@FreeBSD.org> | 2022-10-16 19:24:20 +0000 |
| commit | 643f9a0581e8aac7eb790ced1164748939829826 (patch) | |
| tree | 426d366252d838c8c61b439342ab32eccd181425 /testcode | |
| parent | 0dde6f4f8e604df8c6fbdab8b4aadb5ddf80c76f (diff) | |
Diffstat (limited to 'testcode')
| -rw-r--r-- | testcode/delayer.c | 2 | ||||
| -rwxr-xr-x | testcode/do-tests.sh | 2 | ||||
| -rw-r--r-- | testcode/fake_event.c | 21 | ||||
| -rwxr-xr-x | testcode/mini_tdir.sh | 38 | ||||
| -rwxr-xr-x | testcode/mini_tpkg.sh | 128 | ||||
| -rw-r--r-- | testcode/perf.c | 2 | ||||
| -rw-r--r-- | testcode/replay.c | 11 | ||||
| -rw-r--r-- | testcode/streamtcp.c | 128 | ||||
| -rw-r--r-- | testcode/unitecs.c | 6 | ||||
| -rw-r--r-- | testcode/unittcpreuse.c | 253 |
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(); } |
