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