00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00094 for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
00095 if (rtt[i] == LDNS_RESOLV_RTT_INF) {
00096
00097 continue;
00098 }
00099
00100
00101
00102
00103
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
00113 LDNS_FREE(ns);
00114 continue;
00115 }
00116
00117 if ((ns->ss_family == AF_INET6) &&
00118 (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) {
00119
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
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
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
00162 if (!reply_bytes) {
00163
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
00195
00196 break;
00197 }
00198 }
00199
00200
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
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
00240 }
00241 }
00242 #elif defined(HAVE_IOCTLSOCKET)
00243 unsigned long on = 1;
00244 if(ioctlsocket(sockfd, FIONBIO, &on) != 0) {
00245
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
00260 }
00261 }
00262 #elif defined(HAVE_IOCTLSOCKET)
00263 unsigned long off = 0;
00264 if(ioctlsocket(sockfd, FIONBIO, &off) != 0) {
00265
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
00286 return 0;
00287 else if(ret == -1)
00288
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
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
00317
00318
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
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
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
00401 if(WSAGetLastError() != WSAEINPROGRESS &&
00402 WSAGetLastError() != WSAEWOULDBLOCK) {
00403 closesocket(sockfd);
00404 return 0;
00405 }
00406 #endif
00407
00408 }
00409
00410
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
00425 if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error,
00426 &len) < 0) {
00427 #ifndef USE_WINSOCK
00428 error = errno;
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;
00437 #endif
00438 else if(error != 0) {
00439 close(sockfd);
00440
00441 errno = error;
00442 return 0;
00443 }
00444 #else
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
00455
00456 break;
00457 }
00458
00459
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
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
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
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
00647
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
00671 return LDNS_STATUS_NETWORK_ERR;
00672 }
00673
00674
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
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
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
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
00807
00808
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
00838
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
00853
00854
00855
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
00877
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
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
00895
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
00913
00914 resolver->_axfr_soa_count = 0;
00915 return LDNS_STATUS_OK;
00916 }