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