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