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
34ldns_status
35ldns_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 */
60static struct sockaddr_storage *
61ldns_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
100struct sockaddr_storage *
101ldns_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 */
109static void
110ldns_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 */
129static void
130ldns_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 */
149static int
150ldns_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
172static int
173ldns_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
266int
267ldns_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
273static int
274ldns_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
299int
300ldns_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 */
311static ldns_status
312ldns_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
347ldns_status
348ldns_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
356int
357ldns_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
371static int
372ldns_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
400int
401ldns_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
408static ldns_status
409ldns_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
454ldns_status
455ldns_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
463ldns_status
464ldns_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
647ssize_t
648ldns_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 */
672ssize_t
673ldns_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
690uint8_t *
691ldns_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
720uint8_t *
721ldns_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
779uint8_t *
780ldns_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
829ldns_rdf *
830ldns_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 */
864ldns_status
865ldns_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