xref: /freebsd/contrib/ldns/net.c (revision 17d15b251108ff09e632ed4812f7c66999a6b69b)
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