From 9ef094b356b4da7542c3cab898dac7e135b76903 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sun, 5 Oct 2014 23:44:31 +0200 Subject: added unbound to external deps --- external/unbound/testcode/streamtcp.c | 418 ++++++++++++++++++++++++++++++++++ 1 file changed, 418 insertions(+) create mode 100644 external/unbound/testcode/streamtcp.c (limited to 'external/unbound/testcode/streamtcp.c') diff --git a/external/unbound/testcode/streamtcp.c b/external/unbound/testcode/streamtcp.c new file mode 100644 index 000000000..d93ab966d --- /dev/null +++ b/external/unbound/testcode/streamtcp.c @@ -0,0 +1,418 @@ +/* + * 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 COPYRIGHT + * HOLDER 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" +#ifdef HAVE_GETOPT_H +#include +#endif +#include +#include "util/locks.h" +#include "util/log.h" +#include "util/net_help.h" +#include "util/data/msgencode.h" +#include "util/data/msgparse.h" +#include "util/data/msgreply.h" +#include "util/data/dname.h" +#include "ldns/sbuffer.h" +#include "ldns/str2wire.h" +#include "ldns/wire2str.h" +#include +#include +#include + +#ifndef PF_INET6 +/** define in case streamtcp is compiled on legacy systems */ +#define PF_INET6 10 +#endif + +/** usage information for streamtcp */ +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("-u use UDP. No retries are attempted.\n"); + printf("-n do not wait for an answer.\n"); + printf("-s use ssl\n"); + printf("-h this help text\n"); + exit(1); +} + +/** open TCP socket to svr */ +static int +open_svr(const char* svr, int udp) +{ + 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)) { + printf("fatal: bad server specs '%s'\n", svr); + exit(1); + } + fd = socket(addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET, + udp?SOCK_DGRAM:SOCK_STREAM, 0); + if(fd == -1) { +#ifndef USE_WINSOCK + perror("socket() error"); +#else + printf("socket: %s\n", wsa_strerror(WSAGetLastError())); +#endif + exit(1); + } + if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) { +#ifndef USE_WINSOCK + perror("connect() error"); +#else + printf("connect: %s\n", wsa_strerror(WSAGetLastError())); +#endif + exit(1); + } + return fd; +} + +/** write a query over the TCP fd */ +static void +write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id, + const char* strname, const char* strtype, const char* strclass) +{ + struct query_info qinfo; + uint16_t len; + /* qname */ + qinfo.qname = sldns_str2wire_dname(strname, &qinfo.qname_len); + if(!qinfo.qname) { + printf("cannot parse query name: '%s'\n", strname); + exit(1); + } + + /* qtype and qclass */ + qinfo.qtype = sldns_get_rr_type_by_name(strtype); + qinfo.qclass = sldns_get_rr_class_by_name(strclass); + + /* make query */ + qinfo_query_encode(buf, &qinfo); + sldns_buffer_write_u16_at(buf, 0, id); + sldns_buffer_write_u16_at(buf, 2, BIT_RD); + + if(1) { + /* add EDNS DO */ + struct edns_data edns; + memset(&edns, 0, sizeof(edns)); + edns.edns_present = 1; + edns.bits = EDNS_DO; + edns.udp_size = 4096; + attach_edns_record(buf, &edns); + } + + /* send it */ + if(!udp) { + len = (uint16_t)sldns_buffer_limit(buf); + len = htons(len); + if(ssl) { + if(SSL_write(ssl, (void*)&len, (int)sizeof(len)) <= 0) { + log_crypto_err("cannot SSL_write"); + exit(1); + } + } else { + if(send(fd, (void*)&len, sizeof(len), 0) < + (ssize_t)sizeof(len)){ +#ifndef USE_WINSOCK + perror("send() len failed"); +#else + printf("send len: %s\n", + wsa_strerror(WSAGetLastError())); +#endif + exit(1); + } + } + } + if(ssl) { + if(SSL_write(ssl, (void*)sldns_buffer_begin(buf), + (int)sldns_buffer_limit(buf)) <= 0) { + log_crypto_err("cannot SSL_write"); + exit(1); + } + } else { + if(send(fd, (void*)sldns_buffer_begin(buf), + 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())); +#endif + exit(1); + } + } + + free(qinfo.qname); +} + +/** receive DNS datagram over TCP and print it */ +static void +recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf) +{ + char* pktstr; + uint16_t len; + if(!udp) { + if(ssl) { + if(SSL_read(ssl, (void*)&len, (int)sizeof(len)) <= 0) { + log_crypto_err("could not SSL_read"); + exit(1); + } + } else { + if(recv(fd, (void*)&len, sizeof(len), 0) < + (ssize_t)sizeof(len)) { +#ifndef USE_WINSOCK + perror("read() len failed"); +#else + printf("read len: %s\n", + wsa_strerror(WSAGetLastError())); +#endif + exit(1); + } + } + len = ntohs(len); + sldns_buffer_clear(buf); + sldns_buffer_set_limit(buf, len); + if(ssl) { + int r = SSL_read(ssl, (void*)sldns_buffer_begin(buf), + (int)len); + if(r <= 0) { + log_crypto_err("could not SSL_read"); + exit(1); + } + if(r != (int)len) + fatal_exit("ssl_read %d of %d", r, len); + } else { + 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", + wsa_strerror(WSAGetLastError())); +#endif + exit(1); + } + } + } else { + ssize_t l; + sldns_buffer_clear(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", + wsa_strerror(WSAGetLastError())); +#endif + exit(1); + } + sldns_buffer_set_limit(buf, (size_t)l); + len = (size_t)l; + } + printf("\nnext received packet\n"); + log_buf(0, "data", buf); + + pktstr = sldns_wire2str_pkt(sldns_buffer_begin(buf), len); + printf("%s", pktstr); + free(pktstr); +} + +static int get_random(void) +{ + int r; + if (RAND_bytes((unsigned char*)&r, (int)sizeof(r)) == 1) { + return r; + } + return (int)random(); +} + +/** send the TCP queries and print answers */ +static void +send_em(const char* svr, int udp, int usessl, int noanswer, int num, char** qs) +{ + sldns_buffer* buf = sldns_buffer_new(65553); + int fd = open_svr(svr, udp); + int i; + SSL_CTX* ctx = NULL; + SSL* ssl = NULL; + if(!buf) fatal_exit("out of memory"); + if(usessl) { + ctx = connect_sslctx_create(NULL, NULL, NULL); + if(!ctx) fatal_exit("cannot create ssl ctx"); + ssl = outgoing_ssl_fd(ctx, fd); + if(!ssl) fatal_exit("cannot create ssl"); + while(1) { + int r; + ERR_clear_error(); + if( (r=SSL_do_handshake(ssl)) == 1) + break; + r = SSL_get_error(ssl, r); + if(r != SSL_ERROR_WANT_READ && + r != SSL_ERROR_WANT_WRITE) { + log_crypto_err("could not ssl_handshake"); + exit(1); + } + } + if(1) { + X509* x = SSL_get_peer_certificate(ssl); + if(!x) printf("SSL: no peer certificate\n"); + else { + X509_print_fp(stdout, x); + X509_free(x); + } + } + } + for(i=0; i