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