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 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
281int
282ldns_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
288static int
289ldns_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
310int
311ldns_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 */
322static ldns_status
323ldns_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
354ldns_status
355ldns_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
363int
364ldns_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
378static int
379ldns_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
403int
404ldns_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
411static ldns_status
412ldns_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
449ldns_status
450ldns_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
458ldns_status
459ldns_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
642ssize_t
643ldns_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 */
667ssize_t
668ldns_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
685uint8_t *
686ldns_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
715uint8_t *
716ldns_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
774uint8_t *
775ldns_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
824ldns_rdf *
825ldns_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 */
859ldns_status
860ldns_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