File Coverage

src/ldns/net.c
Criterion Covered Total %
statement 211 409 51.5
branch 84 198 42.4
condition n/a
subroutine n/a
pod n/a
total 295 607 48.6


line stmt bran cond sub pod time code
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
15              
16             #include
17              
18             #ifdef HAVE_NETINET_IN_H
19             #include
20             #endif
21             #ifdef HAVE_SYS_SOCKET_H
22             #include
23             #endif
24             #ifdef HAVE_NETDB_H
25             #include
26             #endif
27             #ifdef HAVE_ARPA_INET_H
28             #include
29             #endif
30             #include
31             #include
32             #include
33              
34             ldns_status
35 26           ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt)
36             {
37             ldns_buffer *qb;
38             ldns_status result;
39 26           ldns_rdf *tsig_mac = NULL;
40              
41 26           qb = ldns_buffer_new(LDNS_MIN_BUFLEN);
42              
43 26 50         if (query_pkt && ldns_pkt_tsig(query_pkt)) {
    50          
44 0           tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3);
45             }
46              
47 52           if (!query_pkt ||
48 26           ldns_pkt2buffer_wire(qb, query_pkt) != LDNS_STATUS_OK) {
49 0           result = LDNS_STATUS_ERR;
50             } else {
51 26           result = ldns_send_buffer(result_packet, r, qb, tsig_mac);
52             }
53              
54 26           ldns_buffer_free(qb);
55              
56 26           return result;
57             }
58              
59             /* code from rdata.c */
60             static struct sockaddr_storage *
61 28           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 28           data = LDNS_MALLOC(struct sockaddr_storage);
69 28 50         if (!data) {
70 0           return NULL;
71             }
72             /* zero the structure for portability */
73 28           memset(data, 0, sizeof(struct sockaddr_storage));
74              
75 28           switch(ldns_rdf_get_type(rd)) {
76             case LDNS_RDF_TYPE_A:
77             #ifndef S_SPLINT_S
78 28           data->ss_family = AF_INET;
79             #endif
80 28           data_in = (struct sockaddr_in*) data;
81 28           data_in->sin_port = (in_port_t)htons(port);
82 28           memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd));
83 28           *size = sizeof(struct sockaddr_in);
84 28           return data;
85             case LDNS_RDF_TYPE_AAAA:
86             #ifndef S_SPLINT_S
87 0           data->ss_family = AF_INET6;
88             #endif
89 0           data_in6 = (struct sockaddr_in6*) data;
90 0           data_in6->sin6_port = (in_port_t)htons(port);
91 0           memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd));
92 0           *size = sizeof(struct sockaddr_in6);
93 0           return data;
94             default:
95 0           LDNS_FREE(data);
96 0           return NULL;
97             }
98             }
99              
100             struct sockaddr_storage *
101 28           ldns_rdf2native_sockaddr_storage(
102             const ldns_rdf *rd, uint16_t port, size_t *size)
103             {
104 28 50         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 27           ldns_sock_nonblock(int sockfd)
111             {
112             #ifdef HAVE_FCNTL
113             int flag;
114 27 50         if((flag = fcntl(sockfd, F_GETFL)) != -1) {
115 27           flag |= O_NONBLOCK;
116 27           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 27           }
127              
128             /** best effort to set blocking */
129             static void
130 2           ldns_sock_block(int sockfd)
131             {
132             #ifdef HAVE_FCNTL
133             int flag;
134 2 50         if((flag = fcntl(sockfd, F_GETFL)) != -1) {
135 2           flag &= ~O_NONBLOCK;
136 2           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 2           }
147              
148             /** wait for a socket to become ready */
149             static int
150 35           ldns_sock_wait(int sockfd, struct timeval timeout, int write)
151             {
152             int ret;
153             #ifndef S_SPLINT_S
154             fd_set fds;
155 35           FD_ZERO(&fds);
156 35           FD_SET(FD_SET_T sockfd, &fds);
157 35 100         if(write)
158 2           ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
159             else
160 33           ret = select(sockfd+1, &fds, NULL, NULL, &timeout);
161             #endif
162 35 100         if(ret == 0)
163             /* timeout expired */
164 3           return 0;
165 32 50         else if(ret == -1)
166             /* error */
167 0           return 0;
168 35           return 1;
169             }
170              
171              
172             static int
173 2           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 2 50         if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM,
181             IPPROTO_TCP)) == -1) {
182 0           return 0;
183             }
184             #endif
185 2 50         if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){
    0          
186 0           return 0;
187             }
188              
189             /* perform nonblocking connect, to be able to wait with select() */
190 2           ldns_sock_nonblock(sockfd);
191 2 50         if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) {
192             #ifndef USE_WINSOCK
193             #ifdef EINPROGRESS
194 2 50         if(errno != EINPROGRESS) {
195             #else
196             if(1) {
197             #endif
198 0           close(sockfd);
199 0           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 2           int error = 0;
214 2           socklen_t len = (socklen_t)sizeof(error);
215              
216 2 50         if(!ldns_sock_wait(sockfd, timeout, 1)) {
217             #ifndef USE_WINSOCK
218 0           close(sockfd);
219             #else
220             closesocket(sockfd);
221             #endif
222 0           return 0;
223             }
224              
225             /* check if there is a pending error for nonblocking connect */
226 2 50         if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error,
227             &len) < 0) {
228             #ifndef USE_WINSOCK
229 0           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 2 50         if(error == EINPROGRESS || error == EWOULDBLOCK)
    50          
237 0           continue; /* try again */
238             #endif
239 2 50         else if(error != 0) {
240 0           close(sockfd);
241             /* error in errno for our user */
242 0           errno = error;
243 0           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 2           break;
258 0           }
259              
260             /* set the socket blocking again */
261 2           ldns_sock_block(sockfd);
262              
263 2           return sockfd;
264             }
265              
266             int
267 0           ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen,
268             struct timeval timeout)
269             {
270 0           return ldns_tcp_connect_from(to, tolen, NULL, 0, timeout);
271             }
272              
273             static int
274 0           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 0           sockfd = ldns_tcp_connect_from(to, tolen, from, fromlen, timeout);
282            
283 0 0         if (sockfd == 0) {
284 0           return 0;
285             }
286            
287 0 0         if (ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) {
288             #ifndef USE_WINSOCK
289 0           close(sockfd);
290             #else
291             closesocket(sockfd);
292             #endif
293 0           return 0;
294             }
295            
296 0           return sockfd;
297             }
298              
299             int
300 0           ldns_tcp_bgsend(ldns_buffer *qbin,
301             const struct sockaddr_storage *to, socklen_t tolen,
302             struct timeval timeout)
303             {
304 0           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 0           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 0           sockfd = ldns_tcp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
321            
322 0 0         if (sockfd == 0) {
323 0           return LDNS_STATUS_ERR;
324             }
325              
326 0           answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout);
327             #ifndef USE_WINSOCK
328 0           close(sockfd);
329             #else
330             closesocket(sockfd);
331             #endif
332              
333 0 0         if (*answer_size == 0) {
334             /* oops */
335 0           return LDNS_STATUS_NETWORK_ERR;
336             }
337              
338             /* resize accordingly */
339 0           *result = LDNS_XREALLOC(answer, uint8_t, (size_t)*answer_size);
340 0 0         if(!*result) {
341 0           LDNS_FREE(answer);
342 0           return LDNS_STATUS_MEM_ERR;
343             }
344 0           return LDNS_STATUS_OK;
345             }
346              
347             ldns_status
348 0           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 0           return ldns_tcp_send_from(result, qbin,
353             to, tolen, NULL, 0, timeout, answer_size);
354             }
355              
356             int
357 28           ldns_udp_connect(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout))
358             {
359             int sockfd;
360              
361             #ifndef S_SPLINT_S
362 28 50         if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM,
363             IPPROTO_UDP))
364             == -1) {
365 0           return 0;
366             }
367             #endif
368 28           return sockfd;
369             }
370              
371             static int
372 28           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 28           sockfd = ldns_udp_connect(to, timeout);
380              
381 28 50         if (sockfd == 0) {
382 0           return 0;
383             }
384              
385 28 50         if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){
    0          
386 0           return 0;
387             }
388              
389 28 50         if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) {
390             #ifndef USE_WINSOCK
391 0           close(sockfd);
392             #else
393             closesocket(sockfd);
394             #endif
395 0           return 0;
396             }
397 28           return sockfd;
398             }
399              
400             int
401 0           ldns_udp_bgsend(ldns_buffer *qbin,
402             const struct sockaddr_storage *to , socklen_t tolen,
403             struct timeval timeout)
404             {
405 0           return ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
406             }
407              
408             static ldns_status
409 28           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 28           sockfd = ldns_udp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
418              
419 28 50         if (sockfd == 0) {
420 0           return LDNS_STATUS_SOCKET_ERROR;
421             }
422              
423             /* wait for an response*/
424 28 100         if(!ldns_sock_wait(sockfd, timeout, 0)) {
425             #ifndef USE_WINSOCK
426 3           close(sockfd);
427             #else
428             closesocket(sockfd);
429             #endif
430 3           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 25           ldns_sock_nonblock(sockfd);
437              
438 25           answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
439             #ifndef USE_WINSOCK
440 25           close(sockfd);
441             #else
442             closesocket(sockfd);
443             #endif
444              
445 25 50         if (*answer_size == 0) {
446             /* oops */
447 0           return LDNS_STATUS_NETWORK_ERR;
448             }
449              
450 25           *result = answer;
451 25           return LDNS_STATUS_OK;
452             }
453              
454             ldns_status
455 0           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 0           return ldns_udp_send_from(result, qbin, to, tolen, NULL, 0,
460             timeout, answer_size);
461             }
462              
463             ldns_status
464 26           ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac)
465             {
466             uint8_t i;
467              
468 26           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 26           uint8_t *reply_bytes = NULL;
482 26           size_t reply_size = 0;
483             ldns_status status, send_status;
484              
485             assert(r != NULL);
486              
487 26           status = LDNS_STATUS_OK;
488 26           rtt = ldns_resolver_rtt(r);
489 26           ns_array = ldns_resolver_nameservers(r);
490 26           reply = NULL;
491 26           ns_len = 0;
492              
493 26           all_servers_rtt_inf = true;
494              
495 26 50         if (ldns_resolver_random(r)) {
496 26           ldns_resolver_nameservers_randomize(r);
497             }
498              
499 26 50         if(ldns_resolver_source(r)) {
500 0           src = ldns_rdf2native_sockaddr_storage_port(
501 0           ldns_resolver_source(r), 0, &src_len);
502             }
503              
504             /* loop through all defined nameservers */
505 27 100         for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
506 26 50         if (rtt[i] == LDNS_RESOLV_RTT_INF) {
507             /* not reachable nameserver! */
508 0           continue;
509             }
510              
511             /* maybe verbosity setting?
512             printf("Sending to ");
513             ldns_rdf_print(stdout, ns_array[i]);
514             printf("\n");
515             */
516 26           ns = ldns_rdf2native_sockaddr_storage(ns_array[i],
517 26           ldns_resolver_port(r), &ns_len);
518              
519              
520             #ifndef S_SPLINT_S
521 52           if ((ns->ss_family == AF_INET) &&
522 26           (ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) {
523             /* not reachable */
524 0           LDNS_FREE(ns);
525 0           continue;
526             }
527              
528 26           if ((ns->ss_family == AF_INET6) &&
529 0           (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) {
530             /* not reachable */
531 0           LDNS_FREE(ns);
532 0           continue;
533             }
534             #endif
535              
536 26           all_servers_rtt_inf = false;
537              
538 26           gettimeofday(&tv_s, NULL);
539              
540 26           send_status = LDNS_STATUS_ERR;
541              
542             /* reply_bytes implicitly handles our error */
543 26 50         if (ldns_resolver_usevc(r)) {
544 0 0         for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
545 0           send_status =
546 0           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 0 0         if (send_status == LDNS_STATUS_OK) {
552 0           break;
553             }
554             }
555             } else {
556 29 100         for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
557             /* ldns_rdf_print(stdout, ns_array[i]); */
558 28           send_status =
559 28           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 28 100         if (send_status == LDNS_STATUS_OK) {
565 25           break;
566             }
567             }
568             }
569              
570 26 100         if (send_status != LDNS_STATUS_OK) {
571 1           ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF);
572 1           status = send_status;
573             }
574            
575             /* obey the fail directive */
576 26 100         if (!reply_bytes) {
577             /* the current nameserver seems to have a problem, blacklist it */
578 1 50         if (ldns_resolver_fail(r)) {
579 0           LDNS_FREE(ns);
580 0           return LDNS_STATUS_ERR;
581             } else {
582 1           LDNS_FREE(ns);
583 1           continue;
584             }
585             }
586            
587 25           status = ldns_wire2pkt(&reply, reply_bytes, reply_size);
588 25 50         if (status != LDNS_STATUS_OK) {
589 0           LDNS_FREE(reply_bytes);
590 0           LDNS_FREE(ns);
591 0           return status;
592             }
593            
594 25           LDNS_FREE(ns);
595 25           gettimeofday(&tv_e, NULL);
596              
597 25 50         if (reply) {
598 25           ldns_pkt_set_querytime(reply, (uint32_t)
599 25           ((tv_e.tv_sec - tv_s.tv_sec) * 1000) +
600 25           (tv_e.tv_usec - tv_s.tv_usec) / 1000);
601 25           ldns_pkt_set_answerfrom(reply,
602 25           ldns_rdf_clone(ns_array[i]));
603 25           ldns_pkt_set_timestamp(reply, tv_s);
604 25           ldns_pkt_set_size(reply, reply_size);
605 25           break;
606             } else {
607 0 0         if (ldns_resolver_fail(r)) {
608             /* if fail is set bail out, after the first
609             * one */
610 0           break;
611             }
612             }
613              
614             /* wait retrans seconds... */
615 0           sleep((unsigned int) ldns_resolver_retrans(r));
616             }
617              
618 26 50         if(src) {
619 0           LDNS_FREE(src);
620             }
621 26 50         if (all_servers_rtt_inf) {
622 0           LDNS_FREE(reply_bytes);
623 0           return LDNS_STATUS_RES_NO_NS;
624             }
625             #ifdef HAVE_SSL
626 26 50         if (tsig_mac && reply && reply_bytes) {
    0          
    0          
627 0 0         if (!ldns_pkt_tsig_verify(reply,
628             reply_bytes,
629             reply_size,
630 0           ldns_resolver_tsig_keyname(r),
631 0           ldns_resolver_tsig_keydata(r), tsig_mac)) {
632 0           status = LDNS_STATUS_CRYPTO_TSIG_BOGUS;
633             }
634             }
635             #else
636             (void)tsig_mac;
637             #endif /* HAVE_SSL */
638              
639 26           LDNS_FREE(reply_bytes);
640 26 50         if (result) {
641 26           *result = reply;
642             }
643              
644 26           return status;
645             }
646              
647             ssize_t
648 2           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 2           sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2);
656 2 50         if(!sendbuf) return 0;
657 2           ldns_write_uint16(sendbuf, ldns_buffer_position(qbin));
658 2           memcpy(sendbuf + 2, ldns_buffer_begin(qbin), ldns_buffer_position(qbin));
659              
660 2           bytes = sendto(sockfd, (void*)sendbuf,
661 2           ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen);
662              
663 2           LDNS_FREE(sendbuf);
664              
665 2 50         if (bytes == -1 || (size_t) bytes != ldns_buffer_position(qbin) + 2 ) {
    50          
666 0           return 0;
667             }
668 2           return bytes;
669             }
670              
671             /* don't wait for an answer */
672             ssize_t
673 28           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 28           bytes = sendto(sockfd, (void*)ldns_buffer_begin(qbin),
679             ldns_buffer_position(qbin), 0, (struct sockaddr *)to, tolen);
680              
681 28 50         if (bytes == -1 || (size_t)bytes != ldns_buffer_position(qbin)) {
    50          
682 0           return 0;
683             }
684 28 50         if ((size_t) bytes != ldns_buffer_position(qbin)) {
685 0           return 0;
686             }
687 28           return bytes;
688             }
689              
690             uint8_t *
691 25           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 25           wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
698 25 50         if (!wire) {
699 0           *size = 0;
700 0           return NULL;
701             }
702              
703 25           wire_size = recvfrom(sockfd, (void*)wire, LDNS_MAX_PACKETLEN, 0,
704             (struct sockaddr *)from, fromlen);
705              
706             /* recvfrom can also return 0 */
707 25 50         if (wire_size == -1 || wire_size == 0) {
    50          
708 0           *size = 0;
709 0           LDNS_FREE(wire);
710 0           return NULL;
711             }
712              
713 25           *size = (size_t)wire_size;
714 25           wireout = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size);
715 25 50         if(!wireout) LDNS_FREE(wire);
716              
717 25           return wireout;
718             }
719              
720             uint8_t *
721 2           ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout)
722             {
723             uint8_t *wire;
724             uint16_t wire_size;
725 2           ssize_t bytes = 0, rc = 0;
726              
727 2           wire = LDNS_XMALLOC(uint8_t, 2);
728 2 50         if (!wire) {
729 0           *size = 0;
730 0           return NULL;
731             }
732            
733 4 100         while (bytes < 2) {
734 2 50         if(!ldns_sock_wait(sockfd, timeout, 0)) {
735 0           *size = 0;
736 0           LDNS_FREE(wire);
737 0           return NULL;
738             }
739 2           rc = recv(sockfd, (void*) (wire + bytes),
740 2           (size_t) (2 - bytes), 0);
741 2 50         if (rc == -1 || rc == 0) {
    50          
742 0           *size = 0;
743 0           LDNS_FREE(wire);
744 0           return NULL;
745             }
746 2           bytes += rc;
747             }
748              
749 2           wire_size = ldns_read_uint16(wire);
750            
751 2           LDNS_FREE(wire);
752 2           wire = LDNS_XMALLOC(uint8_t, wire_size);
753 2 50         if (!wire) {
754 0           *size = 0;
755 0           return NULL;
756             }
757 2           bytes = 0;
758              
759 5 100         while (bytes < (ssize_t) wire_size) {
760 3 50         if(!ldns_sock_wait(sockfd, timeout, 0)) {
761 0           *size = 0;
762 0           LDNS_FREE(wire);
763 0           return NULL;
764             }
765 3           rc = recv(sockfd, (void*) (wire + bytes),
766 3           (size_t) (wire_size - bytes), 0);
767 3 50         if (rc == -1 || rc == 0) {
    50          
768 0           LDNS_FREE(wire);
769 0           *size = 0;
770 0           return NULL;
771             }
772 3           bytes += rc;
773             }
774            
775 2           *size = (size_t) bytes;
776 2           return wire;
777             }
778              
779             uint8_t *
780 0           ldns_tcp_read_wire(int sockfd, size_t *size)
781             {
782             uint8_t *wire;
783             uint16_t wire_size;
784 0           ssize_t bytes = 0, rc = 0;
785              
786 0           wire = LDNS_XMALLOC(uint8_t, 2);
787 0 0         if (!wire) {
788 0           *size = 0;
789 0           return NULL;
790             }
791            
792 0 0         while (bytes < 2) {
793 0           rc = recv(sockfd, (void*) (wire + bytes),
794 0           (size_t) (2 - bytes), 0);
795 0 0         if (rc == -1 || rc == 0) {
    0          
796 0           *size = 0;
797 0           LDNS_FREE(wire);
798 0           return NULL;
799             }
800 0           bytes += rc;
801             }
802              
803 0           wire_size = ldns_read_uint16(wire);
804            
805 0           LDNS_FREE(wire);
806 0           wire = LDNS_XMALLOC(uint8_t, wire_size);
807 0 0         if (!wire) {
808 0           *size = 0;
809 0           return NULL;
810             }
811 0           bytes = 0;
812              
813 0 0         while (bytes < (ssize_t) wire_size) {
814 0           rc = recv(sockfd, (void*) (wire + bytes),
815 0           (size_t) (wire_size - bytes), 0);
816 0 0         if (rc == -1 || rc == 0) {
    0          
817 0           LDNS_FREE(wire);
818 0           *size = 0;
819 0           return NULL;
820             }
821 0           bytes += rc;
822             }
823            
824 0           *size = (size_t) bytes;
825 0           return wire;
826             }
827              
828             #ifndef S_SPLINT_S
829             ldns_rdf *
830 0           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 0           switch(sock->ss_family) {
837             case AF_INET:
838 0           data_in = (struct sockaddr_in*)sock;
839 0 0         if (port) {
840 0           *port = ntohs((uint16_t)data_in->sin_port);
841             }
842 0           addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A,
843 0           LDNS_IP4ADDRLEN, &data_in->sin_addr);
844 0           break;
845             case AF_INET6:
846 0           data_in6 = (struct sockaddr_in6*)sock;
847 0 0         if (port) {
848 0           *port = ntohs((uint16_t)data_in6->sin6_port);
849             }
850 0           addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA,
851 0           LDNS_IP6ADDRLEN, &data_in6->sin6_addr);
852 0           break;
853             default:
854 0 0         if (port) {
855 0           *port = 0;
856             }
857 0           return NULL;
858             }
859 0           return addr;
860             }
861             #endif
862              
863             /* code from resolver.c */
864             ldns_status
865 2           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 2           struct sockaddr_storage *src = NULL;
871 2           size_t src_len = 0;
872 2           struct sockaddr_storage *ns = NULL;
873 2           size_t ns_len = 0;
874             size_t ns_i;
875             ldns_status status;
876              
877 2 50         if (!resolver || ldns_resolver_nameserver_count(resolver) < 1) {
    50          
878 0           return LDNS_STATUS_ERR;
879             }
880              
881 2           query = ldns_pkt_query_new(ldns_rdf_clone(domain), LDNS_RR_TYPE_AXFR, class, 0);
882              
883 2 50         if (!query) {
884 0           return LDNS_STATUS_ADDRESS_ERR;
885             }
886 2 50         if(ldns_resolver_source(resolver)) {
887 0           src = ldns_rdf2native_sockaddr_storage_port(
888 0           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 6 100         for (ns_i = 0;
894 6 50         ns_i < ldns_resolver_nameserver_count(resolver) &&
895 2           resolver->_socket == 0;
896 2           ns_i++) {
897 2 50         if (ns != NULL) {
898 0           LDNS_FREE(ns);
899             }
900 2           ns = ldns_rdf2native_sockaddr_storage(
901 2           resolver->_nameservers[ns_i],
902 2           ldns_resolver_port(resolver), &ns_len);
903              
904 2           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 2 50         if (resolver->_socket == 0) {
911 0           ldns_pkt_free(query);
912 0           LDNS_FREE(ns);
913 0           return LDNS_STATUS_NETWORK_ERR;
914             }
915              
916             #ifdef HAVE_SSL
917 2 50         if (ldns_resolver_tsig_keyname(resolver) && ldns_resolver_tsig_keydata(resolver)) {
    0          
918 0           status = ldns_pkt_tsig_sign(query,
919 0           ldns_resolver_tsig_keyname(resolver),
920 0           ldns_resolver_tsig_keydata(resolver),
921 0           300, ldns_resolver_tsig_algorithm(resolver), NULL);
922 0 0         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 0           close(resolver->_socket);
927             #else
928             closesocket(resolver->_socket);
929             #endif
930 0           resolver->_socket = 0;
931              
932 0           ldns_pkt_free(query);
933 0           LDNS_FREE(ns);
934              
935 0           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 2           query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN);
944 2 50         if(!query_wire) {
945 0           ldns_pkt_free(query);
946 0           LDNS_FREE(ns);
947             #ifndef USE_WINSOCK
948 0           close(resolver->_socket);
949             #else
950             closesocket(resolver->_socket);
951             #endif
952 0           resolver->_socket = 0;
953              
954 0           return LDNS_STATUS_MEM_ERR;
955             }
956 2           status = ldns_pkt2buffer_wire(query_wire, query);
957 2 50         if (status != LDNS_STATUS_OK) {
958 0           ldns_pkt_free(query);
959 0           ldns_buffer_free(query_wire);
960 0           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 0           close(resolver->_socket);
966             #else
967             closesocket(resolver->_socket);
968             #endif
969 0           resolver->_socket = 0;
970              
971 0           return status;
972             }
973             /* Send the query */
974 2 50         if (ldns_tcp_send_query(query_wire, resolver->_socket, ns,
975             (socklen_t)ns_len) == 0) {
976 0           ldns_pkt_free(query);
977 0           ldns_buffer_free(query_wire);
978 0           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 0           close(resolver->_socket);
985             #else
986             closesocket(resolver->_socket);
987             #endif
988 0           resolver->_socket = 0;
989              
990 0           return LDNS_STATUS_NETWORK_ERR;
991             }
992              
993 2           ldns_pkt_free(query);
994 2           ldns_buffer_free(query_wire);
995 2           LDNS_FREE(ns);
996              
997             /*
998             * The AXFR is done once the second SOA record is sent
999             */
1000 2           resolver->_axfr_soa_count = 0;
1001 2           return LDNS_STATUS_OK;
1002             }