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