17b5038d7SDag-Erling Smørgrav /* 27b5038d7SDag-Erling Smørgrav * net.c 37b5038d7SDag-Erling Smørgrav * 47b5038d7SDag-Erling Smørgrav * Network implementation 57b5038d7SDag-Erling Smørgrav * All network related functions are grouped here 67b5038d7SDag-Erling Smørgrav * 77b5038d7SDag-Erling Smørgrav * a Net::DNS like library for C 87b5038d7SDag-Erling Smørgrav * 97b5038d7SDag-Erling Smørgrav * (c) NLnet Labs, 2004-2006 107b5038d7SDag-Erling Smørgrav * 117b5038d7SDag-Erling Smørgrav * See the file LICENSE for the license 127b5038d7SDag-Erling Smørgrav */ 137b5038d7SDag-Erling Smørgrav 147b5038d7SDag-Erling Smørgrav #include <ldns/config.h> 157b5038d7SDag-Erling Smørgrav 167b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h> 177b5038d7SDag-Erling Smørgrav 187b5038d7SDag-Erling Smørgrav #ifdef HAVE_NETINET_IN_H 197b5038d7SDag-Erling Smørgrav #include <netinet/in.h> 207b5038d7SDag-Erling Smørgrav #endif 217b5038d7SDag-Erling Smørgrav #ifdef HAVE_SYS_SOCKET_H 227b5038d7SDag-Erling Smørgrav #include <sys/socket.h> 237b5038d7SDag-Erling Smørgrav #endif 247b5038d7SDag-Erling Smørgrav #ifdef HAVE_NETDB_H 257b5038d7SDag-Erling Smørgrav #include <netdb.h> 267b5038d7SDag-Erling Smørgrav #endif 277b5038d7SDag-Erling Smørgrav #ifdef HAVE_ARPA_INET_H 287b5038d7SDag-Erling Smørgrav #include <arpa/inet.h> 297b5038d7SDag-Erling Smørgrav #endif 307b5038d7SDag-Erling Smørgrav #include <sys/time.h> 317b5038d7SDag-Erling Smørgrav #include <errno.h> 327b5038d7SDag-Erling Smørgrav #include <fcntl.h> 337b5038d7SDag-Erling Smørgrav 347b5038d7SDag-Erling Smørgrav ldns_status 357b5038d7SDag-Erling Smørgrav ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt) 367b5038d7SDag-Erling Smørgrav { 377b5038d7SDag-Erling Smørgrav ldns_buffer *qb; 387b5038d7SDag-Erling Smørgrav ldns_status result; 397b5038d7SDag-Erling Smørgrav ldns_rdf *tsig_mac = NULL; 407b5038d7SDag-Erling Smørgrav 417b5038d7SDag-Erling Smørgrav qb = ldns_buffer_new(LDNS_MIN_BUFLEN); 427b5038d7SDag-Erling Smørgrav 437b5038d7SDag-Erling Smørgrav if (query_pkt && ldns_pkt_tsig(query_pkt)) { 447b5038d7SDag-Erling Smørgrav tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3); 457b5038d7SDag-Erling Smørgrav } 467b5038d7SDag-Erling Smørgrav 477b5038d7SDag-Erling Smørgrav if (!query_pkt || 487b5038d7SDag-Erling Smørgrav ldns_pkt2buffer_wire(qb, query_pkt) != LDNS_STATUS_OK) { 497b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_ERR; 507b5038d7SDag-Erling Smørgrav } else { 517b5038d7SDag-Erling Smørgrav result = ldns_send_buffer(result_packet, r, qb, tsig_mac); 527b5038d7SDag-Erling Smørgrav } 537b5038d7SDag-Erling Smørgrav 547b5038d7SDag-Erling Smørgrav ldns_buffer_free(qb); 557b5038d7SDag-Erling Smørgrav 567b5038d7SDag-Erling Smørgrav return result; 577b5038d7SDag-Erling Smørgrav } 587b5038d7SDag-Erling Smørgrav 59*17d15b25SDag-Erling Smørgrav /* code from rdata.c */ 60*17d15b25SDag-Erling Smørgrav static struct sockaddr_storage * 61*17d15b25SDag-Erling Smørgrav ldns_rdf2native_sockaddr_storage_port( 62*17d15b25SDag-Erling Smørgrav const ldns_rdf *rd, uint16_t port, size_t *size) 637b5038d7SDag-Erling Smørgrav { 64*17d15b25SDag-Erling Smørgrav struct sockaddr_storage *data; 65*17d15b25SDag-Erling Smørgrav struct sockaddr_in *data_in; 66*17d15b25SDag-Erling Smørgrav struct sockaddr_in6 *data_in6; 677b5038d7SDag-Erling Smørgrav 68*17d15b25SDag-Erling Smørgrav data = LDNS_MALLOC(struct sockaddr_storage); 69*17d15b25SDag-Erling Smørgrav if (!data) { 70*17d15b25SDag-Erling Smørgrav return NULL; 717b5038d7SDag-Erling Smørgrav } 72*17d15b25SDag-Erling Smørgrav /* zero the structure for portability */ 73*17d15b25SDag-Erling Smørgrav memset(data, 0, sizeof(struct sockaddr_storage)); 747b5038d7SDag-Erling Smørgrav 75*17d15b25SDag-Erling Smørgrav switch(ldns_rdf_get_type(rd)) { 76*17d15b25SDag-Erling Smørgrav case LDNS_RDF_TYPE_A: 777b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 78*17d15b25SDag-Erling Smørgrav data->ss_family = AF_INET; 797b5038d7SDag-Erling Smørgrav #endif 80*17d15b25SDag-Erling Smørgrav data_in = (struct sockaddr_in*) data; 81*17d15b25SDag-Erling Smørgrav data_in->sin_port = (in_port_t)htons(port); 82*17d15b25SDag-Erling Smørgrav memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd)); 83*17d15b25SDag-Erling Smørgrav *size = sizeof(struct sockaddr_in); 84*17d15b25SDag-Erling Smørgrav return data; 85*17d15b25SDag-Erling Smørgrav case LDNS_RDF_TYPE_AAAA: 86*17d15b25SDag-Erling Smørgrav #ifndef S_SPLINT_S 87*17d15b25SDag-Erling Smørgrav data->ss_family = AF_INET6; 88*17d15b25SDag-Erling Smørgrav #endif 89*17d15b25SDag-Erling Smørgrav data_in6 = (struct sockaddr_in6*) data; 90*17d15b25SDag-Erling Smørgrav data_in6->sin6_port = (in_port_t)htons(port); 91*17d15b25SDag-Erling Smørgrav memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd)); 92*17d15b25SDag-Erling Smørgrav *size = sizeof(struct sockaddr_in6); 93*17d15b25SDag-Erling Smørgrav return data; 94*17d15b25SDag-Erling Smørgrav default: 95*17d15b25SDag-Erling Smørgrav LDNS_FREE(data); 96*17d15b25SDag-Erling Smørgrav return NULL; 977b5038d7SDag-Erling Smørgrav } 987b5038d7SDag-Erling Smørgrav } 997b5038d7SDag-Erling Smørgrav 100*17d15b25SDag-Erling Smørgrav struct sockaddr_storage * 101*17d15b25SDag-Erling Smørgrav ldns_rdf2native_sockaddr_storage( 102*17d15b25SDag-Erling Smørgrav const ldns_rdf *rd, uint16_t port, size_t *size) 103*17d15b25SDag-Erling Smørgrav { 104*17d15b25SDag-Erling Smørgrav return ldns_rdf2native_sockaddr_storage_port( 105*17d15b25SDag-Erling Smørgrav rd, (port == 0 ? (uint16_t)LDNS_PORT : port), size); 1067b5038d7SDag-Erling Smørgrav } 1077b5038d7SDag-Erling Smørgrav 1087b5038d7SDag-Erling Smørgrav /** best effort to set nonblocking */ 1097b5038d7SDag-Erling Smørgrav static void 1107b5038d7SDag-Erling Smørgrav ldns_sock_nonblock(int sockfd) 1117b5038d7SDag-Erling Smørgrav { 1127b5038d7SDag-Erling Smørgrav #ifdef HAVE_FCNTL 1137b5038d7SDag-Erling Smørgrav int flag; 1147b5038d7SDag-Erling Smørgrav if((flag = fcntl(sockfd, F_GETFL)) != -1) { 1157b5038d7SDag-Erling Smørgrav flag |= O_NONBLOCK; 1167b5038d7SDag-Erling Smørgrav if(fcntl(sockfd, F_SETFL, flag) == -1) { 1177b5038d7SDag-Erling Smørgrav /* ignore error, continue blockingly */ 1187b5038d7SDag-Erling Smørgrav } 1197b5038d7SDag-Erling Smørgrav } 1207b5038d7SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET) 1217b5038d7SDag-Erling Smørgrav unsigned long on = 1; 1227b5038d7SDag-Erling Smørgrav if(ioctlsocket(sockfd, FIONBIO, &on) != 0) { 1237b5038d7SDag-Erling Smørgrav /* ignore error, continue blockingly */ 1247b5038d7SDag-Erling Smørgrav } 1257b5038d7SDag-Erling Smørgrav #endif 1267b5038d7SDag-Erling Smørgrav } 1277b5038d7SDag-Erling Smørgrav 1287b5038d7SDag-Erling Smørgrav /** best effort to set blocking */ 1297b5038d7SDag-Erling Smørgrav static void 1307b5038d7SDag-Erling Smørgrav ldns_sock_block(int sockfd) 1317b5038d7SDag-Erling Smørgrav { 1327b5038d7SDag-Erling Smørgrav #ifdef HAVE_FCNTL 1337b5038d7SDag-Erling Smørgrav int flag; 1347b5038d7SDag-Erling Smørgrav if((flag = fcntl(sockfd, F_GETFL)) != -1) { 1357b5038d7SDag-Erling Smørgrav flag &= ~O_NONBLOCK; 1367b5038d7SDag-Erling Smørgrav if(fcntl(sockfd, F_SETFL, flag) == -1) { 1377b5038d7SDag-Erling Smørgrav /* ignore error, continue */ 1387b5038d7SDag-Erling Smørgrav } 1397b5038d7SDag-Erling Smørgrav } 1407b5038d7SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET) 1417b5038d7SDag-Erling Smørgrav unsigned long off = 0; 1427b5038d7SDag-Erling Smørgrav if(ioctlsocket(sockfd, FIONBIO, &off) != 0) { 1437b5038d7SDag-Erling Smørgrav /* ignore error, continue */ 1447b5038d7SDag-Erling Smørgrav } 1457b5038d7SDag-Erling Smørgrav #endif 1467b5038d7SDag-Erling Smørgrav } 1477b5038d7SDag-Erling Smørgrav 1487b5038d7SDag-Erling Smørgrav /** wait for a socket to become ready */ 1497b5038d7SDag-Erling Smørgrav static int 1507b5038d7SDag-Erling Smørgrav ldns_sock_wait(int sockfd, struct timeval timeout, int write) 1517b5038d7SDag-Erling Smørgrav { 1527b5038d7SDag-Erling Smørgrav int ret; 1537b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 1547b5038d7SDag-Erling Smørgrav fd_set fds; 1557b5038d7SDag-Erling Smørgrav FD_ZERO(&fds); 1567b5038d7SDag-Erling Smørgrav FD_SET(FD_SET_T sockfd, &fds); 1577b5038d7SDag-Erling Smørgrav if(write) 1587b5038d7SDag-Erling Smørgrav ret = select(sockfd+1, NULL, &fds, NULL, &timeout); 1597b5038d7SDag-Erling Smørgrav else 1607b5038d7SDag-Erling Smørgrav ret = select(sockfd+1, &fds, NULL, NULL, &timeout); 1617b5038d7SDag-Erling Smørgrav #endif 1627b5038d7SDag-Erling Smørgrav if(ret == 0) 1637b5038d7SDag-Erling Smørgrav /* timeout expired */ 1647b5038d7SDag-Erling Smørgrav return 0; 1657b5038d7SDag-Erling Smørgrav else if(ret == -1) 1667b5038d7SDag-Erling Smørgrav /* error */ 1677b5038d7SDag-Erling Smørgrav return 0; 1687b5038d7SDag-Erling Smørgrav return 1; 1697b5038d7SDag-Erling Smørgrav } 1707b5038d7SDag-Erling Smørgrav 1717b5038d7SDag-Erling Smørgrav 172*17d15b25SDag-Erling Smørgrav static int 173*17d15b25SDag-Erling Smørgrav ldns_tcp_connect_from(const struct sockaddr_storage *to, socklen_t tolen, 174*17d15b25SDag-Erling Smørgrav const struct sockaddr_storage *from, socklen_t fromlen, 1757b5038d7SDag-Erling Smørgrav struct timeval timeout) 1767b5038d7SDag-Erling Smørgrav { 1777b5038d7SDag-Erling Smørgrav int sockfd; 1787b5038d7SDag-Erling Smørgrav 1797b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 1807b5038d7SDag-Erling Smørgrav if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM, 1817b5038d7SDag-Erling Smørgrav IPPROTO_TCP)) == -1) { 1827b5038d7SDag-Erling Smørgrav return 0; 1837b5038d7SDag-Erling Smørgrav } 1847b5038d7SDag-Erling Smørgrav #endif 185*17d15b25SDag-Erling Smørgrav if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){ 186*17d15b25SDag-Erling Smørgrav return 0; 187*17d15b25SDag-Erling Smørgrav } 1887b5038d7SDag-Erling Smørgrav 1897b5038d7SDag-Erling Smørgrav /* perform nonblocking connect, to be able to wait with select() */ 1907b5038d7SDag-Erling Smørgrav ldns_sock_nonblock(sockfd); 1917b5038d7SDag-Erling Smørgrav if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) { 1927b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK 1937b5038d7SDag-Erling Smørgrav #ifdef EINPROGRESS 1947b5038d7SDag-Erling Smørgrav if(errno != EINPROGRESS) { 1957b5038d7SDag-Erling Smørgrav #else 1967b5038d7SDag-Erling Smørgrav if(1) { 1977b5038d7SDag-Erling Smørgrav #endif 1987b5038d7SDag-Erling Smørgrav close(sockfd); 1997b5038d7SDag-Erling Smørgrav return 0; 2007b5038d7SDag-Erling Smørgrav } 2017b5038d7SDag-Erling Smørgrav #else /* USE_WINSOCK */ 2027b5038d7SDag-Erling Smørgrav if(WSAGetLastError() != WSAEINPROGRESS && 2037b5038d7SDag-Erling Smørgrav WSAGetLastError() != WSAEWOULDBLOCK) { 2047b5038d7SDag-Erling Smørgrav closesocket(sockfd); 2057b5038d7SDag-Erling Smørgrav return 0; 2067b5038d7SDag-Erling Smørgrav } 2077b5038d7SDag-Erling Smørgrav #endif 2087b5038d7SDag-Erling Smørgrav /* error was only telling us that it would block */ 2097b5038d7SDag-Erling Smørgrav } 2107b5038d7SDag-Erling Smørgrav 2117b5038d7SDag-Erling Smørgrav /* wait(write) until connected or error */ 2127b5038d7SDag-Erling Smørgrav while(1) { 2137b5038d7SDag-Erling Smørgrav int error = 0; 2147b5038d7SDag-Erling Smørgrav socklen_t len = (socklen_t)sizeof(error); 2157b5038d7SDag-Erling Smørgrav 2167b5038d7SDag-Erling Smørgrav if(!ldns_sock_wait(sockfd, timeout, 1)) { 2177b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK 2187b5038d7SDag-Erling Smørgrav close(sockfd); 2197b5038d7SDag-Erling Smørgrav #else 2207b5038d7SDag-Erling Smørgrav closesocket(sockfd); 2217b5038d7SDag-Erling Smørgrav #endif 2227b5038d7SDag-Erling Smørgrav return 0; 2237b5038d7SDag-Erling Smørgrav } 2247b5038d7SDag-Erling Smørgrav 2257b5038d7SDag-Erling Smørgrav /* check if there is a pending error for nonblocking connect */ 2267b5038d7SDag-Erling Smørgrav if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error, 2277b5038d7SDag-Erling Smørgrav &len) < 0) { 2287b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK 2297b5038d7SDag-Erling Smørgrav error = errno; /* on solaris errno is error */ 2307b5038d7SDag-Erling Smørgrav #else 2317b5038d7SDag-Erling Smørgrav error = WSAGetLastError(); 2327b5038d7SDag-Erling Smørgrav #endif 2337b5038d7SDag-Erling Smørgrav } 2347b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK 2357b5038d7SDag-Erling Smørgrav #if defined(EINPROGRESS) && defined(EWOULDBLOCK) 2367b5038d7SDag-Erling Smørgrav if(error == EINPROGRESS || error == EWOULDBLOCK) 2377b5038d7SDag-Erling Smørgrav continue; /* try again */ 2387b5038d7SDag-Erling Smørgrav #endif 2397b5038d7SDag-Erling Smørgrav else if(error != 0) { 2407b5038d7SDag-Erling Smørgrav close(sockfd); 2417b5038d7SDag-Erling Smørgrav /* error in errno for our user */ 2427b5038d7SDag-Erling Smørgrav errno = error; 2437b5038d7SDag-Erling Smørgrav return 0; 2447b5038d7SDag-Erling Smørgrav } 2457b5038d7SDag-Erling Smørgrav #else /* USE_WINSOCK */ 2467b5038d7SDag-Erling Smørgrav if(error == WSAEINPROGRESS) 2477b5038d7SDag-Erling Smørgrav continue; 2487b5038d7SDag-Erling Smørgrav else if(error == WSAEWOULDBLOCK) 2497b5038d7SDag-Erling Smørgrav continue; 2507b5038d7SDag-Erling Smørgrav else if(error != 0) { 2517b5038d7SDag-Erling Smørgrav closesocket(sockfd); 2527b5038d7SDag-Erling Smørgrav errno = error; 2537b5038d7SDag-Erling Smørgrav return 0; 2547b5038d7SDag-Erling Smørgrav } 2557b5038d7SDag-Erling Smørgrav #endif /* USE_WINSOCK */ 2567b5038d7SDag-Erling Smørgrav /* connected */ 2577b5038d7SDag-Erling Smørgrav break; 2587b5038d7SDag-Erling Smørgrav } 2597b5038d7SDag-Erling Smørgrav 2607b5038d7SDag-Erling Smørgrav /* set the socket blocking again */ 2617b5038d7SDag-Erling Smørgrav ldns_sock_block(sockfd); 2627b5038d7SDag-Erling Smørgrav 2637b5038d7SDag-Erling Smørgrav return sockfd; 2647b5038d7SDag-Erling Smørgrav } 2657b5038d7SDag-Erling Smørgrav 266*17d15b25SDag-Erling Smørgrav int 267*17d15b25SDag-Erling Smørgrav ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, 268*17d15b25SDag-Erling Smørgrav struct timeval timeout) 269*17d15b25SDag-Erling Smørgrav { 270*17d15b25SDag-Erling Smørgrav return ldns_tcp_connect_from(to, tolen, NULL, 0, timeout); 271*17d15b25SDag-Erling Smørgrav } 272*17d15b25SDag-Erling Smørgrav 273*17d15b25SDag-Erling Smørgrav static int 274*17d15b25SDag-Erling Smørgrav ldns_tcp_bgsend_from(ldns_buffer *qbin, 275*17d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to, socklen_t tolen, 276*17d15b25SDag-Erling Smørgrav const struct sockaddr_storage *from, socklen_t fromlen, 277*17d15b25SDag-Erling Smørgrav struct timeval timeout) 278*17d15b25SDag-Erling Smørgrav { 279*17d15b25SDag-Erling Smørgrav int sockfd; 280*17d15b25SDag-Erling Smørgrav 281*17d15b25SDag-Erling Smørgrav sockfd = ldns_tcp_connect_from(to, tolen, from, fromlen, timeout); 282*17d15b25SDag-Erling Smørgrav 283*17d15b25SDag-Erling Smørgrav if (sockfd == 0) { 284*17d15b25SDag-Erling Smørgrav return 0; 285*17d15b25SDag-Erling Smørgrav } 286*17d15b25SDag-Erling Smørgrav 287*17d15b25SDag-Erling Smørgrav if (ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) { 288*17d15b25SDag-Erling Smørgrav #ifndef USE_WINSOCK 289*17d15b25SDag-Erling Smørgrav close(sockfd); 290*17d15b25SDag-Erling Smørgrav #else 291*17d15b25SDag-Erling Smørgrav closesocket(sockfd); 292*17d15b25SDag-Erling Smørgrav #endif 293*17d15b25SDag-Erling Smørgrav return 0; 294*17d15b25SDag-Erling Smørgrav } 295*17d15b25SDag-Erling Smørgrav 296*17d15b25SDag-Erling Smørgrav return sockfd; 297*17d15b25SDag-Erling Smørgrav } 298*17d15b25SDag-Erling Smørgrav 299*17d15b25SDag-Erling Smørgrav int 300*17d15b25SDag-Erling Smørgrav ldns_tcp_bgsend(ldns_buffer *qbin, 301*17d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to, socklen_t tolen, 302*17d15b25SDag-Erling Smørgrav struct timeval timeout) 303*17d15b25SDag-Erling Smørgrav { 304*17d15b25SDag-Erling Smørgrav return ldns_tcp_bgsend_from(qbin, to, tolen, NULL, 0, timeout); 305*17d15b25SDag-Erling Smørgrav } 306*17d15b25SDag-Erling Smørgrav 307*17d15b25SDag-Erling Smørgrav 308*17d15b25SDag-Erling Smørgrav /* keep in mind that in DNS tcp messages the first 2 bytes signal the 309*17d15b25SDag-Erling Smørgrav * amount data to expect 310*17d15b25SDag-Erling Smørgrav */ 311*17d15b25SDag-Erling Smørgrav static ldns_status 312*17d15b25SDag-Erling Smørgrav ldns_tcp_send_from(uint8_t **result, ldns_buffer *qbin, 313*17d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to, socklen_t tolen, 314*17d15b25SDag-Erling Smørgrav const struct sockaddr_storage *from, socklen_t fromlen, 315*17d15b25SDag-Erling Smørgrav struct timeval timeout, size_t *answer_size) 316*17d15b25SDag-Erling Smørgrav { 317*17d15b25SDag-Erling Smørgrav int sockfd; 318*17d15b25SDag-Erling Smørgrav uint8_t *answer; 319*17d15b25SDag-Erling Smørgrav 320*17d15b25SDag-Erling Smørgrav sockfd = ldns_tcp_bgsend_from(qbin, to, tolen, from, fromlen, timeout); 321*17d15b25SDag-Erling Smørgrav 322*17d15b25SDag-Erling Smørgrav if (sockfd == 0) { 323*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_ERR; 324*17d15b25SDag-Erling Smørgrav } 325*17d15b25SDag-Erling Smørgrav 326*17d15b25SDag-Erling Smørgrav answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout); 327*17d15b25SDag-Erling Smørgrav #ifndef USE_WINSOCK 328*17d15b25SDag-Erling Smørgrav close(sockfd); 329*17d15b25SDag-Erling Smørgrav #else 330*17d15b25SDag-Erling Smørgrav closesocket(sockfd); 331*17d15b25SDag-Erling Smørgrav #endif 332*17d15b25SDag-Erling Smørgrav 333*17d15b25SDag-Erling Smørgrav if (*answer_size == 0) { 334*17d15b25SDag-Erling Smørgrav /* oops */ 335*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_NETWORK_ERR; 336*17d15b25SDag-Erling Smørgrav } 337*17d15b25SDag-Erling Smørgrav 338*17d15b25SDag-Erling Smørgrav /* resize accordingly */ 339*17d15b25SDag-Erling Smørgrav *result = LDNS_XREALLOC(answer, uint8_t, (size_t)*answer_size); 340*17d15b25SDag-Erling Smørgrav if(!*result) { 341*17d15b25SDag-Erling Smørgrav LDNS_FREE(answer); 342*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 343*17d15b25SDag-Erling Smørgrav } 344*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_OK; 345*17d15b25SDag-Erling Smørgrav } 346*17d15b25SDag-Erling Smørgrav 347*17d15b25SDag-Erling Smørgrav ldns_status 348*17d15b25SDag-Erling Smørgrav ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, 349*17d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to, socklen_t tolen, 350*17d15b25SDag-Erling Smørgrav struct timeval timeout, size_t *answer_size) 351*17d15b25SDag-Erling Smørgrav { 352*17d15b25SDag-Erling Smørgrav return ldns_tcp_send_from(result, qbin, 353*17d15b25SDag-Erling Smørgrav to, tolen, NULL, 0, timeout, answer_size); 354*17d15b25SDag-Erling Smørgrav } 355*17d15b25SDag-Erling Smørgrav 356*17d15b25SDag-Erling Smørgrav int 357*17d15b25SDag-Erling Smørgrav ldns_udp_connect(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout)) 358*17d15b25SDag-Erling Smørgrav { 359*17d15b25SDag-Erling Smørgrav int sockfd; 360*17d15b25SDag-Erling Smørgrav 361*17d15b25SDag-Erling Smørgrav #ifndef S_SPLINT_S 362*17d15b25SDag-Erling Smørgrav if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM, 363*17d15b25SDag-Erling Smørgrav IPPROTO_UDP)) 364*17d15b25SDag-Erling Smørgrav == -1) { 365*17d15b25SDag-Erling Smørgrav return 0; 366*17d15b25SDag-Erling Smørgrav } 367*17d15b25SDag-Erling Smørgrav #endif 368*17d15b25SDag-Erling Smørgrav return sockfd; 369*17d15b25SDag-Erling Smørgrav } 370*17d15b25SDag-Erling Smørgrav 371*17d15b25SDag-Erling Smørgrav static int 372*17d15b25SDag-Erling Smørgrav ldns_udp_bgsend_from(ldns_buffer *qbin, 373*17d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to , socklen_t tolen, 374*17d15b25SDag-Erling Smørgrav const struct sockaddr_storage *from, socklen_t fromlen, 375*17d15b25SDag-Erling Smørgrav struct timeval timeout) 376*17d15b25SDag-Erling Smørgrav { 377*17d15b25SDag-Erling Smørgrav int sockfd; 378*17d15b25SDag-Erling Smørgrav 379*17d15b25SDag-Erling Smørgrav sockfd = ldns_udp_connect(to, timeout); 380*17d15b25SDag-Erling Smørgrav 381*17d15b25SDag-Erling Smørgrav if (sockfd == 0) { 382*17d15b25SDag-Erling Smørgrav return 0; 383*17d15b25SDag-Erling Smørgrav } 384*17d15b25SDag-Erling Smørgrav 385*17d15b25SDag-Erling Smørgrav if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){ 386*17d15b25SDag-Erling Smørgrav return 0; 387*17d15b25SDag-Erling Smørgrav } 388*17d15b25SDag-Erling Smørgrav 389*17d15b25SDag-Erling Smørgrav if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) { 390*17d15b25SDag-Erling Smørgrav #ifndef USE_WINSOCK 391*17d15b25SDag-Erling Smørgrav close(sockfd); 392*17d15b25SDag-Erling Smørgrav #else 393*17d15b25SDag-Erling Smørgrav closesocket(sockfd); 394*17d15b25SDag-Erling Smørgrav #endif 395*17d15b25SDag-Erling Smørgrav return 0; 396*17d15b25SDag-Erling Smørgrav } 397*17d15b25SDag-Erling Smørgrav return sockfd; 398*17d15b25SDag-Erling Smørgrav } 399*17d15b25SDag-Erling Smørgrav 400*17d15b25SDag-Erling Smørgrav int 401*17d15b25SDag-Erling Smørgrav ldns_udp_bgsend(ldns_buffer *qbin, 402*17d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to , socklen_t tolen, 403*17d15b25SDag-Erling Smørgrav struct timeval timeout) 404*17d15b25SDag-Erling Smørgrav { 405*17d15b25SDag-Erling Smørgrav return ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout); 406*17d15b25SDag-Erling Smørgrav } 407*17d15b25SDag-Erling Smørgrav 408*17d15b25SDag-Erling Smørgrav static ldns_status 409*17d15b25SDag-Erling Smørgrav ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin, 410*17d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to , socklen_t tolen, 411*17d15b25SDag-Erling Smørgrav const struct sockaddr_storage *from, socklen_t fromlen, 412*17d15b25SDag-Erling Smørgrav struct timeval timeout, size_t *answer_size) 413*17d15b25SDag-Erling Smørgrav { 414*17d15b25SDag-Erling Smørgrav int sockfd; 415*17d15b25SDag-Erling Smørgrav uint8_t *answer; 416*17d15b25SDag-Erling Smørgrav 417*17d15b25SDag-Erling Smørgrav sockfd = ldns_udp_bgsend_from(qbin, to, tolen, from, fromlen, timeout); 418*17d15b25SDag-Erling Smørgrav 419*17d15b25SDag-Erling Smørgrav if (sockfd == 0) { 420*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_SOCKET_ERROR; 421*17d15b25SDag-Erling Smørgrav } 422*17d15b25SDag-Erling Smørgrav 423*17d15b25SDag-Erling Smørgrav /* wait for an response*/ 424*17d15b25SDag-Erling Smørgrav if(!ldns_sock_wait(sockfd, timeout, 0)) { 425*17d15b25SDag-Erling Smørgrav #ifndef USE_WINSOCK 426*17d15b25SDag-Erling Smørgrav close(sockfd); 427*17d15b25SDag-Erling Smørgrav #else 428*17d15b25SDag-Erling Smørgrav closesocket(sockfd); 429*17d15b25SDag-Erling Smørgrav #endif 430*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_NETWORK_ERR; 431*17d15b25SDag-Erling Smørgrav } 432*17d15b25SDag-Erling Smørgrav 433*17d15b25SDag-Erling Smørgrav /* set to nonblocking, so if the checksum is bad, it becomes 434*17d15b25SDag-Erling Smørgrav * an EGAIN error and the ldns_udp_send function does not block, 435*17d15b25SDag-Erling Smørgrav * but returns a 'NETWORK_ERROR' much like a timeout. */ 436*17d15b25SDag-Erling Smørgrav ldns_sock_nonblock(sockfd); 437*17d15b25SDag-Erling Smørgrav 438*17d15b25SDag-Erling Smørgrav answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL); 439*17d15b25SDag-Erling Smørgrav #ifndef USE_WINSOCK 440*17d15b25SDag-Erling Smørgrav close(sockfd); 441*17d15b25SDag-Erling Smørgrav #else 442*17d15b25SDag-Erling Smørgrav closesocket(sockfd); 443*17d15b25SDag-Erling Smørgrav #endif 444*17d15b25SDag-Erling Smørgrav 445*17d15b25SDag-Erling Smørgrav if (*answer_size == 0) { 446*17d15b25SDag-Erling Smørgrav /* oops */ 447*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_NETWORK_ERR; 448*17d15b25SDag-Erling Smørgrav } 449*17d15b25SDag-Erling Smørgrav 450*17d15b25SDag-Erling Smørgrav *result = answer; 451*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_OK; 452*17d15b25SDag-Erling Smørgrav } 453*17d15b25SDag-Erling Smørgrav 454*17d15b25SDag-Erling Smørgrav ldns_status 455*17d15b25SDag-Erling Smørgrav ldns_udp_send(uint8_t **result, ldns_buffer *qbin, 456*17d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to , socklen_t tolen, 457*17d15b25SDag-Erling Smørgrav struct timeval timeout, size_t *answer_size) 458*17d15b25SDag-Erling Smørgrav { 459*17d15b25SDag-Erling Smørgrav return ldns_udp_send_from(result, qbin, to, tolen, NULL, 0, 460*17d15b25SDag-Erling Smørgrav timeout, answer_size); 461*17d15b25SDag-Erling Smørgrav } 462*17d15b25SDag-Erling Smørgrav 463*17d15b25SDag-Erling Smørgrav ldns_status 464*17d15b25SDag-Erling Smørgrav ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac) 465*17d15b25SDag-Erling Smørgrav { 466*17d15b25SDag-Erling Smørgrav uint8_t i; 467*17d15b25SDag-Erling Smørgrav 468*17d15b25SDag-Erling Smørgrav struct sockaddr_storage *src = NULL; 469*17d15b25SDag-Erling Smørgrav size_t src_len; 470*17d15b25SDag-Erling Smørgrav struct sockaddr_storage *ns; 471*17d15b25SDag-Erling Smørgrav size_t ns_len; 472*17d15b25SDag-Erling Smørgrav struct timeval tv_s; 473*17d15b25SDag-Erling Smørgrav struct timeval tv_e; 474*17d15b25SDag-Erling Smørgrav 475*17d15b25SDag-Erling Smørgrav ldns_rdf **ns_array; 476*17d15b25SDag-Erling Smørgrav size_t *rtt; 477*17d15b25SDag-Erling Smørgrav ldns_pkt *reply; 478*17d15b25SDag-Erling Smørgrav bool all_servers_rtt_inf; 479*17d15b25SDag-Erling Smørgrav uint8_t retries; 480*17d15b25SDag-Erling Smørgrav 481*17d15b25SDag-Erling Smørgrav uint8_t *reply_bytes = NULL; 482*17d15b25SDag-Erling Smørgrav size_t reply_size = 0; 483*17d15b25SDag-Erling Smørgrav ldns_status status, send_status; 484*17d15b25SDag-Erling Smørgrav 485*17d15b25SDag-Erling Smørgrav assert(r != NULL); 486*17d15b25SDag-Erling Smørgrav 487*17d15b25SDag-Erling Smørgrav status = LDNS_STATUS_OK; 488*17d15b25SDag-Erling Smørgrav rtt = ldns_resolver_rtt(r); 489*17d15b25SDag-Erling Smørgrav ns_array = ldns_resolver_nameservers(r); 490*17d15b25SDag-Erling Smørgrav reply = NULL; 491*17d15b25SDag-Erling Smørgrav ns_len = 0; 492*17d15b25SDag-Erling Smørgrav 493*17d15b25SDag-Erling Smørgrav all_servers_rtt_inf = true; 494*17d15b25SDag-Erling Smørgrav 495*17d15b25SDag-Erling Smørgrav if (ldns_resolver_random(r)) { 496*17d15b25SDag-Erling Smørgrav ldns_resolver_nameservers_randomize(r); 497*17d15b25SDag-Erling Smørgrav } 498*17d15b25SDag-Erling Smørgrav 499*17d15b25SDag-Erling Smørgrav if(ldns_resolver_source(r)) { 500*17d15b25SDag-Erling Smørgrav src = ldns_rdf2native_sockaddr_storage_port( 501*17d15b25SDag-Erling Smørgrav ldns_resolver_source(r), 0, &src_len); 502*17d15b25SDag-Erling Smørgrav } 503*17d15b25SDag-Erling Smørgrav 504*17d15b25SDag-Erling Smørgrav /* loop through all defined nameservers */ 505*17d15b25SDag-Erling Smørgrav for (i = 0; i < ldns_resolver_nameserver_count(r); i++) { 506*17d15b25SDag-Erling Smørgrav if (rtt[i] == LDNS_RESOLV_RTT_INF) { 507*17d15b25SDag-Erling Smørgrav /* not reachable nameserver! */ 508*17d15b25SDag-Erling Smørgrav continue; 509*17d15b25SDag-Erling Smørgrav } 510*17d15b25SDag-Erling Smørgrav 511*17d15b25SDag-Erling Smørgrav /* maybe verbosity setting? 512*17d15b25SDag-Erling Smørgrav printf("Sending to "); 513*17d15b25SDag-Erling Smørgrav ldns_rdf_print(stdout, ns_array[i]); 514*17d15b25SDag-Erling Smørgrav printf("\n"); 515*17d15b25SDag-Erling Smørgrav */ 516*17d15b25SDag-Erling Smørgrav ns = ldns_rdf2native_sockaddr_storage(ns_array[i], 517*17d15b25SDag-Erling Smørgrav ldns_resolver_port(r), &ns_len); 518*17d15b25SDag-Erling Smørgrav 519*17d15b25SDag-Erling Smørgrav 520*17d15b25SDag-Erling Smørgrav #ifndef S_SPLINT_S 521*17d15b25SDag-Erling Smørgrav if ((ns->ss_family == AF_INET) && 522*17d15b25SDag-Erling Smørgrav (ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) { 523*17d15b25SDag-Erling Smørgrav /* not reachable */ 524*17d15b25SDag-Erling Smørgrav LDNS_FREE(ns); 525*17d15b25SDag-Erling Smørgrav continue; 526*17d15b25SDag-Erling Smørgrav } 527*17d15b25SDag-Erling Smørgrav 528*17d15b25SDag-Erling Smørgrav if ((ns->ss_family == AF_INET6) && 529*17d15b25SDag-Erling Smørgrav (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) { 530*17d15b25SDag-Erling Smørgrav /* not reachable */ 531*17d15b25SDag-Erling Smørgrav LDNS_FREE(ns); 532*17d15b25SDag-Erling Smørgrav continue; 533*17d15b25SDag-Erling Smørgrav } 534*17d15b25SDag-Erling Smørgrav #endif 535*17d15b25SDag-Erling Smørgrav 536*17d15b25SDag-Erling Smørgrav all_servers_rtt_inf = false; 537*17d15b25SDag-Erling Smørgrav 538*17d15b25SDag-Erling Smørgrav gettimeofday(&tv_s, NULL); 539*17d15b25SDag-Erling Smørgrav 540*17d15b25SDag-Erling Smørgrav send_status = LDNS_STATUS_ERR; 541*17d15b25SDag-Erling Smørgrav 542*17d15b25SDag-Erling Smørgrav /* reply_bytes implicitly handles our error */ 543*17d15b25SDag-Erling Smørgrav if (ldns_resolver_usevc(r)) { 544*17d15b25SDag-Erling Smørgrav for (retries = ldns_resolver_retry(r); retries > 0; retries--) { 545*17d15b25SDag-Erling Smørgrav send_status = 546*17d15b25SDag-Erling Smørgrav ldns_tcp_send_from(&reply_bytes, qb, 547*17d15b25SDag-Erling Smørgrav ns, (socklen_t)ns_len, 548*17d15b25SDag-Erling Smørgrav src, (socklen_t)src_len, 549*17d15b25SDag-Erling Smørgrav ldns_resolver_timeout(r), 550*17d15b25SDag-Erling Smørgrav &reply_size); 551*17d15b25SDag-Erling Smørgrav if (send_status == LDNS_STATUS_OK) { 552*17d15b25SDag-Erling Smørgrav break; 553*17d15b25SDag-Erling Smørgrav } 554*17d15b25SDag-Erling Smørgrav } 555*17d15b25SDag-Erling Smørgrav } else { 556*17d15b25SDag-Erling Smørgrav for (retries = ldns_resolver_retry(r); retries > 0; retries--) { 557*17d15b25SDag-Erling Smørgrav /* ldns_rdf_print(stdout, ns_array[i]); */ 558*17d15b25SDag-Erling Smørgrav send_status = 559*17d15b25SDag-Erling Smørgrav ldns_udp_send_from(&reply_bytes, qb, 560*17d15b25SDag-Erling Smørgrav ns, (socklen_t)ns_len, 561*17d15b25SDag-Erling Smørgrav src, (socklen_t)src_len, 562*17d15b25SDag-Erling Smørgrav ldns_resolver_timeout(r), 563*17d15b25SDag-Erling Smørgrav &reply_size); 564*17d15b25SDag-Erling Smørgrav if (send_status == LDNS_STATUS_OK) { 565*17d15b25SDag-Erling Smørgrav break; 566*17d15b25SDag-Erling Smørgrav } 567*17d15b25SDag-Erling Smørgrav } 568*17d15b25SDag-Erling Smørgrav } 569*17d15b25SDag-Erling Smørgrav 570*17d15b25SDag-Erling Smørgrav if (send_status != LDNS_STATUS_OK) { 571*17d15b25SDag-Erling Smørgrav ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF); 572*17d15b25SDag-Erling Smørgrav status = send_status; 573*17d15b25SDag-Erling Smørgrav } 574*17d15b25SDag-Erling Smørgrav 575*17d15b25SDag-Erling Smørgrav /* obey the fail directive */ 576*17d15b25SDag-Erling Smørgrav if (!reply_bytes) { 577*17d15b25SDag-Erling Smørgrav /* the current nameserver seems to have a problem, blacklist it */ 578*17d15b25SDag-Erling Smørgrav if (ldns_resolver_fail(r)) { 579*17d15b25SDag-Erling Smørgrav LDNS_FREE(ns); 580*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_ERR; 581*17d15b25SDag-Erling Smørgrav } else { 582*17d15b25SDag-Erling Smørgrav LDNS_FREE(ns); 583*17d15b25SDag-Erling Smørgrav continue; 584*17d15b25SDag-Erling Smørgrav } 585*17d15b25SDag-Erling Smørgrav } 586*17d15b25SDag-Erling Smørgrav 587*17d15b25SDag-Erling Smørgrav status = ldns_wire2pkt(&reply, reply_bytes, reply_size); 588*17d15b25SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) { 589*17d15b25SDag-Erling Smørgrav LDNS_FREE(reply_bytes); 590*17d15b25SDag-Erling Smørgrav LDNS_FREE(ns); 591*17d15b25SDag-Erling Smørgrav return status; 592*17d15b25SDag-Erling Smørgrav } 593*17d15b25SDag-Erling Smørgrav 594*17d15b25SDag-Erling Smørgrav LDNS_FREE(ns); 595*17d15b25SDag-Erling Smørgrav gettimeofday(&tv_e, NULL); 596*17d15b25SDag-Erling Smørgrav 597*17d15b25SDag-Erling Smørgrav if (reply) { 598*17d15b25SDag-Erling Smørgrav ldns_pkt_set_querytime(reply, (uint32_t) 599*17d15b25SDag-Erling Smørgrav ((tv_e.tv_sec - tv_s.tv_sec) * 1000) + 600*17d15b25SDag-Erling Smørgrav (tv_e.tv_usec - tv_s.tv_usec) / 1000); 601*17d15b25SDag-Erling Smørgrav ldns_pkt_set_answerfrom(reply, 602*17d15b25SDag-Erling Smørgrav ldns_rdf_clone(ns_array[i])); 603*17d15b25SDag-Erling Smørgrav ldns_pkt_set_timestamp(reply, tv_s); 604*17d15b25SDag-Erling Smørgrav ldns_pkt_set_size(reply, reply_size); 605*17d15b25SDag-Erling Smørgrav break; 606*17d15b25SDag-Erling Smørgrav } else { 607*17d15b25SDag-Erling Smørgrav if (ldns_resolver_fail(r)) { 608*17d15b25SDag-Erling Smørgrav /* if fail is set bail out, after the first 609*17d15b25SDag-Erling Smørgrav * one */ 610*17d15b25SDag-Erling Smørgrav break; 611*17d15b25SDag-Erling Smørgrav } 612*17d15b25SDag-Erling Smørgrav } 613*17d15b25SDag-Erling Smørgrav 614*17d15b25SDag-Erling Smørgrav /* wait retrans seconds... */ 615*17d15b25SDag-Erling Smørgrav sleep((unsigned int) ldns_resolver_retrans(r)); 616*17d15b25SDag-Erling Smørgrav } 617*17d15b25SDag-Erling Smørgrav 618*17d15b25SDag-Erling Smørgrav if(src) { 619*17d15b25SDag-Erling Smørgrav LDNS_FREE(src); 620*17d15b25SDag-Erling Smørgrav } 621*17d15b25SDag-Erling Smørgrav if (all_servers_rtt_inf) { 622*17d15b25SDag-Erling Smørgrav LDNS_FREE(reply_bytes); 623*17d15b25SDag-Erling Smørgrav return LDNS_STATUS_RES_NO_NS; 624*17d15b25SDag-Erling Smørgrav } 625*17d15b25SDag-Erling Smørgrav #ifdef HAVE_SSL 626*17d15b25SDag-Erling Smørgrav if (tsig_mac && reply && reply_bytes) { 627*17d15b25SDag-Erling Smørgrav if (!ldns_pkt_tsig_verify(reply, 628*17d15b25SDag-Erling Smørgrav reply_bytes, 629*17d15b25SDag-Erling Smørgrav reply_size, 630*17d15b25SDag-Erling Smørgrav ldns_resolver_tsig_keyname(r), 631*17d15b25SDag-Erling Smørgrav ldns_resolver_tsig_keydata(r), tsig_mac)) { 632*17d15b25SDag-Erling Smørgrav status = LDNS_STATUS_CRYPTO_TSIG_BOGUS; 633*17d15b25SDag-Erling Smørgrav } 634*17d15b25SDag-Erling Smørgrav } 635*17d15b25SDag-Erling Smørgrav #else 636*17d15b25SDag-Erling Smørgrav (void)tsig_mac; 637*17d15b25SDag-Erling Smørgrav #endif /* HAVE_SSL */ 638*17d15b25SDag-Erling Smørgrav 639*17d15b25SDag-Erling Smørgrav LDNS_FREE(reply_bytes); 640*17d15b25SDag-Erling Smørgrav if (result) { 641*17d15b25SDag-Erling Smørgrav *result = reply; 642*17d15b25SDag-Erling Smørgrav } 643*17d15b25SDag-Erling Smørgrav 644*17d15b25SDag-Erling Smørgrav return status; 645*17d15b25SDag-Erling Smørgrav } 646*17d15b25SDag-Erling Smørgrav 6477b5038d7SDag-Erling Smørgrav ssize_t 6487b5038d7SDag-Erling Smørgrav ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, 6497b5038d7SDag-Erling Smørgrav const struct sockaddr_storage *to, socklen_t tolen) 6507b5038d7SDag-Erling Smørgrav { 6517b5038d7SDag-Erling Smørgrav uint8_t *sendbuf; 6527b5038d7SDag-Erling Smørgrav ssize_t bytes; 6537b5038d7SDag-Erling Smørgrav 6547b5038d7SDag-Erling Smørgrav /* add length of packet */ 6557b5038d7SDag-Erling Smørgrav sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2); 6567b5038d7SDag-Erling Smørgrav if(!sendbuf) return 0; 6577b5038d7SDag-Erling Smørgrav ldns_write_uint16(sendbuf, ldns_buffer_position(qbin)); 6582787e39aSDag-Erling Smørgrav memcpy(sendbuf + 2, ldns_buffer_begin(qbin), ldns_buffer_position(qbin)); 6597b5038d7SDag-Erling Smørgrav 6607b5038d7SDag-Erling Smørgrav bytes = sendto(sockfd, (void*)sendbuf, 6617b5038d7SDag-Erling Smørgrav ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen); 6627b5038d7SDag-Erling Smørgrav 6637b5038d7SDag-Erling Smørgrav LDNS_FREE(sendbuf); 6647b5038d7SDag-Erling Smørgrav 6657b5038d7SDag-Erling Smørgrav if (bytes == -1 || (size_t) bytes != ldns_buffer_position(qbin) + 2 ) { 6667b5038d7SDag-Erling Smørgrav return 0; 6677b5038d7SDag-Erling Smørgrav } 6687b5038d7SDag-Erling Smørgrav return bytes; 6697b5038d7SDag-Erling Smørgrav } 6707b5038d7SDag-Erling Smørgrav 6717b5038d7SDag-Erling Smørgrav /* don't wait for an answer */ 6727b5038d7SDag-Erling Smørgrav ssize_t 6737b5038d7SDag-Erling Smørgrav ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, 6747b5038d7SDag-Erling Smørgrav socklen_t tolen) 6757b5038d7SDag-Erling Smørgrav { 6767b5038d7SDag-Erling Smørgrav ssize_t bytes; 6777b5038d7SDag-Erling Smørgrav 6787b5038d7SDag-Erling Smørgrav bytes = sendto(sockfd, (void*)ldns_buffer_begin(qbin), 6797b5038d7SDag-Erling Smørgrav ldns_buffer_position(qbin), 0, (struct sockaddr *)to, tolen); 6807b5038d7SDag-Erling Smørgrav 6817b5038d7SDag-Erling Smørgrav if (bytes == -1 || (size_t)bytes != ldns_buffer_position(qbin)) { 6827b5038d7SDag-Erling Smørgrav return 0; 6837b5038d7SDag-Erling Smørgrav } 6847b5038d7SDag-Erling Smørgrav if ((size_t) bytes != ldns_buffer_position(qbin)) { 6857b5038d7SDag-Erling Smørgrav return 0; 6867b5038d7SDag-Erling Smørgrav } 6877b5038d7SDag-Erling Smørgrav return bytes; 6887b5038d7SDag-Erling Smørgrav } 6897b5038d7SDag-Erling Smørgrav 6907b5038d7SDag-Erling Smørgrav uint8_t * 6917b5038d7SDag-Erling Smørgrav ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from, 6927b5038d7SDag-Erling Smørgrav socklen_t *fromlen) 6937b5038d7SDag-Erling Smørgrav { 6947b5038d7SDag-Erling Smørgrav uint8_t *wire, *wireout; 6957b5038d7SDag-Erling Smørgrav ssize_t wire_size; 6967b5038d7SDag-Erling Smørgrav 6977b5038d7SDag-Erling Smørgrav wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN); 6987b5038d7SDag-Erling Smørgrav if (!wire) { 6997b5038d7SDag-Erling Smørgrav *size = 0; 7007b5038d7SDag-Erling Smørgrav return NULL; 7017b5038d7SDag-Erling Smørgrav } 7027b5038d7SDag-Erling Smørgrav 7037b5038d7SDag-Erling Smørgrav wire_size = recvfrom(sockfd, (void*)wire, LDNS_MAX_PACKETLEN, 0, 7047b5038d7SDag-Erling Smørgrav (struct sockaddr *)from, fromlen); 7057b5038d7SDag-Erling Smørgrav 7067b5038d7SDag-Erling Smørgrav /* recvfrom can also return 0 */ 7077b5038d7SDag-Erling Smørgrav if (wire_size == -1 || wire_size == 0) { 7087b5038d7SDag-Erling Smørgrav *size = 0; 7097b5038d7SDag-Erling Smørgrav LDNS_FREE(wire); 7107b5038d7SDag-Erling Smørgrav return NULL; 7117b5038d7SDag-Erling Smørgrav } 7127b5038d7SDag-Erling Smørgrav 7137b5038d7SDag-Erling Smørgrav *size = (size_t)wire_size; 7147b5038d7SDag-Erling Smørgrav wireout = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size); 7157b5038d7SDag-Erling Smørgrav if(!wireout) LDNS_FREE(wire); 7167b5038d7SDag-Erling Smørgrav 7177b5038d7SDag-Erling Smørgrav return wireout; 7187b5038d7SDag-Erling Smørgrav } 7197b5038d7SDag-Erling Smørgrav 7207b5038d7SDag-Erling Smørgrav uint8_t * 7217b5038d7SDag-Erling Smørgrav ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout) 7227b5038d7SDag-Erling Smørgrav { 7237b5038d7SDag-Erling Smørgrav uint8_t *wire; 7247b5038d7SDag-Erling Smørgrav uint16_t wire_size; 7257b5038d7SDag-Erling Smørgrav ssize_t bytes = 0, rc = 0; 7267b5038d7SDag-Erling Smørgrav 7277b5038d7SDag-Erling Smørgrav wire = LDNS_XMALLOC(uint8_t, 2); 7287b5038d7SDag-Erling Smørgrav if (!wire) { 7297b5038d7SDag-Erling Smørgrav *size = 0; 7307b5038d7SDag-Erling Smørgrav return NULL; 7317b5038d7SDag-Erling Smørgrav } 7327b5038d7SDag-Erling Smørgrav 7337b5038d7SDag-Erling Smørgrav while (bytes < 2) { 7347b5038d7SDag-Erling Smørgrav if(!ldns_sock_wait(sockfd, timeout, 0)) { 7357b5038d7SDag-Erling Smørgrav *size = 0; 7367b5038d7SDag-Erling Smørgrav LDNS_FREE(wire); 7377b5038d7SDag-Erling Smørgrav return NULL; 7387b5038d7SDag-Erling Smørgrav } 7397b5038d7SDag-Erling Smørgrav rc = recv(sockfd, (void*) (wire + bytes), 7407b5038d7SDag-Erling Smørgrav (size_t) (2 - bytes), 0); 7417b5038d7SDag-Erling Smørgrav if (rc == -1 || rc == 0) { 7427b5038d7SDag-Erling Smørgrav *size = 0; 7437b5038d7SDag-Erling Smørgrav LDNS_FREE(wire); 7447b5038d7SDag-Erling Smørgrav return NULL; 7457b5038d7SDag-Erling Smørgrav } 7467b5038d7SDag-Erling Smørgrav bytes += rc; 7477b5038d7SDag-Erling Smørgrav } 7487b5038d7SDag-Erling Smørgrav 7497b5038d7SDag-Erling Smørgrav wire_size = ldns_read_uint16(wire); 7507b5038d7SDag-Erling Smørgrav 7517b5038d7SDag-Erling Smørgrav LDNS_FREE(wire); 7527b5038d7SDag-Erling Smørgrav wire = LDNS_XMALLOC(uint8_t, wire_size); 7537b5038d7SDag-Erling Smørgrav if (!wire) { 7547b5038d7SDag-Erling Smørgrav *size = 0; 7557b5038d7SDag-Erling Smørgrav return NULL; 7567b5038d7SDag-Erling Smørgrav } 7577b5038d7SDag-Erling Smørgrav bytes = 0; 7587b5038d7SDag-Erling Smørgrav 7597b5038d7SDag-Erling Smørgrav while (bytes < (ssize_t) wire_size) { 7607b5038d7SDag-Erling Smørgrav if(!ldns_sock_wait(sockfd, timeout, 0)) { 7617b5038d7SDag-Erling Smørgrav *size = 0; 7627b5038d7SDag-Erling Smørgrav LDNS_FREE(wire); 7637b5038d7SDag-Erling Smørgrav return NULL; 7647b5038d7SDag-Erling Smørgrav } 7657b5038d7SDag-Erling Smørgrav rc = recv(sockfd, (void*) (wire + bytes), 7667b5038d7SDag-Erling Smørgrav (size_t) (wire_size - bytes), 0); 7677b5038d7SDag-Erling Smørgrav if (rc == -1 || rc == 0) { 7687b5038d7SDag-Erling Smørgrav LDNS_FREE(wire); 7697b5038d7SDag-Erling Smørgrav *size = 0; 7707b5038d7SDag-Erling Smørgrav return NULL; 7717b5038d7SDag-Erling Smørgrav } 7727b5038d7SDag-Erling Smørgrav bytes += rc; 7737b5038d7SDag-Erling Smørgrav } 7747b5038d7SDag-Erling Smørgrav 7757b5038d7SDag-Erling Smørgrav *size = (size_t) bytes; 7767b5038d7SDag-Erling Smørgrav return wire; 7777b5038d7SDag-Erling Smørgrav } 7787b5038d7SDag-Erling Smørgrav 7797b5038d7SDag-Erling Smørgrav uint8_t * 7807b5038d7SDag-Erling Smørgrav ldns_tcp_read_wire(int sockfd, size_t *size) 7817b5038d7SDag-Erling Smørgrav { 7827b5038d7SDag-Erling Smørgrav uint8_t *wire; 7837b5038d7SDag-Erling Smørgrav uint16_t wire_size; 7847b5038d7SDag-Erling Smørgrav ssize_t bytes = 0, rc = 0; 7857b5038d7SDag-Erling Smørgrav 7867b5038d7SDag-Erling Smørgrav wire = LDNS_XMALLOC(uint8_t, 2); 7877b5038d7SDag-Erling Smørgrav if (!wire) { 7887b5038d7SDag-Erling Smørgrav *size = 0; 7897b5038d7SDag-Erling Smørgrav return NULL; 7907b5038d7SDag-Erling Smørgrav } 7917b5038d7SDag-Erling Smørgrav 7927b5038d7SDag-Erling Smørgrav while (bytes < 2) { 7937b5038d7SDag-Erling Smørgrav rc = recv(sockfd, (void*) (wire + bytes), 7947b5038d7SDag-Erling Smørgrav (size_t) (2 - bytes), 0); 7957b5038d7SDag-Erling Smørgrav if (rc == -1 || rc == 0) { 7967b5038d7SDag-Erling Smørgrav *size = 0; 7977b5038d7SDag-Erling Smørgrav LDNS_FREE(wire); 7987b5038d7SDag-Erling Smørgrav return NULL; 7997b5038d7SDag-Erling Smørgrav } 8007b5038d7SDag-Erling Smørgrav bytes += rc; 8017b5038d7SDag-Erling Smørgrav } 8027b5038d7SDag-Erling Smørgrav 8037b5038d7SDag-Erling Smørgrav wire_size = ldns_read_uint16(wire); 8047b5038d7SDag-Erling Smørgrav 8057b5038d7SDag-Erling Smørgrav LDNS_FREE(wire); 8067b5038d7SDag-Erling Smørgrav wire = LDNS_XMALLOC(uint8_t, wire_size); 8077b5038d7SDag-Erling Smørgrav if (!wire) { 8087b5038d7SDag-Erling Smørgrav *size = 0; 8097b5038d7SDag-Erling Smørgrav return NULL; 8107b5038d7SDag-Erling Smørgrav } 8117b5038d7SDag-Erling Smørgrav bytes = 0; 8127b5038d7SDag-Erling Smørgrav 8137b5038d7SDag-Erling Smørgrav while (bytes < (ssize_t) wire_size) { 8147b5038d7SDag-Erling Smørgrav rc = recv(sockfd, (void*) (wire + bytes), 8157b5038d7SDag-Erling Smørgrav (size_t) (wire_size - bytes), 0); 8167b5038d7SDag-Erling Smørgrav if (rc == -1 || rc == 0) { 8177b5038d7SDag-Erling Smørgrav LDNS_FREE(wire); 8187b5038d7SDag-Erling Smørgrav *size = 0; 8197b5038d7SDag-Erling Smørgrav return NULL; 8207b5038d7SDag-Erling Smørgrav } 8217b5038d7SDag-Erling Smørgrav bytes += rc; 8227b5038d7SDag-Erling Smørgrav } 8237b5038d7SDag-Erling Smørgrav 8247b5038d7SDag-Erling Smørgrav *size = (size_t) bytes; 8257b5038d7SDag-Erling Smørgrav return wire; 8267b5038d7SDag-Erling Smørgrav } 8277b5038d7SDag-Erling Smørgrav 8287b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 8297b5038d7SDag-Erling Smørgrav ldns_rdf * 8307b5038d7SDag-Erling Smørgrav ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port) 8317b5038d7SDag-Erling Smørgrav { 8327b5038d7SDag-Erling Smørgrav ldns_rdf *addr; 8337b5038d7SDag-Erling Smørgrav struct sockaddr_in *data_in; 8347b5038d7SDag-Erling Smørgrav struct sockaddr_in6 *data_in6; 8357b5038d7SDag-Erling Smørgrav 8367b5038d7SDag-Erling Smørgrav switch(sock->ss_family) { 8377b5038d7SDag-Erling Smørgrav case AF_INET: 8387b5038d7SDag-Erling Smørgrav data_in = (struct sockaddr_in*)sock; 8397b5038d7SDag-Erling Smørgrav if (port) { 8407b5038d7SDag-Erling Smørgrav *port = ntohs((uint16_t)data_in->sin_port); 8417b5038d7SDag-Erling Smørgrav } 8427b5038d7SDag-Erling Smørgrav addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A, 8437b5038d7SDag-Erling Smørgrav LDNS_IP4ADDRLEN, &data_in->sin_addr); 8447b5038d7SDag-Erling Smørgrav break; 8457b5038d7SDag-Erling Smørgrav case AF_INET6: 8467b5038d7SDag-Erling Smørgrav data_in6 = (struct sockaddr_in6*)sock; 8477b5038d7SDag-Erling Smørgrav if (port) { 8487b5038d7SDag-Erling Smørgrav *port = ntohs((uint16_t)data_in6->sin6_port); 8497b5038d7SDag-Erling Smørgrav } 8507b5038d7SDag-Erling Smørgrav addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA, 8517b5038d7SDag-Erling Smørgrav LDNS_IP6ADDRLEN, &data_in6->sin6_addr); 8527b5038d7SDag-Erling Smørgrav break; 8537b5038d7SDag-Erling Smørgrav default: 8547b5038d7SDag-Erling Smørgrav if (port) { 8557b5038d7SDag-Erling Smørgrav *port = 0; 8567b5038d7SDag-Erling Smørgrav } 8577b5038d7SDag-Erling Smørgrav return NULL; 8587b5038d7SDag-Erling Smørgrav } 8597b5038d7SDag-Erling Smørgrav return addr; 8607b5038d7SDag-Erling Smørgrav } 8617b5038d7SDag-Erling Smørgrav #endif 8627b5038d7SDag-Erling Smørgrav 8637b5038d7SDag-Erling Smørgrav /* code from resolver.c */ 8647b5038d7SDag-Erling Smørgrav ldns_status 8657b5038d7SDag-Erling Smørgrav ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) 8667b5038d7SDag-Erling Smørgrav { 8677b5038d7SDag-Erling Smørgrav ldns_pkt *query; 8687b5038d7SDag-Erling Smørgrav ldns_buffer *query_wire; 8697b5038d7SDag-Erling Smørgrav 870*17d15b25SDag-Erling Smørgrav struct sockaddr_storage *src = NULL; 871*17d15b25SDag-Erling Smørgrav size_t src_len = 0; 8727b5038d7SDag-Erling Smørgrav struct sockaddr_storage *ns = NULL; 8737b5038d7SDag-Erling Smørgrav size_t ns_len = 0; 8747b5038d7SDag-Erling Smørgrav size_t ns_i; 8757b5038d7SDag-Erling Smørgrav ldns_status status; 8767b5038d7SDag-Erling Smørgrav 8777b5038d7SDag-Erling Smørgrav if (!resolver || ldns_resolver_nameserver_count(resolver) < 1) { 8787b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR; 8797b5038d7SDag-Erling Smørgrav } 8807b5038d7SDag-Erling Smørgrav 8817b5038d7SDag-Erling Smørgrav query = ldns_pkt_query_new(ldns_rdf_clone(domain), LDNS_RR_TYPE_AXFR, class, 0); 8827b5038d7SDag-Erling Smørgrav 8837b5038d7SDag-Erling Smørgrav if (!query) { 8847b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ADDRESS_ERR; 8857b5038d7SDag-Erling Smørgrav } 886*17d15b25SDag-Erling Smørgrav if(ldns_resolver_source(resolver)) { 887*17d15b25SDag-Erling Smørgrav src = ldns_rdf2native_sockaddr_storage_port( 888*17d15b25SDag-Erling Smørgrav ldns_resolver_source(resolver), 0, &src_len); 889*17d15b25SDag-Erling Smørgrav } 8907b5038d7SDag-Erling Smørgrav /* For AXFR, we have to make the connection ourselves */ 8917b5038d7SDag-Erling Smørgrav /* try all nameservers (which usually would mean v4 fallback if 8927b5038d7SDag-Erling Smørgrav * @hostname is used */ 8937b5038d7SDag-Erling Smørgrav for (ns_i = 0; 8947b5038d7SDag-Erling Smørgrav ns_i < ldns_resolver_nameserver_count(resolver) && 8957b5038d7SDag-Erling Smørgrav resolver->_socket == 0; 8967b5038d7SDag-Erling Smørgrav ns_i++) { 8972787e39aSDag-Erling Smørgrav if (ns != NULL) { 8982787e39aSDag-Erling Smørgrav LDNS_FREE(ns); 8992787e39aSDag-Erling Smørgrav } 9007b5038d7SDag-Erling Smørgrav ns = ldns_rdf2native_sockaddr_storage( 9017b5038d7SDag-Erling Smørgrav resolver->_nameservers[ns_i], 9027b5038d7SDag-Erling Smørgrav ldns_resolver_port(resolver), &ns_len); 9037b5038d7SDag-Erling Smørgrav 904*17d15b25SDag-Erling Smørgrav resolver->_socket = ldns_tcp_connect_from( 905*17d15b25SDag-Erling Smørgrav ns, (socklen_t)ns_len, 906*17d15b25SDag-Erling Smørgrav src, (socklen_t)src_len, 9077b5038d7SDag-Erling Smørgrav ldns_resolver_timeout(resolver)); 9087b5038d7SDag-Erling Smørgrav } 9097b5038d7SDag-Erling Smørgrav 9107b5038d7SDag-Erling Smørgrav if (resolver->_socket == 0) { 9117b5038d7SDag-Erling Smørgrav ldns_pkt_free(query); 9127b5038d7SDag-Erling Smørgrav LDNS_FREE(ns); 9137b5038d7SDag-Erling Smørgrav return LDNS_STATUS_NETWORK_ERR; 9147b5038d7SDag-Erling Smørgrav } 9157b5038d7SDag-Erling Smørgrav 9167b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL 9177b5038d7SDag-Erling Smørgrav if (ldns_resolver_tsig_keyname(resolver) && ldns_resolver_tsig_keydata(resolver)) { 9187b5038d7SDag-Erling Smørgrav status = ldns_pkt_tsig_sign(query, 9197b5038d7SDag-Erling Smørgrav ldns_resolver_tsig_keyname(resolver), 9207b5038d7SDag-Erling Smørgrav ldns_resolver_tsig_keydata(resolver), 9217b5038d7SDag-Erling Smørgrav 300, ldns_resolver_tsig_algorithm(resolver), NULL); 9227b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) { 923*17d15b25SDag-Erling Smørgrav /* to prevent problems on subsequent calls to 924*17d15b25SDag-Erling Smørgrav * ldns_axfr_start we have to close the socket here! */ 9257b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK 9267b5038d7SDag-Erling Smørgrav close(resolver->_socket); 9277b5038d7SDag-Erling Smørgrav #else 9287b5038d7SDag-Erling Smørgrav closesocket(resolver->_socket); 9297b5038d7SDag-Erling Smørgrav #endif 9307b5038d7SDag-Erling Smørgrav resolver->_socket = 0; 9317b5038d7SDag-Erling Smørgrav 9322787e39aSDag-Erling Smørgrav ldns_pkt_free(query); 9332787e39aSDag-Erling Smørgrav LDNS_FREE(ns); 9342787e39aSDag-Erling Smørgrav 9357b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_TSIG_ERR; 9367b5038d7SDag-Erling Smørgrav } 9377b5038d7SDag-Erling Smørgrav } 9387b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */ 9397b5038d7SDag-Erling Smørgrav 9407b5038d7SDag-Erling Smørgrav /* Convert the query to a buffer 9417b5038d7SDag-Erling Smørgrav * Is this necessary? 9427b5038d7SDag-Erling Smørgrav */ 9437b5038d7SDag-Erling Smørgrav query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN); 9447b5038d7SDag-Erling Smørgrav if(!query_wire) { 9457b5038d7SDag-Erling Smørgrav ldns_pkt_free(query); 9467b5038d7SDag-Erling Smørgrav LDNS_FREE(ns); 9477b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK 9487b5038d7SDag-Erling Smørgrav close(resolver->_socket); 9497b5038d7SDag-Erling Smørgrav #else 9507b5038d7SDag-Erling Smørgrav closesocket(resolver->_socket); 9517b5038d7SDag-Erling Smørgrav #endif 9527b5038d7SDag-Erling Smørgrav resolver->_socket = 0; 9537b5038d7SDag-Erling Smørgrav 9547b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR; 9557b5038d7SDag-Erling Smørgrav } 9567b5038d7SDag-Erling Smørgrav status = ldns_pkt2buffer_wire(query_wire, query); 9577b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) { 9587b5038d7SDag-Erling Smørgrav ldns_pkt_free(query); 9597b5038d7SDag-Erling Smørgrav ldns_buffer_free(query_wire); 9607b5038d7SDag-Erling Smørgrav LDNS_FREE(ns); 9617b5038d7SDag-Erling Smørgrav 962*17d15b25SDag-Erling Smørgrav /* to prevent problems on subsequent calls to ldns_axfr_start 963*17d15b25SDag-Erling Smørgrav * we have to close the socket here! */ 9647b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK 9657b5038d7SDag-Erling Smørgrav close(resolver->_socket); 9667b5038d7SDag-Erling Smørgrav #else 9677b5038d7SDag-Erling Smørgrav closesocket(resolver->_socket); 9687b5038d7SDag-Erling Smørgrav #endif 9697b5038d7SDag-Erling Smørgrav resolver->_socket = 0; 9707b5038d7SDag-Erling Smørgrav 9717b5038d7SDag-Erling Smørgrav return status; 9727b5038d7SDag-Erling Smørgrav } 9737b5038d7SDag-Erling Smørgrav /* Send the query */ 9747b5038d7SDag-Erling Smørgrav if (ldns_tcp_send_query(query_wire, resolver->_socket, ns, 9757b5038d7SDag-Erling Smørgrav (socklen_t)ns_len) == 0) { 9767b5038d7SDag-Erling Smørgrav ldns_pkt_free(query); 9777b5038d7SDag-Erling Smørgrav ldns_buffer_free(query_wire); 9787b5038d7SDag-Erling Smørgrav LDNS_FREE(ns); 9797b5038d7SDag-Erling Smørgrav 980*17d15b25SDag-Erling Smørgrav /* to prevent problems on subsequent calls to ldns_axfr_start 981*17d15b25SDag-Erling Smørgrav * we have to close the socket here! */ 9827b5038d7SDag-Erling Smørgrav 9837b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK 9847b5038d7SDag-Erling Smørgrav close(resolver->_socket); 9857b5038d7SDag-Erling Smørgrav #else 9867b5038d7SDag-Erling Smørgrav closesocket(resolver->_socket); 9877b5038d7SDag-Erling Smørgrav #endif 9887b5038d7SDag-Erling Smørgrav resolver->_socket = 0; 9897b5038d7SDag-Erling Smørgrav 9907b5038d7SDag-Erling Smørgrav return LDNS_STATUS_NETWORK_ERR; 9917b5038d7SDag-Erling Smørgrav } 9927b5038d7SDag-Erling Smørgrav 9937b5038d7SDag-Erling Smørgrav ldns_pkt_free(query); 9947b5038d7SDag-Erling Smørgrav ldns_buffer_free(query_wire); 9957b5038d7SDag-Erling Smørgrav LDNS_FREE(ns); 9967b5038d7SDag-Erling Smørgrav 9977b5038d7SDag-Erling Smørgrav /* 9987b5038d7SDag-Erling Smørgrav * The AXFR is done once the second SOA record is sent 9997b5038d7SDag-Erling Smørgrav */ 10007b5038d7SDag-Erling Smørgrav resolver->_axfr_soa_count = 0; 10017b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK; 10027b5038d7SDag-Erling Smørgrav } 1003