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
37ldns_status
38ldns_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 */
63static struct sockaddr_storage *
64ldns_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
103struct sockaddr_storage *
104ldns_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 */
112static void
113ldns_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 */
132static void
133ldns_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 */
152static int
153ldns_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
191static int
192ldns_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
282int
283ldns_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
290int
291ldns_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
297static int
298ldns_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
315int
316ldns_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
324int
325ldns_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 */
335static ldns_status
336ldns_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
362ldns_status
363ldns_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
371int
372ldns_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
386int
387ldns_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
401static int
402ldns_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
427int
428ldns_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
436int
437ldns_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
444static ldns_status
445ldns_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
482ldns_status
483ldns_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
491ldns_status
492ldns_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
680ssize_t
681ldns_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 */
705ssize_t
706ldns_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
720uint8_t *
721ldns_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
750uint8_t *
751ldns_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
809uint8_t *
810ldns_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
859ldns_rdf *
860ldns_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 */
894ldns_status
895ldns_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