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