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