Rewrite DNS proxy in transport/timeout test suites

To use the new DNS packet conversion functions.
This looses the dependency on ldns for unit tests too.
This commit is contained in:
Willem Toorop 2016-03-14 10:41:32 +01:00
parent 02d14351fc
commit f95a052e55
6 changed files with 138 additions and 130 deletions

View File

@ -384,9 +384,6 @@ getdns-specific Options
`--with-libidn=pathname'
path to libidn (default: search /usr/local ..)
`--with-libldns=pathname'
path to libldns (default: search /usr/local ..)
`--with-libunbound=pathname'
path to libunbound (default: search /usr/local ..)

View File

@ -122,7 +122,7 @@ NOTE: The current Windows implementation does not support the above.
A suite of regression tests are included with the library, if you make changes or just
want to sanity check things on your system take a look at src/test. You will need
to install [libcheck](https://libcheck.github.io/check/) and [libldns from NLnet Labs](https://nlnetlabs.nl/projects/ldns/) version 1.6.17 or later. Both libraries are also available from
to install [libcheck](https://libcheck.github.io/check/). The check library is also available from
many of the package repositories for the more popular operating systems.
NOTE: The current Windows implementation does not support the above.
@ -198,7 +198,7 @@ build the packages, this is simplythe one we chose to use.
# cd /home/deploy/build
# mv lib lib64
# . /usr/local/rvm/config/alias
# fpm -x "*.la" -a native -s dir -t rpm -n getdns -v 0.2.0rc1 -d "unbound" -d "ldns" -d "libevent" -d "libidn" --prefix /usr --vendor "Verisign Inc., NLnet Labs" --license "BSD New" --url "https://getdnsapi.net" --description "Modern asynchronous API to the DNS" .
# fpm -x "*.la" -a native -s dir -t rpm -n getdns -v 0.2.0rc1 -d "unbound" -d "libevent" -d "libidn" --prefix /usr --vendor "Verisign Inc., NLnet Labs" --license "BSD New" --url "https://getdnsapi.net" --description "Modern asynchronous API to the DNS" .
###OSX

View File

@ -266,7 +266,7 @@ AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <openssl/evp.h>
#include <openssl/engine.h>
#include <openssl/conf.h>
/* routine to load gost (from sldns) */
/* routine to load gost (from gldns) */
int load_gost_id(void)
{
static int gost_id = 0;
@ -606,60 +606,6 @@ AC_SUBST([CHECK_LIBS])
AC_SUBST([CHECK_CFLAGS])
# end libraries needed for libcheck
# find libldns
LIBS="$initial_LIBS"
LDNS_LIBS=""
LDNS_CFLAGS=""
LDNS_LDFLAGS=""
NOLIBLDNS=""
AC_ARG_WITH(libldns, AS_HELP_STRING([--with-libldns=pathname],
[path to libldns (default: search /usr/local ..)]),
[], [withval="yes"])
if test x_$withval = x_yes; then
for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do
if test -f "$dir/include/ldns/ldns.h"; then
LDNS_CFLAGS="-I$dir/include"
LDNS_LDFLAGS="-L$dir/lib"
CFLAGS="$CFLAGS $LDNS_CFLAGS"
LDFLAGS="$LDFLAGS $LDNS_LDFLAGS"
AC_MSG_NOTICE([Found libldns in $dir])
break
fi
done
else
if test x_$withval != x_no; then
LDNS_CFLAGS="-I$withval/include"
LDNS_LDFLAGS="-L$withval/lib"
CFLAGS="$CFLAGS $LDNS_CFLAGS"
LDFLAGS="$LDFLAGS $LDNS_LDFLAGS"
else
NOLIBLDNS="nolibldns"
AC_MSG_WARN([libldns not found or usable; unit tests will not be compiled and run])
fi
fi
if test x$NOLIBLDNS = x
then
AC_CHECK_LIB([ldns], [ldns_dname_new_frm_str], [
LDNS_LIBS="-lldns"
AC_DEFINE_UNQUOTED(HAVE_LIBLDNS, [1], [Have libldns])
], [
NOLIBLDNS="nolibldns"
AC_MSG_WARN([libldns not found or usable; unit tests will not be compiled and run])
])
fi
AC_SUBST([LDNS_LIBS])
AC_SUBST([LDNS_CFLAGS])
AC_SUBST([LDNS_LDFLAGS])
AC_SUBST([NOLIBLDNS])
LIBS="$getdns_LIBS"
CFLAGS="$getdns_CFLAGS"
LDFLAGS="$getdns_LDFLAGS"
#-------------------- libevent extension
AC_ARG_WITH([libevent],
[AS_HELP_STRING([--with-libevent], [path to libevent (default: search /usr/local ..)])],

View File

@ -43,7 +43,6 @@ have_libevent = @have_libevent@
have_libuv = @have_libuv@
have_libev = @have_libev@
NOLIBCHECK = @NOLIBCHECK@
NOLIBLDNS = @NOLIBLDNS@
EXTENSION_LIBEVENT_EXT_LIBS=@EXTENSION_LIBEVENT_EXT_LIBS@
EXTENSION_LIBEVENT_LDFLAGS=@EXTENSION_LIBEVENT_LDFLAGS@
@ -63,9 +62,6 @@ LDFLAGS=-L.. @LDFLAGS@
LDLIBS=../libgetdns.la @LIBS@
CHECK_LIBS=@CHECK_LIBS@
CHECK_CFLAGS=@CHECK_CFLAGS@
LDNS_LIBS=@LDNS_LIBS@
LDNS_CFLAGS=@LDNS_CFLAGS@
LDNS_LDFLAGS=@LDNS_LDFLAGS@
CHECK_OBJS=check_getdns_common.lo check_getdns_context_set_timeout.lo \
check_getdns.lo check_getdns_transport.lo
@ -93,7 +89,7 @@ default: all
all: $(PROGRAMS)
$(ALL_OBJS):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(LDNS_CFLAGS) -c $(srcdir)/$(@:.lo=.c) -o $@
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(srcdir)/$(@:.lo=.c) -o $@
$(NON_C99_OBJS):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -c $(srcdir)/$(@:.lo=.c) -o $@
@ -117,16 +113,16 @@ check_getdns_common: check_getdns_common.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ check_getdns_common.lo
check_getdns: check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_selectloop.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) $(CHECK_CFLAGS) $(CHECK_LIBS) $(LDNS_CFLAGS) $(LDNS_LDFLAGS) $(LDNS_LIBS) -o $@ check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_selectloop.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) $(CHECK_CFLAGS) $(CHECK_LIBS) -o $@ check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_selectloop.lo
check_getdns_event: check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libevent.lo ../libgetdns_ext_event.la
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libevent.lo $(LDFLAGS) $(LDLIBS) $(CHECK_CFLAGS) $(CHECK_LIBS) $(LDNS_CFLAGS) $(LDNS_LDFLAGS) $(LDNS_LIBS) ../libgetdns_ext_event.la $(EXTENSION_LIBEVENT_LDFLAGS) $(EXTENSION_LIBEVENT_EXT_LIBS)
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libevent.lo $(LDFLAGS) $(LDLIBS) $(CHECK_CFLAGS) $(CHECK_LIBS) ../libgetdns_ext_event.la $(EXTENSION_LIBEVENT_LDFLAGS) $(EXTENSION_LIBEVENT_EXT_LIBS)
check_getdns_uv: check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libuv.lo ../libgetdns_ext_uv.la
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libuv.lo $(LDFLAGS) $(LDLIBS) $(CHECK_CFLAGS) $(CHECK_LIBS) $(LDNS_CFLAGS) $(LDNS_LDFLAGS) $(LDNS_LIBS) ../libgetdns_ext_uv.la $(EXTENSION_LIBUV_LDFLAGS) $(EXTENSION_LIBUV_EXT_LIBS)
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libuv.lo $(LDFLAGS) $(LDLIBS) $(CHECK_CFLAGS) $(CHECK_LIBS) ../libgetdns_ext_uv.la $(EXTENSION_LIBUV_LDFLAGS) $(EXTENSION_LIBUV_EXT_LIBS)
check_getdns_ev: check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libev.lo ../libgetdns_ext_ev.la
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libev.lo $(LDFLAGS) $(LDLIBS) $(CHECK_CFLAGS) $(CHECK_LIBS) $(LDNS_CFLAGS) $(LDNS_LDFLAGS) $(LDNS_LIBS) ../libgetdns_ext_ev.la $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS)
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libev.lo $(LDFLAGS) $(LDLIBS) $(CHECK_CFLAGS) $(CHECK_LIBS) ../libgetdns_ext_ev.la $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS)
getdns_query: getdns_query.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ getdns_query.lo $(LDFLAGS) $(LDLIBS)
@ -155,16 +151,7 @@ nolibcheck:
@echo "***"
@false
nolibldns:
@echo "***"
@echo "*** Cannot run unit tests, because they could not be compiled,"
@echo "*** because libldns was not found or usable at configure time."
@echo "*** To compile and run unit tests make sure libldns is available"
@echo "*** and usable during configuration"
@echo "***"
@false
test: $(NOLIBCHECK) $(NOLIBLDNS) all
test: $(NOLIBCHECK) all
(cd $(srcdir)/../.. && find . -type f -executable -and \( -name "*.[ch]" -or -name "*.html" -or -name "*.in" -or -name "*.good" -or -name "*.ac" \) | awk 'BEGIN{e=0}{print("ERROR! Executable bit found on", $$0);e=1}END{exit(e)}')
./$(CHECK_GETDNS)
if test $(have_libevent) = 1 ; then ./$(CHECK_EVENT_PROG) ; fi

View File

@ -33,7 +33,6 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <ldns/ldns.h>
/*
@ -126,7 +125,7 @@ typedef struct timeout_thread_data {
typedef struct queued_response {
struct sockaddr_in client_addr;
ldns_pkt* pkt;
getdns_dict *reply;
} queued_response;
void* run_server(void* data) {
@ -135,13 +134,25 @@ void* run_server(void* data) {
struct sockaddr_in serv_addr;
uint8_t mesg[65536];
fd_set read_fds;
ldns_rdf* answerfrom;
ldns_resolver* resolver;
getdns_context *ctxt;
getdns_return_t r;
getdns_dict *dns_msg;
getdns_bindata *qname;
char *qname_str;
uint32_t qtype, qid;
int num_received = 0;
queued_response responses[10];
ldns_resolver_new_frm_file(&resolver, NULL);
if ((r = getdns_context_create(&ctxt, 1))) {
fprintf( stderr, "Could not create a getdns context: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
return NULL;
}
if ((r = getdns_context_set_resolution_type(ctxt, GETDNS_RESOLUTION_STUB))) {
fprintf( stderr, "Could not set context in stub mode resolution: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
return NULL;
}
fd=socket(AF_INET,SOCK_DGRAM,0);
@ -166,32 +177,63 @@ void* run_server(void* data) {
tv.tv_usec = 0;
int r = select(fd + 1, &read_fds, NULL, NULL, &tv);
if (r > 0 && num_received < 10) {
ldns_pkt* query;
socklen_t len = sizeof(client_addr);
int n = recvfrom(fd,mesg,65536,0,(struct sockaddr *)&(responses[num_received].client_addr),&len);
ldns_wire2pkt(&query, mesg, n);
ldns_resolver_send_pkt(&(responses[num_received].pkt), resolver, query);
ldns_str2rdf_a(&answerfrom, "127.0.0.1");
ldns_pkt_set_answerfrom(responses[num_received].pkt, answerfrom);
ldns_pkt_free(query);
if ((r = getdns_wire2msg_dict(mesg, n, &dns_msg))) {
fprintf( stderr, "Could not convert wireformat to DNS message dict: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
continue;
}
if ((r = getdns_dict_get_bindata(dns_msg, "/question/qname", &qname))) {
fprintf( stderr, "Could not get query name from request dict: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
continue;
}
if ((r = getdns_convert_dns_name_to_fqdn(qname, &qname_str))) {
fprintf( stderr, "Could not convert qname to fqdn: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
continue;
}
if ((r = getdns_dict_get_int(dns_msg, "/question/qtype", &qtype))) {
fprintf( stderr, "Could not get query type from request dict: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
continue;
}
if ((r = getdns_dict_get_int(dns_msg, "/header/id", &qid))) {
fprintf( stderr, "Could not get message ID from request dict: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
continue;
}
getdns_dict_destroy(dns_msg);
r = getdns_general_sync(ctxt, qname_str, qtype, NULL, &responses[num_received].reply);
free(qname_str);
if (r) {
fprintf( stderr, "Could query for \"%s\" %d: \"%s\"\n", qname_str, (int)qtype
, getdns_get_errorstr_by_id(r));
continue;
}
if ((r = getdns_dict_set_int(responses[num_received].reply, "/replies_tree/0/header/id", qid))) {
fprintf( stderr, "Could not set message ID on reply dict: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
continue;
}
++num_received;
} else if (r == 0 && num_received > 0) {
int i = 0;
/* timeout - see if we have anything to send */
for (i = 0; i < num_received; ++i) {
uint8_t* pkt_data;
size_t pkt_len;
ldns_pkt* answer = responses[i].pkt;
ldns_pkt2wire(&pkt_data, answer, &pkt_len);
sendto(fd,pkt_data,pkt_len,0,(struct sockaddr *)&(responses[i].client_addr),sizeof(client_addr));
free(pkt_data);
ldns_pkt_free(answer);
size_t pkt_len = sizeof(mesg);
if ((r = getdns_msg_dict2wire_buf(responses[i].reply, mesg, &pkt_len))) {
fprintf( stderr, "Could not convert DNS message dict to wireformat: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
}
sendto(fd,mesg,pkt_len,0,(struct sockaddr *)&(responses[i].client_addr),sizeof(client_addr));
getdns_dict_destroy(responses[i].reply);
}
num_received = 0;
}
}
ldns_resolver_deep_free(resolver);
getdns_context_destroy(ctxt);
return NULL;
}
@ -214,7 +256,6 @@ void timeout_3_cb(struct getdns_context *context,
}
/* Temporarily disabled because of unpredictable results */
#if 0
START_TEST (getdns_context_set_timeout_3)
{
/*
@ -290,7 +331,6 @@ START_TEST (getdns_context_set_timeout_3)
}
END_TEST
#endif
@ -309,12 +349,10 @@ getdns_context_set_timeout_suite (void)
/* Positive test cases */
/* Temporarily disabled because of unpredictable results */
#if 0
TCase *tc_pos = tcase_create("Positive");
tcase_set_timeout(tc_pos, 15.0);
tcase_add_test(tc_pos, getdns_context_set_timeout_3);
suite_add_tcase(s, tc_pos);
#endif
return s;

View File

@ -33,7 +33,6 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <ldns/ldns.h>
#include <sys/param.h>
@ -58,11 +57,25 @@ void* run_transport_server(void* data) {
struct sockaddr_in serv_addr;
uint8_t mesg[65536], tcplength[2];
fd_set read_fds;
ldns_rdf* answerfrom;
ldns_resolver* resolver;
size_t pkt_len;
getdns_context *ctxt;
getdns_return_t r;
getdns_dict *dns_msg;
getdns_bindata *qname;
char *qname_str;
uint32_t qtype, qid;
int udp_count = 0;
int tcp_count = 0;
ldns_resolver_new_frm_file(&resolver, NULL);
if ((r = getdns_context_create(&ctxt, 1))) {
fprintf( stderr, "Could not create a getdns context: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
return NULL;
}
if ((r = getdns_context_set_resolution_type(ctxt, GETDNS_RESOLUTION_STUB))) {
fprintf( stderr, "Could not set context in stub mode resolution: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
return NULL;
}
udp = socket(AF_INET, SOCK_DGRAM, 0);
tcp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
@ -83,7 +96,6 @@ void* run_transport_server(void* data) {
FD_ZERO(&read_fds);
FD_SET(udp, &read_fds);
FD_SET(tcp, &read_fds);
ldns_pkt* pkt;
int n = 0;
struct timeval tv;
tv.tv_sec = 1;
@ -91,7 +103,6 @@ void* run_transport_server(void* data) {
int maxfdp1 = MAX(udp, tcp) + 1;
int r = select(maxfdp1, &read_fds, NULL, NULL, &tv);
if (r > 0) {
ldns_pkt* query;
socklen_t len = sizeof (client_addr);
if (FD_ISSET(udp, &read_fds)) {
n = recvfrom(udp, mesg, 65536, 0, (struct sockaddr *) &client_addr, &len);
@ -107,37 +118,66 @@ void* run_transport_server(void* data) {
break;
}
ldns_wire2pkt(&query, mesg, n);
ldns_resolver_send_pkt(&pkt, resolver, query);
ldns_str2rdf_a(&answerfrom, "127.0.0.1");
ldns_pkt_set_answerfrom(pkt, answerfrom);
ldns_pkt_free(query);
ldns_buffer *send_buf;
send_buf = ldns_buffer_new(LDNS_MIN_BUFLEN);
ldns_pkt2buffer_wire(send_buf, pkt);
if ((r = getdns_wire2msg_dict(mesg, n, &dns_msg))) {
fprintf( stderr, "Could not convert wireformat to DNS message dict: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
continue;
}
if ((r = getdns_dict_get_bindata(dns_msg, "/question/qname", &qname))) {
fprintf( stderr, "Could not get query name from request dict: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
continue;
}
if ((r = getdns_convert_dns_name_to_fqdn(qname, &qname_str))) {
fprintf( stderr, "Could not convert qname to fqdn: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
continue;
}
if ((r = getdns_dict_get_int(dns_msg, "/question/qtype", &qtype))) {
fprintf( stderr, "Could not get query type from request dict: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
continue;
}
if ((r = getdns_dict_get_int(dns_msg, "/header/id", &qid))) {
fprintf( stderr, "Could not get message ID from request dict: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
continue;
}
getdns_dict_destroy(dns_msg);
r = getdns_general_sync(ctxt, qname_str, qtype, NULL, &dns_msg);
free(qname_str);
if (r) {
fprintf( stderr, "Could query for \"%s\" %d: \"%s\"\n", qname_str, (int)qtype
, getdns_get_errorstr_by_id(r));
continue;
}
if ((r = getdns_dict_set_int(dns_msg, "/replies_tree/0/header/id", qid))) {
fprintf( stderr, "Could not set message ID on reply dict: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
continue;
}
pkt_len = sizeof(mesg) - 2;
if ((r = getdns_msg_dict2wire_buf(dns_msg, mesg + 2, &pkt_len))) {
fprintf( stderr, "Could not convert DNS message dict to wireformat: \"%s\"\n"
, getdns_get_errorstr_by_id(r));
}
getdns_dict_destroy(dns_msg);
if (udp_count > 0) {
sendto(udp, (void*)ldns_buffer_begin(send_buf), ldns_buffer_position(send_buf),
sendto(udp, mesg + 2, pkt_len,
0, (struct sockaddr *) &client_addr, sizeof (client_addr));
} else if (conn > 0) {
uint8_t *send_array;
/* add length of packet */
send_array = LDNS_XMALLOC(uint8_t, ldns_buffer_position(send_buf) + 2);
if(!send_array) return 0;
ldns_write_uint16(send_array, ldns_buffer_position(send_buf));
memcpy(send_array + 2, ldns_buffer_begin(send_buf), ldns_buffer_position(send_buf));
if (write(conn, (void*)send_array, ldns_buffer_position(send_buf) + 2) == -1) return 0;
LDNS_FREE(send_array);
mesg[0] = (uint8_t) ((pkt_len >> 8) & 0xff);
mesg[1] = (uint8_t) (pkt_len & 0xff);
if (write(conn, mesg, pkt_len + 2) == -1) return 0;
}
LDNS_FREE(send_buf);
ldns_pkt_free(pkt);
} /* End of if */
} /* end of while loop */
close(udp);
close(tcp);
if (conn > 0) close(conn);
ldns_resolver_deep_free(resolver);
getdns_context_destroy(ctxt);
tdata->udp_count = udp_count;
tdata->tcp_count = tcp_count;
return NULL;