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