net.c
Go to the documentation of this file.
00001 /*
00002  * net.c
00003  *
00004  * Network implementation
00005  * All network related functions are grouped here
00006  *
00007  * a Net::DNS like library for C
00008  *
00009  * (c) NLnet Labs, 2004-2006
00010  *
00011  * See the file LICENSE for the license
00012  */
00013 
00014 #include <ldns/config.h>
00015 
00016 #include <ldns/ldns.h>
00017 
00018 #ifdef HAVE_NETINET_IN_H
00019 #include <netinet/in.h>
00020 #endif
00021 #ifdef HAVE_SYS_SOCKET_H
00022 #include <sys/socket.h>
00023 #endif
00024 #ifdef HAVE_NETDB_H
00025 #include <netdb.h>
00026 #endif
00027 #ifdef HAVE_ARPA_INET_H
00028 #include <arpa/inet.h>
00029 #endif
00030 #include <sys/time.h>
00031 #include <errno.h>
00032 #include <fcntl.h>
00033 
00034 ldns_status
00035 ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt)
00036 {
00037         ldns_buffer *qb;
00038         ldns_status result;
00039         ldns_rdf *tsig_mac = NULL;
00040 
00041         qb = ldns_buffer_new(LDNS_MIN_BUFLEN);
00042 
00043         if (query_pkt && ldns_pkt_tsig(query_pkt)) {
00044                 tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3);
00045         }
00046 
00047         if (!query_pkt ||
00048             ldns_pkt2buffer_wire(qb, query_pkt) != LDNS_STATUS_OK) {
00049                 result = LDNS_STATUS_ERR;
00050         } else {
00051                 result = ldns_send_buffer(result_packet, r, qb, tsig_mac);
00052         }
00053 
00054         ldns_buffer_free(qb);
00055 
00056         return result;
00057 }
00058 
00059 /* code from rdata.c */
00060 static struct sockaddr_storage *
00061 ldns_rdf2native_sockaddr_storage_port(
00062                 const ldns_rdf *rd, uint16_t port, size_t *size)
00063 {
00064         struct sockaddr_storage *data;
00065         struct sockaddr_in  *data_in;
00066         struct sockaddr_in6 *data_in6;
00067 
00068         data = LDNS_MALLOC(struct sockaddr_storage);
00069         if (!data) {
00070                 return NULL;
00071         }
00072         /* zero the structure for portability */
00073         memset(data, 0, sizeof(struct sockaddr_storage));
00074 
00075         switch(ldns_rdf_get_type(rd)) {
00076                 case LDNS_RDF_TYPE_A:
00077 #ifndef S_SPLINT_S
00078                         data->ss_family = AF_INET;
00079 #endif
00080                         data_in = (struct sockaddr_in*) data;
00081                         data_in->sin_port = (in_port_t)htons(port);
00082                         memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd));
00083                         *size = sizeof(struct sockaddr_in);
00084                         return data;
00085                 case LDNS_RDF_TYPE_AAAA:
00086 #ifndef S_SPLINT_S
00087                         data->ss_family = AF_INET6;
00088 #endif
00089                         data_in6 = (struct sockaddr_in6*) data;
00090                         data_in6->sin6_port = (in_port_t)htons(port);
00091                         memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd));
00092                         *size = sizeof(struct sockaddr_in6);
00093                         return data;
00094                 default:
00095                         LDNS_FREE(data);
00096                         return NULL;
00097         }
00098 }
00099 
00100 struct sockaddr_storage *
00101 ldns_rdf2native_sockaddr_storage(
00102                 const ldns_rdf *rd, uint16_t port, size_t *size)
00103 {
00104         return ldns_rdf2native_sockaddr_storage_port(
00105                         rd, (port == 0 ? (uint16_t)LDNS_PORT : port), size);
00106 }
00107 
00109 static void
00110 ldns_sock_nonblock(int sockfd)
00111 {
00112 #ifdef HAVE_FCNTL
00113         int flag;
00114         if((flag = fcntl(sockfd, F_GETFL)) != -1) {
00115                 flag |= O_NONBLOCK;
00116                 if(fcntl(sockfd, F_SETFL, flag) == -1) {
00117                         /* ignore error, continue blockingly */
00118                 }
00119         }
00120 #elif defined(HAVE_IOCTLSOCKET)
00121         unsigned long on = 1;
00122         if(ioctlsocket(sockfd, FIONBIO, &on) != 0) {
00123                 /* ignore error, continue blockingly */
00124         }
00125 #endif
00126 }
00127 
00129 static void
00130 ldns_sock_block(int sockfd)
00131 {
00132 #ifdef HAVE_FCNTL
00133         int flag;
00134         if((flag = fcntl(sockfd, F_GETFL)) != -1) {
00135                 flag &= ~O_NONBLOCK;
00136                 if(fcntl(sockfd, F_SETFL, flag) == -1) {
00137                         /* ignore error, continue */
00138                 }
00139         }
00140 #elif defined(HAVE_IOCTLSOCKET)
00141         unsigned long off = 0;
00142         if(ioctlsocket(sockfd, FIONBIO, &off) != 0) {
00143                 /* ignore error, continue */
00144         }
00145 #endif
00146 }
00147 
00149 static int
00150 ldns_sock_wait(int sockfd, struct timeval timeout, int write)
00151 {
00152         int ret;
00153 #ifndef S_SPLINT_S
00154         fd_set fds;
00155         FD_ZERO(&fds);
00156         FD_SET(FD_SET_T sockfd, &fds);
00157         if(write)
00158                 ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
00159         else
00160                 ret = select(sockfd+1, &fds, NULL, NULL, &timeout);
00161 #endif
00162         if(ret == 0)
00163                 /* timeout expired */
00164                 return 0;
00165         else if(ret == -1)
00166                 /* error */
00167                 return 0;
00168         return 1;
00169 }
00170 
00171 
00172 static int
00173 ldns_tcp_connect_from(const struct sockaddr_storage *to, socklen_t tolen, 
00174                 const struct sockaddr_storage *from, socklen_t fromlen,
00175                 struct timeval timeout)
00176 {
00177         int sockfd;
00178 
00179 #ifndef S_SPLINT_S
00180         if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM, 
00181                                         IPPROTO_TCP)) == -1) {
00182                 return 0;
00183         }
00184 #endif
00185         if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){
00186                 return 0;
00187         }
00188 
00189         /* perform nonblocking connect, to be able to wait with select() */
00190         ldns_sock_nonblock(sockfd);
00191         if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) {
00192 #ifndef USE_WINSOCK
00193 #ifdef EINPROGRESS
00194                 if(errno != EINPROGRESS) {
00195 #else
00196                 if(1) {
00197 #endif
00198                         close(sockfd);
00199                         return 0;
00200                 }
00201 #else /* USE_WINSOCK */
00202                 if(WSAGetLastError() != WSAEINPROGRESS &&
00203                         WSAGetLastError() != WSAEWOULDBLOCK) {
00204                         closesocket(sockfd);
00205                         return 0;
00206                 }
00207 #endif
00208                 /* error was only telling us that it would block */
00209         }
00210 
00211         /* wait(write) until connected or error */
00212         while(1) {
00213                 int error = 0;
00214                 socklen_t len = (socklen_t)sizeof(error);
00215 
00216                 if(!ldns_sock_wait(sockfd, timeout, 1)) {
00217 #ifndef USE_WINSOCK
00218                         close(sockfd);
00219 #else
00220                         closesocket(sockfd);
00221 #endif
00222                         return 0;
00223                 }
00224 
00225                 /* check if there is a pending error for nonblocking connect */
00226                 if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error,
00227                         &len) < 0) {
00228 #ifndef USE_WINSOCK
00229                         error = errno; /* on solaris errno is error */
00230 #else
00231                         error = WSAGetLastError();
00232 #endif
00233                 }
00234 #ifndef USE_WINSOCK
00235 #if defined(EINPROGRESS) && defined(EWOULDBLOCK)
00236                 if(error == EINPROGRESS || error == EWOULDBLOCK)
00237                         continue; /* try again */
00238 #endif
00239                 else if(error != 0) {
00240                         close(sockfd);
00241                         /* error in errno for our user */
00242                         errno = error;
00243                         return 0;
00244                 }
00245 #else /* USE_WINSOCK */
00246                 if(error == WSAEINPROGRESS)
00247                         continue;
00248                 else if(error == WSAEWOULDBLOCK)
00249                         continue;
00250                 else if(error != 0) {
00251                         closesocket(sockfd);
00252                         errno = error;
00253                         return 0;
00254                 }
00255 #endif /* USE_WINSOCK */
00256                 /* connected */
00257                 break;
00258         }
00259 
00260         /* set the socket blocking again */
00261         ldns_sock_block(sockfd);
00262 
00263         return sockfd;
00264 }
00265 
00266 int
00267 ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, 
00268                 struct timeval timeout)
00269 {
00270         return ldns_tcp_connect_from(to, tolen, NULL, 0, timeout);
00271 }
00272 
00273 static int
00274 ldns_tcp_bgsend_from(ldns_buffer *qbin,
00275                 const struct sockaddr_storage *to, socklen_t tolen, 
00276                 const struct sockaddr_storage *from, socklen_t fromlen,
00277                 struct timeval timeout)
00278 {
00279         int sockfd;
00280         
00281         sockfd = ldns_tcp_connect_from(to, tolen, from, fromlen, timeout);
00282         
00283         if (sockfd == 0) {
00284                 return 0;
00285         }
00286         
00287         if (ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) {
00288 #ifndef USE_WINSOCK
00289                 close(sockfd);
00290 #else
00291                 closesocket(sockfd);
00292 #endif
00293                 return 0;
00294         }
00295         
00296         return sockfd;
00297 }
00298 
00299 int
00300 ldns_tcp_bgsend(ldns_buffer *qbin,
00301                 const struct sockaddr_storage *to, socklen_t tolen, 
00302                 struct timeval timeout)
00303 {
00304         return ldns_tcp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
00305 }
00306 
00307 
00308 /* keep in mind that in DNS tcp messages the first 2 bytes signal the
00309  * amount data to expect
00310  */
00311 static ldns_status
00312 ldns_tcp_send_from(uint8_t **result,  ldns_buffer *qbin,
00313                 const struct sockaddr_storage *to, socklen_t tolen,
00314                 const struct sockaddr_storage *from, socklen_t fromlen,
00315                 struct timeval timeout, size_t *answer_size)
00316 {
00317         int sockfd;
00318         uint8_t *answer;
00319         
00320         sockfd = ldns_tcp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
00321         
00322         if (sockfd == 0) {
00323                 return LDNS_STATUS_ERR;
00324         }
00325 
00326         answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout);
00327 #ifndef USE_WINSOCK
00328         close(sockfd);
00329 #else
00330         closesocket(sockfd);
00331 #endif
00332 
00333         if (*answer_size == 0) {
00334                 /* oops */
00335                 return LDNS_STATUS_NETWORK_ERR;
00336         }
00337 
00338         /* resize accordingly */
00339         *result = LDNS_XREALLOC(answer, uint8_t, (size_t)*answer_size);
00340         if(!*result) {
00341                 LDNS_FREE(answer);
00342                 return LDNS_STATUS_MEM_ERR;
00343         }
00344         return LDNS_STATUS_OK;
00345 }
00346 
00347 ldns_status
00348 ldns_tcp_send(uint8_t **result,  ldns_buffer *qbin,
00349                 const struct sockaddr_storage *to, socklen_t tolen,
00350                 struct timeval timeout, size_t *answer_size)
00351 {
00352         return ldns_tcp_send_from(result, qbin,
00353                         to, tolen, NULL, 0, timeout, answer_size);
00354 }
00355 
00356 int
00357 ldns_udp_connect(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout))
00358 {
00359         int sockfd;
00360 
00361 #ifndef S_SPLINT_S
00362         if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM, 
00363                                         IPPROTO_UDP)) 
00364                         == -1) {
00365                 return 0;
00366         }
00367 #endif
00368         return sockfd;
00369 }
00370 
00371 static int
00372 ldns_udp_bgsend_from(ldns_buffer *qbin,
00373                 const struct sockaddr_storage *to  , socklen_t tolen, 
00374                 const struct sockaddr_storage *from, socklen_t fromlen, 
00375                 struct timeval timeout)
00376 {
00377         int sockfd;
00378 
00379         sockfd = ldns_udp_connect(to, timeout);
00380 
00381         if (sockfd == 0) {
00382                 return 0;
00383         }
00384 
00385         if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){
00386                 return 0;
00387         }
00388 
00389         if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) {
00390 #ifndef USE_WINSOCK
00391                 close(sockfd);
00392 #else
00393                 closesocket(sockfd);
00394 #endif
00395                 return 0;
00396         }
00397         return sockfd;
00398 }
00399 
00400 int
00401 ldns_udp_bgsend(ldns_buffer *qbin,
00402                 const struct sockaddr_storage *to  , socklen_t tolen, 
00403                 struct timeval timeout)
00404 {
00405         return ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
00406 }
00407 
00408 static ldns_status
00409 ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
00410                 const struct sockaddr_storage *to  , socklen_t tolen,
00411                 const struct sockaddr_storage *from, socklen_t fromlen,
00412                 struct timeval timeout, size_t *answer_size)
00413 {
00414         int sockfd;
00415         uint8_t *answer;
00416 
00417         sockfd = ldns_udp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
00418 
00419         if (sockfd == 0) {
00420                 return LDNS_STATUS_SOCKET_ERROR;
00421         }
00422 
00423         /* wait for an response*/
00424         if(!ldns_sock_wait(sockfd, timeout, 0)) {
00425 #ifndef USE_WINSOCK
00426                 close(sockfd);
00427 #else
00428                 closesocket(sockfd);
00429 #endif
00430                 return LDNS_STATUS_NETWORK_ERR;
00431         }
00432 
00433         /* set to nonblocking, so if the checksum is bad, it becomes
00434          * an EGAIN error and the ldns_udp_send function does not block,
00435          * but returns a 'NETWORK_ERROR' much like a timeout. */
00436         ldns_sock_nonblock(sockfd);
00437 
00438         answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
00439 #ifndef USE_WINSOCK
00440         close(sockfd);
00441 #else
00442         closesocket(sockfd);
00443 #endif
00444 
00445         if (*answer_size == 0) {
00446                 /* oops */
00447                 return LDNS_STATUS_NETWORK_ERR;
00448         }
00449 
00450         *result = answer;
00451         return LDNS_STATUS_OK;
00452 }
00453 
00454 ldns_status
00455 ldns_udp_send(uint8_t **result, ldns_buffer *qbin,
00456                 const struct sockaddr_storage *to  , socklen_t tolen,
00457                 struct timeval timeout, size_t *answer_size)
00458 {
00459         return ldns_udp_send_from(result, qbin, to, tolen, NULL, 0,
00460                         timeout, answer_size);
00461 }
00462 
00463 ldns_status
00464 ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac)
00465 {
00466         uint8_t i;
00467 
00468         struct sockaddr_storage *src = NULL;
00469         size_t src_len;
00470         struct sockaddr_storage *ns;
00471         size_t ns_len;
00472         struct timeval tv_s;
00473         struct timeval tv_e;
00474 
00475         ldns_rdf **ns_array;
00476         size_t *rtt;
00477         ldns_pkt *reply;
00478         bool all_servers_rtt_inf;
00479         uint8_t retries;
00480 
00481         uint8_t *reply_bytes = NULL;
00482         size_t reply_size = 0;
00483         ldns_status status, send_status;
00484 
00485         assert(r != NULL);
00486 
00487         status = LDNS_STATUS_OK;
00488         rtt = ldns_resolver_rtt(r);
00489         ns_array = ldns_resolver_nameservers(r);
00490         reply = NULL; 
00491         ns_len = 0;
00492 
00493         all_servers_rtt_inf = true;
00494 
00495         if (ldns_resolver_random(r)) {
00496                 ldns_resolver_nameservers_randomize(r);
00497         }
00498 
00499         if(ldns_resolver_source(r)) {
00500                 src = ldns_rdf2native_sockaddr_storage_port(
00501                                 ldns_resolver_source(r), 0, &src_len);
00502         }
00503 
00504         /* loop through all defined nameservers */
00505         for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
00506                 if (rtt[i] == LDNS_RESOLV_RTT_INF) {
00507                         /* not reachable nameserver! */
00508                         continue;
00509                 }
00510 
00511                 /* maybe verbosity setting?
00512                 printf("Sending to ");
00513                 ldns_rdf_print(stdout, ns_array[i]);
00514                 printf("\n");
00515                 */
00516                 ns = ldns_rdf2native_sockaddr_storage(ns_array[i],
00517                                 ldns_resolver_port(r), &ns_len);
00518 
00519 
00520 #ifndef S_SPLINT_S
00521                 if ((ns->ss_family == AF_INET) &&
00522                                 (ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) {
00523                         /* not reachable */
00524                         LDNS_FREE(ns);
00525                         continue;
00526                 }
00527 
00528                 if ((ns->ss_family == AF_INET6) &&
00529                                  (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) {
00530                         /* not reachable */
00531                         LDNS_FREE(ns);
00532                         continue;
00533                 }
00534 #endif
00535 
00536                 all_servers_rtt_inf = false;
00537 
00538                 gettimeofday(&tv_s, NULL);
00539 
00540                 send_status = LDNS_STATUS_ERR;
00541 
00542                 /* reply_bytes implicitly handles our error */
00543                 if (ldns_resolver_usevc(r)) {
00544                         for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
00545                                 send_status = 
00546                                         ldns_tcp_send_from(&reply_bytes, qb, 
00547                                                 ns, (socklen_t)ns_len,
00548                                                 src, (socklen_t)src_len,
00549                                                 ldns_resolver_timeout(r),
00550                                                 &reply_size);
00551                                 if (send_status == LDNS_STATUS_OK) {
00552                                         break;
00553                                 }
00554                         }
00555                 } else {
00556                         for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
00557                                 /* ldns_rdf_print(stdout, ns_array[i]); */
00558                                 send_status = 
00559                                         ldns_udp_send_from(&reply_bytes, qb,
00560                                                 ns,  (socklen_t)ns_len,
00561                                                 src, (socklen_t)src_len,
00562                                                 ldns_resolver_timeout(r),
00563                                                 &reply_size);
00564                                 if (send_status == LDNS_STATUS_OK) {
00565                                         break;
00566                                 }
00567                         }
00568                 }
00569 
00570                 if (send_status != LDNS_STATUS_OK) {
00571                         ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF);
00572                         status = send_status;
00573                 }
00574                 
00575                 /* obey the fail directive */
00576                 if (!reply_bytes) {
00577                         /* the current nameserver seems to have a problem, blacklist it */
00578                         if (ldns_resolver_fail(r)) {
00579                                 LDNS_FREE(ns);
00580                                 return LDNS_STATUS_ERR;
00581                         } else {
00582                                 LDNS_FREE(ns);
00583                                 continue;
00584                         }
00585                 } 
00586                 
00587                 status = ldns_wire2pkt(&reply, reply_bytes, reply_size);
00588                 if (status != LDNS_STATUS_OK) {
00589                         LDNS_FREE(reply_bytes);
00590                         LDNS_FREE(ns);
00591                         return status;
00592                 }
00593                 
00594                 LDNS_FREE(ns);
00595                 gettimeofday(&tv_e, NULL);
00596 
00597                 if (reply) {
00598                         ldns_pkt_set_querytime(reply, (uint32_t)
00599                                 ((tv_e.tv_sec - tv_s.tv_sec) * 1000) +
00600                                 (tv_e.tv_usec - tv_s.tv_usec) / 1000);
00601                         ldns_pkt_set_answerfrom(reply,
00602                                         ldns_rdf_clone(ns_array[i]));
00603                         ldns_pkt_set_timestamp(reply, tv_s);
00604                         ldns_pkt_set_size(reply, reply_size);
00605                         break;
00606                 } else {
00607                         if (ldns_resolver_fail(r)) {
00608                                 /* if fail is set bail out, after the first
00609                                  * one */
00610                                 break;
00611                         }
00612                 }
00613 
00614                 /* wait retrans seconds... */
00615                 sleep((unsigned int) ldns_resolver_retrans(r));
00616         }
00617 
00618         if(src) {
00619                 LDNS_FREE(src);
00620         }
00621         if (all_servers_rtt_inf) {
00622                 LDNS_FREE(reply_bytes);
00623                 return LDNS_STATUS_RES_NO_NS;
00624         }
00625 #ifdef HAVE_SSL
00626         if (tsig_mac && reply && reply_bytes) {
00627                 if (!ldns_pkt_tsig_verify(reply,
00628                                           reply_bytes,
00629                                           reply_size,
00630                                           ldns_resolver_tsig_keyname(r),
00631                                           ldns_resolver_tsig_keydata(r), tsig_mac)) {
00632                         status = LDNS_STATUS_CRYPTO_TSIG_BOGUS;
00633                 }
00634         }
00635 #else
00636         (void)tsig_mac;
00637 #endif /* HAVE_SSL */
00638 
00639         LDNS_FREE(reply_bytes);
00640         if (result) {
00641                 *result = reply;
00642         }
00643 
00644         return status;
00645 }
00646 
00647 ssize_t
00648 ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, 
00649                     const struct sockaddr_storage *to, socklen_t tolen)
00650 {
00651         uint8_t *sendbuf;
00652         ssize_t bytes;
00653 
00654         /* add length of packet */
00655         sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2);
00656         if(!sendbuf) return 0;
00657         ldns_write_uint16(sendbuf, ldns_buffer_position(qbin));
00658         memcpy(sendbuf + 2, ldns_buffer_begin(qbin), ldns_buffer_position(qbin));
00659 
00660         bytes = sendto(sockfd, (void*)sendbuf,
00661                         ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen);
00662 
00663         LDNS_FREE(sendbuf);
00664 
00665         if (bytes == -1 || (size_t) bytes != ldns_buffer_position(qbin) + 2 ) {
00666                 return 0;
00667         }
00668         return bytes;
00669 }
00670 
00671 /* don't wait for an answer */
00672 ssize_t
00673 ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, 
00674                 socklen_t tolen)
00675 {
00676         ssize_t bytes;
00677 
00678         bytes = sendto(sockfd, (void*)ldns_buffer_begin(qbin),
00679                         ldns_buffer_position(qbin), 0, (struct sockaddr *)to, tolen);
00680 
00681         if (bytes == -1 || (size_t)bytes != ldns_buffer_position(qbin)) {
00682                 return 0;
00683         }
00684         if ((size_t) bytes != ldns_buffer_position(qbin)) {
00685                 return 0;
00686         }
00687         return bytes;
00688 }
00689 
00690 uint8_t *
00691 ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from,
00692                 socklen_t *fromlen)
00693 {
00694         uint8_t *wire, *wireout;
00695         ssize_t wire_size;
00696 
00697         wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
00698         if (!wire) {
00699                 *size = 0;
00700                 return NULL;
00701         }
00702 
00703         wire_size = recvfrom(sockfd, (void*)wire, LDNS_MAX_PACKETLEN, 0, 
00704                         (struct sockaddr *)from, fromlen);
00705 
00706         /* recvfrom can also return 0 */
00707         if (wire_size == -1 || wire_size == 0) {
00708                 *size = 0;
00709                 LDNS_FREE(wire);
00710                 return NULL;
00711         }
00712 
00713         *size = (size_t)wire_size;
00714         wireout = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size);
00715         if(!wireout) LDNS_FREE(wire);
00716 
00717         return wireout;
00718 }
00719 
00720 uint8_t *
00721 ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout)
00722 {
00723         uint8_t *wire;
00724         uint16_t wire_size;
00725         ssize_t bytes = 0, rc = 0;
00726 
00727         wire = LDNS_XMALLOC(uint8_t, 2);
00728         if (!wire) {
00729                 *size = 0;
00730                 return NULL;
00731         }
00732         
00733         while (bytes < 2) {
00734                 if(!ldns_sock_wait(sockfd, timeout, 0)) {
00735                         *size = 0;
00736                         LDNS_FREE(wire);
00737                         return NULL;
00738                 }
00739                 rc = recv(sockfd, (void*) (wire + bytes), 
00740                                 (size_t) (2 - bytes), 0);
00741                 if (rc == -1 || rc == 0) {
00742                         *size = 0;
00743                         LDNS_FREE(wire);
00744                         return NULL;
00745                 }
00746                 bytes += rc;
00747         }
00748 
00749         wire_size = ldns_read_uint16(wire);
00750         
00751         LDNS_FREE(wire);
00752         wire = LDNS_XMALLOC(uint8_t, wire_size);
00753         if (!wire) {
00754                 *size = 0;
00755                 return NULL;
00756         }
00757         bytes = 0;
00758 
00759         while (bytes < (ssize_t) wire_size) {
00760                 if(!ldns_sock_wait(sockfd, timeout, 0)) {
00761                         *size = 0;
00762                         LDNS_FREE(wire);
00763                         return NULL;
00764                 }
00765                 rc = recv(sockfd, (void*) (wire + bytes), 
00766                                 (size_t) (wire_size - bytes), 0);
00767                 if (rc == -1 || rc == 0) {
00768                         LDNS_FREE(wire);
00769                         *size = 0;
00770                         return NULL;
00771                 }
00772                 bytes += rc;
00773         }
00774         
00775         *size = (size_t) bytes;
00776         return wire;
00777 }
00778 
00779 uint8_t *
00780 ldns_tcp_read_wire(int sockfd, size_t *size)
00781 {
00782         uint8_t *wire;
00783         uint16_t wire_size;
00784         ssize_t bytes = 0, rc = 0;
00785 
00786         wire = LDNS_XMALLOC(uint8_t, 2);
00787         if (!wire) {
00788                 *size = 0;
00789                 return NULL;
00790         }
00791         
00792         while (bytes < 2) {
00793                 rc = recv(sockfd, (void*) (wire + bytes), 
00794                                 (size_t) (2 - bytes), 0);
00795                 if (rc == -1 || rc == 0) {
00796                         *size = 0;
00797                         LDNS_FREE(wire);
00798                         return NULL;
00799                 }
00800                 bytes += rc;
00801         }
00802 
00803         wire_size = ldns_read_uint16(wire);
00804         
00805         LDNS_FREE(wire);
00806         wire = LDNS_XMALLOC(uint8_t, wire_size);
00807         if (!wire) {
00808                 *size = 0;
00809                 return NULL;
00810         }
00811         bytes = 0;
00812 
00813         while (bytes < (ssize_t) wire_size) {
00814                 rc = recv(sockfd, (void*) (wire + bytes), 
00815                                 (size_t) (wire_size - bytes), 0);
00816                 if (rc == -1 || rc == 0) {
00817                         LDNS_FREE(wire);
00818                         *size = 0;
00819                         return NULL;
00820                 }
00821                 bytes += rc;
00822         }
00823         
00824         *size = (size_t) bytes;
00825         return wire;
00826 }
00827 
00828 #ifndef S_SPLINT_S
00829 ldns_rdf *
00830 ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port)
00831 {
00832         ldns_rdf *addr;
00833         struct sockaddr_in *data_in;
00834         struct sockaddr_in6 *data_in6;
00835 
00836         switch(sock->ss_family) {
00837                 case AF_INET:
00838                         data_in = (struct sockaddr_in*)sock;
00839                         if (port) {
00840                                 *port = ntohs((uint16_t)data_in->sin_port);
00841                         }
00842                         addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A,
00843                                         LDNS_IP4ADDRLEN, &data_in->sin_addr);
00844                         break;
00845                 case AF_INET6:
00846                         data_in6 = (struct sockaddr_in6*)sock;
00847                         if (port) {
00848                                 *port = ntohs((uint16_t)data_in6->sin6_port);
00849                         }
00850                         addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA,
00851                                         LDNS_IP6ADDRLEN, &data_in6->sin6_addr);
00852                         break;
00853                 default:
00854                         if (port) {
00855                                 *port = 0;
00856                         }
00857                         return NULL;
00858         }
00859         return addr;
00860 }
00861 #endif
00862 
00863 /* code from resolver.c */
00864 ldns_status
00865 ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) 
00866 {
00867         ldns_pkt *query;
00868         ldns_buffer *query_wire;
00869 
00870         struct sockaddr_storage *src = NULL;
00871         size_t src_len = 0;
00872         struct sockaddr_storage *ns = NULL;
00873         size_t ns_len = 0;
00874         size_t ns_i;
00875         ldns_status status;
00876 
00877         if (!resolver || ldns_resolver_nameserver_count(resolver) < 1) {
00878                 return LDNS_STATUS_ERR;
00879         }
00880 
00881         query = ldns_pkt_query_new(ldns_rdf_clone(domain), LDNS_RR_TYPE_AXFR, class, 0);
00882 
00883         if (!query) {
00884                 return LDNS_STATUS_ADDRESS_ERR;
00885         }
00886         if(ldns_resolver_source(resolver)) {
00887                 src = ldns_rdf2native_sockaddr_storage_port(
00888                                 ldns_resolver_source(resolver), 0, &src_len);
00889         }
00890         /* For AXFR, we have to make the connection ourselves */
00891         /* try all nameservers (which usually would mean v4 fallback if
00892          * @hostname is used */
00893         for (ns_i = 0;
00894              ns_i < ldns_resolver_nameserver_count(resolver) &&
00895              resolver->_socket == 0;
00896              ns_i++) {
00897                 if (ns != NULL) {
00898                         LDNS_FREE(ns);
00899                 }
00900                 ns = ldns_rdf2native_sockaddr_storage(
00901                         resolver->_nameservers[ns_i],
00902                         ldns_resolver_port(resolver), &ns_len);
00903 
00904                 resolver->_socket = ldns_tcp_connect_from(
00905                                 ns, (socklen_t)ns_len,
00906                                 src, (socklen_t)src_len,
00907                                 ldns_resolver_timeout(resolver));
00908         }
00909 
00910         if (resolver->_socket == 0) {
00911                 ldns_pkt_free(query);
00912                 LDNS_FREE(ns);
00913                 return LDNS_STATUS_NETWORK_ERR;
00914         }
00915 
00916 #ifdef HAVE_SSL
00917         if (ldns_resolver_tsig_keyname(resolver) && ldns_resolver_tsig_keydata(resolver)) {
00918                 status = ldns_pkt_tsig_sign(query,
00919                                             ldns_resolver_tsig_keyname(resolver),
00920                                             ldns_resolver_tsig_keydata(resolver),
00921                                             300, ldns_resolver_tsig_algorithm(resolver), NULL);
00922                 if (status != LDNS_STATUS_OK) {
00923                         /* to prevent problems on subsequent calls to 
00924                          * ldns_axfr_start we have to close the socket here! */
00925 #ifndef USE_WINSOCK
00926                         close(resolver->_socket);
00927 #else
00928                         closesocket(resolver->_socket);
00929 #endif
00930                         resolver->_socket = 0;
00931 
00932                         ldns_pkt_free(query);
00933                         LDNS_FREE(ns);
00934 
00935                         return LDNS_STATUS_CRYPTO_TSIG_ERR;
00936                 }
00937         }
00938 #endif /* HAVE_SSL */
00939 
00940         /* Convert the query to a buffer
00941          * Is this necessary?
00942          */
00943         query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00944         if(!query_wire) {
00945                 ldns_pkt_free(query);
00946                 LDNS_FREE(ns);
00947 #ifndef USE_WINSOCK
00948                 close(resolver->_socket);
00949 #else
00950                 closesocket(resolver->_socket);
00951 #endif
00952                 resolver->_socket = 0;
00953 
00954                 return LDNS_STATUS_MEM_ERR;
00955         }
00956         status = ldns_pkt2buffer_wire(query_wire, query);
00957         if (status != LDNS_STATUS_OK) {
00958                 ldns_pkt_free(query);
00959                 ldns_buffer_free(query_wire);
00960                 LDNS_FREE(ns);
00961 
00962                 /* to prevent problems on subsequent calls to ldns_axfr_start
00963                  * we have to close the socket here! */
00964 #ifndef USE_WINSOCK
00965                 close(resolver->_socket);
00966 #else
00967                 closesocket(resolver->_socket);
00968 #endif
00969                 resolver->_socket = 0;
00970 
00971                 return status;
00972         }
00973         /* Send the query */
00974         if (ldns_tcp_send_query(query_wire, resolver->_socket, ns,
00975                                 (socklen_t)ns_len) == 0) {
00976                 ldns_pkt_free(query);
00977                 ldns_buffer_free(query_wire);
00978                 LDNS_FREE(ns);
00979 
00980                 /* to prevent problems on subsequent calls to ldns_axfr_start
00981                  * we have to close the socket here! */
00982 
00983 #ifndef USE_WINSOCK
00984                 close(resolver->_socket);
00985 #else
00986                 closesocket(resolver->_socket);
00987 #endif
00988                 resolver->_socket = 0;
00989 
00990                 return LDNS_STATUS_NETWORK_ERR;
00991         }
00992 
00993         ldns_pkt_free(query);
00994         ldns_buffer_free(query_wire);
00995         LDNS_FREE(ns);
00996 
00997         /*
00998          * The AXFR is done once the second SOA record is sent
00999          */
01000         resolver->_axfr_soa_count = 0;
01001         return LDNS_STATUS_OK;
01002 }