1238104Sdes/* 2238104Sdes * net.c 3238104Sdes * 4238104Sdes * Network implementation 5238104Sdes * All network related functions are grouped here 6238104Sdes * 7238104Sdes * a Net::DNS like library for C 8238104Sdes * 9238104Sdes * (c) NLnet Labs, 2004-2006 10238104Sdes * 11238104Sdes * See the file LICENSE for the license 12238104Sdes */ 13238104Sdes 14238104Sdes#include <ldns/config.h> 15238104Sdes 16238104Sdes#include <ldns/ldns.h> 17238104Sdes 18238104Sdes#ifdef HAVE_NETINET_IN_H 19238104Sdes#include <netinet/in.h> 20238104Sdes#endif 21238104Sdes#ifdef HAVE_SYS_SOCKET_H 22238104Sdes#include <sys/socket.h> 23238104Sdes#endif 24238104Sdes#ifdef HAVE_NETDB_H 25238104Sdes#include <netdb.h> 26238104Sdes#endif 27238104Sdes#ifdef HAVE_ARPA_INET_H 28238104Sdes#include <arpa/inet.h> 29238104Sdes#endif 30238104Sdes#include <sys/time.h> 31238104Sdes#include <errno.h> 32238104Sdes#include <fcntl.h> 33238104Sdes 34238104Sdesldns_status 35238104Sdesldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt) 36238104Sdes{ 37238104Sdes ldns_buffer *qb; 38238104Sdes ldns_status result; 39238104Sdes ldns_rdf *tsig_mac = NULL; 40238104Sdes 41238104Sdes qb = ldns_buffer_new(LDNS_MIN_BUFLEN); 42238104Sdes 43238104Sdes if (query_pkt && ldns_pkt_tsig(query_pkt)) { 44238104Sdes tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3); 45238104Sdes } 46238104Sdes 47238104Sdes if (!query_pkt || 48238104Sdes ldns_pkt2buffer_wire(qb, query_pkt) != LDNS_STATUS_OK) { 49238104Sdes result = LDNS_STATUS_ERR; 50238104Sdes } else { 51238104Sdes result = ldns_send_buffer(result_packet, r, qb, tsig_mac); 52238104Sdes } 53238104Sdes 54238104Sdes ldns_buffer_free(qb); 55238104Sdes 56238104Sdes return result; 57238104Sdes} 58238104Sdes 59269257Sdes/* code from rdata.c */ 60269257Sdesstatic struct sockaddr_storage * 61269257Sdesldns_rdf2native_sockaddr_storage_port( 62269257Sdes const ldns_rdf *rd, uint16_t port, size_t *size) 63269257Sdes{ 64269257Sdes struct sockaddr_storage *data; 65269257Sdes struct sockaddr_in *data_in; 66269257Sdes struct sockaddr_in6 *data_in6; 67269257Sdes 68269257Sdes data = LDNS_MALLOC(struct sockaddr_storage); 69269257Sdes if (!data) { 70269257Sdes return NULL; 71269257Sdes } 72269257Sdes /* zero the structure for portability */ 73269257Sdes memset(data, 0, sizeof(struct sockaddr_storage)); 74269257Sdes 75269257Sdes switch(ldns_rdf_get_type(rd)) { 76269257Sdes case LDNS_RDF_TYPE_A: 77269257Sdes#ifndef S_SPLINT_S 78269257Sdes data->ss_family = AF_INET; 79269257Sdes#endif 80269257Sdes data_in = (struct sockaddr_in*) data; 81269257Sdes data_in->sin_port = (in_port_t)htons(port); 82269257Sdes memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd)); 83269257Sdes *size = sizeof(struct sockaddr_in); 84269257Sdes return data; 85269257Sdes case LDNS_RDF_TYPE_AAAA: 86269257Sdes#ifndef S_SPLINT_S 87269257Sdes data->ss_family = AF_INET6; 88269257Sdes#endif 89269257Sdes data_in6 = (struct sockaddr_in6*) data; 90269257Sdes data_in6->sin6_port = (in_port_t)htons(port); 91269257Sdes memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd)); 92269257Sdes *size = sizeof(struct sockaddr_in6); 93269257Sdes return data; 94269257Sdes default: 95269257Sdes LDNS_FREE(data); 96269257Sdes return NULL; 97269257Sdes } 98269257Sdes} 99269257Sdes 100269257Sdesstruct sockaddr_storage * 101269257Sdesldns_rdf2native_sockaddr_storage( 102269257Sdes const ldns_rdf *rd, uint16_t port, size_t *size) 103269257Sdes{ 104269257Sdes return ldns_rdf2native_sockaddr_storage_port( 105269257Sdes rd, (port == 0 ? (uint16_t)LDNS_PORT : port), size); 106269257Sdes} 107269257Sdes 108269257Sdes/** best effort to set nonblocking */ 109269257Sdesstatic void 110269257Sdesldns_sock_nonblock(int sockfd) 111269257Sdes{ 112269257Sdes#ifdef HAVE_FCNTL 113269257Sdes int flag; 114269257Sdes if((flag = fcntl(sockfd, F_GETFL)) != -1) { 115269257Sdes flag |= O_NONBLOCK; 116269257Sdes if(fcntl(sockfd, F_SETFL, flag) == -1) { 117269257Sdes /* ignore error, continue blockingly */ 118269257Sdes } 119269257Sdes } 120269257Sdes#elif defined(HAVE_IOCTLSOCKET) 121269257Sdes unsigned long on = 1; 122269257Sdes if(ioctlsocket(sockfd, FIONBIO, &on) != 0) { 123269257Sdes /* ignore error, continue blockingly */ 124269257Sdes } 125269257Sdes#endif 126269257Sdes} 127269257Sdes 128269257Sdes/** best effort to set blocking */ 129269257Sdesstatic void 130269257Sdesldns_sock_block(int sockfd) 131269257Sdes{ 132269257Sdes#ifdef HAVE_FCNTL 133269257Sdes int flag; 134269257Sdes if((flag = fcntl(sockfd, F_GETFL)) != -1) { 135269257Sdes flag &= ~O_NONBLOCK; 136269257Sdes if(fcntl(sockfd, F_SETFL, flag) == -1) { 137269257Sdes /* ignore error, continue */ 138269257Sdes } 139269257Sdes } 140269257Sdes#elif defined(HAVE_IOCTLSOCKET) 141269257Sdes unsigned long off = 0; 142269257Sdes if(ioctlsocket(sockfd, FIONBIO, &off) != 0) { 143269257Sdes /* ignore error, continue */ 144269257Sdes } 145269257Sdes#endif 146269257Sdes} 147269257Sdes 148269257Sdes/** wait for a socket to become ready */ 149269257Sdesstatic int 150269257Sdesldns_sock_wait(int sockfd, struct timeval timeout, int write) 151269257Sdes{ 152269257Sdes int ret; 153269257Sdes#ifndef S_SPLINT_S 154269257Sdes fd_set fds; 155269257Sdes FD_ZERO(&fds); 156269257Sdes FD_SET(FD_SET_T sockfd, &fds); 157269257Sdes if(write) 158269257Sdes ret = select(sockfd+1, NULL, &fds, NULL, &timeout); 159269257Sdes else 160269257Sdes ret = select(sockfd+1, &fds, NULL, NULL, &timeout); 161269257Sdes#endif 162269257Sdes if(ret == 0) 163269257Sdes /* timeout expired */ 164269257Sdes return 0; 165269257Sdes else if(ret == -1) 166269257Sdes /* error */ 167269257Sdes return 0; 168269257Sdes return 1; 169269257Sdes} 170269257Sdes 171269257Sdes 172269257Sdesstatic int 173269257Sdesldns_tcp_connect_from(const struct sockaddr_storage *to, socklen_t tolen, 174269257Sdes const struct sockaddr_storage *from, socklen_t fromlen, 175269257Sdes struct timeval timeout) 176269257Sdes{ 177269257Sdes int sockfd; 178269257Sdes 179269257Sdes#ifndef S_SPLINT_S 180269257Sdes if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM, 181269257Sdes IPPROTO_TCP)) == -1) { 182269257Sdes return 0; 183269257Sdes } 184269257Sdes#endif 185269257Sdes if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){ 186269257Sdes return 0; 187269257Sdes } 188269257Sdes 189269257Sdes /* perform nonblocking connect, to be able to wait with select() */ 190269257Sdes ldns_sock_nonblock(sockfd); 191269257Sdes if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) { 192269257Sdes#ifndef USE_WINSOCK 193269257Sdes#ifdef EINPROGRESS 194269257Sdes if(errno != EINPROGRESS) { 195269257Sdes#else 196269257Sdes if(1) { 197269257Sdes#endif 198269257Sdes close(sockfd); 199269257Sdes return 0; 200269257Sdes } 201269257Sdes#else /* USE_WINSOCK */ 202269257Sdes if(WSAGetLastError() != WSAEINPROGRESS && 203269257Sdes WSAGetLastError() != WSAEWOULDBLOCK) { 204269257Sdes closesocket(sockfd); 205269257Sdes return 0; 206269257Sdes } 207269257Sdes#endif 208269257Sdes /* error was only telling us that it would block */ 209269257Sdes } 210269257Sdes 211269257Sdes /* wait(write) until connected or error */ 212269257Sdes while(1) { 213269257Sdes int error = 0; 214269257Sdes socklen_t len = (socklen_t)sizeof(error); 215269257Sdes 216269257Sdes if(!ldns_sock_wait(sockfd, timeout, 1)) { 217269257Sdes#ifndef USE_WINSOCK 218269257Sdes close(sockfd); 219269257Sdes#else 220269257Sdes closesocket(sockfd); 221269257Sdes#endif 222269257Sdes return 0; 223269257Sdes } 224269257Sdes 225269257Sdes /* check if there is a pending error for nonblocking connect */ 226269257Sdes if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error, 227269257Sdes &len) < 0) { 228269257Sdes#ifndef USE_WINSOCK 229269257Sdes error = errno; /* on solaris errno is error */ 230269257Sdes#else 231269257Sdes error = WSAGetLastError(); 232269257Sdes#endif 233269257Sdes } 234269257Sdes#ifndef USE_WINSOCK 235269257Sdes#if defined(EINPROGRESS) && defined(EWOULDBLOCK) 236269257Sdes if(error == EINPROGRESS || error == EWOULDBLOCK) 237269257Sdes continue; /* try again */ 238269257Sdes#endif 239269257Sdes else if(error != 0) { 240269257Sdes close(sockfd); 241269257Sdes /* error in errno for our user */ 242269257Sdes errno = error; 243269257Sdes return 0; 244269257Sdes } 245269257Sdes#else /* USE_WINSOCK */ 246269257Sdes if(error == WSAEINPROGRESS) 247269257Sdes continue; 248269257Sdes else if(error == WSAEWOULDBLOCK) 249269257Sdes continue; 250269257Sdes else if(error != 0) { 251269257Sdes closesocket(sockfd); 252269257Sdes errno = error; 253269257Sdes return 0; 254269257Sdes } 255269257Sdes#endif /* USE_WINSOCK */ 256269257Sdes /* connected */ 257269257Sdes break; 258269257Sdes } 259269257Sdes 260269257Sdes /* set the socket blocking again */ 261269257Sdes ldns_sock_block(sockfd); 262269257Sdes 263269257Sdes return sockfd; 264269257Sdes} 265269257Sdes 266269257Sdesint 267269257Sdesldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, 268269257Sdes struct timeval timeout) 269269257Sdes{ 270269257Sdes return ldns_tcp_connect_from(to, tolen, NULL, 0, timeout); 271269257Sdes} 272269257Sdes 273269257Sdesstatic int 274269257Sdesldns_tcp_bgsend_from(ldns_buffer *qbin, 275269257Sdes const struct sockaddr_storage *to, socklen_t tolen, 276269257Sdes const struct sockaddr_storage *from, socklen_t fromlen, 277269257Sdes struct timeval timeout) 278269257Sdes{ 279269257Sdes int sockfd; 280269257Sdes 281269257Sdes sockfd = ldns_tcp_connect_from(to, tolen, from, fromlen, timeout); 282269257Sdes 283269257Sdes if (sockfd == 0) { 284269257Sdes return 0; 285269257Sdes } 286269257Sdes 287269257Sdes if (ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) { 288269257Sdes#ifndef USE_WINSOCK 289269257Sdes close(sockfd); 290269257Sdes#else 291269257Sdes closesocket(sockfd); 292269257Sdes#endif 293269257Sdes return 0; 294269257Sdes } 295269257Sdes 296269257Sdes return sockfd; 297269257Sdes} 298269257Sdes 299269257Sdesint 300269257Sdesldns_tcp_bgsend(ldns_buffer *qbin, 301269257Sdes const struct sockaddr_storage *to, socklen_t tolen, 302269257Sdes struct timeval timeout) 303269257Sdes{ 304269257Sdes return ldns_tcp_bgsend_from(qbin, to, tolen, NULL, 0, timeout); 305269257Sdes} 306269257Sdes 307269257Sdes 308269257Sdes/* keep in mind that in DNS tcp messages the first 2 bytes signal the 309269257Sdes * amount data to expect 310269257Sdes */ 311269257Sdesstatic ldns_status 312269257Sdesldns_tcp_send_from(uint8_t **result, ldns_buffer *qbin, 313269257Sdes const struct sockaddr_storage *to, socklen_t tolen, 314269257Sdes const struct sockaddr_storage *from, socklen_t fromlen, 315269257Sdes struct timeval timeout, size_t *answer_size) 316269257Sdes{ 317269257Sdes int sockfd; 318269257Sdes uint8_t *answer; 319269257Sdes 320269257Sdes sockfd = ldns_tcp_bgsend_from(qbin, to, tolen, from, fromlen, timeout); 321269257Sdes 322269257Sdes if (sockfd == 0) { 323269257Sdes return LDNS_STATUS_ERR; 324269257Sdes } 325269257Sdes 326269257Sdes answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout); 327269257Sdes#ifndef USE_WINSOCK 328269257Sdes close(sockfd); 329269257Sdes#else 330269257Sdes closesocket(sockfd); 331269257Sdes#endif 332269257Sdes 333269257Sdes if (*answer_size == 0) { 334269257Sdes /* oops */ 335269257Sdes return LDNS_STATUS_NETWORK_ERR; 336269257Sdes } 337269257Sdes 338269257Sdes /* resize accordingly */ 339269257Sdes *result = LDNS_XREALLOC(answer, uint8_t, (size_t)*answer_size); 340269257Sdes if(!*result) { 341269257Sdes LDNS_FREE(answer); 342269257Sdes return LDNS_STATUS_MEM_ERR; 343269257Sdes } 344269257Sdes return LDNS_STATUS_OK; 345269257Sdes} 346269257Sdes 347238104Sdesldns_status 348269257Sdesldns_tcp_send(uint8_t **result, ldns_buffer *qbin, 349269257Sdes const struct sockaddr_storage *to, socklen_t tolen, 350269257Sdes struct timeval timeout, size_t *answer_size) 351269257Sdes{ 352269257Sdes return ldns_tcp_send_from(result, qbin, 353269257Sdes to, tolen, NULL, 0, timeout, answer_size); 354269257Sdes} 355269257Sdes 356269257Sdesint 357269257Sdesldns_udp_connect(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout)) 358269257Sdes{ 359269257Sdes int sockfd; 360269257Sdes 361269257Sdes#ifndef S_SPLINT_S 362269257Sdes if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM, 363269257Sdes IPPROTO_UDP)) 364269257Sdes == -1) { 365269257Sdes return 0; 366269257Sdes } 367269257Sdes#endif 368269257Sdes return sockfd; 369269257Sdes} 370269257Sdes 371269257Sdesstatic int 372269257Sdesldns_udp_bgsend_from(ldns_buffer *qbin, 373269257Sdes const struct sockaddr_storage *to , socklen_t tolen, 374269257Sdes const struct sockaddr_storage *from, socklen_t fromlen, 375269257Sdes struct timeval timeout) 376269257Sdes{ 377269257Sdes int sockfd; 378269257Sdes 379269257Sdes sockfd = ldns_udp_connect(to, timeout); 380269257Sdes 381269257Sdes if (sockfd == 0) { 382269257Sdes return 0; 383269257Sdes } 384269257Sdes 385269257Sdes if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){ 386269257Sdes return 0; 387269257Sdes } 388269257Sdes 389269257Sdes if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) { 390269257Sdes#ifndef USE_WINSOCK 391269257Sdes close(sockfd); 392269257Sdes#else 393269257Sdes closesocket(sockfd); 394269257Sdes#endif 395269257Sdes return 0; 396269257Sdes } 397269257Sdes return sockfd; 398269257Sdes} 399269257Sdes 400269257Sdesint 401269257Sdesldns_udp_bgsend(ldns_buffer *qbin, 402269257Sdes const struct sockaddr_storage *to , socklen_t tolen, 403269257Sdes struct timeval timeout) 404269257Sdes{ 405269257Sdes return ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout); 406269257Sdes} 407269257Sdes 408269257Sdesstatic ldns_status 409269257Sdesldns_udp_send_from(uint8_t **result, ldns_buffer *qbin, 410269257Sdes const struct sockaddr_storage *to , socklen_t tolen, 411269257Sdes const struct sockaddr_storage *from, socklen_t fromlen, 412269257Sdes struct timeval timeout, size_t *answer_size) 413269257Sdes{ 414269257Sdes int sockfd; 415269257Sdes uint8_t *answer; 416269257Sdes 417269257Sdes sockfd = ldns_udp_bgsend_from(qbin, to, tolen, from, fromlen, timeout); 418269257Sdes 419269257Sdes if (sockfd == 0) { 420269257Sdes return LDNS_STATUS_SOCKET_ERROR; 421269257Sdes } 422269257Sdes 423269257Sdes /* wait for an response*/ 424269257Sdes if(!ldns_sock_wait(sockfd, timeout, 0)) { 425269257Sdes#ifndef USE_WINSOCK 426269257Sdes close(sockfd); 427269257Sdes#else 428269257Sdes closesocket(sockfd); 429269257Sdes#endif 430269257Sdes return LDNS_STATUS_NETWORK_ERR; 431269257Sdes } 432269257Sdes 433269257Sdes /* set to nonblocking, so if the checksum is bad, it becomes 434269257Sdes * an EGAIN error and the ldns_udp_send function does not block, 435269257Sdes * but returns a 'NETWORK_ERROR' much like a timeout. */ 436269257Sdes ldns_sock_nonblock(sockfd); 437269257Sdes 438269257Sdes answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL); 439269257Sdes#ifndef USE_WINSOCK 440269257Sdes close(sockfd); 441269257Sdes#else 442269257Sdes closesocket(sockfd); 443269257Sdes#endif 444269257Sdes 445269257Sdes if (*answer_size == 0) { 446269257Sdes /* oops */ 447269257Sdes return LDNS_STATUS_NETWORK_ERR; 448269257Sdes } 449269257Sdes 450269257Sdes *result = answer; 451269257Sdes return LDNS_STATUS_OK; 452269257Sdes} 453269257Sdes 454269257Sdesldns_status 455269257Sdesldns_udp_send(uint8_t **result, ldns_buffer *qbin, 456269257Sdes const struct sockaddr_storage *to , socklen_t tolen, 457269257Sdes struct timeval timeout, size_t *answer_size) 458269257Sdes{ 459269257Sdes return ldns_udp_send_from(result, qbin, to, tolen, NULL, 0, 460269257Sdes timeout, answer_size); 461269257Sdes} 462269257Sdes 463269257Sdesldns_status 464238104Sdesldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac) 465238104Sdes{ 466238104Sdes uint8_t i; 467269257Sdes 468269257Sdes struct sockaddr_storage *src = NULL; 469269257Sdes size_t src_len; 470238104Sdes struct sockaddr_storage *ns; 471238104Sdes size_t ns_len; 472238104Sdes struct timeval tv_s; 473238104Sdes struct timeval tv_e; 474238104Sdes 475238104Sdes ldns_rdf **ns_array; 476238104Sdes size_t *rtt; 477238104Sdes ldns_pkt *reply; 478238104Sdes bool all_servers_rtt_inf; 479238104Sdes uint8_t retries; 480238104Sdes 481238104Sdes uint8_t *reply_bytes = NULL; 482238104Sdes size_t reply_size = 0; 483238104Sdes ldns_status status, send_status; 484238104Sdes 485238104Sdes assert(r != NULL); 486238104Sdes 487238104Sdes status = LDNS_STATUS_OK; 488238104Sdes rtt = ldns_resolver_rtt(r); 489238104Sdes ns_array = ldns_resolver_nameservers(r); 490238104Sdes reply = NULL; 491238104Sdes ns_len = 0; 492238104Sdes 493238104Sdes all_servers_rtt_inf = true; 494238104Sdes 495238104Sdes if (ldns_resolver_random(r)) { 496238104Sdes ldns_resolver_nameservers_randomize(r); 497238104Sdes } 498238104Sdes 499269257Sdes if(ldns_resolver_source(r)) { 500269257Sdes src = ldns_rdf2native_sockaddr_storage_port( 501269257Sdes ldns_resolver_source(r), 0, &src_len); 502269257Sdes } 503269257Sdes 504238104Sdes /* loop through all defined nameservers */ 505238104Sdes for (i = 0; i < ldns_resolver_nameserver_count(r); i++) { 506238104Sdes if (rtt[i] == LDNS_RESOLV_RTT_INF) { 507238104Sdes /* not reachable nameserver! */ 508238104Sdes continue; 509238104Sdes } 510238104Sdes 511238104Sdes /* maybe verbosity setting? 512238104Sdes printf("Sending to "); 513238104Sdes ldns_rdf_print(stdout, ns_array[i]); 514238104Sdes printf("\n"); 515238104Sdes */ 516238104Sdes ns = ldns_rdf2native_sockaddr_storage(ns_array[i], 517238104Sdes ldns_resolver_port(r), &ns_len); 518238104Sdes 519238104Sdes 520238104Sdes#ifndef S_SPLINT_S 521238104Sdes if ((ns->ss_family == AF_INET) && 522238104Sdes (ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) { 523238104Sdes /* not reachable */ 524246854Sdes LDNS_FREE(ns); 525238104Sdes continue; 526238104Sdes } 527238104Sdes 528238104Sdes if ((ns->ss_family == AF_INET6) && 529238104Sdes (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) { 530238104Sdes /* not reachable */ 531246854Sdes LDNS_FREE(ns); 532238104Sdes continue; 533238104Sdes } 534238104Sdes#endif 535238104Sdes 536238104Sdes all_servers_rtt_inf = false; 537238104Sdes 538238104Sdes gettimeofday(&tv_s, NULL); 539238104Sdes 540238104Sdes send_status = LDNS_STATUS_ERR; 541238104Sdes 542238104Sdes /* reply_bytes implicitly handles our error */ 543269257Sdes if (ldns_resolver_usevc(r)) { 544238104Sdes for (retries = ldns_resolver_retry(r); retries > 0; retries--) { 545238104Sdes send_status = 546269257Sdes ldns_tcp_send_from(&reply_bytes, qb, 547269257Sdes ns, (socklen_t)ns_len, 548269257Sdes src, (socklen_t)src_len, 549269257Sdes ldns_resolver_timeout(r), 550269257Sdes &reply_size); 551238104Sdes if (send_status == LDNS_STATUS_OK) { 552238104Sdes break; 553238104Sdes } 554238104Sdes } 555238104Sdes } else { 556238104Sdes for (retries = ldns_resolver_retry(r); retries > 0; retries--) { 557238104Sdes /* ldns_rdf_print(stdout, ns_array[i]); */ 558238104Sdes send_status = 559269257Sdes ldns_udp_send_from(&reply_bytes, qb, 560269257Sdes ns, (socklen_t)ns_len, 561269257Sdes src, (socklen_t)src_len, 562269257Sdes ldns_resolver_timeout(r), 563269257Sdes &reply_size); 564238104Sdes if (send_status == LDNS_STATUS_OK) { 565238104Sdes break; 566238104Sdes } 567238104Sdes } 568238104Sdes } 569238104Sdes 570238104Sdes if (send_status != LDNS_STATUS_OK) { 571238104Sdes ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF); 572238104Sdes status = send_status; 573238104Sdes } 574238104Sdes 575238104Sdes /* obey the fail directive */ 576238104Sdes if (!reply_bytes) { 577238104Sdes /* the current nameserver seems to have a problem, blacklist it */ 578238104Sdes if (ldns_resolver_fail(r)) { 579238104Sdes LDNS_FREE(ns); 580238104Sdes return LDNS_STATUS_ERR; 581238104Sdes } else { 582238104Sdes LDNS_FREE(ns); 583238104Sdes continue; 584238104Sdes } 585238104Sdes } 586238104Sdes 587238104Sdes status = ldns_wire2pkt(&reply, reply_bytes, reply_size); 588238104Sdes if (status != LDNS_STATUS_OK) { 589238104Sdes LDNS_FREE(reply_bytes); 590238104Sdes LDNS_FREE(ns); 591238104Sdes return status; 592238104Sdes } 593238104Sdes 594238104Sdes LDNS_FREE(ns); 595238104Sdes gettimeofday(&tv_e, NULL); 596238104Sdes 597238104Sdes if (reply) { 598238104Sdes ldns_pkt_set_querytime(reply, (uint32_t) 599238104Sdes ((tv_e.tv_sec - tv_s.tv_sec) * 1000) + 600238104Sdes (tv_e.tv_usec - tv_s.tv_usec) / 1000); 601246854Sdes ldns_pkt_set_answerfrom(reply, 602246854Sdes ldns_rdf_clone(ns_array[i])); 603238104Sdes ldns_pkt_set_timestamp(reply, tv_s); 604238104Sdes ldns_pkt_set_size(reply, reply_size); 605238104Sdes break; 606238104Sdes } else { 607238104Sdes if (ldns_resolver_fail(r)) { 608238104Sdes /* if fail is set bail out, after the first 609238104Sdes * one */ 610238104Sdes break; 611238104Sdes } 612238104Sdes } 613238104Sdes 614238104Sdes /* wait retrans seconds... */ 615238104Sdes sleep((unsigned int) ldns_resolver_retrans(r)); 616238104Sdes } 617238104Sdes 618269257Sdes if(src) { 619269257Sdes LDNS_FREE(src); 620269257Sdes } 621238104Sdes if (all_servers_rtt_inf) { 622238104Sdes LDNS_FREE(reply_bytes); 623238104Sdes return LDNS_STATUS_RES_NO_NS; 624238104Sdes } 625238104Sdes#ifdef HAVE_SSL 626246854Sdes if (tsig_mac && reply && reply_bytes) { 627238104Sdes if (!ldns_pkt_tsig_verify(reply, 628238104Sdes reply_bytes, 629238104Sdes reply_size, 630238104Sdes ldns_resolver_tsig_keyname(r), 631238104Sdes ldns_resolver_tsig_keydata(r), tsig_mac)) { 632238104Sdes status = LDNS_STATUS_CRYPTO_TSIG_BOGUS; 633238104Sdes } 634238104Sdes } 635238104Sdes#else 636238104Sdes (void)tsig_mac; 637238104Sdes#endif /* HAVE_SSL */ 638238104Sdes 639238104Sdes LDNS_FREE(reply_bytes); 640238104Sdes if (result) { 641238104Sdes *result = reply; 642238104Sdes } 643238104Sdes 644238104Sdes return status; 645238104Sdes} 646238104Sdes 647238104Sdesssize_t 648238104Sdesldns_tcp_send_query(ldns_buffer *qbin, int sockfd, 649238104Sdes const struct sockaddr_storage *to, socklen_t tolen) 650238104Sdes{ 651238104Sdes uint8_t *sendbuf; 652238104Sdes ssize_t bytes; 653238104Sdes 654238104Sdes /* add length of packet */ 655238104Sdes sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2); 656238104Sdes if(!sendbuf) return 0; 657238104Sdes ldns_write_uint16(sendbuf, ldns_buffer_position(qbin)); 658246854Sdes memcpy(sendbuf + 2, ldns_buffer_begin(qbin), ldns_buffer_position(qbin)); 659238104Sdes 660238104Sdes bytes = sendto(sockfd, (void*)sendbuf, 661238104Sdes ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen); 662238104Sdes 663238104Sdes LDNS_FREE(sendbuf); 664238104Sdes 665238104Sdes if (bytes == -1 || (size_t) bytes != ldns_buffer_position(qbin) + 2 ) { 666238104Sdes return 0; 667238104Sdes } 668238104Sdes return bytes; 669238104Sdes} 670238104Sdes 671238104Sdes/* don't wait for an answer */ 672238104Sdesssize_t 673238104Sdesldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, 674238104Sdes socklen_t tolen) 675238104Sdes{ 676238104Sdes ssize_t bytes; 677238104Sdes 678238104Sdes bytes = sendto(sockfd, (void*)ldns_buffer_begin(qbin), 679238104Sdes ldns_buffer_position(qbin), 0, (struct sockaddr *)to, tolen); 680238104Sdes 681238104Sdes if (bytes == -1 || (size_t)bytes != ldns_buffer_position(qbin)) { 682238104Sdes return 0; 683238104Sdes } 684238104Sdes if ((size_t) bytes != ldns_buffer_position(qbin)) { 685238104Sdes return 0; 686238104Sdes } 687238104Sdes return bytes; 688238104Sdes} 689238104Sdes 690238104Sdesuint8_t * 691238104Sdesldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from, 692238104Sdes socklen_t *fromlen) 693238104Sdes{ 694238104Sdes uint8_t *wire, *wireout; 695238104Sdes ssize_t wire_size; 696238104Sdes 697238104Sdes wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN); 698238104Sdes if (!wire) { 699238104Sdes *size = 0; 700238104Sdes return NULL; 701238104Sdes } 702238104Sdes 703238104Sdes wire_size = recvfrom(sockfd, (void*)wire, LDNS_MAX_PACKETLEN, 0, 704238104Sdes (struct sockaddr *)from, fromlen); 705238104Sdes 706238104Sdes /* recvfrom can also return 0 */ 707238104Sdes if (wire_size == -1 || wire_size == 0) { 708238104Sdes *size = 0; 709238104Sdes LDNS_FREE(wire); 710238104Sdes return NULL; 711238104Sdes } 712238104Sdes 713238104Sdes *size = (size_t)wire_size; 714238104Sdes wireout = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size); 715238104Sdes if(!wireout) LDNS_FREE(wire); 716238104Sdes 717238104Sdes return wireout; 718238104Sdes} 719238104Sdes 720238104Sdesuint8_t * 721238104Sdesldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout) 722238104Sdes{ 723238104Sdes uint8_t *wire; 724238104Sdes uint16_t wire_size; 725238104Sdes ssize_t bytes = 0, rc = 0; 726238104Sdes 727238104Sdes wire = LDNS_XMALLOC(uint8_t, 2); 728238104Sdes if (!wire) { 729238104Sdes *size = 0; 730238104Sdes return NULL; 731238104Sdes } 732238104Sdes 733238104Sdes while (bytes < 2) { 734238104Sdes if(!ldns_sock_wait(sockfd, timeout, 0)) { 735238104Sdes *size = 0; 736238104Sdes LDNS_FREE(wire); 737238104Sdes return NULL; 738238104Sdes } 739238104Sdes rc = recv(sockfd, (void*) (wire + bytes), 740238104Sdes (size_t) (2 - bytes), 0); 741238104Sdes if (rc == -1 || rc == 0) { 742238104Sdes *size = 0; 743238104Sdes LDNS_FREE(wire); 744238104Sdes return NULL; 745238104Sdes } 746238104Sdes bytes += rc; 747238104Sdes } 748238104Sdes 749238104Sdes wire_size = ldns_read_uint16(wire); 750238104Sdes 751238104Sdes LDNS_FREE(wire); 752238104Sdes wire = LDNS_XMALLOC(uint8_t, wire_size); 753238104Sdes if (!wire) { 754238104Sdes *size = 0; 755238104Sdes return NULL; 756238104Sdes } 757238104Sdes bytes = 0; 758238104Sdes 759238104Sdes while (bytes < (ssize_t) wire_size) { 760238104Sdes if(!ldns_sock_wait(sockfd, timeout, 0)) { 761238104Sdes *size = 0; 762238104Sdes LDNS_FREE(wire); 763238104Sdes return NULL; 764238104Sdes } 765238104Sdes rc = recv(sockfd, (void*) (wire + bytes), 766238104Sdes (size_t) (wire_size - bytes), 0); 767238104Sdes if (rc == -1 || rc == 0) { 768238104Sdes LDNS_FREE(wire); 769238104Sdes *size = 0; 770238104Sdes return NULL; 771238104Sdes } 772238104Sdes bytes += rc; 773238104Sdes } 774238104Sdes 775238104Sdes *size = (size_t) bytes; 776238104Sdes return wire; 777238104Sdes} 778238104Sdes 779238104Sdesuint8_t * 780238104Sdesldns_tcp_read_wire(int sockfd, size_t *size) 781238104Sdes{ 782238104Sdes uint8_t *wire; 783238104Sdes uint16_t wire_size; 784238104Sdes ssize_t bytes = 0, rc = 0; 785238104Sdes 786238104Sdes wire = LDNS_XMALLOC(uint8_t, 2); 787238104Sdes if (!wire) { 788238104Sdes *size = 0; 789238104Sdes return NULL; 790238104Sdes } 791238104Sdes 792238104Sdes while (bytes < 2) { 793238104Sdes rc = recv(sockfd, (void*) (wire + bytes), 794238104Sdes (size_t) (2 - bytes), 0); 795238104Sdes if (rc == -1 || rc == 0) { 796238104Sdes *size = 0; 797238104Sdes LDNS_FREE(wire); 798238104Sdes return NULL; 799238104Sdes } 800238104Sdes bytes += rc; 801238104Sdes } 802238104Sdes 803238104Sdes wire_size = ldns_read_uint16(wire); 804238104Sdes 805238104Sdes LDNS_FREE(wire); 806238104Sdes wire = LDNS_XMALLOC(uint8_t, wire_size); 807238104Sdes if (!wire) { 808238104Sdes *size = 0; 809238104Sdes return NULL; 810238104Sdes } 811238104Sdes bytes = 0; 812238104Sdes 813238104Sdes while (bytes < (ssize_t) wire_size) { 814238104Sdes rc = recv(sockfd, (void*) (wire + bytes), 815238104Sdes (size_t) (wire_size - bytes), 0); 816238104Sdes if (rc == -1 || rc == 0) { 817238104Sdes LDNS_FREE(wire); 818238104Sdes *size = 0; 819238104Sdes return NULL; 820238104Sdes } 821238104Sdes bytes += rc; 822238104Sdes } 823238104Sdes 824238104Sdes *size = (size_t) bytes; 825238104Sdes return wire; 826238104Sdes} 827238104Sdes 828238104Sdes#ifndef S_SPLINT_S 829238104Sdesldns_rdf * 830238104Sdesldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port) 831238104Sdes{ 832238104Sdes ldns_rdf *addr; 833238104Sdes struct sockaddr_in *data_in; 834238104Sdes struct sockaddr_in6 *data_in6; 835238104Sdes 836238104Sdes switch(sock->ss_family) { 837238104Sdes case AF_INET: 838238104Sdes data_in = (struct sockaddr_in*)sock; 839238104Sdes if (port) { 840238104Sdes *port = ntohs((uint16_t)data_in->sin_port); 841238104Sdes } 842238104Sdes addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A, 843238104Sdes LDNS_IP4ADDRLEN, &data_in->sin_addr); 844238104Sdes break; 845238104Sdes case AF_INET6: 846238104Sdes data_in6 = (struct sockaddr_in6*)sock; 847238104Sdes if (port) { 848238104Sdes *port = ntohs((uint16_t)data_in6->sin6_port); 849238104Sdes } 850238104Sdes addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA, 851238104Sdes LDNS_IP6ADDRLEN, &data_in6->sin6_addr); 852238104Sdes break; 853238104Sdes default: 854238104Sdes if (port) { 855238104Sdes *port = 0; 856238104Sdes } 857238104Sdes return NULL; 858238104Sdes } 859238104Sdes return addr; 860238104Sdes} 861238104Sdes#endif 862238104Sdes 863238104Sdes/* code from resolver.c */ 864238104Sdesldns_status 865238104Sdesldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) 866238104Sdes{ 867238104Sdes ldns_pkt *query; 868238104Sdes ldns_buffer *query_wire; 869238104Sdes 870269257Sdes struct sockaddr_storage *src = NULL; 871269257Sdes size_t src_len = 0; 872238104Sdes struct sockaddr_storage *ns = NULL; 873238104Sdes size_t ns_len = 0; 874238104Sdes size_t ns_i; 875238104Sdes ldns_status status; 876238104Sdes 877238104Sdes if (!resolver || ldns_resolver_nameserver_count(resolver) < 1) { 878238104Sdes return LDNS_STATUS_ERR; 879238104Sdes } 880238104Sdes 881238104Sdes query = ldns_pkt_query_new(ldns_rdf_clone(domain), LDNS_RR_TYPE_AXFR, class, 0); 882238104Sdes 883238104Sdes if (!query) { 884238104Sdes return LDNS_STATUS_ADDRESS_ERR; 885238104Sdes } 886269257Sdes if(ldns_resolver_source(resolver)) { 887269257Sdes src = ldns_rdf2native_sockaddr_storage_port( 888269257Sdes ldns_resolver_source(resolver), 0, &src_len); 889269257Sdes } 890238104Sdes /* For AXFR, we have to make the connection ourselves */ 891238104Sdes /* try all nameservers (which usually would mean v4 fallback if 892238104Sdes * @hostname is used */ 893238104Sdes for (ns_i = 0; 894238104Sdes ns_i < ldns_resolver_nameserver_count(resolver) && 895238104Sdes resolver->_socket == 0; 896238104Sdes ns_i++) { 897246854Sdes if (ns != NULL) { 898246854Sdes LDNS_FREE(ns); 899246854Sdes } 900238104Sdes ns = ldns_rdf2native_sockaddr_storage( 901238104Sdes resolver->_nameservers[ns_i], 902238104Sdes ldns_resolver_port(resolver), &ns_len); 903238104Sdes 904269257Sdes resolver->_socket = ldns_tcp_connect_from( 905269257Sdes ns, (socklen_t)ns_len, 906269257Sdes src, (socklen_t)src_len, 907238104Sdes ldns_resolver_timeout(resolver)); 908238104Sdes } 909238104Sdes 910238104Sdes if (resolver->_socket == 0) { 911238104Sdes ldns_pkt_free(query); 912238104Sdes LDNS_FREE(ns); 913238104Sdes return LDNS_STATUS_NETWORK_ERR; 914238104Sdes } 915238104Sdes 916238104Sdes#ifdef HAVE_SSL 917238104Sdes if (ldns_resolver_tsig_keyname(resolver) && ldns_resolver_tsig_keydata(resolver)) { 918238104Sdes status = ldns_pkt_tsig_sign(query, 919238104Sdes ldns_resolver_tsig_keyname(resolver), 920238104Sdes ldns_resolver_tsig_keydata(resolver), 921238104Sdes 300, ldns_resolver_tsig_algorithm(resolver), NULL); 922238104Sdes if (status != LDNS_STATUS_OK) { 923269257Sdes /* to prevent problems on subsequent calls to 924269257Sdes * ldns_axfr_start we have to close the socket here! */ 925238104Sdes#ifndef USE_WINSOCK 926238104Sdes close(resolver->_socket); 927238104Sdes#else 928238104Sdes closesocket(resolver->_socket); 929238104Sdes#endif 930238104Sdes resolver->_socket = 0; 931238104Sdes 932246854Sdes ldns_pkt_free(query); 933246854Sdes LDNS_FREE(ns); 934246854Sdes 935238104Sdes return LDNS_STATUS_CRYPTO_TSIG_ERR; 936238104Sdes } 937238104Sdes } 938238104Sdes#endif /* HAVE_SSL */ 939238104Sdes 940238104Sdes /* Convert the query to a buffer 941238104Sdes * Is this necessary? 942238104Sdes */ 943238104Sdes query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN); 944238104Sdes if(!query_wire) { 945238104Sdes ldns_pkt_free(query); 946238104Sdes LDNS_FREE(ns); 947238104Sdes#ifndef USE_WINSOCK 948238104Sdes close(resolver->_socket); 949238104Sdes#else 950238104Sdes closesocket(resolver->_socket); 951238104Sdes#endif 952238104Sdes resolver->_socket = 0; 953238104Sdes 954238104Sdes return LDNS_STATUS_MEM_ERR; 955238104Sdes } 956238104Sdes status = ldns_pkt2buffer_wire(query_wire, query); 957238104Sdes if (status != LDNS_STATUS_OK) { 958238104Sdes ldns_pkt_free(query); 959238104Sdes ldns_buffer_free(query_wire); 960238104Sdes LDNS_FREE(ns); 961238104Sdes 962269257Sdes /* to prevent problems on subsequent calls to ldns_axfr_start 963269257Sdes * we have to close the socket here! */ 964238104Sdes#ifndef USE_WINSOCK 965238104Sdes close(resolver->_socket); 966238104Sdes#else 967238104Sdes closesocket(resolver->_socket); 968238104Sdes#endif 969238104Sdes resolver->_socket = 0; 970238104Sdes 971238104Sdes return status; 972238104Sdes } 973238104Sdes /* Send the query */ 974238104Sdes if (ldns_tcp_send_query(query_wire, resolver->_socket, ns, 975238104Sdes (socklen_t)ns_len) == 0) { 976238104Sdes ldns_pkt_free(query); 977238104Sdes ldns_buffer_free(query_wire); 978238104Sdes LDNS_FREE(ns); 979238104Sdes 980269257Sdes /* to prevent problems on subsequent calls to ldns_axfr_start 981269257Sdes * we have to close the socket here! */ 982238104Sdes 983238104Sdes#ifndef USE_WINSOCK 984238104Sdes close(resolver->_socket); 985238104Sdes#else 986238104Sdes closesocket(resolver->_socket); 987238104Sdes#endif 988238104Sdes resolver->_socket = 0; 989238104Sdes 990238104Sdes return LDNS_STATUS_NETWORK_ERR; 991238104Sdes } 992238104Sdes 993238104Sdes ldns_pkt_free(query); 994238104Sdes ldns_buffer_free(query_wire); 995238104Sdes LDNS_FREE(ns); 996238104Sdes 997238104Sdes /* 998238104Sdes * The AXFR is done once the second SOA record is sent 999238104Sdes */ 1000238104Sdes resolver->_axfr_soa_count = 0; 1001238104Sdes return LDNS_STATUS_OK; 1002238104Sdes} 1003