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>
33986ba33cSDag-Erling Smørgrav #ifdef HAVE_POLL
34986ba33cSDag-Erling Smørgrav #include <poll.h>
35986ba33cSDag-Erling Smørgrav #endif
367b5038d7SDag-Erling Smørgrav
377b5038d7SDag-Erling Smørgrav ldns_status
ldns_send(ldns_pkt ** result_packet,ldns_resolver * r,const ldns_pkt * query_pkt)387b5038d7SDag-Erling Smørgrav ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt)
397b5038d7SDag-Erling Smørgrav {
407b5038d7SDag-Erling Smørgrav ldns_buffer *qb;
417b5038d7SDag-Erling Smørgrav ldns_status result;
427b5038d7SDag-Erling Smørgrav ldns_rdf *tsig_mac = NULL;
437b5038d7SDag-Erling Smørgrav
447b5038d7SDag-Erling Smørgrav qb = ldns_buffer_new(LDNS_MIN_BUFLEN);
457b5038d7SDag-Erling Smørgrav
467b5038d7SDag-Erling Smørgrav if (query_pkt && ldns_pkt_tsig(query_pkt)) {
477b5038d7SDag-Erling Smørgrav tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3);
487b5038d7SDag-Erling Smørgrav }
497b5038d7SDag-Erling Smørgrav
507b5038d7SDag-Erling Smørgrav if (!query_pkt ||
517b5038d7SDag-Erling Smørgrav ldns_pkt2buffer_wire(qb, query_pkt) != LDNS_STATUS_OK) {
527b5038d7SDag-Erling Smørgrav result = LDNS_STATUS_ERR;
537b5038d7SDag-Erling Smørgrav } else {
547b5038d7SDag-Erling Smørgrav result = ldns_send_buffer(result_packet, r, qb, tsig_mac);
557b5038d7SDag-Erling Smørgrav }
567b5038d7SDag-Erling Smørgrav
577b5038d7SDag-Erling Smørgrav ldns_buffer_free(qb);
587b5038d7SDag-Erling Smørgrav
597b5038d7SDag-Erling Smørgrav return result;
607b5038d7SDag-Erling Smørgrav }
617b5038d7SDag-Erling Smørgrav
6217d15b25SDag-Erling Smørgrav /* code from rdata.c */
6317d15b25SDag-Erling Smørgrav static struct sockaddr_storage *
ldns_rdf2native_sockaddr_storage_port(const ldns_rdf * rd,uint16_t port,size_t * size)6417d15b25SDag-Erling Smørgrav ldns_rdf2native_sockaddr_storage_port(
6517d15b25SDag-Erling Smørgrav const ldns_rdf *rd, uint16_t port, size_t *size)
667b5038d7SDag-Erling Smørgrav {
6717d15b25SDag-Erling Smørgrav struct sockaddr_storage *data;
6817d15b25SDag-Erling Smørgrav struct sockaddr_in *data_in;
6917d15b25SDag-Erling Smørgrav struct sockaddr_in6 *data_in6;
707b5038d7SDag-Erling Smørgrav
7117d15b25SDag-Erling Smørgrav data = LDNS_MALLOC(struct sockaddr_storage);
7217d15b25SDag-Erling Smørgrav if (!data) {
7317d15b25SDag-Erling Smørgrav return NULL;
747b5038d7SDag-Erling Smørgrav }
7517d15b25SDag-Erling Smørgrav /* zero the structure for portability */
7617d15b25SDag-Erling Smørgrav memset(data, 0, sizeof(struct sockaddr_storage));
777b5038d7SDag-Erling Smørgrav
7817d15b25SDag-Erling Smørgrav switch(ldns_rdf_get_type(rd)) {
7917d15b25SDag-Erling Smørgrav case LDNS_RDF_TYPE_A:
807b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
8117d15b25SDag-Erling Smørgrav data->ss_family = AF_INET;
827b5038d7SDag-Erling Smørgrav #endif
8317d15b25SDag-Erling Smørgrav data_in = (struct sockaddr_in*) data;
8417d15b25SDag-Erling Smørgrav data_in->sin_port = (in_port_t)htons(port);
8517d15b25SDag-Erling Smørgrav memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd));
8617d15b25SDag-Erling Smørgrav *size = sizeof(struct sockaddr_in);
8717d15b25SDag-Erling Smørgrav return data;
8817d15b25SDag-Erling Smørgrav case LDNS_RDF_TYPE_AAAA:
8917d15b25SDag-Erling Smørgrav #ifndef S_SPLINT_S
9017d15b25SDag-Erling Smørgrav data->ss_family = AF_INET6;
9117d15b25SDag-Erling Smørgrav #endif
9217d15b25SDag-Erling Smørgrav data_in6 = (struct sockaddr_in6*) data;
9317d15b25SDag-Erling Smørgrav data_in6->sin6_port = (in_port_t)htons(port);
9417d15b25SDag-Erling Smørgrav memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd));
9517d15b25SDag-Erling Smørgrav *size = sizeof(struct sockaddr_in6);
9617d15b25SDag-Erling Smørgrav return data;
9717d15b25SDag-Erling Smørgrav default:
9817d15b25SDag-Erling Smørgrav LDNS_FREE(data);
9917d15b25SDag-Erling Smørgrav return NULL;
1007b5038d7SDag-Erling Smørgrav }
1017b5038d7SDag-Erling Smørgrav }
1027b5038d7SDag-Erling Smørgrav
10317d15b25SDag-Erling Smørgrav struct sockaddr_storage *
ldns_rdf2native_sockaddr_storage(const ldns_rdf * rd,uint16_t port,size_t * size)10417d15b25SDag-Erling Smørgrav ldns_rdf2native_sockaddr_storage(
10517d15b25SDag-Erling Smørgrav const ldns_rdf *rd, uint16_t port, size_t *size)
10617d15b25SDag-Erling Smørgrav {
10717d15b25SDag-Erling Smørgrav return ldns_rdf2native_sockaddr_storage_port(
10817d15b25SDag-Erling Smørgrav rd, (port == 0 ? (uint16_t)LDNS_PORT : port), size);
1097b5038d7SDag-Erling Smørgrav }
1107b5038d7SDag-Erling Smørgrav
1117b5038d7SDag-Erling Smørgrav /** best effort to set nonblocking */
1127b5038d7SDag-Erling Smørgrav static void
ldns_sock_nonblock(int sockfd)1137b5038d7SDag-Erling Smørgrav ldns_sock_nonblock(int sockfd)
1147b5038d7SDag-Erling Smørgrav {
1157b5038d7SDag-Erling Smørgrav #ifdef HAVE_FCNTL
1167b5038d7SDag-Erling Smørgrav int flag;
1177b5038d7SDag-Erling Smørgrav if((flag = fcntl(sockfd, F_GETFL)) != -1) {
1187b5038d7SDag-Erling Smørgrav flag |= O_NONBLOCK;
1197b5038d7SDag-Erling Smørgrav if(fcntl(sockfd, F_SETFL, flag) == -1) {
1207b5038d7SDag-Erling Smørgrav /* ignore error, continue blockingly */
1217b5038d7SDag-Erling Smørgrav }
1227b5038d7SDag-Erling Smørgrav }
1237b5038d7SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET)
1247b5038d7SDag-Erling Smørgrav unsigned long on = 1;
1257b5038d7SDag-Erling Smørgrav if(ioctlsocket(sockfd, FIONBIO, &on) != 0) {
1267b5038d7SDag-Erling Smørgrav /* ignore error, continue blockingly */
1277b5038d7SDag-Erling Smørgrav }
1287b5038d7SDag-Erling Smørgrav #endif
1297b5038d7SDag-Erling Smørgrav }
1307b5038d7SDag-Erling Smørgrav
1317b5038d7SDag-Erling Smørgrav /** best effort to set blocking */
1327b5038d7SDag-Erling Smørgrav static void
ldns_sock_block(int sockfd)1337b5038d7SDag-Erling Smørgrav ldns_sock_block(int sockfd)
1347b5038d7SDag-Erling Smørgrav {
1357b5038d7SDag-Erling Smørgrav #ifdef HAVE_FCNTL
1367b5038d7SDag-Erling Smørgrav int flag;
1377b5038d7SDag-Erling Smørgrav if((flag = fcntl(sockfd, F_GETFL)) != -1) {
1387b5038d7SDag-Erling Smørgrav flag &= ~O_NONBLOCK;
1397b5038d7SDag-Erling Smørgrav if(fcntl(sockfd, F_SETFL, flag) == -1) {
1407b5038d7SDag-Erling Smørgrav /* ignore error, continue */
1417b5038d7SDag-Erling Smørgrav }
1427b5038d7SDag-Erling Smørgrav }
1437b5038d7SDag-Erling Smørgrav #elif defined(HAVE_IOCTLSOCKET)
1447b5038d7SDag-Erling Smørgrav unsigned long off = 0;
1457b5038d7SDag-Erling Smørgrav if(ioctlsocket(sockfd, FIONBIO, &off) != 0) {
1467b5038d7SDag-Erling Smørgrav /* ignore error, continue */
1477b5038d7SDag-Erling Smørgrav }
1487b5038d7SDag-Erling Smørgrav #endif
1497b5038d7SDag-Erling Smørgrav }
1507b5038d7SDag-Erling Smørgrav
1517b5038d7SDag-Erling Smørgrav /** wait for a socket to become ready */
1527b5038d7SDag-Erling Smørgrav static int
ldns_sock_wait(int sockfd,struct timeval timeout,int write)1537b5038d7SDag-Erling Smørgrav ldns_sock_wait(int sockfd, struct timeval timeout, int write)
1547b5038d7SDag-Erling Smørgrav {
1557b5038d7SDag-Erling Smørgrav int ret;
156986ba33cSDag-Erling Smørgrav #ifndef HAVE_POLL
1577b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
1587b5038d7SDag-Erling Smørgrav fd_set fds;
1597b5038d7SDag-Erling Smørgrav FD_ZERO(&fds);
1607b5038d7SDag-Erling Smørgrav FD_SET(FD_SET_T sockfd, &fds);
1617b5038d7SDag-Erling Smørgrav if(write)
1627b5038d7SDag-Erling Smørgrav ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
1637b5038d7SDag-Erling Smørgrav else
1647b5038d7SDag-Erling Smørgrav ret = select(sockfd+1, &fds, NULL, NULL, &timeout);
1657b5038d7SDag-Erling Smørgrav #endif
166986ba33cSDag-Erling Smørgrav #else
167986ba33cSDag-Erling Smørgrav struct pollfd pfds[2];
168986ba33cSDag-Erling Smørgrav
169986ba33cSDag-Erling Smørgrav memset(&pfds[0], 0, sizeof(pfds[0]) * 2);
170986ba33cSDag-Erling Smørgrav
171986ba33cSDag-Erling Smørgrav pfds[0].fd = sockfd;
172986ba33cSDag-Erling Smørgrav pfds[0].events = POLLIN|POLLERR;
173986ba33cSDag-Erling Smørgrav
174986ba33cSDag-Erling Smørgrav if (write) {
175986ba33cSDag-Erling Smørgrav pfds[0].events |= POLLOUT;
176986ba33cSDag-Erling Smørgrav }
177986ba33cSDag-Erling Smørgrav
178986ba33cSDag-Erling Smørgrav ret = poll(pfds, 1, (int)(timeout.tv_sec * 1000
179986ba33cSDag-Erling Smørgrav + timeout.tv_usec / 1000));
180986ba33cSDag-Erling Smørgrav #endif
1817b5038d7SDag-Erling Smørgrav if(ret == 0)
1827b5038d7SDag-Erling Smørgrav /* timeout expired */
1837b5038d7SDag-Erling Smørgrav return 0;
1847b5038d7SDag-Erling Smørgrav else if(ret == -1)
1857b5038d7SDag-Erling Smørgrav /* error */
1867b5038d7SDag-Erling Smørgrav return 0;
1877b5038d7SDag-Erling Smørgrav return 1;
1887b5038d7SDag-Erling Smørgrav }
1897b5038d7SDag-Erling Smørgrav
1907b5038d7SDag-Erling Smørgrav
19117d15b25SDag-Erling Smørgrav static int
ldns_tcp_connect_from(const struct sockaddr_storage * to,socklen_t tolen,const struct sockaddr_storage * from,socklen_t fromlen,struct timeval timeout)19217d15b25SDag-Erling Smørgrav ldns_tcp_connect_from(const struct sockaddr_storage *to, socklen_t tolen,
19317d15b25SDag-Erling Smørgrav const struct sockaddr_storage *from, socklen_t fromlen,
1947b5038d7SDag-Erling Smørgrav struct timeval timeout)
1957b5038d7SDag-Erling Smørgrav {
1967b5038d7SDag-Erling Smørgrav int sockfd;
1977b5038d7SDag-Erling Smørgrav
1987b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
1997b5038d7SDag-Erling Smørgrav if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM,
200986ba33cSDag-Erling Smørgrav IPPROTO_TCP)) == SOCK_INVALID) {
201*5afab0e5SDag-Erling Smørgrav return -1;
2027b5038d7SDag-Erling Smørgrav }
2037b5038d7SDag-Erling Smørgrav #endif
204986ba33cSDag-Erling Smørgrav if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == SOCK_INVALID){
205*5afab0e5SDag-Erling Smørgrav close_socket(sockfd);
206*5afab0e5SDag-Erling Smørgrav return -1;
20717d15b25SDag-Erling Smørgrav }
2087b5038d7SDag-Erling Smørgrav
2097b5038d7SDag-Erling Smørgrav /* perform nonblocking connect, to be able to wait with select() */
2107b5038d7SDag-Erling Smørgrav ldns_sock_nonblock(sockfd);
211986ba33cSDag-Erling Smørgrav if (connect(sockfd, (struct sockaddr*)to, tolen) == SOCK_INVALID) {
2127b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK
2137b5038d7SDag-Erling Smørgrav #ifdef EINPROGRESS
2147b5038d7SDag-Erling Smørgrav if(errno != EINPROGRESS) {
2157b5038d7SDag-Erling Smørgrav #else
2167b5038d7SDag-Erling Smørgrav if(1) {
2177b5038d7SDag-Erling Smørgrav #endif
218986ba33cSDag-Erling Smørgrav close_socket(sockfd);
219*5afab0e5SDag-Erling Smørgrav return -1;
2207b5038d7SDag-Erling Smørgrav }
2217b5038d7SDag-Erling Smørgrav #else /* USE_WINSOCK */
2227b5038d7SDag-Erling Smørgrav if(WSAGetLastError() != WSAEINPROGRESS &&
2237b5038d7SDag-Erling Smørgrav WSAGetLastError() != WSAEWOULDBLOCK) {
224986ba33cSDag-Erling Smørgrav close_socket(sockfd);
225*5afab0e5SDag-Erling Smørgrav return -1;
2267b5038d7SDag-Erling Smørgrav }
2277b5038d7SDag-Erling Smørgrav #endif
2287b5038d7SDag-Erling Smørgrav /* error was only telling us that it would block */
2297b5038d7SDag-Erling Smørgrav }
2307b5038d7SDag-Erling Smørgrav
2317b5038d7SDag-Erling Smørgrav /* wait(write) until connected or error */
2327b5038d7SDag-Erling Smørgrav while(1) {
2337b5038d7SDag-Erling Smørgrav int error = 0;
2347b5038d7SDag-Erling Smørgrav socklen_t len = (socklen_t)sizeof(error);
2357b5038d7SDag-Erling Smørgrav
2367b5038d7SDag-Erling Smørgrav if(!ldns_sock_wait(sockfd, timeout, 1)) {
237986ba33cSDag-Erling Smørgrav close_socket(sockfd);
238*5afab0e5SDag-Erling Smørgrav return -1;
2397b5038d7SDag-Erling Smørgrav }
2407b5038d7SDag-Erling Smørgrav
2417b5038d7SDag-Erling Smørgrav /* check if there is a pending error for nonblocking connect */
2427b5038d7SDag-Erling Smørgrav if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error,
2437b5038d7SDag-Erling Smørgrav &len) < 0) {
2447b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK
2457b5038d7SDag-Erling Smørgrav error = errno; /* on solaris errno is error */
2467b5038d7SDag-Erling Smørgrav #else
2477b5038d7SDag-Erling Smørgrav error = WSAGetLastError();
2487b5038d7SDag-Erling Smørgrav #endif
2497b5038d7SDag-Erling Smørgrav }
2507b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK
2517b5038d7SDag-Erling Smørgrav #if defined(EINPROGRESS) && defined(EWOULDBLOCK)
2527b5038d7SDag-Erling Smørgrav if(error == EINPROGRESS || error == EWOULDBLOCK)
2537b5038d7SDag-Erling Smørgrav continue; /* try again */
2547b5038d7SDag-Erling Smørgrav #endif
2557b5038d7SDag-Erling Smørgrav else if(error != 0) {
256986ba33cSDag-Erling Smørgrav close_socket(sockfd);
2577b5038d7SDag-Erling Smørgrav /* error in errno for our user */
2587b5038d7SDag-Erling Smørgrav errno = error;
259*5afab0e5SDag-Erling Smørgrav return -1;
2607b5038d7SDag-Erling Smørgrav }
2617b5038d7SDag-Erling Smørgrav #else /* USE_WINSOCK */
2627b5038d7SDag-Erling Smørgrav if(error == WSAEINPROGRESS)
2637b5038d7SDag-Erling Smørgrav continue;
2647b5038d7SDag-Erling Smørgrav else if(error == WSAEWOULDBLOCK)
2657b5038d7SDag-Erling Smørgrav continue;
2667b5038d7SDag-Erling Smørgrav else if(error != 0) {
267986ba33cSDag-Erling Smørgrav close_socket(sockfd);
2687b5038d7SDag-Erling Smørgrav errno = error;
269*5afab0e5SDag-Erling Smørgrav return -1;
2707b5038d7SDag-Erling Smørgrav }
2717b5038d7SDag-Erling Smørgrav #endif /* USE_WINSOCK */
2727b5038d7SDag-Erling Smørgrav /* connected */
2737b5038d7SDag-Erling Smørgrav break;
2747b5038d7SDag-Erling Smørgrav }
2757b5038d7SDag-Erling Smørgrav
2767b5038d7SDag-Erling Smørgrav /* set the socket blocking again */
2777b5038d7SDag-Erling Smørgrav ldns_sock_block(sockfd);
2787b5038d7SDag-Erling Smørgrav
2797b5038d7SDag-Erling Smørgrav return sockfd;
2807b5038d7SDag-Erling Smørgrav }
2817b5038d7SDag-Erling Smørgrav
28217d15b25SDag-Erling Smørgrav int
28317d15b25SDag-Erling Smørgrav ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen,
28417d15b25SDag-Erling Smørgrav struct timeval timeout)
28517d15b25SDag-Erling Smørgrav {
286*5afab0e5SDag-Erling Smørgrav int s = ldns_tcp_connect_from(to, tolen, NULL, 0, timeout);
287*5afab0e5SDag-Erling Smørgrav return s > 0 ? s : 0;
288*5afab0e5SDag-Erling Smørgrav }
289*5afab0e5SDag-Erling Smørgrav
290*5afab0e5SDag-Erling Smørgrav int
291*5afab0e5SDag-Erling Smørgrav ldns_tcp_connect2(const struct sockaddr_storage *to, socklen_t tolen,
292*5afab0e5SDag-Erling Smørgrav struct timeval timeout)
293*5afab0e5SDag-Erling Smørgrav {
29417d15b25SDag-Erling Smørgrav return ldns_tcp_connect_from(to, tolen, NULL, 0, timeout);
29517d15b25SDag-Erling Smørgrav }
29617d15b25SDag-Erling Smørgrav
29717d15b25SDag-Erling Smørgrav static int
29817d15b25SDag-Erling Smørgrav ldns_tcp_bgsend_from(ldns_buffer *qbin,
29917d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to, socklen_t tolen,
30017d15b25SDag-Erling Smørgrav const struct sockaddr_storage *from, socklen_t fromlen,
30117d15b25SDag-Erling Smørgrav struct timeval timeout)
30217d15b25SDag-Erling Smørgrav {
30317d15b25SDag-Erling Smørgrav int sockfd;
30417d15b25SDag-Erling Smørgrav
30517d15b25SDag-Erling Smørgrav sockfd = ldns_tcp_connect_from(to, tolen, from, fromlen, timeout);
30617d15b25SDag-Erling Smørgrav
307*5afab0e5SDag-Erling Smørgrav if (sockfd >= 0 && ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) {
308986ba33cSDag-Erling Smørgrav close_socket(sockfd);
309*5afab0e5SDag-Erling Smørgrav return -1;
31017d15b25SDag-Erling Smørgrav }
31117d15b25SDag-Erling Smørgrav
31217d15b25SDag-Erling Smørgrav return sockfd;
31317d15b25SDag-Erling Smørgrav }
31417d15b25SDag-Erling Smørgrav
31517d15b25SDag-Erling Smørgrav int
31617d15b25SDag-Erling Smørgrav ldns_tcp_bgsend(ldns_buffer *qbin,
31717d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to, socklen_t tolen,
31817d15b25SDag-Erling Smørgrav struct timeval timeout)
31917d15b25SDag-Erling Smørgrav {
320*5afab0e5SDag-Erling Smørgrav int s = ldns_tcp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
321*5afab0e5SDag-Erling Smørgrav return s > 0 ? s : 0;
32217d15b25SDag-Erling Smørgrav }
32317d15b25SDag-Erling Smørgrav
324*5afab0e5SDag-Erling Smørgrav int
325*5afab0e5SDag-Erling Smørgrav ldns_tcp_bgsend2(ldns_buffer *qbin,
326*5afab0e5SDag-Erling Smørgrav const struct sockaddr_storage *to, socklen_t tolen,
327*5afab0e5SDag-Erling Smørgrav struct timeval timeout)
328*5afab0e5SDag-Erling Smørgrav {
329*5afab0e5SDag-Erling Smørgrav return ldns_tcp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
330*5afab0e5SDag-Erling Smørgrav }
33117d15b25SDag-Erling Smørgrav
33217d15b25SDag-Erling Smørgrav /* keep in mind that in DNS tcp messages the first 2 bytes signal the
33317d15b25SDag-Erling Smørgrav * amount data to expect
33417d15b25SDag-Erling Smørgrav */
33517d15b25SDag-Erling Smørgrav static ldns_status
33617d15b25SDag-Erling Smørgrav ldns_tcp_send_from(uint8_t **result, ldns_buffer *qbin,
33717d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to, socklen_t tolen,
33817d15b25SDag-Erling Smørgrav const struct sockaddr_storage *from, socklen_t fromlen,
33917d15b25SDag-Erling Smørgrav struct timeval timeout, size_t *answer_size)
34017d15b25SDag-Erling Smørgrav {
34117d15b25SDag-Erling Smørgrav int sockfd;
34217d15b25SDag-Erling Smørgrav uint8_t *answer;
34317d15b25SDag-Erling Smørgrav
34417d15b25SDag-Erling Smørgrav sockfd = ldns_tcp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
34517d15b25SDag-Erling Smørgrav
346*5afab0e5SDag-Erling Smørgrav if (sockfd == -1) {
34717d15b25SDag-Erling Smørgrav return LDNS_STATUS_ERR;
34817d15b25SDag-Erling Smørgrav }
34917d15b25SDag-Erling Smørgrav
35017d15b25SDag-Erling Smørgrav answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout);
351986ba33cSDag-Erling Smørgrav close_socket(sockfd);
35217d15b25SDag-Erling Smørgrav
353*5afab0e5SDag-Erling Smørgrav if (!answer) {
35417d15b25SDag-Erling Smørgrav /* oops */
35517d15b25SDag-Erling Smørgrav return LDNS_STATUS_NETWORK_ERR;
35617d15b25SDag-Erling Smørgrav }
35717d15b25SDag-Erling Smørgrav
358*5afab0e5SDag-Erling Smørgrav *result = answer;
35917d15b25SDag-Erling Smørgrav return LDNS_STATUS_OK;
36017d15b25SDag-Erling Smørgrav }
36117d15b25SDag-Erling Smørgrav
36217d15b25SDag-Erling Smørgrav ldns_status
36317d15b25SDag-Erling Smørgrav ldns_tcp_send(uint8_t **result, ldns_buffer *qbin,
36417d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to, socklen_t tolen,
36517d15b25SDag-Erling Smørgrav struct timeval timeout, size_t *answer_size)
36617d15b25SDag-Erling Smørgrav {
36717d15b25SDag-Erling Smørgrav return ldns_tcp_send_from(result, qbin,
36817d15b25SDag-Erling Smørgrav to, tolen, NULL, 0, timeout, answer_size);
36917d15b25SDag-Erling Smørgrav }
37017d15b25SDag-Erling Smørgrav
37117d15b25SDag-Erling Smørgrav int
37217d15b25SDag-Erling Smørgrav ldns_udp_connect(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout))
37317d15b25SDag-Erling Smørgrav {
37417d15b25SDag-Erling Smørgrav int sockfd;
37517d15b25SDag-Erling Smørgrav
37617d15b25SDag-Erling Smørgrav #ifndef S_SPLINT_S
37717d15b25SDag-Erling Smørgrav if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM,
37817d15b25SDag-Erling Smørgrav IPPROTO_UDP))
379*5afab0e5SDag-Erling Smørgrav == SOCK_INVALID) {
38017d15b25SDag-Erling Smørgrav return 0;
38117d15b25SDag-Erling Smørgrav }
38217d15b25SDag-Erling Smørgrav #endif
38317d15b25SDag-Erling Smørgrav return sockfd;
38417d15b25SDag-Erling Smørgrav }
38517d15b25SDag-Erling Smørgrav
386*5afab0e5SDag-Erling Smørgrav int
387*5afab0e5SDag-Erling Smørgrav ldns_udp_connect2(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout))
388*5afab0e5SDag-Erling Smørgrav {
389*5afab0e5SDag-Erling Smørgrav int sockfd;
390*5afab0e5SDag-Erling Smørgrav
391*5afab0e5SDag-Erling Smørgrav #ifndef S_SPLINT_S
392*5afab0e5SDag-Erling Smørgrav if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM,
393*5afab0e5SDag-Erling Smørgrav IPPROTO_UDP))
394*5afab0e5SDag-Erling Smørgrav == SOCK_INVALID) {
395*5afab0e5SDag-Erling Smørgrav return -1;
396*5afab0e5SDag-Erling Smørgrav }
397*5afab0e5SDag-Erling Smørgrav #endif
398*5afab0e5SDag-Erling Smørgrav return sockfd;
399*5afab0e5SDag-Erling Smørgrav }
400*5afab0e5SDag-Erling Smørgrav
40117d15b25SDag-Erling Smørgrav static int
40217d15b25SDag-Erling Smørgrav ldns_udp_bgsend_from(ldns_buffer *qbin,
40317d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to , socklen_t tolen,
40417d15b25SDag-Erling Smørgrav const struct sockaddr_storage *from, socklen_t fromlen,
40517d15b25SDag-Erling Smørgrav struct timeval timeout)
40617d15b25SDag-Erling Smørgrav {
40717d15b25SDag-Erling Smørgrav int sockfd;
40817d15b25SDag-Erling Smørgrav
409*5afab0e5SDag-Erling Smørgrav sockfd = ldns_udp_connect2(to, timeout);
41017d15b25SDag-Erling Smørgrav
411*5afab0e5SDag-Erling Smørgrav if (sockfd == -1) {
412*5afab0e5SDag-Erling Smørgrav return -1;
41317d15b25SDag-Erling Smørgrav }
41417d15b25SDag-Erling Smørgrav
41517d15b25SDag-Erling Smørgrav if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){
416*5afab0e5SDag-Erling Smørgrav close_socket(sockfd);
417*5afab0e5SDag-Erling Smørgrav return -1;
41817d15b25SDag-Erling Smørgrav }
41917d15b25SDag-Erling Smørgrav
42017d15b25SDag-Erling Smørgrav if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) {
421986ba33cSDag-Erling Smørgrav close_socket(sockfd);
422*5afab0e5SDag-Erling Smørgrav return -1;
42317d15b25SDag-Erling Smørgrav }
42417d15b25SDag-Erling Smørgrav return sockfd;
42517d15b25SDag-Erling Smørgrav }
42617d15b25SDag-Erling Smørgrav
42717d15b25SDag-Erling Smørgrav int
42817d15b25SDag-Erling Smørgrav ldns_udp_bgsend(ldns_buffer *qbin,
42917d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to , socklen_t tolen,
43017d15b25SDag-Erling Smørgrav struct timeval timeout)
43117d15b25SDag-Erling Smørgrav {
432*5afab0e5SDag-Erling Smørgrav int s = ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
433*5afab0e5SDag-Erling Smørgrav return s > 0 ? s : 0;
434*5afab0e5SDag-Erling Smørgrav }
435*5afab0e5SDag-Erling Smørgrav
436*5afab0e5SDag-Erling Smørgrav int
437*5afab0e5SDag-Erling Smørgrav ldns_udp_bgsend2(ldns_buffer *qbin,
438*5afab0e5SDag-Erling Smørgrav const struct sockaddr_storage *to , socklen_t tolen,
439*5afab0e5SDag-Erling Smørgrav struct timeval timeout)
440*5afab0e5SDag-Erling Smørgrav {
44117d15b25SDag-Erling Smørgrav return ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
44217d15b25SDag-Erling Smørgrav }
44317d15b25SDag-Erling Smørgrav
44417d15b25SDag-Erling Smørgrav static ldns_status
44517d15b25SDag-Erling Smørgrav ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
44617d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to , socklen_t tolen,
44717d15b25SDag-Erling Smørgrav const struct sockaddr_storage *from, socklen_t fromlen,
44817d15b25SDag-Erling Smørgrav struct timeval timeout, size_t *answer_size)
44917d15b25SDag-Erling Smørgrav {
45017d15b25SDag-Erling Smørgrav int sockfd;
45117d15b25SDag-Erling Smørgrav uint8_t *answer;
45217d15b25SDag-Erling Smørgrav
45317d15b25SDag-Erling Smørgrav sockfd = ldns_udp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
45417d15b25SDag-Erling Smørgrav
455*5afab0e5SDag-Erling Smørgrav if (sockfd == -1) {
45617d15b25SDag-Erling Smørgrav return LDNS_STATUS_SOCKET_ERROR;
45717d15b25SDag-Erling Smørgrav }
45817d15b25SDag-Erling Smørgrav
45917d15b25SDag-Erling Smørgrav /* wait for an response*/
46017d15b25SDag-Erling Smørgrav if(!ldns_sock_wait(sockfd, timeout, 0)) {
461986ba33cSDag-Erling Smørgrav close_socket(sockfd);
46217d15b25SDag-Erling Smørgrav return LDNS_STATUS_NETWORK_ERR;
46317d15b25SDag-Erling Smørgrav }
46417d15b25SDag-Erling Smørgrav
46517d15b25SDag-Erling Smørgrav /* set to nonblocking, so if the checksum is bad, it becomes
466*5afab0e5SDag-Erling Smørgrav * an EAGAIN error and the ldns_udp_send function does not block,
46717d15b25SDag-Erling Smørgrav * but returns a 'NETWORK_ERROR' much like a timeout. */
46817d15b25SDag-Erling Smørgrav ldns_sock_nonblock(sockfd);
46917d15b25SDag-Erling Smørgrav
47017d15b25SDag-Erling Smørgrav answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
471986ba33cSDag-Erling Smørgrav close_socket(sockfd);
47217d15b25SDag-Erling Smørgrav
473*5afab0e5SDag-Erling Smørgrav if (!answer) {
47417d15b25SDag-Erling Smørgrav /* oops */
47517d15b25SDag-Erling Smørgrav return LDNS_STATUS_NETWORK_ERR;
47617d15b25SDag-Erling Smørgrav }
47717d15b25SDag-Erling Smørgrav
47817d15b25SDag-Erling Smørgrav *result = answer;
47917d15b25SDag-Erling Smørgrav return LDNS_STATUS_OK;
48017d15b25SDag-Erling Smørgrav }
48117d15b25SDag-Erling Smørgrav
48217d15b25SDag-Erling Smørgrav ldns_status
48317d15b25SDag-Erling Smørgrav ldns_udp_send(uint8_t **result, ldns_buffer *qbin,
48417d15b25SDag-Erling Smørgrav const struct sockaddr_storage *to , socklen_t tolen,
48517d15b25SDag-Erling Smørgrav struct timeval timeout, size_t *answer_size)
48617d15b25SDag-Erling Smørgrav {
48717d15b25SDag-Erling Smørgrav return ldns_udp_send_from(result, qbin, to, tolen, NULL, 0,
48817d15b25SDag-Erling Smørgrav timeout, answer_size);
48917d15b25SDag-Erling Smørgrav }
49017d15b25SDag-Erling Smørgrav
49117d15b25SDag-Erling Smørgrav ldns_status
49217d15b25SDag-Erling Smørgrav ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac)
49317d15b25SDag-Erling Smørgrav {
49417d15b25SDag-Erling Smørgrav uint8_t i;
49517d15b25SDag-Erling Smørgrav
49617d15b25SDag-Erling Smørgrav struct sockaddr_storage *src = NULL;
497*5afab0e5SDag-Erling Smørgrav size_t src_len = 0;
49817d15b25SDag-Erling Smørgrav struct sockaddr_storage *ns;
49917d15b25SDag-Erling Smørgrav size_t ns_len;
50017d15b25SDag-Erling Smørgrav struct timeval tv_s;
50117d15b25SDag-Erling Smørgrav struct timeval tv_e;
50217d15b25SDag-Erling Smørgrav
50317d15b25SDag-Erling Smørgrav ldns_rdf **ns_array;
50417d15b25SDag-Erling Smørgrav size_t *rtt;
50517d15b25SDag-Erling Smørgrav ldns_pkt *reply;
50617d15b25SDag-Erling Smørgrav bool all_servers_rtt_inf;
50717d15b25SDag-Erling Smørgrav uint8_t retries;
50817d15b25SDag-Erling Smørgrav
50917d15b25SDag-Erling Smørgrav uint8_t *reply_bytes = NULL;
51017d15b25SDag-Erling Smørgrav size_t reply_size = 0;
51117d15b25SDag-Erling Smørgrav ldns_status status, send_status;
51217d15b25SDag-Erling Smørgrav
51317d15b25SDag-Erling Smørgrav assert(r != NULL);
51417d15b25SDag-Erling Smørgrav
51517d15b25SDag-Erling Smørgrav status = LDNS_STATUS_OK;
51617d15b25SDag-Erling Smørgrav rtt = ldns_resolver_rtt(r);
51717d15b25SDag-Erling Smørgrav ns_array = ldns_resolver_nameservers(r);
51817d15b25SDag-Erling Smørgrav reply = NULL;
51917d15b25SDag-Erling Smørgrav ns_len = 0;
52017d15b25SDag-Erling Smørgrav
52117d15b25SDag-Erling Smørgrav all_servers_rtt_inf = true;
52217d15b25SDag-Erling Smørgrav
52317d15b25SDag-Erling Smørgrav if (ldns_resolver_random(r)) {
52417d15b25SDag-Erling Smørgrav ldns_resolver_nameservers_randomize(r);
52517d15b25SDag-Erling Smørgrav }
52617d15b25SDag-Erling Smørgrav
52717d15b25SDag-Erling Smørgrav if(ldns_resolver_source(r)) {
52817d15b25SDag-Erling Smørgrav src = ldns_rdf2native_sockaddr_storage_port(
52917d15b25SDag-Erling Smørgrav ldns_resolver_source(r), 0, &src_len);
53017d15b25SDag-Erling Smørgrav }
53117d15b25SDag-Erling Smørgrav
53217d15b25SDag-Erling Smørgrav /* loop through all defined nameservers */
53317d15b25SDag-Erling Smørgrav for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
53417d15b25SDag-Erling Smørgrav if (rtt[i] == LDNS_RESOLV_RTT_INF) {
53517d15b25SDag-Erling Smørgrav /* not reachable nameserver! */
53617d15b25SDag-Erling Smørgrav continue;
53717d15b25SDag-Erling Smørgrav }
53817d15b25SDag-Erling Smørgrav
53917d15b25SDag-Erling Smørgrav /* maybe verbosity setting?
54017d15b25SDag-Erling Smørgrav printf("Sending to ");
54117d15b25SDag-Erling Smørgrav ldns_rdf_print(stdout, ns_array[i]);
54217d15b25SDag-Erling Smørgrav printf("\n");
54317d15b25SDag-Erling Smørgrav */
54417d15b25SDag-Erling Smørgrav ns = ldns_rdf2native_sockaddr_storage(ns_array[i],
54517d15b25SDag-Erling Smørgrav ldns_resolver_port(r), &ns_len);
54617d15b25SDag-Erling Smørgrav
54717d15b25SDag-Erling Smørgrav
54817d15b25SDag-Erling Smørgrav #ifndef S_SPLINT_S
54917d15b25SDag-Erling Smørgrav if ((ns->ss_family == AF_INET) &&
55017d15b25SDag-Erling Smørgrav (ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) {
55117d15b25SDag-Erling Smørgrav /* not reachable */
55217d15b25SDag-Erling Smørgrav LDNS_FREE(ns);
55317d15b25SDag-Erling Smørgrav continue;
55417d15b25SDag-Erling Smørgrav }
55517d15b25SDag-Erling Smørgrav
55617d15b25SDag-Erling Smørgrav if ((ns->ss_family == AF_INET6) &&
55717d15b25SDag-Erling Smørgrav (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) {
55817d15b25SDag-Erling Smørgrav /* not reachable */
55917d15b25SDag-Erling Smørgrav LDNS_FREE(ns);
56017d15b25SDag-Erling Smørgrav continue;
56117d15b25SDag-Erling Smørgrav }
56217d15b25SDag-Erling Smørgrav #endif
56317d15b25SDag-Erling Smørgrav
56417d15b25SDag-Erling Smørgrav all_servers_rtt_inf = false;
56517d15b25SDag-Erling Smørgrav
56617d15b25SDag-Erling Smørgrav gettimeofday(&tv_s, NULL);
56717d15b25SDag-Erling Smørgrav
56817d15b25SDag-Erling Smørgrav send_status = LDNS_STATUS_ERR;
56917d15b25SDag-Erling Smørgrav
57017d15b25SDag-Erling Smørgrav /* reply_bytes implicitly handles our error */
57117d15b25SDag-Erling Smørgrav if (ldns_resolver_usevc(r)) {
57217d15b25SDag-Erling Smørgrav for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
57317d15b25SDag-Erling Smørgrav send_status =
57417d15b25SDag-Erling Smørgrav ldns_tcp_send_from(&reply_bytes, qb,
57517d15b25SDag-Erling Smørgrav ns, (socklen_t)ns_len,
57617d15b25SDag-Erling Smørgrav src, (socklen_t)src_len,
57717d15b25SDag-Erling Smørgrav ldns_resolver_timeout(r),
57817d15b25SDag-Erling Smørgrav &reply_size);
57917d15b25SDag-Erling Smørgrav if (send_status == LDNS_STATUS_OK) {
58017d15b25SDag-Erling Smørgrav break;
58117d15b25SDag-Erling Smørgrav }
58217d15b25SDag-Erling Smørgrav }
58317d15b25SDag-Erling Smørgrav } else {
58417d15b25SDag-Erling Smørgrav for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
58517d15b25SDag-Erling Smørgrav /* ldns_rdf_print(stdout, ns_array[i]); */
58617d15b25SDag-Erling Smørgrav send_status =
58717d15b25SDag-Erling Smørgrav ldns_udp_send_from(&reply_bytes, qb,
58817d15b25SDag-Erling Smørgrav ns, (socklen_t)ns_len,
58917d15b25SDag-Erling Smørgrav src, (socklen_t)src_len,
59017d15b25SDag-Erling Smørgrav ldns_resolver_timeout(r),
59117d15b25SDag-Erling Smørgrav &reply_size);
59217d15b25SDag-Erling Smørgrav if (send_status == LDNS_STATUS_OK) {
59317d15b25SDag-Erling Smørgrav break;
59417d15b25SDag-Erling Smørgrav }
59517d15b25SDag-Erling Smørgrav }
59617d15b25SDag-Erling Smørgrav }
59717d15b25SDag-Erling Smørgrav
59817d15b25SDag-Erling Smørgrav if (send_status != LDNS_STATUS_OK) {
59917d15b25SDag-Erling Smørgrav ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF);
60017d15b25SDag-Erling Smørgrav status = send_status;
60117d15b25SDag-Erling Smørgrav }
60217d15b25SDag-Erling Smørgrav
60317d15b25SDag-Erling Smørgrav /* obey the fail directive */
60417d15b25SDag-Erling Smørgrav if (!reply_bytes) {
60517d15b25SDag-Erling Smørgrav /* the current nameserver seems to have a problem, blacklist it */
60617d15b25SDag-Erling Smørgrav if (ldns_resolver_fail(r)) {
607*5afab0e5SDag-Erling Smørgrav if(src) {
608*5afab0e5SDag-Erling Smørgrav LDNS_FREE(src);
609*5afab0e5SDag-Erling Smørgrav }
61017d15b25SDag-Erling Smørgrav LDNS_FREE(ns);
61117d15b25SDag-Erling Smørgrav return LDNS_STATUS_ERR;
61217d15b25SDag-Erling Smørgrav } else {
61317d15b25SDag-Erling Smørgrav LDNS_FREE(ns);
61417d15b25SDag-Erling Smørgrav continue;
61517d15b25SDag-Erling Smørgrav }
61617d15b25SDag-Erling Smørgrav }
61717d15b25SDag-Erling Smørgrav
61817d15b25SDag-Erling Smørgrav status = ldns_wire2pkt(&reply, reply_bytes, reply_size);
61917d15b25SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) {
620*5afab0e5SDag-Erling Smørgrav if(src) LDNS_FREE(src);
62117d15b25SDag-Erling Smørgrav LDNS_FREE(reply_bytes);
62217d15b25SDag-Erling Smørgrav LDNS_FREE(ns);
62317d15b25SDag-Erling Smørgrav return status;
62417d15b25SDag-Erling Smørgrav }
625*5afab0e5SDag-Erling Smørgrav assert(reply);
62617d15b25SDag-Erling Smørgrav
62717d15b25SDag-Erling Smørgrav LDNS_FREE(ns);
62817d15b25SDag-Erling Smørgrav gettimeofday(&tv_e, NULL);
62917d15b25SDag-Erling Smørgrav
63017d15b25SDag-Erling Smørgrav if (reply) {
63117d15b25SDag-Erling Smørgrav ldns_pkt_set_querytime(reply, (uint32_t)
63217d15b25SDag-Erling Smørgrav ((tv_e.tv_sec - tv_s.tv_sec) * 1000) +
63317d15b25SDag-Erling Smørgrav (tv_e.tv_usec - tv_s.tv_usec) / 1000);
63417d15b25SDag-Erling Smørgrav ldns_pkt_set_answerfrom(reply,
63517d15b25SDag-Erling Smørgrav ldns_rdf_clone(ns_array[i]));
63617d15b25SDag-Erling Smørgrav ldns_pkt_set_timestamp(reply, tv_s);
63717d15b25SDag-Erling Smørgrav ldns_pkt_set_size(reply, reply_size);
63817d15b25SDag-Erling Smørgrav break;
63917d15b25SDag-Erling Smørgrav } else {
64017d15b25SDag-Erling Smørgrav if (ldns_resolver_fail(r)) {
64117d15b25SDag-Erling Smørgrav /* if fail is set bail out, after the first
64217d15b25SDag-Erling Smørgrav * one */
64317d15b25SDag-Erling Smørgrav break;
64417d15b25SDag-Erling Smørgrav }
64517d15b25SDag-Erling Smørgrav }
64617d15b25SDag-Erling Smørgrav
64717d15b25SDag-Erling Smørgrav /* wait retrans seconds... */
64817d15b25SDag-Erling Smørgrav sleep((unsigned int) ldns_resolver_retrans(r));
64917d15b25SDag-Erling Smørgrav }
65017d15b25SDag-Erling Smørgrav
65117d15b25SDag-Erling Smørgrav if(src) {
65217d15b25SDag-Erling Smørgrav LDNS_FREE(src);
65317d15b25SDag-Erling Smørgrav }
65417d15b25SDag-Erling Smørgrav if (all_servers_rtt_inf) {
65517d15b25SDag-Erling Smørgrav LDNS_FREE(reply_bytes);
65617d15b25SDag-Erling Smørgrav return LDNS_STATUS_RES_NO_NS;
65717d15b25SDag-Erling Smørgrav }
65817d15b25SDag-Erling Smørgrav #ifdef HAVE_SSL
65917d15b25SDag-Erling Smørgrav if (tsig_mac && reply && reply_bytes) {
66017d15b25SDag-Erling Smørgrav if (!ldns_pkt_tsig_verify(reply,
66117d15b25SDag-Erling Smørgrav reply_bytes,
66217d15b25SDag-Erling Smørgrav reply_size,
66317d15b25SDag-Erling Smørgrav ldns_resolver_tsig_keyname(r),
66417d15b25SDag-Erling Smørgrav ldns_resolver_tsig_keydata(r), tsig_mac)) {
66517d15b25SDag-Erling Smørgrav status = LDNS_STATUS_CRYPTO_TSIG_BOGUS;
66617d15b25SDag-Erling Smørgrav }
66717d15b25SDag-Erling Smørgrav }
66817d15b25SDag-Erling Smørgrav #else
66917d15b25SDag-Erling Smørgrav (void)tsig_mac;
67017d15b25SDag-Erling Smørgrav #endif /* HAVE_SSL */
67117d15b25SDag-Erling Smørgrav
67217d15b25SDag-Erling Smørgrav LDNS_FREE(reply_bytes);
67317d15b25SDag-Erling Smørgrav if (result) {
67417d15b25SDag-Erling Smørgrav *result = reply;
67517d15b25SDag-Erling Smørgrav }
67617d15b25SDag-Erling Smørgrav
67717d15b25SDag-Erling Smørgrav return status;
67817d15b25SDag-Erling Smørgrav }
67917d15b25SDag-Erling Smørgrav
6807b5038d7SDag-Erling Smørgrav ssize_t
6817b5038d7SDag-Erling Smørgrav ldns_tcp_send_query(ldns_buffer *qbin, int sockfd,
6827b5038d7SDag-Erling Smørgrav const struct sockaddr_storage *to, socklen_t tolen)
6837b5038d7SDag-Erling Smørgrav {
6847b5038d7SDag-Erling Smørgrav uint8_t *sendbuf;
6857b5038d7SDag-Erling Smørgrav ssize_t bytes;
6867b5038d7SDag-Erling Smørgrav
6877b5038d7SDag-Erling Smørgrav /* add length of packet */
6887b5038d7SDag-Erling Smørgrav sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2);
6897b5038d7SDag-Erling Smørgrav if(!sendbuf) return 0;
6907b5038d7SDag-Erling Smørgrav ldns_write_uint16(sendbuf, ldns_buffer_position(qbin));
6912787e39aSDag-Erling Smørgrav memcpy(sendbuf + 2, ldns_buffer_begin(qbin), ldns_buffer_position(qbin));
6927b5038d7SDag-Erling Smørgrav
6937b5038d7SDag-Erling Smørgrav bytes = sendto(sockfd, (void*)sendbuf,
6947b5038d7SDag-Erling Smørgrav ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen);
6957b5038d7SDag-Erling Smørgrav
6967b5038d7SDag-Erling Smørgrav LDNS_FREE(sendbuf);
6977b5038d7SDag-Erling Smørgrav
6987b5038d7SDag-Erling Smørgrav if (bytes == -1 || (size_t) bytes != ldns_buffer_position(qbin) + 2 ) {
6997b5038d7SDag-Erling Smørgrav return 0;
7007b5038d7SDag-Erling Smørgrav }
7017b5038d7SDag-Erling Smørgrav return bytes;
7027b5038d7SDag-Erling Smørgrav }
7037b5038d7SDag-Erling Smørgrav
7047b5038d7SDag-Erling Smørgrav /* don't wait for an answer */
7057b5038d7SDag-Erling Smørgrav ssize_t
7067b5038d7SDag-Erling Smørgrav ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to,
7077b5038d7SDag-Erling Smørgrav socklen_t tolen)
7087b5038d7SDag-Erling Smørgrav {
7097b5038d7SDag-Erling Smørgrav ssize_t bytes;
7107b5038d7SDag-Erling Smørgrav
7117b5038d7SDag-Erling Smørgrav bytes = sendto(sockfd, (void*)ldns_buffer_begin(qbin),
7127b5038d7SDag-Erling Smørgrav ldns_buffer_position(qbin), 0, (struct sockaddr *)to, tolen);
7137b5038d7SDag-Erling Smørgrav
7147b5038d7SDag-Erling Smørgrav if (bytes == -1 || (size_t)bytes != ldns_buffer_position(qbin)) {
7157b5038d7SDag-Erling Smørgrav return 0;
7167b5038d7SDag-Erling Smørgrav }
7177b5038d7SDag-Erling Smørgrav return bytes;
7187b5038d7SDag-Erling Smørgrav }
7197b5038d7SDag-Erling Smørgrav
7207b5038d7SDag-Erling Smørgrav uint8_t *
7217b5038d7SDag-Erling Smørgrav ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from,
7227b5038d7SDag-Erling Smørgrav socklen_t *fromlen)
7237b5038d7SDag-Erling Smørgrav {
7247b5038d7SDag-Erling Smørgrav uint8_t *wire, *wireout;
7257b5038d7SDag-Erling Smørgrav ssize_t wire_size;
7267b5038d7SDag-Erling Smørgrav
7277b5038d7SDag-Erling Smørgrav wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
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 wire_size = recvfrom(sockfd, (void*)wire, LDNS_MAX_PACKETLEN, 0,
7347b5038d7SDag-Erling Smørgrav (struct sockaddr *)from, fromlen);
7357b5038d7SDag-Erling Smørgrav
7367b5038d7SDag-Erling Smørgrav /* recvfrom can also return 0 */
7377b5038d7SDag-Erling Smørgrav if (wire_size == -1 || wire_size == 0) {
7387b5038d7SDag-Erling Smørgrav *size = 0;
7397b5038d7SDag-Erling Smørgrav LDNS_FREE(wire);
7407b5038d7SDag-Erling Smørgrav return NULL;
7417b5038d7SDag-Erling Smørgrav }
7427b5038d7SDag-Erling Smørgrav
7437b5038d7SDag-Erling Smørgrav *size = (size_t)wire_size;
7447b5038d7SDag-Erling Smørgrav wireout = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size);
7457b5038d7SDag-Erling Smørgrav if(!wireout) LDNS_FREE(wire);
7467b5038d7SDag-Erling Smørgrav
7477b5038d7SDag-Erling Smørgrav return wireout;
7487b5038d7SDag-Erling Smørgrav }
7497b5038d7SDag-Erling Smørgrav
7507b5038d7SDag-Erling Smørgrav uint8_t *
7517b5038d7SDag-Erling Smørgrav ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout)
7527b5038d7SDag-Erling Smørgrav {
7537b5038d7SDag-Erling Smørgrav uint8_t *wire;
7547b5038d7SDag-Erling Smørgrav uint16_t wire_size;
7557b5038d7SDag-Erling Smørgrav ssize_t bytes = 0, rc = 0;
7567b5038d7SDag-Erling Smørgrav
7577b5038d7SDag-Erling Smørgrav wire = LDNS_XMALLOC(uint8_t, 2);
7587b5038d7SDag-Erling Smørgrav if (!wire) {
7597b5038d7SDag-Erling Smørgrav *size = 0;
7607b5038d7SDag-Erling Smørgrav return NULL;
7617b5038d7SDag-Erling Smørgrav }
7627b5038d7SDag-Erling Smørgrav
7637b5038d7SDag-Erling Smørgrav while (bytes < 2) {
7647b5038d7SDag-Erling Smørgrav if(!ldns_sock_wait(sockfd, timeout, 0)) {
7657b5038d7SDag-Erling Smørgrav *size = 0;
7667b5038d7SDag-Erling Smørgrav LDNS_FREE(wire);
7677b5038d7SDag-Erling Smørgrav return NULL;
7687b5038d7SDag-Erling Smørgrav }
7697b5038d7SDag-Erling Smørgrav rc = recv(sockfd, (void*) (wire + bytes),
7707b5038d7SDag-Erling Smørgrav (size_t) (2 - bytes), 0);
7717b5038d7SDag-Erling Smørgrav if (rc == -1 || rc == 0) {
7727b5038d7SDag-Erling Smørgrav *size = 0;
7737b5038d7SDag-Erling Smørgrav LDNS_FREE(wire);
7747b5038d7SDag-Erling Smørgrav return NULL;
7757b5038d7SDag-Erling Smørgrav }
7767b5038d7SDag-Erling Smørgrav bytes += rc;
7777b5038d7SDag-Erling Smørgrav }
7787b5038d7SDag-Erling Smørgrav
7797b5038d7SDag-Erling Smørgrav wire_size = ldns_read_uint16(wire);
7807b5038d7SDag-Erling Smørgrav
7817b5038d7SDag-Erling Smørgrav LDNS_FREE(wire);
7827b5038d7SDag-Erling Smørgrav wire = LDNS_XMALLOC(uint8_t, wire_size);
7837b5038d7SDag-Erling Smørgrav if (!wire) {
7847b5038d7SDag-Erling Smørgrav *size = 0;
7857b5038d7SDag-Erling Smørgrav return NULL;
7867b5038d7SDag-Erling Smørgrav }
7877b5038d7SDag-Erling Smørgrav bytes = 0;
7887b5038d7SDag-Erling Smørgrav
7897b5038d7SDag-Erling Smørgrav while (bytes < (ssize_t) wire_size) {
7907b5038d7SDag-Erling Smørgrav if(!ldns_sock_wait(sockfd, timeout, 0)) {
7917b5038d7SDag-Erling Smørgrav *size = 0;
7927b5038d7SDag-Erling Smørgrav LDNS_FREE(wire);
7937b5038d7SDag-Erling Smørgrav return NULL;
7947b5038d7SDag-Erling Smørgrav }
7957b5038d7SDag-Erling Smørgrav rc = recv(sockfd, (void*) (wire + bytes),
7967b5038d7SDag-Erling Smørgrav (size_t) (wire_size - bytes), 0);
7977b5038d7SDag-Erling Smørgrav if (rc == -1 || rc == 0) {
7987b5038d7SDag-Erling Smørgrav LDNS_FREE(wire);
7997b5038d7SDag-Erling Smørgrav *size = 0;
8007b5038d7SDag-Erling Smørgrav return NULL;
8017b5038d7SDag-Erling Smørgrav }
8027b5038d7SDag-Erling Smørgrav bytes += rc;
8037b5038d7SDag-Erling Smørgrav }
8047b5038d7SDag-Erling Smørgrav
8057b5038d7SDag-Erling Smørgrav *size = (size_t) bytes;
8067b5038d7SDag-Erling Smørgrav return wire;
8077b5038d7SDag-Erling Smørgrav }
8087b5038d7SDag-Erling Smørgrav
8097b5038d7SDag-Erling Smørgrav uint8_t *
8107b5038d7SDag-Erling Smørgrav ldns_tcp_read_wire(int sockfd, size_t *size)
8117b5038d7SDag-Erling Smørgrav {
8127b5038d7SDag-Erling Smørgrav uint8_t *wire;
8137b5038d7SDag-Erling Smørgrav uint16_t wire_size;
8147b5038d7SDag-Erling Smørgrav ssize_t bytes = 0, rc = 0;
8157b5038d7SDag-Erling Smørgrav
8167b5038d7SDag-Erling Smørgrav wire = LDNS_XMALLOC(uint8_t, 2);
8177b5038d7SDag-Erling Smørgrav if (!wire) {
8187b5038d7SDag-Erling Smørgrav *size = 0;
8197b5038d7SDag-Erling Smørgrav return NULL;
8207b5038d7SDag-Erling Smørgrav }
8217b5038d7SDag-Erling Smørgrav
8227b5038d7SDag-Erling Smørgrav while (bytes < 2) {
8237b5038d7SDag-Erling Smørgrav rc = recv(sockfd, (void*) (wire + bytes),
8247b5038d7SDag-Erling Smørgrav (size_t) (2 - bytes), 0);
8257b5038d7SDag-Erling Smørgrav if (rc == -1 || rc == 0) {
8267b5038d7SDag-Erling Smørgrav *size = 0;
8277b5038d7SDag-Erling Smørgrav LDNS_FREE(wire);
8287b5038d7SDag-Erling Smørgrav return NULL;
8297b5038d7SDag-Erling Smørgrav }
8307b5038d7SDag-Erling Smørgrav bytes += rc;
8317b5038d7SDag-Erling Smørgrav }
8327b5038d7SDag-Erling Smørgrav
8337b5038d7SDag-Erling Smørgrav wire_size = ldns_read_uint16(wire);
8347b5038d7SDag-Erling Smørgrav
8357b5038d7SDag-Erling Smørgrav LDNS_FREE(wire);
8367b5038d7SDag-Erling Smørgrav wire = LDNS_XMALLOC(uint8_t, wire_size);
8377b5038d7SDag-Erling Smørgrav if (!wire) {
8387b5038d7SDag-Erling Smørgrav *size = 0;
8397b5038d7SDag-Erling Smørgrav return NULL;
8407b5038d7SDag-Erling Smørgrav }
8417b5038d7SDag-Erling Smørgrav bytes = 0;
8427b5038d7SDag-Erling Smørgrav
8437b5038d7SDag-Erling Smørgrav while (bytes < (ssize_t) wire_size) {
8447b5038d7SDag-Erling Smørgrav rc = recv(sockfd, (void*) (wire + bytes),
8457b5038d7SDag-Erling Smørgrav (size_t) (wire_size - bytes), 0);
8467b5038d7SDag-Erling Smørgrav if (rc == -1 || rc == 0) {
8477b5038d7SDag-Erling Smørgrav LDNS_FREE(wire);
8487b5038d7SDag-Erling Smørgrav *size = 0;
8497b5038d7SDag-Erling Smørgrav return NULL;
8507b5038d7SDag-Erling Smørgrav }
8517b5038d7SDag-Erling Smørgrav bytes += rc;
8527b5038d7SDag-Erling Smørgrav }
8537b5038d7SDag-Erling Smørgrav
8547b5038d7SDag-Erling Smørgrav *size = (size_t) bytes;
8557b5038d7SDag-Erling Smørgrav return wire;
8567b5038d7SDag-Erling Smørgrav }
8577b5038d7SDag-Erling Smørgrav
8587b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
8597b5038d7SDag-Erling Smørgrav ldns_rdf *
860986ba33cSDag-Erling Smørgrav ldns_sockaddr_storage2rdf(const struct sockaddr_storage *sock, uint16_t *port)
8617b5038d7SDag-Erling Smørgrav {
8627b5038d7SDag-Erling Smørgrav ldns_rdf *addr;
8637b5038d7SDag-Erling Smørgrav struct sockaddr_in *data_in;
8647b5038d7SDag-Erling Smørgrav struct sockaddr_in6 *data_in6;
8657b5038d7SDag-Erling Smørgrav
8667b5038d7SDag-Erling Smørgrav switch(sock->ss_family) {
8677b5038d7SDag-Erling Smørgrav case AF_INET:
8687b5038d7SDag-Erling Smørgrav data_in = (struct sockaddr_in*)sock;
8697b5038d7SDag-Erling Smørgrav if (port) {
8707b5038d7SDag-Erling Smørgrav *port = ntohs((uint16_t)data_in->sin_port);
8717b5038d7SDag-Erling Smørgrav }
8727b5038d7SDag-Erling Smørgrav addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A,
8737b5038d7SDag-Erling Smørgrav LDNS_IP4ADDRLEN, &data_in->sin_addr);
8747b5038d7SDag-Erling Smørgrav break;
8757b5038d7SDag-Erling Smørgrav case AF_INET6:
8767b5038d7SDag-Erling Smørgrav data_in6 = (struct sockaddr_in6*)sock;
8777b5038d7SDag-Erling Smørgrav if (port) {
8787b5038d7SDag-Erling Smørgrav *port = ntohs((uint16_t)data_in6->sin6_port);
8797b5038d7SDag-Erling Smørgrav }
8807b5038d7SDag-Erling Smørgrav addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA,
8817b5038d7SDag-Erling Smørgrav LDNS_IP6ADDRLEN, &data_in6->sin6_addr);
8827b5038d7SDag-Erling Smørgrav break;
8837b5038d7SDag-Erling Smørgrav default:
8847b5038d7SDag-Erling Smørgrav if (port) {
8857b5038d7SDag-Erling Smørgrav *port = 0;
8867b5038d7SDag-Erling Smørgrav }
8877b5038d7SDag-Erling Smørgrav return NULL;
8887b5038d7SDag-Erling Smørgrav }
8897b5038d7SDag-Erling Smørgrav return addr;
8907b5038d7SDag-Erling Smørgrav }
8917b5038d7SDag-Erling Smørgrav #endif
8927b5038d7SDag-Erling Smørgrav
8937b5038d7SDag-Erling Smørgrav /* code from resolver.c */
8947b5038d7SDag-Erling Smørgrav ldns_status
895986ba33cSDag-Erling Smørgrav ldns_axfr_start(ldns_resolver *resolver, const ldns_rdf *domain, ldns_rr_class class)
8967b5038d7SDag-Erling Smørgrav {
8977b5038d7SDag-Erling Smørgrav ldns_pkt *query;
8987b5038d7SDag-Erling Smørgrav ldns_buffer *query_wire;
8997b5038d7SDag-Erling Smørgrav
90017d15b25SDag-Erling Smørgrav struct sockaddr_storage *src = NULL;
90117d15b25SDag-Erling Smørgrav size_t src_len = 0;
9027b5038d7SDag-Erling Smørgrav struct sockaddr_storage *ns = NULL;
9037b5038d7SDag-Erling Smørgrav size_t ns_len = 0;
9047b5038d7SDag-Erling Smørgrav size_t ns_i;
9057b5038d7SDag-Erling Smørgrav ldns_status status;
9067b5038d7SDag-Erling Smørgrav
9077b5038d7SDag-Erling Smørgrav if (!resolver || ldns_resolver_nameserver_count(resolver) < 1) {
9087b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR;
9097b5038d7SDag-Erling Smørgrav }
9107b5038d7SDag-Erling Smørgrav
9117b5038d7SDag-Erling Smørgrav query = ldns_pkt_query_new(ldns_rdf_clone(domain), LDNS_RR_TYPE_AXFR, class, 0);
9127b5038d7SDag-Erling Smørgrav
9137b5038d7SDag-Erling Smørgrav if (!query) {
9147b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ADDRESS_ERR;
9157b5038d7SDag-Erling Smørgrav }
91617d15b25SDag-Erling Smørgrav if(ldns_resolver_source(resolver)) {
91717d15b25SDag-Erling Smørgrav src = ldns_rdf2native_sockaddr_storage_port(
91817d15b25SDag-Erling Smørgrav ldns_resolver_source(resolver), 0, &src_len);
91917d15b25SDag-Erling Smørgrav }
9207b5038d7SDag-Erling Smørgrav /* For AXFR, we have to make the connection ourselves */
9217b5038d7SDag-Erling Smørgrav /* try all nameservers (which usually would mean v4 fallback if
9227b5038d7SDag-Erling Smørgrav * @hostname is used */
9237b5038d7SDag-Erling Smørgrav for (ns_i = 0;
9247b5038d7SDag-Erling Smørgrav ns_i < ldns_resolver_nameserver_count(resolver) &&
925986ba33cSDag-Erling Smørgrav resolver->_socket == SOCK_INVALID;
9267b5038d7SDag-Erling Smørgrav ns_i++) {
9272787e39aSDag-Erling Smørgrav if (ns != NULL) {
9282787e39aSDag-Erling Smørgrav LDNS_FREE(ns);
9292787e39aSDag-Erling Smørgrav }
9307b5038d7SDag-Erling Smørgrav ns = ldns_rdf2native_sockaddr_storage(
9317b5038d7SDag-Erling Smørgrav resolver->_nameservers[ns_i],
9327b5038d7SDag-Erling Smørgrav ldns_resolver_port(resolver), &ns_len);
933986ba33cSDag-Erling Smørgrav #ifndef S_SPLINT_S
934986ba33cSDag-Erling Smørgrav if ((ns->ss_family == AF_INET) &&
935986ba33cSDag-Erling Smørgrav (ldns_resolver_ip6(resolver) == LDNS_RESOLV_INET6)) {
936986ba33cSDag-Erling Smørgrav /* not reachable */
937986ba33cSDag-Erling Smørgrav LDNS_FREE(ns);
938986ba33cSDag-Erling Smørgrav ns = NULL;
939986ba33cSDag-Erling Smørgrav continue;
940986ba33cSDag-Erling Smørgrav }
941986ba33cSDag-Erling Smørgrav
942986ba33cSDag-Erling Smørgrav if ((ns->ss_family == AF_INET6) &&
943986ba33cSDag-Erling Smørgrav (ldns_resolver_ip6(resolver) == LDNS_RESOLV_INET)) {
944986ba33cSDag-Erling Smørgrav /* not reachable */
945986ba33cSDag-Erling Smørgrav LDNS_FREE(ns);
946986ba33cSDag-Erling Smørgrav ns = NULL;
947986ba33cSDag-Erling Smørgrav continue;
948986ba33cSDag-Erling Smørgrav }
949986ba33cSDag-Erling Smørgrav #endif
9507b5038d7SDag-Erling Smørgrav
95117d15b25SDag-Erling Smørgrav resolver->_socket = ldns_tcp_connect_from(
95217d15b25SDag-Erling Smørgrav ns, (socklen_t)ns_len,
95317d15b25SDag-Erling Smørgrav src, (socklen_t)src_len,
9547b5038d7SDag-Erling Smørgrav ldns_resolver_timeout(resolver));
9557b5038d7SDag-Erling Smørgrav }
956*5afab0e5SDag-Erling Smørgrav if (src) {
957*5afab0e5SDag-Erling Smørgrav LDNS_FREE(src);
958*5afab0e5SDag-Erling Smørgrav }
9597b5038d7SDag-Erling Smørgrav
960986ba33cSDag-Erling Smørgrav if (resolver->_socket == SOCK_INVALID) {
9617b5038d7SDag-Erling Smørgrav ldns_pkt_free(query);
9627b5038d7SDag-Erling Smørgrav LDNS_FREE(ns);
9637b5038d7SDag-Erling Smørgrav return LDNS_STATUS_NETWORK_ERR;
9647b5038d7SDag-Erling Smørgrav }
9657b5038d7SDag-Erling Smørgrav
9667b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
9677b5038d7SDag-Erling Smørgrav if (ldns_resolver_tsig_keyname(resolver) && ldns_resolver_tsig_keydata(resolver)) {
9687b5038d7SDag-Erling Smørgrav status = ldns_pkt_tsig_sign(query,
9697b5038d7SDag-Erling Smørgrav ldns_resolver_tsig_keyname(resolver),
9707b5038d7SDag-Erling Smørgrav ldns_resolver_tsig_keydata(resolver),
9717b5038d7SDag-Erling Smørgrav 300, ldns_resolver_tsig_algorithm(resolver), NULL);
9727b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) {
97317d15b25SDag-Erling Smørgrav /* to prevent problems on subsequent calls to
97417d15b25SDag-Erling Smørgrav * ldns_axfr_start we have to close the socket here! */
975986ba33cSDag-Erling Smørgrav close_socket(resolver->_socket);
9767b5038d7SDag-Erling Smørgrav resolver->_socket = 0;
9777b5038d7SDag-Erling Smørgrav
9782787e39aSDag-Erling Smørgrav ldns_pkt_free(query);
9792787e39aSDag-Erling Smørgrav LDNS_FREE(ns);
9802787e39aSDag-Erling Smørgrav
9817b5038d7SDag-Erling Smørgrav return LDNS_STATUS_CRYPTO_TSIG_ERR;
9827b5038d7SDag-Erling Smørgrav }
9837b5038d7SDag-Erling Smørgrav }
9847b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
9857b5038d7SDag-Erling Smørgrav
9867b5038d7SDag-Erling Smørgrav /* Convert the query to a buffer
9877b5038d7SDag-Erling Smørgrav * Is this necessary?
9887b5038d7SDag-Erling Smørgrav */
9897b5038d7SDag-Erling Smørgrav query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN);
9907b5038d7SDag-Erling Smørgrav if(!query_wire) {
9917b5038d7SDag-Erling Smørgrav ldns_pkt_free(query);
9927b5038d7SDag-Erling Smørgrav LDNS_FREE(ns);
993986ba33cSDag-Erling Smørgrav
994986ba33cSDag-Erling Smørgrav close_socket(resolver->_socket);
9957b5038d7SDag-Erling Smørgrav
9967b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
9977b5038d7SDag-Erling Smørgrav }
9987b5038d7SDag-Erling Smørgrav status = ldns_pkt2buffer_wire(query_wire, query);
9997b5038d7SDag-Erling Smørgrav if (status != LDNS_STATUS_OK) {
10007b5038d7SDag-Erling Smørgrav ldns_pkt_free(query);
10017b5038d7SDag-Erling Smørgrav ldns_buffer_free(query_wire);
10027b5038d7SDag-Erling Smørgrav LDNS_FREE(ns);
10037b5038d7SDag-Erling Smørgrav
100417d15b25SDag-Erling Smørgrav /* to prevent problems on subsequent calls to ldns_axfr_start
100517d15b25SDag-Erling Smørgrav * we have to close the socket here! */
1006986ba33cSDag-Erling Smørgrav close_socket(resolver->_socket);
10077b5038d7SDag-Erling Smørgrav resolver->_socket = 0;
10087b5038d7SDag-Erling Smørgrav
10097b5038d7SDag-Erling Smørgrav return status;
10107b5038d7SDag-Erling Smørgrav }
10117b5038d7SDag-Erling Smørgrav /* Send the query */
10127b5038d7SDag-Erling Smørgrav if (ldns_tcp_send_query(query_wire, resolver->_socket, ns,
10137b5038d7SDag-Erling Smørgrav (socklen_t)ns_len) == 0) {
10147b5038d7SDag-Erling Smørgrav ldns_pkt_free(query);
10157b5038d7SDag-Erling Smørgrav ldns_buffer_free(query_wire);
10167b5038d7SDag-Erling Smørgrav LDNS_FREE(ns);
10177b5038d7SDag-Erling Smørgrav
101817d15b25SDag-Erling Smørgrav /* to prevent problems on subsequent calls to ldns_axfr_start
101917d15b25SDag-Erling Smørgrav * we have to close the socket here! */
10207b5038d7SDag-Erling Smørgrav
1021986ba33cSDag-Erling Smørgrav
1022986ba33cSDag-Erling Smørgrav close_socket(resolver->_socket);
10237b5038d7SDag-Erling Smørgrav
10247b5038d7SDag-Erling Smørgrav return LDNS_STATUS_NETWORK_ERR;
10257b5038d7SDag-Erling Smørgrav }
10267b5038d7SDag-Erling Smørgrav
10277b5038d7SDag-Erling Smørgrav ldns_pkt_free(query);
10287b5038d7SDag-Erling Smørgrav ldns_buffer_free(query_wire);
10297b5038d7SDag-Erling Smørgrav LDNS_FREE(ns);
10307b5038d7SDag-Erling Smørgrav
10317b5038d7SDag-Erling Smørgrav /*
10327b5038d7SDag-Erling Smørgrav * The AXFR is done once the second SOA record is sent
10337b5038d7SDag-Erling Smørgrav */
10347b5038d7SDag-Erling Smørgrav resolver->_axfr_soa_count = 0;
10357b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK;
10367b5038d7SDag-Erling Smørgrav }
1037