1 /*
2  * testcode/streamtcp.c - debug program perform multiple DNS queries on tcp.
3  *
4  * Copyright (c) 2008, NLnet Labs. All rights reserved.
5  *
6  * This software is open source.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
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.
18  *
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.
22  *
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.
34  */
35 
36 /**
37  * \file
38  *
39  * This program performs multiple DNS queries on a TCP stream.
40  */
41 
42 #include "config.h"
43 #ifdef HAVE_GETOPT_H
44 #include <getopt.h>
45 #endif
46 #include <signal.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include "util/locks.h"
50 #include "util/log.h"
51 #include "util/net_help.h"
52 #include "util/proxy_protocol.h"
53 #include "util/data/msgencode.h"
54 #include "util/data/msgparse.h"
55 #include "util/data/msgreply.h"
56 #include "util/data/dname.h"
57 #include "sldns/sbuffer.h"
58 #include "sldns/str2wire.h"
59 #include "sldns/wire2str.h"
60 #include <openssl/ssl.h>
61 #include <openssl/rand.h>
62 #include <openssl/err.h>
63 
64 #ifndef PF_INET6
65 /** define in case streamtcp is compiled on legacy systems */
66 #define PF_INET6 10
67 #endif
68 
69 /** usage information for streamtcp */
usage(char * argv[])70 static void usage(char* argv[])
71 {
72 	printf("usage: %s [options] name type class ...\n", argv[0]);
73 	printf("	sends the name-type-class queries over TCP.\n");
74 	printf("-f server	what ipaddr@portnr to send the queries to\n");
75 	printf("-p client	what ipaddr@portnr to include in PROXYv2\n");
76 	printf("-u 		use UDP. No retries are attempted.\n");
77 	printf("-n 		do not wait for an answer.\n");
78 	printf("-a 		print answers as they arrive.\n");
79 	printf("-d secs		delay after connection before sending query\n");
80 	printf("-s		use ssl\n");
81 	printf("-h 		this help text\n");
82 	printf("IXFR=N 		for the type, sends ixfr query with serial N.\n");
83 	printf("NOTIFY[=N] 	for the type, sends notify. Can set new zone serial N.\n");
84 	exit(1);
85 }
86 
87 /** open TCP socket to svr */
88 static int
open_svr(const char * svr,int udp,struct sockaddr_storage * addr,socklen_t * addrlen)89 open_svr(const char* svr, int udp, struct sockaddr_storage* addr,
90 	socklen_t* addrlen)
91 {
92 	int fd = -1;
93 	/* svr can be ip@port */
94 	memset(addr, 0, sizeof(*addr));
95 	if(!extstrtoaddr(svr, addr, addrlen, UNBOUND_DNS_PORT)) {
96 		printf("fatal: bad server specs '%s'\n", svr);
97 		exit(1);
98 	}
99 	fd = socket(addr_is_ip6(addr, *addrlen)?PF_INET6:PF_INET,
100 		udp?SOCK_DGRAM:SOCK_STREAM, 0);
101 	if(fd == -1) {
102 #ifndef USE_WINSOCK
103 		perror("socket() error");
104 #else
105 		printf("socket: %s\n", wsa_strerror(WSAGetLastError()));
106 #endif
107 		exit(1);
108 	}
109 	if(connect(fd, (struct sockaddr*)addr, *addrlen) < 0) {
110 #ifndef USE_WINSOCK
111 		perror("connect() error");
112 #else
113 		printf("connect: %s\n", wsa_strerror(WSAGetLastError()));
114 #endif
115 		exit(1);
116 	}
117 	return fd;
118 }
119 
120 /** Append a SOA record with serial number */
121 static void
write_soa_serial_to_buf(sldns_buffer * buf,struct query_info * qinfo,uint32_t serial)122 write_soa_serial_to_buf(sldns_buffer* buf, struct query_info* qinfo,
123 	uint32_t serial)
124 {
125 	sldns_buffer_set_position(buf, sldns_buffer_limit(buf));
126 	sldns_buffer_set_limit(buf, sldns_buffer_capacity(buf));
127 	/* Write compressed reference to the query */
128 	sldns_buffer_write_u16(buf, PTR_CREATE(LDNS_HEADER_SIZE));
129 	sldns_buffer_write_u16(buf, LDNS_RR_TYPE_SOA);
130 	sldns_buffer_write_u16(buf, qinfo->qclass);
131 	sldns_buffer_write_u32(buf, 3600); /* TTL */
132 	sldns_buffer_write_u16(buf, 1+1+4*5); /* rdatalen */
133 	sldns_buffer_write_u8(buf, 0); /* primary "." */
134 	sldns_buffer_write_u8(buf, 0); /* email "." */
135 	sldns_buffer_write_u32(buf, serial); /* serial */
136 	sldns_buffer_write_u32(buf, 0); /* refresh */
137 	sldns_buffer_write_u32(buf, 0); /* retry */
138 	sldns_buffer_write_u32(buf, 0); /* expire */
139 	sldns_buffer_write_u32(buf, 0); /* minimum */
140 	sldns_buffer_flip(buf);
141 }
142 
143 /** write a query over the TCP fd */
144 static void
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)145 write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
146 	sldns_buffer* proxy_buf, int pp2_parsed,
147 	const char* strname, const char* strtype, const char* strclass)
148 {
149 	struct query_info qinfo;
150 	size_t proxy_buf_limit = sldns_buffer_limit(proxy_buf);
151 	int have_serial = 0, is_notify = 0;
152 	uint32_t serial = 0;
153 	/* qname */
154 	qinfo.qname = sldns_str2wire_dname(strname, &qinfo.qname_len);
155 	if(!qinfo.qname) {
156 		printf("cannot parse query name: '%s'\n", strname);
157 		exit(1);
158 	}
159 
160 	/* qtype */
161 	if(strncasecmp(strtype, "IXFR=", 5) == 0) {
162 		serial = (uint32_t)atoi(strtype+5);
163 		have_serial = 1;
164 		qinfo.qtype = LDNS_RR_TYPE_IXFR;
165 	} else if(strcasecmp(strtype, "NOTIFY") == 0) {
166 		is_notify = 1;
167 		qinfo.qtype = LDNS_RR_TYPE_SOA;
168 	} else if(strncasecmp(strtype, "NOTIFY=", 7) == 0) {
169 		serial = (uint32_t)atoi(strtype+7);
170 		have_serial = 1;
171 		is_notify = 1;
172 		qinfo.qtype = LDNS_RR_TYPE_SOA;
173 	} else {
174 		qinfo.qtype = sldns_get_rr_type_by_name(strtype);
175 		if(qinfo.qtype == 0 && strcmp(strtype, "TYPE0") != 0) {
176 			printf("cannot parse query type: '%s'\n", strtype);
177 			exit(1);
178 		}
179 	}
180 	/* qclass */
181 	qinfo.qclass = sldns_get_rr_class_by_name(strclass);
182 	if(qinfo.qclass == 0 && strcmp(strclass, "CLASS0") != 0) {
183 		printf("cannot parse query class: '%s'\n", strclass);
184 		exit(1);
185 	}
186 
187 	/* clear local alias */
188 	qinfo.local_alias = NULL;
189 
190 	/* make query */
191 	qinfo_query_encode(buf, &qinfo);
192 	sldns_buffer_write_u16_at(buf, 0, id);
193 	sldns_buffer_write_u16_at(buf, 2, BIT_RD);
194 
195 	if(have_serial && qinfo.qtype == LDNS_RR_TYPE_IXFR) {
196 		/* Attach serial to SOA record in the authority section. */
197 		write_soa_serial_to_buf(buf, &qinfo, serial);
198 		LDNS_NSCOUNT_SET(sldns_buffer_begin(buf), 1);
199 	}
200 	if(is_notify) {
201 		LDNS_OPCODE_SET(sldns_buffer_begin(buf), LDNS_PACKET_NOTIFY);
202 		LDNS_RD_CLR(sldns_buffer_begin(buf));
203 		LDNS_AA_SET(sldns_buffer_begin(buf));
204 		if(have_serial) {
205 			write_soa_serial_to_buf(buf, &qinfo, serial);
206 			LDNS_ANCOUNT_SET(sldns_buffer_begin(buf), 1);
207 		}
208 	}
209 
210 	if(1) {
211 		/* add EDNS DO */
212 		struct edns_data edns;
213 		memset(&edns, 0, sizeof(edns));
214 		edns.edns_present = 1;
215 		edns.bits = EDNS_DO;
216 		edns.udp_size = 4096;
217 		if(sldns_buffer_capacity(buf) >=
218 			sldns_buffer_limit(buf)+calc_edns_field_size(&edns))
219 			attach_edns_record(buf, &edns);
220 	}
221 
222 	/* we need to send the PROXYv2 information in every UDP message */
223 	if(udp && pp2_parsed) {
224 		/* append the proxy_buf with the buf's content
225 		 * and use that for sending */
226 		if(sldns_buffer_capacity(proxy_buf) <
227 			sldns_buffer_limit(proxy_buf) +
228 			sldns_buffer_limit(buf)) {
229 			printf("buffer too small for packet + proxy");
230 			exit(1);
231 		}
232 		sldns_buffer_clear(proxy_buf);
233 		sldns_buffer_skip(proxy_buf, proxy_buf_limit);
234 		sldns_buffer_write(proxy_buf, sldns_buffer_begin(buf),
235 			sldns_buffer_limit(buf));
236 		sldns_buffer_flip(proxy_buf);
237 		buf = proxy_buf;
238 	}
239 
240 	/* send it */
241 	if(!udp) {
242 		uint16_t len = (uint16_t)sldns_buffer_limit(buf);
243 		len = htons(len);
244 		if(ssl) {
245 			if(SSL_write(ssl, (void*)&len, (int)sizeof(len)) <= 0) {
246 				log_crypto_err("cannot SSL_write");
247 				exit(1);
248 			}
249 		} else {
250 			if(send(fd, (void*)&len, sizeof(len), 0) <
251 				(ssize_t)sizeof(len)){
252 #ifndef USE_WINSOCK
253 				perror("send() len failed");
254 #else
255 				printf("send len: %s\n",
256 					wsa_strerror(WSAGetLastError()));
257 #endif
258 				exit(1);
259 			}
260 		}
261 	}
262 	if(ssl) {
263 		if(SSL_write(ssl, (void*)sldns_buffer_begin(buf),
264 			(int)sldns_buffer_limit(buf)) <= 0) {
265 			log_crypto_err("cannot SSL_write");
266 			exit(1);
267 		}
268 	} else {
269 		if(send(fd, (void*)sldns_buffer_begin(buf),
270 			sldns_buffer_limit(buf), 0) <
271 			(ssize_t)sldns_buffer_limit(buf)) {
272 #ifndef USE_WINSOCK
273 			perror("send() data failed");
274 #else
275 			printf("send data: %s\n",
276 				wsa_strerror(WSAGetLastError()));
277 #endif
278 			exit(1);
279 		}
280 	}
281 
282 	/* reset the proxy_buf for next packet */
283 	sldns_buffer_set_limit(proxy_buf, proxy_buf_limit);
284 	free(qinfo.qname);
285 }
286 
287 /** receive DNS datagram over TCP and print it */
288 static void
recv_one(int fd,int udp,SSL * ssl,sldns_buffer * buf)289 recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf)
290 {
291 	size_t i;
292 	char* pktstr;
293 	uint16_t len;
294 	if(!udp) {
295 		if(ssl) {
296 			int sr = SSL_read(ssl, (void*)&len, (int)sizeof(len));
297 			if(sr == 0) {
298 				printf("ssl: stream closed\n");
299 				exit(1);
300 			}
301 			if(sr < 0) {
302 				log_crypto_err("could not SSL_read");
303 				exit(1);
304 			}
305 		} else {
306 			ssize_t r = recv(fd, (void*)&len, sizeof(len), 0);
307 			if(r == 0) {
308 				printf("recv: stream closed\n");
309 				exit(1);
310 			}
311 			if(r < (ssize_t)sizeof(len)) {
312 #ifndef USE_WINSOCK
313 				perror("read() len failed");
314 #else
315 				printf("read len: %s\n",
316 					wsa_strerror(WSAGetLastError()));
317 #endif
318 				exit(1);
319 			}
320 		}
321 		len = ntohs(len);
322 		sldns_buffer_clear(buf);
323 		sldns_buffer_set_limit(buf, len);
324 		if(ssl) {
325 			int r = SSL_read(ssl, (void*)sldns_buffer_begin(buf),
326 				(int)len);
327 			if(r <= 0) {
328 				log_crypto_err("could not SSL_read");
329 				exit(1);
330 			}
331 			if(r != (int)len)
332 				fatal_exit("ssl_read %d of %d", r, len);
333 		} else {
334 			if(recv(fd, (void*)sldns_buffer_begin(buf), len, 0) <
335 				(ssize_t)len) {
336 #ifndef USE_WINSOCK
337 				perror("read() data failed");
338 #else
339 				printf("read data: %s\n",
340 					wsa_strerror(WSAGetLastError()));
341 #endif
342 				exit(1);
343 			}
344 		}
345 	} else {
346 		ssize_t l;
347 		sldns_buffer_clear(buf);
348 		if((l=recv(fd, (void*)sldns_buffer_begin(buf),
349 			sldns_buffer_capacity(buf), 0)) < 0) {
350 #ifndef USE_WINSOCK
351 			perror("read() data failed");
352 #else
353 			printf("read data: %s\n",
354 				wsa_strerror(WSAGetLastError()));
355 #endif
356 			exit(1);
357 		}
358 		sldns_buffer_set_limit(buf, (size_t)l);
359 		len = (size_t)l;
360 	}
361 	printf("\nnext received packet\n");
362 	printf("data[%d] ", (int)sldns_buffer_limit(buf));
363 	for(i=0; i<sldns_buffer_limit(buf); i++) {
364 		const char* hex = "0123456789ABCDEF";
365 		printf("%c%c", hex[(sldns_buffer_read_u8_at(buf, i)&0xf0)>>4],
366                         hex[sldns_buffer_read_u8_at(buf, i)&0x0f]);
367 	}
368 	printf("\n");
369 
370 	pktstr = sldns_wire2str_pkt(sldns_buffer_begin(buf), len);
371 	printf("%s", pktstr);
372 	free(pktstr);
373 }
374 
375 /** see if we can receive any results */
376 static void
print_any_answers(int fd,int udp,SSL * ssl,sldns_buffer * buf,int * num_answers,int wait_all)377 print_any_answers(int fd, int udp, SSL* ssl, sldns_buffer* buf,
378 	int* num_answers, int wait_all)
379 {
380 	/* see if the fd can read, if so, print one answer, repeat */
381 	int ret;
382 	struct timeval tv, *waittv;
383 	fd_set rfd;
384 	while(*num_answers > 0) {
385 		memset(&rfd, 0, sizeof(rfd));
386 		memset(&tv, 0, sizeof(tv));
387 		FD_ZERO(&rfd);
388 		FD_SET(fd, &rfd);
389 		if(wait_all) waittv = NULL;
390 		else waittv = &tv;
391 		ret = select(fd+1, &rfd, NULL, NULL, waittv);
392 		if(ret < 0) {
393 			if(errno == EINTR || errno == EAGAIN) continue;
394 			perror("select() failed");
395 			exit(1);
396 		}
397 		if(ret == 0) {
398 			if(wait_all) continue;
399 			return;
400 		}
401 		(*num_answers) -= 1;
402 		recv_one(fd, udp, ssl, buf);
403 	}
404 }
405 
get_random(void)406 static int get_random(void)
407 {
408 	int r;
409 	if (RAND_bytes((unsigned char*)&r, (int)sizeof(r)) == 1) {
410 		return r;
411 	}
412 	return (int)arc4random();
413 }
414 
415 /* parse the pp2_client and populate the proxy_buffer
416  * It doesn't populate the destination parts. */
parse_pp2_client(const char * pp2_client,int udp,sldns_buffer * proxy_buf)417 static int parse_pp2_client(const char* pp2_client, int udp,
418 	sldns_buffer* proxy_buf)
419 {
420 	struct sockaddr_storage pp2_addr;
421 	size_t bytes_written;
422 	socklen_t pp2_addrlen = 0;
423 	memset(&pp2_addr, 0, sizeof(pp2_addr));
424 	if(*pp2_client == 0) return 0;
425 	if(!extstrtoaddr(pp2_client, &pp2_addr, &pp2_addrlen, UNBOUND_DNS_PORT)) {
426 		printf("fatal: bad proxy client specs '%s'\n", pp2_client);
427 		exit(1);
428 	}
429 	sldns_buffer_clear(proxy_buf);
430 	bytes_written = pp2_write_to_buf(sldns_buffer_begin(proxy_buf),
431 		sldns_buffer_remaining(proxy_buf), &pp2_addr, !udp);
432 	sldns_buffer_set_position(proxy_buf, bytes_written);
433 	sldns_buffer_flip(proxy_buf);
434 	return 1;
435 }
436 
437 /** send the TCP queries and print answers */
438 static void
send_em(const char * svr,const char * pp2_client,int udp,int usessl,int noanswer,int onarrival,int delay,int num,char ** qs)439 send_em(const char* svr, const char* pp2_client, int udp, int usessl,
440 	int noanswer, int onarrival, int delay, int num, char** qs)
441 {
442 	struct sockaddr_storage svr_addr;
443 	socklen_t svr_addrlen;
444 	int fd = open_svr(svr, udp, &svr_addr, &svr_addrlen);
445 	int i, wait_results = 0, pp2_parsed;
446 	SSL_CTX* ctx = NULL;
447 	SSL* ssl = NULL;
448 	sldns_buffer* buf = sldns_buffer_new(65553);
449 	sldns_buffer* proxy_buf = sldns_buffer_new(65553);
450 	if(!buf || !proxy_buf) {
451 		sldns_buffer_free(buf);
452 		sldns_buffer_free(proxy_buf);
453 		fatal_exit("out of memory");
454 	}
455 	pp2_parsed = parse_pp2_client(pp2_client, udp, proxy_buf);
456 	if(usessl) {
457 		ctx = connect_sslctx_create(NULL, NULL, NULL, 0);
458 		if(!ctx) fatal_exit("cannot create ssl ctx");
459 		ssl = outgoing_ssl_fd(ctx, fd);
460 		if(!ssl) fatal_exit("cannot create ssl");
461 		while(1) {
462 			int r;
463 			ERR_clear_error();
464 			if( (r=SSL_do_handshake(ssl)) == 1)
465 				break;
466 			r = SSL_get_error(ssl, r);
467 			if(r != SSL_ERROR_WANT_READ &&
468 				r != SSL_ERROR_WANT_WRITE) {
469 				log_crypto_err_io("could not ssl_handshake", r);
470 				exit(1);
471 			}
472 		}
473 		if(1) {
474 #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
475 			X509* x = SSL_get1_peer_certificate(ssl);
476 #else
477 			X509* x = SSL_get_peer_certificate(ssl);
478 #endif
479 			if(!x) printf("SSL: no peer certificate\n");
480 			else {
481 				X509_print_fp(stdout, x);
482 				X509_free(x);
483 			}
484 		}
485 	}
486 	/* Send the PROXYv2 information once per stream */
487 	if(!udp && pp2_parsed) {
488 		if(ssl) {
489 			if(SSL_write(ssl, (void*)sldns_buffer_begin(proxy_buf),
490 				(int)sldns_buffer_limit(proxy_buf)) <= 0) {
491 				log_crypto_err("cannot SSL_write");
492 				exit(1);
493 			}
494 		} else {
495 			if(send(fd, (void*)sldns_buffer_begin(proxy_buf),
496 				sldns_buffer_limit(proxy_buf), 0) <
497 				(ssize_t)sldns_buffer_limit(proxy_buf)) {
498 #ifndef USE_WINSOCK
499 				perror("send() data failed");
500 #else
501 				printf("send data: %s\n",
502 					wsa_strerror(WSAGetLastError()));
503 #endif
504 				exit(1);
505 			}
506 		}
507 	}
508 	for(i=0; i<num; i+=3) {
509 		if (delay != 0) {
510 #ifdef HAVE_SLEEP
511 			sleep((unsigned)delay);
512 #else
513 			Sleep(delay*1000);
514 #endif
515 		}
516 		printf("\nNext query is %s %s %s\n", qs[i], qs[i+1], qs[i+2]);
517 		write_q(fd, udp, ssl, buf, (uint16_t)get_random(), proxy_buf,
518 			pp2_parsed,
519 			qs[i], qs[i+1], qs[i+2]);
520 		/* print at least one result */
521 		if(onarrival) {
522 			wait_results += 1; /* one more answer to fetch */
523 			print_any_answers(fd, udp, ssl, buf, &wait_results, 0);
524 		} else if(!noanswer) {
525 			recv_one(fd, udp, ssl, buf);
526 		}
527 	}
528 	if(onarrival)
529 		print_any_answers(fd, udp, ssl, buf, &wait_results, 1);
530 
531 	if(usessl) {
532 		SSL_shutdown(ssl);
533 		SSL_free(ssl);
534 		SSL_CTX_free(ctx);
535 	}
536 	sock_close(fd);
537 	sldns_buffer_free(buf);
538 	sldns_buffer_free(proxy_buf);
539 	printf("orderly exit\n");
540 }
541 
542 #ifdef SIGPIPE
543 /** SIGPIPE handler */
sigh(int sig)544 static RETSIGTYPE sigh(int sig)
545 {
546 	char str[] = "Got unhandled signal   \n";
547 	if(sig == SIGPIPE) {
548 		char* strpipe = "got SIGPIPE, remote connection gone\n";
549 		/* simple cast to void will not silence Wunused-result */
550 		(void)!write(STDOUT_FILENO, strpipe, strlen(strpipe));
551 		exit(1);
552 	}
553 	str[21] = '0' + (sig/10)%10;
554 	str[22] = '0' + sig%10;
555 	/* simple cast to void will not silence Wunused-result */
556 	(void)!write(STDOUT_FILENO, str, strlen(str));
557 	exit(1);
558 }
559 #endif /* SIGPIPE */
560 
561 /** getopt global, in case header files fail to declare it. */
562 extern int optind;
563 /** getopt global, in case header files fail to declare it. */
564 extern char* optarg;
565 
566 /** main program for streamtcp */
main(int argc,char ** argv)567 int main(int argc, char** argv)
568 {
569 	int c;
570 	const char* svr = "127.0.0.1";
571 	const char* pp2_client = "";
572 	int udp = 0;
573 	int noanswer = 0;
574 	int onarrival = 0;
575 	int usessl = 0;
576 	int delay = 0;
577 
578 #ifdef USE_WINSOCK
579 	WSADATA wsa_data;
580 	if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) {
581 		printf("WSAStartup failed\n");
582 		return 1;
583 	}
584 #endif
585 
586 	/* lock debug start (if any) */
587 	checklock_start();
588 	log_init(0, 0, 0);
589 
590 #ifdef SIGPIPE
591 	if(signal(SIGPIPE, &sigh) == SIG_ERR) {
592 		perror("could not install signal handler");
593 		return 1;
594 	}
595 #endif
596 
597 	/* command line options */
598 	if(argc == 1) {
599 		usage(argv);
600 	}
601 	while( (c=getopt(argc, argv, "af:p:hnsud:")) != -1) {
602 		switch(c) {
603 			case 'f':
604 				svr = optarg;
605 				break;
606 			case 'p':
607 				pp2_client = optarg;
608 				pp_init(&sldns_write_uint16,
609 					&sldns_write_uint32);
610 				break;
611 			case 'a':
612 				onarrival = 1;
613 				break;
614 			case 'n':
615 				noanswer = 1;
616 				break;
617 			case 'u':
618 				udp = 1;
619 				break;
620 			case 's':
621 				usessl = 1;
622 				break;
623 			case 'd':
624 				if(atoi(optarg)==0 && strcmp(optarg,"0")!=0) {
625 					printf("error parsing delay, "
626 					    "number expected: %s\n", optarg);
627 					return 1;
628 				}
629 				delay = atoi(optarg);
630 				break;
631 			case 'h':
632 			case '?':
633 			default:
634 				usage(argv);
635 		}
636 	}
637 	argc -= optind;
638 	argv += optind;
639 
640 	if(argc % 3 != 0) {
641 		printf("queries must be multiples of name,type,class\n");
642 		return 1;
643 	}
644 	if(usessl) {
645 #if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
646 		ERR_load_SSL_strings();
647 #endif
648 #if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
649 #  ifndef S_SPLINT_S
650 		OpenSSL_add_all_algorithms();
651 #  endif
652 #else
653 		OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
654 			| OPENSSL_INIT_ADD_ALL_DIGESTS
655 			| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
656 #endif
657 #if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
658 		(void)SSL_library_init();
659 #else
660 		(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
661 #endif
662 	}
663 	send_em(svr, pp2_client, udp, usessl, noanswer, onarrival, delay, argc, argv);
664 	checklock_stop();
665 #ifdef USE_WINSOCK
666 	WSACleanup();
667 #endif
668 	return 0;
669 }
670