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