1825eb42bSJan Lentfer /* 2825eb42bSJan Lentfer * resolver.c 3825eb42bSJan Lentfer * 4825eb42bSJan Lentfer * resolver implementation 5825eb42bSJan Lentfer * 6825eb42bSJan Lentfer * a Net::DNS like library for C 7825eb42bSJan Lentfer * 8825eb42bSJan Lentfer * (c) NLnet Labs, 2004-2006 9825eb42bSJan Lentfer * 10825eb42bSJan Lentfer * See the file LICENSE for the license 11825eb42bSJan Lentfer */ 12825eb42bSJan Lentfer 13825eb42bSJan Lentfer #include <ldns/config.h> 14825eb42bSJan Lentfer 15825eb42bSJan Lentfer #include <ldns/ldns.h> 16825eb42bSJan Lentfer #include <strings.h> 17825eb42bSJan Lentfer 18825eb42bSJan Lentfer /* Access function for reading 19825eb42bSJan Lentfer * and setting the different Resolver 20825eb42bSJan Lentfer * options */ 21825eb42bSJan Lentfer 22825eb42bSJan Lentfer /* read */ 23825eb42bSJan Lentfer uint16_t 24825eb42bSJan Lentfer ldns_resolver_port(const ldns_resolver *r) 25825eb42bSJan Lentfer { 26825eb42bSJan Lentfer return r->_port; 27825eb42bSJan Lentfer } 28825eb42bSJan Lentfer 29825eb42bSJan Lentfer uint16_t 30825eb42bSJan Lentfer ldns_resolver_edns_udp_size(const ldns_resolver *r) 31825eb42bSJan Lentfer { 32825eb42bSJan Lentfer return r->_edns_udp_size; 33825eb42bSJan Lentfer } 34825eb42bSJan Lentfer 35825eb42bSJan Lentfer uint8_t 36825eb42bSJan Lentfer ldns_resolver_retry(const ldns_resolver *r) 37825eb42bSJan Lentfer { 38825eb42bSJan Lentfer return r->_retry; 39825eb42bSJan Lentfer } 40825eb42bSJan Lentfer 41825eb42bSJan Lentfer uint8_t 42825eb42bSJan Lentfer ldns_resolver_retrans(const ldns_resolver *r) 43825eb42bSJan Lentfer { 44825eb42bSJan Lentfer return r->_retrans; 45825eb42bSJan Lentfer } 46825eb42bSJan Lentfer 47825eb42bSJan Lentfer bool 48825eb42bSJan Lentfer ldns_resolver_fallback(const ldns_resolver *r) 49825eb42bSJan Lentfer { 50825eb42bSJan Lentfer return r->_fallback; 51825eb42bSJan Lentfer } 52825eb42bSJan Lentfer 53825eb42bSJan Lentfer uint8_t 54825eb42bSJan Lentfer ldns_resolver_ip6(const ldns_resolver *r) 55825eb42bSJan Lentfer { 56825eb42bSJan Lentfer return r->_ip6; 57825eb42bSJan Lentfer } 58825eb42bSJan Lentfer 59825eb42bSJan Lentfer bool 60825eb42bSJan Lentfer ldns_resolver_recursive(const ldns_resolver *r) 61825eb42bSJan Lentfer { 62825eb42bSJan Lentfer return r->_recursive; 63825eb42bSJan Lentfer } 64825eb42bSJan Lentfer 65825eb42bSJan Lentfer bool 66825eb42bSJan Lentfer ldns_resolver_debug(const ldns_resolver *r) 67825eb42bSJan Lentfer { 68825eb42bSJan Lentfer return r->_debug; 69825eb42bSJan Lentfer } 70825eb42bSJan Lentfer 71825eb42bSJan Lentfer bool 72825eb42bSJan Lentfer ldns_resolver_dnsrch(const ldns_resolver *r) 73825eb42bSJan Lentfer { 74825eb42bSJan Lentfer return r->_dnsrch; 75825eb42bSJan Lentfer } 76825eb42bSJan Lentfer 77825eb42bSJan Lentfer bool 78825eb42bSJan Lentfer ldns_resolver_fail(const ldns_resolver *r) 79825eb42bSJan Lentfer { 80825eb42bSJan Lentfer return r->_fail; 81825eb42bSJan Lentfer } 82825eb42bSJan Lentfer 83825eb42bSJan Lentfer bool 84825eb42bSJan Lentfer ldns_resolver_defnames(const ldns_resolver *r) 85825eb42bSJan Lentfer { 86825eb42bSJan Lentfer return r->_defnames; 87825eb42bSJan Lentfer } 88825eb42bSJan Lentfer 89825eb42bSJan Lentfer ldns_rdf * 90825eb42bSJan Lentfer ldns_resolver_domain(const ldns_resolver *r) 91825eb42bSJan Lentfer { 92825eb42bSJan Lentfer return r->_domain; 93825eb42bSJan Lentfer } 94825eb42bSJan Lentfer 95825eb42bSJan Lentfer ldns_rdf ** 96825eb42bSJan Lentfer ldns_resolver_searchlist(const ldns_resolver *r) 97825eb42bSJan Lentfer { 98825eb42bSJan Lentfer return r->_searchlist; 99825eb42bSJan Lentfer } 100825eb42bSJan Lentfer 101825eb42bSJan Lentfer ldns_rdf ** 102825eb42bSJan Lentfer ldns_resolver_nameservers(const ldns_resolver *r) 103825eb42bSJan Lentfer { 104825eb42bSJan Lentfer return r->_nameservers; 105825eb42bSJan Lentfer } 106825eb42bSJan Lentfer 107825eb42bSJan Lentfer size_t 108825eb42bSJan Lentfer ldns_resolver_nameserver_count(const ldns_resolver *r) 109825eb42bSJan Lentfer { 110825eb42bSJan Lentfer return r->_nameserver_count; 111825eb42bSJan Lentfer } 112825eb42bSJan Lentfer 113825eb42bSJan Lentfer bool 114825eb42bSJan Lentfer ldns_resolver_dnssec(const ldns_resolver *r) 115825eb42bSJan Lentfer { 116825eb42bSJan Lentfer return r->_dnssec; 117825eb42bSJan Lentfer } 118825eb42bSJan Lentfer 119825eb42bSJan Lentfer bool 120825eb42bSJan Lentfer ldns_resolver_dnssec_cd(const ldns_resolver *r) 121825eb42bSJan Lentfer { 122825eb42bSJan Lentfer return r->_dnssec_cd; 123825eb42bSJan Lentfer } 124825eb42bSJan Lentfer 125825eb42bSJan Lentfer ldns_rr_list * 126825eb42bSJan Lentfer ldns_resolver_dnssec_anchors(const ldns_resolver *r) 127825eb42bSJan Lentfer { 128825eb42bSJan Lentfer return r->_dnssec_anchors; 129825eb42bSJan Lentfer } 130825eb42bSJan Lentfer 131825eb42bSJan Lentfer bool 132825eb42bSJan Lentfer ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys) 133825eb42bSJan Lentfer { 134825eb42bSJan Lentfer size_t i; 135825eb42bSJan Lentfer bool result = false; 136825eb42bSJan Lentfer 137825eb42bSJan Lentfer ldns_rr_list * trust_anchors; 138825eb42bSJan Lentfer ldns_rr * cur_rr; 139825eb42bSJan Lentfer 140825eb42bSJan Lentfer if (!r || !keys) { return false; } 141825eb42bSJan Lentfer 142825eb42bSJan Lentfer trust_anchors = ldns_resolver_dnssec_anchors(r); 143825eb42bSJan Lentfer 144825eb42bSJan Lentfer if (!trust_anchors) { return false; } 145825eb42bSJan Lentfer 146825eb42bSJan Lentfer for (i = 0; i < ldns_rr_list_rr_count(keys); i++) { 147825eb42bSJan Lentfer 148825eb42bSJan Lentfer cur_rr = ldns_rr_list_rr(keys, i); 149825eb42bSJan Lentfer if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) { 150825eb42bSJan Lentfer if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); } 151825eb42bSJan Lentfer result = true; 152825eb42bSJan Lentfer } 153825eb42bSJan Lentfer } 154825eb42bSJan Lentfer 155825eb42bSJan Lentfer return result; 156825eb42bSJan Lentfer } 157825eb42bSJan Lentfer 158825eb42bSJan Lentfer bool 159825eb42bSJan Lentfer ldns_resolver_igntc(const ldns_resolver *r) 160825eb42bSJan Lentfer { 161825eb42bSJan Lentfer return r->_igntc; 162825eb42bSJan Lentfer } 163825eb42bSJan Lentfer 164825eb42bSJan Lentfer bool 165825eb42bSJan Lentfer ldns_resolver_usevc(const ldns_resolver *r) 166825eb42bSJan Lentfer { 167825eb42bSJan Lentfer return r->_usevc; 168825eb42bSJan Lentfer } 169825eb42bSJan Lentfer 170825eb42bSJan Lentfer size_t * 171825eb42bSJan Lentfer ldns_resolver_rtt(const ldns_resolver *r) 172825eb42bSJan Lentfer { 173825eb42bSJan Lentfer return r->_rtt; 174825eb42bSJan Lentfer } 175825eb42bSJan Lentfer 176825eb42bSJan Lentfer size_t 177825eb42bSJan Lentfer ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos) 178825eb42bSJan Lentfer { 179825eb42bSJan Lentfer size_t *rtt; 180825eb42bSJan Lentfer 181825eb42bSJan Lentfer assert(r != NULL); 182825eb42bSJan Lentfer 183825eb42bSJan Lentfer rtt = ldns_resolver_rtt(r); 184825eb42bSJan Lentfer 185825eb42bSJan Lentfer if (pos >= ldns_resolver_nameserver_count(r)) { 186825eb42bSJan Lentfer /* error ?*/ 187825eb42bSJan Lentfer return 0; 188825eb42bSJan Lentfer } else { 189825eb42bSJan Lentfer return rtt[pos]; 190825eb42bSJan Lentfer } 191825eb42bSJan Lentfer 192825eb42bSJan Lentfer } 193825eb42bSJan Lentfer 194825eb42bSJan Lentfer struct timeval 195825eb42bSJan Lentfer ldns_resolver_timeout(const ldns_resolver *r) 196825eb42bSJan Lentfer { 197825eb42bSJan Lentfer return r->_timeout; 198825eb42bSJan Lentfer } 199825eb42bSJan Lentfer 200825eb42bSJan Lentfer char * 201825eb42bSJan Lentfer ldns_resolver_tsig_keyname(const ldns_resolver *r) 202825eb42bSJan Lentfer { 203825eb42bSJan Lentfer return r->_tsig_keyname; 204825eb42bSJan Lentfer } 205825eb42bSJan Lentfer 206825eb42bSJan Lentfer char * 207825eb42bSJan Lentfer ldns_resolver_tsig_algorithm(const ldns_resolver *r) 208825eb42bSJan Lentfer { 209825eb42bSJan Lentfer return r->_tsig_algorithm; 210825eb42bSJan Lentfer } 211825eb42bSJan Lentfer 212825eb42bSJan Lentfer char * 213825eb42bSJan Lentfer ldns_resolver_tsig_keydata(const ldns_resolver *r) 214825eb42bSJan Lentfer { 215825eb42bSJan Lentfer return r->_tsig_keydata; 216825eb42bSJan Lentfer } 217825eb42bSJan Lentfer 218825eb42bSJan Lentfer bool 219825eb42bSJan Lentfer ldns_resolver_random(const ldns_resolver *r) 220825eb42bSJan Lentfer { 221825eb42bSJan Lentfer return r->_random; 222825eb42bSJan Lentfer } 223825eb42bSJan Lentfer 224825eb42bSJan Lentfer size_t 225825eb42bSJan Lentfer ldns_resolver_searchlist_count(const ldns_resolver *r) 226825eb42bSJan Lentfer { 227825eb42bSJan Lentfer return r->_searchlist_count; 228825eb42bSJan Lentfer } 229825eb42bSJan Lentfer 230825eb42bSJan Lentfer /* write */ 231825eb42bSJan Lentfer void 232825eb42bSJan Lentfer ldns_resolver_set_port(ldns_resolver *r, uint16_t p) 233825eb42bSJan Lentfer { 234825eb42bSJan Lentfer r->_port = p; 235825eb42bSJan Lentfer } 236825eb42bSJan Lentfer 237825eb42bSJan Lentfer ldns_rdf * 238825eb42bSJan Lentfer ldns_resolver_pop_nameserver(ldns_resolver *r) 239825eb42bSJan Lentfer { 240825eb42bSJan Lentfer ldns_rdf **nameservers; 241825eb42bSJan Lentfer ldns_rdf *pop; 242825eb42bSJan Lentfer size_t ns_count; 243825eb42bSJan Lentfer size_t *rtt; 244825eb42bSJan Lentfer 245825eb42bSJan Lentfer assert(r != NULL); 246825eb42bSJan Lentfer 247825eb42bSJan Lentfer ns_count = ldns_resolver_nameserver_count(r); 248825eb42bSJan Lentfer nameservers = ldns_resolver_nameservers(r); 249825eb42bSJan Lentfer rtt = ldns_resolver_rtt(r); 250825eb42bSJan Lentfer if (ns_count == 0 || !nameservers) { 251825eb42bSJan Lentfer return NULL; 252825eb42bSJan Lentfer } 253825eb42bSJan Lentfer 254825eb42bSJan Lentfer pop = nameservers[ns_count - 1]; 255825eb42bSJan Lentfer 256*d1b2b5caSJohn Marino if (ns_count == 1) { 257*d1b2b5caSJohn Marino LDNS_FREE(nameservers); 258*d1b2b5caSJohn Marino LDNS_FREE(rtt); 259*d1b2b5caSJohn Marino 260*d1b2b5caSJohn Marino ldns_resolver_set_nameservers(r, NULL); 261*d1b2b5caSJohn Marino ldns_resolver_set_rtt(r, NULL); 262*d1b2b5caSJohn Marino } else { 263*d1b2b5caSJohn Marino nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, 264*d1b2b5caSJohn Marino (ns_count - 1)); 265825eb42bSJan Lentfer rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1)); 266825eb42bSJan Lentfer 267825eb42bSJan Lentfer ldns_resolver_set_nameservers(r, nameservers); 268825eb42bSJan Lentfer ldns_resolver_set_rtt(r, rtt); 269*d1b2b5caSJohn Marino } 270825eb42bSJan Lentfer /* decr the count */ 271825eb42bSJan Lentfer ldns_resolver_dec_nameserver_count(r); 272825eb42bSJan Lentfer return pop; 273825eb42bSJan Lentfer } 274825eb42bSJan Lentfer 275825eb42bSJan Lentfer ldns_status 276825eb42bSJan Lentfer ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n) 277825eb42bSJan Lentfer { 278825eb42bSJan Lentfer ldns_rdf **nameservers; 279825eb42bSJan Lentfer size_t ns_count; 280825eb42bSJan Lentfer size_t *rtt; 281825eb42bSJan Lentfer 282825eb42bSJan Lentfer if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A && 283825eb42bSJan Lentfer ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) { 284825eb42bSJan Lentfer return LDNS_STATUS_ERR; 285825eb42bSJan Lentfer } 286825eb42bSJan Lentfer 287825eb42bSJan Lentfer ns_count = ldns_resolver_nameserver_count(r); 288825eb42bSJan Lentfer nameservers = ldns_resolver_nameservers(r); 289825eb42bSJan Lentfer rtt = ldns_resolver_rtt(r); 290825eb42bSJan Lentfer 291825eb42bSJan Lentfer /* make room for the next one */ 292fd185f4dSJan Lentfer if (ns_count == 0) { 293fd185f4dSJan Lentfer nameservers = LDNS_XMALLOC(ldns_rdf *, 1); 294fd185f4dSJan Lentfer } else { 295825eb42bSJan Lentfer nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1)); 296fd185f4dSJan Lentfer } 297fd185f4dSJan Lentfer if(!nameservers) 298fd185f4dSJan Lentfer return LDNS_STATUS_MEM_ERR; 299825eb42bSJan Lentfer 300825eb42bSJan Lentfer /* set the new value in the resolver */ 301825eb42bSJan Lentfer ldns_resolver_set_nameservers(r, nameservers); 302825eb42bSJan Lentfer 303fd185f4dSJan Lentfer /* don't forget the rtt */ 304fd185f4dSJan Lentfer if (ns_count == 0) { 305fd185f4dSJan Lentfer rtt = LDNS_XMALLOC(size_t, 1); 306fd185f4dSJan Lentfer } else { 307fd185f4dSJan Lentfer rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1)); 308fd185f4dSJan Lentfer } 309fd185f4dSJan Lentfer if(!rtt) 310fd185f4dSJan Lentfer return LDNS_STATUS_MEM_ERR; 311fd185f4dSJan Lentfer 312825eb42bSJan Lentfer /* slide n in its slot. */ 313825eb42bSJan Lentfer /* we clone it here, because then we can free the original 314825eb42bSJan Lentfer * rr's where it stood */ 315825eb42bSJan Lentfer nameservers[ns_count] = ldns_rdf_clone(n); 316825eb42bSJan Lentfer rtt[ns_count] = LDNS_RESOLV_RTT_MIN; 317825eb42bSJan Lentfer ldns_resolver_incr_nameserver_count(r); 318825eb42bSJan Lentfer ldns_resolver_set_rtt(r, rtt); 319825eb42bSJan Lentfer return LDNS_STATUS_OK; 320825eb42bSJan Lentfer } 321825eb42bSJan Lentfer 322825eb42bSJan Lentfer ldns_status 323825eb42bSJan Lentfer ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr) 324825eb42bSJan Lentfer { 325825eb42bSJan Lentfer ldns_rdf *address; 326825eb42bSJan Lentfer if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A && 327825eb42bSJan Lentfer ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) { 328825eb42bSJan Lentfer return LDNS_STATUS_ERR; 329825eb42bSJan Lentfer } 330825eb42bSJan Lentfer address = ldns_rr_rdf(rr, 0); /* extract the ip number */ 331825eb42bSJan Lentfer if (address) { 332825eb42bSJan Lentfer return ldns_resolver_push_nameserver(r, address); 333825eb42bSJan Lentfer } else { 334825eb42bSJan Lentfer return LDNS_STATUS_ERR; 335825eb42bSJan Lentfer } 336825eb42bSJan Lentfer } 337825eb42bSJan Lentfer 338825eb42bSJan Lentfer ldns_status 339825eb42bSJan Lentfer ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist) 340825eb42bSJan Lentfer { 341825eb42bSJan Lentfer ldns_rr *rr; 342825eb42bSJan Lentfer ldns_status stat; 343825eb42bSJan Lentfer size_t i; 344825eb42bSJan Lentfer 345825eb42bSJan Lentfer stat = LDNS_STATUS_OK; 346825eb42bSJan Lentfer if (rrlist) { 347825eb42bSJan Lentfer for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { 348825eb42bSJan Lentfer rr = ldns_rr_list_rr(rrlist, i); 349825eb42bSJan Lentfer if (ldns_resolver_push_nameserver_rr(r, rr) != LDNS_STATUS_OK) { 350825eb42bSJan Lentfer stat = LDNS_STATUS_ERR; 351fd185f4dSJan Lentfer break; 352825eb42bSJan Lentfer } 353825eb42bSJan Lentfer } 354825eb42bSJan Lentfer return stat; 355825eb42bSJan Lentfer } else { 356825eb42bSJan Lentfer return LDNS_STATUS_ERR; 357825eb42bSJan Lentfer } 358825eb42bSJan Lentfer } 359825eb42bSJan Lentfer 360825eb42bSJan Lentfer void 361825eb42bSJan Lentfer ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s) 362825eb42bSJan Lentfer { 363825eb42bSJan Lentfer r->_edns_udp_size = s; 364825eb42bSJan Lentfer } 365825eb42bSJan Lentfer 366825eb42bSJan Lentfer void 367825eb42bSJan Lentfer ldns_resolver_set_recursive(ldns_resolver *r, bool re) 368825eb42bSJan Lentfer { 369825eb42bSJan Lentfer r->_recursive = re; 370825eb42bSJan Lentfer } 371825eb42bSJan Lentfer 372825eb42bSJan Lentfer void 373825eb42bSJan Lentfer ldns_resolver_set_dnssec(ldns_resolver *r, bool d) 374825eb42bSJan Lentfer { 375825eb42bSJan Lentfer r->_dnssec = d; 376825eb42bSJan Lentfer } 377825eb42bSJan Lentfer 378825eb42bSJan Lentfer void 379825eb42bSJan Lentfer ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d) 380825eb42bSJan Lentfer { 381825eb42bSJan Lentfer r->_dnssec_cd = d; 382825eb42bSJan Lentfer } 383825eb42bSJan Lentfer 384825eb42bSJan Lentfer void 385825eb42bSJan Lentfer ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l) 386825eb42bSJan Lentfer { 387825eb42bSJan Lentfer r->_dnssec_anchors = l; 388825eb42bSJan Lentfer } 389825eb42bSJan Lentfer 390825eb42bSJan Lentfer ldns_status 391825eb42bSJan Lentfer ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr) 392825eb42bSJan Lentfer { 393825eb42bSJan Lentfer ldns_rr_list * trust_anchors; 394825eb42bSJan Lentfer 395*d1b2b5caSJohn Marino if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY && 396*d1b2b5caSJohn Marino ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS)) { 397*d1b2b5caSJohn Marino 398825eb42bSJan Lentfer return LDNS_STATUS_ERR; 399825eb42bSJan Lentfer } 400825eb42bSJan Lentfer 401825eb42bSJan Lentfer if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */ 402825eb42bSJan Lentfer trust_anchors = ldns_rr_list_new(); 403825eb42bSJan Lentfer ldns_resolver_set_dnssec_anchors(r, trust_anchors); 404825eb42bSJan Lentfer } 405825eb42bSJan Lentfer 406825eb42bSJan Lentfer return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR; 407825eb42bSJan Lentfer } 408825eb42bSJan Lentfer 409825eb42bSJan Lentfer void 410825eb42bSJan Lentfer ldns_resolver_set_igntc(ldns_resolver *r, bool i) 411825eb42bSJan Lentfer { 412825eb42bSJan Lentfer r->_igntc = i; 413825eb42bSJan Lentfer } 414825eb42bSJan Lentfer 415825eb42bSJan Lentfer void 416825eb42bSJan Lentfer ldns_resolver_set_usevc(ldns_resolver *r, bool vc) 417825eb42bSJan Lentfer { 418825eb42bSJan Lentfer r->_usevc = vc; 419825eb42bSJan Lentfer } 420825eb42bSJan Lentfer 421825eb42bSJan Lentfer void 422825eb42bSJan Lentfer ldns_resolver_set_debug(ldns_resolver *r, bool d) 423825eb42bSJan Lentfer { 424825eb42bSJan Lentfer r->_debug = d; 425825eb42bSJan Lentfer } 426825eb42bSJan Lentfer 427825eb42bSJan Lentfer void 428825eb42bSJan Lentfer ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6) 429825eb42bSJan Lentfer { 430825eb42bSJan Lentfer r->_ip6 = ip6; 431825eb42bSJan Lentfer } 432825eb42bSJan Lentfer 433825eb42bSJan Lentfer void 434825eb42bSJan Lentfer ldns_resolver_set_fail(ldns_resolver *r, bool f) 435825eb42bSJan Lentfer { 436825eb42bSJan Lentfer r->_fail =f; 437825eb42bSJan Lentfer } 438825eb42bSJan Lentfer 439825eb42bSJan Lentfer void 440825eb42bSJan Lentfer ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c) 441825eb42bSJan Lentfer { 442825eb42bSJan Lentfer r->_searchlist_count = c; 443825eb42bSJan Lentfer } 444825eb42bSJan Lentfer 445825eb42bSJan Lentfer void 446825eb42bSJan Lentfer ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c) 447825eb42bSJan Lentfer { 448825eb42bSJan Lentfer r->_nameserver_count = c; 449825eb42bSJan Lentfer } 450825eb42bSJan Lentfer 451825eb42bSJan Lentfer void 452825eb42bSJan Lentfer ldns_resolver_set_dnsrch(ldns_resolver *r, bool d) 453825eb42bSJan Lentfer { 454825eb42bSJan Lentfer r->_dnsrch = d; 455825eb42bSJan Lentfer } 456825eb42bSJan Lentfer 457825eb42bSJan Lentfer void 458825eb42bSJan Lentfer ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry) 459825eb42bSJan Lentfer { 460825eb42bSJan Lentfer r->_retry = retry; 461825eb42bSJan Lentfer } 462825eb42bSJan Lentfer 463825eb42bSJan Lentfer void 464825eb42bSJan Lentfer ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans) 465825eb42bSJan Lentfer { 466825eb42bSJan Lentfer r->_retrans = retrans; 467825eb42bSJan Lentfer } 468825eb42bSJan Lentfer 469825eb42bSJan Lentfer void 470825eb42bSJan Lentfer ldns_resolver_set_fallback(ldns_resolver *r, bool fallback) 471825eb42bSJan Lentfer { 472825eb42bSJan Lentfer r->_fallback = fallback; 473825eb42bSJan Lentfer } 474825eb42bSJan Lentfer 475825eb42bSJan Lentfer void 476825eb42bSJan Lentfer ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n) 477825eb42bSJan Lentfer { 478825eb42bSJan Lentfer r->_nameservers = n; 479825eb42bSJan Lentfer } 480825eb42bSJan Lentfer 481825eb42bSJan Lentfer void 482825eb42bSJan Lentfer ldns_resolver_set_defnames(ldns_resolver *r, bool d) 483825eb42bSJan Lentfer { 484825eb42bSJan Lentfer r->_defnames = d; 485825eb42bSJan Lentfer } 486825eb42bSJan Lentfer 487825eb42bSJan Lentfer void 488825eb42bSJan Lentfer ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt) 489825eb42bSJan Lentfer { 490825eb42bSJan Lentfer r->_rtt = rtt; 491825eb42bSJan Lentfer } 492825eb42bSJan Lentfer 493825eb42bSJan Lentfer void 494825eb42bSJan Lentfer ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value) 495825eb42bSJan Lentfer { 496825eb42bSJan Lentfer size_t *rtt; 497825eb42bSJan Lentfer 498825eb42bSJan Lentfer assert(r != NULL); 499825eb42bSJan Lentfer 500825eb42bSJan Lentfer rtt = ldns_resolver_rtt(r); 501825eb42bSJan Lentfer 502825eb42bSJan Lentfer if (pos >= ldns_resolver_nameserver_count(r)) { 503825eb42bSJan Lentfer /* error ?*/ 504825eb42bSJan Lentfer } else { 505825eb42bSJan Lentfer rtt[pos] = value; 506825eb42bSJan Lentfer } 507825eb42bSJan Lentfer 508825eb42bSJan Lentfer } 509825eb42bSJan Lentfer 510825eb42bSJan Lentfer void 511825eb42bSJan Lentfer ldns_resolver_incr_nameserver_count(ldns_resolver *r) 512825eb42bSJan Lentfer { 513825eb42bSJan Lentfer size_t c; 514825eb42bSJan Lentfer 515825eb42bSJan Lentfer c = ldns_resolver_nameserver_count(r); 516825eb42bSJan Lentfer ldns_resolver_set_nameserver_count(r, ++c); 517825eb42bSJan Lentfer } 518825eb42bSJan Lentfer 519825eb42bSJan Lentfer void 520825eb42bSJan Lentfer ldns_resolver_dec_nameserver_count(ldns_resolver *r) 521825eb42bSJan Lentfer { 522825eb42bSJan Lentfer size_t c; 523825eb42bSJan Lentfer 524825eb42bSJan Lentfer c = ldns_resolver_nameserver_count(r); 525825eb42bSJan Lentfer if (c == 0) { 526825eb42bSJan Lentfer return; 527825eb42bSJan Lentfer } else { 528825eb42bSJan Lentfer ldns_resolver_set_nameserver_count(r, --c); 529825eb42bSJan Lentfer } 530825eb42bSJan Lentfer } 531825eb42bSJan Lentfer 532825eb42bSJan Lentfer void 533825eb42bSJan Lentfer ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d) 534825eb42bSJan Lentfer { 535825eb42bSJan Lentfer r->_domain = d; 536825eb42bSJan Lentfer } 537825eb42bSJan Lentfer 538825eb42bSJan Lentfer void 539825eb42bSJan Lentfer ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout) 540825eb42bSJan Lentfer { 541825eb42bSJan Lentfer r->_timeout.tv_sec = timeout.tv_sec; 542825eb42bSJan Lentfer r->_timeout.tv_usec = timeout.tv_usec; 543825eb42bSJan Lentfer } 544825eb42bSJan Lentfer 545825eb42bSJan Lentfer void 546825eb42bSJan Lentfer ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d) 547825eb42bSJan Lentfer { 548825eb42bSJan Lentfer ldns_rdf **searchlist; 549825eb42bSJan Lentfer size_t list_count; 550825eb42bSJan Lentfer 551825eb42bSJan Lentfer if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) { 552825eb42bSJan Lentfer return; 553825eb42bSJan Lentfer } 554825eb42bSJan Lentfer 555825eb42bSJan Lentfer list_count = ldns_resolver_searchlist_count(r); 556825eb42bSJan Lentfer searchlist = ldns_resolver_searchlist(r); 557825eb42bSJan Lentfer 558825eb42bSJan Lentfer searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1)); 559825eb42bSJan Lentfer if (searchlist) { 560825eb42bSJan Lentfer r->_searchlist = searchlist; 561825eb42bSJan Lentfer 562825eb42bSJan Lentfer searchlist[list_count] = ldns_rdf_clone(d); 563825eb42bSJan Lentfer ldns_resolver_set_searchlist_count(r, list_count + 1); 564fd185f4dSJan Lentfer } /* no way to report mem err */ 565825eb42bSJan Lentfer } 566825eb42bSJan Lentfer 567825eb42bSJan Lentfer void 568825eb42bSJan Lentfer ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname) 569825eb42bSJan Lentfer { 570ac996e71SJan Lentfer LDNS_FREE(r->_tsig_keyname); 571ac996e71SJan Lentfer r->_tsig_keyname = strdup(tsig_keyname); 572825eb42bSJan Lentfer } 573825eb42bSJan Lentfer 574825eb42bSJan Lentfer void 575825eb42bSJan Lentfer ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm) 576825eb42bSJan Lentfer { 577ac996e71SJan Lentfer LDNS_FREE(r->_tsig_algorithm); 578ac996e71SJan Lentfer r->_tsig_algorithm = strdup(tsig_algorithm); 579825eb42bSJan Lentfer } 580825eb42bSJan Lentfer 581825eb42bSJan Lentfer void 582825eb42bSJan Lentfer ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata) 583825eb42bSJan Lentfer { 584ac996e71SJan Lentfer LDNS_FREE(r->_tsig_keydata); 585ac996e71SJan Lentfer r->_tsig_keydata = strdup(tsig_keydata); 586825eb42bSJan Lentfer } 587825eb42bSJan Lentfer 588825eb42bSJan Lentfer void 589825eb42bSJan Lentfer ldns_resolver_set_random(ldns_resolver *r, bool b) 590825eb42bSJan Lentfer { 591825eb42bSJan Lentfer r->_random = b; 592825eb42bSJan Lentfer } 593825eb42bSJan Lentfer 594825eb42bSJan Lentfer /* more sophisticated functions */ 595825eb42bSJan Lentfer ldns_resolver * 596825eb42bSJan Lentfer ldns_resolver_new(void) 597825eb42bSJan Lentfer { 598825eb42bSJan Lentfer ldns_resolver *r; 599825eb42bSJan Lentfer 600825eb42bSJan Lentfer r = LDNS_MALLOC(ldns_resolver); 601825eb42bSJan Lentfer if (!r) { 602825eb42bSJan Lentfer return NULL; 603825eb42bSJan Lentfer } 604825eb42bSJan Lentfer 605825eb42bSJan Lentfer r->_searchlist = NULL; 606825eb42bSJan Lentfer r->_nameservers = NULL; 607825eb42bSJan Lentfer r->_rtt = NULL; 608825eb42bSJan Lentfer 609825eb42bSJan Lentfer /* defaults are filled out */ 610825eb42bSJan Lentfer ldns_resolver_set_searchlist_count(r, 0); 611825eb42bSJan Lentfer ldns_resolver_set_nameserver_count(r, 0); 612825eb42bSJan Lentfer ldns_resolver_set_usevc(r, 0); 613825eb42bSJan Lentfer ldns_resolver_set_port(r, LDNS_PORT); 614825eb42bSJan Lentfer ldns_resolver_set_domain(r, NULL); 615825eb42bSJan Lentfer ldns_resolver_set_defnames(r, false); 616825eb42bSJan Lentfer ldns_resolver_set_retry(r, 3); 617825eb42bSJan Lentfer ldns_resolver_set_retrans(r, 2); 618825eb42bSJan Lentfer ldns_resolver_set_fallback(r, true); 619825eb42bSJan Lentfer ldns_resolver_set_fail(r, false); 620825eb42bSJan Lentfer ldns_resolver_set_edns_udp_size(r, 0); 621825eb42bSJan Lentfer ldns_resolver_set_dnssec(r, false); 622825eb42bSJan Lentfer ldns_resolver_set_dnssec_cd(r, false); 623825eb42bSJan Lentfer ldns_resolver_set_dnssec_anchors(r, NULL); 624825eb42bSJan Lentfer ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY); 625ac996e71SJan Lentfer ldns_resolver_set_igntc(r, false); 626ac996e71SJan Lentfer ldns_resolver_set_recursive(r, false); 627ac996e71SJan Lentfer ldns_resolver_set_dnsrch(r, true); 628825eb42bSJan Lentfer 629825eb42bSJan Lentfer /* randomize the nameserver to be queried 630825eb42bSJan Lentfer * when there are multiple 631825eb42bSJan Lentfer */ 632825eb42bSJan Lentfer ldns_resolver_set_random(r, true); 633825eb42bSJan Lentfer 634825eb42bSJan Lentfer ldns_resolver_set_debug(r, 0); 635825eb42bSJan Lentfer 636825eb42bSJan Lentfer r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC; 637825eb42bSJan Lentfer r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC; 638825eb42bSJan Lentfer 639ac996e71SJan Lentfer /* TODO: fd=0 is actually a valid socket (stdin), 640ac996e71SJan Lentfer replace with -1 */ 641825eb42bSJan Lentfer r->_socket = 0; 642825eb42bSJan Lentfer r->_axfr_soa_count = 0; 643825eb42bSJan Lentfer r->_axfr_i = 0; 644825eb42bSJan Lentfer r->_cur_axfr_pkt = NULL; 645825eb42bSJan Lentfer 646825eb42bSJan Lentfer r->_tsig_keyname = NULL; 647825eb42bSJan Lentfer r->_tsig_keydata = NULL; 648825eb42bSJan Lentfer r->_tsig_algorithm = NULL; 649825eb42bSJan Lentfer return r; 650825eb42bSJan Lentfer } 651825eb42bSJan Lentfer 652825eb42bSJan Lentfer ldns_status 653825eb42bSJan Lentfer ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp) 654825eb42bSJan Lentfer { 655825eb42bSJan Lentfer return ldns_resolver_new_frm_fp_l(res, fp, NULL); 656825eb42bSJan Lentfer } 657825eb42bSJan Lentfer 658825eb42bSJan Lentfer ldns_status 659825eb42bSJan Lentfer ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) 660825eb42bSJan Lentfer { 661825eb42bSJan Lentfer ldns_resolver *r; 662825eb42bSJan Lentfer const char *keyword[LDNS_RESOLV_KEYWORDS]; 663825eb42bSJan Lentfer char word[LDNS_MAX_LINELEN + 1]; 664825eb42bSJan Lentfer int8_t expect; 665825eb42bSJan Lentfer uint8_t i; 666825eb42bSJan Lentfer ldns_rdf *tmp; 667825eb42bSJan Lentfer #ifdef HAVE_SSL 668825eb42bSJan Lentfer ldns_rr *tmp_rr; 669825eb42bSJan Lentfer #endif 670ac996e71SJan Lentfer ssize_t gtr, bgtr; 671825eb42bSJan Lentfer ldns_buffer *b; 672ac996e71SJan Lentfer int lnr = 0, oldline; 673ac996e71SJan Lentfer if(!line_nr) line_nr = &lnr; 674825eb42bSJan Lentfer 675825eb42bSJan Lentfer /* do this better 676825eb42bSJan Lentfer * expect = 677825eb42bSJan Lentfer * 0: keyword 678825eb42bSJan Lentfer * 1: default domain dname 679825eb42bSJan Lentfer * 2: NS aaaa or a record 680825eb42bSJan Lentfer */ 681825eb42bSJan Lentfer 682825eb42bSJan Lentfer /* recognized keywords */ 683825eb42bSJan Lentfer keyword[LDNS_RESOLV_NAMESERVER] = "nameserver"; 684825eb42bSJan Lentfer keyword[LDNS_RESOLV_DEFDOMAIN] = "domain"; 685825eb42bSJan Lentfer keyword[LDNS_RESOLV_SEARCH] = "search"; 686825eb42bSJan Lentfer /* these two are read but not used atm TODO */ 687825eb42bSJan Lentfer keyword[LDNS_RESOLV_SORTLIST] = "sortlist"; 688825eb42bSJan Lentfer keyword[LDNS_RESOLV_OPTIONS] = "options"; 689825eb42bSJan Lentfer keyword[LDNS_RESOLV_ANCHOR] = "anchor"; 690825eb42bSJan Lentfer expect = LDNS_RESOLV_KEYWORD; 691825eb42bSJan Lentfer 692825eb42bSJan Lentfer r = ldns_resolver_new(); 693825eb42bSJan Lentfer if (!r) { 694825eb42bSJan Lentfer return LDNS_STATUS_MEM_ERR; 695825eb42bSJan Lentfer } 696825eb42bSJan Lentfer 697825eb42bSJan Lentfer gtr = 1; 698825eb42bSJan Lentfer word[0] = 0; 699ac996e71SJan Lentfer oldline = *line_nr; 700ac996e71SJan Lentfer expect = LDNS_RESOLV_KEYWORD; 701825eb42bSJan Lentfer while (gtr > 0) { 702825eb42bSJan Lentfer /* check comments */ 703825eb42bSJan Lentfer if (word[0] == '#') { 704ac996e71SJan Lentfer word[0]='x'; 705ac996e71SJan Lentfer if(oldline == *line_nr) { 706ac996e71SJan Lentfer /* skip until end of line */ 707ac996e71SJan Lentfer int c; 708ac996e71SJan Lentfer do { 709ac996e71SJan Lentfer c = fgetc(fp); 710ac996e71SJan Lentfer } while(c != EOF && c != '\n'); 711ac996e71SJan Lentfer if(c=='\n' && line_nr) (*line_nr)++; 712ac996e71SJan Lentfer } 713ac996e71SJan Lentfer /* and read next to prepare for further parsing */ 714ac996e71SJan Lentfer oldline = *line_nr; 715825eb42bSJan Lentfer continue; 716825eb42bSJan Lentfer } 717ac996e71SJan Lentfer oldline = *line_nr; 718825eb42bSJan Lentfer switch(expect) { 719825eb42bSJan Lentfer case LDNS_RESOLV_KEYWORD: 720825eb42bSJan Lentfer /* keyword */ 721825eb42bSJan Lentfer gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); 722825eb42bSJan Lentfer if (gtr != 0) { 723ac996e71SJan Lentfer if(word[0] == '#') continue; 724825eb42bSJan Lentfer for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) { 725825eb42bSJan Lentfer if (strcasecmp(keyword[i], word) == 0) { 726825eb42bSJan Lentfer /* chosen the keyword and 727825eb42bSJan Lentfer * expect values carefully 728825eb42bSJan Lentfer */ 729825eb42bSJan Lentfer expect = i; 730825eb42bSJan Lentfer break; 731825eb42bSJan Lentfer } 732825eb42bSJan Lentfer } 733825eb42bSJan Lentfer /* no keyword recognized */ 734825eb42bSJan Lentfer if (expect == LDNS_RESOLV_KEYWORD) { 735825eb42bSJan Lentfer /* skip line */ 736825eb42bSJan Lentfer /* 737825eb42bSJan Lentfer ldns_resolver_deep_free(r); 738825eb42bSJan Lentfer return LDNS_STATUS_SYNTAX_KEYWORD_ERR; 739825eb42bSJan Lentfer */ 740825eb42bSJan Lentfer } 741825eb42bSJan Lentfer } 742825eb42bSJan Lentfer break; 743825eb42bSJan Lentfer case LDNS_RESOLV_DEFDOMAIN: 744825eb42bSJan Lentfer /* default domain dname */ 745825eb42bSJan Lentfer gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); 746825eb42bSJan Lentfer if (gtr == 0) { 747825eb42bSJan Lentfer return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; 748825eb42bSJan Lentfer } 749ac996e71SJan Lentfer if(word[0] == '#') { 750ac996e71SJan Lentfer expect = LDNS_RESOLV_KEYWORD; 751ac996e71SJan Lentfer continue; 752ac996e71SJan Lentfer } 753825eb42bSJan Lentfer tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); 754825eb42bSJan Lentfer if (!tmp) { 755825eb42bSJan Lentfer ldns_resolver_deep_free(r); 756825eb42bSJan Lentfer return LDNS_STATUS_SYNTAX_DNAME_ERR; 757825eb42bSJan Lentfer } 758825eb42bSJan Lentfer 759825eb42bSJan Lentfer /* DOn't free, because we copy the pointer */ 760825eb42bSJan Lentfer ldns_resolver_set_domain(r, tmp); 761825eb42bSJan Lentfer expect = LDNS_RESOLV_KEYWORD; 762825eb42bSJan Lentfer break; 763825eb42bSJan Lentfer case LDNS_RESOLV_NAMESERVER: 764825eb42bSJan Lentfer /* NS aaaa or a record */ 765825eb42bSJan Lentfer gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); 766825eb42bSJan Lentfer if (gtr == 0) { 767825eb42bSJan Lentfer return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; 768825eb42bSJan Lentfer } 769ac996e71SJan Lentfer if(word[0] == '#') { 770ac996e71SJan Lentfer expect = LDNS_RESOLV_KEYWORD; 771ac996e71SJan Lentfer continue; 772ac996e71SJan Lentfer } 773ac996e71SJan Lentfer if(strchr(word, '%')) { 774ac996e71SJan Lentfer /* snip off interface labels, 775ac996e71SJan Lentfer * fe80::222:19ff:fe31:4222%eth0 */ 776ac996e71SJan Lentfer strchr(word, '%')[0]=0; 777ac996e71SJan Lentfer } 778825eb42bSJan Lentfer tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word); 779825eb42bSJan Lentfer if (!tmp) { 780825eb42bSJan Lentfer /* try ip4 */ 781825eb42bSJan Lentfer tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word); 782825eb42bSJan Lentfer } 783825eb42bSJan Lentfer /* could not parse it, exit */ 784825eb42bSJan Lentfer if (!tmp) { 785825eb42bSJan Lentfer ldns_resolver_deep_free(r); 786825eb42bSJan Lentfer return LDNS_STATUS_SYNTAX_ERR; 787825eb42bSJan Lentfer } 788825eb42bSJan Lentfer (void)ldns_resolver_push_nameserver(r, tmp); 789825eb42bSJan Lentfer ldns_rdf_deep_free(tmp); 790825eb42bSJan Lentfer expect = LDNS_RESOLV_KEYWORD; 791825eb42bSJan Lentfer break; 792825eb42bSJan Lentfer case LDNS_RESOLV_SEARCH: 793825eb42bSJan Lentfer /* search list domain dname */ 794825eb42bSJan Lentfer gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); 795825eb42bSJan Lentfer b = LDNS_MALLOC(ldns_buffer); 796ac996e71SJan Lentfer if(!b) { 797ac996e71SJan Lentfer ldns_resolver_deep_free(r); 798ac996e71SJan Lentfer return LDNS_STATUS_MEM_ERR; 799ac996e71SJan Lentfer } 800825eb42bSJan Lentfer 801ac996e71SJan Lentfer ldns_buffer_new_frm_data(b, word, (size_t) gtr); 802ac996e71SJan Lentfer if(ldns_buffer_status(b) != LDNS_STATUS_OK) { 803ac996e71SJan Lentfer LDNS_FREE(b); 804ac996e71SJan Lentfer ldns_resolver_deep_free(r); 805ac996e71SJan Lentfer return LDNS_STATUS_MEM_ERR; 806ac996e71SJan Lentfer } 807ac996e71SJan Lentfer bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1); 808ac996e71SJan Lentfer while (bgtr > 0) { 809ac996e71SJan Lentfer gtr -= bgtr; 810ac996e71SJan Lentfer if(word[0] == '#') { 811ac996e71SJan Lentfer expect = LDNS_RESOLV_KEYWORD; 812*d1b2b5caSJohn Marino break; 813ac996e71SJan Lentfer } 814825eb42bSJan Lentfer tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); 815825eb42bSJan Lentfer if (!tmp) { 816825eb42bSJan Lentfer ldns_resolver_deep_free(r); 817ac996e71SJan Lentfer ldns_buffer_free(b); 818825eb42bSJan Lentfer return LDNS_STATUS_SYNTAX_DNAME_ERR; 819825eb42bSJan Lentfer } 820825eb42bSJan Lentfer 821825eb42bSJan Lentfer ldns_resolver_push_searchlist(r, tmp); 822825eb42bSJan Lentfer 823825eb42bSJan Lentfer ldns_rdf_deep_free(tmp); 824ac996e71SJan Lentfer bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, 825ac996e71SJan Lentfer (size_t) gtr + 1); 826825eb42bSJan Lentfer } 827825eb42bSJan Lentfer ldns_buffer_free(b); 828*d1b2b5caSJohn Marino if (expect != LDNS_RESOLV_KEYWORD) { 829825eb42bSJan Lentfer gtr = 1; 830825eb42bSJan Lentfer expect = LDNS_RESOLV_KEYWORD; 831*d1b2b5caSJohn Marino } 832825eb42bSJan Lentfer break; 833825eb42bSJan Lentfer case LDNS_RESOLV_SORTLIST: 834825eb42bSJan Lentfer gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); 835825eb42bSJan Lentfer /* sortlist not implemented atm */ 836825eb42bSJan Lentfer expect = LDNS_RESOLV_KEYWORD; 837825eb42bSJan Lentfer break; 838825eb42bSJan Lentfer case LDNS_RESOLV_OPTIONS: 839825eb42bSJan Lentfer gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); 840825eb42bSJan Lentfer /* options not implemented atm */ 841825eb42bSJan Lentfer expect = LDNS_RESOLV_KEYWORD; 842825eb42bSJan Lentfer break; 843825eb42bSJan Lentfer case LDNS_RESOLV_ANCHOR: 844825eb42bSJan Lentfer /* a file containing a DNSSEC trust anchor */ 845825eb42bSJan Lentfer gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); 846825eb42bSJan Lentfer if (gtr == 0) { 847ac996e71SJan Lentfer ldns_resolver_deep_free(r); 848825eb42bSJan Lentfer return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; 849825eb42bSJan Lentfer } 850ac996e71SJan Lentfer if(word[0] == '#') { 851ac996e71SJan Lentfer expect = LDNS_RESOLV_KEYWORD; 852ac996e71SJan Lentfer continue; 853ac996e71SJan Lentfer } 854825eb42bSJan Lentfer 855825eb42bSJan Lentfer #ifdef HAVE_SSL 856825eb42bSJan Lentfer tmp_rr = ldns_read_anchor_file(word); 857825eb42bSJan Lentfer (void) ldns_resolver_push_dnssec_anchor(r, tmp_rr); 858825eb42bSJan Lentfer ldns_rr_free(tmp_rr); 859825eb42bSJan Lentfer #endif 860825eb42bSJan Lentfer expect = LDNS_RESOLV_KEYWORD; 861825eb42bSJan Lentfer break; 862825eb42bSJan Lentfer } 863825eb42bSJan Lentfer } 864825eb42bSJan Lentfer 865825eb42bSJan Lentfer if (res) { 866825eb42bSJan Lentfer *res = r; 867825eb42bSJan Lentfer return LDNS_STATUS_OK; 868825eb42bSJan Lentfer } else { 869ac996e71SJan Lentfer ldns_resolver_deep_free(r); 870825eb42bSJan Lentfer return LDNS_STATUS_NULL; 871825eb42bSJan Lentfer } 872825eb42bSJan Lentfer } 873825eb42bSJan Lentfer 874825eb42bSJan Lentfer ldns_status 875825eb42bSJan Lentfer ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename) 876825eb42bSJan Lentfer { 877825eb42bSJan Lentfer ldns_resolver *r; 878825eb42bSJan Lentfer FILE *fp; 879825eb42bSJan Lentfer ldns_status s; 880825eb42bSJan Lentfer 881825eb42bSJan Lentfer if (!filename) { 882825eb42bSJan Lentfer fp = fopen(LDNS_RESOLV_CONF, "r"); 883825eb42bSJan Lentfer 884825eb42bSJan Lentfer } else { 885825eb42bSJan Lentfer fp = fopen(filename, "r"); 886825eb42bSJan Lentfer } 887825eb42bSJan Lentfer if (!fp) { 888825eb42bSJan Lentfer return LDNS_STATUS_FILE_ERR; 889825eb42bSJan Lentfer } 890825eb42bSJan Lentfer 891825eb42bSJan Lentfer s = ldns_resolver_new_frm_fp(&r, fp); 892825eb42bSJan Lentfer fclose(fp); 893825eb42bSJan Lentfer if (s == LDNS_STATUS_OK) { 894825eb42bSJan Lentfer if (res) { 895825eb42bSJan Lentfer *res = r; 896825eb42bSJan Lentfer return LDNS_STATUS_OK; 897825eb42bSJan Lentfer } else { 898*d1b2b5caSJohn Marino ldns_resolver_free(r); 899825eb42bSJan Lentfer return LDNS_STATUS_NULL; 900825eb42bSJan Lentfer } 901825eb42bSJan Lentfer } 902825eb42bSJan Lentfer return s; 903825eb42bSJan Lentfer } 904825eb42bSJan Lentfer 905825eb42bSJan Lentfer void 906825eb42bSJan Lentfer ldns_resolver_free(ldns_resolver *res) 907825eb42bSJan Lentfer { 908825eb42bSJan Lentfer LDNS_FREE(res); 909825eb42bSJan Lentfer } 910825eb42bSJan Lentfer 911825eb42bSJan Lentfer void 912825eb42bSJan Lentfer ldns_resolver_deep_free(ldns_resolver *res) 913825eb42bSJan Lentfer { 914825eb42bSJan Lentfer size_t i; 915825eb42bSJan Lentfer 916825eb42bSJan Lentfer if (res) { 917825eb42bSJan Lentfer if (res->_searchlist) { 918825eb42bSJan Lentfer for (i = 0; i < ldns_resolver_searchlist_count(res); i++) { 919825eb42bSJan Lentfer ldns_rdf_deep_free(res->_searchlist[i]); 920825eb42bSJan Lentfer } 921825eb42bSJan Lentfer LDNS_FREE(res->_searchlist); 922825eb42bSJan Lentfer } 923825eb42bSJan Lentfer if (res->_nameservers) { 924825eb42bSJan Lentfer for (i = 0; i < res->_nameserver_count; i++) { 925825eb42bSJan Lentfer ldns_rdf_deep_free(res->_nameservers[i]); 926825eb42bSJan Lentfer } 927825eb42bSJan Lentfer LDNS_FREE(res->_nameservers); 928825eb42bSJan Lentfer } 929825eb42bSJan Lentfer if (ldns_resolver_domain(res)) { 930825eb42bSJan Lentfer ldns_rdf_deep_free(ldns_resolver_domain(res)); 931825eb42bSJan Lentfer } 932ac996e71SJan Lentfer if (res->_tsig_keyname) { 933825eb42bSJan Lentfer LDNS_FREE(res->_tsig_keyname); 934825eb42bSJan Lentfer } 935ac996e71SJan Lentfer if (res->_tsig_keydata) { 936ac996e71SJan Lentfer LDNS_FREE(res->_tsig_keydata); 937ac996e71SJan Lentfer } 938ac996e71SJan Lentfer if (res->_tsig_algorithm) { 939ac996e71SJan Lentfer LDNS_FREE(res->_tsig_algorithm); 940ac996e71SJan Lentfer } 941825eb42bSJan Lentfer 942825eb42bSJan Lentfer if (res->_cur_axfr_pkt) { 943825eb42bSJan Lentfer ldns_pkt_free(res->_cur_axfr_pkt); 944825eb42bSJan Lentfer } 945825eb42bSJan Lentfer 946825eb42bSJan Lentfer if (res->_rtt) { 947825eb42bSJan Lentfer LDNS_FREE(res->_rtt); 948825eb42bSJan Lentfer } 949825eb42bSJan Lentfer if (res->_dnssec_anchors) { 950825eb42bSJan Lentfer ldns_rr_list_deep_free(res->_dnssec_anchors); 951825eb42bSJan Lentfer } 952825eb42bSJan Lentfer LDNS_FREE(res); 953825eb42bSJan Lentfer } 954825eb42bSJan Lentfer } 955825eb42bSJan Lentfer 956825eb42bSJan Lentfer ldns_pkt * 957825eb42bSJan Lentfer ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, 958825eb42bSJan Lentfer ldns_rr_type t, ldns_rr_class c, uint16_t flags) 959825eb42bSJan Lentfer { 960825eb42bSJan Lentfer 961825eb42bSJan Lentfer ldns_rdf *new_name; 962825eb42bSJan Lentfer ldns_rdf **search_list; 963825eb42bSJan Lentfer size_t i; 964825eb42bSJan Lentfer ldns_pkt *p; 965825eb42bSJan Lentfer 966*d1b2b5caSJohn Marino if (ldns_dname_absolute(name)) { 967825eb42bSJan Lentfer /* query as-is */ 968825eb42bSJan Lentfer return ldns_resolver_query(r, name, t, c, flags); 969ac996e71SJan Lentfer } else if (ldns_resolver_dnsrch(r)) { 970825eb42bSJan Lentfer search_list = ldns_resolver_searchlist(r); 971825eb42bSJan Lentfer for (i = 0; i < ldns_resolver_searchlist_count(r); i++) { 972825eb42bSJan Lentfer new_name = ldns_dname_cat_clone(name, search_list[i]); 973825eb42bSJan Lentfer 974825eb42bSJan Lentfer p = ldns_resolver_query(r, new_name, t, c, flags); 975825eb42bSJan Lentfer ldns_rdf_free(new_name); 976825eb42bSJan Lentfer if (p) { 977ac996e71SJan Lentfer if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NOERROR) { 978825eb42bSJan Lentfer return p; 979ac996e71SJan Lentfer } else { 980ac996e71SJan Lentfer ldns_pkt_free(p); 981ac996e71SJan Lentfer p = NULL; 982ac996e71SJan Lentfer } 983825eb42bSJan Lentfer } 984825eb42bSJan Lentfer } 985825eb42bSJan Lentfer } 986825eb42bSJan Lentfer return NULL; 987825eb42bSJan Lentfer } 988825eb42bSJan Lentfer 989825eb42bSJan Lentfer ldns_pkt * 990825eb42bSJan Lentfer ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, 991825eb42bSJan Lentfer ldns_rr_type t, ldns_rr_class c, uint16_t flags) 992825eb42bSJan Lentfer { 993825eb42bSJan Lentfer ldns_rdf *newname; 994825eb42bSJan Lentfer ldns_pkt *pkt; 995825eb42bSJan Lentfer ldns_status status; 996825eb42bSJan Lentfer 997825eb42bSJan Lentfer pkt = NULL; 998825eb42bSJan Lentfer 999825eb42bSJan Lentfer if (!ldns_resolver_defnames(r)) { 1000825eb42bSJan Lentfer status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, 1001825eb42bSJan Lentfer t, c, flags); 1002825eb42bSJan Lentfer if (status == LDNS_STATUS_OK) { 1003825eb42bSJan Lentfer return pkt; 1004825eb42bSJan Lentfer } else { 1005825eb42bSJan Lentfer if (pkt) { 1006825eb42bSJan Lentfer ldns_pkt_free(pkt); 1007825eb42bSJan Lentfer } 1008825eb42bSJan Lentfer return NULL; 1009825eb42bSJan Lentfer } 1010825eb42bSJan Lentfer } 1011825eb42bSJan Lentfer 1012825eb42bSJan Lentfer if (!ldns_resolver_domain(r)) { 1013825eb42bSJan Lentfer /* _defnames is set, but the domain is not....?? */ 1014825eb42bSJan Lentfer status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, 1015825eb42bSJan Lentfer t, c, flags); 1016825eb42bSJan Lentfer if (status == LDNS_STATUS_OK) { 1017825eb42bSJan Lentfer return pkt; 1018825eb42bSJan Lentfer } else { 1019825eb42bSJan Lentfer if (pkt) { 1020825eb42bSJan Lentfer ldns_pkt_free(pkt); 1021825eb42bSJan Lentfer } 1022825eb42bSJan Lentfer return NULL; 1023825eb42bSJan Lentfer } 1024825eb42bSJan Lentfer } 1025825eb42bSJan Lentfer 1026825eb42bSJan Lentfer newname = ldns_dname_cat_clone((const ldns_rdf*)name, ldns_resolver_domain(r)); 1027825eb42bSJan Lentfer if (!newname) { 1028825eb42bSJan Lentfer return NULL; 1029825eb42bSJan Lentfer } 1030ac996e71SJan Lentfer 1031ac996e71SJan Lentfer (void)ldns_resolver_send(&pkt, (ldns_resolver *)r, newname, t, c, 1032825eb42bSJan Lentfer flags); 1033825eb42bSJan Lentfer 1034825eb42bSJan Lentfer ldns_rdf_free(newname); 1035825eb42bSJan Lentfer 1036825eb42bSJan Lentfer return pkt; 1037825eb42bSJan Lentfer } 1038825eb42bSJan Lentfer 1039b5dedccaSJan Lentfer static size_t * 1040b5dedccaSJan Lentfer ldns_resolver_backup_rtt(ldns_resolver *r) 1041b5dedccaSJan Lentfer { 1042b5dedccaSJan Lentfer size_t *new_rtt; 1043b5dedccaSJan Lentfer size_t *old_rtt = ldns_resolver_rtt(r); 1044b5dedccaSJan Lentfer 1045b5dedccaSJan Lentfer if (old_rtt && ldns_resolver_nameserver_count(r)) { 1046b5dedccaSJan Lentfer new_rtt = LDNS_XMALLOC(size_t 1047b5dedccaSJan Lentfer , ldns_resolver_nameserver_count(r)); 1048b5dedccaSJan Lentfer memcpy(new_rtt, old_rtt, sizeof(size_t) 1049b5dedccaSJan Lentfer * ldns_resolver_nameserver_count(r)); 1050b5dedccaSJan Lentfer ldns_resolver_set_rtt(r, new_rtt); 1051b5dedccaSJan Lentfer return old_rtt; 1052b5dedccaSJan Lentfer } 1053b5dedccaSJan Lentfer return NULL; 1054b5dedccaSJan Lentfer } 1055b5dedccaSJan Lentfer 1056b5dedccaSJan Lentfer static void 1057b5dedccaSJan Lentfer ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt) 1058b5dedccaSJan Lentfer { 1059b5dedccaSJan Lentfer size_t *cur_rtt = ldns_resolver_rtt(r); 1060b5dedccaSJan Lentfer 1061b5dedccaSJan Lentfer if (cur_rtt) { 1062b5dedccaSJan Lentfer LDNS_FREE(cur_rtt); 1063b5dedccaSJan Lentfer } 1064b5dedccaSJan Lentfer ldns_resolver_set_rtt(r, old_rtt); 1065b5dedccaSJan Lentfer } 1066b5dedccaSJan Lentfer 1067825eb42bSJan Lentfer ldns_status 1068825eb42bSJan Lentfer ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r, 1069825eb42bSJan Lentfer ldns_pkt *query_pkt) 1070825eb42bSJan Lentfer { 1071825eb42bSJan Lentfer ldns_pkt *answer_pkt = NULL; 1072825eb42bSJan Lentfer ldns_status stat = LDNS_STATUS_OK; 1073b5dedccaSJan Lentfer size_t *rtt; 1074825eb42bSJan Lentfer 1075825eb42bSJan Lentfer stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt); 1076825eb42bSJan Lentfer if (stat != LDNS_STATUS_OK) { 1077825eb42bSJan Lentfer if(answer_pkt) { 1078825eb42bSJan Lentfer ldns_pkt_free(answer_pkt); 1079825eb42bSJan Lentfer answer_pkt = NULL; 1080825eb42bSJan Lentfer } 1081825eb42bSJan Lentfer } else { 1082825eb42bSJan Lentfer /* if tc=1 fall back to EDNS and/or TCP */ 1083825eb42bSJan Lentfer /* check for tcp first (otherwise we don't care about tc=1) */ 1084825eb42bSJan Lentfer if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) { 1085825eb42bSJan Lentfer if (ldns_pkt_tc(answer_pkt)) { 1086825eb42bSJan Lentfer /* was EDNS0 set? */ 1087825eb42bSJan Lentfer if (ldns_pkt_edns_udp_size(query_pkt) == 0) { 1088b5dedccaSJan Lentfer ldns_pkt_set_edns_udp_size(query_pkt 1089b5dedccaSJan Lentfer , 4096); 1090825eb42bSJan Lentfer ldns_pkt_free(answer_pkt); 1091b5dedccaSJan Lentfer /* Nameservers should not become 1092b5dedccaSJan Lentfer * unreachable because fragments are 1093b5dedccaSJan Lentfer * dropped (network error). We might 1094b5dedccaSJan Lentfer * still have success with TCP. 1095b5dedccaSJan Lentfer * Therefore maintain reachability 1096b5dedccaSJan Lentfer * statuses of the nameservers by 1097b5dedccaSJan Lentfer * backup and restore the rtt list. 1098b5dedccaSJan Lentfer */ 1099b5dedccaSJan Lentfer rtt = ldns_resolver_backup_rtt(r); 1100b5dedccaSJan Lentfer stat = ldns_send(&answer_pkt, r 1101b5dedccaSJan Lentfer , query_pkt); 1102b5dedccaSJan Lentfer ldns_resolver_restore_rtt(r, rtt); 1103825eb42bSJan Lentfer } 1104825eb42bSJan Lentfer /* either way, if it is still truncated, use TCP */ 1105825eb42bSJan Lentfer if (stat != LDNS_STATUS_OK || 1106825eb42bSJan Lentfer ldns_pkt_tc(answer_pkt)) { 1107825eb42bSJan Lentfer ldns_resolver_set_usevc(r, true); 1108825eb42bSJan Lentfer ldns_pkt_free(answer_pkt); 1109825eb42bSJan Lentfer stat = ldns_send(&answer_pkt, r, query_pkt); 1110825eb42bSJan Lentfer ldns_resolver_set_usevc(r, false); 1111825eb42bSJan Lentfer } 1112825eb42bSJan Lentfer } 1113825eb42bSJan Lentfer } 1114825eb42bSJan Lentfer } 1115825eb42bSJan Lentfer 1116825eb42bSJan Lentfer if (answer) { 1117825eb42bSJan Lentfer *answer = answer_pkt; 1118825eb42bSJan Lentfer } 1119825eb42bSJan Lentfer 1120825eb42bSJan Lentfer return stat; 1121825eb42bSJan Lentfer } 1122825eb42bSJan Lentfer 1123825eb42bSJan Lentfer ldns_status 1124825eb42bSJan Lentfer ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r, 1125825eb42bSJan Lentfer const ldns_rdf *name, ldns_rr_type t, 1126825eb42bSJan Lentfer ldns_rr_class c, uint16_t flags) 1127825eb42bSJan Lentfer { 1128fd185f4dSJan Lentfer struct timeval now; 1129fd185f4dSJan Lentfer 1130825eb42bSJan Lentfer /* prepare a question pkt from the parameters 1131825eb42bSJan Lentfer * and then send this */ 1132825eb42bSJan Lentfer *query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags); 1133825eb42bSJan Lentfer if (!*query_pkt) { 1134825eb42bSJan Lentfer return LDNS_STATUS_ERR; 1135825eb42bSJan Lentfer } 1136825eb42bSJan Lentfer 1137825eb42bSJan Lentfer /* set DO bit if necessary */ 1138825eb42bSJan Lentfer if (ldns_resolver_dnssec(r)) { 1139825eb42bSJan Lentfer if (ldns_resolver_edns_udp_size(r) == 0) { 1140825eb42bSJan Lentfer ldns_resolver_set_edns_udp_size(r, 4096); 1141825eb42bSJan Lentfer } 1142825eb42bSJan Lentfer ldns_pkt_set_edns_do(*query_pkt, true); 1143825eb42bSJan Lentfer if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) { 1144825eb42bSJan Lentfer ldns_pkt_set_cd(*query_pkt, true); 1145825eb42bSJan Lentfer } 1146825eb42bSJan Lentfer } 1147825eb42bSJan Lentfer 1148825eb42bSJan Lentfer /* transfer the udp_edns_size from the resolver to the packet */ 1149825eb42bSJan Lentfer if (ldns_resolver_edns_udp_size(r) != 0) { 1150825eb42bSJan Lentfer ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r)); 1151825eb42bSJan Lentfer } 1152825eb42bSJan Lentfer 1153fd185f4dSJan Lentfer /* set the timestamp */ 1154fd185f4dSJan Lentfer now.tv_sec = time(NULL); 1155fd185f4dSJan Lentfer now.tv_usec = 0; 1156fd185f4dSJan Lentfer ldns_pkt_set_timestamp(*query_pkt, now); 1157fd185f4dSJan Lentfer 1158fd185f4dSJan Lentfer 1159825eb42bSJan Lentfer if (ldns_resolver_debug(r)) { 1160825eb42bSJan Lentfer ldns_pkt_print(stdout, *query_pkt); 1161825eb42bSJan Lentfer } 1162825eb42bSJan Lentfer 1163825eb42bSJan Lentfer /* only set the id if it is not set yet */ 1164825eb42bSJan Lentfer if (ldns_pkt_id(*query_pkt) == 0) { 1165825eb42bSJan Lentfer ldns_pkt_set_random_id(*query_pkt); 1166825eb42bSJan Lentfer } 1167825eb42bSJan Lentfer 1168825eb42bSJan Lentfer return LDNS_STATUS_OK; 1169825eb42bSJan Lentfer } 1170825eb42bSJan Lentfer 1171825eb42bSJan Lentfer 1172825eb42bSJan Lentfer ldns_status 1173825eb42bSJan Lentfer ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, 1174825eb42bSJan Lentfer ldns_rr_type t, ldns_rr_class c, uint16_t flags) 1175825eb42bSJan Lentfer { 1176825eb42bSJan Lentfer ldns_pkt *query_pkt; 1177825eb42bSJan Lentfer ldns_pkt *answer_pkt; 1178825eb42bSJan Lentfer ldns_status status; 1179825eb42bSJan Lentfer 1180825eb42bSJan Lentfer assert(r != NULL); 1181825eb42bSJan Lentfer assert(name != NULL); 1182825eb42bSJan Lentfer 1183825eb42bSJan Lentfer answer_pkt = NULL; 1184825eb42bSJan Lentfer 1185825eb42bSJan Lentfer /* do all the preprocessing here, then fire of an query to 1186825eb42bSJan Lentfer * the network */ 1187825eb42bSJan Lentfer 1188825eb42bSJan Lentfer if (0 == t) { 1189825eb42bSJan Lentfer t= LDNS_RR_TYPE_A; 1190825eb42bSJan Lentfer } 1191825eb42bSJan Lentfer if (0 == c) { 1192825eb42bSJan Lentfer c= LDNS_RR_CLASS_IN; 1193825eb42bSJan Lentfer } 1194825eb42bSJan Lentfer if (0 == ldns_resolver_nameserver_count(r)) { 1195825eb42bSJan Lentfer return LDNS_STATUS_RES_NO_NS; 1196825eb42bSJan Lentfer } 1197825eb42bSJan Lentfer if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) { 1198825eb42bSJan Lentfer return LDNS_STATUS_RES_QUERY; 1199825eb42bSJan Lentfer } 1200825eb42bSJan Lentfer 1201825eb42bSJan Lentfer status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name, 1202825eb42bSJan Lentfer t, c, flags); 1203825eb42bSJan Lentfer if (status != LDNS_STATUS_OK) { 1204825eb42bSJan Lentfer return status; 1205825eb42bSJan Lentfer } 1206825eb42bSJan Lentfer 1207825eb42bSJan Lentfer /* if tsig values are set, tsign it */ 1208825eb42bSJan Lentfer /* TODO: make last 3 arguments optional too? maybe make complete 1209825eb42bSJan Lentfer rr instead of seperate values in resolver (and packet) 1210825eb42bSJan Lentfer Jelte 1211825eb42bSJan Lentfer should this go in pkt_prepare? 1212825eb42bSJan Lentfer */ 1213825eb42bSJan Lentfer if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) { 1214fd185f4dSJan Lentfer #ifdef HAVE_SSL 1215825eb42bSJan Lentfer status = ldns_pkt_tsig_sign(query_pkt, 1216825eb42bSJan Lentfer ldns_resolver_tsig_keyname(r), 1217825eb42bSJan Lentfer ldns_resolver_tsig_keydata(r), 1218825eb42bSJan Lentfer 300, ldns_resolver_tsig_algorithm(r), NULL); 1219825eb42bSJan Lentfer if (status != LDNS_STATUS_OK) { 1220*d1b2b5caSJohn Marino ldns_pkt_free(query_pkt); 1221825eb42bSJan Lentfer return LDNS_STATUS_CRYPTO_TSIG_ERR; 1222825eb42bSJan Lentfer } 1223825eb42bSJan Lentfer #else 1224*d1b2b5caSJohn Marino ldns_pkt_free(query_pkt); 1225825eb42bSJan Lentfer return LDNS_STATUS_CRYPTO_TSIG_ERR; 1226825eb42bSJan Lentfer #endif /* HAVE_SSL */ 1227fd185f4dSJan Lentfer } 1228ac996e71SJan Lentfer 1229825eb42bSJan Lentfer status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt); 1230825eb42bSJan Lentfer ldns_pkt_free(query_pkt); 1231825eb42bSJan Lentfer 1232825eb42bSJan Lentfer /* allows answer to be NULL when not interested in return value */ 1233825eb42bSJan Lentfer if (answer) { 1234825eb42bSJan Lentfer *answer = answer_pkt; 1235825eb42bSJan Lentfer } 1236825eb42bSJan Lentfer return status; 1237825eb42bSJan Lentfer } 1238825eb42bSJan Lentfer 1239825eb42bSJan Lentfer ldns_rr * 1240825eb42bSJan Lentfer ldns_axfr_next(ldns_resolver *resolver) 1241825eb42bSJan Lentfer { 1242825eb42bSJan Lentfer ldns_rr *cur_rr; 1243825eb42bSJan Lentfer uint8_t *packet_wire; 1244825eb42bSJan Lentfer size_t packet_wire_size; 1245825eb42bSJan Lentfer ldns_lookup_table *rcode; 1246825eb42bSJan Lentfer ldns_status status; 1247825eb42bSJan Lentfer 1248825eb42bSJan Lentfer /* check if start() has been called */ 1249825eb42bSJan Lentfer if (!resolver || resolver->_socket == 0) { 1250825eb42bSJan Lentfer return NULL; 1251825eb42bSJan Lentfer } 1252825eb42bSJan Lentfer 1253825eb42bSJan Lentfer if (resolver->_cur_axfr_pkt) { 1254825eb42bSJan Lentfer if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) { 1255825eb42bSJan Lentfer ldns_pkt_free(resolver->_cur_axfr_pkt); 1256825eb42bSJan Lentfer resolver->_cur_axfr_pkt = NULL; 1257825eb42bSJan Lentfer return ldns_axfr_next(resolver); 1258825eb42bSJan Lentfer } 1259825eb42bSJan Lentfer cur_rr = ldns_rr_clone(ldns_rr_list_rr( 1260825eb42bSJan Lentfer ldns_pkt_answer(resolver->_cur_axfr_pkt), 1261825eb42bSJan Lentfer resolver->_axfr_i)); 1262825eb42bSJan Lentfer resolver->_axfr_i++; 1263825eb42bSJan Lentfer if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) { 1264825eb42bSJan Lentfer resolver->_axfr_soa_count++; 1265825eb42bSJan Lentfer if (resolver->_axfr_soa_count >= 2) { 1266ac996e71SJan Lentfer #ifndef USE_WINSOCK 1267825eb42bSJan Lentfer close(resolver->_socket); 1268ac996e71SJan Lentfer #else 1269ac996e71SJan Lentfer closesocket(resolver->_socket); 1270ac996e71SJan Lentfer #endif 1271825eb42bSJan Lentfer resolver->_socket = 0; 1272825eb42bSJan Lentfer ldns_pkt_free(resolver->_cur_axfr_pkt); 1273825eb42bSJan Lentfer resolver->_cur_axfr_pkt = NULL; 1274825eb42bSJan Lentfer } 1275825eb42bSJan Lentfer } 1276825eb42bSJan Lentfer return cur_rr; 1277825eb42bSJan Lentfer } else { 1278825eb42bSJan Lentfer packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size); 1279825eb42bSJan Lentfer if(!packet_wire) 1280825eb42bSJan Lentfer return NULL; 1281825eb42bSJan Lentfer 1282825eb42bSJan Lentfer status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire, 1283825eb42bSJan Lentfer packet_wire_size); 1284*d1b2b5caSJohn Marino LDNS_FREE(packet_wire); 1285825eb42bSJan Lentfer 1286825eb42bSJan Lentfer resolver->_axfr_i = 0; 1287825eb42bSJan Lentfer if (status != LDNS_STATUS_OK) { 1288825eb42bSJan Lentfer /* TODO: make status return type of this function (...api change) */ 1289825eb42bSJan Lentfer fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status)); 1290ac996e71SJan Lentfer 1291ac996e71SJan Lentfer /* RoRi: we must now also close the socket, otherwise subsequent uses of the 1292ac996e71SJan Lentfer same resolver structure will fail because the link is still open or 1293ac996e71SJan Lentfer in an undefined state */ 1294ac996e71SJan Lentfer #ifndef USE_WINSOCK 1295ac996e71SJan Lentfer close(resolver->_socket); 1296ac996e71SJan Lentfer #else 1297ac996e71SJan Lentfer closesocket(resolver->_socket); 1298ac996e71SJan Lentfer #endif 1299ac996e71SJan Lentfer resolver->_socket = 0; 1300ac996e71SJan Lentfer 1301825eb42bSJan Lentfer return NULL; 1302825eb42bSJan Lentfer } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) { 1303825eb42bSJan Lentfer rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt)); 1304*d1b2b5caSJohn Marino if (rcode) { 1305*d1b2b5caSJohn Marino fprintf(stderr, "Error in AXFR: %s\n", 1306*d1b2b5caSJohn Marino rcode->name); 1307*d1b2b5caSJohn Marino } else { 1308*d1b2b5caSJohn Marino fprintf(stderr, "Error in AXFR: %d\n", 1309*d1b2b5caSJohn Marino (int) ldns_pkt_get_rcode( 1310*d1b2b5caSJohn Marino resolver->_cur_axfr_pkt)); 1311*d1b2b5caSJohn Marino } 1312ac996e71SJan Lentfer 1313ac996e71SJan Lentfer /* RoRi: we must now also close the socket, otherwise subsequent uses of the 1314ac996e71SJan Lentfer same resolver structure will fail because the link is still open or 1315ac996e71SJan Lentfer in an undefined state */ 1316ac996e71SJan Lentfer #ifndef USE_WINSOCK 1317ac996e71SJan Lentfer close(resolver->_socket); 1318ac996e71SJan Lentfer #else 1319ac996e71SJan Lentfer closesocket(resolver->_socket); 1320ac996e71SJan Lentfer #endif 1321ac996e71SJan Lentfer resolver->_socket = 0; 1322ac996e71SJan Lentfer 1323825eb42bSJan Lentfer return NULL; 1324825eb42bSJan Lentfer } else { 1325825eb42bSJan Lentfer return ldns_axfr_next(resolver); 1326825eb42bSJan Lentfer } 1327825eb42bSJan Lentfer 1328825eb42bSJan Lentfer } 1329825eb42bSJan Lentfer 1330825eb42bSJan Lentfer } 1331825eb42bSJan Lentfer 1332825eb42bSJan Lentfer bool 1333825eb42bSJan Lentfer ldns_axfr_complete(const ldns_resolver *res) 1334825eb42bSJan Lentfer { 1335825eb42bSJan Lentfer /* complete when soa count is 2? */ 1336825eb42bSJan Lentfer return res->_axfr_soa_count == 2; 1337825eb42bSJan Lentfer } 1338825eb42bSJan Lentfer 1339825eb42bSJan Lentfer ldns_pkt * 1340825eb42bSJan Lentfer ldns_axfr_last_pkt(const ldns_resolver *res) 1341825eb42bSJan Lentfer { 1342825eb42bSJan Lentfer return res->_cur_axfr_pkt; 1343825eb42bSJan Lentfer } 1344825eb42bSJan Lentfer 1345825eb42bSJan Lentfer /* random isn't really that good */ 1346825eb42bSJan Lentfer void 1347825eb42bSJan Lentfer ldns_resolver_nameservers_randomize(ldns_resolver *r) 1348825eb42bSJan Lentfer { 1349ac996e71SJan Lentfer uint16_t i, j; 1350*d1b2b5caSJohn Marino ldns_rdf **ns, *tmpns; 1351*d1b2b5caSJohn Marino size_t *rtt, tmprtt; 1352825eb42bSJan Lentfer 1353825eb42bSJan Lentfer /* should I check for ldns_resolver_random?? */ 1354825eb42bSJan Lentfer assert(r != NULL); 1355825eb42bSJan Lentfer 1356825eb42bSJan Lentfer ns = ldns_resolver_nameservers(r); 1357*d1b2b5caSJohn Marino rtt = ldns_resolver_rtt(r); 1358825eb42bSJan Lentfer for (i = 0; i < ldns_resolver_nameserver_count(r); i++) { 1359ac996e71SJan Lentfer j = ldns_get_random() % ldns_resolver_nameserver_count(r); 1360*d1b2b5caSJohn Marino tmpns = ns[i]; 1361825eb42bSJan Lentfer ns[i] = ns[j]; 1362*d1b2b5caSJohn Marino ns[j] = tmpns; 1363*d1b2b5caSJohn Marino tmprtt = rtt[i]; 1364*d1b2b5caSJohn Marino rtt[i] = rtt[j]; 1365*d1b2b5caSJohn Marino rtt[j] = tmprtt; 1366825eb42bSJan Lentfer } 1367825eb42bSJan Lentfer ldns_resolver_set_nameservers(r, ns); 1368825eb42bSJan Lentfer } 1369825eb42bSJan Lentfer 1370