From: Wouter Wijngaards Date: Fri, 8 Feb 2008 10:59:18 +0000 (+0000) Subject: do multiple queries over TCP. X-Git-Tag: release-0.9~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=04edbb68b7ba2f2307173016d63e5f8f1026b9eb;p=thirdparty%2Funbound.git do multiple queries over TCP. git-svn-id: file:///svn/unbound/trunk@935 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/Makefile.in b/Makefile.in index 0a2341ea2..fc3aefb2e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -92,13 +92,15 @@ MEMSTATS_SRC=testcode/memstats.c smallapp/worker_cb.c $(COMMON_SRC) MEMSTATS_OBJ=$(addprefix $(BUILD),$(MEMSTATS_SRC:.c=.o)) $(COMPAT_OBJ) ASYNCLOOK_SRC=testcode/asynclook.c ASYNCLOOK_OBJ=$(addprefix $(BUILD),$(ASYNCLOOK_SRC:.c=.o)) $(COMPAT_OBJ) +STREAMTCP_SRC=testcode/streamtcp.c smallapp/worker_cb.c $(COMMON_SRC) +STREAMTCP_OBJ=$(addprefix $(BUILD),$(STREAMTCP_SRC:.c=.o)) $(COMPAT_OBJ) LIBUNBOUND_SRC=$(patsubst $(srcdir)/%,%, \ $(wildcard $(srcdir)/libunbound/*.c) $(COMMON_SRC)) LIBUNBOUND_OBJ=$(addprefix $(BUILD),$(LIBUNBOUND_SRC:.c=.o)) $(COMPAT_OBJ) -ALL_SRC=$(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \ +ALL_SRC=$(sort $(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \ $(TESTBOUND_SRC) $(LOCKVERIFY_SRC) $(PKTVIEW_SRC) $(SIGNIT_SRC) \ $(MEMSTATS_SRC) $(CHECKCONF_SRC) $(LIBUNBOUND_SRC) $(HOST_SRC) \ - $(ASYNCLOOK_SRC) + $(ASYNCLOOK_SRC) $(STREAMTCP_SRC)) ALL_OBJ=$(addprefix $(BUILD),$(ALL_SRC:.c=.o) \ $(addprefix compat/,$(LIBOBJS))) $(COMPAT_OBJ) @@ -117,7 +119,8 @@ $(BUILD)%.o: $(srcdir)/%.c all: $(COMMON_OBJ) unbound unbound-checkconf lib unbound-host -tests: all unittest testbound lock-verify pktview signit memstats asynclook +tests: all unittest testbound lock-verify pktview signit memstats \ + asynclook streamtcp test: tests bash testcode/do-tests.sh @@ -177,6 +180,10 @@ asynclook: $(ASYNCLOOK_OBJ) $(ldnslib) libunbound.la $(INFO) Link $@ $Q$(LINK) -o $@ $(sort $(ASYNCLOOK_OBJ)) $(LIBS) -L. -L.libs -lunbound +streamtcp: $(STREAMTCP_OBJ) $(ldnslib) + $(INFO) Link $@ + $Q$(LINK) -o $@ $(sort $(STREAMTCP_OBJ)) $(LIBS) + #testcode/ldns-testpkts.c: $(ldnsdir)/examples/ldns-testpkts.c \ # $(ldnsdir)/examples/ldns-testpkts.h # cp $(ldnsdir)/examples/ldns-testpkts.c testcode/ldns-testpkts.c diff --git a/doc/Changelog b/doc/Changelog index 76dcc0691..ff85eb9a9 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,8 @@ +8 February 2008: Wouter + - test program for multiple queries over a TCP channel. + - tpkg test for stream tcp queries. + - unbound replies to multiple TCP queries on a TCP channel. + 7 February 2008: Wouter - moved up all current level 2 to be level 3. And 3 to 4. to make room for new debug level 2 for detailed information diff --git a/testcode/streamtcp.c b/testcode/streamtcp.c new file mode 100644 index 000000000..6fbeb3904 --- /dev/null +++ b/testcode/streamtcp.c @@ -0,0 +1,239 @@ +/* + * testcode/streamtcp.c - debug program perform multiple DNS queries on tcp. + * + * Copyright (c) 2008, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This program performs multiple DNS queries on a TCP stream. + */ + +#include "config.h" +#include +#include "util/locks.h" +#include "util/log.h" +#include "util/net_help.h" +#include "util/data/msgencode.h" +#include "util/data/msgreply.h" +#include "util/data/dname.h" + +/** usage information for streamtcp */ +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("-h this help text\n"); + exit(1); +} + +/** open TCP socket to svr */ +static int +open_svr(char* svr) +{ + struct sockaddr_storage addr; + socklen_t addrlen; + int fd = -1; + /* svr can be ip@port */ + if(!extstrtoaddr(svr, &addr, &addrlen)) { + printf("fatal: bad server specs '%s'\n", svr); + exit(1); + } + fd = socket(addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET, + SOCK_STREAM, 0); + if(fd == -1) { + perror("socket() error"); + exit(1); + } + if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) { + perror("connect() error"); + exit(1); + } + return fd; +} + +/** write a query over the TCP fd */ +static void +write_q(int fd, ldns_buffer* buf, int id, + char* strname, char* strtype, char* strclass) +{ + struct query_info qinfo; + ldns_rdf* rdf; + int labs; + uint16_t len; + /* qname */ + rdf = ldns_dname_new_frm_str(strname); + if(!rdf) { + printf("cannot parse query name: '%s'\n", strname); + exit(1); + } + qinfo.qname = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf)); + labs = dname_count_size_labels(qinfo.qname, &qinfo.qname_len); + ldns_rdf_deep_free(rdf); + if(!qinfo.qname) fatal_exit("out of memory"); + + /* qtype and qclass */ + qinfo.qtype = ldns_get_rr_type_by_name(strtype); + qinfo.qclass = ldns_get_rr_class_by_name(strclass); + + /* make query */ + qinfo_query_encode(buf, &qinfo); + ldns_buffer_write_u16_at(buf, 0, (uint16_t)id); + ldns_buffer_write_u16_at(buf, 2, BIT_RD); + + /* send it */ + len = (uint16_t)ldns_buffer_limit(buf); + len = htons(len); + if(write(fd, &len, sizeof(len)) < (ssize_t)sizeof(len)) { + perror("write() len failed"); + exit(1); + } + if(write(fd, ldns_buffer_begin(buf), ldns_buffer_limit(buf)) < + (ssize_t)ldns_buffer_limit(buf)) { + perror("write() data failed"); + exit(1); + } + + free(qinfo.qname); +} + +/** receive DNS datagram over TCP and print it */ +static void +recv_one(int fd, ldns_buffer* buf) +{ + uint16_t len; + ldns_pkt* pkt; + ldns_status status; + if(read(fd, &len, sizeof(len)) < (ssize_t)sizeof(len)) { + perror("read() len failed"); + exit(1); + } + len = ntohs(len); + ldns_buffer_clear(buf); + ldns_buffer_set_limit(buf, len); + if(read(fd, ldns_buffer_begin(buf), len) < (ssize_t)len) { + perror("read() data failed"); + exit(1); + } + printf("\nnext received packet\n"); + log_buf(0, "data", buf); + + status = ldns_wire2pkt(&pkt, ldns_buffer_begin(buf), len); + if(status != LDNS_STATUS_OK) { + printf("could not parse incoming packet: %s\n", + ldns_get_errorstr_by_id(status)); + log_buf(0, "data was", buf); + exit(1); + } + ldns_pkt_print(stdout, pkt); + ldns_pkt_free(pkt); +} + +/** send the TCP queries and print answers */ +static void +send_em(char* svr, int num, char** qs) +{ + ldns_buffer* buf = ldns_buffer_new(65553); + int fd = open_svr(svr); + int i; + if(!buf) fatal_exit("out of memory"); + for(i=0; itcp_do_toggle_rw) c->tcp_is_reading = 1; c->tcp_byte_count = 0; + /* switch from listening(write) to listening(read) */ comm_point_stop_listening(c); - if(c->tcp_parent) /* for listening socket */ - reclaim_tcp_handler(c); - else /* its outgoing socket, start listening for reading */ - comm_point_start_listening(c, -1, -1); + comm_point_start_listening(c, -1, -1); } /** do the callback when reading is done */