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

Generated on 8 Apr 2014 for ldns by  doxygen 1.4.7