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 exit(1); 83 } 84 85 /** open TCP socket to svr */ 86 static int 87 open_svr(const char* svr, int udp, struct sockaddr_storage* addr, 88 socklen_t* addrlen) 89 { 90 int fd = -1; 91 /* svr can be ip@port */ 92 memset(addr, 0, sizeof(*addr)); 93 if(!extstrtoaddr(svr, addr, addrlen, UNBOUND_DNS_PORT)) { 94 printf("fatal: bad server specs '%s'\n", svr); 95 exit(1); 96 } 97 fd = socket(addr_is_ip6(addr, *addrlen)?PF_INET6:PF_INET, 98 udp?SOCK_DGRAM:SOCK_STREAM, 0); 99 if(fd == -1) { 100 #ifndef USE_WINSOCK 101 perror("socket() error"); 102 #else 103 printf("socket: %s\n", wsa_strerror(WSAGetLastError())); 104 #endif 105 exit(1); 106 } 107 if(connect(fd, (struct sockaddr*)addr, *addrlen) < 0) { 108 #ifndef USE_WINSOCK 109 perror("connect() error"); 110 #else 111 printf("connect: %s\n", wsa_strerror(WSAGetLastError())); 112 #endif 113 exit(1); 114 } 115 return fd; 116 } 117 118 /** write a query over the TCP fd */ 119 static void 120 write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id, 121 sldns_buffer* proxy_buf, int pp2_parsed, 122 const char* strname, const char* strtype, const char* strclass) 123 { 124 struct query_info qinfo; 125 size_t proxy_buf_limit = sldns_buffer_limit(proxy_buf); 126 /* qname */ 127 qinfo.qname = sldns_str2wire_dname(strname, &qinfo.qname_len); 128 if(!qinfo.qname) { 129 printf("cannot parse query name: '%s'\n", strname); 130 exit(1); 131 } 132 133 /* qtype and qclass */ 134 qinfo.qtype = sldns_get_rr_type_by_name(strtype); 135 qinfo.qclass = sldns_get_rr_class_by_name(strclass); 136 137 /* clear local alias */ 138 qinfo.local_alias = NULL; 139 140 /* make query */ 141 qinfo_query_encode(buf, &qinfo); 142 sldns_buffer_write_u16_at(buf, 0, id); 143 sldns_buffer_write_u16_at(buf, 2, BIT_RD); 144 145 if(1) { 146 /* add EDNS DO */ 147 struct edns_data edns; 148 memset(&edns, 0, sizeof(edns)); 149 edns.edns_present = 1; 150 edns.bits = EDNS_DO; 151 edns.udp_size = 4096; 152 if(sldns_buffer_capacity(buf) >= 153 sldns_buffer_limit(buf)+calc_edns_field_size(&edns)) 154 attach_edns_record(buf, &edns); 155 } 156 157 /* we need to send the PROXYv2 information in every UDP message */ 158 if(udp && pp2_parsed) { 159 /* append the proxy_buf with the buf's content 160 * and use that for sending */ 161 if(sldns_buffer_capacity(proxy_buf) < 162 sldns_buffer_limit(proxy_buf) + 163 sldns_buffer_limit(buf)) { 164 printf("buffer too small for packet + proxy"); 165 exit(1); 166 } 167 sldns_buffer_clear(proxy_buf); 168 sldns_buffer_skip(proxy_buf, proxy_buf_limit); 169 sldns_buffer_write(proxy_buf, sldns_buffer_begin(buf), 170 sldns_buffer_limit(buf)); 171 sldns_buffer_flip(proxy_buf); 172 buf = proxy_buf; 173 } 174 175 /* send it */ 176 if(!udp) { 177 uint16_t len = (uint16_t)sldns_buffer_limit(buf); 178 len = htons(len); 179 if(ssl) { 180 if(SSL_write(ssl, (void*)&len, (int)sizeof(len)) <= 0) { 181 log_crypto_err("cannot SSL_write"); 182 exit(1); 183 } 184 } else { 185 if(send(fd, (void*)&len, sizeof(len), 0) < 186 (ssize_t)sizeof(len)){ 187 #ifndef USE_WINSOCK 188 perror("send() len failed"); 189 #else 190 printf("send len: %s\n", 191 wsa_strerror(WSAGetLastError())); 192 #endif 193 exit(1); 194 } 195 } 196 } 197 if(ssl) { 198 if(SSL_write(ssl, (void*)sldns_buffer_begin(buf), 199 (int)sldns_buffer_limit(buf)) <= 0) { 200 log_crypto_err("cannot SSL_write"); 201 exit(1); 202 } 203 } else { 204 if(send(fd, (void*)sldns_buffer_begin(buf), 205 sldns_buffer_limit(buf), 0) < 206 (ssize_t)sldns_buffer_limit(buf)) { 207 #ifndef USE_WINSOCK 208 perror("send() data failed"); 209 #else 210 printf("send data: %s\n", 211 wsa_strerror(WSAGetLastError())); 212 #endif 213 exit(1); 214 } 215 } 216 217 /* reset the proxy_buf for next packet */ 218 sldns_buffer_set_limit(proxy_buf, proxy_buf_limit); 219 free(qinfo.qname); 220 } 221 222 /** receive DNS datagram over TCP and print it */ 223 static void 224 recv_one(int fd, int udp, SSL* ssl, sldns_buffer* buf) 225 { 226 size_t i; 227 char* pktstr; 228 uint16_t len; 229 if(!udp) { 230 if(ssl) { 231 int sr = SSL_read(ssl, (void*)&len, (int)sizeof(len)); 232 if(sr == 0) { 233 printf("ssl: stream closed\n"); 234 exit(1); 235 } 236 if(sr < 0) { 237 log_crypto_err("could not SSL_read"); 238 exit(1); 239 } 240 } else { 241 ssize_t r = recv(fd, (void*)&len, sizeof(len), 0); 242 if(r == 0) { 243 printf("recv: stream closed\n"); 244 exit(1); 245 } 246 if(r < (ssize_t)sizeof(len)) { 247 #ifndef USE_WINSOCK 248 perror("read() len failed"); 249 #else 250 printf("read len: %s\n", 251 wsa_strerror(WSAGetLastError())); 252 #endif 253 exit(1); 254 } 255 } 256 len = ntohs(len); 257 sldns_buffer_clear(buf); 258 sldns_buffer_set_limit(buf, len); 259 if(ssl) { 260 int r = SSL_read(ssl, (void*)sldns_buffer_begin(buf), 261 (int)len); 262 if(r <= 0) { 263 log_crypto_err("could not SSL_read"); 264 exit(1); 265 } 266 if(r != (int)len) 267 fatal_exit("ssl_read %d of %d", r, len); 268 } else { 269 if(recv(fd, (void*)sldns_buffer_begin(buf), len, 0) < 270 (ssize_t)len) { 271 #ifndef USE_WINSOCK 272 perror("read() data failed"); 273 #else 274 printf("read data: %s\n", 275 wsa_strerror(WSAGetLastError())); 276 #endif 277 exit(1); 278 } 279 } 280 } else { 281 ssize_t l; 282 sldns_buffer_clear(buf); 283 if((l=recv(fd, (void*)sldns_buffer_begin(buf), 284 sldns_buffer_capacity(buf), 0)) < 0) { 285 #ifndef USE_WINSOCK 286 perror("read() data failed"); 287 #else 288 printf("read data: %s\n", 289 wsa_strerror(WSAGetLastError())); 290 #endif 291 exit(1); 292 } 293 sldns_buffer_set_limit(buf, (size_t)l); 294 len = (size_t)l; 295 } 296 printf("\nnext received packet\n"); 297 printf("data[%d] ", (int)sldns_buffer_limit(buf)); 298 for(i=0; i<sldns_buffer_limit(buf); i++) { 299 const char* hex = "0123456789ABCDEF"; 300 printf("%c%c", hex[(sldns_buffer_read_u8_at(buf, i)&0xf0)>>4], 301 hex[sldns_buffer_read_u8_at(buf, i)&0x0f]); 302 } 303 printf("\n"); 304 305 pktstr = sldns_wire2str_pkt(sldns_buffer_begin(buf), len); 306 printf("%s", pktstr); 307 free(pktstr); 308 } 309 310 /** see if we can receive any results */ 311 static void 312 print_any_answers(int fd, int udp, SSL* ssl, sldns_buffer* buf, 313 int* num_answers, int wait_all) 314 { 315 /* see if the fd can read, if so, print one answer, repeat */ 316 int ret; 317 struct timeval tv, *waittv; 318 fd_set rfd; 319 while(*num_answers > 0) { 320 memset(&rfd, 0, sizeof(rfd)); 321 memset(&tv, 0, sizeof(tv)); 322 FD_ZERO(&rfd); 323 FD_SET(fd, &rfd); 324 if(wait_all) waittv = NULL; 325 else waittv = &tv; 326 ret = select(fd+1, &rfd, NULL, NULL, waittv); 327 if(ret < 0) { 328 if(errno == EINTR || errno == EAGAIN) continue; 329 perror("select() failed"); 330 exit(1); 331 } 332 if(ret == 0) { 333 if(wait_all) continue; 334 return; 335 } 336 (*num_answers) -= 1; 337 recv_one(fd, udp, ssl, buf); 338 } 339 } 340 341 static int get_random(void) 342 { 343 int r; 344 if (RAND_bytes((unsigned char*)&r, (int)sizeof(r)) == 1) { 345 return r; 346 } 347 return (int)arc4random(); 348 } 349 350 /* parse the pp2_client and populate the proxy_buffer 351 * It doesn't populate the destination parts. */ 352 static int parse_pp2_client(const char* pp2_client, int udp, 353 sldns_buffer* proxy_buf) 354 { 355 struct sockaddr_storage pp2_addr; 356 socklen_t pp2_addrlen = 0; 357 memset(&pp2_addr, 0, sizeof(pp2_addr)); 358 if(*pp2_client == 0) return 0; 359 if(!extstrtoaddr(pp2_client, &pp2_addr, &pp2_addrlen, UNBOUND_DNS_PORT)) { 360 printf("fatal: bad proxy client specs '%s'\n", pp2_client); 361 exit(1); 362 } 363 sldns_buffer_clear(proxy_buf); 364 pp2_write_to_buf(proxy_buf, &pp2_addr, !udp); 365 sldns_buffer_flip(proxy_buf); 366 return 1; 367 } 368 369 /** send the TCP queries and print answers */ 370 static void 371 send_em(const char* svr, const char* pp2_client, int udp, int usessl, 372 int noanswer, int onarrival, int delay, int num, char** qs) 373 { 374 sldns_buffer* buf = sldns_buffer_new(65553); 375 sldns_buffer* proxy_buf = sldns_buffer_new(65553); 376 struct sockaddr_storage svr_addr; 377 socklen_t svr_addrlen; 378 int fd = open_svr(svr, udp, &svr_addr, &svr_addrlen); 379 int i, wait_results = 0, pp2_parsed; 380 SSL_CTX* ctx = NULL; 381 SSL* ssl = NULL; 382 if(!buf) fatal_exit("out of memory"); 383 pp2_parsed = parse_pp2_client(pp2_client, udp, proxy_buf); 384 if(usessl) { 385 ctx = connect_sslctx_create(NULL, NULL, NULL, 0); 386 if(!ctx) fatal_exit("cannot create ssl ctx"); 387 ssl = outgoing_ssl_fd(ctx, fd); 388 if(!ssl) fatal_exit("cannot create ssl"); 389 while(1) { 390 int r; 391 ERR_clear_error(); 392 if( (r=SSL_do_handshake(ssl)) == 1) 393 break; 394 r = SSL_get_error(ssl, r); 395 if(r != SSL_ERROR_WANT_READ && 396 r != SSL_ERROR_WANT_WRITE) { 397 log_crypto_err("could not ssl_handshake"); 398 exit(1); 399 } 400 } 401 if(1) { 402 X509* x = SSL_get_peer_certificate(ssl); 403 if(!x) printf("SSL: no peer certificate\n"); 404 else { 405 X509_print_fp(stdout, x); 406 X509_free(x); 407 } 408 } 409 } 410 /* Send the PROXYv2 information once per stream */ 411 if(!udp && pp2_parsed) { 412 if(ssl) { 413 if(SSL_write(ssl, (void*)sldns_buffer_begin(proxy_buf), 414 (int)sldns_buffer_limit(proxy_buf)) <= 0) { 415 log_crypto_err("cannot SSL_write"); 416 exit(1); 417 } 418 } else { 419 if(send(fd, (void*)sldns_buffer_begin(proxy_buf), 420 sldns_buffer_limit(proxy_buf), 0) < 421 (ssize_t)sldns_buffer_limit(proxy_buf)) { 422 #ifndef USE_WINSOCK 423 perror("send() data failed"); 424 #else 425 printf("send data: %s\n", 426 wsa_strerror(WSAGetLastError())); 427 #endif 428 exit(1); 429 } 430 } 431 } 432 for(i=0; i<num; i+=3) { 433 if (delay != 0) { 434 #ifdef HAVE_SLEEP 435 sleep((unsigned)delay); 436 #else 437 Sleep(delay*1000); 438 #endif 439 } 440 printf("\nNext query is %s %s %s\n", qs[i], qs[i+1], qs[i+2]); 441 write_q(fd, udp, ssl, buf, (uint16_t)get_random(), proxy_buf, 442 pp2_parsed, 443 qs[i], qs[i+1], qs[i+2]); 444 /* print at least one result */ 445 if(onarrival) { 446 wait_results += 1; /* one more answer to fetch */ 447 print_any_answers(fd, udp, ssl, buf, &wait_results, 0); 448 } else if(!noanswer) { 449 recv_one(fd, udp, ssl, buf); 450 } 451 } 452 if(onarrival) 453 print_any_answers(fd, udp, ssl, buf, &wait_results, 1); 454 455 if(usessl) { 456 SSL_shutdown(ssl); 457 SSL_free(ssl); 458 SSL_CTX_free(ctx); 459 } 460 sock_close(fd); 461 sldns_buffer_free(buf); 462 sldns_buffer_free(proxy_buf); 463 printf("orderly exit\n"); 464 } 465 466 #ifdef SIGPIPE 467 /** SIGPIPE handler */ 468 static RETSIGTYPE sigh(int sig) 469 { 470 char str[] = "Got unhandled signal \n"; 471 if(sig == SIGPIPE) { 472 char* strpipe = "got SIGPIPE, remote connection gone\n"; 473 /* simple cast to void will not silence Wunused-result */ 474 (void)!write(STDOUT_FILENO, strpipe, strlen(strpipe)); 475 exit(1); 476 } 477 str[21] = '0' + (sig/10)%10; 478 str[22] = '0' + sig%10; 479 /* simple cast to void will not silence Wunused-result */ 480 (void)!write(STDOUT_FILENO, str, strlen(str)); 481 exit(1); 482 } 483 #endif /* SIGPIPE */ 484 485 /** getopt global, in case header files fail to declare it. */ 486 extern int optind; 487 /** getopt global, in case header files fail to declare it. */ 488 extern char* optarg; 489 490 /** main program for streamtcp */ 491 int main(int argc, char** argv) 492 { 493 int c; 494 const char* svr = "127.0.0.1"; 495 const char* pp2_client = ""; 496 int udp = 0; 497 int noanswer = 0; 498 int onarrival = 0; 499 int usessl = 0; 500 int delay = 0; 501 502 #ifdef USE_WINSOCK 503 WSADATA wsa_data; 504 if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) { 505 printf("WSAStartup failed\n"); 506 return 1; 507 } 508 #endif 509 510 /* lock debug start (if any) */ 511 checklock_start(); 512 log_init(0, 0, 0); 513 514 #ifdef SIGPIPE 515 if(signal(SIGPIPE, &sigh) == SIG_ERR) { 516 perror("could not install signal handler"); 517 return 1; 518 } 519 #endif 520 521 /* command line options */ 522 if(argc == 1) { 523 usage(argv); 524 } 525 while( (c=getopt(argc, argv, "af:p:hnsud:")) != -1) { 526 switch(c) { 527 case 'f': 528 svr = optarg; 529 break; 530 case 'p': 531 pp2_client = optarg; 532 break; 533 case 'a': 534 onarrival = 1; 535 break; 536 case 'n': 537 noanswer = 1; 538 break; 539 case 'u': 540 udp = 1; 541 break; 542 case 's': 543 usessl = 1; 544 break; 545 case 'd': 546 if(atoi(optarg)==0 && strcmp(optarg,"0")!=0) { 547 printf("error parsing delay, " 548 "number expected: %s\n", optarg); 549 return 1; 550 } 551 delay = atoi(optarg); 552 break; 553 case 'h': 554 case '?': 555 default: 556 usage(argv); 557 } 558 } 559 argc -= optind; 560 argv += optind; 561 562 if(argc % 3 != 0) { 563 printf("queries must be multiples of name,type,class\n"); 564 return 1; 565 } 566 if(usessl) { 567 #if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL) 568 ERR_load_SSL_strings(); 569 #endif 570 #if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO) 571 # ifndef S_SPLINT_S 572 OpenSSL_add_all_algorithms(); 573 # endif 574 #else 575 OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS 576 | OPENSSL_INIT_ADD_ALL_DIGESTS 577 | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); 578 #endif 579 #if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL) 580 (void)SSL_library_init(); 581 #else 582 (void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); 583 #endif 584 } 585 send_em(svr, pp2_client, udp, usessl, noanswer, onarrival, delay, argc, argv); 586 checklock_stop(); 587 #ifdef USE_WINSOCK 588 WSACleanup(); 589 #endif 590 return 0; 591 } 592