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 uint8_t
00048 ldns_resolver_ip6(const ldns_resolver *r)
00049 {
00050         return r->_ip6;
00051 }
00052 
00053 bool
00054 ldns_resolver_recursive(const ldns_resolver *r)
00055 {
00056         return r->_recursive;
00057 }
00058 
00059 bool
00060 ldns_resolver_debug(const ldns_resolver *r)
00061 {
00062         return r->_debug;
00063 }
00064 
00065 bool
00066 ldns_resolver_dnsrch(const ldns_resolver *r)
00067 {
00068         return r->_dnsrch;
00069 }
00070 
00071 bool
00072 ldns_resolver_fail(const ldns_resolver *r)
00073 {
00074         return r->_fail;
00075 }
00076 
00077 bool
00078 ldns_resolver_defnames(const ldns_resolver *r)
00079 {
00080         return r->_defnames;
00081 }
00082 
00083 ldns_rdf *
00084 ldns_resolver_domain(const ldns_resolver *r)
00085 {
00086         return r->_domain;
00087 }
00088 
00089 ldns_rdf **
00090 ldns_resolver_searchlist(const ldns_resolver *r)
00091 {
00092         return r->_searchlist;
00093 }
00094 
00095 ldns_rdf **
00096 ldns_resolver_nameservers(const ldns_resolver *r)
00097 {
00098         return r->_nameservers;
00099 }
00100 
00101 size_t
00102 ldns_resolver_nameserver_count(const ldns_resolver *r)
00103 {
00104         return r->_nameserver_count;
00105 }
00106 
00107 bool
00108 ldns_resolver_dnssec(const ldns_resolver *r)
00109 {
00110         return r->_dnssec;
00111 }
00112 
00113 bool
00114 ldns_resolver_dnssec_cd(const ldns_resolver *r)
00115 {
00116         return r->_dnssec_cd;
00117 }
00118 
00119 bool
00120 ldns_resolver_igntc(const ldns_resolver *r)
00121 {
00122         return r->_igntc;
00123 }
00124 
00125 bool
00126 ldns_resolver_usevc(const ldns_resolver *r)
00127 {
00128         return r->_usevc;
00129 }
00130 
00131 size_t *
00132 ldns_resolver_rtt(const ldns_resolver *r)
00133 {
00134         return r->_rtt;
00135 }
00136 
00137 size_t
00138 ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos)
00139 {
00140         size_t *rtt;
00141 
00142         assert(r != NULL);
00143         
00144         rtt = ldns_resolver_rtt(r);
00145         
00146         if (pos >= ldns_resolver_nameserver_count(r)) {
00147                 /* error ?*/
00148                 return 0;
00149         } else {
00150                 return rtt[pos];
00151         }
00152 
00153 }
00154 
00155 struct timeval
00156 ldns_resolver_timeout(const ldns_resolver *r)
00157 {
00158         return r->_timeout;
00159 } 
00160 
00161 char *
00162 ldns_resolver_tsig_keyname(const ldns_resolver *r)
00163 {
00164         return r->_tsig_keyname;
00165 }
00166 
00167 char *
00168 ldns_resolver_tsig_algorithm(const ldns_resolver *r)
00169 {
00170         return r->_tsig_algorithm;
00171 }
00172 
00173 char *
00174 ldns_resolver_tsig_keydata(const ldns_resolver *r)
00175 {
00176         return r->_tsig_keydata;
00177 }
00178 
00179 bool
00180 ldns_resolver_random(const ldns_resolver *r)
00181 {
00182         return r->_random;
00183 }
00184 
00185 size_t
00186 ldns_resolver_searchlist_count(const ldns_resolver *r)
00187 {
00188         return r->_searchlist_count;
00189 }
00190 
00191 /* write */
00192 void
00193 ldns_resolver_set_port(ldns_resolver *r, uint16_t p)
00194 {
00195         r->_port = p;
00196 }
00197 
00198 ldns_rdf *
00199 ldns_resolver_pop_nameserver(ldns_resolver *r)
00200 {
00201         ldns_rdf **nameservers;
00202         ldns_rdf *pop;
00203         size_t ns_count;
00204         size_t *rtt;
00205 
00206         assert(r != NULL);
00207 
00208         ns_count = ldns_resolver_nameserver_count(r);
00209         nameservers = ldns_resolver_nameservers(r);
00210         rtt = ldns_resolver_rtt(r);
00211         if (ns_count == 0 || !nameservers) {
00212                 return NULL;
00213         }
00214         
00215         pop = nameservers[ns_count - 1];
00216 
00217         nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count - 1));
00218         rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1));
00219 
00220         ldns_resolver_set_nameservers(r, nameservers);
00221         ldns_resolver_set_rtt(r, rtt);
00222         /* decr the count */
00223         ldns_resolver_dec_nameserver_count(r);
00224         return pop;
00225 }
00226 
00227 ldns_status
00228 ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n)
00229 {
00230         ldns_rdf **nameservers;
00231         size_t ns_count;
00232         size_t *rtt;
00233 
00234         if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A &&
00235                         ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) {
00236                 return LDNS_STATUS_ERR;
00237         }
00238 
00239         ns_count = ldns_resolver_nameserver_count(r);
00240         nameservers = ldns_resolver_nameservers(r);
00241         rtt = ldns_resolver_rtt(r);
00242 
00243         /* make room for the next one */
00244         nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1));
00245         /* don't forget the rtt */
00246         rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1));
00247         
00248         /* set the new value in the resolver */
00249         ldns_resolver_set_nameservers(r, nameservers);
00250 
00251         /* slide n in its slot. */
00252         /* we clone it here, because then we can free the original
00253          * rr's where it stood */
00254         nameservers[ns_count] = ldns_rdf_clone(n);
00255         rtt[ns_count] = LDNS_RESOLV_RTT_MIN;
00256         ldns_resolver_incr_nameserver_count(r);
00257         ldns_resolver_set_rtt(r, rtt);
00258         return LDNS_STATUS_OK;
00259 }
00260 
00261 ldns_status
00262 ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr)
00263 {
00264         ldns_rdf *address;
00265         if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A &&
00266                         ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) {
00267                 return LDNS_STATUS_ERR;
00268         }
00269         address = ldns_rr_rdf(rr, 0); /* extract the ip number */
00270         if (address) {
00271                 return ldns_resolver_push_nameserver(r, address);
00272         } else {
00273                 return LDNS_STATUS_ERR;
00274         }
00275 }
00276 
00277 ldns_status
00278 ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist)
00279 {
00280         ldns_rr *rr;
00281         ldns_status stat;
00282         size_t i;
00283 
00284         stat = LDNS_STATUS_OK;
00285         if (rrlist) {
00286                 for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
00287                         rr = ldns_rr_list_rr(rrlist, i);
00288                         if (ldns_resolver_push_nameserver_rr(r, rr) != LDNS_STATUS_OK) {
00289                                 stat = LDNS_STATUS_ERR;
00290                         }
00291                 }
00292                 return stat;
00293         } else {
00294                 return LDNS_STATUS_ERR;
00295         }
00296 }
00297 
00298 void
00299 ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s)
00300 {
00301                 r->_edns_udp_size = s;
00302 }
00303 
00304 void
00305 ldns_resolver_set_recursive(ldns_resolver *r, bool re)
00306 {
00307         r->_recursive = re;
00308 }
00309 
00310 void
00311 ldns_resolver_set_dnssec(ldns_resolver *r, bool d)
00312 {
00313         r->_dnssec = d;
00314 }
00315 
00316 void
00317 ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d)
00318 {
00319         r->_dnssec_cd = d;
00320 }
00321 
00322 void
00323 ldns_resolver_set_igntc(ldns_resolver *r, bool i)
00324 {
00325         r->_igntc = i;
00326 }
00327 
00328 void
00329 ldns_resolver_set_usevc(ldns_resolver *r, bool vc)
00330 {
00331         r->_usevc = vc;
00332 }
00333 
00334 void
00335 ldns_resolver_set_debug(ldns_resolver *r, bool d)
00336 {
00337         r->_debug = d;
00338 }
00339 
00340 void
00341 ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6)
00342 {
00343         r->_ip6 = ip6;
00344 }
00345 
00346 void
00347 ldns_resolver_set_fail(ldns_resolver *r, bool f)
00348 {
00349         r->_fail =f;
00350 }
00351 
00352 void
00353 ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c)
00354 {
00355         r->_searchlist_count = c;
00356 }
00357 
00358 void
00359 ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c)
00360 {
00361         r->_nameserver_count = c;
00362 }
00363 
00364 void
00365 ldns_resolver_set_dnsrch(ldns_resolver *r, bool d)
00366 {
00367         r->_dnsrch = d;
00368 }
00369 
00370 void
00371 ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry)
00372 {
00373         r->_retry = retry;
00374 }
00375 
00376 void
00377 ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans)
00378 {
00379         r->_retrans = retrans;
00380 }
00381 
00382 void
00383 ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n)
00384 {
00385         r->_nameservers = n;
00386 }
00387 
00388 void
00389 ldns_resolver_set_defnames(ldns_resolver *r, bool d)
00390 {
00391         r->_defnames = d;
00392 }
00393 
00394 void
00395 ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt)
00396 {
00397         r->_rtt = rtt;
00398 }
00399 
00400 void
00401 ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value)
00402 {
00403         size_t *rtt;
00404 
00405         assert(r != NULL);
00406 
00407         rtt = ldns_resolver_rtt(r);
00408         
00409         if (pos >= ldns_resolver_nameserver_count(r)) {
00410                 /* error ?*/
00411         } else {
00412                 rtt[pos] = value;
00413         }
00414 
00415 }
00416 
00417 void
00418 ldns_resolver_incr_nameserver_count(ldns_resolver *r)
00419 {
00420         size_t c;
00421 
00422         c = ldns_resolver_nameserver_count(r);
00423         ldns_resolver_set_nameserver_count(r, ++c);
00424 }
00425 
00426 void
00427 ldns_resolver_dec_nameserver_count(ldns_resolver *r)
00428 {
00429         size_t c;
00430 
00431         c = ldns_resolver_nameserver_count(r);
00432         if (c == 0) {
00433                 return;
00434         } else {
00435                 ldns_resolver_set_nameserver_count(r, --c);
00436         }
00437 }
00438 
00439 void
00440 ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d)
00441 {
00442         r->_domain = d;
00443 }
00444 
00445 void
00446 ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout)
00447 {
00448         r->_timeout.tv_sec = timeout.tv_sec;
00449         r->_timeout.tv_usec = timeout.tv_usec;
00450 }
00451 
00452 void
00453 ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d)
00454 {
00455         ldns_rdf **searchlist;
00456         size_t list_count;
00457 
00458         if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
00459                 return;
00460         }
00461 
00462         list_count = ldns_resolver_searchlist_count(r);
00463         searchlist = ldns_resolver_searchlist(r);
00464 
00465         searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1));
00466         if (searchlist) {
00467                 r->_searchlist = searchlist;
00468 
00469                 searchlist[list_count] = ldns_rdf_clone(d);
00470                 ldns_resolver_set_searchlist_count(r, list_count + 1);
00471         }
00472 }
00473 
00474 void
00475 ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname)
00476 {
00477         r->_tsig_keyname = tsig_keyname;
00478 }
00479 
00480 void
00481 ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm)
00482 {
00483         r->_tsig_algorithm = tsig_algorithm;
00484 }
00485 
00486 void
00487 ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata)
00488 {
00489         r->_tsig_keydata = tsig_keydata;
00490 }
00491 
00492 void
00493 ldns_resolver_set_random(ldns_resolver *r, bool b)
00494 {
00495         r->_random = b;
00496 }
00497 
00498 /* more sophisticated functions */
00499 ldns_resolver *
00500 ldns_resolver_new(void)
00501 {
00502         ldns_resolver *r;
00503 
00504         r = LDNS_MALLOC(ldns_resolver);
00505         if (!r) {
00506                 return NULL;
00507         }
00508 
00509         r->_searchlist = NULL;
00510         r->_nameservers = NULL;
00511         r->_rtt = NULL;
00512 
00513         /* defaults are filled out */
00514         ldns_resolver_set_searchlist_count(r, 0);
00515         ldns_resolver_set_nameserver_count(r, 0);
00516         ldns_resolver_set_usevc(r, 0);
00517         ldns_resolver_set_port(r, LDNS_PORT);
00518         ldns_resolver_set_domain(r, NULL);
00519         ldns_resolver_set_defnames(r, false);
00520         ldns_resolver_set_retry(r, 3);
00521         ldns_resolver_set_retrans(r, 2);
00522         ldns_resolver_set_fail(r, false);
00523         ldns_resolver_set_edns_udp_size(r, 0);
00524         ldns_resolver_set_dnssec(r, false);
00525         ldns_resolver_set_dnssec_cd(r, false);
00526         ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY);
00527 
00528         /* randomize the nameserver to be queried
00529          * when there are multiple
00530          */
00531         ldns_resolver_set_random(r, true);
00532 
00533         ldns_resolver_set_debug(r, 0);
00534         
00535         r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
00536         r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
00537 
00538         r->_socket = 0;
00539         r->_axfr_soa_count = 0;
00540         r->_axfr_i = 0;
00541         r->_cur_axfr_pkt = NULL;
00542         
00543         r->_tsig_keyname = NULL;
00544         r->_tsig_keydata = NULL;
00545         r->_tsig_algorithm = NULL;
00546         return r;
00547 }
00548 
00549 ldns_status
00550 ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp)
00551 {
00552         return ldns_resolver_new_frm_fp_l(res, fp, NULL);
00553 }
00554 
00555 ldns_status
00556 ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
00557 {
00558         ldns_resolver *r;
00559         const char *keyword[LDNS_RESOLV_KEYWORDS];
00560         char word[LDNS_MAX_LINELEN + 1];
00561         int8_t expect;
00562         uint8_t i;
00563         ldns_rdf *tmp;
00564         ssize_t gtr;
00565         ldns_buffer *b;
00566 
00567         /* do this better 
00568          * expect = 
00569          * 0: keyword
00570          * 1: default domain dname
00571          * 2: NS aaaa or a record
00572          */
00573 
00574         /* recognized keywords */
00575         keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
00576         keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
00577         keyword[LDNS_RESOLV_SEARCH] = "search";
00578         /* these two are read but not used atm TODO */
00579         keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
00580         keyword[LDNS_RESOLV_OPTIONS] = "options";
00581         expect = LDNS_RESOLV_KEYWORD;
00582 
00583         r = ldns_resolver_new();
00584         if (!r) {
00585                 return LDNS_STATUS_MEM_ERR;
00586         }
00587 
00588         gtr = 1;
00589         word[0] = 0;
00590         while (gtr > 0) {
00591                 /* check comments */
00592                 if (word[0] == '#') {
00593                         /* read the rest of the line, should be 1 word */
00594                         gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
00595                         /* prepare the next string for further parsing */
00596                         gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
00597                         continue;
00598                 }
00599                 switch(expect) {
00600                         case LDNS_RESOLV_KEYWORD:
00601                                 /* keyword */
00602                                 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
00603                                 if (gtr != 0) {
00604                                         for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
00605                                                 if (strcasecmp(keyword[i], word) == 0) {
00606                                                         /* chosen the keyword and
00607                                                          * expect values carefully
00608                                                          */
00609                                                         expect = i;
00610                                                         break;
00611                                                 }
00612                                         }
00613                                         if (word[0] == '#') {
00614                                                 /* skip the rest of the line*/
00615                                                 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
00616                                                 continue;
00617                                         }
00618                                         /* no keyword recognized */
00619                                         if (expect == LDNS_RESOLV_KEYWORD) {
00620                                                 ldns_resolver_deep_free(r);
00621                                                 return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
00622                                         }
00623                                 }
00624                                 break;
00625                         case LDNS_RESOLV_DEFDOMAIN:
00626                                 /* default domain dname */
00627                                 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
00628                                 if (gtr == 0) {
00629                                         return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
00630                                 }
00631                                 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
00632                                 if (!tmp) {
00633                                         ldns_resolver_deep_free(r);
00634                                         return LDNS_STATUS_SYNTAX_DNAME_ERR;
00635                                 }
00636 
00637                                 /* DOn't free, because we copy the pointer */
00638                                 ldns_resolver_set_domain(r, tmp);
00639                                 expect = LDNS_RESOLV_KEYWORD;
00640                                 break;
00641                         case LDNS_RESOLV_NAMESERVER:
00642                                 /* NS aaaa or a record */
00643                                 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
00644                                 if (gtr == 0) {
00645                                         return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
00646                                 }
00647                                 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
00648                                 if (!tmp) {
00649                                         /* try ip4 */
00650                                         tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
00651                                 }
00652                                 /* could not parse it, exit */
00653                                 if (!tmp) {
00654                                         ldns_resolver_deep_free(r);
00655                                         return LDNS_STATUS_SYNTAX_ERR;
00656                                 }
00657                                 (void)ldns_resolver_push_nameserver(r, tmp);
00658                                 ldns_rdf_deep_free(tmp);
00659                                 expect = LDNS_RESOLV_KEYWORD;
00660                                 break;
00661                         case LDNS_RESOLV_SEARCH:
00662                                 /* search list domain dname */
00663                                 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
00664                                 b = LDNS_MALLOC(ldns_buffer);
00665                                 ldns_buffer_new_frm_data(b, word, (size_t) gtr);
00666 
00667                                 gtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr);
00668                                 while (gtr > 0) {
00669                                         tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
00670                                         if (!tmp) {
00671                                                 ldns_resolver_deep_free(r);
00672                                                 return LDNS_STATUS_SYNTAX_DNAME_ERR;
00673                                         }
00674 
00675                                         ldns_resolver_push_searchlist(r, tmp); 
00676 
00677                                         ldns_rdf_deep_free(tmp);
00678                                         gtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr);
00679                                 }
00680                                 ldns_buffer_free(b);
00681                                 gtr = 1;
00682                                 expect = LDNS_RESOLV_KEYWORD;
00683                                 break;
00684                         case LDNS_RESOLV_SORTLIST:
00685                                 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
00686                                 /* sortlist not implemented atm */
00687                                 expect = LDNS_RESOLV_KEYWORD;
00688                                 break;
00689                         case LDNS_RESOLV_OPTIONS:
00690                                 gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
00691                                 /* options not implemented atm */
00692                                 expect = LDNS_RESOLV_KEYWORD;
00693                                 break;
00694                 }
00695         }
00696         
00697         if (res) {
00698                 *res = r;
00699                 return LDNS_STATUS_OK;
00700         } else {
00701                 return LDNS_STATUS_NULL;
00702         }
00703 }
00704 
00705 ldns_status
00706 ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
00707 {
00708         ldns_resolver *r;
00709         FILE *fp;
00710         ldns_status s;
00711 
00712         if (!filename) {
00713                 fp = fopen(LDNS_RESOLV_CONF, "r");
00714 
00715         } else {
00716                 fp = fopen(filename, "r");
00717         }
00718         if (!fp) {
00719                 return LDNS_STATUS_FILE_ERR;
00720         }
00721 
00722         s = ldns_resolver_new_frm_fp(&r, fp);
00723         fclose(fp);
00724         if (s == LDNS_STATUS_OK) {
00725                 if (res) {
00726                         *res = r;
00727                         return LDNS_STATUS_OK;
00728                 } else  {
00729                         return LDNS_STATUS_NULL;
00730                 }
00731         }
00732         return s;
00733 }
00734 
00735 void
00736 ldns_resolver_free(ldns_resolver *res)
00737 {
00738         LDNS_FREE(res);
00739 }
00740 
00741 void
00742 ldns_resolver_deep_free(ldns_resolver *res)
00743 {
00744         size_t i;
00745         
00746         if (res) {
00747                 if (res->_searchlist) {
00748                         for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
00749                                 ldns_rdf_deep_free(res->_searchlist[i]);
00750                         }
00751                         LDNS_FREE(res->_searchlist);
00752                 }
00753                 if (res->_nameservers) {
00754                         for (i = 0; i < res->_nameserver_count; i++) {
00755                                 ldns_rdf_deep_free(res->_nameservers[i]);
00756                         }
00757                         LDNS_FREE(res->_nameservers);
00758                 }
00759                 if (ldns_resolver_domain(res)) {
00760                         ldns_rdf_deep_free(ldns_resolver_domain(res));
00761                 }
00762                 if (ldns_resolver_tsig_keyname(res)) {
00763                         LDNS_FREE(res->_tsig_keyname);
00764                 }
00765                 
00766                 if (res->_cur_axfr_pkt) {
00767                         ldns_pkt_free(res->_cur_axfr_pkt);
00768                 }
00769                 
00770                 if (res->_rtt) {
00771                         LDNS_FREE(res->_rtt);
00772                 }
00773                 LDNS_FREE(res);
00774         }
00775 }
00776 
00777 ldns_pkt *
00778 ldns_resolver_search(const ldns_resolver *r,const  ldns_rdf *name, ldns_rr_type type, 
00779                 ldns_rr_class class, uint16_t flags)
00780 {
00781 
00782         char *str_dname;
00783         ldns_rdf *new_name;
00784         ldns_rdf **search_list;
00785         size_t i;
00786         ldns_pkt *p;
00787 
00788         str_dname = ldns_rdf2str(name);
00789 
00790         if (ldns_dname_str_absolute(str_dname)) {
00791                 /* query as-is */
00792                 return ldns_resolver_query(r, name, type, class, flags);
00793         } else {
00794                 search_list = ldns_resolver_searchlist(r);
00795                 for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
00796                         new_name = ldns_dname_cat_clone(name, search_list[i]);
00797 
00798                         p = ldns_resolver_query(r, new_name, type, class, flags);
00799                         ldns_rdf_free(new_name);
00800                         if (p) {
00801                                 return p;
00802                         }
00803                 }
00804         }
00805         return NULL;
00806 }
00807 
00808 ldns_pkt *
00809 ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, ldns_rr_type type, 
00810                 ldns_rr_class class, uint16_t flags)
00811 {
00812         ldns_rdf *newname;
00813         ldns_pkt *pkt;
00814         ldns_status status;
00815 
00816         pkt = NULL;
00817 
00818         if (!ldns_resolver_defnames(r)) {
00819                 status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, type, class, 
00820                                 flags);
00821                 if (status == LDNS_STATUS_OK) {
00822                         return pkt;
00823                 } else {
00824                         if (pkt) {
00825                                 ldns_pkt_free(pkt);
00826                         }
00827                         fprintf(stderr, "error: %s\n", ldns_get_errorstr_by_id(status));
00828                         return NULL;
00829                 }
00830         }
00831 
00832         if (!ldns_resolver_domain(r)) {
00833                 /* _defnames is set, but the domain is not....?? */
00834                 status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, type, class, 
00835                                 flags);
00836                 if (status == LDNS_STATUS_OK) {
00837                         return pkt;
00838                 } else {
00839                         if (pkt) {
00840                                 ldns_pkt_free(pkt);
00841                         }
00842                         return NULL;
00843                 }
00844         }
00845 
00846         newname = ldns_dname_cat_clone((const ldns_rdf*)name, ldns_resolver_domain(r));
00847         if (!newname) {
00848                 if (pkt) {
00849                         ldns_pkt_free(pkt);
00850                 }
00851                 return NULL;
00852         }
00853         status = ldns_resolver_send(&pkt, (ldns_resolver *)r, newname, type, class, 
00854                         flags);
00855         ldns_rdf_free(newname);
00856         return pkt;
00857 }
00858 
00859 ldns_status
00860 ldns_resolver_send_pkt(ldns_pkt **answer,const ldns_resolver *r, 
00861                 const ldns_pkt *query_pkt)
00862 {
00863         ldns_pkt *answer_pkt = NULL;
00864         ldns_status stat = LDNS_STATUS_OK;
00865 
00866         stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt);
00867         if (stat != LDNS_STATUS_OK) {
00868                 if(answer_pkt) {
00869                         ldns_pkt_free(answer_pkt);
00870                         answer_pkt = NULL;
00871                 }
00872         }
00873         
00874         if (answer) {
00875                 *answer = answer_pkt;
00876         }
00877 
00878         return stat;
00879 }
00880 
00881 ldns_status
00882 ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r,
00883                                 const ldns_rdf *name, ldns_rr_type type, 
00884                                 ldns_rr_class class, uint16_t flags)
00885 {
00886         /* prepare a question pkt from the parameters
00887          * and then send this */
00888         *query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), type, class, flags);
00889         if (!*query_pkt) {
00890                 return LDNS_STATUS_ERR;
00891         }
00892 
00893         /* set DO bit if necessary */
00894         if (ldns_resolver_dnssec(r)) {
00895                 if (ldns_resolver_edns_udp_size(r) == 0) {
00896                         ldns_resolver_set_edns_udp_size(r, 4096);
00897                 }
00898                 ldns_pkt_set_edns_do(*query_pkt, true);
00899                 ldns_pkt_set_cd(*query_pkt, ldns_resolver_dnssec_cd(r));
00900         }
00901 
00902         /* transfer the udp_edns_size from the resolver to the packet */
00903         if (ldns_resolver_edns_udp_size(r) != 0) {
00904                 ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r));
00905         }
00906 
00907         if (ldns_resolver_debug(r)) {
00908                 ldns_pkt_print(stdout, *query_pkt);
00909         }
00910         
00911         /* only set the id if it is not set yet */
00912         if (ldns_pkt_id(*query_pkt) == 0) {
00913                 ldns_pkt_set_random_id(*query_pkt);
00914         }
00915 
00916         return LDNS_STATUS_OK;
00917 }
00918 
00919 
00920 ldns_status
00921 ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, 
00922                 ldns_rr_type type, ldns_rr_class class, uint16_t flags)
00923 {
00924         ldns_pkt *query_pkt;
00925         ldns_pkt *answer_pkt;
00926         ldns_status status;
00927 
00928         assert(r != NULL);
00929         assert(name != NULL);
00930 
00931         answer_pkt = NULL;
00932         
00933         /* do all the preprocessing here, then fire of an query to 
00934          * the network */
00935 
00936         if (0 == type) {
00937                 type = LDNS_RR_TYPE_A;
00938         }
00939         if (0 == class) {
00940                 class = LDNS_RR_CLASS_IN;
00941         }
00942         if (0 == ldns_resolver_nameserver_count(r)) {
00943                 return LDNS_STATUS_RES_NO_NS;
00944         }
00945         if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
00946                 return LDNS_STATUS_RES_QUERY;
00947         }
00948 
00949         status = ldns_resolver_prepare_query_pkt(&query_pkt,
00950                                                  r,
00951                                                  name,
00952                                                  type,
00953                                                  class,
00954                                                  flags);
00955         if (status != LDNS_STATUS_OK) {
00956                 return status;
00957         }
00958 
00959         /* if tsig values are set, tsign it */
00960         /* TODO: make last 3 arguments optional too? maybe make complete
00961                  rr instead of seperate values in resolver (and packet)
00962           Jelte
00963           should this go in pkt_prepare?
00964         */
00965 #ifdef HAVE_SSL
00966         if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
00967                 status = ldns_pkt_tsig_sign(query_pkt,
00968                                             ldns_resolver_tsig_keyname(r),
00969                                             ldns_resolver_tsig_keydata(r),
00970                                             300, ldns_resolver_tsig_algorithm(r), NULL);
00971                 if (status != LDNS_STATUS_OK) {
00972                         return LDNS_STATUS_CRYPTO_TSIG_ERR;
00973                 }
00974         }
00975 #endif /* HAVE_SSL */
00976         status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
00977         ldns_pkt_free(query_pkt);
00978         
00979         /* allows answer to be NULL when not interested in return value */
00980         if (answer) {
00981                 *answer = answer_pkt;
00982         }
00983         return status;
00984 }
00985 
00986 ldns_rr *
00987 ldns_axfr_next(ldns_resolver *resolver)
00988 {
00989         ldns_rr *cur_rr;
00990         uint8_t *packet_wire;
00991         size_t packet_wire_size;
00992         ldns_lookup_table *rcode;
00993         ldns_status status;
00994         
00995         /* check if start() has been called */
00996         if (!resolver || resolver->_socket == 0) {
00997                 return NULL;
00998         }
00999         
01000         if (resolver->_cur_axfr_pkt) {
01001                 if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) {
01002                         ldns_pkt_free(resolver->_cur_axfr_pkt);
01003                         resolver->_cur_axfr_pkt = NULL;
01004                         return ldns_axfr_next(resolver);
01005                 }
01006                 cur_rr = ldns_rr_clone(ldns_rr_list_rr(
01007                                         ldns_pkt_answer(resolver->_cur_axfr_pkt), 
01008                                         resolver->_axfr_i));
01009                 resolver->_axfr_i++;
01010                 if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
01011                         resolver->_axfr_soa_count++;
01012                         if (resolver->_axfr_soa_count >= 2) {
01013                                 close(resolver->_socket);
01014                                 resolver->_socket = 0;
01015                                 ldns_pkt_free(resolver->_cur_axfr_pkt);
01016                                 resolver->_cur_axfr_pkt = NULL;
01017                         }
01018                 }
01019                 return cur_rr;
01020         } else {
01021                 packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size);
01022                 if(!packet_wire) 
01023                         return NULL;
01024                 
01025                 status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire, 
01026                                      packet_wire_size);
01027                 free(packet_wire);
01028 
01029                 resolver->_axfr_i = 0;
01030                 if (status != LDNS_STATUS_OK) {
01031                         /* TODO: make status return type of this function (...api change) */
01032                         fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status));
01033                         return NULL;
01034                 } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
01035                         rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt));
01036                         fprintf(stderr, "Error in AXFR: %s\n", rcode->name);
01037                         return NULL;
01038                 } else {
01039                         return ldns_axfr_next(resolver);
01040                 }
01041                 
01042         }
01043         
01044 }
01045 
01046 bool
01047 ldns_axfr_complete(const ldns_resolver *res) 
01048 {
01049         /* complete when soa count is 2? */
01050         return res->_axfr_soa_count == 2;
01051 }
01052 
01053 ldns_pkt *
01054 ldns_axfr_last_pkt(const ldns_resolver *res) 
01055 {
01056         return res->_cur_axfr_pkt;
01057 }
01058 
01059 /* random isn't really that good */
01060 void
01061 ldns_resolver_nameservers_randomize(ldns_resolver *r)
01062 {
01063         uint8_t i, j;
01064         ldns_rdf **ns, *tmp;
01065 
01066         /* should I check for ldns_resolver_random?? */
01067         assert(r != NULL);
01068 
01069         ns = ldns_resolver_nameservers(r);
01070         
01071         for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
01072                 j = random() % ldns_resolver_nameserver_count(r);
01073                 tmp = ns[i];
01074                 ns[i] = ns[j];
01075                 ns[j] = tmp;
01076         }
01077         ldns_resolver_set_nameservers(r, ns);
01078 }

Generated on Thu Nov 29 14:14:59 2007 for ldns by  doxygen 1.5.1