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