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