xref: /freebsd/contrib/ldns/resolver.c (revision 17d15b25)
17b5038d7SDag-Erling Smørgrav /*
27b5038d7SDag-Erling Smørgrav  * resolver.c
37b5038d7SDag-Erling Smørgrav  *
47b5038d7SDag-Erling Smørgrav  * resolver implementation
57b5038d7SDag-Erling Smørgrav  *
67b5038d7SDag-Erling Smørgrav  * a Net::DNS like library for C
77b5038d7SDag-Erling Smørgrav  *
87b5038d7SDag-Erling Smørgrav  * (c) NLnet Labs, 2004-2006
97b5038d7SDag-Erling Smørgrav  *
107b5038d7SDag-Erling Smørgrav  * See the file LICENSE for the license
117b5038d7SDag-Erling Smørgrav  */
127b5038d7SDag-Erling Smørgrav 
137b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
147b5038d7SDag-Erling Smørgrav 
157b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
167b5038d7SDag-Erling Smørgrav #include <strings.h>
177b5038d7SDag-Erling Smørgrav 
187b5038d7SDag-Erling Smørgrav /* Access function for reading
197b5038d7SDag-Erling Smørgrav  * and setting the different Resolver
207b5038d7SDag-Erling Smørgrav  * options */
217b5038d7SDag-Erling Smørgrav 
227b5038d7SDag-Erling Smørgrav /* read */
237b5038d7SDag-Erling Smørgrav uint16_t
247b5038d7SDag-Erling Smørgrav ldns_resolver_port(const ldns_resolver *r)
257b5038d7SDag-Erling Smørgrav {
267b5038d7SDag-Erling Smørgrav 	return r->_port;
277b5038d7SDag-Erling Smørgrav }
287b5038d7SDag-Erling Smørgrav 
29*17d15b25SDag-Erling Smørgrav ldns_rdf *
30*17d15b25SDag-Erling Smørgrav ldns_resolver_source(const ldns_resolver *r)
31*17d15b25SDag-Erling Smørgrav {
32*17d15b25SDag-Erling Smørgrav 	return r->_source;
33*17d15b25SDag-Erling Smørgrav }
34*17d15b25SDag-Erling Smørgrav 
357b5038d7SDag-Erling Smørgrav uint16_t
367b5038d7SDag-Erling Smørgrav ldns_resolver_edns_udp_size(const ldns_resolver *r)
377b5038d7SDag-Erling Smørgrav {
387b5038d7SDag-Erling Smørgrav 	        return r->_edns_udp_size;
397b5038d7SDag-Erling Smørgrav }
407b5038d7SDag-Erling Smørgrav 
417b5038d7SDag-Erling Smørgrav uint8_t
427b5038d7SDag-Erling Smørgrav ldns_resolver_retry(const ldns_resolver *r)
437b5038d7SDag-Erling Smørgrav {
447b5038d7SDag-Erling Smørgrav 	return r->_retry;
457b5038d7SDag-Erling Smørgrav }
467b5038d7SDag-Erling Smørgrav 
477b5038d7SDag-Erling Smørgrav uint8_t
487b5038d7SDag-Erling Smørgrav ldns_resolver_retrans(const ldns_resolver *r)
497b5038d7SDag-Erling Smørgrav {
507b5038d7SDag-Erling Smørgrav 	return r->_retrans;
517b5038d7SDag-Erling Smørgrav }
527b5038d7SDag-Erling Smørgrav 
537b5038d7SDag-Erling Smørgrav bool
547b5038d7SDag-Erling Smørgrav ldns_resolver_fallback(const ldns_resolver *r)
557b5038d7SDag-Erling Smørgrav {
567b5038d7SDag-Erling Smørgrav 	return r->_fallback;
577b5038d7SDag-Erling Smørgrav }
587b5038d7SDag-Erling Smørgrav 
597b5038d7SDag-Erling Smørgrav uint8_t
607b5038d7SDag-Erling Smørgrav ldns_resolver_ip6(const ldns_resolver *r)
617b5038d7SDag-Erling Smørgrav {
627b5038d7SDag-Erling Smørgrav 	return r->_ip6;
637b5038d7SDag-Erling Smørgrav }
647b5038d7SDag-Erling Smørgrav 
657b5038d7SDag-Erling Smørgrav bool
667b5038d7SDag-Erling Smørgrav ldns_resolver_recursive(const ldns_resolver *r)
677b5038d7SDag-Erling Smørgrav {
687b5038d7SDag-Erling Smørgrav 	return r->_recursive;
697b5038d7SDag-Erling Smørgrav }
707b5038d7SDag-Erling Smørgrav 
717b5038d7SDag-Erling Smørgrav bool
727b5038d7SDag-Erling Smørgrav ldns_resolver_debug(const ldns_resolver *r)
737b5038d7SDag-Erling Smørgrav {
747b5038d7SDag-Erling Smørgrav 	return r->_debug;
757b5038d7SDag-Erling Smørgrav }
767b5038d7SDag-Erling Smørgrav 
777b5038d7SDag-Erling Smørgrav bool
787b5038d7SDag-Erling Smørgrav ldns_resolver_dnsrch(const ldns_resolver *r)
797b5038d7SDag-Erling Smørgrav {
807b5038d7SDag-Erling Smørgrav 	return r->_dnsrch;
817b5038d7SDag-Erling Smørgrav }
827b5038d7SDag-Erling Smørgrav 
837b5038d7SDag-Erling Smørgrav bool
847b5038d7SDag-Erling Smørgrav ldns_resolver_fail(const ldns_resolver *r)
857b5038d7SDag-Erling Smørgrav {
867b5038d7SDag-Erling Smørgrav 	return r->_fail;
877b5038d7SDag-Erling Smørgrav }
887b5038d7SDag-Erling Smørgrav 
897b5038d7SDag-Erling Smørgrav bool
907b5038d7SDag-Erling Smørgrav ldns_resolver_defnames(const ldns_resolver *r)
917b5038d7SDag-Erling Smørgrav {
927b5038d7SDag-Erling Smørgrav 	return r->_defnames;
937b5038d7SDag-Erling Smørgrav }
947b5038d7SDag-Erling Smørgrav 
957b5038d7SDag-Erling Smørgrav ldns_rdf *
967b5038d7SDag-Erling Smørgrav ldns_resolver_domain(const ldns_resolver *r)
977b5038d7SDag-Erling Smørgrav {
987b5038d7SDag-Erling Smørgrav 	return r->_domain;
997b5038d7SDag-Erling Smørgrav }
1007b5038d7SDag-Erling Smørgrav 
1017b5038d7SDag-Erling Smørgrav ldns_rdf **
1027b5038d7SDag-Erling Smørgrav ldns_resolver_searchlist(const ldns_resolver *r)
1037b5038d7SDag-Erling Smørgrav {
1047b5038d7SDag-Erling Smørgrav 	return r->_searchlist;
1057b5038d7SDag-Erling Smørgrav }
1067b5038d7SDag-Erling Smørgrav 
1077b5038d7SDag-Erling Smørgrav ldns_rdf **
1087b5038d7SDag-Erling Smørgrav ldns_resolver_nameservers(const ldns_resolver *r)
1097b5038d7SDag-Erling Smørgrav {
1107b5038d7SDag-Erling Smørgrav 	return r->_nameservers;
1117b5038d7SDag-Erling Smørgrav }
1127b5038d7SDag-Erling Smørgrav 
1137b5038d7SDag-Erling Smørgrav size_t
1147b5038d7SDag-Erling Smørgrav ldns_resolver_nameserver_count(const ldns_resolver *r)
1157b5038d7SDag-Erling Smørgrav {
1167b5038d7SDag-Erling Smørgrav 	return r->_nameserver_count;
1177b5038d7SDag-Erling Smørgrav }
1187b5038d7SDag-Erling Smørgrav 
1197b5038d7SDag-Erling Smørgrav bool
1207b5038d7SDag-Erling Smørgrav ldns_resolver_dnssec(const ldns_resolver *r)
1217b5038d7SDag-Erling Smørgrav {
1227b5038d7SDag-Erling Smørgrav 	return r->_dnssec;
1237b5038d7SDag-Erling Smørgrav }
1247b5038d7SDag-Erling Smørgrav 
1257b5038d7SDag-Erling Smørgrav bool
1267b5038d7SDag-Erling Smørgrav ldns_resolver_dnssec_cd(const ldns_resolver *r)
1277b5038d7SDag-Erling Smørgrav {
1287b5038d7SDag-Erling Smørgrav 	return r->_dnssec_cd;
1297b5038d7SDag-Erling Smørgrav }
1307b5038d7SDag-Erling Smørgrav 
1317b5038d7SDag-Erling Smørgrav ldns_rr_list *
1327b5038d7SDag-Erling Smørgrav ldns_resolver_dnssec_anchors(const ldns_resolver *r)
1337b5038d7SDag-Erling Smørgrav {
1347b5038d7SDag-Erling Smørgrav     return r->_dnssec_anchors;
1357b5038d7SDag-Erling Smørgrav }
1367b5038d7SDag-Erling Smørgrav 
1377b5038d7SDag-Erling Smørgrav bool
1387b5038d7SDag-Erling Smørgrav ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys)
1397b5038d7SDag-Erling Smørgrav {
1407b5038d7SDag-Erling Smørgrav   size_t i;
1417b5038d7SDag-Erling Smørgrav   bool result = false;
1427b5038d7SDag-Erling Smørgrav 
1437b5038d7SDag-Erling Smørgrav   ldns_rr_list * trust_anchors;
1447b5038d7SDag-Erling Smørgrav   ldns_rr * cur_rr;
1457b5038d7SDag-Erling Smørgrav 
1467b5038d7SDag-Erling Smørgrav   if (!r || !keys) { return false; }
1477b5038d7SDag-Erling Smørgrav 
1487b5038d7SDag-Erling Smørgrav   trust_anchors = ldns_resolver_dnssec_anchors(r);
1497b5038d7SDag-Erling Smørgrav 
1507b5038d7SDag-Erling Smørgrav   if (!trust_anchors) { return false; }
1517b5038d7SDag-Erling Smørgrav 
1527b5038d7SDag-Erling Smørgrav   for (i = 0; i < ldns_rr_list_rr_count(keys); i++) {
1537b5038d7SDag-Erling Smørgrav 
1547b5038d7SDag-Erling Smørgrav     cur_rr = ldns_rr_list_rr(keys, i);
1557b5038d7SDag-Erling Smørgrav     if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) {
1567b5038d7SDag-Erling Smørgrav       if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); }
1577b5038d7SDag-Erling Smørgrav       result = true;
1587b5038d7SDag-Erling Smørgrav     }
1597b5038d7SDag-Erling Smørgrav   }
1607b5038d7SDag-Erling Smørgrav 
1617b5038d7SDag-Erling Smørgrav   return result;
1627b5038d7SDag-Erling Smørgrav }
1637b5038d7SDag-Erling Smørgrav 
1647b5038d7SDag-Erling Smørgrav bool
1657b5038d7SDag-Erling Smørgrav ldns_resolver_igntc(const ldns_resolver *r)
1667b5038d7SDag-Erling Smørgrav {
1677b5038d7SDag-Erling Smørgrav 	return r->_igntc;
1687b5038d7SDag-Erling Smørgrav }
1697b5038d7SDag-Erling Smørgrav 
1707b5038d7SDag-Erling Smørgrav bool
1717b5038d7SDag-Erling Smørgrav ldns_resolver_usevc(const ldns_resolver *r)
1727b5038d7SDag-Erling Smørgrav {
1737b5038d7SDag-Erling Smørgrav 	return r->_usevc;
1747b5038d7SDag-Erling Smørgrav }
1757b5038d7SDag-Erling Smørgrav 
1767b5038d7SDag-Erling Smørgrav size_t *
1777b5038d7SDag-Erling Smørgrav ldns_resolver_rtt(const ldns_resolver *r)
1787b5038d7SDag-Erling Smørgrav {
1797b5038d7SDag-Erling Smørgrav 	return r->_rtt;
1807b5038d7SDag-Erling Smørgrav }
1817b5038d7SDag-Erling Smørgrav 
1827b5038d7SDag-Erling Smørgrav size_t
1837b5038d7SDag-Erling Smørgrav ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos)
1847b5038d7SDag-Erling Smørgrav {
1857b5038d7SDag-Erling Smørgrav 	size_t *rtt;
1867b5038d7SDag-Erling Smørgrav 
1877b5038d7SDag-Erling Smørgrav 	assert(r != NULL);
1887b5038d7SDag-Erling Smørgrav 
1897b5038d7SDag-Erling Smørgrav 	rtt = ldns_resolver_rtt(r);
1907b5038d7SDag-Erling Smørgrav 
1917b5038d7SDag-Erling Smørgrav 	if (pos >= ldns_resolver_nameserver_count(r)) {
1927b5038d7SDag-Erling Smørgrav 		/* error ?*/
1937b5038d7SDag-Erling Smørgrav 		return 0;
1947b5038d7SDag-Erling Smørgrav 	} else {
1957b5038d7SDag-Erling Smørgrav 		return rtt[pos];
1967b5038d7SDag-Erling Smørgrav 	}
1977b5038d7SDag-Erling Smørgrav 
1987b5038d7SDag-Erling Smørgrav }
1997b5038d7SDag-Erling Smørgrav 
2007b5038d7SDag-Erling Smørgrav struct timeval
2017b5038d7SDag-Erling Smørgrav ldns_resolver_timeout(const ldns_resolver *r)
2027b5038d7SDag-Erling Smørgrav {
2037b5038d7SDag-Erling Smørgrav 	return r->_timeout;
2047b5038d7SDag-Erling Smørgrav }
2057b5038d7SDag-Erling Smørgrav 
2067b5038d7SDag-Erling Smørgrav char *
2077b5038d7SDag-Erling Smørgrav ldns_resolver_tsig_keyname(const ldns_resolver *r)
2087b5038d7SDag-Erling Smørgrav {
2097b5038d7SDag-Erling Smørgrav 	return r->_tsig_keyname;
2107b5038d7SDag-Erling Smørgrav }
2117b5038d7SDag-Erling Smørgrav 
2127b5038d7SDag-Erling Smørgrav char *
2137b5038d7SDag-Erling Smørgrav ldns_resolver_tsig_algorithm(const ldns_resolver *r)
2147b5038d7SDag-Erling Smørgrav {
2157b5038d7SDag-Erling Smørgrav 	return r->_tsig_algorithm;
2167b5038d7SDag-Erling Smørgrav }
2177b5038d7SDag-Erling Smørgrav 
2187b5038d7SDag-Erling Smørgrav char *
2197b5038d7SDag-Erling Smørgrav ldns_resolver_tsig_keydata(const ldns_resolver *r)
2207b5038d7SDag-Erling Smørgrav {
2217b5038d7SDag-Erling Smørgrav 	return r->_tsig_keydata;
2227b5038d7SDag-Erling Smørgrav }
2237b5038d7SDag-Erling Smørgrav 
2247b5038d7SDag-Erling Smørgrav bool
2257b5038d7SDag-Erling Smørgrav ldns_resolver_random(const ldns_resolver *r)
2267b5038d7SDag-Erling Smørgrav {
2277b5038d7SDag-Erling Smørgrav 	return r->_random;
2287b5038d7SDag-Erling Smørgrav }
2297b5038d7SDag-Erling Smørgrav 
2307b5038d7SDag-Erling Smørgrav size_t
2317b5038d7SDag-Erling Smørgrav ldns_resolver_searchlist_count(const ldns_resolver *r)
2327b5038d7SDag-Erling Smørgrav {
2337b5038d7SDag-Erling Smørgrav 	return r->_searchlist_count;
2347b5038d7SDag-Erling Smørgrav }
2357b5038d7SDag-Erling Smørgrav 
2367b5038d7SDag-Erling Smørgrav /* write */
2377b5038d7SDag-Erling Smørgrav void
2387b5038d7SDag-Erling Smørgrav ldns_resolver_set_port(ldns_resolver *r, uint16_t p)
2397b5038d7SDag-Erling Smørgrav {
2407b5038d7SDag-Erling Smørgrav 	r->_port = p;
2417b5038d7SDag-Erling Smørgrav }
2427b5038d7SDag-Erling Smørgrav 
243*17d15b25SDag-Erling Smørgrav void
244*17d15b25SDag-Erling Smørgrav ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s)
245*17d15b25SDag-Erling Smørgrav {
246*17d15b25SDag-Erling Smørgrav 	r->_source = s;
247*17d15b25SDag-Erling Smørgrav }
248*17d15b25SDag-Erling Smørgrav 
2497b5038d7SDag-Erling Smørgrav ldns_rdf *
2507b5038d7SDag-Erling Smørgrav ldns_resolver_pop_nameserver(ldns_resolver *r)
2517b5038d7SDag-Erling Smørgrav {
2527b5038d7SDag-Erling Smørgrav 	ldns_rdf **nameservers;
2537b5038d7SDag-Erling Smørgrav 	ldns_rdf *pop;
2547b5038d7SDag-Erling Smørgrav 	size_t ns_count;
2557b5038d7SDag-Erling Smørgrav 	size_t *rtt;
2567b5038d7SDag-Erling Smørgrav 
2577b5038d7SDag-Erling Smørgrav 	assert(r != NULL);
2587b5038d7SDag-Erling Smørgrav 
2597b5038d7SDag-Erling Smørgrav 	ns_count = ldns_resolver_nameserver_count(r);
2607b5038d7SDag-Erling Smørgrav 	nameservers = ldns_resolver_nameservers(r);
2617b5038d7SDag-Erling Smørgrav 	rtt = ldns_resolver_rtt(r);
2627b5038d7SDag-Erling Smørgrav 	if (ns_count == 0 || !nameservers) {
2637b5038d7SDag-Erling Smørgrav 		return NULL;
2647b5038d7SDag-Erling Smørgrav 	}
2657b5038d7SDag-Erling Smørgrav 
2667b5038d7SDag-Erling Smørgrav 	pop = nameservers[ns_count - 1];
2677b5038d7SDag-Erling Smørgrav 
2682787e39aSDag-Erling Smørgrav 	if (ns_count == 1) {
2692787e39aSDag-Erling Smørgrav 		LDNS_FREE(nameservers);
2702787e39aSDag-Erling Smørgrav 		LDNS_FREE(rtt);
2712787e39aSDag-Erling Smørgrav 
2722787e39aSDag-Erling Smørgrav 		ldns_resolver_set_nameservers(r, NULL);
2732787e39aSDag-Erling Smørgrav 		ldns_resolver_set_rtt(r, NULL);
2742787e39aSDag-Erling Smørgrav 	} else {
2752787e39aSDag-Erling Smørgrav 		nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *,
2762787e39aSDag-Erling Smørgrav 				(ns_count - 1));
2777b5038d7SDag-Erling Smørgrav 		rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1));
2787b5038d7SDag-Erling Smørgrav 
2797b5038d7SDag-Erling Smørgrav 	        ldns_resolver_set_nameservers(r, nameservers);
2807b5038d7SDag-Erling Smørgrav 	        ldns_resolver_set_rtt(r, rtt);
2812787e39aSDag-Erling Smørgrav 	}
2827b5038d7SDag-Erling Smørgrav 	/* decr the count */
2837b5038d7SDag-Erling Smørgrav 	ldns_resolver_dec_nameserver_count(r);
2847b5038d7SDag-Erling Smørgrav 	return pop;
2857b5038d7SDag-Erling Smørgrav }
2867b5038d7SDag-Erling Smørgrav 
2877b5038d7SDag-Erling Smørgrav ldns_status
2887b5038d7SDag-Erling Smørgrav ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n)
2897b5038d7SDag-Erling Smørgrav {
2907b5038d7SDag-Erling Smørgrav 	ldns_rdf **nameservers;
2917b5038d7SDag-Erling Smørgrav 	size_t ns_count;
2927b5038d7SDag-Erling Smørgrav 	size_t *rtt;
2937b5038d7SDag-Erling Smørgrav 
2947b5038d7SDag-Erling Smørgrav 	if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A &&
2957b5038d7SDag-Erling Smørgrav 			ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) {
2967b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
2977b5038d7SDag-Erling Smørgrav 	}
2987b5038d7SDag-Erling Smørgrav 
2997b5038d7SDag-Erling Smørgrav 	ns_count = ldns_resolver_nameserver_count(r);
3007b5038d7SDag-Erling Smørgrav 	nameservers = ldns_resolver_nameservers(r);
3017b5038d7SDag-Erling Smørgrav 	rtt = ldns_resolver_rtt(r);
3027b5038d7SDag-Erling Smørgrav 
3037b5038d7SDag-Erling Smørgrav 	/* make room for the next one */
3047b5038d7SDag-Erling Smørgrav 	if (ns_count == 0) {
3057b5038d7SDag-Erling Smørgrav 		nameservers = LDNS_XMALLOC(ldns_rdf *, 1);
3067b5038d7SDag-Erling Smørgrav 	} else {
3077b5038d7SDag-Erling Smørgrav 		nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1));
3087b5038d7SDag-Erling Smørgrav 	}
3097b5038d7SDag-Erling Smørgrav         if(!nameservers)
3107b5038d7SDag-Erling Smørgrav                 return LDNS_STATUS_MEM_ERR;
3117b5038d7SDag-Erling Smørgrav 
3127b5038d7SDag-Erling Smørgrav 	/* set the new value in the resolver */
3137b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_nameservers(r, nameservers);
3147b5038d7SDag-Erling Smørgrav 
3157b5038d7SDag-Erling Smørgrav 	/* don't forget the rtt */
3167b5038d7SDag-Erling Smørgrav 	if (ns_count == 0) {
3177b5038d7SDag-Erling Smørgrav 		rtt = LDNS_XMALLOC(size_t, 1);
3187b5038d7SDag-Erling Smørgrav 	} else {
3197b5038d7SDag-Erling Smørgrav 		rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1));
3207b5038d7SDag-Erling Smørgrav 	}
3217b5038d7SDag-Erling Smørgrav         if(!rtt)
3227b5038d7SDag-Erling Smørgrav                 return LDNS_STATUS_MEM_ERR;
3237b5038d7SDag-Erling Smørgrav 
3247b5038d7SDag-Erling Smørgrav 	/* slide n in its slot. */
3257b5038d7SDag-Erling Smørgrav 	/* we clone it here, because then we can free the original
3267b5038d7SDag-Erling Smørgrav 	 * rr's where it stood */
3277b5038d7SDag-Erling Smørgrav 	nameservers[ns_count] = ldns_rdf_clone(n);
3287b5038d7SDag-Erling Smørgrav 	rtt[ns_count] = LDNS_RESOLV_RTT_MIN;
3297b5038d7SDag-Erling Smørgrav 	ldns_resolver_incr_nameserver_count(r);
3307b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_rtt(r, rtt);
3317b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
3327b5038d7SDag-Erling Smørgrav }
3337b5038d7SDag-Erling Smørgrav 
3347b5038d7SDag-Erling Smørgrav ldns_status
3357b5038d7SDag-Erling Smørgrav ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr)
3367b5038d7SDag-Erling Smørgrav {
3377b5038d7SDag-Erling Smørgrav 	ldns_rdf *address;
3387b5038d7SDag-Erling Smørgrav 	if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A &&
3397b5038d7SDag-Erling Smørgrav 			ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) {
3407b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
3417b5038d7SDag-Erling Smørgrav 	}
3427b5038d7SDag-Erling Smørgrav 	address = ldns_rr_rdf(rr, 0); /* extract the ip number */
3437b5038d7SDag-Erling Smørgrav 	if (address) {
3447b5038d7SDag-Erling Smørgrav 		return ldns_resolver_push_nameserver(r, address);
3457b5038d7SDag-Erling Smørgrav 	} else {
3467b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
3477b5038d7SDag-Erling Smørgrav 	}
3487b5038d7SDag-Erling Smørgrav }
3497b5038d7SDag-Erling Smørgrav 
3507b5038d7SDag-Erling Smørgrav ldns_status
3517b5038d7SDag-Erling Smørgrav ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist)
3527b5038d7SDag-Erling Smørgrav {
3537b5038d7SDag-Erling Smørgrav 	ldns_rr *rr;
3547b5038d7SDag-Erling Smørgrav 	ldns_status stat;
3557b5038d7SDag-Erling Smørgrav 	size_t i;
3567b5038d7SDag-Erling Smørgrav 
3577b5038d7SDag-Erling Smørgrav 	stat = LDNS_STATUS_OK;
3587b5038d7SDag-Erling Smørgrav 	if (rrlist) {
3597b5038d7SDag-Erling Smørgrav 		for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
3607b5038d7SDag-Erling Smørgrav 			rr = ldns_rr_list_rr(rrlist, i);
3617b5038d7SDag-Erling Smørgrav 			if (ldns_resolver_push_nameserver_rr(r, rr) != LDNS_STATUS_OK) {
3627b5038d7SDag-Erling Smørgrav 				stat = LDNS_STATUS_ERR;
3637b5038d7SDag-Erling Smørgrav 				break;
3647b5038d7SDag-Erling Smørgrav 			}
3657b5038d7SDag-Erling Smørgrav 		}
3667b5038d7SDag-Erling Smørgrav 		return stat;
3677b5038d7SDag-Erling Smørgrav 	} else {
3687b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
3697b5038d7SDag-Erling Smørgrav 	}
3707b5038d7SDag-Erling Smørgrav }
3717b5038d7SDag-Erling Smørgrav 
3727b5038d7SDag-Erling Smørgrav void
3737b5038d7SDag-Erling Smørgrav ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s)
3747b5038d7SDag-Erling Smørgrav {
3757b5038d7SDag-Erling Smørgrav 	        r->_edns_udp_size = s;
3767b5038d7SDag-Erling Smørgrav }
3777b5038d7SDag-Erling Smørgrav 
3787b5038d7SDag-Erling Smørgrav void
3797b5038d7SDag-Erling Smørgrav ldns_resolver_set_recursive(ldns_resolver *r, bool re)
3807b5038d7SDag-Erling Smørgrav {
3817b5038d7SDag-Erling Smørgrav 	r->_recursive = re;
3827b5038d7SDag-Erling Smørgrav }
3837b5038d7SDag-Erling Smørgrav 
3847b5038d7SDag-Erling Smørgrav void
3857b5038d7SDag-Erling Smørgrav ldns_resolver_set_dnssec(ldns_resolver *r, bool d)
3867b5038d7SDag-Erling Smørgrav {
3877b5038d7SDag-Erling Smørgrav 	r->_dnssec = d;
3887b5038d7SDag-Erling Smørgrav }
3897b5038d7SDag-Erling Smørgrav 
3907b5038d7SDag-Erling Smørgrav void
3917b5038d7SDag-Erling Smørgrav ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d)
3927b5038d7SDag-Erling Smørgrav {
3937b5038d7SDag-Erling Smørgrav 	r->_dnssec_cd = d;
3947b5038d7SDag-Erling Smørgrav }
3957b5038d7SDag-Erling Smørgrav 
3967b5038d7SDag-Erling Smørgrav void
3977b5038d7SDag-Erling Smørgrav ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l)
3987b5038d7SDag-Erling Smørgrav {
3997b5038d7SDag-Erling Smørgrav   r->_dnssec_anchors = l;
4007b5038d7SDag-Erling Smørgrav }
4017b5038d7SDag-Erling Smørgrav 
4027b5038d7SDag-Erling Smørgrav ldns_status
4037b5038d7SDag-Erling Smørgrav ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr)
4047b5038d7SDag-Erling Smørgrav {
4057b5038d7SDag-Erling Smørgrav   ldns_rr_list * trust_anchors;
4067b5038d7SDag-Erling Smørgrav 
4072787e39aSDag-Erling Smørgrav   if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY &&
4082787e39aSDag-Erling Smørgrav                 ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS)) {
4092787e39aSDag-Erling Smørgrav 
4107b5038d7SDag-Erling Smørgrav     return LDNS_STATUS_ERR;
4117b5038d7SDag-Erling Smørgrav   }
4127b5038d7SDag-Erling Smørgrav 
4137b5038d7SDag-Erling Smørgrav   if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */
4147b5038d7SDag-Erling Smørgrav     trust_anchors = ldns_rr_list_new();
4157b5038d7SDag-Erling Smørgrav     ldns_resolver_set_dnssec_anchors(r, trust_anchors);
4167b5038d7SDag-Erling Smørgrav   }
4177b5038d7SDag-Erling Smørgrav 
4187b5038d7SDag-Erling Smørgrav   return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
4197b5038d7SDag-Erling Smørgrav }
4207b5038d7SDag-Erling Smørgrav 
4217b5038d7SDag-Erling Smørgrav void
4227b5038d7SDag-Erling Smørgrav ldns_resolver_set_igntc(ldns_resolver *r, bool i)
4237b5038d7SDag-Erling Smørgrav {
4247b5038d7SDag-Erling Smørgrav 	r->_igntc = i;
4257b5038d7SDag-Erling Smørgrav }
4267b5038d7SDag-Erling Smørgrav 
4277b5038d7SDag-Erling Smørgrav void
4287b5038d7SDag-Erling Smørgrav ldns_resolver_set_usevc(ldns_resolver *r, bool vc)
4297b5038d7SDag-Erling Smørgrav {
4307b5038d7SDag-Erling Smørgrav 	r->_usevc = vc;
4317b5038d7SDag-Erling Smørgrav }
4327b5038d7SDag-Erling Smørgrav 
4337b5038d7SDag-Erling Smørgrav void
4347b5038d7SDag-Erling Smørgrav ldns_resolver_set_debug(ldns_resolver *r, bool d)
4357b5038d7SDag-Erling Smørgrav {
4367b5038d7SDag-Erling Smørgrav 	r->_debug = d;
4377b5038d7SDag-Erling Smørgrav }
4387b5038d7SDag-Erling Smørgrav 
4397b5038d7SDag-Erling Smørgrav void
4407b5038d7SDag-Erling Smørgrav ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6)
4417b5038d7SDag-Erling Smørgrav {
4427b5038d7SDag-Erling Smørgrav 	r->_ip6 = ip6;
4437b5038d7SDag-Erling Smørgrav }
4447b5038d7SDag-Erling Smørgrav 
4457b5038d7SDag-Erling Smørgrav void
4467b5038d7SDag-Erling Smørgrav ldns_resolver_set_fail(ldns_resolver *r, bool f)
4477b5038d7SDag-Erling Smørgrav {
4487b5038d7SDag-Erling Smørgrav 	r->_fail =f;
4497b5038d7SDag-Erling Smørgrav }
4507b5038d7SDag-Erling Smørgrav 
4517b5038d7SDag-Erling Smørgrav static void
4527b5038d7SDag-Erling Smørgrav ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c)
4537b5038d7SDag-Erling Smørgrav {
4547b5038d7SDag-Erling Smørgrav 	r->_searchlist_count = c;
4557b5038d7SDag-Erling Smørgrav }
4567b5038d7SDag-Erling Smørgrav 
4577b5038d7SDag-Erling Smørgrav void
4587b5038d7SDag-Erling Smørgrav ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c)
4597b5038d7SDag-Erling Smørgrav {
4607b5038d7SDag-Erling Smørgrav 	r->_nameserver_count = c;
4617b5038d7SDag-Erling Smørgrav }
4627b5038d7SDag-Erling Smørgrav 
4637b5038d7SDag-Erling Smørgrav void
4647b5038d7SDag-Erling Smørgrav ldns_resolver_set_dnsrch(ldns_resolver *r, bool d)
4657b5038d7SDag-Erling Smørgrav {
4667b5038d7SDag-Erling Smørgrav 	r->_dnsrch = d;
4677b5038d7SDag-Erling Smørgrav }
4687b5038d7SDag-Erling Smørgrav 
4697b5038d7SDag-Erling Smørgrav void
4707b5038d7SDag-Erling Smørgrav ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry)
4717b5038d7SDag-Erling Smørgrav {
4727b5038d7SDag-Erling Smørgrav 	r->_retry = retry;
4737b5038d7SDag-Erling Smørgrav }
4747b5038d7SDag-Erling Smørgrav 
4757b5038d7SDag-Erling Smørgrav void
4767b5038d7SDag-Erling Smørgrav ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans)
4777b5038d7SDag-Erling Smørgrav {
4787b5038d7SDag-Erling Smørgrav 	r->_retrans = retrans;
4797b5038d7SDag-Erling Smørgrav }
4807b5038d7SDag-Erling Smørgrav 
4817b5038d7SDag-Erling Smørgrav void
4827b5038d7SDag-Erling Smørgrav ldns_resolver_set_fallback(ldns_resolver *r, bool fallback)
4837b5038d7SDag-Erling Smørgrav {
4847b5038d7SDag-Erling Smørgrav 	r->_fallback = fallback;
4857b5038d7SDag-Erling Smørgrav }
4867b5038d7SDag-Erling Smørgrav 
4877b5038d7SDag-Erling Smørgrav void
4887b5038d7SDag-Erling Smørgrav ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n)
4897b5038d7SDag-Erling Smørgrav {
4907b5038d7SDag-Erling Smørgrav 	r->_nameservers = n;
4917b5038d7SDag-Erling Smørgrav }
4927b5038d7SDag-Erling Smørgrav 
4937b5038d7SDag-Erling Smørgrav void
4947b5038d7SDag-Erling Smørgrav ldns_resolver_set_defnames(ldns_resolver *r, bool d)
4957b5038d7SDag-Erling Smørgrav {
4967b5038d7SDag-Erling Smørgrav 	r->_defnames = d;
4977b5038d7SDag-Erling Smørgrav }
4987b5038d7SDag-Erling Smørgrav 
4997b5038d7SDag-Erling Smørgrav void
5007b5038d7SDag-Erling Smørgrav ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt)
5017b5038d7SDag-Erling Smørgrav {
5027b5038d7SDag-Erling Smørgrav 	r->_rtt = rtt;
5037b5038d7SDag-Erling Smørgrav }
5047b5038d7SDag-Erling Smørgrav 
5057b5038d7SDag-Erling Smørgrav void
5067b5038d7SDag-Erling Smørgrav ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value)
5077b5038d7SDag-Erling Smørgrav {
5087b5038d7SDag-Erling Smørgrav 	size_t *rtt;
5097b5038d7SDag-Erling Smørgrav 
5107b5038d7SDag-Erling Smørgrav 	assert(r != NULL);
5117b5038d7SDag-Erling Smørgrav 
5127b5038d7SDag-Erling Smørgrav 	rtt = ldns_resolver_rtt(r);
5137b5038d7SDag-Erling Smørgrav 
5147b5038d7SDag-Erling Smørgrav 	if (pos >= ldns_resolver_nameserver_count(r)) {
5157b5038d7SDag-Erling Smørgrav 		/* error ?*/
5167b5038d7SDag-Erling Smørgrav 	} else {
5177b5038d7SDag-Erling Smørgrav 		rtt[pos] = value;
5187b5038d7SDag-Erling Smørgrav 	}
5197b5038d7SDag-Erling Smørgrav 
5207b5038d7SDag-Erling Smørgrav }
5217b5038d7SDag-Erling Smørgrav 
5227b5038d7SDag-Erling Smørgrav void
5237b5038d7SDag-Erling Smørgrav ldns_resolver_incr_nameserver_count(ldns_resolver *r)
5247b5038d7SDag-Erling Smørgrav {
5257b5038d7SDag-Erling Smørgrav 	size_t c;
5267b5038d7SDag-Erling Smørgrav 
5277b5038d7SDag-Erling Smørgrav 	c = ldns_resolver_nameserver_count(r);
5287b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_nameserver_count(r, ++c);
5297b5038d7SDag-Erling Smørgrav }
5307b5038d7SDag-Erling Smørgrav 
5317b5038d7SDag-Erling Smørgrav void
5327b5038d7SDag-Erling Smørgrav ldns_resolver_dec_nameserver_count(ldns_resolver *r)
5337b5038d7SDag-Erling Smørgrav {
5347b5038d7SDag-Erling Smørgrav 	size_t c;
5357b5038d7SDag-Erling Smørgrav 
5367b5038d7SDag-Erling Smørgrav 	c = ldns_resolver_nameserver_count(r);
5377b5038d7SDag-Erling Smørgrav 	if (c == 0) {
5387b5038d7SDag-Erling Smørgrav 		return;
5397b5038d7SDag-Erling Smørgrav 	} else {
5407b5038d7SDag-Erling Smørgrav 		ldns_resolver_set_nameserver_count(r, --c);
5417b5038d7SDag-Erling Smørgrav 	}
5427b5038d7SDag-Erling Smørgrav }
5437b5038d7SDag-Erling Smørgrav 
5447b5038d7SDag-Erling Smørgrav void
5457b5038d7SDag-Erling Smørgrav ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d)
5467b5038d7SDag-Erling Smørgrav {
5477b5038d7SDag-Erling Smørgrav 	r->_domain = d;
5487b5038d7SDag-Erling Smørgrav }
5497b5038d7SDag-Erling Smørgrav 
5507b5038d7SDag-Erling Smørgrav void
5517b5038d7SDag-Erling Smørgrav ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout)
5527b5038d7SDag-Erling Smørgrav {
5537b5038d7SDag-Erling Smørgrav 	r->_timeout.tv_sec = timeout.tv_sec;
5547b5038d7SDag-Erling Smørgrav 	r->_timeout.tv_usec = timeout.tv_usec;
5557b5038d7SDag-Erling Smørgrav }
5567b5038d7SDag-Erling Smørgrav 
5577b5038d7SDag-Erling Smørgrav void
5587b5038d7SDag-Erling Smørgrav ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d)
5597b5038d7SDag-Erling Smørgrav {
5607b5038d7SDag-Erling Smørgrav 	ldns_rdf **searchlist;
5617b5038d7SDag-Erling Smørgrav 	size_t list_count;
5627b5038d7SDag-Erling Smørgrav 
5637b5038d7SDag-Erling Smørgrav 	if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
5647b5038d7SDag-Erling Smørgrav 		return;
5657b5038d7SDag-Erling Smørgrav 	}
5667b5038d7SDag-Erling Smørgrav 
5677b5038d7SDag-Erling Smørgrav 	list_count = ldns_resolver_searchlist_count(r);
5687b5038d7SDag-Erling Smørgrav 	searchlist = ldns_resolver_searchlist(r);
5697b5038d7SDag-Erling Smørgrav 
5707b5038d7SDag-Erling Smørgrav 	searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1));
5717b5038d7SDag-Erling Smørgrav 	if (searchlist) {
5727b5038d7SDag-Erling Smørgrav 		r->_searchlist = searchlist;
5737b5038d7SDag-Erling Smørgrav 
5747b5038d7SDag-Erling Smørgrav 		searchlist[list_count] = ldns_rdf_clone(d);
5757b5038d7SDag-Erling Smørgrav 		ldns_resolver_set_searchlist_count(r, list_count + 1);
5767b5038d7SDag-Erling Smørgrav 	} /* no way to report mem err */
5777b5038d7SDag-Erling Smørgrav }
5787b5038d7SDag-Erling Smørgrav 
5797b5038d7SDag-Erling Smørgrav void
5807b5038d7SDag-Erling Smørgrav ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname)
5817b5038d7SDag-Erling Smørgrav {
5827b5038d7SDag-Erling Smørgrav 	LDNS_FREE(r->_tsig_keyname);
5837b5038d7SDag-Erling Smørgrav 	r->_tsig_keyname = strdup(tsig_keyname);
5847b5038d7SDag-Erling Smørgrav }
5857b5038d7SDag-Erling Smørgrav 
5867b5038d7SDag-Erling Smørgrav void
5877b5038d7SDag-Erling Smørgrav ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm)
5887b5038d7SDag-Erling Smørgrav {
5897b5038d7SDag-Erling Smørgrav 	LDNS_FREE(r->_tsig_algorithm);
5907b5038d7SDag-Erling Smørgrav 	r->_tsig_algorithm = strdup(tsig_algorithm);
5917b5038d7SDag-Erling Smørgrav }
5927b5038d7SDag-Erling Smørgrav 
5937b5038d7SDag-Erling Smørgrav void
5947b5038d7SDag-Erling Smørgrav ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata)
5957b5038d7SDag-Erling Smørgrav {
5967b5038d7SDag-Erling Smørgrav 	LDNS_FREE(r->_tsig_keydata);
5977b5038d7SDag-Erling Smørgrav 	r->_tsig_keydata = strdup(tsig_keydata);
5987b5038d7SDag-Erling Smørgrav }
5997b5038d7SDag-Erling Smørgrav 
6007b5038d7SDag-Erling Smørgrav void
6017b5038d7SDag-Erling Smørgrav ldns_resolver_set_random(ldns_resolver *r, bool b)
6027b5038d7SDag-Erling Smørgrav {
6037b5038d7SDag-Erling Smørgrav 	r->_random = b;
6047b5038d7SDag-Erling Smørgrav }
6057b5038d7SDag-Erling Smørgrav 
6067b5038d7SDag-Erling Smørgrav /* more sophisticated functions */
6077b5038d7SDag-Erling Smørgrav ldns_resolver *
6087b5038d7SDag-Erling Smørgrav ldns_resolver_new(void)
6097b5038d7SDag-Erling Smørgrav {
6107b5038d7SDag-Erling Smørgrav 	ldns_resolver *r;
6117b5038d7SDag-Erling Smørgrav 
6127b5038d7SDag-Erling Smørgrav 	r = LDNS_MALLOC(ldns_resolver);
6137b5038d7SDag-Erling Smørgrav 	if (!r) {
6147b5038d7SDag-Erling Smørgrav 		return NULL;
6157b5038d7SDag-Erling Smørgrav 	}
6167b5038d7SDag-Erling Smørgrav 
6177b5038d7SDag-Erling Smørgrav 	r->_searchlist = NULL;
6187b5038d7SDag-Erling Smørgrav 	r->_nameservers = NULL;
6197b5038d7SDag-Erling Smørgrav 	r->_rtt = NULL;
6207b5038d7SDag-Erling Smørgrav 
6217b5038d7SDag-Erling Smørgrav 	/* defaults are filled out */
6227b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_searchlist_count(r, 0);
6237b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_nameserver_count(r, 0);
6247b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_usevc(r, 0);
6257b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_port(r, LDNS_PORT);
6267b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_domain(r, NULL);
6277b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_defnames(r, false);
6287b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_retry(r, 3);
6297b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_retrans(r, 2);
6307b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_fallback(r, true);
6317b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_fail(r, false);
6327b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_edns_udp_size(r, 0);
6337b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_dnssec(r, false);
6347b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_dnssec_cd(r, false);
6357b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_dnssec_anchors(r, NULL);
6367b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY);
6377b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_igntc(r, false);
6387b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_recursive(r, false);
6397b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_dnsrch(r, true);
640*17d15b25SDag-Erling Smørgrav 	ldns_resolver_set_source(r, NULL);
6417b5038d7SDag-Erling Smørgrav 
6427b5038d7SDag-Erling Smørgrav 	/* randomize the nameserver to be queried
6437b5038d7SDag-Erling Smørgrav 	 * when there are multiple
6447b5038d7SDag-Erling Smørgrav 	 */
6457b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_random(r, true);
6467b5038d7SDag-Erling Smørgrav 
6477b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_debug(r, 0);
6487b5038d7SDag-Erling Smørgrav 
6497b5038d7SDag-Erling Smørgrav 	r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
6507b5038d7SDag-Erling Smørgrav 	r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
6517b5038d7SDag-Erling Smørgrav 
6527b5038d7SDag-Erling Smørgrav 	/* TODO: fd=0 is actually a valid socket (stdin),
6537b5038d7SDag-Erling Smørgrav            replace with -1 */
6547b5038d7SDag-Erling Smørgrav 	r->_socket = 0;
6557b5038d7SDag-Erling Smørgrav 	r->_axfr_soa_count = 0;
6567b5038d7SDag-Erling Smørgrav 	r->_axfr_i = 0;
6577b5038d7SDag-Erling Smørgrav 	r->_cur_axfr_pkt = NULL;
6587b5038d7SDag-Erling Smørgrav 
6597b5038d7SDag-Erling Smørgrav 	r->_tsig_keyname = NULL;
6607b5038d7SDag-Erling Smørgrav 	r->_tsig_keydata = NULL;
6617b5038d7SDag-Erling Smørgrav 	r->_tsig_algorithm = NULL;
6627b5038d7SDag-Erling Smørgrav 	return r;
6637b5038d7SDag-Erling Smørgrav }
6647b5038d7SDag-Erling Smørgrav 
6657b5038d7SDag-Erling Smørgrav ldns_status
6667b5038d7SDag-Erling Smørgrav ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp)
6677b5038d7SDag-Erling Smørgrav {
6687b5038d7SDag-Erling Smørgrav 	return ldns_resolver_new_frm_fp_l(res, fp, NULL);
6697b5038d7SDag-Erling Smørgrav }
6707b5038d7SDag-Erling Smørgrav 
6717b5038d7SDag-Erling Smørgrav ldns_status
6727b5038d7SDag-Erling Smørgrav ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
6737b5038d7SDag-Erling Smørgrav {
6747b5038d7SDag-Erling Smørgrav 	ldns_resolver *r;
6757b5038d7SDag-Erling Smørgrav 	const char *keyword[LDNS_RESOLV_KEYWORDS];
6767b5038d7SDag-Erling Smørgrav 	char word[LDNS_MAX_LINELEN + 1];
6777b5038d7SDag-Erling Smørgrav 	int8_t expect;
6787b5038d7SDag-Erling Smørgrav 	uint8_t i;
6797b5038d7SDag-Erling Smørgrav 	ldns_rdf *tmp;
6807b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
6817b5038d7SDag-Erling Smørgrav 	ldns_rr *tmp_rr;
6827b5038d7SDag-Erling Smørgrav #endif
6837b5038d7SDag-Erling Smørgrav 	ssize_t gtr, bgtr;
6847b5038d7SDag-Erling Smørgrav 	ldns_buffer *b;
6857b5038d7SDag-Erling Smørgrav         int lnr = 0, oldline;
686*17d15b25SDag-Erling Smørgrav 	FILE* myfp = fp;
6877b5038d7SDag-Erling Smørgrav         if(!line_nr) line_nr = &lnr;
6887b5038d7SDag-Erling Smørgrav 
689*17d15b25SDag-Erling Smørgrav 	if(!fp) {
690*17d15b25SDag-Erling Smørgrav 		myfp = fopen("/etc/resolv.conf", "r");
691*17d15b25SDag-Erling Smørgrav 		if(!myfp)
692*17d15b25SDag-Erling Smørgrav 			return LDNS_STATUS_FILE_ERR;
693*17d15b25SDag-Erling Smørgrav 	}
694*17d15b25SDag-Erling Smørgrav 
6957b5038d7SDag-Erling Smørgrav 	/* do this better
6967b5038d7SDag-Erling Smørgrav 	 * expect =
6977b5038d7SDag-Erling Smørgrav 	 * 0: keyword
6987b5038d7SDag-Erling Smørgrav 	 * 1: default domain dname
6997b5038d7SDag-Erling Smørgrav 	 * 2: NS aaaa or a record
7007b5038d7SDag-Erling Smørgrav 	 */
7017b5038d7SDag-Erling Smørgrav 
7027b5038d7SDag-Erling Smørgrav 	/* recognized keywords */
7037b5038d7SDag-Erling Smørgrav 	keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
7047b5038d7SDag-Erling Smørgrav 	keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
7057b5038d7SDag-Erling Smørgrav 	keyword[LDNS_RESOLV_SEARCH] = "search";
7067b5038d7SDag-Erling Smørgrav 	/* these two are read but not used atm TODO */
7077b5038d7SDag-Erling Smørgrav 	keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
7087b5038d7SDag-Erling Smørgrav 	keyword[LDNS_RESOLV_OPTIONS] = "options";
7097b5038d7SDag-Erling Smørgrav 	keyword[LDNS_RESOLV_ANCHOR] = "anchor";
7107b5038d7SDag-Erling Smørgrav 	expect = LDNS_RESOLV_KEYWORD;
7117b5038d7SDag-Erling Smørgrav 
7127b5038d7SDag-Erling Smørgrav 	r = ldns_resolver_new();
7137b5038d7SDag-Erling Smørgrav 	if (!r) {
714*17d15b25SDag-Erling Smørgrav 		if(!fp) fclose(myfp);
7157b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MEM_ERR;
7167b5038d7SDag-Erling Smørgrav 	}
7177b5038d7SDag-Erling Smørgrav 
7187b5038d7SDag-Erling Smørgrav 	gtr = 1;
7197b5038d7SDag-Erling Smørgrav 	word[0] = 0;
7207b5038d7SDag-Erling Smørgrav         oldline = *line_nr;
7217b5038d7SDag-Erling Smørgrav         expect = LDNS_RESOLV_KEYWORD;
7227b5038d7SDag-Erling Smørgrav 	while (gtr > 0) {
7237b5038d7SDag-Erling Smørgrav 		/* check comments */
7247b5038d7SDag-Erling Smørgrav 		if (word[0] == '#') {
7257b5038d7SDag-Erling Smørgrav                         word[0]='x';
7267b5038d7SDag-Erling Smørgrav                         if(oldline == *line_nr) {
7277b5038d7SDag-Erling Smørgrav                                 /* skip until end of line */
7287b5038d7SDag-Erling Smørgrav                                 int c;
7297b5038d7SDag-Erling Smørgrav                                 do {
730*17d15b25SDag-Erling Smørgrav                                         c = fgetc(myfp);
7317b5038d7SDag-Erling Smørgrav                                 } while(c != EOF && c != '\n');
732*17d15b25SDag-Erling Smørgrav                                 if(c=='\n') (*line_nr)++;
7337b5038d7SDag-Erling Smørgrav                         }
7347b5038d7SDag-Erling Smørgrav 			/* and read next to prepare for further parsing */
7357b5038d7SDag-Erling Smørgrav                         oldline = *line_nr;
7367b5038d7SDag-Erling Smørgrav 			continue;
7377b5038d7SDag-Erling Smørgrav 		}
7387b5038d7SDag-Erling Smørgrav                 oldline = *line_nr;
7397b5038d7SDag-Erling Smørgrav 		switch(expect) {
7407b5038d7SDag-Erling Smørgrav 			case LDNS_RESOLV_KEYWORD:
7417b5038d7SDag-Erling Smørgrav 				/* keyword */
742*17d15b25SDag-Erling Smørgrav 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
7437b5038d7SDag-Erling Smørgrav 				if (gtr != 0) {
7447b5038d7SDag-Erling Smørgrav                                         if(word[0] == '#') continue;
7457b5038d7SDag-Erling Smørgrav 					for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
7467b5038d7SDag-Erling Smørgrav 						if (strcasecmp(keyword[i], word) == 0) {
7477b5038d7SDag-Erling Smørgrav 							/* chosen the keyword and
7487b5038d7SDag-Erling Smørgrav 							 * expect values carefully
7497b5038d7SDag-Erling Smørgrav 	        					 */
7507b5038d7SDag-Erling Smørgrav 							expect = i;
7517b5038d7SDag-Erling Smørgrav 							break;
7527b5038d7SDag-Erling Smørgrav 						}
7537b5038d7SDag-Erling Smørgrav 					}
7547b5038d7SDag-Erling Smørgrav 					/* no keyword recognized */
7557b5038d7SDag-Erling Smørgrav 					if (expect == LDNS_RESOLV_KEYWORD) {
7567b5038d7SDag-Erling Smørgrav 						/* skip line */
7577b5038d7SDag-Erling Smørgrav 						/*
7587b5038d7SDag-Erling Smørgrav 						ldns_resolver_deep_free(r);
759*17d15b25SDag-Erling Smørgrav 						if(!fp) fclose(myfp);
7607b5038d7SDag-Erling Smørgrav 						return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
7617b5038d7SDag-Erling Smørgrav 						*/
7627b5038d7SDag-Erling Smørgrav 					}
7637b5038d7SDag-Erling Smørgrav 				}
7647b5038d7SDag-Erling Smørgrav 				break;
7657b5038d7SDag-Erling Smørgrav 			case LDNS_RESOLV_DEFDOMAIN:
7667b5038d7SDag-Erling Smørgrav 				/* default domain dname */
767*17d15b25SDag-Erling Smørgrav 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
7687b5038d7SDag-Erling Smørgrav 				if (gtr == 0) {
769*17d15b25SDag-Erling Smørgrav 					if(!fp) fclose(myfp);
7707b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
7717b5038d7SDag-Erling Smørgrav 				}
7727b5038d7SDag-Erling Smørgrav                                 if(word[0] == '#') {
7737b5038d7SDag-Erling Smørgrav                                         expect = LDNS_RESOLV_KEYWORD;
7747b5038d7SDag-Erling Smørgrav                                         continue;
7757b5038d7SDag-Erling Smørgrav                                 }
7767b5038d7SDag-Erling Smørgrav 				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
7777b5038d7SDag-Erling Smørgrav 				if (!tmp) {
7787b5038d7SDag-Erling Smørgrav 					ldns_resolver_deep_free(r);
779*17d15b25SDag-Erling Smørgrav 					if(!fp) fclose(myfp);
7807b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_SYNTAX_DNAME_ERR;
7817b5038d7SDag-Erling Smørgrav 				}
7827b5038d7SDag-Erling Smørgrav 
7837b5038d7SDag-Erling Smørgrav 				/* DOn't free, because we copy the pointer */
7847b5038d7SDag-Erling Smørgrav 				ldns_resolver_set_domain(r, tmp);
7857b5038d7SDag-Erling Smørgrav 				expect = LDNS_RESOLV_KEYWORD;
7867b5038d7SDag-Erling Smørgrav 				break;
7877b5038d7SDag-Erling Smørgrav 			case LDNS_RESOLV_NAMESERVER:
7887b5038d7SDag-Erling Smørgrav 				/* NS aaaa or a record */
789*17d15b25SDag-Erling Smørgrav 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
7907b5038d7SDag-Erling Smørgrav 				if (gtr == 0) {
791*17d15b25SDag-Erling Smørgrav 					if(!fp) fclose(myfp);
7927b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
7937b5038d7SDag-Erling Smørgrav 				}
7947b5038d7SDag-Erling Smørgrav                                 if(word[0] == '#') {
7957b5038d7SDag-Erling Smørgrav                                         expect = LDNS_RESOLV_KEYWORD;
7967b5038d7SDag-Erling Smørgrav                                         continue;
7977b5038d7SDag-Erling Smørgrav                                 }
7987b5038d7SDag-Erling Smørgrav                                 if(strchr(word, '%')) {
7997b5038d7SDag-Erling Smørgrav                                         /* snip off interface labels,
8007b5038d7SDag-Erling Smørgrav                                          * fe80::222:19ff:fe31:4222%eth0 */
8017b5038d7SDag-Erling Smørgrav                                         strchr(word, '%')[0]=0;
8027b5038d7SDag-Erling Smørgrav                                 }
8037b5038d7SDag-Erling Smørgrav 				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
8047b5038d7SDag-Erling Smørgrav 				if (!tmp) {
8057b5038d7SDag-Erling Smørgrav 					/* try ip4 */
8067b5038d7SDag-Erling Smørgrav 					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
8077b5038d7SDag-Erling Smørgrav 				}
8087b5038d7SDag-Erling Smørgrav 				/* could not parse it, exit */
8097b5038d7SDag-Erling Smørgrav 				if (!tmp) {
8107b5038d7SDag-Erling Smørgrav 					ldns_resolver_deep_free(r);
811*17d15b25SDag-Erling Smørgrav 					if(!fp) fclose(myfp);
8127b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_SYNTAX_ERR;
8137b5038d7SDag-Erling Smørgrav 				}
8147b5038d7SDag-Erling Smørgrav 				(void)ldns_resolver_push_nameserver(r, tmp);
8157b5038d7SDag-Erling Smørgrav 				ldns_rdf_deep_free(tmp);
8167b5038d7SDag-Erling Smørgrav 				expect = LDNS_RESOLV_KEYWORD;
8177b5038d7SDag-Erling Smørgrav 				break;
8187b5038d7SDag-Erling Smørgrav 			case LDNS_RESOLV_SEARCH:
8197b5038d7SDag-Erling Smørgrav 				/* search list domain dname */
820*17d15b25SDag-Erling Smørgrav 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
8217b5038d7SDag-Erling Smørgrav 				b = LDNS_MALLOC(ldns_buffer);
8227b5038d7SDag-Erling Smørgrav 				if(!b) {
8237b5038d7SDag-Erling Smørgrav 					ldns_resolver_deep_free(r);
824*17d15b25SDag-Erling Smørgrav 					if(!fp) fclose(myfp);
8257b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_MEM_ERR;
8267b5038d7SDag-Erling Smørgrav 				}
8277b5038d7SDag-Erling Smørgrav 
8287b5038d7SDag-Erling Smørgrav 				ldns_buffer_new_frm_data(b, word, (size_t) gtr);
8297b5038d7SDag-Erling Smørgrav 				if(ldns_buffer_status(b) != LDNS_STATUS_OK) {
8307b5038d7SDag-Erling Smørgrav 					LDNS_FREE(b);
8317b5038d7SDag-Erling Smørgrav 					ldns_resolver_deep_free(r);
832*17d15b25SDag-Erling Smørgrav 					if(!fp) fclose(myfp);
8337b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_MEM_ERR;
8347b5038d7SDag-Erling Smørgrav 				}
8357b5038d7SDag-Erling Smørgrav 				bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1);
8367b5038d7SDag-Erling Smørgrav 				while (bgtr > 0) {
8377b5038d7SDag-Erling Smørgrav 					gtr -= bgtr;
8387b5038d7SDag-Erling Smørgrav                                         if(word[0] == '#') {
8397b5038d7SDag-Erling Smørgrav                                                 expect = LDNS_RESOLV_KEYWORD;
8402787e39aSDag-Erling Smørgrav                                                 break;
8417b5038d7SDag-Erling Smørgrav                                         }
8427b5038d7SDag-Erling Smørgrav 					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
8437b5038d7SDag-Erling Smørgrav 					if (!tmp) {
8447b5038d7SDag-Erling Smørgrav 						ldns_resolver_deep_free(r);
8457b5038d7SDag-Erling Smørgrav 						ldns_buffer_free(b);
846*17d15b25SDag-Erling Smørgrav 						if(!fp) fclose(myfp);
8477b5038d7SDag-Erling Smørgrav 						return LDNS_STATUS_SYNTAX_DNAME_ERR;
8487b5038d7SDag-Erling Smørgrav 					}
8497b5038d7SDag-Erling Smørgrav 
8507b5038d7SDag-Erling Smørgrav 					ldns_resolver_push_searchlist(r, tmp);
8517b5038d7SDag-Erling Smørgrav 
8527b5038d7SDag-Erling Smørgrav 					ldns_rdf_deep_free(tmp);
8537b5038d7SDag-Erling Smørgrav 					bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
8547b5038d7SDag-Erling Smørgrav 					    (size_t) gtr + 1);
8557b5038d7SDag-Erling Smørgrav 				}
8567b5038d7SDag-Erling Smørgrav 				ldns_buffer_free(b);
8572787e39aSDag-Erling Smørgrav 				if (expect != LDNS_RESOLV_KEYWORD) {
8587b5038d7SDag-Erling Smørgrav 					gtr = 1;
8597b5038d7SDag-Erling Smørgrav 					expect = LDNS_RESOLV_KEYWORD;
8602787e39aSDag-Erling Smørgrav 				}
8617b5038d7SDag-Erling Smørgrav 				break;
8627b5038d7SDag-Erling Smørgrav 			case LDNS_RESOLV_SORTLIST:
863*17d15b25SDag-Erling Smørgrav 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
8647b5038d7SDag-Erling Smørgrav 				/* sortlist not implemented atm */
8657b5038d7SDag-Erling Smørgrav 				expect = LDNS_RESOLV_KEYWORD;
8667b5038d7SDag-Erling Smørgrav 				break;
8677b5038d7SDag-Erling Smørgrav 			case LDNS_RESOLV_OPTIONS:
868*17d15b25SDag-Erling Smørgrav 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
8697b5038d7SDag-Erling Smørgrav 				/* options not implemented atm */
8707b5038d7SDag-Erling Smørgrav 				expect = LDNS_RESOLV_KEYWORD;
8717b5038d7SDag-Erling Smørgrav 				break;
8727b5038d7SDag-Erling Smørgrav 			case LDNS_RESOLV_ANCHOR:
8737b5038d7SDag-Erling Smørgrav 				/* a file containing a DNSSEC trust anchor */
874*17d15b25SDag-Erling Smørgrav 				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
8757b5038d7SDag-Erling Smørgrav 				if (gtr == 0) {
8767b5038d7SDag-Erling Smørgrav 					ldns_resolver_deep_free(r);
877*17d15b25SDag-Erling Smørgrav 					if(!fp) fclose(myfp);
8787b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
8797b5038d7SDag-Erling Smørgrav 				}
8807b5038d7SDag-Erling Smørgrav                                 if(word[0] == '#') {
8817b5038d7SDag-Erling Smørgrav                                         expect = LDNS_RESOLV_KEYWORD;
8827b5038d7SDag-Erling Smørgrav                                         continue;
8837b5038d7SDag-Erling Smørgrav                                 }
8847b5038d7SDag-Erling Smørgrav 
8857b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
8867b5038d7SDag-Erling Smørgrav 				tmp_rr = ldns_read_anchor_file(word);
8877b5038d7SDag-Erling Smørgrav 				(void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
8887b5038d7SDag-Erling Smørgrav 				ldns_rr_free(tmp_rr);
8897b5038d7SDag-Erling Smørgrav #endif
8907b5038d7SDag-Erling Smørgrav 				expect = LDNS_RESOLV_KEYWORD;
8917b5038d7SDag-Erling Smørgrav 				break;
8927b5038d7SDag-Erling Smørgrav 		}
8937b5038d7SDag-Erling Smørgrav 	}
8947b5038d7SDag-Erling Smørgrav 
895*17d15b25SDag-Erling Smørgrav 	if(!fp)
896*17d15b25SDag-Erling Smørgrav 		fclose(myfp);
897*17d15b25SDag-Erling Smørgrav 
8987b5038d7SDag-Erling Smørgrav 	if (res) {
8997b5038d7SDag-Erling Smørgrav 		*res = r;
9007b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_OK;
9017b5038d7SDag-Erling Smørgrav 	} else {
9027b5038d7SDag-Erling Smørgrav 		ldns_resolver_deep_free(r);
9037b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_NULL;
9047b5038d7SDag-Erling Smørgrav 	}
9057b5038d7SDag-Erling Smørgrav }
9067b5038d7SDag-Erling Smørgrav 
9077b5038d7SDag-Erling Smørgrav ldns_status
9087b5038d7SDag-Erling Smørgrav ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
9097b5038d7SDag-Erling Smørgrav {
9107b5038d7SDag-Erling Smørgrav 	ldns_resolver *r;
9117b5038d7SDag-Erling Smørgrav 	FILE *fp;
9127b5038d7SDag-Erling Smørgrav 	ldns_status s;
9137b5038d7SDag-Erling Smørgrav 
9147b5038d7SDag-Erling Smørgrav 	if (!filename) {
9157b5038d7SDag-Erling Smørgrav 		fp = fopen(LDNS_RESOLV_CONF, "r");
9167b5038d7SDag-Erling Smørgrav 
9177b5038d7SDag-Erling Smørgrav 	} else {
9187b5038d7SDag-Erling Smørgrav 		fp = fopen(filename, "r");
9197b5038d7SDag-Erling Smørgrav 	}
9207b5038d7SDag-Erling Smørgrav 	if (!fp) {
9217b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_FILE_ERR;
9227b5038d7SDag-Erling Smørgrav 	}
9237b5038d7SDag-Erling Smørgrav 
9247b5038d7SDag-Erling Smørgrav 	s = ldns_resolver_new_frm_fp(&r, fp);
9257b5038d7SDag-Erling Smørgrav 	fclose(fp);
9267b5038d7SDag-Erling Smørgrav 	if (s == LDNS_STATUS_OK) {
9277b5038d7SDag-Erling Smørgrav 		if (res) {
9287b5038d7SDag-Erling Smørgrav 			*res = r;
9297b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_OK;
9307b5038d7SDag-Erling Smørgrav 		} else  {
9312787e39aSDag-Erling Smørgrav 			ldns_resolver_free(r);
9327b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_NULL;
9337b5038d7SDag-Erling Smørgrav 		}
9347b5038d7SDag-Erling Smørgrav 	}
9357b5038d7SDag-Erling Smørgrav 	return s;
9367b5038d7SDag-Erling Smørgrav }
9377b5038d7SDag-Erling Smørgrav 
9387b5038d7SDag-Erling Smørgrav void
9397b5038d7SDag-Erling Smørgrav ldns_resolver_free(ldns_resolver *res)
9407b5038d7SDag-Erling Smørgrav {
9417b5038d7SDag-Erling Smørgrav 	LDNS_FREE(res);
9427b5038d7SDag-Erling Smørgrav }
9437b5038d7SDag-Erling Smørgrav 
9447b5038d7SDag-Erling Smørgrav void
9457b5038d7SDag-Erling Smørgrav ldns_resolver_deep_free(ldns_resolver *res)
9467b5038d7SDag-Erling Smørgrav {
9477b5038d7SDag-Erling Smørgrav 	size_t i;
9487b5038d7SDag-Erling Smørgrav 
9497b5038d7SDag-Erling Smørgrav 	if (res) {
9507b5038d7SDag-Erling Smørgrav 		if (res->_searchlist) {
9517b5038d7SDag-Erling Smørgrav 			for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
9527b5038d7SDag-Erling Smørgrav 				ldns_rdf_deep_free(res->_searchlist[i]);
9537b5038d7SDag-Erling Smørgrav 			}
9547b5038d7SDag-Erling Smørgrav 			LDNS_FREE(res->_searchlist);
9557b5038d7SDag-Erling Smørgrav 		}
9567b5038d7SDag-Erling Smørgrav 		if (res->_nameservers) {
9577b5038d7SDag-Erling Smørgrav 			for (i = 0; i < res->_nameserver_count; i++) {
9587b5038d7SDag-Erling Smørgrav 				ldns_rdf_deep_free(res->_nameservers[i]);
9597b5038d7SDag-Erling Smørgrav 			}
9607b5038d7SDag-Erling Smørgrav 			LDNS_FREE(res->_nameservers);
9617b5038d7SDag-Erling Smørgrav 		}
9627b5038d7SDag-Erling Smørgrav 		if (ldns_resolver_domain(res)) {
9637b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(ldns_resolver_domain(res));
9647b5038d7SDag-Erling Smørgrav 		}
9657b5038d7SDag-Erling Smørgrav 		if (res->_tsig_keyname) {
9667b5038d7SDag-Erling Smørgrav 			LDNS_FREE(res->_tsig_keyname);
9677b5038d7SDag-Erling Smørgrav 		}
9687b5038d7SDag-Erling Smørgrav 		if (res->_tsig_keydata) {
9697b5038d7SDag-Erling Smørgrav 			LDNS_FREE(res->_tsig_keydata);
9707b5038d7SDag-Erling Smørgrav 		}
9717b5038d7SDag-Erling Smørgrav 		if (res->_tsig_algorithm) {
9727b5038d7SDag-Erling Smørgrav 			LDNS_FREE(res->_tsig_algorithm);
9737b5038d7SDag-Erling Smørgrav 		}
9747b5038d7SDag-Erling Smørgrav 
9757b5038d7SDag-Erling Smørgrav 		if (res->_cur_axfr_pkt) {
9767b5038d7SDag-Erling Smørgrav 			ldns_pkt_free(res->_cur_axfr_pkt);
9777b5038d7SDag-Erling Smørgrav 		}
9787b5038d7SDag-Erling Smørgrav 
9797b5038d7SDag-Erling Smørgrav 		if (res->_rtt) {
9807b5038d7SDag-Erling Smørgrav 			LDNS_FREE(res->_rtt);
9817b5038d7SDag-Erling Smørgrav 		}
9827b5038d7SDag-Erling Smørgrav 		if (res->_dnssec_anchors) {
9837b5038d7SDag-Erling Smørgrav 			ldns_rr_list_deep_free(res->_dnssec_anchors);
9847b5038d7SDag-Erling Smørgrav 		}
9857b5038d7SDag-Erling Smørgrav 		LDNS_FREE(res);
9867b5038d7SDag-Erling Smørgrav 	}
9877b5038d7SDag-Erling Smørgrav }
9887b5038d7SDag-Erling Smørgrav 
989*17d15b25SDag-Erling Smørgrav ldns_status
990*17d15b25SDag-Erling Smørgrav ldns_resolver_search_status(ldns_pkt** pkt,
991*17d15b25SDag-Erling Smørgrav 		ldns_resolver *r, const  ldns_rdf *name,
9927b5038d7SDag-Erling Smørgrav 		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
9937b5038d7SDag-Erling Smørgrav {
9947b5038d7SDag-Erling Smørgrav 	ldns_rdf *new_name;
9957b5038d7SDag-Erling Smørgrav 	ldns_rdf **search_list;
9967b5038d7SDag-Erling Smørgrav 	size_t i;
997*17d15b25SDag-Erling Smørgrav 	ldns_status s = LDNS_STATUS_OK;
9987b5038d7SDag-Erling Smørgrav 
9992787e39aSDag-Erling Smørgrav 	if (ldns_dname_absolute(name)) {
10007b5038d7SDag-Erling Smørgrav 		/* query as-is */
1001*17d15b25SDag-Erling Smørgrav 		return ldns_resolver_query_status(pkt, r, name, t, c, flags);
10027b5038d7SDag-Erling Smørgrav 	} else if (ldns_resolver_dnsrch(r)) {
10037b5038d7SDag-Erling Smørgrav 		search_list = ldns_resolver_searchlist(r);
10047b5038d7SDag-Erling Smørgrav 		for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
10057b5038d7SDag-Erling Smørgrav 			new_name = ldns_dname_cat_clone(name, search_list[i]);
10067b5038d7SDag-Erling Smørgrav 
1007*17d15b25SDag-Erling Smørgrav 			s = ldns_resolver_query_status(pkt, r,
1008*17d15b25SDag-Erling Smørgrav 					new_name, t, c, flags);
10097b5038d7SDag-Erling Smørgrav 			ldns_rdf_free(new_name);
1010*17d15b25SDag-Erling Smørgrav 			if (pkt) {
1011*17d15b25SDag-Erling Smørgrav 				if (s == LDNS_STATUS_OK && *pkt &&
1012*17d15b25SDag-Erling Smørgrav 						ldns_pkt_get_rcode(*pkt) ==
1013*17d15b25SDag-Erling Smørgrav 						LDNS_RCODE_NOERROR) {
1014*17d15b25SDag-Erling Smørgrav 					return LDNS_STATUS_OK;
1015*17d15b25SDag-Erling Smørgrav 				}
1016*17d15b25SDag-Erling Smørgrav 				ldns_pkt_free(*pkt);
10177b5038d7SDag-Erling Smørgrav 			}
10187b5038d7SDag-Erling Smørgrav 		}
10197b5038d7SDag-Erling Smørgrav 	}
1020*17d15b25SDag-Erling Smørgrav 	return s;
10217b5038d7SDag-Erling Smørgrav }
1022*17d15b25SDag-Erling Smørgrav 
1023*17d15b25SDag-Erling Smørgrav ldns_pkt *
1024*17d15b25SDag-Erling Smørgrav ldns_resolver_search(const ldns_resolver *r,const  ldns_rdf *name,
1025*17d15b25SDag-Erling Smørgrav 	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1026*17d15b25SDag-Erling Smørgrav {
1027*17d15b25SDag-Erling Smørgrav 	ldns_pkt* pkt = NULL;
1028*17d15b25SDag-Erling Smørgrav 	if (ldns_resolver_search_status(&pkt, (ldns_resolver *)r,
1029*17d15b25SDag-Erling Smørgrav 				name, t, c, flags) != LDNS_STATUS_OK) {
1030*17d15b25SDag-Erling Smørgrav 		ldns_pkt_free(pkt);
1031*17d15b25SDag-Erling Smørgrav 	}
1032*17d15b25SDag-Erling Smørgrav 	return pkt;
1033*17d15b25SDag-Erling Smørgrav }
1034*17d15b25SDag-Erling Smørgrav 
1035*17d15b25SDag-Erling Smørgrav ldns_status
1036*17d15b25SDag-Erling Smørgrav ldns_resolver_query_status(ldns_pkt** pkt,
1037*17d15b25SDag-Erling Smørgrav 		ldns_resolver *r, const ldns_rdf *name,
1038*17d15b25SDag-Erling Smørgrav 		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
1039*17d15b25SDag-Erling Smørgrav {
1040*17d15b25SDag-Erling Smørgrav 	ldns_rdf *newname;
1041*17d15b25SDag-Erling Smørgrav 	ldns_status status;
1042*17d15b25SDag-Erling Smørgrav 
1043*17d15b25SDag-Erling Smørgrav 	if (!ldns_resolver_defnames(r) || !ldns_resolver_domain(r)) {
1044*17d15b25SDag-Erling Smørgrav 		return ldns_resolver_send(pkt, r, name, t, c, flags);
1045*17d15b25SDag-Erling Smørgrav 	}
1046*17d15b25SDag-Erling Smørgrav 
1047*17d15b25SDag-Erling Smørgrav 	newname = ldns_dname_cat_clone(name, ldns_resolver_domain(r));
1048*17d15b25SDag-Erling Smørgrav 	if (!newname) {
1049*17d15b25SDag-Erling Smørgrav 		return LDNS_STATUS_MEM_ERR;
1050*17d15b25SDag-Erling Smørgrav 	}
1051*17d15b25SDag-Erling Smørgrav 	status = ldns_resolver_send(pkt, r, newname, t, c, flags);
1052*17d15b25SDag-Erling Smørgrav 	ldns_rdf_free(newname);
1053*17d15b25SDag-Erling Smørgrav 	return status;
10547b5038d7SDag-Erling Smørgrav }
10557b5038d7SDag-Erling Smørgrav 
10567b5038d7SDag-Erling Smørgrav ldns_pkt *
10577b5038d7SDag-Erling Smørgrav ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name,
10587b5038d7SDag-Erling Smørgrav 	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
10597b5038d7SDag-Erling Smørgrav {
1060*17d15b25SDag-Erling Smørgrav 	ldns_pkt* pkt = NULL;
1061*17d15b25SDag-Erling Smørgrav 	if (ldns_resolver_query_status(&pkt, (ldns_resolver *)r,
1062*17d15b25SDag-Erling Smørgrav 				name, t, c, flags) != LDNS_STATUS_OK) {
10637b5038d7SDag-Erling Smørgrav 		ldns_pkt_free(pkt);
10647b5038d7SDag-Erling Smørgrav 	}
10657b5038d7SDag-Erling Smørgrav 	return pkt;
10667b5038d7SDag-Erling Smørgrav }
10677b5038d7SDag-Erling Smørgrav 
10687b5038d7SDag-Erling Smørgrav static size_t *
10697b5038d7SDag-Erling Smørgrav ldns_resolver_backup_rtt(ldns_resolver *r)
10707b5038d7SDag-Erling Smørgrav {
10717b5038d7SDag-Erling Smørgrav 	size_t *new_rtt;
10727b5038d7SDag-Erling Smørgrav 	size_t *old_rtt = ldns_resolver_rtt(r);
10737b5038d7SDag-Erling Smørgrav 
10747b5038d7SDag-Erling Smørgrav 	if (old_rtt && ldns_resolver_nameserver_count(r)) {
10757b5038d7SDag-Erling Smørgrav 		new_rtt = LDNS_XMALLOC(size_t
10767b5038d7SDag-Erling Smørgrav 				, ldns_resolver_nameserver_count(r));
10777b5038d7SDag-Erling Smørgrav 		memcpy(new_rtt, old_rtt, sizeof(size_t)
10787b5038d7SDag-Erling Smørgrav 				* ldns_resolver_nameserver_count(r));
10797b5038d7SDag-Erling Smørgrav 		ldns_resolver_set_rtt(r, new_rtt);
10807b5038d7SDag-Erling Smørgrav 		return old_rtt;
10817b5038d7SDag-Erling Smørgrav 	}
10827b5038d7SDag-Erling Smørgrav 	return NULL;
10837b5038d7SDag-Erling Smørgrav }
10847b5038d7SDag-Erling Smørgrav 
10857b5038d7SDag-Erling Smørgrav static void
10867b5038d7SDag-Erling Smørgrav ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt)
10877b5038d7SDag-Erling Smørgrav {
10887b5038d7SDag-Erling Smørgrav 	size_t *cur_rtt = ldns_resolver_rtt(r);
10897b5038d7SDag-Erling Smørgrav 
10907b5038d7SDag-Erling Smørgrav 	if (cur_rtt) {
10917b5038d7SDag-Erling Smørgrav 		LDNS_FREE(cur_rtt);
10927b5038d7SDag-Erling Smørgrav 	}
10937b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_rtt(r, old_rtt);
10947b5038d7SDag-Erling Smørgrav }
10957b5038d7SDag-Erling Smørgrav 
10967b5038d7SDag-Erling Smørgrav ldns_status
10977b5038d7SDag-Erling Smørgrav ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r,
10987b5038d7SDag-Erling Smørgrav 				   ldns_pkt *query_pkt)
10997b5038d7SDag-Erling Smørgrav {
11007b5038d7SDag-Erling Smørgrav 	ldns_pkt *answer_pkt = NULL;
11017b5038d7SDag-Erling Smørgrav 	ldns_status stat = LDNS_STATUS_OK;
11027b5038d7SDag-Erling Smørgrav 	size_t *rtt;
11037b5038d7SDag-Erling Smørgrav 
11047b5038d7SDag-Erling Smørgrav 	stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt);
11057b5038d7SDag-Erling Smørgrav 	if (stat != LDNS_STATUS_OK) {
11067b5038d7SDag-Erling Smørgrav 		if(answer_pkt) {
11077b5038d7SDag-Erling Smørgrav 			ldns_pkt_free(answer_pkt);
11087b5038d7SDag-Erling Smørgrav 			answer_pkt = NULL;
11097b5038d7SDag-Erling Smørgrav 		}
11107b5038d7SDag-Erling Smørgrav 	} else {
11117b5038d7SDag-Erling Smørgrav 		/* if tc=1 fall back to EDNS and/or TCP */
11127b5038d7SDag-Erling Smørgrav 		/* check for tcp first (otherwise we don't care about tc=1) */
11137b5038d7SDag-Erling Smørgrav 		if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) {
11147b5038d7SDag-Erling Smørgrav 			if (ldns_pkt_tc(answer_pkt)) {
11157b5038d7SDag-Erling Smørgrav 				/* was EDNS0 set? */
11167b5038d7SDag-Erling Smørgrav 				if (ldns_pkt_edns_udp_size(query_pkt) == 0) {
11177b5038d7SDag-Erling Smørgrav 					ldns_pkt_set_edns_udp_size(query_pkt
11187b5038d7SDag-Erling Smørgrav 							, 4096);
11197b5038d7SDag-Erling Smørgrav 					ldns_pkt_free(answer_pkt);
11207b5038d7SDag-Erling Smørgrav 					/* Nameservers should not become
11217b5038d7SDag-Erling Smørgrav 					 * unreachable because fragments are
11227b5038d7SDag-Erling Smørgrav 					 * dropped (network error). We might
11237b5038d7SDag-Erling Smørgrav 					 * still have success with TCP.
11247b5038d7SDag-Erling Smørgrav 					 * Therefore maintain reachability
11257b5038d7SDag-Erling Smørgrav 					 * statuses of the nameservers by
11267b5038d7SDag-Erling Smørgrav 					 * backup and restore the rtt list.
11277b5038d7SDag-Erling Smørgrav 					 */
11287b5038d7SDag-Erling Smørgrav 					rtt = ldns_resolver_backup_rtt(r);
11297b5038d7SDag-Erling Smørgrav 					stat = ldns_send(&answer_pkt, r
11307b5038d7SDag-Erling Smørgrav 							, query_pkt);
11317b5038d7SDag-Erling Smørgrav 					ldns_resolver_restore_rtt(r, rtt);
11327b5038d7SDag-Erling Smørgrav 				}
11337b5038d7SDag-Erling Smørgrav 				/* either way, if it is still truncated, use TCP */
11347b5038d7SDag-Erling Smørgrav 				if (stat != LDNS_STATUS_OK ||
11357b5038d7SDag-Erling Smørgrav 				    ldns_pkt_tc(answer_pkt)) {
11367b5038d7SDag-Erling Smørgrav 					ldns_resolver_set_usevc(r, true);
11377b5038d7SDag-Erling Smørgrav 					ldns_pkt_free(answer_pkt);
11387b5038d7SDag-Erling Smørgrav 					stat = ldns_send(&answer_pkt, r, query_pkt);
11397b5038d7SDag-Erling Smørgrav 					ldns_resolver_set_usevc(r, false);
11407b5038d7SDag-Erling Smørgrav 				}
11417b5038d7SDag-Erling Smørgrav 			}
11427b5038d7SDag-Erling Smørgrav 		}
11437b5038d7SDag-Erling Smørgrav 	}
11447b5038d7SDag-Erling Smørgrav 
11457b5038d7SDag-Erling Smørgrav 	if (answer) {
11467b5038d7SDag-Erling Smørgrav 		*answer = answer_pkt;
11477b5038d7SDag-Erling Smørgrav 	}
11487b5038d7SDag-Erling Smørgrav 
11497b5038d7SDag-Erling Smørgrav 	return stat;
11507b5038d7SDag-Erling Smørgrav }
11517b5038d7SDag-Erling Smørgrav 
11527b5038d7SDag-Erling Smørgrav ldns_status
11537b5038d7SDag-Erling Smørgrav ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r,
11547b5038d7SDag-Erling Smørgrav                                 const ldns_rdf *name, ldns_rr_type t,
11557b5038d7SDag-Erling Smørgrav                                 ldns_rr_class c, uint16_t flags)
11567b5038d7SDag-Erling Smørgrav {
11577b5038d7SDag-Erling Smørgrav 	struct timeval now;
11587b5038d7SDag-Erling Smørgrav 
11597b5038d7SDag-Erling Smørgrav 	/* prepare a question pkt from the parameters
11607b5038d7SDag-Erling Smørgrav 	 * and then send this */
1161*17d15b25SDag-Erling Smørgrav 	if (t == LDNS_RR_TYPE_IXFR) {
1162*17d15b25SDag-Erling Smørgrav 		*query_pkt = ldns_pkt_ixfr_request_new(ldns_rdf_clone(name),
1163*17d15b25SDag-Erling Smørgrav 			c, flags, NULL);
1164*17d15b25SDag-Erling Smørgrav 	} else {
11657b5038d7SDag-Erling Smørgrav 		*query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags);
1166*17d15b25SDag-Erling Smørgrav 	}
11677b5038d7SDag-Erling Smørgrav 	if (!*query_pkt) {
11687b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
11697b5038d7SDag-Erling Smørgrav 	}
11707b5038d7SDag-Erling Smørgrav 
11717b5038d7SDag-Erling Smørgrav 	/* set DO bit if necessary */
11727b5038d7SDag-Erling Smørgrav 	if (ldns_resolver_dnssec(r)) {
11737b5038d7SDag-Erling Smørgrav 		if (ldns_resolver_edns_udp_size(r) == 0) {
11747b5038d7SDag-Erling Smørgrav 			ldns_resolver_set_edns_udp_size(r, 4096);
11757b5038d7SDag-Erling Smørgrav 		}
11767b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_edns_do(*query_pkt, true);
11777b5038d7SDag-Erling Smørgrav 		if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) {
11787b5038d7SDag-Erling Smørgrav 			ldns_pkt_set_cd(*query_pkt, true);
11797b5038d7SDag-Erling Smørgrav 		}
11807b5038d7SDag-Erling Smørgrav 	}
11817b5038d7SDag-Erling Smørgrav 
11827b5038d7SDag-Erling Smørgrav 	/* transfer the udp_edns_size from the resolver to the packet */
11837b5038d7SDag-Erling Smørgrav 	if (ldns_resolver_edns_udp_size(r) != 0) {
11847b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r));
11857b5038d7SDag-Erling Smørgrav 	}
11867b5038d7SDag-Erling Smørgrav 
11877b5038d7SDag-Erling Smørgrav 	/* set the timestamp */
11887b5038d7SDag-Erling Smørgrav 	now.tv_sec = time(NULL);
11897b5038d7SDag-Erling Smørgrav 	now.tv_usec = 0;
11907b5038d7SDag-Erling Smørgrav 	ldns_pkt_set_timestamp(*query_pkt, now);
11917b5038d7SDag-Erling Smørgrav 
11927b5038d7SDag-Erling Smørgrav 
11937b5038d7SDag-Erling Smørgrav 	if (ldns_resolver_debug(r)) {
11947b5038d7SDag-Erling Smørgrav 		ldns_pkt_print(stdout, *query_pkt);
11957b5038d7SDag-Erling Smørgrav 	}
11967b5038d7SDag-Erling Smørgrav 
11977b5038d7SDag-Erling Smørgrav 	/* only set the id if it is not set yet */
11987b5038d7SDag-Erling Smørgrav 	if (ldns_pkt_id(*query_pkt) == 0) {
11997b5038d7SDag-Erling Smørgrav 		ldns_pkt_set_random_id(*query_pkt);
12007b5038d7SDag-Erling Smørgrav 	}
12017b5038d7SDag-Erling Smørgrav 
12027b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
12037b5038d7SDag-Erling Smørgrav }
12047b5038d7SDag-Erling Smørgrav 
12057b5038d7SDag-Erling Smørgrav 
12067b5038d7SDag-Erling Smørgrav ldns_status
12077b5038d7SDag-Erling Smørgrav ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name,
12087b5038d7SDag-Erling Smørgrav 		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
12097b5038d7SDag-Erling Smørgrav {
12107b5038d7SDag-Erling Smørgrav 	ldns_pkt *query_pkt;
12117b5038d7SDag-Erling Smørgrav 	ldns_pkt *answer_pkt;
12127b5038d7SDag-Erling Smørgrav 	ldns_status status;
12137b5038d7SDag-Erling Smørgrav 
12147b5038d7SDag-Erling Smørgrav 	assert(r != NULL);
12157b5038d7SDag-Erling Smørgrav 	assert(name != NULL);
12167b5038d7SDag-Erling Smørgrav 
12177b5038d7SDag-Erling Smørgrav 	answer_pkt = NULL;
12187b5038d7SDag-Erling Smørgrav 
12197b5038d7SDag-Erling Smørgrav 	/* do all the preprocessing here, then fire of an query to
12207b5038d7SDag-Erling Smørgrav 	 * the network */
12217b5038d7SDag-Erling Smørgrav 
12227b5038d7SDag-Erling Smørgrav 	if (0 == t) {
12237b5038d7SDag-Erling Smørgrav 		t= LDNS_RR_TYPE_A;
12247b5038d7SDag-Erling Smørgrav 	}
12257b5038d7SDag-Erling Smørgrav 	if (0 == c) {
12267b5038d7SDag-Erling Smørgrav 		c= LDNS_RR_CLASS_IN;
12277b5038d7SDag-Erling Smørgrav 	}
12287b5038d7SDag-Erling Smørgrav 	if (0 == ldns_resolver_nameserver_count(r)) {
12297b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_RES_NO_NS;
12307b5038d7SDag-Erling Smørgrav 	}
12317b5038d7SDag-Erling Smørgrav 	if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
12327b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_RES_QUERY;
12337b5038d7SDag-Erling Smørgrav 	}
12347b5038d7SDag-Erling Smørgrav 
12357b5038d7SDag-Erling Smørgrav 	status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name,
12367b5038d7SDag-Erling Smørgrav 	                                         t, c, flags);
12377b5038d7SDag-Erling Smørgrav 	if (status != LDNS_STATUS_OK) {
12387b5038d7SDag-Erling Smørgrav 		return status;
12397b5038d7SDag-Erling Smørgrav 	}
12407b5038d7SDag-Erling Smørgrav 
12417b5038d7SDag-Erling Smørgrav 	/* if tsig values are set, tsign it */
12427b5038d7SDag-Erling Smørgrav 	/* TODO: make last 3 arguments optional too? maybe make complete
1243*17d15b25SDag-Erling Smørgrav 	         rr instead of separate values in resolver (and packet)
12447b5038d7SDag-Erling Smørgrav 	  Jelte
12457b5038d7SDag-Erling Smørgrav 	  should this go in pkt_prepare?
12467b5038d7SDag-Erling Smørgrav 	*/
12477b5038d7SDag-Erling Smørgrav 	if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
12487b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
12497b5038d7SDag-Erling Smørgrav 		status = ldns_pkt_tsig_sign(query_pkt,
12507b5038d7SDag-Erling Smørgrav 		                            ldns_resolver_tsig_keyname(r),
12517b5038d7SDag-Erling Smørgrav 		                            ldns_resolver_tsig_keydata(r),
12527b5038d7SDag-Erling Smørgrav 		                            300, ldns_resolver_tsig_algorithm(r), NULL);
12537b5038d7SDag-Erling Smørgrav 		if (status != LDNS_STATUS_OK) {
12542787e39aSDag-Erling Smørgrav 			ldns_pkt_free(query_pkt);
12557b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_CRYPTO_TSIG_ERR;
12567b5038d7SDag-Erling Smørgrav 		}
12577b5038d7SDag-Erling Smørgrav #else
12582787e39aSDag-Erling Smørgrav 		ldns_pkt_free(query_pkt);
12597b5038d7SDag-Erling Smørgrav 	        return LDNS_STATUS_CRYPTO_TSIG_ERR;
12607b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
12617b5038d7SDag-Erling Smørgrav 	}
12627b5038d7SDag-Erling Smørgrav 
12637b5038d7SDag-Erling Smørgrav 	status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
12647b5038d7SDag-Erling Smørgrav 	ldns_pkt_free(query_pkt);
12657b5038d7SDag-Erling Smørgrav 
12667b5038d7SDag-Erling Smørgrav 	/* allows answer to be NULL when not interested in return value */
12677b5038d7SDag-Erling Smørgrav 	if (answer) {
12687b5038d7SDag-Erling Smørgrav 		*answer = answer_pkt;
12697b5038d7SDag-Erling Smørgrav 	}
12707b5038d7SDag-Erling Smørgrav 	return status;
12717b5038d7SDag-Erling Smørgrav }
12727b5038d7SDag-Erling Smørgrav 
12737b5038d7SDag-Erling Smørgrav ldns_rr *
12747b5038d7SDag-Erling Smørgrav ldns_axfr_next(ldns_resolver *resolver)
12757b5038d7SDag-Erling Smørgrav {
12767b5038d7SDag-Erling Smørgrav 	ldns_rr *cur_rr;
12777b5038d7SDag-Erling Smørgrav 	uint8_t *packet_wire;
12787b5038d7SDag-Erling Smørgrav 	size_t packet_wire_size;
12797b5038d7SDag-Erling Smørgrav 	ldns_lookup_table *rcode;
12807b5038d7SDag-Erling Smørgrav 	ldns_status status;
12817b5038d7SDag-Erling Smørgrav 
12827b5038d7SDag-Erling Smørgrav 	/* check if start() has been called */
12837b5038d7SDag-Erling Smørgrav 	if (!resolver || resolver->_socket == 0) {
12847b5038d7SDag-Erling Smørgrav 		return NULL;
12857b5038d7SDag-Erling Smørgrav 	}
12867b5038d7SDag-Erling Smørgrav 
12877b5038d7SDag-Erling Smørgrav 	if (resolver->_cur_axfr_pkt) {
12887b5038d7SDag-Erling Smørgrav 		if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) {
12897b5038d7SDag-Erling Smørgrav 			ldns_pkt_free(resolver->_cur_axfr_pkt);
12907b5038d7SDag-Erling Smørgrav 			resolver->_cur_axfr_pkt = NULL;
12917b5038d7SDag-Erling Smørgrav 			return ldns_axfr_next(resolver);
12927b5038d7SDag-Erling Smørgrav 		}
12937b5038d7SDag-Erling Smørgrav 		cur_rr = ldns_rr_clone(ldns_rr_list_rr(
12947b5038d7SDag-Erling Smørgrav 					ldns_pkt_answer(resolver->_cur_axfr_pkt),
12957b5038d7SDag-Erling Smørgrav 					resolver->_axfr_i));
12967b5038d7SDag-Erling Smørgrav 		resolver->_axfr_i++;
12977b5038d7SDag-Erling Smørgrav 		if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
12987b5038d7SDag-Erling Smørgrav 			resolver->_axfr_soa_count++;
12997b5038d7SDag-Erling Smørgrav 			if (resolver->_axfr_soa_count >= 2) {
13007b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK
13017b5038d7SDag-Erling Smørgrav 				close(resolver->_socket);
13027b5038d7SDag-Erling Smørgrav #else
13037b5038d7SDag-Erling Smørgrav 				closesocket(resolver->_socket);
13047b5038d7SDag-Erling Smørgrav #endif
13057b5038d7SDag-Erling Smørgrav 				resolver->_socket = 0;
13067b5038d7SDag-Erling Smørgrav 				ldns_pkt_free(resolver->_cur_axfr_pkt);
13077b5038d7SDag-Erling Smørgrav 				resolver->_cur_axfr_pkt = NULL;
13087b5038d7SDag-Erling Smørgrav 			}
13097b5038d7SDag-Erling Smørgrav 		}
13107b5038d7SDag-Erling Smørgrav 		return cur_rr;
13117b5038d7SDag-Erling Smørgrav 	} else {
13127b5038d7SDag-Erling Smørgrav 		packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size);
13137b5038d7SDag-Erling Smørgrav 		if(!packet_wire)
13147b5038d7SDag-Erling Smørgrav 			return NULL;
13157b5038d7SDag-Erling Smørgrav 
13167b5038d7SDag-Erling Smørgrav 		status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire,
13177b5038d7SDag-Erling Smørgrav 				     packet_wire_size);
13187b5038d7SDag-Erling Smørgrav 		LDNS_FREE(packet_wire);
13197b5038d7SDag-Erling Smørgrav 
13207b5038d7SDag-Erling Smørgrav 		resolver->_axfr_i = 0;
13217b5038d7SDag-Erling Smørgrav 		if (status != LDNS_STATUS_OK) {
13227b5038d7SDag-Erling Smørgrav 			/* TODO: make status return type of this function (...api change) */
1323*17d15b25SDag-Erling Smørgrav #ifdef STDERR_MSGS
13247b5038d7SDag-Erling Smørgrav 			fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status));
1325*17d15b25SDag-Erling Smørgrav #endif
13267b5038d7SDag-Erling Smørgrav 
1327*17d15b25SDag-Erling Smørgrav 			/* we must now also close the socket, otherwise subsequent uses of the
13287b5038d7SDag-Erling Smørgrav 			   same resolver structure will fail because the link is still open or
13297b5038d7SDag-Erling Smørgrav 			   in an undefined state */
13307b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK
13317b5038d7SDag-Erling Smørgrav 			close(resolver->_socket);
13327b5038d7SDag-Erling Smørgrav #else
13337b5038d7SDag-Erling Smørgrav 			closesocket(resolver->_socket);
13347b5038d7SDag-Erling Smørgrav #endif
13357b5038d7SDag-Erling Smørgrav 			resolver->_socket = 0;
13367b5038d7SDag-Erling Smørgrav 
13377b5038d7SDag-Erling Smørgrav 			return NULL;
13387b5038d7SDag-Erling Smørgrav 		} else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
13397b5038d7SDag-Erling Smørgrav 			rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt));
1340*17d15b25SDag-Erling Smørgrav #ifdef STDERR_MSGS
13412787e39aSDag-Erling Smørgrav 			if (rcode) {
13422787e39aSDag-Erling Smørgrav 				fprintf(stderr, "Error in AXFR: %s\n",
13432787e39aSDag-Erling Smørgrav 						rcode->name);
13442787e39aSDag-Erling Smørgrav 			} else {
13452787e39aSDag-Erling Smørgrav 				fprintf(stderr, "Error in AXFR: %d\n",
13462787e39aSDag-Erling Smørgrav 						(int) ldns_pkt_get_rcode(
13472787e39aSDag-Erling Smørgrav 						resolver->_cur_axfr_pkt));
13482787e39aSDag-Erling Smørgrav 			}
1349*17d15b25SDag-Erling Smørgrav #endif
13507b5038d7SDag-Erling Smørgrav 
1351*17d15b25SDag-Erling Smørgrav 			/* we must now also close the socket, otherwise subsequent uses of the
13527b5038d7SDag-Erling Smørgrav 			   same resolver structure will fail because the link is still open or
13537b5038d7SDag-Erling Smørgrav 			   in an undefined state */
13547b5038d7SDag-Erling Smørgrav #ifndef USE_WINSOCK
13557b5038d7SDag-Erling Smørgrav 			close(resolver->_socket);
13567b5038d7SDag-Erling Smørgrav #else
13577b5038d7SDag-Erling Smørgrav 			closesocket(resolver->_socket);
13587b5038d7SDag-Erling Smørgrav #endif
13597b5038d7SDag-Erling Smørgrav 			resolver->_socket = 0;
13607b5038d7SDag-Erling Smørgrav 
13617b5038d7SDag-Erling Smørgrav 			return NULL;
13627b5038d7SDag-Erling Smørgrav 		} else {
13637b5038d7SDag-Erling Smørgrav 			return ldns_axfr_next(resolver);
13647b5038d7SDag-Erling Smørgrav 		}
13657b5038d7SDag-Erling Smørgrav 
13667b5038d7SDag-Erling Smørgrav 	}
13677b5038d7SDag-Erling Smørgrav 
13687b5038d7SDag-Erling Smørgrav }
13697b5038d7SDag-Erling Smørgrav 
1370*17d15b25SDag-Erling Smørgrav /* this function is needed to abort a transfer that is in progress;
1371*17d15b25SDag-Erling Smørgrav  * without it an aborted transfer will lead to the AXFR code in the
1372*17d15b25SDag-Erling Smørgrav  * library staying in an indetermined state because the socket for the
1373*17d15b25SDag-Erling Smørgrav  * AXFR is never closed
1374*17d15b25SDag-Erling Smørgrav  */
1375*17d15b25SDag-Erling Smørgrav static void
1376*17d15b25SDag-Erling Smørgrav ldns_axfr_abort(ldns_resolver *resolver)
1377*17d15b25SDag-Erling Smørgrav {
1378*17d15b25SDag-Erling Smørgrav 	/* Only abort if an actual AXFR is in progress */
1379*17d15b25SDag-Erling Smørgrav 	if (resolver->_socket != 0)
1380*17d15b25SDag-Erling Smørgrav 	{
1381*17d15b25SDag-Erling Smørgrav #ifndef USE_WINSOCK
1382*17d15b25SDag-Erling Smørgrav 		close(resolver->_socket);
1383*17d15b25SDag-Erling Smørgrav #else
1384*17d15b25SDag-Erling Smørgrav 		closesocket(resolver->_socket);
1385*17d15b25SDag-Erling Smørgrav #endif
1386*17d15b25SDag-Erling Smørgrav 		resolver->_socket = 0;
1387*17d15b25SDag-Erling Smørgrav 	}
1388*17d15b25SDag-Erling Smørgrav }
1389*17d15b25SDag-Erling Smørgrav 
13907b5038d7SDag-Erling Smørgrav bool
13917b5038d7SDag-Erling Smørgrav ldns_axfr_complete(const ldns_resolver *res)
13927b5038d7SDag-Erling Smørgrav {
13937b5038d7SDag-Erling Smørgrav 	/* complete when soa count is 2? */
13947b5038d7SDag-Erling Smørgrav 	return res->_axfr_soa_count == 2;
13957b5038d7SDag-Erling Smørgrav }
13967b5038d7SDag-Erling Smørgrav 
13977b5038d7SDag-Erling Smørgrav ldns_pkt *
13987b5038d7SDag-Erling Smørgrav ldns_axfr_last_pkt(const ldns_resolver *res)
13997b5038d7SDag-Erling Smørgrav {
14007b5038d7SDag-Erling Smørgrav 	return res->_cur_axfr_pkt;
14017b5038d7SDag-Erling Smørgrav }
14027b5038d7SDag-Erling Smørgrav 
14037b5038d7SDag-Erling Smørgrav /* random isn't really that good */
14047b5038d7SDag-Erling Smørgrav void
14057b5038d7SDag-Erling Smørgrav ldns_resolver_nameservers_randomize(ldns_resolver *r)
14067b5038d7SDag-Erling Smørgrav {
14077b5038d7SDag-Erling Smørgrav 	uint16_t i, j;
14082787e39aSDag-Erling Smørgrav 	ldns_rdf **ns, *tmpns;
14092787e39aSDag-Erling Smørgrav 	size_t *rtt, tmprtt;
14107b5038d7SDag-Erling Smørgrav 
14117b5038d7SDag-Erling Smørgrav 	/* should I check for ldns_resolver_random?? */
14127b5038d7SDag-Erling Smørgrav 	assert(r != NULL);
14137b5038d7SDag-Erling Smørgrav 
14147b5038d7SDag-Erling Smørgrav 	ns = ldns_resolver_nameservers(r);
14152787e39aSDag-Erling Smørgrav 	rtt = ldns_resolver_rtt(r);
14167b5038d7SDag-Erling Smørgrav 	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
14177b5038d7SDag-Erling Smørgrav 		j = ldns_get_random() % ldns_resolver_nameserver_count(r);
14182787e39aSDag-Erling Smørgrav 		tmpns = ns[i];
14197b5038d7SDag-Erling Smørgrav 		ns[i] = ns[j];
14202787e39aSDag-Erling Smørgrav 		ns[j] = tmpns;
14212787e39aSDag-Erling Smørgrav 		tmprtt = rtt[i];
14222787e39aSDag-Erling Smørgrav 		rtt[i] = rtt[j];
14232787e39aSDag-Erling Smørgrav 		rtt[j] = tmprtt;
14247b5038d7SDag-Erling Smørgrav 	}
14257b5038d7SDag-Erling Smørgrav 	ldns_resolver_set_nameservers(r, ns);
14267b5038d7SDag-Erling Smørgrav }
14277b5038d7SDag-Erling Smørgrav 
1428