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

Generated on Thu Apr 5 23:03:55 2012 for ldns by  doxygen 1.4.7