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 */ 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 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 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 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 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 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 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. */ 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 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 */ 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 */ 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