resolver.c
Go to the documentation of this file.
00001 /*
00002  * resolver.c
00003  *
00004  * resolver implementation
00005  *
00006  * a Net::DNS like library for C
00007  *
00008  * (c) NLnet Labs, 2004-2006
00009  *
00010  * See the file LICENSE for the license
00011  */
00012 
00013 #include <ldns/config.h>
00014 
00015 #include <ldns/ldns.h>
00016 #include <strings.h>
00017 
00018 /* Access function for reading
00019  * and setting the different Resolver
00020  * options */
00021 
00022 /* read */
00023 uint16_t
00024 ldns_resolver_port(const ldns_resolver *r)
00025 {
00026         return r->_port;
00027 }
00028 
00029 ldns_rdf *
00030 ldns_resolver_source(const ldns_resolver *r)
00031 {
00032         return r->_source;
00033 }
00034 
00035 uint16_t
00036 ldns_resolver_edns_udp_size(const ldns_resolver *r)
00037 {
00038                 return r->_edns_udp_size;
00039 }
00040 
00041 uint8_t
00042 ldns_resolver_retry(const ldns_resolver *r)
00043 {
00044         return r->_retry;
00045 }
00046 
00047 uint8_t
00048 ldns_resolver_retrans(const ldns_resolver *r)
00049 {
00050         return r->_retrans;
00051 }
00052 
00053 bool
00054 ldns_resolver_fallback(const ldns_resolver *r)
00055 {
00056         return r->_fallback;
00057 }
00058 
00059 uint8_t
00060 ldns_resolver_ip6(const ldns_resolver *r)
00061 {
00062         return r->_ip6;
00063 }
00064 
00065 bool
00066 ldns_resolver_recursive(const ldns_resolver *r)
00067 {
00068         return r->_recursive;
00069 }
00070 
00071 bool
00072 ldns_resolver_debug(const ldns_resolver *r)
00073 {
00074         return r->_debug;
00075 }
00076 
00077 bool
00078 ldns_resolver_dnsrch(const ldns_resolver *r)
00079 {
00080         return r->_dnsrch;
00081 }
00082 
00083 bool
00084 ldns_resolver_fail(const ldns_resolver *r)
00085 {
00086         return r->_fail;
00087 }
00088 
00089 bool
00090 ldns_resolver_defnames(const ldns_resolver *r)
00091 {
00092         return r->_defnames;
00093 }
00094 
00095 ldns_rdf *
00096 ldns_resolver_domain(const ldns_resolver *r)
00097 {
00098         return r->_domain;
00099 }
00100 
00101 ldns_rdf **
00102 ldns_resolver_searchlist(const ldns_resolver *r)
00103 {
00104         return r->_searchlist;
00105 }
00106 
00107 ldns_rdf **
00108 ldns_resolver_nameservers(const ldns_resolver *r)
00109 {
00110         return r->_nameservers;
00111 }
00112 
00113 size_t
00114 ldns_resolver_nameserver_count(const ldns_resolver *r)
00115 {
00116         return r->_nameserver_count;
00117 }
00118 
00119 bool
00120 ldns_resolver_dnssec(const ldns_resolver *r)
00121 {
00122         return r->_dnssec;
00123 }
00124 
00125 bool
00126 ldns_resolver_dnssec_cd(const ldns_resolver *r)
00127 {
00128         return r->_dnssec_cd;
00129 }
00130 
00131 ldns_rr_list *
00132 ldns_resolver_dnssec_anchors(const ldns_resolver *r)
00133 {
00134     return r->_dnssec_anchors;
00135 }
00136 
00137 bool
00138 ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys)
00139 {
00140   size_t i;
00141   bool result = false;
00142 
00143   ldns_rr_list * trust_anchors;
00144   ldns_rr * cur_rr;
00145 
00146   if (!r || !keys) { return false; }
00147 
00148   trust_anchors = ldns_resolver_dnssec_anchors(r);
00149 
00150   if (!trust_anchors) { return false; }
00151 
00152   for (i = 0; i < ldns_rr_list_rr_count(keys); i++) {
00153 
00154     cur_rr = ldns_rr_list_rr(keys, i);
00155     if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) {
00156       if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); }
00157       result = true;
00158     }
00159   }
00160 
00161   return result;
00162 }
00163 
00164 bool
00165 ldns_resolver_igntc(const ldns_resolver *r)
00166 {
00167         return r->_igntc;
00168 }
00169 
00170 bool
00171 ldns_resolver_usevc(const ldns_resolver *r)
00172 {
00173         return r->_usevc;
00174 }
00175 
00176 size_t *
00177 ldns_resolver_rtt(const ldns_resolver *r)
00178 {
00179         return r->_rtt;
00180 }
00181 
00182 size_t
00183 ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos)
00184 {
00185         size_t *rtt;
00186 
00187         assert(r != NULL);
00188 
00189         rtt = ldns_resolver_rtt(r);
00190 
00191         if (pos >= ldns_resolver_nameserver_count(r)) {
00192                 /* error ?*/
00193                 return 0;
00194         } else {
00195                 return rtt[pos];
00196         }
00197 
00198 }
00199 
00200 struct timeval
00201 ldns_resolver_timeout(const ldns_resolver *r)
00202 {
00203         return r->_timeout;
00204 }
00205 
00206 char *
00207 ldns_resolver_tsig_keyname(const ldns_resolver *r)
00208 {
00209         return r->_tsig_keyname;
00210 }
00211 
00212 char *
00213 ldns_resolver_tsig_algorithm(const ldns_resolver *r)
00214 {
00215         return r->_tsig_algorithm;
00216 }
00217 
00218 char *
00219 ldns_resolver_tsig_keydata(const ldns_resolver *r)
00220 {
00221         return r->_tsig_keydata;
00222 }
00223 
00224 bool
00225 ldns_resolver_random(const ldns_resolver *r)
00226 {
00227         return r->_random;
00228 }
00229 
00230 size_t
00231 ldns_resolver_searchlist_count(const ldns_resolver *r)
00232 {
00233         return r->_searchlist_count;
00234 }
00235 
00236 /* write */
00237 void
00238 ldns_resolver_set_port(ldns_resolver *r, uint16_t p)
00239 {
00240         r->_port = p;
00241 }
00242 
00243 void
00244 ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s)
00245 {
00246         r->_source = s;
00247 }
00248 
00249 ldns_rdf *
00250 ldns_resolver_pop_nameserver(ldns_resolver *r)
00251 {
00252         ldns_rdf **nameservers;
00253         ldns_rdf *pop;
00254         size_t ns_count;
00255         size_t *rtt;
00256 
00257         assert(r != NULL);
00258 
00259         ns_count = ldns_resolver_nameserver_count(r);
00260         nameservers = ldns_resolver_nameservers(r);
00261         rtt = ldns_resolver_rtt(r);
00262         if (ns_count == 0 || !nameservers) {
00263                 return NULL;
00264         }
00265 
00266         pop = nameservers[ns_count - 1];
00267 
00268         if (ns_count == 1) {
00269                 LDNS_FREE(nameservers);
00270                 LDNS_FREE(rtt);
00271 
00272                 ldns_resolver_set_nameservers(r, NULL);
00273                 ldns_resolver_set_rtt(r, NULL);
00274         } else {
00275                 nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, 
00276                                 (ns_count - 1));
00277                 rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1));
00278 
00279                 ldns_resolver_set_nameservers(r, nameservers);
00280                 ldns_resolver_set_rtt(r, rtt);
00281         }
00282         /* decr the count */
00283         ldns_resolver_dec_nameserver_count(r);
00284         return pop;
00285 }
00286 
00287 ldns_status
00288 ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n)
00289 {
00290         ldns_rdf **nameservers;
00291         size_t ns_count;
00292         size_t *rtt;
00293 
00294         if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A &&
00295                         ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) {
00296                 return LDNS_STATUS_ERR;
00297         }
00298 
00299         ns_count = ldns_resolver_nameserver_count(r);
00300         nameservers = ldns_resolver_nameservers(r);
00301         rtt = ldns_resolver_rtt(r);
00302 
00303         /* make room for the next one */
00304         if (ns_count == 0) {
00305                 nameservers = LDNS_XMALLOC(ldns_rdf *, 1);
00306         } else {
00307                 nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1));
00308         }
00309         if(!nameservers)
00310                 return LDNS_STATUS_MEM_ERR;
00311 
00312         /* set the new value in the resolver */
00313         ldns_resolver_set_nameservers(r, nameservers);
00314 
00315         /* don't forget the rtt */
00316         if (ns_count == 0) {
00317                 rtt = LDNS_XMALLOC(size_t, 1);
00318         } else {
00319                 rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1));
00320         }
00321         if(!rtt)
00322                 return LDNS_STATUS_MEM_ERR;
00323 
00324         /* slide n in its slot. */
00325         /* we clone it here, because then we can free the original
00326          * rr's where it stood */
00327         nameservers[ns_count] = ldns_rdf_clone(n);
00328         rtt[ns_count] = LDNS_RESOLV_RTT_MIN;
00329         ldns_resolver_incr_nameserver_count(r);
00330         ldns_resolver_set_rtt(r, rtt);
00331         return LDNS_STATUS_OK;
00332 }
00333 
00334 ldns_status
00335 ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr)
00336 {
00337         ldns_rdf *address;
00338         if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A &&
00339                         ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) {
00340                 return LDNS_STATUS_ERR;
00341         }
00342         address = ldns_rr_rdf(rr, 0); /* extract the ip number */
00343         if (address) {
00344                 return ldns_resolver_push_nameserver(r, address);
00345         } else {
00346                 return LDNS_STATUS_ERR;
00347         }
00348 }
00349 
00350 ldns_status
00351 ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist)
00352 {
00353         ldns_rr *rr;
00354         ldns_status stat;
00355         size_t i;
00356 
00357         stat = LDNS_STATUS_OK;
00358         if (rrlist) {
00359                 for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
00360                         rr = ldns_rr_list_rr(rrlist, i);
00361                         if (ldns_resolver_push_nameserver_rr(r, rr) != LDNS_STATUS_OK) {
00362                                 stat = LDNS_STATUS_ERR;
00363                                 break;
00364                         }
00365                 }
00366                 return stat;
00367         } else {
00368                 return LDNS_STATUS_ERR;
00369         }
00370 }
00371 
00372 void
00373 ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s)
00374 {
00375                 r->_edns_udp_size = s;
00376 }
00377 
00378 void
00379 ldns_resolver_set_recursive(ldns_resolver *r, bool re)
00380 {
00381         r->_recursive = re;
00382 }
00383 
00384 void
00385 ldns_resolver_set_dnssec(ldns_resolver *r, bool d)
00386 {
00387         r->_dnssec = d;
00388 }
00389 
00390 void
00391 ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d)
00392 {
00393         r->_dnssec_cd = d;
00394 }
00395 
00396 void
00397 ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l)
00398 {
00399   r->_dnssec_anchors = l;
00400 }
00401 
00402 ldns_status
00403 ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr)
00404 {
00405   ldns_rr_list * trust_anchors;
00406 
00407   if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY &&
00408                 ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS)) {
00409 
00410     return LDNS_STATUS_ERR;
00411   }
00412 
00413   if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */
00414     trust_anchors = ldns_rr_list_new();
00415     ldns_resolver_set_dnssec_anchors(r, trust_anchors);
00416   }
00417 
00418   return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
00419 }
00420 
00421 void
00422 ldns_resolver_set_igntc(ldns_resolver *r, bool i)
00423 {
00424         r->_igntc = i;
00425 }
00426 
00427 void
00428 ldns_resolver_set_usevc(ldns_resolver *r, bool vc)
00429 {
00430         r->_usevc = vc;
00431 }
00432 
00433 void
00434 ldns_resolver_set_debug(ldns_resolver *r, bool d)
00435 {
00436         r->_debug = d;
00437 }
00438 
00439 void
00440 ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6)
00441 {
00442         r->_ip6 = ip6;
00443 }
00444 
00445 void
00446 ldns_resolver_set_fail(ldns_resolver *r, bool f)
00447 {
00448         r->_fail =f;
00449 }
00450 
00451 static void
00452 ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c)
00453 {
00454         r->_searchlist_count = c;
00455 }
00456 
00457 void
00458 ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c)
00459 {
00460         r->_nameserver_count = c;
00461 }
00462 
00463 void
00464 ldns_resolver_set_dnsrch(ldns_resolver *r, bool d)
00465 {
00466         r->_dnsrch = d;
00467 }
00468 
00469 void
00470 ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry)
00471 {
00472         r->_retry = retry;
00473 }
00474 
00475 void
00476 ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans)
00477 {
00478         r->_retrans = retrans;
00479 }
00480 
00481 void
00482 ldns_resolver_set_fallback(ldns_resolver *r, bool fallback)
00483 {
00484         r->_fallback = fallback;
00485 }
00486 
00487 void
00488 ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n)
00489 {
00490         r->_nameservers = n;
00491 }
00492 
00493 void
00494 ldns_resolver_set_defnames(ldns_resolver *r, bool d)
00495 {
00496         r->_defnames = d;
00497 }
00498 
00499 void
00500 ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt)
00501 {
00502         r->_rtt = rtt;
00503 }
00504 
00505 void
00506 ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value)
00507 {
00508         size_t *rtt;
00509 
00510         assert(r != NULL);
00511 
00512         rtt = ldns_resolver_rtt(r);
00513 
00514         if (pos >= ldns_resolver_nameserver_count(r)) {
00515                 /* error ?*/
00516         } else {
00517                 rtt[pos] = value;
00518         }
00519 
00520 }
00521 
00522 void
00523 ldns_resolver_incr_nameserver_count(ldns_resolver *r)
00524 {
00525         size_t c;
00526 
00527         c = ldns_resolver_nameserver_count(r);
00528         ldns_resolver_set_nameserver_count(r, ++c);
00529 }
00530 
00531 void
00532 ldns_resolver_dec_nameserver_count(ldns_resolver *r)
00533 {
00534         size_t c;
00535 
00536         c = ldns_resolver_nameserver_count(r);
00537         if (c == 0) {
00538                 return;
00539         } else {
00540                 ldns_resolver_set_nameserver_count(r, --c);
00541         }
00542 }
00543 
00544 void
00545 ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d)
00546 {
00547         r->_domain = d;
00548 }
00549 
00550 void
00551 ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout)
00552 {
00553         r->_timeout.tv_sec = timeout.tv_sec;
00554         r->_timeout.tv_usec = timeout.tv_usec;
00555 }
00556 
00557 void
00558 ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d)
00559 {
00560         ldns_rdf **searchlist;
00561         size_t list_count;
00562 
00563         if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
00564                 return;
00565         }
00566 
00567         list_count = ldns_resolver_searchlist_count(r);
00568         searchlist = ldns_resolver_searchlist(r);
00569 
00570         searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1));
00571         if (searchlist) {
00572                 r->_searchlist = searchlist;
00573 
00574                 searchlist[list_count] = ldns_rdf_clone(d);
00575                 ldns_resolver_set_searchlist_count(r, list_count + 1);
00576         } /* no way to report mem err */
00577 }
00578 
00579 void
00580 ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname)
00581 {
00582         LDNS_FREE(r->_tsig_keyname);
00583         r->_tsig_keyname = strdup(tsig_keyname);
00584 }
00585 
00586 void
00587 ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm)
00588 {
00589         LDNS_FREE(r->_tsig_algorithm);
00590         r->_tsig_algorithm = strdup(tsig_algorithm);
00591 }
00592 
00593 void
00594 ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata)
00595 {
00596         LDNS_FREE(r->_tsig_keydata);
00597         r->_tsig_keydata = strdup(tsig_keydata);
00598 }
00599 
00600 void
00601 ldns_resolver_set_random(ldns_resolver *r, bool b)
00602 {
00603         r->_random = b;
00604 }
00605 
00606 /* more sophisticated functions */
00607 ldns_resolver *
00608 ldns_resolver_new(void)
00609 {
00610         ldns_resolver *r;
00611 
00612         r = LDNS_MALLOC(ldns_resolver);
00613         if (!r) {
00614                 return NULL;
00615         }
00616 
00617         r->_searchlist = NULL;
00618         r->_nameservers = NULL;
00619         r->_rtt = NULL;
00620 
00621         /* defaults are filled out */
00622         ldns_resolver_set_searchlist_count(r, 0);
00623         ldns_resolver_set_nameserver_count(r, 0);
00624         ldns_resolver_set_usevc(r, 0);
00625         ldns_resolver_set_port(r, LDNS_PORT);
00626         ldns_resolver_set_domain(r, NULL);
00627         ldns_resolver_set_defnames(r, false);
00628         ldns_resolver_set_retry(r, 3);
00629         ldns_resolver_set_retrans(r, 2);
00630         ldns_resolver_set_fallback(r, true);
00631         ldns_resolver_set_fail(r, false);
00632         ldns_resolver_set_edns_udp_size(r, 0);
00633         ldns_resolver_set_dnssec(r, false);
00634         ldns_resolver_set_dnssec_cd(r, false);
00635         ldns_resolver_set_dnssec_anchors(r, NULL);
00636         ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY);
00637         ldns_resolver_set_igntc(r, false);
00638         ldns_resolver_set_recursive(r, false);
00639         ldns_resolver_set_dnsrch(r, true);
00640         ldns_resolver_set_source(r, NULL);
00641 
00642         /* randomize the nameserver to be queried
00643          * when there are multiple
00644          */
00645         ldns_resolver_set_random(r, true);
00646 
00647         ldns_resolver_set_debug(r, 0);
00648 
00649         r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
00650         r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
00651 
00652         /* TODO: fd=0 is actually a valid socket (stdin),
00653            replace with -1 */
00654         r->_socket = 0;
00655         r->_axfr_soa_count = 0;
00656         r->_axfr_i = 0;
00657         r->_cur_axfr_pkt = NULL;
00658 
00659         r->_tsig_keyname = NULL;
00660         r->_tsig_keydata = NULL;
00661         r->_tsig_algorithm = NULL;
00662         return r;
00663 }
00664 
00665 ldns_status
00666 ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp)
00667 {
00668         return ldns_resolver_new_frm_fp_l(res, fp, NULL);
00669 }
00670 
00671 ldns_status
00672 ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
00673 {
00674         ldns_resolver *r;
00675         const char *keyword[LDNS_RESOLV_KEYWORDS];
00676         char word[LDNS_MAX_LINELEN + 1];
00677         int8_t expect;
00678         uint8_t i;
00679         ldns_rdf *tmp;
00680 #ifdef HAVE_SSL
00681         ldns_rr *tmp_rr;
00682 #endif
00683         ssize_t gtr, bgtr;
00684         ldns_buffer *b;
00685         int lnr = 0, oldline;
00686         FILE* myfp = fp;
00687         if(!line_nr) line_nr = &lnr;
00688 
00689         if(!fp) {
00690                 myfp = fopen("/etc/resolv.conf", "r");
00691                 if(!myfp)
00692                         return LDNS_STATUS_FILE_ERR;
00693         }
00694 
00695         /* do this better
00696          * expect =
00697          * 0: keyword
00698          * 1: default domain dname
00699          * 2: NS aaaa or a record
00700          */
00701 
00702         /* recognized keywords */
00703         keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
00704         keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
00705         keyword[LDNS_RESOLV_SEARCH] = "search";
00706         /* these two are read but not used atm TODO */
00707         keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
00708         keyword[LDNS_RESOLV_OPTIONS] = "options";
00709         keyword[LDNS_RESOLV_ANCHOR] = "anchor";
00710         expect = LDNS_RESOLV_KEYWORD;
00711 
00712         r = ldns_resolver_new();
00713         if (!r) {
00714                 if(!fp) fclose(myfp);
00715                 return LDNS_STATUS_MEM_ERR;
00716         }
00717 
00718         gtr = 1;
00719         word[0] = 0;
00720         oldline = *line_nr;
00721         expect = LDNS_RESOLV_KEYWORD;
00722         while (gtr > 0) {
00723                 /* check comments */
00724                 if (word[0] == '#') {
00725                         word[0]='x';
00726                         if(oldline == *line_nr) {
00727                                 /* skip until end of line */
00728                                 int c;
00729                                 do {
00730                                         c = fgetc(myfp);
00731                                 } while(c != EOF && c != '\n');
00732                                 if(c=='\n') (*line_nr)++;
00733                         }
00734                         /* and read next to prepare for further parsing */
00735                         oldline = *line_nr;
00736                         continue;
00737                 }
00738                 oldline = *line_nr;
00739                 switch(expect) {
00740                         case LDNS_RESOLV_KEYWORD:
00741                                 /* keyword */
00742                                 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
00743                                 if (gtr != 0) {
00744                                         if(word[0] == '#') continue;
00745                                         for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
00746                                                 if (strcasecmp(keyword[i], word) == 0) {
00747                                                         /* chosen the keyword and
00748                                                          * expect values carefully
00749                                                          */
00750                                                         expect = i;
00751                                                         break;
00752                                                 }
00753                                         }
00754                                         /* no keyword recognized */
00755                                         if (expect == LDNS_RESOLV_KEYWORD) {
00756                                                 /* skip line */
00757                                                 /*
00758                                                 ldns_resolver_deep_free(r);
00759                                                 if(!fp) fclose(myfp);
00760                                                 return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
00761                                                 */
00762                                         }
00763                                 }
00764                                 break;
00765                         case LDNS_RESOLV_DEFDOMAIN:
00766                                 /* default domain dname */
00767                                 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
00768                                 if (gtr == 0) {
00769                                         if(!fp) fclose(myfp);
00770                                         return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
00771                                 }
00772                                 if(word[0] == '#') {
00773                                         expect = LDNS_RESOLV_KEYWORD;
00774                                         continue;
00775                                 }
00776                                 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
00777                                 if (!tmp) {
00778                                         ldns_resolver_deep_free(r);
00779                                         if(!fp) fclose(myfp);
00780                                         return LDNS_STATUS_SYNTAX_DNAME_ERR;
00781                                 }
00782 
00783                                 /* DOn't free, because we copy the pointer */
00784                                 ldns_resolver_set_domain(r, tmp);
00785                                 expect = LDNS_RESOLV_KEYWORD;
00786                                 break;
00787                         case LDNS_RESOLV_NAMESERVER:
00788                                 /* NS aaaa or a record */
00789                                 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
00790                                 if (gtr == 0) {
00791                                         if(!fp) fclose(myfp);
00792                                         return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
00793                                 }
00794                                 if(word[0] == '#') {
00795                                         expect = LDNS_RESOLV_KEYWORD;
00796                                         continue;
00797                                 }
00798                                 if(strchr(word, '%')) {
00799                                         /* snip off interface labels,
00800                                          * fe80::222:19ff:fe31:4222%eth0 */
00801                                         strchr(word, '%')[0]=0;
00802                                 }
00803                                 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
00804                                 if (!tmp) {
00805                                         /* try ip4 */
00806                                         tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
00807                                 }
00808                                 /* could not parse it, exit */
00809                                 if (!tmp) {
00810                                         ldns_resolver_deep_free(r);
00811                                         if(!fp) fclose(myfp);
00812                                         return LDNS_STATUS_SYNTAX_ERR;
00813                                 }
00814                                 (void)ldns_resolver_push_nameserver(r, tmp);
00815                                 ldns_rdf_deep_free(tmp);
00816                                 expect = LDNS_RESOLV_KEYWORD;
00817                                 break;
00818                         case LDNS_RESOLV_SEARCH:
00819                                 /* search list domain dname */
00820                                 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
00821                                 b = LDNS_MALLOC(ldns_buffer);
00822                                 if(!b) {
00823                                         ldns_resolver_deep_free(r);
00824                                         if(!fp) fclose(myfp);
00825                                         return LDNS_STATUS_MEM_ERR;
00826                                 }
00827 
00828                                 ldns_buffer_new_frm_data(b, word, (size_t) gtr);
00829                                 if(ldns_buffer_status(b) != LDNS_STATUS_OK) {
00830                                         LDNS_FREE(b);
00831                                         ldns_resolver_deep_free(r);
00832                                         if(!fp) fclose(myfp);
00833                                         return LDNS_STATUS_MEM_ERR;
00834                                 }
00835                                 bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1);
00836                                 while (bgtr > 0) {
00837                                         gtr -= bgtr;
00838                                         if(word[0] == '#') {
00839                                                 expect = LDNS_RESOLV_KEYWORD;
00840                                                 break;
00841                                         }
00842                                         tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
00843                                         if (!tmp) {
00844                                                 ldns_resolver_deep_free(r);
00845                                                 ldns_buffer_free(b);
00846                                                 if(!fp) fclose(myfp);
00847                                                 return LDNS_STATUS_SYNTAX_DNAME_ERR;
00848                                         }
00849 
00850                                         ldns_resolver_push_searchlist(r, tmp);
00851 
00852                                         ldns_rdf_deep_free(tmp);
00853                                         bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
00854                                             (size_t) gtr + 1);
00855                                 }
00856                                 ldns_buffer_free(b);
00857                                 if (expect != LDNS_RESOLV_KEYWORD) {
00858                                         gtr = 1;
00859                                         expect = LDNS_RESOLV_KEYWORD;
00860                                 }
00861                                 break;
00862                         case LDNS_RESOLV_SORTLIST:
00863                                 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
00864                                 /* sortlist not implemented atm */
00865                                 expect = LDNS_RESOLV_KEYWORD;
00866                                 break;
00867                         case LDNS_RESOLV_OPTIONS:
00868                                 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
00869                                 /* options not implemented atm */
00870                                 expect = LDNS_RESOLV_KEYWORD;
00871                                 break;
00872                         case LDNS_RESOLV_ANCHOR:
00873                                 /* a file containing a DNSSEC trust anchor */
00874                                 gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
00875                                 if (gtr == 0) {
00876                                         ldns_resolver_deep_free(r);
00877                                         if(!fp) fclose(myfp);
00878                                         return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
00879                                 }
00880                                 if(word[0] == '#') {
00881                                         expect = LDNS_RESOLV_KEYWORD;
00882                                         continue;
00883                                 }
00884 
00885 #ifdef HAVE_SSL
00886                                 tmp_rr = ldns_read_anchor_file(word);
00887                                 (void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
00888                                 ldns_rr_free(tmp_rr);
00889 #endif
00890                                 expect = LDNS_RESOLV_KEYWORD;
00891                                 break;
00892                 }
00893         }
00894 
00895         if(!fp)
00896                 fclose(myfp);
00897 
00898         if (res) {
00899                 *res = r;
00900                 return LDNS_STATUS_OK;
00901         } else {
00902                 ldns_resolver_deep_free(r);
00903                 return LDNS_STATUS_NULL;
00904         }
00905 }
00906 
00907 ldns_status
00908 ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
00909 {
00910         ldns_resolver *r;
00911         FILE *fp;
00912         ldns_status s;
00913 
00914         if (!filename) {
00915                 fp = fopen(LDNS_RESOLV_CONF, "r");
00916 
00917         } else {
00918                 fp = fopen(filename, "r");
00919         }
00920         if (!fp) {
00921                 return LDNS_STATUS_FILE_ERR;
00922         }
00923 
00924         s = ldns_resolver_new_frm_fp(&r, fp);
00925         fclose(fp);
00926         if (s == LDNS_STATUS_OK) {
00927                 if (res) {
00928                         *res = r;
00929                         return LDNS_STATUS_OK;
00930                 } else  {
00931                         ldns_resolver_free(r);
00932                         return LDNS_STATUS_NULL;
00933                 }
00934         }
00935         return s;
00936 }
00937 
00938 void
00939 ldns_resolver_free(ldns_resolver *res)
00940 {
00941         LDNS_FREE(res);
00942 }
00943 
00944 void
00945 ldns_resolver_deep_free(ldns_resolver *res)
00946 {
00947         size_t i;
00948 
00949         if (res) {
00950                 if (res->_searchlist) {
00951                         for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
00952                                 ldns_rdf_deep_free(res->_searchlist[i]);
00953                         }
00954                         LDNS_FREE(res->_searchlist);
00955                 }
00956                 if (res->_nameservers) {
00957                         for (i = 0; i < res->_nameserver_count; i++) {
00958                                 ldns_rdf_deep_free(res->_nameservers[i]);
00959                         }
00960                         LDNS_FREE(res->_nameservers);
00961                 }
00962                 if (ldns_resolver_domain(res)) {
00963                         ldns_rdf_deep_free(ldns_resolver_domain(res));
00964                 }
00965                 if (res->_tsig_keyname) {
00966                         LDNS_FREE(res->_tsig_keyname);
00967                 }
00968                 if (res->_tsig_keydata) {
00969                         LDNS_FREE(res->_tsig_keydata);
00970                 }
00971                 if (res->_tsig_algorithm) {
00972                         LDNS_FREE(res->_tsig_algorithm);
00973                 }
00974 
00975                 if (res->_cur_axfr_pkt) {
00976                         ldns_pkt_free(res->_cur_axfr_pkt);
00977                 }
00978 
00979                 if (res->_rtt) {
00980                         LDNS_FREE(res->_rtt);
00981                 }
00982                 if (res->_dnssec_anchors) {
00983                         ldns_rr_list_deep_free(res->_dnssec_anchors);
00984                 }
00985                 LDNS_FREE(res);
00986         }
00987 }
00988 
00989 ldns_status
00990 ldns_resolver_search_status(ldns_pkt** pkt,
00991                 ldns_resolver *r, const  ldns_rdf *name,
00992                 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
00993 {
00994         ldns_rdf *new_name;
00995         ldns_rdf **search_list;
00996         size_t i;
00997         ldns_status s = LDNS_STATUS_OK;
00998 
00999         if (ldns_dname_absolute(name)) {
01000                 /* query as-is */
01001                 return ldns_resolver_query_status(pkt, r, name, t, c, flags);
01002         } else if (ldns_resolver_dnsrch(r)) {
01003                 search_list = ldns_resolver_searchlist(r);
01004                 for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
01005                         new_name = ldns_dname_cat_clone(name, search_list[i]);
01006 
01007                         s = ldns_resolver_query_status(pkt, r,
01008                                         new_name, t, c, flags);
01009                         ldns_rdf_free(new_name);
01010                         if (pkt) {
01011                                 if (s == LDNS_STATUS_OK && *pkt &&
01012                                                 ldns_pkt_get_rcode(*pkt) ==
01013                                                 LDNS_RCODE_NOERROR) {
01014                                         return LDNS_STATUS_OK;
01015                                 }
01016                                 ldns_pkt_free(*pkt);
01017                         }
01018                 }
01019         }
01020         return s;
01021 }
01022 
01023 ldns_pkt *
01024 ldns_resolver_search(const ldns_resolver *r,const  ldns_rdf *name,
01025         ldns_rr_type t, ldns_rr_class c, uint16_t flags)
01026 {
01027         ldns_pkt* pkt = NULL;
01028         if (ldns_resolver_search_status(&pkt, (ldns_resolver *)r,
01029                                 name, t, c, flags) != LDNS_STATUS_OK) {
01030                 ldns_pkt_free(pkt);
01031         }
01032         return pkt;
01033 }
01034 
01035 ldns_status
01036 ldns_resolver_query_status(ldns_pkt** pkt,
01037                 ldns_resolver *r, const ldns_rdf *name,
01038                 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
01039 {
01040         ldns_rdf *newname;
01041         ldns_status status;
01042 
01043         if (!ldns_resolver_defnames(r) || !ldns_resolver_domain(r)) {
01044                 return ldns_resolver_send(pkt, r, name, t, c, flags);
01045         }
01046 
01047         newname = ldns_dname_cat_clone(name, ldns_resolver_domain(r));
01048         if (!newname) {
01049                 return LDNS_STATUS_MEM_ERR;
01050         }
01051         status = ldns_resolver_send(pkt, r, newname, t, c, flags);
01052         ldns_rdf_free(newname);
01053         return status;
01054 }
01055 
01056 ldns_pkt *
01057 ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name,
01058         ldns_rr_type t, ldns_rr_class c, uint16_t flags)
01059 {
01060         ldns_pkt* pkt = NULL;
01061         if (ldns_resolver_query_status(&pkt, (ldns_resolver *)r,
01062                                 name, t, c, flags) != LDNS_STATUS_OK) {
01063                 ldns_pkt_free(pkt);
01064         }
01065         return pkt;
01066 }
01067 
01068 static size_t *
01069 ldns_resolver_backup_rtt(ldns_resolver *r)
01070 {
01071         size_t *new_rtt;
01072         size_t *old_rtt = ldns_resolver_rtt(r);
01073 
01074         if (old_rtt && ldns_resolver_nameserver_count(r)) {
01075                 new_rtt = LDNS_XMALLOC(size_t
01076                                 , ldns_resolver_nameserver_count(r));
01077                 memcpy(new_rtt, old_rtt, sizeof(size_t)
01078                                 * ldns_resolver_nameserver_count(r));
01079                 ldns_resolver_set_rtt(r, new_rtt);
01080                 return old_rtt;
01081         }
01082         return NULL;
01083 }
01084 
01085 static void
01086 ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt)
01087 {
01088         size_t *cur_rtt = ldns_resolver_rtt(r);
01089 
01090         if (cur_rtt) {
01091                 LDNS_FREE(cur_rtt);
01092         }
01093         ldns_resolver_set_rtt(r, old_rtt);
01094 }
01095 
01096 ldns_status
01097 ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r,
01098                                    ldns_pkt *query_pkt)
01099 {
01100         ldns_pkt *answer_pkt = NULL;
01101         ldns_status stat = LDNS_STATUS_OK;
01102         size_t *rtt;
01103 
01104         stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt);
01105         if (stat != LDNS_STATUS_OK) {
01106                 if(answer_pkt) {
01107                         ldns_pkt_free(answer_pkt);
01108                         answer_pkt = NULL;
01109                 }
01110         } else {
01111                 /* if tc=1 fall back to EDNS and/or TCP */
01112                 /* check for tcp first (otherwise we don't care about tc=1) */
01113                 if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) {
01114                         if (ldns_pkt_tc(answer_pkt)) {
01115                                 /* was EDNS0 set? */
01116                                 if (ldns_pkt_edns_udp_size(query_pkt) == 0) {
01117                                         ldns_pkt_set_edns_udp_size(query_pkt
01118                                                         , 4096);
01119                                         ldns_pkt_free(answer_pkt);
01120                                         /* Nameservers should not become 
01121                                          * unreachable because fragments are
01122                                          * dropped (network error). We might
01123                                          * still have success with TCP.
01124                                          * Therefore maintain reachability
01125                                          * statuses of the nameservers by
01126                                          * backup and restore the rtt list.
01127                                          */
01128                                         rtt = ldns_resolver_backup_rtt(r);
01129                                         stat = ldns_send(&answer_pkt, r
01130                                                         , query_pkt);
01131                                         ldns_resolver_restore_rtt(r, rtt);
01132                                 }
01133                                 /* either way, if it is still truncated, use TCP */
01134                                 if (stat != LDNS_STATUS_OK ||
01135                                     ldns_pkt_tc(answer_pkt)) {
01136                                         ldns_resolver_set_usevc(r, true);
01137                                         ldns_pkt_free(answer_pkt);
01138                                         stat = ldns_send(&answer_pkt, r, query_pkt);
01139                                         ldns_resolver_set_usevc(r, false);
01140                                 }
01141                         }
01142                 }
01143         }
01144 
01145         if (answer) {
01146                 *answer = answer_pkt;
01147         }
01148 
01149         return stat;
01150 }
01151 
01152 ldns_status
01153 ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r,
01154                                 const ldns_rdf *name, ldns_rr_type t,
01155                                 ldns_rr_class c, uint16_t flags)
01156 {
01157         struct timeval now;
01158 
01159         /* prepare a question pkt from the parameters
01160          * and then send this */
01161         if (t == LDNS_RR_TYPE_IXFR) {
01162                 *query_pkt = ldns_pkt_ixfr_request_new(ldns_rdf_clone(name),
01163                         c, flags, NULL);
01164         } else {
01165                 *query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags);
01166         }
01167         if (!*query_pkt) {
01168                 return LDNS_STATUS_ERR;
01169         }
01170 
01171         /* set DO bit if necessary */
01172         if (ldns_resolver_dnssec(r)) {
01173                 if (ldns_resolver_edns_udp_size(r) == 0) {
01174                         ldns_resolver_set_edns_udp_size(r, 4096);
01175                 }
01176                 ldns_pkt_set_edns_do(*query_pkt, true);
01177                 if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) {
01178                         ldns_pkt_set_cd(*query_pkt, true);
01179                 }
01180         }
01181 
01182         /* transfer the udp_edns_size from the resolver to the packet */
01183         if (ldns_resolver_edns_udp_size(r) != 0) {
01184                 ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r));
01185         }
01186 
01187         /* set the timestamp */
01188         now.tv_sec = time(NULL);
01189         now.tv_usec = 0;
01190         ldns_pkt_set_timestamp(*query_pkt, now);
01191 
01192 
01193         if (ldns_resolver_debug(r)) {
01194                 ldns_pkt_print(stdout, *query_pkt);
01195         }
01196 
01197         /* only set the id if it is not set yet */
01198         if (ldns_pkt_id(*query_pkt) == 0) {
01199                 ldns_pkt_set_random_id(*query_pkt);
01200         }
01201 
01202         return LDNS_STATUS_OK;
01203 }
01204 
01205 
01206 ldns_status
01207 ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name,
01208                 ldns_rr_type t, ldns_rr_class c, uint16_t flags)
01209 {
01210         ldns_pkt *query_pkt;
01211         ldns_pkt *answer_pkt;
01212         ldns_status status;
01213 
01214         assert(r != NULL);
01215         assert(name != NULL);
01216 
01217         answer_pkt = NULL;
01218 
01219         /* do all the preprocessing here, then fire of an query to
01220          * the network */
01221 
01222         if (0 == t) {
01223                 t= LDNS_RR_TYPE_A;
01224         }
01225         if (0 == c) {
01226                 c= LDNS_RR_CLASS_IN;
01227         }
01228         if (0 == ldns_resolver_nameserver_count(r)) {
01229                 return LDNS_STATUS_RES_NO_NS;
01230         }
01231         if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
01232                 return LDNS_STATUS_RES_QUERY;
01233         }
01234 
01235         status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name,
01236                                                  t, c, flags);
01237         if (status != LDNS_STATUS_OK) {
01238                 return status;
01239         }
01240 
01241         /* if tsig values are set, tsign it */
01242         /* TODO: make last 3 arguments optional too? maybe make complete
01243                  rr instead of separate values in resolver (and packet)
01244           Jelte
01245           should this go in pkt_prepare?
01246         */
01247         if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
01248 #ifdef HAVE_SSL
01249                 status = ldns_pkt_tsig_sign(query_pkt,
01250                                             ldns_resolver_tsig_keyname(r),
01251                                             ldns_resolver_tsig_keydata(r),
01252                                             300, ldns_resolver_tsig_algorithm(r), NULL);
01253                 if (status != LDNS_STATUS_OK) {
01254                         ldns_pkt_free(query_pkt);
01255                         return LDNS_STATUS_CRYPTO_TSIG_ERR;
01256                 }
01257 #else
01258                 ldns_pkt_free(query_pkt);
01259                 return LDNS_STATUS_CRYPTO_TSIG_ERR;
01260 #endif /* HAVE_SSL */
01261         }
01262 
01263         status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
01264         ldns_pkt_free(query_pkt);
01265 
01266         /* allows answer to be NULL when not interested in return value */
01267         if (answer) {
01268                 *answer = answer_pkt;
01269         }
01270         return status;
01271 }
01272 
01273 ldns_rr *
01274 ldns_axfr_next(ldns_resolver *resolver)
01275 {
01276         ldns_rr *cur_rr;
01277         uint8_t *packet_wire;
01278         size_t packet_wire_size;
01279         ldns_lookup_table *rcode;
01280         ldns_status status;
01281 
01282         /* check if start() has been called */
01283         if (!resolver || resolver->_socket == 0) {
01284                 return NULL;
01285         }
01286 
01287         if (resolver->_cur_axfr_pkt) {
01288                 if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) {
01289                         ldns_pkt_free(resolver->_cur_axfr_pkt);
01290                         resolver->_cur_axfr_pkt = NULL;
01291                         return ldns_axfr_next(resolver);
01292                 }
01293                 cur_rr = ldns_rr_clone(ldns_rr_list_rr(
01294                                         ldns_pkt_answer(resolver->_cur_axfr_pkt),
01295                                         resolver->_axfr_i));
01296                 resolver->_axfr_i++;
01297                 if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
01298                         resolver->_axfr_soa_count++;
01299                         if (resolver->_axfr_soa_count >= 2) {
01300 #ifndef USE_WINSOCK
01301                                 close(resolver->_socket);
01302 #else
01303                                 closesocket(resolver->_socket);
01304 #endif
01305                                 resolver->_socket = 0;
01306                                 ldns_pkt_free(resolver->_cur_axfr_pkt);
01307                                 resolver->_cur_axfr_pkt = NULL;
01308                         }
01309                 }
01310                 return cur_rr;
01311         } else {
01312                 packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size);
01313                 if(!packet_wire)
01314                         return NULL;
01315 
01316                 status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire,
01317                                      packet_wire_size);
01318                 LDNS_FREE(packet_wire);
01319 
01320                 resolver->_axfr_i = 0;
01321                 if (status != LDNS_STATUS_OK) {
01322                         /* TODO: make status return type of this function (...api change) */
01323 #ifdef STDERR_MSGS
01324                         fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status));
01325 #endif
01326 
01327                         /* we must now also close the socket, otherwise subsequent uses of the
01328                            same resolver structure will fail because the link is still open or
01329                            in an undefined state */
01330 #ifndef USE_WINSOCK
01331                         close(resolver->_socket);
01332 #else
01333                         closesocket(resolver->_socket);
01334 #endif
01335                         resolver->_socket = 0;
01336 
01337                         return NULL;
01338                 } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
01339                         rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt));
01340 #ifdef STDERR_MSGS
01341                         if (rcode) {
01342                                 fprintf(stderr, "Error in AXFR: %s\n", 
01343                                                 rcode->name);
01344                         } else {
01345                                 fprintf(stderr, "Error in AXFR: %d\n", 
01346                                                 (int) ldns_pkt_get_rcode(
01347                                                 resolver->_cur_axfr_pkt));
01348                         }
01349 #endif
01350 
01351                         /* we must now also close the socket, otherwise subsequent uses of the
01352                            same resolver structure will fail because the link is still open or
01353                            in an undefined state */
01354 #ifndef USE_WINSOCK
01355                         close(resolver->_socket);
01356 #else
01357                         closesocket(resolver->_socket);
01358 #endif
01359                         resolver->_socket = 0;
01360 
01361                         return NULL;
01362                 } else {
01363                         return ldns_axfr_next(resolver);
01364                 }
01365 
01366         }
01367 
01368 }
01369 
01370 /* this function is needed to abort a transfer that is in progress;
01371  * without it an aborted transfer will lead to the AXFR code in the
01372  * library staying in an indetermined state because the socket for the
01373  * AXFR is never closed
01374  */
01375 void
01376 ldns_axfr_abort(ldns_resolver *resolver)
01377 {
01378         /* Only abort if an actual AXFR is in progress */
01379         if (resolver->_socket != 0)
01380         {
01381 #ifndef USE_WINSOCK
01382                 close(resolver->_socket);
01383 #else
01384                 closesocket(resolver->_socket);
01385 #endif
01386                 resolver->_socket = 0;
01387         }
01388 }
01389 
01390 bool
01391 ldns_axfr_complete(const ldns_resolver *res)
01392 {
01393         /* complete when soa count is 2? */
01394         return res->_axfr_soa_count == 2;
01395 }
01396 
01397 ldns_pkt *
01398 ldns_axfr_last_pkt(const ldns_resolver *res)
01399 {
01400         return res->_cur_axfr_pkt;
01401 }
01402 
01403 /* random isn't really that good */
01404 void
01405 ldns_resolver_nameservers_randomize(ldns_resolver *r)
01406 {
01407         uint16_t i, j;
01408         ldns_rdf **ns, *tmpns;
01409         size_t *rtt, tmprtt;
01410 
01411         /* should I check for ldns_resolver_random?? */
01412         assert(r != NULL);
01413 
01414         ns = ldns_resolver_nameservers(r);
01415         rtt = ldns_resolver_rtt(r);
01416         for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
01417                 j = ldns_get_random() % ldns_resolver_nameserver_count(r);
01418                 tmpns = ns[i];
01419                 ns[i] = ns[j];
01420                 ns[j] = tmpns;
01421                 tmprtt = rtt[i];
01422                 rtt[i] = rtt[j];
01423                 rtt[j] = tmprtt;
01424         }
01425         ldns_resolver_set_nameservers(r, ns);
01426 }
01427