ldns/drill: Update vendor branch to 1.6.9
[dragonfly.git] / contrib / ldns / net.c
CommitLineData
825eb42b
JL
1/*
2 * net.c
3 *
4 * Network implementation
5 * All network related functions are grouped here
6 *
7 * a Net::DNS like library for C
8 *
9 * (c) NLnet Labs, 2004-2006
10 *
11 * See the file LICENSE for the license
12 */
13
14#include <ldns/config.h>
15
16#include <ldns/ldns.h>
17
18#ifdef HAVE_NETINET_IN_H
19#include <netinet/in.h>
20#endif
21#ifdef HAVE_SYS_SOCKET_H
22#include <sys/socket.h>
23#endif
24#ifdef HAVE_NETDB_H
25#include <netdb.h>
26#endif
27#ifdef HAVE_ARPA_INET_H
28#include <arpa/inet.h>
29#endif
30#include <sys/time.h>
31#include <errno.h>
32#include <fcntl.h>
33
34ldns_status
35ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt)
36{
37 ldns_buffer *qb;
38 ldns_status result;
39 ldns_rdf *tsig_mac = NULL;
40
41 qb = ldns_buffer_new(LDNS_MIN_BUFLEN);
42
43 if (query_pkt && ldns_pkt_tsig(query_pkt)) {
44 tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3);
45 }
46
825eb42b
JL
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);
ac996e71 55
825eb42b
JL
56 return result;
57}
58
59ldns_status
60ldns_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 }
825eb42b
JL
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);
ac996e71
JL
107
108 if ((ns->ss_family == AF_INET) &&
825eb42b 109 (ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) {
ac996e71 110 /* not reachable */
825eb42b
JL
111 continue;
112 }
113
114 if ((ns->ss_family == AF_INET6) &&
115 (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) {
ac996e71 116 /* not reachable */
825eb42b
JL
117 continue;
118 }
119
ac996e71
JL
120 all_servers_rtt_inf = false;
121
825eb42b
JL
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 */
ac996e71 215
825eb42b
JL
216 LDNS_FREE(reply_bytes);
217 if (result) {
218 *result = reply;
219 }
220
221 return status;
222}
223
224/** best effort to set nonblocking */
225static void
226ldns_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 */
245static void
246ldns_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 */
265static int
266ldns_sock_wait(int sockfd, struct timeval timeout, int write)
267{
268 fd_set fds;
269 int ret;
fd185f4d 270#ifndef S_SPLINT_S
825eb42b
JL
271 FD_ZERO(&fds);
272 FD_SET(FD_SET_T sockfd, &fds);
fd185f4d 273#endif
825eb42b
JL
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
287ldns_status
ac996e71 288ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to,
825eb42b
JL
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)) {
ac996e71 302#ifndef USE_WINSOCK
825eb42b 303 close(sockfd);
ac996e71
JL
304#else
305 closesocket(sockfd);
306#endif
825eb42b
JL
307 return LDNS_STATUS_NETWORK_ERR;
308 }
ac996e71 309
fd185f4d
JL
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
825eb42b 315 answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
ac996e71 316#ifndef USE_WINSOCK
825eb42b 317 close(sockfd);
ac996e71
JL
318#else
319 closesocket(sockfd);
320#endif
825eb42b
JL
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
331int
332ldns_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 return 0;
345 }
346 return sockfd;
347}
348
349int
350ldns_udp_connect(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout))
351{
352 int sockfd;
ac996e71 353
825eb42b
JL
354 if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM,
355 IPPROTO_UDP))
356 == -1) {
357 return 0;
358 }
359 return sockfd;
360}
361
362int
363ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen,
364 struct timeval timeout)
365{
366 int sockfd;
ac996e71 367
825eb42b
JL
368 if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM,
369 IPPROTO_TCP)) == -1) {
370 return 0;
371 }
372
373 /* perform nonblocking connect, to be able to wait with select() */
374 ldns_sock_nonblock(sockfd);
375 if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) {
376#ifndef USE_WINSOCK
377#ifdef EINPROGRESS
378 if(errno != EINPROGRESS) {
379#else
380 if(1) {
381#endif
382 close(sockfd);
383 return 0;
384 }
385#else /* USE_WINSOCK */
386 if(WSAGetLastError() != WSAEINPROGRESS &&
387 WSAGetLastError() != WSAEWOULDBLOCK) {
388 closesocket(sockfd);
389 return 0;
390 }
391#endif
392 /* error was only telling us that it would block */
393 }
394
395 /* wait(write) until connected or error */
396 while(1) {
397 int error = 0;
398 socklen_t len = (socklen_t)sizeof(error);
399
400 if(!ldns_sock_wait(sockfd, timeout, 1)) {
ac996e71 401#ifndef USE_WINSOCK
825eb42b 402 close(sockfd);
ac996e71
JL
403#else
404 closesocket(sockfd);
405#endif
825eb42b
JL
406 return 0;
407 }
408
409 /* check if there is a pending error for nonblocking connect */
410 if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error,
411 &len) < 0) {
412#ifndef USE_WINSOCK
413 error = errno; /* on solaris errno is error */
414#else
415 error = WSAGetLastError();
416#endif
417 }
418#ifndef USE_WINSOCK
419#if defined(EINPROGRESS) && defined(EWOULDBLOCK)
420 if(error == EINPROGRESS || error == EWOULDBLOCK)
421 continue; /* try again */
422#endif
423 else if(error != 0) {
424 close(sockfd);
425 /* error in errno for our user */
426 errno = error;
427 return 0;
428 }
429#else /* USE_WINSOCK */
430 if(error == WSAEINPROGRESS)
431 continue;
432 else if(error == WSAEWOULDBLOCK)
433 continue;
434 else if(error != 0) {
435 closesocket(sockfd);
436 errno = error;
437 return 0;
438 }
439#endif /* USE_WINSOCK */
440 /* connected */
441 break;
442 }
443
444 /* set the socket blocking again */
445 ldns_sock_block(sockfd);
446
447 return sockfd;
448}
449
450ssize_t
451ldns_tcp_send_query(ldns_buffer *qbin, int sockfd,
452 const struct sockaddr_storage *to, socklen_t tolen)
453{
454 uint8_t *sendbuf;
455 ssize_t bytes;
456
457 /* add length of packet */
458 sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2);
ac996e71 459 if(!sendbuf) return 0;
825eb42b
JL
460 ldns_write_uint16(sendbuf, ldns_buffer_position(qbin));
461 memcpy(sendbuf + 2, ldns_buffer_export(qbin), ldns_buffer_position(qbin));
462
463 bytes = sendto(sockfd, (void*)sendbuf,
464 ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen);
465
466 LDNS_FREE(sendbuf);
467
468 if (bytes == -1 || (size_t) bytes != ldns_buffer_position(qbin) + 2 ) {
469 return 0;
470 }
471 return bytes;
472}
473
474/* don't wait for an answer */
475ssize_t
476ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to,
477 socklen_t tolen)
478{
479 ssize_t bytes;
480
481 bytes = sendto(sockfd, (void*)ldns_buffer_begin(qbin),
482 ldns_buffer_position(qbin), 0, (struct sockaddr *)to, tolen);
483
484 if (bytes == -1 || (size_t)bytes != ldns_buffer_position(qbin)) {
485 return 0;
486 }
487 if ((size_t) bytes != ldns_buffer_position(qbin)) {
488 return 0;
489 }
490 return bytes;
491}
492
493uint8_t *
494ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from,
495 socklen_t *fromlen)
496{
ac996e71 497 uint8_t *wire, *wireout;
825eb42b
JL
498 ssize_t wire_size;
499
500 wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
501 if (!wire) {
502 *size = 0;
503 return NULL;
504 }
505
506 wire_size = recvfrom(sockfd, (void*)wire, LDNS_MAX_PACKETLEN, 0,
507 (struct sockaddr *)from, fromlen);
508
509 /* recvfrom can also return 0 */
510 if (wire_size == -1 || wire_size == 0) {
511 *size = 0;
512 LDNS_FREE(wire);
513 return NULL;
514 }
515
516 *size = (size_t)wire_size;
ac996e71
JL
517 wireout = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size);
518 if(!wireout) LDNS_FREE(wire);
825eb42b 519
ac996e71 520 return wireout;
825eb42b
JL
521}
522
523uint8_t *
524ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout)
525{
526 uint8_t *wire;
527 uint16_t wire_size;
ac996e71 528 ssize_t bytes = 0, rc = 0;
825eb42b
JL
529
530 wire = LDNS_XMALLOC(uint8_t, 2);
531 if (!wire) {
532 *size = 0;
533 return NULL;
534 }
535
536 while (bytes < 2) {
537 if(!ldns_sock_wait(sockfd, timeout, 0)) {
538 *size = 0;
539 LDNS_FREE(wire);
540 return NULL;
541 }
ac996e71
JL
542 rc = recv(sockfd, (void*) (wire + bytes),
543 (size_t) (2 - bytes), 0);
544 if (rc == -1 || rc == 0) {
825eb42b
JL
545 *size = 0;
546 LDNS_FREE(wire);
547 return NULL;
548 }
ac996e71 549 bytes += rc;
825eb42b
JL
550 }
551
552 wire_size = ldns_read_uint16(wire);
553
554 LDNS_FREE(wire);
555 wire = LDNS_XMALLOC(uint8_t, wire_size);
fd185f4d
JL
556 if (!wire) {
557 *size = 0;
558 return NULL;
559 }
825eb42b
JL
560 bytes = 0;
561
562 while (bytes < (ssize_t) wire_size) {
563 if(!ldns_sock_wait(sockfd, timeout, 0)) {
564 *size = 0;
565 LDNS_FREE(wire);
566 return NULL;
567 }
ac996e71 568 rc = recv(sockfd, (void*) (wire + bytes),
825eb42b 569 (size_t) (wire_size - bytes), 0);
ac996e71 570 if (rc == -1 || rc == 0) {
825eb42b
JL
571 LDNS_FREE(wire);
572 *size = 0;
573 return NULL;
574 }
ac996e71 575 bytes += rc;
825eb42b
JL
576 }
577
578 *size = (size_t) bytes;
579 return wire;
580}
581
582uint8_t *
583ldns_tcp_read_wire(int sockfd, size_t *size)
584{
585 uint8_t *wire;
586 uint16_t wire_size;
ac996e71 587 ssize_t bytes = 0, rc = 0;
825eb42b
JL
588
589 wire = LDNS_XMALLOC(uint8_t, 2);
590 if (!wire) {
591 *size = 0;
592 return NULL;
593 }
594
595 while (bytes < 2) {
ac996e71
JL
596 rc = recv(sockfd, (void*) (wire + bytes),
597 (size_t) (2 - bytes), 0);
598 if (rc == -1 || rc == 0) {
825eb42b
JL
599 *size = 0;
600 LDNS_FREE(wire);
601 return NULL;
602 }
ac996e71 603 bytes += rc;
825eb42b
JL
604 }
605
606 wire_size = ldns_read_uint16(wire);
607
608 LDNS_FREE(wire);
609 wire = LDNS_XMALLOC(uint8_t, wire_size);
fd185f4d
JL
610 if (!wire) {
611 *size = 0;
612 return NULL;
613 }
825eb42b
JL
614 bytes = 0;
615
616 while (bytes < (ssize_t) wire_size) {
ac996e71 617 rc = recv(sockfd, (void*) (wire + bytes),
825eb42b 618 (size_t) (wire_size - bytes), 0);
ac996e71 619 if (rc == -1 || rc == 0) {
825eb42b
JL
620 LDNS_FREE(wire);
621 *size = 0;
622 return NULL;
623 }
ac996e71 624 bytes += rc;
825eb42b
JL
625 }
626
627 *size = (size_t) bytes;
628 return wire;
629}
630
631/* keep in mind that in DNS tcp messages the first 2 bytes signal the
632 * amount data to expect
633 */
634ldns_status
635ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to,
636 socklen_t tolen, struct timeval timeout, size_t *answer_size)
637{
638 int sockfd;
639 uint8_t *answer;
640
641 sockfd = ldns_tcp_bgsend(qbin, to, tolen, timeout);
642
643 if (sockfd == 0) {
644 return LDNS_STATUS_ERR;
645 }
646
647 answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout);
ac996e71 648#ifndef USE_WINSOCK
825eb42b 649 close(sockfd);
ac996e71
JL
650#else
651 closesocket(sockfd);
652#endif
825eb42b
JL
653
654 if (*answer_size == 0) {
655 /* oops */
656 return LDNS_STATUS_NETWORK_ERR;
657 }
658
659 /* resize accordingly */
fd185f4d
JL
660 *result = (uint8_t*)LDNS_XREALLOC(answer, uint8_t *, (size_t)*answer_size);
661 if(!*result) {
662 LDNS_FREE(answer);
663 return LDNS_STATUS_MEM_ERR;
664 }
825eb42b
JL
665 return LDNS_STATUS_OK;
666}
667
668int
669ldns_tcp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen,
670 struct timeval timeout)
671{
672 int sockfd;
673
674 sockfd = ldns_tcp_connect(to, tolen, timeout);
675
676 if (sockfd == 0) {
677 return 0;
678 }
679
680 if (ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) {
681 return 0;
682 }
683
684 return sockfd;
685}
686
687/* code from rdata.c */
688struct sockaddr_storage *
689ldns_rdf2native_sockaddr_storage(const ldns_rdf *rd, uint16_t port, size_t *size)
690{
691 struct sockaddr_storage *data;
692 struct sockaddr_in *data_in;
693 struct sockaddr_in6 *data_in6;
694
695 data = LDNS_MALLOC(struct sockaddr_storage);
696 if (!data) {
697 return NULL;
698 }
699 /* zero the structure for portability */
700 memset(data, 0, sizeof(struct sockaddr_storage));
701 if (port == 0) {
702 port = LDNS_PORT;
703 }
704
705 switch(ldns_rdf_get_type(rd)) {
706 case LDNS_RDF_TYPE_A:
707 data->ss_family = AF_INET;
708 data_in = (struct sockaddr_in*) data;
709 data_in->sin_port = (in_port_t)htons(port);
710 memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd));
711 *size = sizeof(struct sockaddr_in);
712 return data;
713 case LDNS_RDF_TYPE_AAAA:
714 data->ss_family = AF_INET6;
715 data_in6 = (struct sockaddr_in6*) data;
716 data_in6->sin6_port = (in_port_t)htons(port);
717 memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd));
718 *size = sizeof(struct sockaddr_in6);
719 return data;
720 default:
721 LDNS_FREE(data);
722 return NULL;
723 }
724}
725
726ldns_rdf *
727ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port)
728{
729 ldns_rdf *addr;
730 struct sockaddr_in *data_in;
731 struct sockaddr_in6 *data_in6;
732
733 switch(sock->ss_family) {
734 case AF_INET:
735 data_in = (struct sockaddr_in*)sock;
736 if (port) {
737 *port = ntohs((uint16_t)data_in->sin_port);
738 }
739 addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A,
740 LDNS_IP4ADDRLEN, &data_in->sin_addr);
741 break;
742 case AF_INET6:
743 data_in6 = (struct sockaddr_in6*)sock;
744 if (port) {
745 *port = ntohs((uint16_t)data_in6->sin6_port);
746 }
747 addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA,
748 LDNS_IP6ADDRLEN, &data_in6->sin6_addr);
749 break;
750 default:
751 if (port) {
752 *port = 0;
753 }
754 return NULL;
755 }
756 return addr;
757}
758
759/* code from resolver.c */
760ldns_status
761ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class)
762{
763 ldns_pkt *query;
764 ldns_buffer *query_wire;
765
766 struct sockaddr_storage *ns = NULL;
767 size_t ns_len = 0;
768 size_t ns_i;
769 ldns_status status;
770
771 if (!resolver || ldns_resolver_nameserver_count(resolver) < 1) {
772 return LDNS_STATUS_ERR;
773 }
774
775 query = ldns_pkt_query_new(ldns_rdf_clone(domain), LDNS_RR_TYPE_AXFR, class, 0);
776
777 if (!query) {
778 return LDNS_STATUS_ADDRESS_ERR;
779 }
780 /* For AXFR, we have to make the connection ourselves */
ac996e71 781 /* try all nameservers (which usually would mean v4 fallback if
825eb42b
JL
782 * @hostname is used */
783 for (ns_i = 0;
784 ns_i < ldns_resolver_nameserver_count(resolver) &&
785 resolver->_socket == 0;
786 ns_i++) {
787 ns = ldns_rdf2native_sockaddr_storage(
788 resolver->_nameservers[ns_i],
789 ldns_resolver_port(resolver), &ns_len);
ac996e71
JL
790
791 resolver->_socket = ldns_tcp_connect(ns, (socklen_t)ns_len,
825eb42b
JL
792 ldns_resolver_timeout(resolver));
793 }
794
795 if (resolver->_socket == 0) {
796 ldns_pkt_free(query);
797 LDNS_FREE(ns);
798 return LDNS_STATUS_NETWORK_ERR;
799 }
800
801#ifdef HAVE_SSL
802 if (ldns_resolver_tsig_keyname(resolver) && ldns_resolver_tsig_keydata(resolver)) {
803 status = ldns_pkt_tsig_sign(query,
804 ldns_resolver_tsig_keyname(resolver),
805 ldns_resolver_tsig_keydata(resolver),
806 300, ldns_resolver_tsig_algorithm(resolver), NULL);
807 if (status != LDNS_STATUS_OK) {
ac996e71
JL
808 /* RoRi: to prevent problems on subsequent calls to ldns_axfr_start
809 we have to close the socket here! */
810#ifndef USE_WINSOCK
811 close(resolver->_socket);
812#else
813 closesocket(resolver->_socket);
814#endif
815 resolver->_socket = 0;
816
825eb42b
JL
817 return LDNS_STATUS_CRYPTO_TSIG_ERR;
818 }
819 }
820#endif /* HAVE_SSL */
821
ac996e71
JL
822 /* Convert the query to a buffer
823 * Is this necessary?
825eb42b
JL
824 */
825 query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN);
fd185f4d
JL
826 if(!query_wire) {
827 ldns_pkt_free(query);
828 LDNS_FREE(ns);
829#ifndef USE_WINSOCK
830 close(resolver->_socket);
831#else
832 closesocket(resolver->_socket);
833#endif
834 resolver->_socket = 0;
835
836 return LDNS_STATUS_MEM_ERR;
837 }
825eb42b
JL
838 status = ldns_pkt2buffer_wire(query_wire, query);
839 if (status != LDNS_STATUS_OK) {
840 ldns_pkt_free(query);
ac996e71 841 ldns_buffer_free(query_wire);
825eb42b 842 LDNS_FREE(ns);
ac996e71
JL
843
844 /* RoRi: to prevent problems on subsequent calls to ldns_axfr_start
845 we have to close the socket here! */
846#ifndef USE_WINSOCK
847 close(resolver->_socket);
848#else
849 closesocket(resolver->_socket);
850#endif
851 resolver->_socket = 0;
852
825eb42b
JL
853 return status;
854 }
855 /* Send the query */
ac996e71 856 if (ldns_tcp_send_query(query_wire, resolver->_socket, ns,
825eb42b
JL
857 (socklen_t)ns_len) == 0) {
858 ldns_pkt_free(query);
859 ldns_buffer_free(query_wire);
860 LDNS_FREE(ns);
ac996e71
JL
861
862 /* RoRi: to prevent problems on subsequent calls to ldns_axfr_start
863 we have to close the socket here! */
864
865#ifndef USE_WINSOCK
866 close(resolver->_socket);
867#else
868 closesocket(resolver->_socket);
869#endif
870 resolver->_socket = 0;
871
825eb42b
JL
872 return LDNS_STATUS_NETWORK_ERR;
873 }
874
875 ldns_pkt_free(query);
876 ldns_buffer_free(query_wire);
877 LDNS_FREE(ns);
878
879 /*
880 * The AXFR is done once the second SOA record is sent
881 */
882 resolver->_axfr_soa_count = 0;
883 return LDNS_STATUS_OK;
884}