xref: /freebsd/contrib/ldns/net.c (revision b111430e54537a66080df115c3a2950a2922da5a)
1 /*
2  * net.c
3  *
4  * Network implementation
5  * All network related functions are grouped here
6  *
7  * a Net::DNS like library for C
8  *
9  * (c) NLnet Labs, 2004-2006
10  *
11  * See the file LICENSE for the license
12  */
13 
14 #include <ldns/config.h>
15 
16 #include <ldns/ldns.h>
17 
18 #ifdef HAVE_NETINET_IN_H
19 #include <netinet/in.h>
20 #endif
21 #ifdef HAVE_SYS_SOCKET_H
22 #include <sys/socket.h>
23 #endif
24 #ifdef HAVE_NETDB_H
25 #include <netdb.h>
26 #endif
27 #ifdef HAVE_ARPA_INET_H
28 #include <arpa/inet.h>
29 #endif
30 #include <sys/time.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #ifdef HAVE_POLL
34 #include <poll.h>
35 #endif
36 
37 ldns_status
38 ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt)
39 {
40 	ldns_buffer *qb;
41 	ldns_status result;
42 	ldns_rdf *tsig_mac = NULL;
43 
44 	qb = ldns_buffer_new(LDNS_MIN_BUFLEN);
45 
46 	if (query_pkt && ldns_pkt_tsig(query_pkt)) {
47 		tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3);
48 	}
49 
50 	if (!query_pkt ||
51 	    ldns_pkt2buffer_wire(qb, query_pkt) != LDNS_STATUS_OK) {
52 		result = LDNS_STATUS_ERR;
53 	} else {
54         	result = ldns_send_buffer(result_packet, r, qb, tsig_mac);
55 	}
56 
57 	ldns_buffer_free(qb);
58 
59 	return result;
60 }
61 
62 /* code from rdata.c */
63 static struct sockaddr_storage *
64 ldns_rdf2native_sockaddr_storage_port(
65 		const ldns_rdf *rd, uint16_t port, size_t *size)
66 {
67         struct sockaddr_storage *data;
68         struct sockaddr_in  *data_in;
69         struct sockaddr_in6 *data_in6;
70 
71         data = LDNS_MALLOC(struct sockaddr_storage);
72         if (!data) {
73                 return NULL;
74         }
75 	/* zero the structure for portability */
76 	memset(data, 0, sizeof(struct sockaddr_storage));
77 
78         switch(ldns_rdf_get_type(rd)) {
79                 case LDNS_RDF_TYPE_A:
80 #ifndef S_SPLINT_S
81                         data->ss_family = AF_INET;
82 #endif
83                         data_in = (struct sockaddr_in*) data;
84                         data_in->sin_port = (in_port_t)htons(port);
85                         memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd));
86                         *size = sizeof(struct sockaddr_in);
87                         return data;
88                 case LDNS_RDF_TYPE_AAAA:
89 #ifndef S_SPLINT_S
90                         data->ss_family = AF_INET6;
91 #endif
92                         data_in6 = (struct sockaddr_in6*) data;
93                         data_in6->sin6_port = (in_port_t)htons(port);
94                         memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd));
95                         *size = sizeof(struct sockaddr_in6);
96                         return data;
97                 default:
98                         LDNS_FREE(data);
99                         return NULL;
100         }
101 }
102 
103 struct sockaddr_storage *
104 ldns_rdf2native_sockaddr_storage(
105 		const ldns_rdf *rd, uint16_t port, size_t *size)
106 {
107 	return ldns_rdf2native_sockaddr_storage_port(
108 			rd, (port == 0 ? (uint16_t)LDNS_PORT : port), size);
109 }
110 
111 /** best effort to set nonblocking */
112 static void
113 ldns_sock_nonblock(int sockfd)
114 {
115 #ifdef HAVE_FCNTL
116 	int flag;
117 	if((flag = fcntl(sockfd, F_GETFL)) != -1) {
118 		flag |= O_NONBLOCK;
119 		if(fcntl(sockfd, F_SETFL, flag) == -1) {
120 			/* ignore error, continue blockingly */
121 		}
122 	}
123 #elif defined(HAVE_IOCTLSOCKET)
124 	unsigned long on = 1;
125 	if(ioctlsocket(sockfd, FIONBIO, &on) != 0) {
126 		/* ignore error, continue blockingly */
127 	}
128 #endif
129 }
130 
131 /** best effort to set blocking */
132 static void
133 ldns_sock_block(int sockfd)
134 {
135 #ifdef HAVE_FCNTL
136 	int flag;
137 	if((flag = fcntl(sockfd, F_GETFL)) != -1) {
138 		flag &= ~O_NONBLOCK;
139 		if(fcntl(sockfd, F_SETFL, flag) == -1) {
140 			/* ignore error, continue */
141 		}
142 	}
143 #elif defined(HAVE_IOCTLSOCKET)
144 	unsigned long off = 0;
145 	if(ioctlsocket(sockfd, FIONBIO, &off) != 0) {
146 		/* ignore error, continue */
147 	}
148 #endif
149 }
150 
151 /** wait for a socket to become ready */
152 static int
153 ldns_sock_wait(int sockfd, struct timeval timeout, int write)
154 {
155 	int ret;
156 #ifndef HAVE_POLL
157 #ifndef S_SPLINT_S
158 	fd_set fds;
159 	FD_ZERO(&fds);
160 	FD_SET(FD_SET_T sockfd, &fds);
161 	if(write)
162 		ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
163 	else
164 		ret = select(sockfd+1, &fds, NULL, NULL, &timeout);
165 #endif
166 #else
167 	struct pollfd pfds[2];
168 
169 	memset(&pfds[0], 0, sizeof(pfds[0]) * 2);
170 
171 	pfds[0].fd = sockfd;
172 	pfds[0].events = POLLIN|POLLERR;
173 
174 	if (write) {
175 		pfds[0].events |= POLLOUT;
176 	}
177 
178 	ret = poll(pfds, 1, (int)(timeout.tv_sec * 1000
179 				+ timeout.tv_usec / 1000));
180 #endif
181 	if(ret == 0)
182 		/* timeout expired */
183 		return 0;
184 	else if(ret == -1)
185 		/* error */
186 		return 0;
187 	return 1;
188 }
189 
190 
191 static int
192 ldns_tcp_connect_from(const struct sockaddr_storage *to, socklen_t tolen,
193 	       	const struct sockaddr_storage *from, socklen_t fromlen,
194 		struct timeval timeout)
195 {
196 	int sockfd;
197 
198 #ifndef S_SPLINT_S
199 	if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM,
200 					IPPROTO_TCP)) == SOCK_INVALID) {
201 		return 0;
202 	}
203 #endif
204 	if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == SOCK_INVALID){
205 		return 0;
206 	}
207 
208 	/* perform nonblocking connect, to be able to wait with select() */
209 	ldns_sock_nonblock(sockfd);
210 	if (connect(sockfd, (struct sockaddr*)to, tolen) == SOCK_INVALID) {
211 #ifndef USE_WINSOCK
212 #ifdef EINPROGRESS
213 		if(errno != EINPROGRESS) {
214 #else
215 		if(1) {
216 #endif
217 			close_socket(sockfd);
218 			return 0;
219 		}
220 #else /* USE_WINSOCK */
221 		if(WSAGetLastError() != WSAEINPROGRESS &&
222 			WSAGetLastError() != WSAEWOULDBLOCK) {
223 			close_socket(sockfd);
224 			return 0;
225 		}
226 #endif
227 		/* error was only telling us that it would block */
228 	}
229 
230 	/* wait(write) until connected or error */
231 	while(1) {
232 		int error = 0;
233 		socklen_t len = (socklen_t)sizeof(error);
234 
235 		if(!ldns_sock_wait(sockfd, timeout, 1)) {
236 			close_socket(sockfd);
237 			return 0;
238 		}
239 
240 		/* check if there is a pending error for nonblocking connect */
241 		if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error,
242 			&len) < 0) {
243 #ifndef USE_WINSOCK
244 			error = errno; /* on solaris errno is error */
245 #else
246 			error = WSAGetLastError();
247 #endif
248 		}
249 #ifndef USE_WINSOCK
250 #if defined(EINPROGRESS) && defined(EWOULDBLOCK)
251 		if(error == EINPROGRESS || error == EWOULDBLOCK)
252 			continue; /* try again */
253 #endif
254 		else if(error != 0) {
255 			close_socket(sockfd);
256 			/* error in errno for our user */
257 			errno = error;
258 			return 0;
259 		}
260 #else /* USE_WINSOCK */
261 		if(error == WSAEINPROGRESS)
262 			continue;
263 		else if(error == WSAEWOULDBLOCK)
264 			continue;
265 		else if(error != 0) {
266 			close_socket(sockfd);
267 			errno = error;
268 			return 0;
269 		}
270 #endif /* USE_WINSOCK */
271 		/* connected */
272 		break;
273 	}
274 
275 	/* set the socket blocking again */
276 	ldns_sock_block(sockfd);
277 
278 	return sockfd;
279 }
280 
281 int
282 ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen,
283 		struct timeval timeout)
284 {
285 	return ldns_tcp_connect_from(to, tolen, NULL, 0, timeout);
286 }
287 
288 static int
289 ldns_tcp_bgsend_from(ldns_buffer *qbin,
290 		const struct sockaddr_storage *to, socklen_t tolen,
291 	       	const struct sockaddr_storage *from, socklen_t fromlen,
292 		struct timeval timeout)
293 {
294 	int sockfd;
295 
296 	sockfd = ldns_tcp_connect_from(to, tolen, from, fromlen, timeout);
297 
298 	if (sockfd == 0) {
299 		return 0;
300 	}
301 
302 	if (ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) {
303 		close_socket(sockfd);
304 		return 0;
305 	}
306 
307 	return sockfd;
308 }
309 
310 int
311 ldns_tcp_bgsend(ldns_buffer *qbin,
312 		const struct sockaddr_storage *to, socklen_t tolen,
313 		struct timeval timeout)
314 {
315 	return ldns_tcp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
316 }
317 
318 
319 /* keep in mind that in DNS tcp messages the first 2 bytes signal the
320  * amount data to expect
321  */
322 static ldns_status
323 ldns_tcp_send_from(uint8_t **result,  ldns_buffer *qbin,
324 	       	const struct sockaddr_storage *to, socklen_t tolen,
325 	       	const struct sockaddr_storage *from, socklen_t fromlen,
326 		struct timeval timeout, size_t *answer_size)
327 {
328 	int sockfd;
329 	uint8_t *answer;
330 
331 	sockfd = ldns_tcp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
332 
333 	if (sockfd == 0) {
334 		return LDNS_STATUS_ERR;
335 	}
336 
337 	answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout);
338 	close_socket(sockfd);
339 
340 	if (*answer_size == 0) {
341 		/* oops */
342 		return LDNS_STATUS_NETWORK_ERR;
343 	}
344 
345 	/* resize accordingly */
346 	*result = LDNS_XREALLOC(answer, uint8_t, (size_t)*answer_size);
347         if(!*result) {
348                 LDNS_FREE(answer);
349                 return LDNS_STATUS_MEM_ERR;
350         }
351 	return LDNS_STATUS_OK;
352 }
353 
354 ldns_status
355 ldns_tcp_send(uint8_t **result,  ldns_buffer *qbin,
356 		const struct sockaddr_storage *to, socklen_t tolen,
357 		struct timeval timeout, size_t *answer_size)
358 {
359 	return ldns_tcp_send_from(result, qbin,
360 			to, tolen, NULL, 0, timeout, answer_size);
361 }
362 
363 int
364 ldns_udp_connect(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout))
365 {
366 	int sockfd;
367 
368 #ifndef S_SPLINT_S
369 	if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM,
370 					IPPROTO_UDP))
371 			== -1) {
372                 return 0;
373         }
374 #endif
375 	return sockfd;
376 }
377 
378 static int
379 ldns_udp_bgsend_from(ldns_buffer *qbin,
380 		const struct sockaddr_storage *to  , socklen_t tolen,
381 		const struct sockaddr_storage *from, socklen_t fromlen,
382 		struct timeval timeout)
383 {
384 	int sockfd;
385 
386 	sockfd = ldns_udp_connect(to, timeout);
387 
388 	if (sockfd == 0) {
389 		return 0;
390 	}
391 
392 	if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){
393 		return 0;
394 	}
395 
396 	if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) {
397 		close_socket(sockfd);
398 		return 0;
399 	}
400 	return sockfd;
401 }
402 
403 int
404 ldns_udp_bgsend(ldns_buffer *qbin,
405 		const struct sockaddr_storage *to  , socklen_t tolen,
406 		struct timeval timeout)
407 {
408 	return ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
409 }
410 
411 static ldns_status
412 ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
413 		const struct sockaddr_storage *to  , socklen_t tolen,
414 		const struct sockaddr_storage *from, socklen_t fromlen,
415 		struct timeval timeout, size_t *answer_size)
416 {
417 	int sockfd;
418 	uint8_t *answer;
419 
420 	sockfd = ldns_udp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
421 
422 	if (sockfd == 0) {
423 		return LDNS_STATUS_SOCKET_ERROR;
424 	}
425 
426 	/* wait for an response*/
427 	if(!ldns_sock_wait(sockfd, timeout, 0)) {
428 		close_socket(sockfd);
429 		return LDNS_STATUS_NETWORK_ERR;
430 	}
431 
432         /* set to nonblocking, so if the checksum is bad, it becomes
433          * an EGAIN error and the ldns_udp_send function does not block,
434          * but returns a 'NETWORK_ERROR' much like a timeout. */
435         ldns_sock_nonblock(sockfd);
436 
437 	answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
438 	close_socket(sockfd);
439 
440 	if (*answer_size == 0) {
441 		/* oops */
442 		return LDNS_STATUS_NETWORK_ERR;
443 	}
444 
445 	*result = answer;
446 	return LDNS_STATUS_OK;
447 }
448 
449 ldns_status
450 ldns_udp_send(uint8_t **result, ldns_buffer *qbin,
451 		const struct sockaddr_storage *to  , socklen_t tolen,
452 		struct timeval timeout, size_t *answer_size)
453 {
454 	return ldns_udp_send_from(result, qbin, to, tolen, NULL, 0,
455 			timeout, answer_size);
456 }
457 
458 ldns_status
459 ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac)
460 {
461 	uint8_t i;
462 
463 	struct sockaddr_storage *src = NULL;
464 	size_t src_len;
465 	struct sockaddr_storage *ns;
466 	size_t ns_len;
467 	struct timeval tv_s;
468 	struct timeval tv_e;
469 
470 	ldns_rdf **ns_array;
471 	size_t *rtt;
472 	ldns_pkt *reply;
473 	bool all_servers_rtt_inf;
474 	uint8_t retries;
475 
476 	uint8_t *reply_bytes = NULL;
477 	size_t reply_size = 0;
478 	ldns_status status, send_status;
479 
480 	assert(r != NULL);
481 
482 	status = LDNS_STATUS_OK;
483 	rtt = ldns_resolver_rtt(r);
484 	ns_array = ldns_resolver_nameservers(r);
485 	reply = NULL;
486 	ns_len = 0;
487 
488 	all_servers_rtt_inf = true;
489 
490 	if (ldns_resolver_random(r)) {
491 		ldns_resolver_nameservers_randomize(r);
492 	}
493 
494 	if(ldns_resolver_source(r)) {
495 		src = ldns_rdf2native_sockaddr_storage_port(
496 				ldns_resolver_source(r), 0, &src_len);
497 	}
498 
499 	/* loop through all defined nameservers */
500 	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
501 		if (rtt[i] == LDNS_RESOLV_RTT_INF) {
502 			/* not reachable nameserver! */
503 			continue;
504 		}
505 
506 		/* maybe verbosity setting?
507 		printf("Sending to ");
508 		ldns_rdf_print(stdout, ns_array[i]);
509 		printf("\n");
510 		*/
511 		ns = ldns_rdf2native_sockaddr_storage(ns_array[i],
512 				ldns_resolver_port(r), &ns_len);
513 
514 
515 #ifndef S_SPLINT_S
516 		if ((ns->ss_family == AF_INET) &&
517 				(ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) {
518 			/* not reachable */
519 			LDNS_FREE(ns);
520 			continue;
521 		}
522 
523 		if ((ns->ss_family == AF_INET6) &&
524 				 (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) {
525 			/* not reachable */
526 			LDNS_FREE(ns);
527 			continue;
528 		}
529 #endif
530 
531 		all_servers_rtt_inf = false;
532 
533 		gettimeofday(&tv_s, NULL);
534 
535 		send_status = LDNS_STATUS_ERR;
536 
537 		/* reply_bytes implicitly handles our error */
538 		if (ldns_resolver_usevc(r)) {
539 			for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
540 				send_status =
541 					ldns_tcp_send_from(&reply_bytes, qb,
542 						ns, (socklen_t)ns_len,
543 						src, (socklen_t)src_len,
544 						ldns_resolver_timeout(r),
545 						&reply_size);
546 				if (send_status == LDNS_STATUS_OK) {
547 					break;
548 				}
549 			}
550 		} else {
551 			for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
552 				/* ldns_rdf_print(stdout, ns_array[i]); */
553 				send_status =
554 					ldns_udp_send_from(&reply_bytes, qb,
555 						ns,  (socklen_t)ns_len,
556 						src, (socklen_t)src_len,
557 						ldns_resolver_timeout(r),
558 						&reply_size);
559 				if (send_status == LDNS_STATUS_OK) {
560 					break;
561 				}
562 			}
563 		}
564 
565 		if (send_status != LDNS_STATUS_OK) {
566 			ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF);
567 			status = send_status;
568 		}
569 
570 		/* obey the fail directive */
571 		if (!reply_bytes) {
572 			/* the current nameserver seems to have a problem, blacklist it */
573 			if (ldns_resolver_fail(r)) {
574 				LDNS_FREE(ns);
575 				return LDNS_STATUS_ERR;
576 			} else {
577 				LDNS_FREE(ns);
578 				continue;
579 			}
580 		}
581 
582 		status = ldns_wire2pkt(&reply, reply_bytes, reply_size);
583 		if (status != LDNS_STATUS_OK) {
584 			LDNS_FREE(reply_bytes);
585 			LDNS_FREE(ns);
586 			return status;
587 		}
588 
589 		LDNS_FREE(ns);
590 		gettimeofday(&tv_e, NULL);
591 
592 		if (reply) {
593 			ldns_pkt_set_querytime(reply, (uint32_t)
594 				((tv_e.tv_sec - tv_s.tv_sec) * 1000) +
595 				(tv_e.tv_usec - tv_s.tv_usec) / 1000);
596 			ldns_pkt_set_answerfrom(reply,
597 					ldns_rdf_clone(ns_array[i]));
598 			ldns_pkt_set_timestamp(reply, tv_s);
599 			ldns_pkt_set_size(reply, reply_size);
600 			break;
601 		} else {
602 			if (ldns_resolver_fail(r)) {
603 				/* if fail is set bail out, after the first
604 				 * one */
605 				break;
606 			}
607 		}
608 
609 		/* wait retrans seconds... */
610 		sleep((unsigned int) ldns_resolver_retrans(r));
611 	}
612 
613 	if(src) {
614 		LDNS_FREE(src);
615 	}
616 	if (all_servers_rtt_inf) {
617 		LDNS_FREE(reply_bytes);
618 		return LDNS_STATUS_RES_NO_NS;
619 	}
620 #ifdef HAVE_SSL
621 	if (tsig_mac && reply && reply_bytes) {
622 		if (!ldns_pkt_tsig_verify(reply,
623 		                          reply_bytes,
624 					  reply_size,
625 		                          ldns_resolver_tsig_keyname(r),
626 		                          ldns_resolver_tsig_keydata(r), tsig_mac)) {
627 			status = LDNS_STATUS_CRYPTO_TSIG_BOGUS;
628 		}
629 	}
630 #else
631 	(void)tsig_mac;
632 #endif /* HAVE_SSL */
633 
634 	LDNS_FREE(reply_bytes);
635 	if (result) {
636 		*result = reply;
637 	}
638 
639 	return status;
640 }
641 
642 ssize_t
643 ldns_tcp_send_query(ldns_buffer *qbin, int sockfd,
644                     const struct sockaddr_storage *to, socklen_t tolen)
645 {
646 	uint8_t *sendbuf;
647 	ssize_t bytes;
648 
649 	/* add length of packet */
650 	sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2);
651 	if(!sendbuf) return 0;
652 	ldns_write_uint16(sendbuf, ldns_buffer_position(qbin));
653 	memcpy(sendbuf + 2, ldns_buffer_begin(qbin), ldns_buffer_position(qbin));
654 
655 	bytes = sendto(sockfd, (void*)sendbuf,
656 			ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen);
657 
658         LDNS_FREE(sendbuf);
659 
660 	if (bytes == -1 || (size_t) bytes != ldns_buffer_position(qbin) + 2 ) {
661 		return 0;
662 	}
663 	return bytes;
664 }
665 
666 /* don't wait for an answer */
667 ssize_t
668 ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to,
669 		socklen_t tolen)
670 {
671 	ssize_t bytes;
672 
673 	bytes = sendto(sockfd, (void*)ldns_buffer_begin(qbin),
674 			ldns_buffer_position(qbin), 0, (struct sockaddr *)to, tolen);
675 
676 	if (bytes == -1 || (size_t)bytes != ldns_buffer_position(qbin)) {
677 		return 0;
678 	}
679 	if ((size_t) bytes != ldns_buffer_position(qbin)) {
680 		return 0;
681 	}
682 	return bytes;
683 }
684 
685 uint8_t *
686 ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from,
687 		socklen_t *fromlen)
688 {
689 	uint8_t *wire, *wireout;
690 	ssize_t wire_size;
691 
692 	wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
693 	if (!wire) {
694 		*size = 0;
695 		return NULL;
696 	}
697 
698 	wire_size = recvfrom(sockfd, (void*)wire, LDNS_MAX_PACKETLEN, 0,
699 			(struct sockaddr *)from, fromlen);
700 
701 	/* recvfrom can also return 0 */
702 	if (wire_size == -1 || wire_size == 0) {
703 		*size = 0;
704 		LDNS_FREE(wire);
705 		return NULL;
706 	}
707 
708 	*size = (size_t)wire_size;
709 	wireout = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size);
710 	if(!wireout) LDNS_FREE(wire);
711 
712 	return wireout;
713 }
714 
715 uint8_t *
716 ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout)
717 {
718 	uint8_t *wire;
719 	uint16_t wire_size;
720 	ssize_t bytes = 0, rc = 0;
721 
722 	wire = LDNS_XMALLOC(uint8_t, 2);
723 	if (!wire) {
724 		*size = 0;
725 		return NULL;
726 	}
727 
728 	while (bytes < 2) {
729 		if(!ldns_sock_wait(sockfd, timeout, 0)) {
730 			*size = 0;
731 			LDNS_FREE(wire);
732 			return NULL;
733 		}
734 		rc = recv(sockfd, (void*) (wire + bytes),
735 				(size_t) (2 - bytes), 0);
736 		if (rc == -1 || rc == 0) {
737 			*size = 0;
738 			LDNS_FREE(wire);
739 			return NULL;
740 		}
741                 bytes += rc;
742 	}
743 
744 	wire_size = ldns_read_uint16(wire);
745 
746 	LDNS_FREE(wire);
747 	wire = LDNS_XMALLOC(uint8_t, wire_size);
748 	if (!wire) {
749 		*size = 0;
750 		return NULL;
751 	}
752 	bytes = 0;
753 
754 	while (bytes < (ssize_t) wire_size) {
755 		if(!ldns_sock_wait(sockfd, timeout, 0)) {
756 			*size = 0;
757 			LDNS_FREE(wire);
758 			return NULL;
759 		}
760 		rc = recv(sockfd, (void*) (wire + bytes),
761 				(size_t) (wire_size - bytes), 0);
762 		if (rc == -1 || rc == 0) {
763 			LDNS_FREE(wire);
764 			*size = 0;
765 			return NULL;
766 		}
767                 bytes += rc;
768 	}
769 
770 	*size = (size_t) bytes;
771 	return wire;
772 }
773 
774 uint8_t *
775 ldns_tcp_read_wire(int sockfd, size_t *size)
776 {
777 	uint8_t *wire;
778 	uint16_t wire_size;
779 	ssize_t bytes = 0, rc = 0;
780 
781 	wire = LDNS_XMALLOC(uint8_t, 2);
782 	if (!wire) {
783 		*size = 0;
784 		return NULL;
785 	}
786 
787 	while (bytes < 2) {
788 		rc = recv(sockfd, (void*) (wire + bytes),
789 				(size_t) (2 - bytes), 0);
790 		if (rc == -1 || rc == 0) {
791 			*size = 0;
792 			LDNS_FREE(wire);
793 			return NULL;
794 		}
795                 bytes += rc;
796 	}
797 
798 	wire_size = ldns_read_uint16(wire);
799 
800 	LDNS_FREE(wire);
801 	wire = LDNS_XMALLOC(uint8_t, wire_size);
802 	if (!wire) {
803 		*size = 0;
804 		return NULL;
805 	}
806 	bytes = 0;
807 
808 	while (bytes < (ssize_t) wire_size) {
809 		rc = recv(sockfd, (void*) (wire + bytes),
810 				(size_t) (wire_size - bytes), 0);
811 		if (rc == -1 || rc == 0) {
812 			LDNS_FREE(wire);
813 			*size = 0;
814 			return NULL;
815 		}
816                 bytes += rc;
817 	}
818 
819 	*size = (size_t) bytes;
820 	return wire;
821 }
822 
823 #ifndef S_SPLINT_S
824 ldns_rdf *
825 ldns_sockaddr_storage2rdf(const struct sockaddr_storage *sock, uint16_t *port)
826 {
827         ldns_rdf *addr;
828         struct sockaddr_in *data_in;
829         struct sockaddr_in6 *data_in6;
830 
831         switch(sock->ss_family) {
832                 case AF_INET:
833                         data_in = (struct sockaddr_in*)sock;
834                         if (port) {
835                                 *port = ntohs((uint16_t)data_in->sin_port);
836                         }
837                         addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A,
838                                         LDNS_IP4ADDRLEN, &data_in->sin_addr);
839                         break;
840                 case AF_INET6:
841                         data_in6 = (struct sockaddr_in6*)sock;
842                         if (port) {
843                                 *port = ntohs((uint16_t)data_in6->sin6_port);
844                         }
845                         addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA,
846                                         LDNS_IP6ADDRLEN, &data_in6->sin6_addr);
847                         break;
848                 default:
849                         if (port) {
850                                 *port = 0;
851                         }
852                         return NULL;
853         }
854         return addr;
855 }
856 #endif
857 
858 /* code from resolver.c */
859 ldns_status
860 ldns_axfr_start(ldns_resolver *resolver, const ldns_rdf *domain, ldns_rr_class class)
861 {
862         ldns_pkt *query;
863         ldns_buffer *query_wire;
864 
865         struct sockaddr_storage *src = NULL;
866         size_t src_len = 0;
867         struct sockaddr_storage *ns = NULL;
868         size_t ns_len = 0;
869         size_t ns_i;
870         ldns_status status;
871 
872         if (!resolver || ldns_resolver_nameserver_count(resolver) < 1) {
873                 return LDNS_STATUS_ERR;
874         }
875 
876         query = ldns_pkt_query_new(ldns_rdf_clone(domain), LDNS_RR_TYPE_AXFR, class, 0);
877 
878         if (!query) {
879                 return LDNS_STATUS_ADDRESS_ERR;
880         }
881 	if(ldns_resolver_source(resolver)) {
882 		src = ldns_rdf2native_sockaddr_storage_port(
883 				ldns_resolver_source(resolver), 0, &src_len);
884 	}
885         /* For AXFR, we have to make the connection ourselves */
886         /* try all nameservers (which usually would mean v4 fallback if
887          * @hostname is used */
888         for (ns_i = 0;
889              ns_i < ldns_resolver_nameserver_count(resolver) &&
890              resolver->_socket == SOCK_INVALID;
891              ns_i++) {
892 		if (ns != NULL) {
893 			LDNS_FREE(ns);
894 		}
895 	        ns = ldns_rdf2native_sockaddr_storage(
896 	        	resolver->_nameservers[ns_i],
897 			ldns_resolver_port(resolver), &ns_len);
898 #ifndef S_SPLINT_S
899 		if ((ns->ss_family == AF_INET) &&
900 			(ldns_resolver_ip6(resolver) == LDNS_RESOLV_INET6)) {
901 			/* not reachable */
902 			LDNS_FREE(ns);
903 			ns = NULL;
904 			continue;
905 		}
906 
907 		if ((ns->ss_family == AF_INET6) &&
908 			 (ldns_resolver_ip6(resolver) == LDNS_RESOLV_INET)) {
909 			/* not reachable */
910 			LDNS_FREE(ns);
911 			ns = NULL;
912 			continue;
913 		}
914 #endif
915 
916 		resolver->_socket = ldns_tcp_connect_from(
917 				ns, (socklen_t)ns_len,
918 				src, (socklen_t)src_len,
919 				ldns_resolver_timeout(resolver));
920 	}
921 
922 	if (resolver->_socket == SOCK_INVALID) {
923 		ldns_pkt_free(query);
924 		LDNS_FREE(ns);
925 		return LDNS_STATUS_NETWORK_ERR;
926 	}
927 
928 #ifdef HAVE_SSL
929 	if (ldns_resolver_tsig_keyname(resolver) && ldns_resolver_tsig_keydata(resolver)) {
930 		status = ldns_pkt_tsig_sign(query,
931 		                            ldns_resolver_tsig_keyname(resolver),
932 		                            ldns_resolver_tsig_keydata(resolver),
933 		                            300, ldns_resolver_tsig_algorithm(resolver), NULL);
934 		if (status != LDNS_STATUS_OK) {
935 			/* to prevent problems on subsequent calls to
936 			 * ldns_axfr_start we have to close the socket here! */
937 			close_socket(resolver->_socket);
938 			resolver->_socket = 0;
939 
940 			ldns_pkt_free(query);
941 			LDNS_FREE(ns);
942 
943 			return LDNS_STATUS_CRYPTO_TSIG_ERR;
944 		}
945 	}
946 #endif /* HAVE_SSL */
947 
948         /* Convert the query to a buffer
949          * Is this necessary?
950          */
951         query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN);
952         if(!query_wire) {
953                 ldns_pkt_free(query);
954                 LDNS_FREE(ns);
955 
956 		close_socket(resolver->_socket);
957 
958                 return LDNS_STATUS_MEM_ERR;
959         }
960         status = ldns_pkt2buffer_wire(query_wire, query);
961         if (status != LDNS_STATUS_OK) {
962                 ldns_pkt_free(query);
963 		ldns_buffer_free(query_wire);
964                 LDNS_FREE(ns);
965 
966 		/* to prevent problems on subsequent calls to ldns_axfr_start
967 		 * we have to close the socket here! */
968 		close_socket(resolver->_socket);
969 		resolver->_socket = 0;
970 
971                 return status;
972         }
973         /* Send the query */
974         if (ldns_tcp_send_query(query_wire, resolver->_socket, ns,
975 				(socklen_t)ns_len) == 0) {
976                 ldns_pkt_free(query);
977                 ldns_buffer_free(query_wire);
978                 LDNS_FREE(ns);
979 
980 		/* to prevent problems on subsequent calls to ldns_axfr_start
981 		 * we have to close the socket here! */
982 
983 
984 		close_socket(resolver->_socket);
985 
986                 return LDNS_STATUS_NETWORK_ERR;
987         }
988 
989         ldns_pkt_free(query);
990         ldns_buffer_free(query_wire);
991         LDNS_FREE(ns);
992 
993         /*
994          * The AXFR is done once the second SOA record is sent
995          */
996         resolver->_axfr_soa_count = 0;
997         return LDNS_STATUS_OK;
998 }
999