resolver.c revision 246827
1238104Sdes/* 2238104Sdes * resolver.c 3238104Sdes * 4238104Sdes * resolver implementation 5238104Sdes * 6238104Sdes * a Net::DNS like library for C 7238104Sdes * 8238104Sdes * (c) NLnet Labs, 2004-2006 9238104Sdes * 10238104Sdes * See the file LICENSE for the license 11238104Sdes */ 12238104Sdes 13238104Sdes#include <ldns/config.h> 14238104Sdes 15238104Sdes#include <ldns/ldns.h> 16238104Sdes#include <strings.h> 17238104Sdes 18238104Sdes/* Access function for reading 19238104Sdes * and setting the different Resolver 20238104Sdes * options */ 21238104Sdes 22238104Sdes/* read */ 23238104Sdesuint16_t 24238104Sdesldns_resolver_port(const ldns_resolver *r) 25238104Sdes{ 26238104Sdes return r->_port; 27238104Sdes} 28238104Sdes 29238104Sdesuint16_t 30238104Sdesldns_resolver_edns_udp_size(const ldns_resolver *r) 31238104Sdes{ 32238104Sdes return r->_edns_udp_size; 33238104Sdes} 34238104Sdes 35238104Sdesuint8_t 36238104Sdesldns_resolver_retry(const ldns_resolver *r) 37238104Sdes{ 38238104Sdes return r->_retry; 39238104Sdes} 40238104Sdes 41238104Sdesuint8_t 42238104Sdesldns_resolver_retrans(const ldns_resolver *r) 43238104Sdes{ 44238104Sdes return r->_retrans; 45238104Sdes} 46238104Sdes 47238104Sdesbool 48238104Sdesldns_resolver_fallback(const ldns_resolver *r) 49238104Sdes{ 50238104Sdes return r->_fallback; 51238104Sdes} 52238104Sdes 53238104Sdesuint8_t 54238104Sdesldns_resolver_ip6(const ldns_resolver *r) 55238104Sdes{ 56238104Sdes return r->_ip6; 57238104Sdes} 58238104Sdes 59238104Sdesbool 60238104Sdesldns_resolver_recursive(const ldns_resolver *r) 61238104Sdes{ 62238104Sdes return r->_recursive; 63238104Sdes} 64238104Sdes 65238104Sdesbool 66238104Sdesldns_resolver_debug(const ldns_resolver *r) 67238104Sdes{ 68238104Sdes return r->_debug; 69238104Sdes} 70238104Sdes 71238104Sdesbool 72238104Sdesldns_resolver_dnsrch(const ldns_resolver *r) 73238104Sdes{ 74238104Sdes return r->_dnsrch; 75238104Sdes} 76238104Sdes 77238104Sdesbool 78238104Sdesldns_resolver_fail(const ldns_resolver *r) 79238104Sdes{ 80238104Sdes return r->_fail; 81238104Sdes} 82238104Sdes 83238104Sdesbool 84238104Sdesldns_resolver_defnames(const ldns_resolver *r) 85238104Sdes{ 86238104Sdes return r->_defnames; 87238104Sdes} 88238104Sdes 89238104Sdesldns_rdf * 90238104Sdesldns_resolver_domain(const ldns_resolver *r) 91238104Sdes{ 92238104Sdes return r->_domain; 93238104Sdes} 94238104Sdes 95238104Sdesldns_rdf ** 96238104Sdesldns_resolver_searchlist(const ldns_resolver *r) 97238104Sdes{ 98238104Sdes return r->_searchlist; 99238104Sdes} 100238104Sdes 101238104Sdesldns_rdf ** 102238104Sdesldns_resolver_nameservers(const ldns_resolver *r) 103238104Sdes{ 104238104Sdes return r->_nameservers; 105238104Sdes} 106238104Sdes 107238104Sdessize_t 108238104Sdesldns_resolver_nameserver_count(const ldns_resolver *r) 109238104Sdes{ 110238104Sdes return r->_nameserver_count; 111238104Sdes} 112238104Sdes 113238104Sdesbool 114238104Sdesldns_resolver_dnssec(const ldns_resolver *r) 115238104Sdes{ 116238104Sdes return r->_dnssec; 117238104Sdes} 118238104Sdes 119238104Sdesbool 120238104Sdesldns_resolver_dnssec_cd(const ldns_resolver *r) 121238104Sdes{ 122238104Sdes return r->_dnssec_cd; 123238104Sdes} 124238104Sdes 125238104Sdesldns_rr_list * 126238104Sdesldns_resolver_dnssec_anchors(const ldns_resolver *r) 127238104Sdes{ 128238104Sdes return r->_dnssec_anchors; 129238104Sdes} 130238104Sdes 131238104Sdesbool 132238104Sdesldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys) 133238104Sdes{ 134238104Sdes size_t i; 135238104Sdes bool result = false; 136238104Sdes 137238104Sdes ldns_rr_list * trust_anchors; 138238104Sdes ldns_rr * cur_rr; 139238104Sdes 140238104Sdes if (!r || !keys) { return false; } 141238104Sdes 142238104Sdes trust_anchors = ldns_resolver_dnssec_anchors(r); 143238104Sdes 144238104Sdes if (!trust_anchors) { return false; } 145238104Sdes 146238104Sdes for (i = 0; i < ldns_rr_list_rr_count(keys); i++) { 147238104Sdes 148238104Sdes cur_rr = ldns_rr_list_rr(keys, i); 149238104Sdes if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) { 150238104Sdes if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); } 151238104Sdes result = true; 152238104Sdes } 153238104Sdes } 154238104Sdes 155238104Sdes return result; 156238104Sdes} 157238104Sdes 158238104Sdesbool 159238104Sdesldns_resolver_igntc(const ldns_resolver *r) 160238104Sdes{ 161238104Sdes return r->_igntc; 162238104Sdes} 163238104Sdes 164238104Sdesbool 165238104Sdesldns_resolver_usevc(const ldns_resolver *r) 166238104Sdes{ 167238104Sdes return r->_usevc; 168238104Sdes} 169238104Sdes 170238104Sdessize_t * 171238104Sdesldns_resolver_rtt(const ldns_resolver *r) 172238104Sdes{ 173238104Sdes return r->_rtt; 174238104Sdes} 175238104Sdes 176238104Sdessize_t 177238104Sdesldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos) 178238104Sdes{ 179238104Sdes size_t *rtt; 180238104Sdes 181238104Sdes assert(r != NULL); 182238104Sdes 183238104Sdes rtt = ldns_resolver_rtt(r); 184238104Sdes 185238104Sdes if (pos >= ldns_resolver_nameserver_count(r)) { 186238104Sdes /* error ?*/ 187238104Sdes return 0; 188238104Sdes } else { 189238104Sdes return rtt[pos]; 190238104Sdes } 191238104Sdes 192238104Sdes} 193238104Sdes 194238104Sdesstruct timeval 195238104Sdesldns_resolver_timeout(const ldns_resolver *r) 196238104Sdes{ 197238104Sdes return r->_timeout; 198238104Sdes} 199238104Sdes 200238104Sdeschar * 201238104Sdesldns_resolver_tsig_keyname(const ldns_resolver *r) 202238104Sdes{ 203238104Sdes return r->_tsig_keyname; 204238104Sdes} 205238104Sdes 206238104Sdeschar * 207238104Sdesldns_resolver_tsig_algorithm(const ldns_resolver *r) 208238104Sdes{ 209238104Sdes return r->_tsig_algorithm; 210238104Sdes} 211238104Sdes 212238104Sdeschar * 213238104Sdesldns_resolver_tsig_keydata(const ldns_resolver *r) 214238104Sdes{ 215238104Sdes return r->_tsig_keydata; 216238104Sdes} 217238104Sdes 218238104Sdesbool 219238104Sdesldns_resolver_random(const ldns_resolver *r) 220238104Sdes{ 221238104Sdes return r->_random; 222238104Sdes} 223238104Sdes 224238104Sdessize_t 225238104Sdesldns_resolver_searchlist_count(const ldns_resolver *r) 226238104Sdes{ 227238104Sdes return r->_searchlist_count; 228238104Sdes} 229238104Sdes 230238104Sdes/* write */ 231238104Sdesvoid 232238104Sdesldns_resolver_set_port(ldns_resolver *r, uint16_t p) 233238104Sdes{ 234238104Sdes r->_port = p; 235238104Sdes} 236238104Sdes 237238104Sdesldns_rdf * 238238104Sdesldns_resolver_pop_nameserver(ldns_resolver *r) 239238104Sdes{ 240238104Sdes ldns_rdf **nameservers; 241238104Sdes ldns_rdf *pop; 242238104Sdes size_t ns_count; 243238104Sdes size_t *rtt; 244238104Sdes 245238104Sdes assert(r != NULL); 246238104Sdes 247238104Sdes ns_count = ldns_resolver_nameserver_count(r); 248238104Sdes nameservers = ldns_resolver_nameservers(r); 249238104Sdes rtt = ldns_resolver_rtt(r); 250238104Sdes if (ns_count == 0 || !nameservers) { 251238104Sdes return NULL; 252238104Sdes } 253238104Sdes 254238104Sdes pop = nameservers[ns_count - 1]; 255238104Sdes 256238104Sdes nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count - 1)); 257238104Sdes rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1)); 258238104Sdes 259238104Sdes if(nameservers) 260238104Sdes ldns_resolver_set_nameservers(r, nameservers); 261238104Sdes if(rtt) 262238104Sdes ldns_resolver_set_rtt(r, rtt); 263238104Sdes /* decr the count */ 264238104Sdes ldns_resolver_dec_nameserver_count(r); 265238104Sdes return pop; 266238104Sdes} 267238104Sdes 268238104Sdesldns_status 269238104Sdesldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n) 270238104Sdes{ 271238104Sdes ldns_rdf **nameservers; 272238104Sdes size_t ns_count; 273238104Sdes size_t *rtt; 274238104Sdes 275238104Sdes if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A && 276238104Sdes ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) { 277238104Sdes return LDNS_STATUS_ERR; 278238104Sdes } 279238104Sdes 280238104Sdes ns_count = ldns_resolver_nameserver_count(r); 281238104Sdes nameservers = ldns_resolver_nameservers(r); 282238104Sdes rtt = ldns_resolver_rtt(r); 283238104Sdes 284238104Sdes /* make room for the next one */ 285238104Sdes if (ns_count == 0) { 286238104Sdes nameservers = LDNS_XMALLOC(ldns_rdf *, 1); 287238104Sdes } else { 288238104Sdes nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1)); 289238104Sdes } 290238104Sdes if(!nameservers) 291238104Sdes return LDNS_STATUS_MEM_ERR; 292238104Sdes 293238104Sdes /* set the new value in the resolver */ 294238104Sdes ldns_resolver_set_nameservers(r, nameservers); 295238104Sdes 296238104Sdes /* don't forget the rtt */ 297238104Sdes if (ns_count == 0) { 298238104Sdes rtt = LDNS_XMALLOC(size_t, 1); 299238104Sdes } else { 300238104Sdes rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1)); 301238104Sdes } 302238104Sdes if(!rtt) 303238104Sdes return LDNS_STATUS_MEM_ERR; 304238104Sdes 305238104Sdes /* slide n in its slot. */ 306238104Sdes /* we clone it here, because then we can free the original 307238104Sdes * rr's where it stood */ 308238104Sdes nameservers[ns_count] = ldns_rdf_clone(n); 309238104Sdes rtt[ns_count] = LDNS_RESOLV_RTT_MIN; 310238104Sdes ldns_resolver_incr_nameserver_count(r); 311238104Sdes ldns_resolver_set_rtt(r, rtt); 312238104Sdes return LDNS_STATUS_OK; 313238104Sdes} 314238104Sdes 315238104Sdesldns_status 316238104Sdesldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr) 317238104Sdes{ 318238104Sdes ldns_rdf *address; 319238104Sdes if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A && 320238104Sdes ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) { 321238104Sdes return LDNS_STATUS_ERR; 322238104Sdes } 323238104Sdes address = ldns_rr_rdf(rr, 0); /* extract the ip number */ 324238104Sdes if (address) { 325238104Sdes return ldns_resolver_push_nameserver(r, address); 326238104Sdes } else { 327238104Sdes return LDNS_STATUS_ERR; 328238104Sdes } 329238104Sdes} 330238104Sdes 331238104Sdesldns_status 332238104Sdesldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist) 333238104Sdes{ 334238104Sdes ldns_rr *rr; 335238104Sdes ldns_status stat; 336238104Sdes size_t i; 337238104Sdes 338238104Sdes stat = LDNS_STATUS_OK; 339238104Sdes if (rrlist) { 340238104Sdes for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { 341238104Sdes rr = ldns_rr_list_rr(rrlist, i); 342238104Sdes if (ldns_resolver_push_nameserver_rr(r, rr) != LDNS_STATUS_OK) { 343238104Sdes stat = LDNS_STATUS_ERR; 344238104Sdes break; 345238104Sdes } 346238104Sdes } 347238104Sdes return stat; 348238104Sdes } else { 349238104Sdes return LDNS_STATUS_ERR; 350238104Sdes } 351238104Sdes} 352238104Sdes 353238104Sdesvoid 354238104Sdesldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s) 355238104Sdes{ 356238104Sdes r->_edns_udp_size = s; 357238104Sdes} 358238104Sdes 359238104Sdesvoid 360238104Sdesldns_resolver_set_recursive(ldns_resolver *r, bool re) 361238104Sdes{ 362238104Sdes r->_recursive = re; 363238104Sdes} 364238104Sdes 365238104Sdesvoid 366238104Sdesldns_resolver_set_dnssec(ldns_resolver *r, bool d) 367238104Sdes{ 368238104Sdes r->_dnssec = d; 369238104Sdes} 370238104Sdes 371238104Sdesvoid 372238104Sdesldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d) 373238104Sdes{ 374238104Sdes r->_dnssec_cd = d; 375238104Sdes} 376238104Sdes 377238104Sdesvoid 378238104Sdesldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l) 379238104Sdes{ 380238104Sdes r->_dnssec_anchors = l; 381238104Sdes} 382238104Sdes 383238104Sdesldns_status 384238104Sdesldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr) 385238104Sdes{ 386238104Sdes ldns_rr_list * trust_anchors; 387238104Sdes 388238104Sdes if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY)) { 389238104Sdes return LDNS_STATUS_ERR; 390238104Sdes } 391238104Sdes 392238104Sdes if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */ 393238104Sdes trust_anchors = ldns_rr_list_new(); 394238104Sdes ldns_resolver_set_dnssec_anchors(r, trust_anchors); 395238104Sdes } 396238104Sdes 397238104Sdes return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR; 398238104Sdes} 399238104Sdes 400238104Sdesvoid 401238104Sdesldns_resolver_set_igntc(ldns_resolver *r, bool i) 402238104Sdes{ 403238104Sdes r->_igntc = i; 404238104Sdes} 405238104Sdes 406238104Sdesvoid 407238104Sdesldns_resolver_set_usevc(ldns_resolver *r, bool vc) 408238104Sdes{ 409238104Sdes r->_usevc = vc; 410238104Sdes} 411238104Sdes 412238104Sdesvoid 413238104Sdesldns_resolver_set_debug(ldns_resolver *r, bool d) 414238104Sdes{ 415238104Sdes r->_debug = d; 416238104Sdes} 417238104Sdes 418238104Sdesvoid 419238104Sdesldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6) 420238104Sdes{ 421238104Sdes r->_ip6 = ip6; 422238104Sdes} 423238104Sdes 424238104Sdesvoid 425238104Sdesldns_resolver_set_fail(ldns_resolver *r, bool f) 426238104Sdes{ 427238104Sdes r->_fail =f; 428238104Sdes} 429238104Sdes 430246827Sdesstatic void 431238104Sdesldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c) 432238104Sdes{ 433238104Sdes r->_searchlist_count = c; 434238104Sdes} 435238104Sdes 436238104Sdesvoid 437238104Sdesldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c) 438238104Sdes{ 439238104Sdes r->_nameserver_count = c; 440238104Sdes} 441238104Sdes 442238104Sdesvoid 443238104Sdesldns_resolver_set_dnsrch(ldns_resolver *r, bool d) 444238104Sdes{ 445238104Sdes r->_dnsrch = d; 446238104Sdes} 447238104Sdes 448238104Sdesvoid 449238104Sdesldns_resolver_set_retry(ldns_resolver *r, uint8_t retry) 450238104Sdes{ 451238104Sdes r->_retry = retry; 452238104Sdes} 453238104Sdes 454238104Sdesvoid 455238104Sdesldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans) 456238104Sdes{ 457238104Sdes r->_retrans = retrans; 458238104Sdes} 459238104Sdes 460238104Sdesvoid 461238104Sdesldns_resolver_set_fallback(ldns_resolver *r, bool fallback) 462238104Sdes{ 463238104Sdes r->_fallback = fallback; 464238104Sdes} 465238104Sdes 466238104Sdesvoid 467238104Sdesldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n) 468238104Sdes{ 469238104Sdes r->_nameservers = n; 470238104Sdes} 471238104Sdes 472238104Sdesvoid 473238104Sdesldns_resolver_set_defnames(ldns_resolver *r, bool d) 474238104Sdes{ 475238104Sdes r->_defnames = d; 476238104Sdes} 477238104Sdes 478238104Sdesvoid 479238104Sdesldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt) 480238104Sdes{ 481238104Sdes r->_rtt = rtt; 482238104Sdes} 483238104Sdes 484238104Sdesvoid 485238104Sdesldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value) 486238104Sdes{ 487238104Sdes size_t *rtt; 488238104Sdes 489238104Sdes assert(r != NULL); 490238104Sdes 491238104Sdes rtt = ldns_resolver_rtt(r); 492238104Sdes 493238104Sdes if (pos >= ldns_resolver_nameserver_count(r)) { 494238104Sdes /* error ?*/ 495238104Sdes } else { 496238104Sdes rtt[pos] = value; 497238104Sdes } 498238104Sdes 499238104Sdes} 500238104Sdes 501238104Sdesvoid 502238104Sdesldns_resolver_incr_nameserver_count(ldns_resolver *r) 503238104Sdes{ 504238104Sdes size_t c; 505238104Sdes 506238104Sdes c = ldns_resolver_nameserver_count(r); 507238104Sdes ldns_resolver_set_nameserver_count(r, ++c); 508238104Sdes} 509238104Sdes 510238104Sdesvoid 511238104Sdesldns_resolver_dec_nameserver_count(ldns_resolver *r) 512238104Sdes{ 513238104Sdes size_t c; 514238104Sdes 515238104Sdes c = ldns_resolver_nameserver_count(r); 516238104Sdes if (c == 0) { 517238104Sdes return; 518238104Sdes } else { 519238104Sdes ldns_resolver_set_nameserver_count(r, --c); 520238104Sdes } 521238104Sdes} 522238104Sdes 523238104Sdesvoid 524238104Sdesldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d) 525238104Sdes{ 526238104Sdes r->_domain = d; 527238104Sdes} 528238104Sdes 529238104Sdesvoid 530238104Sdesldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout) 531238104Sdes{ 532238104Sdes r->_timeout.tv_sec = timeout.tv_sec; 533238104Sdes r->_timeout.tv_usec = timeout.tv_usec; 534238104Sdes} 535238104Sdes 536238104Sdesvoid 537238104Sdesldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d) 538238104Sdes{ 539238104Sdes ldns_rdf **searchlist; 540238104Sdes size_t list_count; 541238104Sdes 542238104Sdes if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) { 543238104Sdes return; 544238104Sdes } 545238104Sdes 546238104Sdes list_count = ldns_resolver_searchlist_count(r); 547238104Sdes searchlist = ldns_resolver_searchlist(r); 548238104Sdes 549238104Sdes searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1)); 550238104Sdes if (searchlist) { 551238104Sdes r->_searchlist = searchlist; 552238104Sdes 553238104Sdes searchlist[list_count] = ldns_rdf_clone(d); 554238104Sdes ldns_resolver_set_searchlist_count(r, list_count + 1); 555238104Sdes } /* no way to report mem err */ 556238104Sdes} 557238104Sdes 558238104Sdesvoid 559238104Sdesldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname) 560238104Sdes{ 561238104Sdes LDNS_FREE(r->_tsig_keyname); 562238104Sdes r->_tsig_keyname = strdup(tsig_keyname); 563238104Sdes} 564238104Sdes 565238104Sdesvoid 566238104Sdesldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm) 567238104Sdes{ 568238104Sdes LDNS_FREE(r->_tsig_algorithm); 569238104Sdes r->_tsig_algorithm = strdup(tsig_algorithm); 570238104Sdes} 571238104Sdes 572238104Sdesvoid 573238104Sdesldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata) 574238104Sdes{ 575238104Sdes LDNS_FREE(r->_tsig_keydata); 576238104Sdes r->_tsig_keydata = strdup(tsig_keydata); 577238104Sdes} 578238104Sdes 579238104Sdesvoid 580238104Sdesldns_resolver_set_random(ldns_resolver *r, bool b) 581238104Sdes{ 582238104Sdes r->_random = b; 583238104Sdes} 584238104Sdes 585238104Sdes/* more sophisticated functions */ 586238104Sdesldns_resolver * 587238104Sdesldns_resolver_new(void) 588238104Sdes{ 589238104Sdes ldns_resolver *r; 590238104Sdes 591238104Sdes r = LDNS_MALLOC(ldns_resolver); 592238104Sdes if (!r) { 593238104Sdes return NULL; 594238104Sdes } 595238104Sdes 596238104Sdes r->_searchlist = NULL; 597238104Sdes r->_nameservers = NULL; 598238104Sdes r->_rtt = NULL; 599238104Sdes 600238104Sdes /* defaults are filled out */ 601238104Sdes ldns_resolver_set_searchlist_count(r, 0); 602238104Sdes ldns_resolver_set_nameserver_count(r, 0); 603238104Sdes ldns_resolver_set_usevc(r, 0); 604238104Sdes ldns_resolver_set_port(r, LDNS_PORT); 605238104Sdes ldns_resolver_set_domain(r, NULL); 606238104Sdes ldns_resolver_set_defnames(r, false); 607238104Sdes ldns_resolver_set_retry(r, 3); 608238104Sdes ldns_resolver_set_retrans(r, 2); 609238104Sdes ldns_resolver_set_fallback(r, true); 610238104Sdes ldns_resolver_set_fail(r, false); 611238104Sdes ldns_resolver_set_edns_udp_size(r, 0); 612238104Sdes ldns_resolver_set_dnssec(r, false); 613238104Sdes ldns_resolver_set_dnssec_cd(r, false); 614238104Sdes ldns_resolver_set_dnssec_anchors(r, NULL); 615238104Sdes ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY); 616238104Sdes ldns_resolver_set_igntc(r, false); 617238104Sdes ldns_resolver_set_recursive(r, false); 618238104Sdes ldns_resolver_set_dnsrch(r, true); 619238104Sdes 620238104Sdes /* randomize the nameserver to be queried 621238104Sdes * when there are multiple 622238104Sdes */ 623238104Sdes ldns_resolver_set_random(r, true); 624238104Sdes 625238104Sdes ldns_resolver_set_debug(r, 0); 626238104Sdes 627238104Sdes r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC; 628238104Sdes r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC; 629238104Sdes 630238104Sdes /* TODO: fd=0 is actually a valid socket (stdin), 631238104Sdes replace with -1 */ 632238104Sdes r->_socket = 0; 633238104Sdes r->_axfr_soa_count = 0; 634238104Sdes r->_axfr_i = 0; 635238104Sdes r->_cur_axfr_pkt = NULL; 636238104Sdes 637238104Sdes r->_tsig_keyname = NULL; 638238104Sdes r->_tsig_keydata = NULL; 639238104Sdes r->_tsig_algorithm = NULL; 640238104Sdes return r; 641238104Sdes} 642238104Sdes 643238104Sdesldns_status 644238104Sdesldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp) 645238104Sdes{ 646238104Sdes return ldns_resolver_new_frm_fp_l(res, fp, NULL); 647238104Sdes} 648238104Sdes 649238104Sdesldns_status 650238104Sdesldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) 651238104Sdes{ 652238104Sdes ldns_resolver *r; 653238104Sdes const char *keyword[LDNS_RESOLV_KEYWORDS]; 654238104Sdes char word[LDNS_MAX_LINELEN + 1]; 655238104Sdes int8_t expect; 656238104Sdes uint8_t i; 657238104Sdes ldns_rdf *tmp; 658238104Sdes#ifdef HAVE_SSL 659238104Sdes ldns_rr *tmp_rr; 660238104Sdes#endif 661238104Sdes ssize_t gtr, bgtr; 662238104Sdes ldns_buffer *b; 663238104Sdes int lnr = 0, oldline; 664238104Sdes if(!line_nr) line_nr = &lnr; 665238104Sdes 666238104Sdes /* do this better 667238104Sdes * expect = 668238104Sdes * 0: keyword 669238104Sdes * 1: default domain dname 670238104Sdes * 2: NS aaaa or a record 671238104Sdes */ 672238104Sdes 673238104Sdes /* recognized keywords */ 674238104Sdes keyword[LDNS_RESOLV_NAMESERVER] = "nameserver"; 675238104Sdes keyword[LDNS_RESOLV_DEFDOMAIN] = "domain"; 676238104Sdes keyword[LDNS_RESOLV_SEARCH] = "search"; 677238104Sdes /* these two are read but not used atm TODO */ 678238104Sdes keyword[LDNS_RESOLV_SORTLIST] = "sortlist"; 679238104Sdes keyword[LDNS_RESOLV_OPTIONS] = "options"; 680238104Sdes keyword[LDNS_RESOLV_ANCHOR] = "anchor"; 681238104Sdes expect = LDNS_RESOLV_KEYWORD; 682238104Sdes 683238104Sdes r = ldns_resolver_new(); 684238104Sdes if (!r) { 685238104Sdes return LDNS_STATUS_MEM_ERR; 686238104Sdes } 687238104Sdes 688238104Sdes gtr = 1; 689238104Sdes word[0] = 0; 690238104Sdes oldline = *line_nr; 691238104Sdes expect = LDNS_RESOLV_KEYWORD; 692238104Sdes while (gtr > 0) { 693238104Sdes /* check comments */ 694238104Sdes if (word[0] == '#') { 695238104Sdes word[0]='x'; 696238104Sdes if(oldline == *line_nr) { 697238104Sdes /* skip until end of line */ 698238104Sdes int c; 699238104Sdes do { 700238104Sdes c = fgetc(fp); 701238104Sdes } while(c != EOF && c != '\n'); 702238104Sdes if(c=='\n' && line_nr) (*line_nr)++; 703238104Sdes } 704238104Sdes /* and read next to prepare for further parsing */ 705238104Sdes oldline = *line_nr; 706238104Sdes continue; 707238104Sdes } 708238104Sdes oldline = *line_nr; 709238104Sdes switch(expect) { 710238104Sdes case LDNS_RESOLV_KEYWORD: 711238104Sdes /* keyword */ 712238104Sdes gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); 713238104Sdes if (gtr != 0) { 714238104Sdes if(word[0] == '#') continue; 715238104Sdes for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) { 716238104Sdes if (strcasecmp(keyword[i], word) == 0) { 717238104Sdes /* chosen the keyword and 718238104Sdes * expect values carefully 719238104Sdes */ 720238104Sdes expect = i; 721238104Sdes break; 722238104Sdes } 723238104Sdes } 724238104Sdes /* no keyword recognized */ 725238104Sdes if (expect == LDNS_RESOLV_KEYWORD) { 726238104Sdes /* skip line */ 727238104Sdes /* 728238104Sdes ldns_resolver_deep_free(r); 729238104Sdes return LDNS_STATUS_SYNTAX_KEYWORD_ERR; 730238104Sdes */ 731238104Sdes } 732238104Sdes } 733238104Sdes break; 734238104Sdes case LDNS_RESOLV_DEFDOMAIN: 735238104Sdes /* default domain dname */ 736238104Sdes gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); 737238104Sdes if (gtr == 0) { 738238104Sdes return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; 739238104Sdes } 740238104Sdes if(word[0] == '#') { 741238104Sdes expect = LDNS_RESOLV_KEYWORD; 742238104Sdes continue; 743238104Sdes } 744238104Sdes tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); 745238104Sdes if (!tmp) { 746238104Sdes ldns_resolver_deep_free(r); 747238104Sdes return LDNS_STATUS_SYNTAX_DNAME_ERR; 748238104Sdes } 749238104Sdes 750238104Sdes /* DOn't free, because we copy the pointer */ 751238104Sdes ldns_resolver_set_domain(r, tmp); 752238104Sdes expect = LDNS_RESOLV_KEYWORD; 753238104Sdes break; 754238104Sdes case LDNS_RESOLV_NAMESERVER: 755238104Sdes /* NS aaaa or a record */ 756238104Sdes gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); 757238104Sdes if (gtr == 0) { 758238104Sdes return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; 759238104Sdes } 760238104Sdes if(word[0] == '#') { 761238104Sdes expect = LDNS_RESOLV_KEYWORD; 762238104Sdes continue; 763238104Sdes } 764238104Sdes if(strchr(word, '%')) { 765238104Sdes /* snip off interface labels, 766238104Sdes * fe80::222:19ff:fe31:4222%eth0 */ 767238104Sdes strchr(word, '%')[0]=0; 768238104Sdes } 769238104Sdes tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word); 770238104Sdes if (!tmp) { 771238104Sdes /* try ip4 */ 772238104Sdes tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word); 773238104Sdes } 774238104Sdes /* could not parse it, exit */ 775238104Sdes if (!tmp) { 776238104Sdes ldns_resolver_deep_free(r); 777238104Sdes return LDNS_STATUS_SYNTAX_ERR; 778238104Sdes } 779238104Sdes (void)ldns_resolver_push_nameserver(r, tmp); 780238104Sdes ldns_rdf_deep_free(tmp); 781238104Sdes expect = LDNS_RESOLV_KEYWORD; 782238104Sdes break; 783238104Sdes case LDNS_RESOLV_SEARCH: 784238104Sdes /* search list domain dname */ 785238104Sdes gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); 786238104Sdes b = LDNS_MALLOC(ldns_buffer); 787238104Sdes if(!b) { 788238104Sdes ldns_resolver_deep_free(r); 789238104Sdes return LDNS_STATUS_MEM_ERR; 790238104Sdes } 791238104Sdes 792238104Sdes ldns_buffer_new_frm_data(b, word, (size_t) gtr); 793238104Sdes if(ldns_buffer_status(b) != LDNS_STATUS_OK) { 794238104Sdes LDNS_FREE(b); 795238104Sdes ldns_resolver_deep_free(r); 796238104Sdes return LDNS_STATUS_MEM_ERR; 797238104Sdes } 798238104Sdes bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1); 799238104Sdes while (bgtr > 0) { 800238104Sdes gtr -= bgtr; 801238104Sdes if(word[0] == '#') { 802238104Sdes expect = LDNS_RESOLV_KEYWORD; 803238104Sdes ldns_buffer_free(b); 804238104Sdes continue; 805238104Sdes } 806238104Sdes tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); 807238104Sdes if (!tmp) { 808238104Sdes ldns_resolver_deep_free(r); 809238104Sdes ldns_buffer_free(b); 810238104Sdes return LDNS_STATUS_SYNTAX_DNAME_ERR; 811238104Sdes } 812238104Sdes 813238104Sdes ldns_resolver_push_searchlist(r, tmp); 814238104Sdes 815238104Sdes ldns_rdf_deep_free(tmp); 816238104Sdes bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, 817238104Sdes (size_t) gtr + 1); 818238104Sdes } 819238104Sdes ldns_buffer_free(b); 820238104Sdes gtr = 1; 821238104Sdes expect = LDNS_RESOLV_KEYWORD; 822238104Sdes break; 823238104Sdes case LDNS_RESOLV_SORTLIST: 824238104Sdes gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); 825238104Sdes /* sortlist not implemented atm */ 826238104Sdes expect = LDNS_RESOLV_KEYWORD; 827238104Sdes break; 828238104Sdes case LDNS_RESOLV_OPTIONS: 829238104Sdes gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); 830238104Sdes /* options not implemented atm */ 831238104Sdes expect = LDNS_RESOLV_KEYWORD; 832238104Sdes break; 833238104Sdes case LDNS_RESOLV_ANCHOR: 834238104Sdes /* a file containing a DNSSEC trust anchor */ 835238104Sdes gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); 836238104Sdes if (gtr == 0) { 837238104Sdes ldns_resolver_deep_free(r); 838238104Sdes return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; 839238104Sdes } 840238104Sdes if(word[0] == '#') { 841238104Sdes expect = LDNS_RESOLV_KEYWORD; 842238104Sdes continue; 843238104Sdes } 844238104Sdes 845238104Sdes#ifdef HAVE_SSL 846238104Sdes tmp_rr = ldns_read_anchor_file(word); 847238104Sdes (void) ldns_resolver_push_dnssec_anchor(r, tmp_rr); 848238104Sdes ldns_rr_free(tmp_rr); 849238104Sdes#endif 850238104Sdes expect = LDNS_RESOLV_KEYWORD; 851238104Sdes break; 852238104Sdes } 853238104Sdes } 854238104Sdes 855238104Sdes if (res) { 856238104Sdes *res = r; 857238104Sdes return LDNS_STATUS_OK; 858238104Sdes } else { 859238104Sdes ldns_resolver_deep_free(r); 860238104Sdes return LDNS_STATUS_NULL; 861238104Sdes } 862238104Sdes} 863238104Sdes 864238104Sdesldns_status 865238104Sdesldns_resolver_new_frm_file(ldns_resolver **res, const char *filename) 866238104Sdes{ 867238104Sdes ldns_resolver *r; 868238104Sdes FILE *fp; 869238104Sdes ldns_status s; 870238104Sdes 871238104Sdes if (!filename) { 872238104Sdes fp = fopen(LDNS_RESOLV_CONF, "r"); 873238104Sdes 874238104Sdes } else { 875238104Sdes fp = fopen(filename, "r"); 876238104Sdes } 877238104Sdes if (!fp) { 878238104Sdes return LDNS_STATUS_FILE_ERR; 879238104Sdes } 880238104Sdes 881238104Sdes s = ldns_resolver_new_frm_fp(&r, fp); 882238104Sdes fclose(fp); 883238104Sdes if (s == LDNS_STATUS_OK) { 884238104Sdes if (res) { 885238104Sdes *res = r; 886238104Sdes return LDNS_STATUS_OK; 887238104Sdes } else { 888238104Sdes return LDNS_STATUS_NULL; 889238104Sdes } 890238104Sdes } 891238104Sdes return s; 892238104Sdes} 893238104Sdes 894238104Sdesvoid 895238104Sdesldns_resolver_free(ldns_resolver *res) 896238104Sdes{ 897238104Sdes LDNS_FREE(res); 898238104Sdes} 899238104Sdes 900238104Sdesvoid 901238104Sdesldns_resolver_deep_free(ldns_resolver *res) 902238104Sdes{ 903238104Sdes size_t i; 904238104Sdes 905238104Sdes if (res) { 906238104Sdes if (res->_searchlist) { 907238104Sdes for (i = 0; i < ldns_resolver_searchlist_count(res); i++) { 908238104Sdes ldns_rdf_deep_free(res->_searchlist[i]); 909238104Sdes } 910238104Sdes LDNS_FREE(res->_searchlist); 911238104Sdes } 912238104Sdes if (res->_nameservers) { 913238104Sdes for (i = 0; i < res->_nameserver_count; i++) { 914238104Sdes ldns_rdf_deep_free(res->_nameservers[i]); 915238104Sdes } 916238104Sdes LDNS_FREE(res->_nameservers); 917238104Sdes } 918238104Sdes if (ldns_resolver_domain(res)) { 919238104Sdes ldns_rdf_deep_free(ldns_resolver_domain(res)); 920238104Sdes } 921238104Sdes if (res->_tsig_keyname) { 922238104Sdes LDNS_FREE(res->_tsig_keyname); 923238104Sdes } 924238104Sdes if (res->_tsig_keydata) { 925238104Sdes LDNS_FREE(res->_tsig_keydata); 926238104Sdes } 927238104Sdes if (res->_tsig_algorithm) { 928238104Sdes LDNS_FREE(res->_tsig_algorithm); 929238104Sdes } 930238104Sdes 931238104Sdes if (res->_cur_axfr_pkt) { 932238104Sdes ldns_pkt_free(res->_cur_axfr_pkt); 933238104Sdes } 934238104Sdes 935238104Sdes if (res->_rtt) { 936238104Sdes LDNS_FREE(res->_rtt); 937238104Sdes } 938238104Sdes if (res->_dnssec_anchors) { 939238104Sdes ldns_rr_list_deep_free(res->_dnssec_anchors); 940238104Sdes } 941238104Sdes LDNS_FREE(res); 942238104Sdes } 943238104Sdes} 944238104Sdes 945238104Sdesldns_pkt * 946238104Sdesldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, 947238104Sdes ldns_rr_type t, ldns_rr_class c, uint16_t flags) 948238104Sdes{ 949238104Sdes 950238104Sdes char *str_dname; 951238104Sdes ldns_rdf *new_name; 952238104Sdes ldns_rdf **search_list; 953238104Sdes size_t i; 954238104Sdes ldns_pkt *p; 955238104Sdes 956238104Sdes str_dname = ldns_rdf2str(name); 957238104Sdes 958238104Sdes if (ldns_dname_str_absolute(str_dname)) { 959238104Sdes /* query as-is */ 960238104Sdes return ldns_resolver_query(r, name, t, c, flags); 961238104Sdes } else if (ldns_resolver_dnsrch(r)) { 962238104Sdes search_list = ldns_resolver_searchlist(r); 963238104Sdes for (i = 0; i < ldns_resolver_searchlist_count(r); i++) { 964238104Sdes new_name = ldns_dname_cat_clone(name, search_list[i]); 965238104Sdes 966238104Sdes p = ldns_resolver_query(r, new_name, t, c, flags); 967238104Sdes ldns_rdf_free(new_name); 968238104Sdes if (p) { 969238104Sdes if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NOERROR) { 970238104Sdes return p; 971238104Sdes } else { 972238104Sdes ldns_pkt_free(p); 973238104Sdes p = NULL; 974238104Sdes } 975238104Sdes } 976238104Sdes } 977238104Sdes } 978238104Sdes return NULL; 979238104Sdes} 980238104Sdes 981238104Sdesldns_pkt * 982238104Sdesldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, 983238104Sdes ldns_rr_type t, ldns_rr_class c, uint16_t flags) 984238104Sdes{ 985238104Sdes ldns_rdf *newname; 986238104Sdes ldns_pkt *pkt; 987238104Sdes ldns_status status; 988238104Sdes 989238104Sdes pkt = NULL; 990238104Sdes 991238104Sdes if (!ldns_resolver_defnames(r)) { 992238104Sdes status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, 993238104Sdes t, c, flags); 994238104Sdes if (status == LDNS_STATUS_OK) { 995238104Sdes return pkt; 996238104Sdes } else { 997238104Sdes if (pkt) { 998238104Sdes ldns_pkt_free(pkt); 999238104Sdes } 1000238104Sdes return NULL; 1001238104Sdes } 1002238104Sdes } 1003238104Sdes 1004238104Sdes if (!ldns_resolver_domain(r)) { 1005238104Sdes /* _defnames is set, but the domain is not....?? */ 1006238104Sdes status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, 1007238104Sdes t, c, flags); 1008238104Sdes if (status == LDNS_STATUS_OK) { 1009238104Sdes return pkt; 1010238104Sdes } else { 1011238104Sdes if (pkt) { 1012238104Sdes ldns_pkt_free(pkt); 1013238104Sdes } 1014238104Sdes return NULL; 1015238104Sdes } 1016238104Sdes } 1017238104Sdes 1018238104Sdes newname = ldns_dname_cat_clone((const ldns_rdf*)name, ldns_resolver_domain(r)); 1019238104Sdes if (!newname) { 1020238104Sdes if (pkt) { 1021238104Sdes ldns_pkt_free(pkt); 1022238104Sdes } 1023238104Sdes return NULL; 1024238104Sdes } 1025238104Sdes 1026238104Sdes (void)ldns_resolver_send(&pkt, (ldns_resolver *)r, newname, t, c, 1027238104Sdes flags); 1028238104Sdes 1029238104Sdes ldns_rdf_free(newname); 1030238104Sdes 1031238104Sdes return pkt; 1032238104Sdes} 1033238104Sdes 1034238104Sdesstatic size_t * 1035238104Sdesldns_resolver_backup_rtt(ldns_resolver *r) 1036238104Sdes{ 1037238104Sdes size_t *new_rtt; 1038238104Sdes size_t *old_rtt = ldns_resolver_rtt(r); 1039238104Sdes 1040238104Sdes if (old_rtt && ldns_resolver_nameserver_count(r)) { 1041238104Sdes new_rtt = LDNS_XMALLOC(size_t 1042238104Sdes , ldns_resolver_nameserver_count(r)); 1043238104Sdes memcpy(new_rtt, old_rtt, sizeof(size_t) 1044238104Sdes * ldns_resolver_nameserver_count(r)); 1045238104Sdes ldns_resolver_set_rtt(r, new_rtt); 1046238104Sdes return old_rtt; 1047238104Sdes } 1048238104Sdes return NULL; 1049238104Sdes} 1050238104Sdes 1051238104Sdesstatic void 1052238104Sdesldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt) 1053238104Sdes{ 1054238104Sdes size_t *cur_rtt = ldns_resolver_rtt(r); 1055238104Sdes 1056238104Sdes if (cur_rtt) { 1057238104Sdes LDNS_FREE(cur_rtt); 1058238104Sdes } 1059238104Sdes ldns_resolver_set_rtt(r, old_rtt); 1060238104Sdes} 1061238104Sdes 1062238104Sdesldns_status 1063238104Sdesldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r, 1064238104Sdes ldns_pkt *query_pkt) 1065238104Sdes{ 1066238104Sdes ldns_pkt *answer_pkt = NULL; 1067238104Sdes ldns_status stat = LDNS_STATUS_OK; 1068238104Sdes size_t *rtt; 1069238104Sdes 1070238104Sdes stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt); 1071238104Sdes if (stat != LDNS_STATUS_OK) { 1072238104Sdes if(answer_pkt) { 1073238104Sdes ldns_pkt_free(answer_pkt); 1074238104Sdes answer_pkt = NULL; 1075238104Sdes } 1076238104Sdes } else { 1077238104Sdes /* if tc=1 fall back to EDNS and/or TCP */ 1078238104Sdes /* check for tcp first (otherwise we don't care about tc=1) */ 1079238104Sdes if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) { 1080238104Sdes if (ldns_pkt_tc(answer_pkt)) { 1081238104Sdes /* was EDNS0 set? */ 1082238104Sdes if (ldns_pkt_edns_udp_size(query_pkt) == 0) { 1083238104Sdes ldns_pkt_set_edns_udp_size(query_pkt 1084238104Sdes , 4096); 1085238104Sdes ldns_pkt_free(answer_pkt); 1086238104Sdes /* Nameservers should not become 1087238104Sdes * unreachable because fragments are 1088238104Sdes * dropped (network error). We might 1089238104Sdes * still have success with TCP. 1090238104Sdes * Therefore maintain reachability 1091238104Sdes * statuses of the nameservers by 1092238104Sdes * backup and restore the rtt list. 1093238104Sdes */ 1094238104Sdes rtt = ldns_resolver_backup_rtt(r); 1095238104Sdes stat = ldns_send(&answer_pkt, r 1096238104Sdes , query_pkt); 1097238104Sdes ldns_resolver_restore_rtt(r, rtt); 1098238104Sdes } 1099238104Sdes /* either way, if it is still truncated, use TCP */ 1100238104Sdes if (stat != LDNS_STATUS_OK || 1101238104Sdes ldns_pkt_tc(answer_pkt)) { 1102238104Sdes ldns_resolver_set_usevc(r, true); 1103238104Sdes ldns_pkt_free(answer_pkt); 1104238104Sdes stat = ldns_send(&answer_pkt, r, query_pkt); 1105238104Sdes ldns_resolver_set_usevc(r, false); 1106238104Sdes } 1107238104Sdes } 1108238104Sdes } 1109238104Sdes } 1110238104Sdes 1111238104Sdes if (answer) { 1112238104Sdes *answer = answer_pkt; 1113238104Sdes } 1114238104Sdes 1115238104Sdes return stat; 1116238104Sdes} 1117238104Sdes 1118238104Sdesldns_status 1119238104Sdesldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r, 1120238104Sdes const ldns_rdf *name, ldns_rr_type t, 1121238104Sdes ldns_rr_class c, uint16_t flags) 1122238104Sdes{ 1123238104Sdes struct timeval now; 1124238104Sdes 1125238104Sdes /* prepare a question pkt from the parameters 1126238104Sdes * and then send this */ 1127238104Sdes *query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags); 1128238104Sdes if (!*query_pkt) { 1129238104Sdes return LDNS_STATUS_ERR; 1130238104Sdes } 1131238104Sdes 1132238104Sdes /* set DO bit if necessary */ 1133238104Sdes if (ldns_resolver_dnssec(r)) { 1134238104Sdes if (ldns_resolver_edns_udp_size(r) == 0) { 1135238104Sdes ldns_resolver_set_edns_udp_size(r, 4096); 1136238104Sdes } 1137238104Sdes ldns_pkt_set_edns_do(*query_pkt, true); 1138238104Sdes if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) { 1139238104Sdes ldns_pkt_set_cd(*query_pkt, true); 1140238104Sdes } 1141238104Sdes } 1142238104Sdes 1143238104Sdes /* transfer the udp_edns_size from the resolver to the packet */ 1144238104Sdes if (ldns_resolver_edns_udp_size(r) != 0) { 1145238104Sdes ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r)); 1146238104Sdes } 1147238104Sdes 1148238104Sdes /* set the timestamp */ 1149238104Sdes now.tv_sec = time(NULL); 1150238104Sdes now.tv_usec = 0; 1151238104Sdes ldns_pkt_set_timestamp(*query_pkt, now); 1152238104Sdes 1153238104Sdes 1154238104Sdes if (ldns_resolver_debug(r)) { 1155238104Sdes ldns_pkt_print(stdout, *query_pkt); 1156238104Sdes } 1157238104Sdes 1158238104Sdes /* only set the id if it is not set yet */ 1159238104Sdes if (ldns_pkt_id(*query_pkt) == 0) { 1160238104Sdes ldns_pkt_set_random_id(*query_pkt); 1161238104Sdes } 1162238104Sdes 1163238104Sdes return LDNS_STATUS_OK; 1164238104Sdes} 1165238104Sdes 1166238104Sdes 1167238104Sdesldns_status 1168238104Sdesldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, 1169238104Sdes ldns_rr_type t, ldns_rr_class c, uint16_t flags) 1170238104Sdes{ 1171238104Sdes ldns_pkt *query_pkt; 1172238104Sdes ldns_pkt *answer_pkt; 1173238104Sdes ldns_status status; 1174238104Sdes 1175238104Sdes assert(r != NULL); 1176238104Sdes assert(name != NULL); 1177238104Sdes 1178238104Sdes answer_pkt = NULL; 1179238104Sdes 1180238104Sdes /* do all the preprocessing here, then fire of an query to 1181238104Sdes * the network */ 1182238104Sdes 1183238104Sdes if (0 == t) { 1184238104Sdes t= LDNS_RR_TYPE_A; 1185238104Sdes } 1186238104Sdes if (0 == c) { 1187238104Sdes c= LDNS_RR_CLASS_IN; 1188238104Sdes } 1189238104Sdes if (0 == ldns_resolver_nameserver_count(r)) { 1190238104Sdes return LDNS_STATUS_RES_NO_NS; 1191238104Sdes } 1192238104Sdes if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) { 1193238104Sdes return LDNS_STATUS_RES_QUERY; 1194238104Sdes } 1195238104Sdes 1196238104Sdes status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name, 1197238104Sdes t, c, flags); 1198238104Sdes if (status != LDNS_STATUS_OK) { 1199238104Sdes return status; 1200238104Sdes } 1201238104Sdes 1202238104Sdes /* if tsig values are set, tsign it */ 1203238104Sdes /* TODO: make last 3 arguments optional too? maybe make complete 1204238104Sdes rr instead of seperate values in resolver (and packet) 1205238104Sdes Jelte 1206238104Sdes should this go in pkt_prepare? 1207238104Sdes */ 1208238104Sdes if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) { 1209238104Sdes#ifdef HAVE_SSL 1210238104Sdes status = ldns_pkt_tsig_sign(query_pkt, 1211238104Sdes ldns_resolver_tsig_keyname(r), 1212238104Sdes ldns_resolver_tsig_keydata(r), 1213238104Sdes 300, ldns_resolver_tsig_algorithm(r), NULL); 1214238104Sdes if (status != LDNS_STATUS_OK) { 1215238104Sdes return LDNS_STATUS_CRYPTO_TSIG_ERR; 1216238104Sdes } 1217238104Sdes#else 1218238104Sdes return LDNS_STATUS_CRYPTO_TSIG_ERR; 1219238104Sdes#endif /* HAVE_SSL */ 1220238104Sdes } 1221238104Sdes 1222238104Sdes status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt); 1223238104Sdes ldns_pkt_free(query_pkt); 1224238104Sdes 1225238104Sdes /* allows answer to be NULL when not interested in return value */ 1226238104Sdes if (answer) { 1227238104Sdes *answer = answer_pkt; 1228238104Sdes } 1229238104Sdes return status; 1230238104Sdes} 1231238104Sdes 1232238104Sdesldns_rr * 1233238104Sdesldns_axfr_next(ldns_resolver *resolver) 1234238104Sdes{ 1235238104Sdes ldns_rr *cur_rr; 1236238104Sdes uint8_t *packet_wire; 1237238104Sdes size_t packet_wire_size; 1238238104Sdes ldns_lookup_table *rcode; 1239238104Sdes ldns_status status; 1240238104Sdes 1241238104Sdes /* check if start() has been called */ 1242238104Sdes if (!resolver || resolver->_socket == 0) { 1243238104Sdes return NULL; 1244238104Sdes } 1245238104Sdes 1246238104Sdes if (resolver->_cur_axfr_pkt) { 1247238104Sdes if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) { 1248238104Sdes ldns_pkt_free(resolver->_cur_axfr_pkt); 1249238104Sdes resolver->_cur_axfr_pkt = NULL; 1250238104Sdes return ldns_axfr_next(resolver); 1251238104Sdes } 1252238104Sdes cur_rr = ldns_rr_clone(ldns_rr_list_rr( 1253238104Sdes ldns_pkt_answer(resolver->_cur_axfr_pkt), 1254238104Sdes resolver->_axfr_i)); 1255238104Sdes resolver->_axfr_i++; 1256238104Sdes if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) { 1257238104Sdes resolver->_axfr_soa_count++; 1258238104Sdes if (resolver->_axfr_soa_count >= 2) { 1259238104Sdes#ifndef USE_WINSOCK 1260238104Sdes close(resolver->_socket); 1261238104Sdes#else 1262238104Sdes closesocket(resolver->_socket); 1263238104Sdes#endif 1264238104Sdes resolver->_socket = 0; 1265238104Sdes ldns_pkt_free(resolver->_cur_axfr_pkt); 1266238104Sdes resolver->_cur_axfr_pkt = NULL; 1267238104Sdes } 1268238104Sdes } 1269238104Sdes return cur_rr; 1270238104Sdes } else { 1271238104Sdes packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size); 1272238104Sdes if(!packet_wire) 1273238104Sdes return NULL; 1274238104Sdes 1275238104Sdes status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire, 1276238104Sdes packet_wire_size); 1277238104Sdes LDNS_FREE(packet_wire); 1278238104Sdes 1279238104Sdes resolver->_axfr_i = 0; 1280238104Sdes if (status != LDNS_STATUS_OK) { 1281238104Sdes /* TODO: make status return type of this function (...api change) */ 1282238104Sdes fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status)); 1283238104Sdes 1284238104Sdes /* RoRi: we must now also close the socket, otherwise subsequent uses of the 1285238104Sdes same resolver structure will fail because the link is still open or 1286238104Sdes in an undefined state */ 1287238104Sdes#ifndef USE_WINSOCK 1288238104Sdes close(resolver->_socket); 1289238104Sdes#else 1290238104Sdes closesocket(resolver->_socket); 1291238104Sdes#endif 1292238104Sdes resolver->_socket = 0; 1293238104Sdes 1294238104Sdes return NULL; 1295238104Sdes } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) { 1296238104Sdes rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt)); 1297238104Sdes fprintf(stderr, "Error in AXFR: %s\n", rcode->name); 1298238104Sdes 1299238104Sdes /* RoRi: we must now also close the socket, otherwise subsequent uses of the 1300238104Sdes same resolver structure will fail because the link is still open or 1301238104Sdes in an undefined state */ 1302238104Sdes#ifndef USE_WINSOCK 1303238104Sdes close(resolver->_socket); 1304238104Sdes#else 1305238104Sdes closesocket(resolver->_socket); 1306238104Sdes#endif 1307238104Sdes resolver->_socket = 0; 1308238104Sdes 1309238104Sdes return NULL; 1310238104Sdes } else { 1311238104Sdes return ldns_axfr_next(resolver); 1312238104Sdes } 1313238104Sdes 1314238104Sdes } 1315238104Sdes 1316238104Sdes} 1317238104Sdes 1318238104Sdesbool 1319238104Sdesldns_axfr_complete(const ldns_resolver *res) 1320238104Sdes{ 1321238104Sdes /* complete when soa count is 2? */ 1322238104Sdes return res->_axfr_soa_count == 2; 1323238104Sdes} 1324238104Sdes 1325238104Sdesldns_pkt * 1326238104Sdesldns_axfr_last_pkt(const ldns_resolver *res) 1327238104Sdes{ 1328238104Sdes return res->_cur_axfr_pkt; 1329238104Sdes} 1330238104Sdes 1331238104Sdes/* random isn't really that good */ 1332238104Sdesvoid 1333238104Sdesldns_resolver_nameservers_randomize(ldns_resolver *r) 1334238104Sdes{ 1335238104Sdes uint16_t i, j; 1336238104Sdes ldns_rdf **ns, *tmp; 1337238104Sdes 1338238104Sdes /* should I check for ldns_resolver_random?? */ 1339238104Sdes assert(r != NULL); 1340238104Sdes 1341238104Sdes ns = ldns_resolver_nameservers(r); 1342238104Sdes for (i = 0; i < ldns_resolver_nameserver_count(r); i++) { 1343238104Sdes j = ldns_get_random() % ldns_resolver_nameserver_count(r); 1344238104Sdes tmp = ns[i]; 1345238104Sdes ns[i] = ns[j]; 1346238104Sdes ns[j] = tmp; 1347238104Sdes } 1348238104Sdes ldns_resolver_set_nameservers(r, ns); 1349238104Sdes} 1350238104Sdes 1351