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