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 #include <netinet/in.h>
00019 #include <sys/socket.h>
00020 #include <netdb.h>
00021 #include <arpa/inet.h>
00022 #include <sys/time.h>
00023 #include <errno.h>
00024 
00025 ldns_status
00026 ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt)
00027 {
00028         ldns_buffer *qb;
00029         ldns_status result;
00030         ldns_rdf *tsig_mac = NULL;
00031 
00032         qb = ldns_buffer_new(LDNS_MIN_BUFLEN);
00033 
00034         if (ldns_pkt_tsig(query_pkt)) {
00035                 tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3);
00036         }
00037 
00038 
00039         if (!query_pkt ||
00040             ldns_pkt2buffer_wire(qb, query_pkt) != LDNS_STATUS_OK) {
00041                 result = LDNS_STATUS_ERR;
00042         } else {
00043                 result = ldns_send_buffer(result_packet, r, qb, tsig_mac);
00044         }
00045 
00046         ldns_buffer_free(qb);
00047         
00048         return result;
00049 }
00050 
00051 ldns_status
00052 ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac)
00053 {
00054         uint8_t i;
00055         
00056         struct sockaddr_storage *ns;
00057         size_t ns_len;
00058         struct timeval tv_s;
00059         struct timeval tv_e;
00060 
00061         ldns_rdf **ns_array;
00062         size_t *rtt;
00063         ldns_pkt *reply;
00064         bool all_servers_rtt_inf;
00065         uint8_t retries;
00066 
00067         uint8_t *reply_bytes = NULL;
00068         size_t reply_size = 0;
00069         ldns_status status, send_status;
00070         
00071         assert(r != NULL);
00072 
00073         status = LDNS_STATUS_OK;
00074         rtt = ldns_resolver_rtt(r);
00075         ns_array = ldns_resolver_nameservers(r);
00076         reply = NULL; 
00077         ns_len = 0;
00078 
00079         all_servers_rtt_inf = true;
00080 
00081         if (ldns_resolver_random(r)) {
00082                 ldns_resolver_nameservers_randomize(r);
00083         }
00084 
00085         /* loop through all defined nameservers */
00086         for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
00087 
00088                 if (rtt[i] == LDNS_RESOLV_RTT_INF) {
00089                         /* not reachable nameserver! */
00090                         continue;
00091                 }
00092                 all_servers_rtt_inf = false;
00093 
00094                 /* maybe verbosity setting?
00095                 printf("Sending to ");
00096                 ldns_rdf_print(stdout, ns_array[i]);
00097                 printf("\n");
00098                 */
00099                 ns = ldns_rdf2native_sockaddr_storage(ns_array[i],
00100                                 ldns_resolver_port(r), &ns_len);
00101                 
00102                 if ((ns->ss_family == AF_INET) && 
00103                                 (ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) {
00104                         continue;
00105                 }
00106 
00107                 if ((ns->ss_family == AF_INET6) &&
00108                                  (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) {
00109                         continue;
00110                 }
00111 
00112                 gettimeofday(&tv_s, NULL);
00113 
00114                 send_status = LDNS_STATUS_ERR;
00115                 /* reply_bytes implicitly handles our error */
00116                 if (1 == ldns_resolver_usevc(r)) {
00117                         for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
00118                                 send_status = 
00119                                         ldns_tcp_send(&reply_bytes, qb, ns, 
00120                                         (socklen_t)ns_len, ldns_resolver_timeout(r), 
00121                                         &reply_size);
00122                                 if (send_status == LDNS_STATUS_OK) {
00123                                         break;
00124                                 }
00125                         }
00126                 } else {
00127                         for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
00128                                 /* ldns_rdf_print(stdout, ns_array[i]); */
00129                                 send_status = 
00130                                         ldns_udp_send(&reply_bytes, qb, ns, 
00131                                                         (socklen_t)ns_len, ldns_resolver_timeout(r), 
00132                                                         &reply_size);
00133                                 
00134                                 if (send_status == LDNS_STATUS_OK) {
00135                                         break;
00136                                 }
00137                         }
00138                 }
00139 
00140                 if (send_status != LDNS_STATUS_OK) {
00141                         ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF);
00142                         status = send_status;
00143                 }
00144                 
00145                 /* obey the fail directive */
00146                 if (!reply_bytes) {
00147                         /* the current nameserver seems to have a problem, blacklist it */
00148                         if (ldns_resolver_fail(r)) {
00149                                 LDNS_FREE(ns);
00150                                 return LDNS_STATUS_ERR;
00151                         } else {
00152                                 LDNS_FREE(ns);
00153                                 continue;
00154                         }
00155                 } 
00156                 
00157                 status = ldns_wire2pkt(&reply, reply_bytes, reply_size);
00158                 if (status != LDNS_STATUS_OK) {
00159                         LDNS_FREE(reply_bytes);
00160                         LDNS_FREE(ns);
00161                         return status;
00162                 }
00163                 
00164                 LDNS_FREE(ns);
00165                 gettimeofday(&tv_e, NULL);
00166 
00167                 if (reply) {
00168                         ldns_pkt_set_querytime(reply, (uint32_t)
00169                                 ((tv_e.tv_sec - tv_s.tv_sec) * 1000) +
00170                                 (tv_e.tv_usec - tv_s.tv_usec) / 1000);
00171                         ldns_pkt_set_answerfrom(reply, ns_array[i]);
00172                         ldns_pkt_set_timestamp(reply, tv_s);
00173                         ldns_pkt_set_size(reply, reply_size);
00174                         break;
00175                 } else {
00176                         if (ldns_resolver_fail(r)) {
00177                                 /* if fail is set bail out, after the first
00178                                  * one */
00179                                 break;
00180                         }
00181                 }
00182 
00183                 /* wait retrans seconds... */
00184                 sleep((unsigned int) ldns_resolver_retrans(r));
00185         }
00186 
00187         if (all_servers_rtt_inf) {
00188                 LDNS_FREE(reply_bytes);
00189                 return LDNS_STATUS_RES_NO_NS;
00190         }
00191 #ifdef HAVE_SSL
00192         if (tsig_mac && reply_bytes) {
00193                 if (!ldns_pkt_tsig_verify(reply,
00194                                           reply_bytes,
00195                                           reply_size,
00196                                           ldns_resolver_tsig_keyname(r),
00197                                           ldns_resolver_tsig_keydata(r), tsig_mac)) {
00198                         status = LDNS_STATUS_CRYPTO_TSIG_BOGUS;
00199                 }
00200         }
00201 #else
00202         (void)tsig_mac;
00203 #endif /* HAVE_SSL */
00204         LDNS_FREE(reply_bytes);
00205         if (result) {
00206                 *result = reply;
00207         }
00208 
00209         return status;
00210 }
00211 
00212 ldns_status
00213 ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, 
00214                 socklen_t tolen, struct timeval timeout, size_t *answer_size)
00215 {
00216         int sockfd;
00217         uint8_t *answer;
00218 
00219         sockfd = ldns_udp_bgsend(qbin, to, tolen, timeout);
00220 
00221         if (sockfd == 0) {
00222                 return LDNS_STATUS_SOCKET_ERROR;
00223         }
00224 
00225         /* wait for an response*/
00226         answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
00227         close(sockfd);
00228 
00229         if (*answer_size == 0) {
00230                 /* oops */
00231                 return LDNS_STATUS_NETWORK_ERR;
00232         }
00233 
00234         *result = answer;
00235         return LDNS_STATUS_OK;
00236 }
00237 
00238 int
00239 ldns_udp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, 
00240                 struct timeval timeout)
00241 {
00242         int sockfd;
00243 
00244         sockfd = ldns_udp_connect(to, timeout);
00245 
00246         if (sockfd == 0) {
00247                 return 0;
00248         }
00249 
00250         if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) {
00251                 return 0;
00252         }
00253         return sockfd;
00254 }
00255 
00256 int
00257 ldns_udp_connect(const struct sockaddr_storage *to, struct timeval timeout)
00258 {
00259         int sockfd;
00260         
00261         if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM, 
00262                                         IPPROTO_UDP)) 
00263                         == -1) {
00264                 return 0;
00265         }
00266         if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout,
00267                                 (socklen_t)sizeof(timeout))) {
00268                 /* might fail, in that case, use default for now */
00269                 /*
00270                 close(sockfd);
00271                 return 0;
00272                 */
00273         }
00274         return sockfd;
00275 }
00276 
00277 int
00278 ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, 
00279                 struct timeval timeout)
00280 {
00281         int sockfd;
00282         
00283         if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM, 
00284                                         IPPROTO_TCP)) == -1) {
00285                 /*perror("could not open socket");*/
00286                 return 0;
00287         }
00288 
00289         if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout,
00290                         (socklen_t) sizeof(timeout))) {
00291                 /*perror("setsockopt");*/
00292                 close(sockfd);
00293                 return 0;
00294         }
00295 
00296         if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) {
00297                 close(sockfd);
00298                 /*perror("could not bind socket");*/
00299                 return 0;
00300         }
00301         return sockfd;
00302 }
00303 
00304 ssize_t
00305 ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, 
00306                     const struct sockaddr_storage *to, socklen_t tolen)
00307 {
00308         uint8_t *sendbuf;
00309         ssize_t bytes;
00310 
00311         /* add length of packet */
00312         sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2);
00313         ldns_write_uint16(sendbuf, ldns_buffer_position(qbin));
00314         memcpy(sendbuf + 2, ldns_buffer_export(qbin), ldns_buffer_position(qbin));
00315 
00316         bytes = sendto(sockfd, sendbuf,
00317                         ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen);
00318 
00319         LDNS_FREE(sendbuf);
00320 
00321         if (bytes == -1 || (size_t) bytes != ldns_buffer_position(qbin) + 2 ) {
00322                 return 0;
00323         }
00324         return bytes;
00325 }
00326 
00327 /* don't wait for an answer */
00328 ssize_t
00329 ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, 
00330                 socklen_t tolen)
00331 {
00332         ssize_t bytes;
00333 
00334         bytes = sendto(sockfd, ldns_buffer_begin(qbin),
00335                         ldns_buffer_position(qbin), 0, (struct sockaddr *)to, tolen);
00336 
00337         if (bytes == -1 || (size_t)bytes != ldns_buffer_position(qbin)) {
00338                 return 0;
00339         }
00340         if ((size_t) bytes != ldns_buffer_position(qbin)) {
00341                 return 0;
00342         }
00343         return bytes;
00344 }
00345 
00346 uint8_t *
00347 ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from,
00348                 socklen_t *fromlen)
00349 {
00350         uint8_t *wire;
00351         ssize_t wire_size;
00352         socklen_t flen;
00353 
00354         wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
00355         if (!wire) {
00356                 *size = 0;
00357                 return NULL;
00358         }
00359 
00360         wire_size = recvfrom(sockfd, wire, LDNS_MAX_PACKETLEN, 0, 
00361                         (struct sockaddr*) from, &flen);
00362 
00363         if (from) {
00364                 if (fromlen) {
00365                         *fromlen = flen;
00366                 }
00367         }
00368 
00369         /* recvfrom can also return 0 */
00370         if (wire_size == -1 || wire_size == 0) {
00371                 *size = 0;
00372                 LDNS_FREE(wire);
00373                 return NULL;
00374         }
00375 
00376         *size = (size_t)wire_size;
00377         wire = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size);
00378 
00379         return wire;
00380 }
00381 
00382 uint8_t *
00383 ldns_tcp_read_wire(int sockfd, size_t *size)
00384 {
00385         uint8_t *wire;
00386         uint16_t wire_size;
00387         ssize_t bytes = 0;
00388 
00389         wire = LDNS_XMALLOC(uint8_t, 2);
00390         if (!wire) {
00391                 *size = 0;
00392                 return NULL;
00393         }
00394         
00395         while (bytes < 2) {
00396                 bytes = recv(sockfd, wire, 2, 0);
00397                 if (bytes == -1 || bytes == 0) {
00398                         *size = 0;
00399                         LDNS_FREE(wire);
00400                         return NULL;
00401                 }
00402         }
00403 
00404         wire_size = ldns_read_uint16(wire);
00405         
00406         LDNS_FREE(wire);
00407         wire = LDNS_XMALLOC(uint8_t, wire_size);
00408         bytes = 0;
00409 
00410         while (bytes < (ssize_t) wire_size) {
00411                 bytes += recv(sockfd, wire + bytes, (size_t) (wire_size - bytes), 0);
00412                 if (bytes == -1 || bytes == 0) {
00413                         LDNS_FREE(wire);
00414                         *size = 0;
00415                         return NULL;
00416                 }
00417         }
00418         
00419         *size = (size_t) bytes;
00420         return wire;
00421 }
00422 
00423 /* keep in mind that in DNS tcp messages the first 2 bytes signal the
00424  * amount data to expect
00425  */
00426 ldns_status
00427 ldns_tcp_send(uint8_t **result,  ldns_buffer *qbin, const struct sockaddr_storage *to, 
00428                 socklen_t tolen, struct timeval timeout, size_t *answer_size)
00429 {
00430         int sockfd;
00431         uint8_t *answer;
00432         
00433         sockfd = ldns_tcp_bgsend(qbin, to, tolen, timeout);
00434         
00435         if (sockfd == 0) {
00436                 return LDNS_STATUS_ERR;
00437         }
00438         
00439         answer = ldns_tcp_read_wire(sockfd, answer_size);
00440         close(sockfd);
00441 
00442         if (*answer_size == 0) {
00443                 /* oops */
00444                 return LDNS_STATUS_NETWORK_ERR;
00445         }
00446 
00447         /* resize accordingly */
00448         answer = (uint8_t*)LDNS_XREALLOC(answer, uint8_t *, (size_t)*answer_size);
00449         *result = answer;
00450         return LDNS_STATUS_OK;
00451 }
00452 
00453 int
00454 ldns_tcp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, 
00455                 struct timeval timeout)
00456 {
00457         int sockfd;
00458         
00459         sockfd = ldns_tcp_connect(to, tolen, timeout);
00460         
00461         if (sockfd == 0) {
00462                 return 0;
00463         }
00464         
00465         if (ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) {
00466                 return 0;
00467         }
00468         
00469         return sockfd;
00470 }
00471 
00472 /* code from rdata.c */
00473 struct sockaddr_storage *
00474 ldns_rdf2native_sockaddr_storage(const ldns_rdf *rd, uint16_t port, size_t *size)
00475 {
00476         struct sockaddr_storage *data;
00477         struct sockaddr_in  *data_in;
00478         struct sockaddr_in6 *data_in6;
00479 
00480         data = LDNS_MALLOC(struct sockaddr_storage);
00481         if (!data) {
00482                 return NULL;
00483         }
00484         if (port == 0) {
00485                 port =  LDNS_PORT;
00486         }
00487 
00488         switch(ldns_rdf_get_type(rd)) {
00489                 case LDNS_RDF_TYPE_A:
00490                         data->ss_family = AF_INET;
00491                         data_in = (struct sockaddr_in*) data;
00492                         data_in->sin_port = (in_port_t)htons(port);
00493                         memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd));
00494                         *size = sizeof(struct sockaddr_in);
00495                         return data;
00496                 case LDNS_RDF_TYPE_AAAA:
00497                         data->ss_family = AF_INET6;
00498                         data_in6 = (struct sockaddr_in6*) data;
00499                         data_in6->sin6_port = (in_port_t)htons(port);
00500                         memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd));
00501                         *size = sizeof(struct sockaddr_in6);
00502                         return data;
00503                 default:
00504                         LDNS_FREE(data);
00505                         return NULL;
00506         }
00507 }
00508 
00509 ldns_rdf *
00510 ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port)
00511 {
00512         ldns_rdf *addr;
00513         struct sockaddr_in *data_in;
00514         struct sockaddr_in6 *data_in6;
00515 
00516         switch(sock->ss_family) {
00517                 case AF_INET:
00518                         data_in = (struct sockaddr_in*)sock;
00519                         if (port) {
00520                                 *port = ntohs((uint16_t)data_in->sin_port);
00521                         }
00522                         addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A,
00523                                         LDNS_IP4ADDRLEN, &data_in->sin_addr);
00524                         break;
00525                 case AF_INET6:
00526                         data_in6 = (struct sockaddr_in6*)sock;
00527                         if (port) {
00528                                 *port = ntohs((uint16_t)data_in6->sin6_port);
00529                         }
00530                         addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA,
00531                                         LDNS_IP6ADDRLEN, &data_in6->sin6_addr);
00532                         break;
00533                 default:
00534                         if (port) {
00535                                 *port = 0;
00536                         }
00537                         return NULL;
00538         }
00539         return addr;
00540 }
00541 
00542 /* code from resolver.c */
00543 ldns_status
00544 ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) 
00545 {
00546         ldns_pkt *query;
00547         ldns_buffer *query_wire;
00548 
00549         struct sockaddr_storage *ns;
00550         size_t ns_len = 0;
00551         ldns_status status;
00552 
00553         if (!resolver || ldns_resolver_nameserver_count(resolver) < 1) {
00554                 return LDNS_STATUS_ERR;
00555         }
00556 
00557         query = ldns_pkt_query_new(ldns_rdf_clone(domain), LDNS_RR_TYPE_AXFR, class, 0);
00558 
00559         if (!query) {
00560                 return LDNS_STATUS_ADDRESS_ERR;
00561         }
00562         /* For AXFR, we have to make the connection ourselves */
00563         ns = ldns_rdf2native_sockaddr_storage(resolver->_nameservers[0],
00564                         ldns_resolver_port(resolver), &ns_len);
00565 
00566         resolver->_socket = ldns_tcp_connect(ns, (socklen_t)ns_len, 
00567                         ldns_resolver_timeout(resolver));
00568         if (resolver->_socket == 0) {
00569                 ldns_pkt_free(query);
00570                 LDNS_FREE(ns);
00571                 return LDNS_STATUS_NETWORK_ERR;
00572         }
00573 
00574 #ifdef HAVE_SSL
00575         if (ldns_resolver_tsig_keyname(resolver) && ldns_resolver_tsig_keydata(resolver)) {
00576                 status = ldns_pkt_tsig_sign(query,
00577                                             ldns_resolver_tsig_keyname(resolver),
00578                                             ldns_resolver_tsig_keydata(resolver),
00579                                             300, ldns_resolver_tsig_algorithm(resolver), NULL);
00580                 if (status != LDNS_STATUS_OK) {
00581                         return LDNS_STATUS_CRYPTO_TSIG_ERR;
00582                 }
00583         }
00584 #endif /* HAVE_SSL */
00585 
00586         /* Convert the query to a buffer          * Is this necessary?
00587          */
00588         query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN);
00589         status = ldns_pkt2buffer_wire(query_wire, query);
00590         if (status != LDNS_STATUS_OK) {
00591                 ldns_pkt_free(query);
00592                 LDNS_FREE(ns);
00593                 return status;
00594         }
00595         /* Send the query */
00596         if (ldns_tcp_send_query(query_wire, resolver->_socket, ns, 
00597                                 (socklen_t)ns_len) == 0) {
00598                 ldns_pkt_free(query);
00599                 ldns_buffer_free(query_wire);
00600                 LDNS_FREE(ns);
00601                 return LDNS_STATUS_NETWORK_ERR;
00602         }
00603 
00604         ldns_pkt_free(query);
00605         ldns_buffer_free(query_wire);
00606         LDNS_FREE(ns);
00607 
00608         /*
00609          * The AXFR is done once the second SOA record is sent
00610          */
00611         resolver->_axfr_soa_count = 0;
00612         return LDNS_STATUS_OK;
00613 }

Generated on Thu Nov 29 13:38:26 2007 for ldns by  doxygen 1.5.2