]>
git.saurik.com Git - apple/network_cmds.git/blob - unbound/testcode/streamtcp.c
d93ab966d564343e6507b0110f4e567d7e2522f4
2 * testcode/streamtcp.c - debug program perform multiple DNS queries on tcp.
4 * Copyright (c) 2008, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 * This program performs multiple DNS queries on a TCP stream.
47 #include "util/locks.h"
49 #include "util/net_help.h"
50 #include "util/data/msgencode.h"
51 #include "util/data/msgparse.h"
52 #include "util/data/msgreply.h"
53 #include "util/data/dname.h"
54 #include "ldns/sbuffer.h"
55 #include "ldns/str2wire.h"
56 #include "ldns/wire2str.h"
57 #include <openssl/ssl.h>
58 #include <openssl/rand.h>
59 #include <openssl/err.h>
62 /** define in case streamtcp is compiled on legacy systems */
66 /** usage information for streamtcp */
67 static void usage(char* argv
[])
69 printf("usage: %s [options] name type class ...\n", argv
[0]);
70 printf(" sends the name-type-class queries over TCP.\n");
71 printf("-f server what ipaddr@portnr to send the queries to\n");
72 printf("-u use UDP. No retries are attempted.\n");
73 printf("-n do not wait for an answer.\n");
74 printf("-s use ssl\n");
75 printf("-h this help text\n");
79 /** open TCP socket to svr */
81 open_svr(const char* svr
, int udp
)
83 struct sockaddr_storage addr
;
86 /* svr can be ip@port */
87 memset(&addr
, 0, sizeof(addr
));
88 if(!extstrtoaddr(svr
, &addr
, &addrlen
)) {
89 printf("fatal: bad server specs '%s'\n", svr
);
92 fd
= socket(addr_is_ip6(&addr
, addrlen
)?PF_INET6
:PF_INET
,
93 udp
?SOCK_DGRAM
:SOCK_STREAM
, 0);
96 perror("socket() error");
98 printf("socket: %s\n", wsa_strerror(WSAGetLastError()));
102 if(connect(fd
, (struct sockaddr
*)&addr
, addrlen
) < 0) {
104 perror("connect() error");
106 printf("connect: %s\n", wsa_strerror(WSAGetLastError()));
113 /** write a query over the TCP fd */
115 write_q(int fd
, int udp
, SSL
* ssl
, sldns_buffer
* buf
, uint16_t id
,
116 const char* strname
, const char* strtype
, const char* strclass
)
118 struct query_info qinfo
;
121 qinfo
.qname
= sldns_str2wire_dname(strname
, &qinfo
.qname_len
);
123 printf("cannot parse query name: '%s'\n", strname
);
127 /* qtype and qclass */
128 qinfo
.qtype
= sldns_get_rr_type_by_name(strtype
);
129 qinfo
.qclass
= sldns_get_rr_class_by_name(strclass
);
132 qinfo_query_encode(buf
, &qinfo
);
133 sldns_buffer_write_u16_at(buf
, 0, id
);
134 sldns_buffer_write_u16_at(buf
, 2, BIT_RD
);
138 struct edns_data edns
;
139 memset(&edns
, 0, sizeof(edns
));
140 edns
.edns_present
= 1;
142 edns
.udp_size
= 4096;
143 attach_edns_record(buf
, &edns
);
148 len
= (uint16_t)sldns_buffer_limit(buf
);
151 if(SSL_write(ssl
, (void*)&len
, (int)sizeof(len
)) <= 0) {
152 log_crypto_err("cannot SSL_write");
156 if(send(fd
, (void*)&len
, sizeof(len
), 0) <
157 (ssize_t
)sizeof(len
)){
159 perror("send() len failed");
161 printf("send len: %s\n",
162 wsa_strerror(WSAGetLastError()));
169 if(SSL_write(ssl
, (void*)sldns_buffer_begin(buf
),
170 (int)sldns_buffer_limit(buf
)) <= 0) {
171 log_crypto_err("cannot SSL_write");
175 if(send(fd
, (void*)sldns_buffer_begin(buf
),
176 sldns_buffer_limit(buf
), 0) <
177 (ssize_t
)sldns_buffer_limit(buf
)) {
179 perror("send() data failed");
181 printf("send data: %s\n", wsa_strerror(WSAGetLastError()));
190 /** receive DNS datagram over TCP and print it */
192 recv_one(int fd
, int udp
, SSL
* ssl
, sldns_buffer
* buf
)
198 if(SSL_read(ssl
, (void*)&len
, (int)sizeof(len
)) <= 0) {
199 log_crypto_err("could not SSL_read");
203 if(recv(fd
, (void*)&len
, sizeof(len
), 0) <
204 (ssize_t
)sizeof(len
)) {
206 perror("read() len failed");
208 printf("read len: %s\n",
209 wsa_strerror(WSAGetLastError()));
215 sldns_buffer_clear(buf
);
216 sldns_buffer_set_limit(buf
, len
);
218 int r
= SSL_read(ssl
, (void*)sldns_buffer_begin(buf
),
221 log_crypto_err("could not SSL_read");
225 fatal_exit("ssl_read %d of %d", r
, len
);
227 if(recv(fd
, (void*)sldns_buffer_begin(buf
), len
, 0) <
230 perror("read() data failed");
232 printf("read data: %s\n",
233 wsa_strerror(WSAGetLastError()));
240 sldns_buffer_clear(buf
);
241 if((l
=recv(fd
, (void*)sldns_buffer_begin(buf
),
242 sldns_buffer_capacity(buf
), 0)) < 0) {
244 perror("read() data failed");
246 printf("read data: %s\n",
247 wsa_strerror(WSAGetLastError()));
251 sldns_buffer_set_limit(buf
, (size_t)l
);
254 printf("\nnext received packet\n");
255 log_buf(0, "data", buf
);
257 pktstr
= sldns_wire2str_pkt(sldns_buffer_begin(buf
), len
);
258 printf("%s", pktstr
);
262 static int get_random(void)
265 if (RAND_bytes((unsigned char*)&r
, (int)sizeof(r
)) == 1) {
268 return (int)random();
271 /** send the TCP queries and print answers */
273 send_em(const char* svr
, int udp
, int usessl
, int noanswer
, int num
, char** qs
)
275 sldns_buffer
* buf
= sldns_buffer_new(65553);
276 int fd
= open_svr(svr
, udp
);
280 if(!buf
) fatal_exit("out of memory");
282 ctx
= connect_sslctx_create(NULL
, NULL
, NULL
);
283 if(!ctx
) fatal_exit("cannot create ssl ctx");
284 ssl
= outgoing_ssl_fd(ctx
, fd
);
285 if(!ssl
) fatal_exit("cannot create ssl");
289 if( (r
=SSL_do_handshake(ssl
)) == 1)
291 r
= SSL_get_error(ssl
, r
);
292 if(r
!= SSL_ERROR_WANT_READ
&&
293 r
!= SSL_ERROR_WANT_WRITE
) {
294 log_crypto_err("could not ssl_handshake");
299 X509
* x
= SSL_get_peer_certificate(ssl
);
300 if(!x
) printf("SSL: no peer certificate\n");
302 X509_print_fp(stdout
, x
);
307 for(i
=0; i
<num
; i
+=3) {
308 printf("\nNext query is %s %s %s\n", qs
[i
], qs
[i
+1], qs
[i
+2]);
309 write_q(fd
, udp
, ssl
, buf
, (uint16_t)get_random(), qs
[i
],
311 /* print at least one result */
313 recv_one(fd
, udp
, ssl
, buf
);
326 sldns_buffer_free(buf
);
327 printf("orderly exit\n");
331 /** SIGPIPE handler */
332 static RETSIGTYPE
sigh(int sig
)
335 printf("got SIGPIPE, remote connection gone\n");
338 printf("Got unhandled signal %d\n", sig
);
343 /** getopt global, in case header files fail to declare it. */
345 /** getopt global, in case header files fail to declare it. */
348 /** main program for streamtcp */
349 int main(int argc
, char** argv
)
352 const char* svr
= "127.0.0.1";
359 if(WSAStartup(MAKEWORD(2,2), &wsa_data
) != 0) {
360 printf("WSAStartup failed\n");
365 /* lock debug start (if any) */
370 if(signal(SIGPIPE
, &sigh
) == SIG_ERR
) {
371 perror("could not install signal handler");
376 /* command line options */
380 while( (c
=getopt(argc
, argv
, "f:hnsu")) != -1) {
404 printf("queries must be multiples of name,type,class\n");
408 ERR_load_SSL_strings();
409 OpenSSL_add_all_algorithms();
412 send_em(svr
, udp
, usessl
, noanswer
, argc
, argv
);