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