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

Generated on 20 Mar 2013 for ldns by  doxygen 1.4.7