xref: /freebsd/contrib/unbound/daemon/cachedump.c (revision 335c7cda)
1b7579f77SDag-Erling Smørgrav /*
2b7579f77SDag-Erling Smørgrav  * daemon/cachedump.c - dump the cache to text format.
3b7579f77SDag-Erling Smørgrav  *
4b7579f77SDag-Erling Smørgrav  * Copyright (c) 2008, NLnet Labs. All rights reserved.
5b7579f77SDag-Erling Smørgrav  *
6b7579f77SDag-Erling Smørgrav  * This software is open source.
7b7579f77SDag-Erling Smørgrav  *
8b7579f77SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
9b7579f77SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
10b7579f77SDag-Erling Smørgrav  * are met:
11b7579f77SDag-Erling Smørgrav  *
12b7579f77SDag-Erling Smørgrav  * Redistributions of source code must retain the above copyright notice,
13b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer.
14b7579f77SDag-Erling Smørgrav  *
15b7579f77SDag-Erling Smørgrav  * Redistributions in binary form must reproduce the above copyright notice,
16b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer in the documentation
17b7579f77SDag-Erling Smørgrav  * and/or other materials provided with the distribution.
18b7579f77SDag-Erling Smørgrav  *
19b7579f77SDag-Erling Smørgrav  * Neither the name of the NLNET LABS nor the names of its contributors may
20b7579f77SDag-Erling Smørgrav  * be used to endorse or promote products derived from this software without
21b7579f77SDag-Erling Smørgrav  * specific prior written permission.
22b7579f77SDag-Erling Smørgrav  *
23b7579f77SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2417d15b25SDag-Erling Smørgrav  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2517d15b25SDag-Erling Smørgrav  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2617d15b25SDag-Erling Smørgrav  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2717d15b25SDag-Erling Smørgrav  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2817d15b25SDag-Erling Smørgrav  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2917d15b25SDag-Erling Smørgrav  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3017d15b25SDag-Erling Smørgrav  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3117d15b25SDag-Erling Smørgrav  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3217d15b25SDag-Erling Smørgrav  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3317d15b25SDag-Erling Smørgrav  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34b7579f77SDag-Erling Smørgrav  */
35b7579f77SDag-Erling Smørgrav 
36b7579f77SDag-Erling Smørgrav /**
37b7579f77SDag-Erling Smørgrav  * \file
38b7579f77SDag-Erling Smørgrav  *
39b7579f77SDag-Erling Smørgrav  * This file contains functions to read and write the cache(s)
40b7579f77SDag-Erling Smørgrav  * to text format.
41b7579f77SDag-Erling Smørgrav  */
42b7579f77SDag-Erling Smørgrav #include "config.h"
4317d15b25SDag-Erling Smørgrav #include <openssl/ssl.h>
44b7579f77SDag-Erling Smørgrav #include "daemon/cachedump.h"
45b7579f77SDag-Erling Smørgrav #include "daemon/remote.h"
46b7579f77SDag-Erling Smørgrav #include "daemon/worker.h"
47b7579f77SDag-Erling Smørgrav #include "services/cache/rrset.h"
48b7579f77SDag-Erling Smørgrav #include "services/cache/dns.h"
49b7579f77SDag-Erling Smørgrav #include "services/cache/infra.h"
50a39a5a69SCy Schubert #include "services/outside_network.h"
51b7579f77SDag-Erling Smørgrav #include "util/data/msgreply.h"
52b7579f77SDag-Erling Smørgrav #include "util/regional.h"
53b7579f77SDag-Erling Smørgrav #include "util/net_help.h"
54b7579f77SDag-Erling Smørgrav #include "util/data/dname.h"
55a39a5a69SCy Schubert #include "util/config_file.h"
56b7579f77SDag-Erling Smørgrav #include "iterator/iterator.h"
57b7579f77SDag-Erling Smørgrav #include "iterator/iter_delegpt.h"
58b7579f77SDag-Erling Smørgrav #include "iterator/iter_utils.h"
59b7579f77SDag-Erling Smørgrav #include "iterator/iter_fwd.h"
60b7579f77SDag-Erling Smørgrav #include "iterator/iter_hints.h"
6109a3aaf3SDag-Erling Smørgrav #include "sldns/sbuffer.h"
6209a3aaf3SDag-Erling Smørgrav #include "sldns/wire2str.h"
6309a3aaf3SDag-Erling Smørgrav #include "sldns/str2wire.h"
64b7579f77SDag-Erling Smørgrav 
65b7579f77SDag-Erling Smørgrav /** dump one rrset zonefile line */
66b7579f77SDag-Erling Smørgrav static int
dump_rrset_line(RES * ssl,struct ub_packed_rrset_key * k,time_t now,size_t i)677da0adf7SDag-Erling Smørgrav dump_rrset_line(RES* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
68b7579f77SDag-Erling Smørgrav {
6917d15b25SDag-Erling Smørgrav 	char s[65535];
7017d15b25SDag-Erling Smørgrav 	if(!packed_rr_to_string(k, i, now, s, sizeof(s))) {
71b7579f77SDag-Erling Smørgrav 		return ssl_printf(ssl, "BADRR\n");
72b7579f77SDag-Erling Smørgrav 	}
7317d15b25SDag-Erling Smørgrav 	return ssl_printf(ssl, "%s", s);
74b7579f77SDag-Erling Smørgrav }
75b7579f77SDag-Erling Smørgrav 
76b7579f77SDag-Erling Smørgrav /** dump rrset key and data info */
77b7579f77SDag-Erling Smørgrav static int
dump_rrset(RES * ssl,struct ub_packed_rrset_key * k,struct packed_rrset_data * d,time_t now)787da0adf7SDag-Erling Smørgrav dump_rrset(RES* ssl, struct ub_packed_rrset_key* k,
7917d15b25SDag-Erling Smørgrav 	struct packed_rrset_data* d, time_t now)
80b7579f77SDag-Erling Smørgrav {
81b7579f77SDag-Erling Smørgrav 	size_t i;
82b7579f77SDag-Erling Smørgrav 	/* rd lock held by caller */
83b7579f77SDag-Erling Smørgrav 	if(!k || !d) return 1;
8457bddd21SDag-Erling Smørgrav 	if(k->id == 0) return 1; /* deleted */
85b7579f77SDag-Erling Smørgrav 	if(d->ttl < now) return 1; /* expired */
86b7579f77SDag-Erling Smørgrav 
87b7579f77SDag-Erling Smørgrav 	/* meta line */
8817d15b25SDag-Erling Smørgrav 	if(!ssl_printf(ssl, ";rrset%s " ARG_LL "d %u %u %d %d\n",
89b7579f77SDag-Erling Smørgrav 		(k->rk.flags & PACKED_RRSET_NSEC_AT_APEX)?" nsec_apex":"",
9017d15b25SDag-Erling Smørgrav 		(long long)(d->ttl - now),
91b7579f77SDag-Erling Smørgrav 		(unsigned)d->count, (unsigned)d->rrsig_count,
92b7579f77SDag-Erling Smørgrav 		(int)d->trust, (int)d->security
93b7579f77SDag-Erling Smørgrav 		))
94b7579f77SDag-Erling Smørgrav 		return 0;
9517d15b25SDag-Erling Smørgrav 	for(i=0; i<d->count + d->rrsig_count; i++) {
9617d15b25SDag-Erling Smørgrav 		if(!dump_rrset_line(ssl, k, now, i))
97b7579f77SDag-Erling Smørgrav 			return 0;
98b7579f77SDag-Erling Smørgrav 	}
99b7579f77SDag-Erling Smørgrav 	return 1;
100b7579f77SDag-Erling Smørgrav }
101b7579f77SDag-Erling Smørgrav 
102b7579f77SDag-Erling Smørgrav /** dump lruhash rrset cache */
103b7579f77SDag-Erling Smørgrav static int
dump_rrset_lruhash(RES * ssl,struct lruhash * h,time_t now)1047da0adf7SDag-Erling Smørgrav dump_rrset_lruhash(RES* ssl, struct lruhash* h, time_t now)
105b7579f77SDag-Erling Smørgrav {
106b7579f77SDag-Erling Smørgrav 	struct lruhash_entry* e;
107b7579f77SDag-Erling Smørgrav 	/* lruhash already locked by caller */
108b7579f77SDag-Erling Smørgrav 	/* walk in order of lru; best first */
109b7579f77SDag-Erling Smørgrav 	for(e=h->lru_start; e; e = e->lru_next) {
110b7579f77SDag-Erling Smørgrav 		lock_rw_rdlock(&e->lock);
111b7579f77SDag-Erling Smørgrav 		if(!dump_rrset(ssl, (struct ub_packed_rrset_key*)e->key,
112b7579f77SDag-Erling Smørgrav 			(struct packed_rrset_data*)e->data, now)) {
113b7579f77SDag-Erling Smørgrav 			lock_rw_unlock(&e->lock);
114b7579f77SDag-Erling Smørgrav 			return 0;
115b7579f77SDag-Erling Smørgrav 		}
116b7579f77SDag-Erling Smørgrav 		lock_rw_unlock(&e->lock);
117b7579f77SDag-Erling Smørgrav 	}
118b7579f77SDag-Erling Smørgrav 	return 1;
119b7579f77SDag-Erling Smørgrav }
120b7579f77SDag-Erling Smørgrav 
121b7579f77SDag-Erling Smørgrav /** dump rrset cache */
122b7579f77SDag-Erling Smørgrav static int
dump_rrset_cache(RES * ssl,struct worker * worker)1237da0adf7SDag-Erling Smørgrav dump_rrset_cache(RES* ssl, struct worker* worker)
124b7579f77SDag-Erling Smørgrav {
125b7579f77SDag-Erling Smørgrav 	struct rrset_cache* r = worker->env.rrset_cache;
126b7579f77SDag-Erling Smørgrav 	size_t slab;
127b7579f77SDag-Erling Smørgrav 	if(!ssl_printf(ssl, "START_RRSET_CACHE\n")) return 0;
128b7579f77SDag-Erling Smørgrav 	for(slab=0; slab<r->table.size; slab++) {
129b7579f77SDag-Erling Smørgrav 		lock_quick_lock(&r->table.array[slab]->lock);
130b7579f77SDag-Erling Smørgrav 		if(!dump_rrset_lruhash(ssl, r->table.array[slab],
131b7579f77SDag-Erling Smørgrav 			*worker->env.now)) {
132b7579f77SDag-Erling Smørgrav 			lock_quick_unlock(&r->table.array[slab]->lock);
133b7579f77SDag-Erling Smørgrav 			return 0;
134b7579f77SDag-Erling Smørgrav 		}
135b7579f77SDag-Erling Smørgrav 		lock_quick_unlock(&r->table.array[slab]->lock);
136b7579f77SDag-Erling Smørgrav 	}
137b7579f77SDag-Erling Smørgrav 	return ssl_printf(ssl, "END_RRSET_CACHE\n");
138b7579f77SDag-Erling Smørgrav }
139b7579f77SDag-Erling Smørgrav 
140b7579f77SDag-Erling Smørgrav /** dump message to rrset reference */
141b7579f77SDag-Erling Smørgrav static int
dump_msg_ref(RES * ssl,struct ub_packed_rrset_key * k)1427da0adf7SDag-Erling Smørgrav dump_msg_ref(RES* ssl, struct ub_packed_rrset_key* k)
143b7579f77SDag-Erling Smørgrav {
144b7579f77SDag-Erling Smørgrav 	char* nm, *tp, *cl;
14517d15b25SDag-Erling Smørgrav 	nm = sldns_wire2str_dname(k->rk.dname, k->rk.dname_len);
14617d15b25SDag-Erling Smørgrav 	tp = sldns_wire2str_type(ntohs(k->rk.type));
14717d15b25SDag-Erling Smørgrav 	cl = sldns_wire2str_class(ntohs(k->rk.rrset_class));
148b7579f77SDag-Erling Smørgrav 	if(!nm || !cl || !tp) {
149b7579f77SDag-Erling Smørgrav 		free(nm);
150b7579f77SDag-Erling Smørgrav 		free(tp);
151b7579f77SDag-Erling Smørgrav 		free(cl);
152b7579f77SDag-Erling Smørgrav 		return ssl_printf(ssl, "BADREF\n");
153b7579f77SDag-Erling Smørgrav 	}
154b7579f77SDag-Erling Smørgrav 	if(!ssl_printf(ssl, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags)) {
155b7579f77SDag-Erling Smørgrav 		free(nm);
156b7579f77SDag-Erling Smørgrav 		free(tp);
157b7579f77SDag-Erling Smørgrav 		free(cl);
158b7579f77SDag-Erling Smørgrav 		return 0;
159b7579f77SDag-Erling Smørgrav 	}
160b7579f77SDag-Erling Smørgrav 	free(nm);
161b7579f77SDag-Erling Smørgrav 	free(tp);
162b7579f77SDag-Erling Smørgrav 	free(cl);
163b7579f77SDag-Erling Smørgrav 
164b7579f77SDag-Erling Smørgrav 	return 1;
165b7579f77SDag-Erling Smørgrav }
166b7579f77SDag-Erling Smørgrav 
167b7579f77SDag-Erling Smørgrav /** dump message entry */
168b7579f77SDag-Erling Smørgrav static int
dump_msg(RES * ssl,struct query_info * k,struct reply_info * d,time_t now)1698f76bb7dSCy Schubert dump_msg(RES* ssl, struct query_info* k, struct reply_info* d, time_t now)
170b7579f77SDag-Erling Smørgrav {
171b7579f77SDag-Erling Smørgrav 	size_t i;
172b7579f77SDag-Erling Smørgrav 	char* nm, *tp, *cl;
173b7579f77SDag-Erling Smørgrav 	if(!k || !d) return 1;
174b7579f77SDag-Erling Smørgrav 	if(d->ttl < now) return 1; /* expired */
175b7579f77SDag-Erling Smørgrav 
17617d15b25SDag-Erling Smørgrav 	nm = sldns_wire2str_dname(k->qname, k->qname_len);
17717d15b25SDag-Erling Smørgrav 	tp = sldns_wire2str_type(k->qtype);
17817d15b25SDag-Erling Smørgrav 	cl = sldns_wire2str_class(k->qclass);
179b7579f77SDag-Erling Smørgrav 	if(!nm || !tp || !cl) {
180b7579f77SDag-Erling Smørgrav 		free(nm);
181b7579f77SDag-Erling Smørgrav 		free(tp);
182b7579f77SDag-Erling Smørgrav 		free(cl);
183b7579f77SDag-Erling Smørgrav 		return 1; /* skip this entry */
184b7579f77SDag-Erling Smørgrav 	}
185b7579f77SDag-Erling Smørgrav 	if(!rrset_array_lock(d->ref, d->rrset_count, now)) {
186b7579f77SDag-Erling Smørgrav 		/* rrsets have timed out or do not exist */
187b7579f77SDag-Erling Smørgrav 		free(nm);
188b7579f77SDag-Erling Smørgrav 		free(tp);
189b7579f77SDag-Erling Smørgrav 		free(cl);
190b7579f77SDag-Erling Smørgrav 		return 1; /* skip this entry */
191b7579f77SDag-Erling Smørgrav 	}
192b7579f77SDag-Erling Smørgrav 
193b7579f77SDag-Erling Smørgrav 	/* meta line */
1948f76bb7dSCy Schubert 	if(!ssl_printf(ssl, "msg %s %s %s %d %d " ARG_LL "d %d %u %u %u %d %s\n",
195b7579f77SDag-Erling Smørgrav 			nm, cl, tp,
196b7579f77SDag-Erling Smørgrav 			(int)d->flags, (int)d->qdcount,
19717d15b25SDag-Erling Smørgrav 			(long long)(d->ttl-now), (int)d->security,
198b7579f77SDag-Erling Smørgrav 			(unsigned)d->an_numrrsets,
199b7579f77SDag-Erling Smørgrav 			(unsigned)d->ns_numrrsets,
2008f76bb7dSCy Schubert 			(unsigned)d->ar_numrrsets,
2018f76bb7dSCy Schubert 			(int)d->reason_bogus,
2028f76bb7dSCy Schubert 			d->reason_bogus_str?d->reason_bogus_str:"")) {
203b7579f77SDag-Erling Smørgrav 		free(nm);
204b7579f77SDag-Erling Smørgrav 		free(tp);
205b7579f77SDag-Erling Smørgrav 		free(cl);
206b7579f77SDag-Erling Smørgrav 		rrset_array_unlock(d->ref, d->rrset_count);
207b7579f77SDag-Erling Smørgrav 		return 0;
208b7579f77SDag-Erling Smørgrav 	}
209b7579f77SDag-Erling Smørgrav 	free(nm);
210b7579f77SDag-Erling Smørgrav 	free(tp);
211b7579f77SDag-Erling Smørgrav 	free(cl);
212b7579f77SDag-Erling Smørgrav 
213b7579f77SDag-Erling Smørgrav 	for(i=0; i<d->rrset_count; i++) {
214b7579f77SDag-Erling Smørgrav 		if(!dump_msg_ref(ssl, d->rrsets[i])) {
215b7579f77SDag-Erling Smørgrav 			rrset_array_unlock(d->ref, d->rrset_count);
216b7579f77SDag-Erling Smørgrav 			return 0;
217b7579f77SDag-Erling Smørgrav 		}
218b7579f77SDag-Erling Smørgrav 	}
219b7579f77SDag-Erling Smørgrav 	rrset_array_unlock(d->ref, d->rrset_count);
220b7579f77SDag-Erling Smørgrav 
221b7579f77SDag-Erling Smørgrav 	return 1;
222b7579f77SDag-Erling Smørgrav }
223b7579f77SDag-Erling Smørgrav 
224b7579f77SDag-Erling Smørgrav /** copy msg to worker pad */
225b7579f77SDag-Erling Smørgrav static int
copy_msg(struct regional * region,struct lruhash_entry * e,struct query_info ** k,struct reply_info ** d)226b7579f77SDag-Erling Smørgrav copy_msg(struct regional* region, struct lruhash_entry* e,
227b7579f77SDag-Erling Smørgrav 	struct query_info** k, struct reply_info** d)
228b7579f77SDag-Erling Smørgrav {
229b7579f77SDag-Erling Smørgrav 	struct reply_info* rep = (struct reply_info*)e->data;
23009a3aaf3SDag-Erling Smørgrav 	if(rep->rrset_count > RR_COUNT_MAX)
23109a3aaf3SDag-Erling Smørgrav 		return 0; /* to protect against integer overflow */
232b7579f77SDag-Erling Smørgrav 	*d = (struct reply_info*)regional_alloc_init(region, e->data,
233b7579f77SDag-Erling Smørgrav 		sizeof(struct reply_info) +
234b7579f77SDag-Erling Smørgrav 		sizeof(struct rrset_ref) * (rep->rrset_count-1) +
235b7579f77SDag-Erling Smørgrav 		sizeof(struct ub_packed_rrset_key*) * rep->rrset_count);
236b7579f77SDag-Erling Smørgrav 	if(!*d)
237b7579f77SDag-Erling Smørgrav 		return 0;
23804b59eacSDag-Erling Smørgrav 	(*d)->rrsets = (struct ub_packed_rrset_key**)(void *)(
239b7579f77SDag-Erling Smørgrav 		(uint8_t*)(&((*d)->ref[0])) +
240b7579f77SDag-Erling Smørgrav 		sizeof(struct rrset_ref) * rep->rrset_count);
241b7579f77SDag-Erling Smørgrav 	*k = (struct query_info*)regional_alloc_init(region,
242b7579f77SDag-Erling Smørgrav 		e->key, sizeof(struct query_info));
243b7579f77SDag-Erling Smørgrav 	if(!*k)
244b7579f77SDag-Erling Smørgrav 		return 0;
245b7579f77SDag-Erling Smørgrav 	(*k)->qname = regional_alloc_init(region,
246b7579f77SDag-Erling Smørgrav 		(*k)->qname, (*k)->qname_len);
247b7579f77SDag-Erling Smørgrav 	return (*k)->qname != NULL;
248b7579f77SDag-Erling Smørgrav }
249b7579f77SDag-Erling Smørgrav 
250b7579f77SDag-Erling Smørgrav /** dump lruhash msg cache */
251b7579f77SDag-Erling Smørgrav static int
dump_msg_lruhash(RES * ssl,struct worker * worker,struct lruhash * h)2527da0adf7SDag-Erling Smørgrav dump_msg_lruhash(RES* ssl, struct worker* worker, struct lruhash* h)
253b7579f77SDag-Erling Smørgrav {
254b7579f77SDag-Erling Smørgrav 	struct lruhash_entry* e;
255b7579f77SDag-Erling Smørgrav 	struct query_info* k;
256b7579f77SDag-Erling Smørgrav 	struct reply_info* d;
257b7579f77SDag-Erling Smørgrav 
258b7579f77SDag-Erling Smørgrav 	/* lruhash already locked by caller */
259b7579f77SDag-Erling Smørgrav 	/* walk in order of lru; best first */
260b7579f77SDag-Erling Smørgrav 	for(e=h->lru_start; e; e = e->lru_next) {
261b7579f77SDag-Erling Smørgrav 		regional_free_all(worker->scratchpad);
262b7579f77SDag-Erling Smørgrav 		lock_rw_rdlock(&e->lock);
263b7579f77SDag-Erling Smørgrav 		/* make copy of rrset in worker buffer */
264b7579f77SDag-Erling Smørgrav 		if(!copy_msg(worker->scratchpad, e, &k, &d)) {
265b7579f77SDag-Erling Smørgrav 			lock_rw_unlock(&e->lock);
266b7579f77SDag-Erling Smørgrav 			return 0;
267b7579f77SDag-Erling Smørgrav 		}
268b7579f77SDag-Erling Smørgrav 		lock_rw_unlock(&e->lock);
269b7579f77SDag-Erling Smørgrav 		/* release lock so we can lookup the rrset references
270b7579f77SDag-Erling Smørgrav 		 * in the rrset cache */
271b7579f77SDag-Erling Smørgrav 		if(!dump_msg(ssl, k, d, *worker->env.now)) {
272b7579f77SDag-Erling Smørgrav 			return 0;
273b7579f77SDag-Erling Smørgrav 		}
274b7579f77SDag-Erling Smørgrav 	}
275b7579f77SDag-Erling Smørgrav 	return 1;
276b7579f77SDag-Erling Smørgrav }
277b7579f77SDag-Erling Smørgrav 
278b7579f77SDag-Erling Smørgrav /** dump msg cache */
279b7579f77SDag-Erling Smørgrav static int
dump_msg_cache(RES * ssl,struct worker * worker)2807da0adf7SDag-Erling Smørgrav dump_msg_cache(RES* ssl, struct worker* worker)
281b7579f77SDag-Erling Smørgrav {
282b7579f77SDag-Erling Smørgrav 	struct slabhash* sh = worker->env.msg_cache;
283b7579f77SDag-Erling Smørgrav 	size_t slab;
284b7579f77SDag-Erling Smørgrav 	if(!ssl_printf(ssl, "START_MSG_CACHE\n")) return 0;
285b7579f77SDag-Erling Smørgrav 	for(slab=0; slab<sh->size; slab++) {
286b7579f77SDag-Erling Smørgrav 		lock_quick_lock(&sh->array[slab]->lock);
287b7579f77SDag-Erling Smørgrav 		if(!dump_msg_lruhash(ssl, worker, sh->array[slab])) {
288b7579f77SDag-Erling Smørgrav 			lock_quick_unlock(&sh->array[slab]->lock);
289b7579f77SDag-Erling Smørgrav 			return 0;
290b7579f77SDag-Erling Smørgrav 		}
291b7579f77SDag-Erling Smørgrav 		lock_quick_unlock(&sh->array[slab]->lock);
292b7579f77SDag-Erling Smørgrav 	}
293b7579f77SDag-Erling Smørgrav 	return ssl_printf(ssl, "END_MSG_CACHE\n");
294b7579f77SDag-Erling Smørgrav }
295b7579f77SDag-Erling Smørgrav 
296b7579f77SDag-Erling Smørgrav int
dump_cache(RES * ssl,struct worker * worker)2977da0adf7SDag-Erling Smørgrav dump_cache(RES* ssl, struct worker* worker)
298b7579f77SDag-Erling Smørgrav {
299b7579f77SDag-Erling Smørgrav 	if(!dump_rrset_cache(ssl, worker))
300b7579f77SDag-Erling Smørgrav 		return 0;
301b7579f77SDag-Erling Smørgrav 	if(!dump_msg_cache(ssl, worker))
302b7579f77SDag-Erling Smørgrav 		return 0;
303b7579f77SDag-Erling Smørgrav 	return ssl_printf(ssl, "EOF\n");
304b7579f77SDag-Erling Smørgrav }
305b7579f77SDag-Erling Smørgrav 
306b7579f77SDag-Erling Smørgrav /** read a line from ssl into buffer */
307b7579f77SDag-Erling Smørgrav static int
ssl_read_buf(RES * ssl,sldns_buffer * buf)3087da0adf7SDag-Erling Smørgrav ssl_read_buf(RES* ssl, sldns_buffer* buf)
309b7579f77SDag-Erling Smørgrav {
31017d15b25SDag-Erling Smørgrav 	return ssl_read_line(ssl, (char*)sldns_buffer_begin(buf),
31117d15b25SDag-Erling Smørgrav 		sldns_buffer_capacity(buf));
312b7579f77SDag-Erling Smørgrav }
313b7579f77SDag-Erling Smørgrav 
314b7579f77SDag-Erling Smørgrav /** check fixed text on line */
315b7579f77SDag-Erling Smørgrav static int
read_fixed(RES * ssl,sldns_buffer * buf,const char * str)3167da0adf7SDag-Erling Smørgrav read_fixed(RES* ssl, sldns_buffer* buf, const char* str)
317b7579f77SDag-Erling Smørgrav {
318b7579f77SDag-Erling Smørgrav 	if(!ssl_read_buf(ssl, buf)) return 0;
31917d15b25SDag-Erling Smørgrav 	return (strcmp((char*)sldns_buffer_begin(buf), str) == 0);
320b7579f77SDag-Erling Smørgrav }
321b7579f77SDag-Erling Smørgrav 
322b7579f77SDag-Erling Smørgrav /** load an RR into rrset */
323b7579f77SDag-Erling Smørgrav static int
load_rr(RES * ssl,sldns_buffer * buf,struct regional * region,struct ub_packed_rrset_key * rk,struct packed_rrset_data * d,unsigned int i,int is_rrsig,int * go_on,time_t now)3247da0adf7SDag-Erling Smørgrav load_rr(RES* ssl, sldns_buffer* buf, struct regional* region,
325b7579f77SDag-Erling Smørgrav 	struct ub_packed_rrset_key* rk, struct packed_rrset_data* d,
32617d15b25SDag-Erling Smørgrav 	unsigned int i, int is_rrsig, int* go_on, time_t now)
327b7579f77SDag-Erling Smørgrav {
32817d15b25SDag-Erling Smørgrav 	uint8_t rr[LDNS_RR_BUF_SIZE];
32917d15b25SDag-Erling Smørgrav 	size_t rr_len = sizeof(rr), dname_len = 0;
33017d15b25SDag-Erling Smørgrav 	int status;
331b7579f77SDag-Erling Smørgrav 
332b7579f77SDag-Erling Smørgrav 	/* read the line */
333b7579f77SDag-Erling Smørgrav 	if(!ssl_read_buf(ssl, buf))
334b7579f77SDag-Erling Smørgrav 		return 0;
33517d15b25SDag-Erling Smørgrav 	if(strncmp((char*)sldns_buffer_begin(buf), "BADRR\n", 6) == 0) {
336b7579f77SDag-Erling Smørgrav 		*go_on = 0;
337b7579f77SDag-Erling Smørgrav 		return 1;
338b7579f77SDag-Erling Smørgrav 	}
33917d15b25SDag-Erling Smørgrav 	status = sldns_str2wire_rr_buf((char*)sldns_buffer_begin(buf), rr,
34017d15b25SDag-Erling Smørgrav 		&rr_len, &dname_len, 3600, NULL, 0, NULL, 0);
34117d15b25SDag-Erling Smørgrav 	if(status != 0) {
342b7579f77SDag-Erling Smørgrav 		log_warn("error cannot parse rr: %s: %s",
34317d15b25SDag-Erling Smørgrav 			sldns_get_errorstr_parse(status),
34417d15b25SDag-Erling Smørgrav 			(char*)sldns_buffer_begin(buf));
345b7579f77SDag-Erling Smørgrav 		return 0;
346b7579f77SDag-Erling Smørgrav 	}
34717d15b25SDag-Erling Smørgrav 	if(is_rrsig && sldns_wirerr_get_type(rr, rr_len, dname_len)
34817d15b25SDag-Erling Smørgrav 		!= LDNS_RR_TYPE_RRSIG) {
349b7579f77SDag-Erling Smørgrav 		log_warn("error expected rrsig but got %s",
35017d15b25SDag-Erling Smørgrav 			(char*)sldns_buffer_begin(buf));
351b7579f77SDag-Erling Smørgrav 		return 0;
352b7579f77SDag-Erling Smørgrav 	}
353b7579f77SDag-Erling Smørgrav 
354b7579f77SDag-Erling Smørgrav 	/* convert ldns rr into packed_rr */
35517d15b25SDag-Erling Smørgrav 	d->rr_ttl[i] = (time_t)sldns_wirerr_get_ttl(rr, rr_len, dname_len) + now;
35617d15b25SDag-Erling Smørgrav 	sldns_buffer_clear(buf);
35717d15b25SDag-Erling Smørgrav 	d->rr_len[i] = sldns_wirerr_get_rdatalen(rr, rr_len, dname_len)+2;
358b7579f77SDag-Erling Smørgrav 	d->rr_data[i] = (uint8_t*)regional_alloc_init(region,
35917d15b25SDag-Erling Smørgrav 		sldns_wirerr_get_rdatawl(rr, rr_len, dname_len), d->rr_len[i]);
360b7579f77SDag-Erling Smørgrav 	if(!d->rr_data[i]) {
361b7579f77SDag-Erling Smørgrav 		log_warn("error out of memory");
362b7579f77SDag-Erling Smørgrav 		return 0;
363b7579f77SDag-Erling Smørgrav 	}
364b7579f77SDag-Erling Smørgrav 
365b7579f77SDag-Erling Smørgrav 	/* if first entry, fill the key structure */
366b7579f77SDag-Erling Smørgrav 	if(i==0) {
36717d15b25SDag-Erling Smørgrav 		rk->rk.type = htons(sldns_wirerr_get_type(rr, rr_len, dname_len));
36817d15b25SDag-Erling Smørgrav 		rk->rk.rrset_class = htons(sldns_wirerr_get_class(rr, rr_len, dname_len));
36917d15b25SDag-Erling Smørgrav 		rk->rk.dname_len = dname_len;
37017d15b25SDag-Erling Smørgrav 		rk->rk.dname = regional_alloc_init(region, rr, dname_len);
371b7579f77SDag-Erling Smørgrav 		if(!rk->rk.dname) {
372b7579f77SDag-Erling Smørgrav 			log_warn("error out of memory");
373b7579f77SDag-Erling Smørgrav 			return 0;
374b7579f77SDag-Erling Smørgrav 		}
375b7579f77SDag-Erling Smørgrav 	}
376b7579f77SDag-Erling Smørgrav 
377b7579f77SDag-Erling Smørgrav 	return 1;
378b7579f77SDag-Erling Smørgrav }
379b7579f77SDag-Erling Smørgrav 
380b7579f77SDag-Erling Smørgrav /** move entry into cache */
381b7579f77SDag-Erling Smørgrav static int
move_into_cache(struct ub_packed_rrset_key * k,struct packed_rrset_data * d,struct worker * worker)382b7579f77SDag-Erling Smørgrav move_into_cache(struct ub_packed_rrset_key* k,
383b7579f77SDag-Erling Smørgrav 	struct packed_rrset_data* d, struct worker* worker)
384b7579f77SDag-Erling Smørgrav {
385b7579f77SDag-Erling Smørgrav 	struct ub_packed_rrset_key* ak;
386b7579f77SDag-Erling Smørgrav 	struct packed_rrset_data* ad;
387b7579f77SDag-Erling Smørgrav 	size_t s, i, num = d->count + d->rrsig_count;
388b7579f77SDag-Erling Smørgrav 	struct rrset_ref ref;
389b7579f77SDag-Erling Smørgrav 	uint8_t* p;
390b7579f77SDag-Erling Smørgrav 
3911838dec3SCy Schubert 	ak = alloc_special_obtain(worker->alloc);
392b7579f77SDag-Erling Smørgrav 	if(!ak) {
393b7579f77SDag-Erling Smørgrav 		log_warn("error out of memory");
394b7579f77SDag-Erling Smørgrav 		return 0;
395b7579f77SDag-Erling Smørgrav 	}
396b7579f77SDag-Erling Smørgrav 	ak->entry.data = NULL;
397b7579f77SDag-Erling Smørgrav 	ak->rk = k->rk;
398b7579f77SDag-Erling Smørgrav 	ak->entry.hash = rrset_key_hash(&k->rk);
399b7579f77SDag-Erling Smørgrav 	ak->rk.dname = (uint8_t*)memdup(k->rk.dname, k->rk.dname_len);
400b7579f77SDag-Erling Smørgrav 	if(!ak->rk.dname) {
401b7579f77SDag-Erling Smørgrav 		log_warn("error out of memory");
4021838dec3SCy Schubert 		ub_packed_rrset_parsedelete(ak, worker->alloc);
403b7579f77SDag-Erling Smørgrav 		return 0;
404b7579f77SDag-Erling Smørgrav 	}
405b7579f77SDag-Erling Smørgrav 	s = sizeof(*ad) + (sizeof(size_t) + sizeof(uint8_t*) +
40617d15b25SDag-Erling Smørgrav 		sizeof(time_t))* num;
407b7579f77SDag-Erling Smørgrav 	for(i=0; i<num; i++)
408b7579f77SDag-Erling Smørgrav 		s += d->rr_len[i];
409b7579f77SDag-Erling Smørgrav 	ad = (struct packed_rrset_data*)malloc(s);
410b7579f77SDag-Erling Smørgrav 	if(!ad) {
411b7579f77SDag-Erling Smørgrav 		log_warn("error out of memory");
4121838dec3SCy Schubert 		ub_packed_rrset_parsedelete(ak, worker->alloc);
413b7579f77SDag-Erling Smørgrav 		return 0;
414b7579f77SDag-Erling Smørgrav 	}
415b7579f77SDag-Erling Smørgrav 	p = (uint8_t*)ad;
416b7579f77SDag-Erling Smørgrav 	memmove(p, d, sizeof(*ad));
417b7579f77SDag-Erling Smørgrav 	p += sizeof(*ad);
418b7579f77SDag-Erling Smørgrav 	memmove(p, &d->rr_len[0], sizeof(size_t)*num);
419b7579f77SDag-Erling Smørgrav 	p += sizeof(size_t)*num;
420b7579f77SDag-Erling Smørgrav 	memmove(p, &d->rr_data[0], sizeof(uint8_t*)*num);
421b7579f77SDag-Erling Smørgrav 	p += sizeof(uint8_t*)*num;
42217d15b25SDag-Erling Smørgrav 	memmove(p, &d->rr_ttl[0], sizeof(time_t)*num);
42317d15b25SDag-Erling Smørgrav 	p += sizeof(time_t)*num;
424b7579f77SDag-Erling Smørgrav 	for(i=0; i<num; i++) {
425b7579f77SDag-Erling Smørgrav 		memmove(p, d->rr_data[i], d->rr_len[i]);
426b7579f77SDag-Erling Smørgrav 		p += d->rr_len[i];
427b7579f77SDag-Erling Smørgrav 	}
428b7579f77SDag-Erling Smørgrav 	packed_rrset_ptr_fixup(ad);
429b7579f77SDag-Erling Smørgrav 
430b7579f77SDag-Erling Smørgrav 	ak->entry.data = ad;
431b7579f77SDag-Erling Smørgrav 
432b7579f77SDag-Erling Smørgrav 	ref.key = ak;
433b7579f77SDag-Erling Smørgrav 	ref.id = ak->id;
434b7579f77SDag-Erling Smørgrav 	(void)rrset_cache_update(worker->env.rrset_cache, &ref,
4351838dec3SCy Schubert 		worker->alloc, *worker->env.now);
4361838dec3SCy Schubert 
437b7579f77SDag-Erling Smørgrav 	return 1;
438b7579f77SDag-Erling Smørgrav }
439b7579f77SDag-Erling Smørgrav 
440b7579f77SDag-Erling Smørgrav /** load an rrset entry */
441b7579f77SDag-Erling Smørgrav static int
load_rrset(RES * ssl,sldns_buffer * buf,struct worker * worker)4427da0adf7SDag-Erling Smørgrav load_rrset(RES* ssl, sldns_buffer* buf, struct worker* worker)
443b7579f77SDag-Erling Smørgrav {
44417d15b25SDag-Erling Smørgrav 	char* s = (char*)sldns_buffer_begin(buf);
445b7579f77SDag-Erling Smørgrav 	struct regional* region = worker->scratchpad;
446b7579f77SDag-Erling Smørgrav 	struct ub_packed_rrset_key* rk;
447b7579f77SDag-Erling Smørgrav 	struct packed_rrset_data* d;
44817d15b25SDag-Erling Smørgrav 	unsigned int rr_count, rrsig_count, trust, security;
44917d15b25SDag-Erling Smørgrav 	long long ttl;
450b7579f77SDag-Erling Smørgrav 	unsigned int i;
451b7579f77SDag-Erling Smørgrav 	int go_on = 1;
452b7579f77SDag-Erling Smørgrav 	regional_free_all(region);
453b7579f77SDag-Erling Smørgrav 
454b7579f77SDag-Erling Smørgrav 	rk = (struct ub_packed_rrset_key*)regional_alloc_zero(region,
455b7579f77SDag-Erling Smørgrav 		sizeof(*rk));
456b7579f77SDag-Erling Smørgrav 	d = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*d));
457b7579f77SDag-Erling Smørgrav 	if(!rk || !d) {
458b7579f77SDag-Erling Smørgrav 		log_warn("error out of memory");
459b7579f77SDag-Erling Smørgrav 		return 0;
460b7579f77SDag-Erling Smørgrav 	}
461b7579f77SDag-Erling Smørgrav 
462b7579f77SDag-Erling Smørgrav 	if(strncmp(s, ";rrset", 6) != 0) {
463b7579f77SDag-Erling Smørgrav 		log_warn("error expected ';rrset' but got %s", s);
464b7579f77SDag-Erling Smørgrav 		return 0;
465b7579f77SDag-Erling Smørgrav 	}
466b7579f77SDag-Erling Smørgrav 	s += 6;
467b7579f77SDag-Erling Smørgrav 	if(strncmp(s, " nsec_apex", 10) == 0) {
468b7579f77SDag-Erling Smørgrav 		s += 10;
469b7579f77SDag-Erling Smørgrav 		rk->rk.flags |= PACKED_RRSET_NSEC_AT_APEX;
470b7579f77SDag-Erling Smørgrav 	}
47117d15b25SDag-Erling Smørgrav 	if(sscanf(s, " " ARG_LL "d %u %u %u %u", &ttl, &rr_count, &rrsig_count,
472b7579f77SDag-Erling Smørgrav 		&trust, &security) != 5) {
473b7579f77SDag-Erling Smørgrav 		log_warn("error bad rrset spec %s", s);
474b7579f77SDag-Erling Smørgrav 		return 0;
475b7579f77SDag-Erling Smørgrav 	}
476b7579f77SDag-Erling Smørgrav 	if(rr_count == 0 && rrsig_count == 0) {
477b7579f77SDag-Erling Smørgrav 		log_warn("bad rrset without contents");
478b7579f77SDag-Erling Smørgrav 		return 0;
479b7579f77SDag-Erling Smørgrav 	}
48009a3aaf3SDag-Erling Smørgrav 	if(rr_count > RR_COUNT_MAX || rrsig_count > RR_COUNT_MAX) {
48109a3aaf3SDag-Erling Smørgrav 		log_warn("bad rrset with too many rrs");
48209a3aaf3SDag-Erling Smørgrav 		return 0;
48309a3aaf3SDag-Erling Smørgrav 	}
484b7579f77SDag-Erling Smørgrav 	d->count = (size_t)rr_count;
485b7579f77SDag-Erling Smørgrav 	d->rrsig_count = (size_t)rrsig_count;
486b7579f77SDag-Erling Smørgrav 	d->security = (enum sec_status)security;
487b7579f77SDag-Erling Smørgrav 	d->trust = (enum rrset_trust)trust;
48817d15b25SDag-Erling Smørgrav 	d->ttl = (time_t)ttl + *worker->env.now;
489b7579f77SDag-Erling Smørgrav 
490b7579f77SDag-Erling Smørgrav 	d->rr_len = regional_alloc_zero(region,
491b7579f77SDag-Erling Smørgrav 		sizeof(size_t)*(d->count+d->rrsig_count));
492b7579f77SDag-Erling Smørgrav 	d->rr_ttl = regional_alloc_zero(region,
49317d15b25SDag-Erling Smørgrav 		sizeof(time_t)*(d->count+d->rrsig_count));
494b7579f77SDag-Erling Smørgrav 	d->rr_data = regional_alloc_zero(region,
495b7579f77SDag-Erling Smørgrav 		sizeof(uint8_t*)*(d->count+d->rrsig_count));
496b7579f77SDag-Erling Smørgrav 	if(!d->rr_len || !d->rr_ttl || !d->rr_data) {
497b7579f77SDag-Erling Smørgrav 		log_warn("error out of memory");
498b7579f77SDag-Erling Smørgrav 		return 0;
499b7579f77SDag-Erling Smørgrav 	}
500b7579f77SDag-Erling Smørgrav 
501b7579f77SDag-Erling Smørgrav 	/* read the rr's themselves */
502b7579f77SDag-Erling Smørgrav 	for(i=0; i<rr_count; i++) {
503b7579f77SDag-Erling Smørgrav 		if(!load_rr(ssl, buf, region, rk, d, i, 0,
504b7579f77SDag-Erling Smørgrav 			&go_on, *worker->env.now)) {
505b7579f77SDag-Erling Smørgrav 			log_warn("could not read rr %u", i);
506b7579f77SDag-Erling Smørgrav 			return 0;
507b7579f77SDag-Erling Smørgrav 		}
508b7579f77SDag-Erling Smørgrav 	}
509b7579f77SDag-Erling Smørgrav 	for(i=0; i<rrsig_count; i++) {
510b7579f77SDag-Erling Smørgrav 		if(!load_rr(ssl, buf, region, rk, d, i+rr_count, 1,
511b7579f77SDag-Erling Smørgrav 			&go_on, *worker->env.now)) {
512b7579f77SDag-Erling Smørgrav 			log_warn("could not read rrsig %u", i);
513b7579f77SDag-Erling Smørgrav 			return 0;
514b7579f77SDag-Erling Smørgrav 		}
515b7579f77SDag-Erling Smørgrav 	}
516b7579f77SDag-Erling Smørgrav 	if(!go_on) {
517b7579f77SDag-Erling Smørgrav 		/* skip this entry */
518b7579f77SDag-Erling Smørgrav 		return 1;
519b7579f77SDag-Erling Smørgrav 	}
520b7579f77SDag-Erling Smørgrav 
521b7579f77SDag-Erling Smørgrav 	return move_into_cache(rk, d, worker);
522b7579f77SDag-Erling Smørgrav }
523b7579f77SDag-Erling Smørgrav 
524b7579f77SDag-Erling Smørgrav /** load rrset cache */
525b7579f77SDag-Erling Smørgrav static int
load_rrset_cache(RES * ssl,struct worker * worker)5267da0adf7SDag-Erling Smørgrav load_rrset_cache(RES* ssl, struct worker* worker)
527b7579f77SDag-Erling Smørgrav {
52817d15b25SDag-Erling Smørgrav 	sldns_buffer* buf = worker->env.scratch_buffer;
529b7579f77SDag-Erling Smørgrav 	if(!read_fixed(ssl, buf, "START_RRSET_CACHE")) return 0;
530b7579f77SDag-Erling Smørgrav 	while(ssl_read_buf(ssl, buf) &&
53117d15b25SDag-Erling Smørgrav 		strcmp((char*)sldns_buffer_begin(buf), "END_RRSET_CACHE")!=0) {
532b7579f77SDag-Erling Smørgrav 		if(!load_rrset(ssl, buf, worker))
533b7579f77SDag-Erling Smørgrav 			return 0;
534b7579f77SDag-Erling Smørgrav 	}
535b7579f77SDag-Erling Smørgrav 	return 1;
536b7579f77SDag-Erling Smørgrav }
537b7579f77SDag-Erling Smørgrav 
538b7579f77SDag-Erling Smørgrav /** read qinfo from next three words */
539b7579f77SDag-Erling Smørgrav static char*
load_qinfo(char * str,struct query_info * qinfo,struct regional * region)54017d15b25SDag-Erling Smørgrav load_qinfo(char* str, struct query_info* qinfo, struct regional* region)
541b7579f77SDag-Erling Smørgrav {
542b7579f77SDag-Erling Smørgrav 	/* s is part of the buf */
543b7579f77SDag-Erling Smørgrav 	char* s = str;
54417d15b25SDag-Erling Smørgrav 	uint8_t rr[LDNS_RR_BUF_SIZE];
54517d15b25SDag-Erling Smørgrav 	size_t rr_len = sizeof(rr), dname_len = 0;
54617d15b25SDag-Erling Smørgrav 	int status;
547b7579f77SDag-Erling Smørgrav 
548b7579f77SDag-Erling Smørgrav 	/* skip three words */
549b7579f77SDag-Erling Smørgrav 	s = strchr(str, ' ');
550b7579f77SDag-Erling Smørgrav 	if(s) s = strchr(s+1, ' ');
551b7579f77SDag-Erling Smørgrav 	if(s) s = strchr(s+1, ' ');
552b7579f77SDag-Erling Smørgrav 	if(!s) {
553b7579f77SDag-Erling Smørgrav 		log_warn("error line too short, %s", str);
554b7579f77SDag-Erling Smørgrav 		return NULL;
555b7579f77SDag-Erling Smørgrav 	}
556b7579f77SDag-Erling Smørgrav 	s[0] = 0;
557b7579f77SDag-Erling Smørgrav 	s++;
558b7579f77SDag-Erling Smørgrav 
559b7579f77SDag-Erling Smørgrav 	/* parse them */
56017d15b25SDag-Erling Smørgrav 	status = sldns_str2wire_rr_question_buf(str, rr, &rr_len, &dname_len,
56117d15b25SDag-Erling Smørgrav 		NULL, 0, NULL, 0);
56217d15b25SDag-Erling Smørgrav 	if(status != 0) {
563b7579f77SDag-Erling Smørgrav 		log_warn("error cannot parse: %s %s",
56417d15b25SDag-Erling Smørgrav 			sldns_get_errorstr_parse(status), str);
565b7579f77SDag-Erling Smørgrav 		return NULL;
566b7579f77SDag-Erling Smørgrav 	}
56717d15b25SDag-Erling Smørgrav 	qinfo->qtype = sldns_wirerr_get_type(rr, rr_len, dname_len);
56817d15b25SDag-Erling Smørgrav 	qinfo->qclass = sldns_wirerr_get_class(rr, rr_len, dname_len);
56917d15b25SDag-Erling Smørgrav 	qinfo->qname_len = dname_len;
57017d15b25SDag-Erling Smørgrav 	qinfo->qname = (uint8_t*)regional_alloc_init(region, rr, dname_len);
571bc892140SDag-Erling Smørgrav 	qinfo->local_alias = NULL;
572b7579f77SDag-Erling Smørgrav 	if(!qinfo->qname) {
573b7579f77SDag-Erling Smørgrav 		log_warn("error out of memory");
574b7579f77SDag-Erling Smørgrav 		return NULL;
575b7579f77SDag-Erling Smørgrav 	}
576b7579f77SDag-Erling Smørgrav 
577b7579f77SDag-Erling Smørgrav 	return s;
578b7579f77SDag-Erling Smørgrav }
579b7579f77SDag-Erling Smørgrav 
580b7579f77SDag-Erling Smørgrav /** load a msg rrset reference */
581b7579f77SDag-Erling Smørgrav static int
load_ref(RES * ssl,sldns_buffer * buf,struct worker * worker,struct regional * region,struct ub_packed_rrset_key ** rrset,int * go_on)5827da0adf7SDag-Erling Smørgrav load_ref(RES* ssl, sldns_buffer* buf, struct worker* worker,
583b7579f77SDag-Erling Smørgrav 	struct regional *region, struct ub_packed_rrset_key** rrset,
584b7579f77SDag-Erling Smørgrav 	int* go_on)
585b7579f77SDag-Erling Smørgrav {
58617d15b25SDag-Erling Smørgrav 	char* s = (char*)sldns_buffer_begin(buf);
587b7579f77SDag-Erling Smørgrav 	struct query_info qinfo;
588b7579f77SDag-Erling Smørgrav 	unsigned int flags;
589b7579f77SDag-Erling Smørgrav 	struct ub_packed_rrset_key* k;
590b7579f77SDag-Erling Smørgrav 
591b7579f77SDag-Erling Smørgrav 	/* read line */
592b7579f77SDag-Erling Smørgrav 	if(!ssl_read_buf(ssl, buf))
593b7579f77SDag-Erling Smørgrav 		return 0;
594b7579f77SDag-Erling Smørgrav 	if(strncmp(s, "BADREF", 6) == 0) {
595b7579f77SDag-Erling Smørgrav 		*go_on = 0; /* its bad, skip it and skip message */
596b7579f77SDag-Erling Smørgrav 		return 1;
597b7579f77SDag-Erling Smørgrav 	}
598b7579f77SDag-Erling Smørgrav 
59917d15b25SDag-Erling Smørgrav 	s = load_qinfo(s, &qinfo, region);
600b7579f77SDag-Erling Smørgrav 	if(!s) {
601b7579f77SDag-Erling Smørgrav 		return 0;
602b7579f77SDag-Erling Smørgrav 	}
603b7579f77SDag-Erling Smørgrav 	if(sscanf(s, " %u", &flags) != 1) {
604b7579f77SDag-Erling Smørgrav 		log_warn("error cannot parse flags: %s", s);
605b7579f77SDag-Erling Smørgrav 		return 0;
606b7579f77SDag-Erling Smørgrav 	}
607b7579f77SDag-Erling Smørgrav 
608b7579f77SDag-Erling Smørgrav 	/* lookup in cache */
609b7579f77SDag-Erling Smørgrav 	k = rrset_cache_lookup(worker->env.rrset_cache, qinfo.qname,
610b7579f77SDag-Erling Smørgrav 		qinfo.qname_len, qinfo.qtype, qinfo.qclass,
611b7579f77SDag-Erling Smørgrav 		(uint32_t)flags, *worker->env.now, 0);
612b7579f77SDag-Erling Smørgrav 	if(!k) {
613b7579f77SDag-Erling Smørgrav 		/* not found or expired */
614b7579f77SDag-Erling Smørgrav 		*go_on = 0;
615b7579f77SDag-Erling Smørgrav 		return 1;
616b7579f77SDag-Erling Smørgrav 	}
617b7579f77SDag-Erling Smørgrav 
618b7579f77SDag-Erling Smørgrav 	/* store in result */
619b7579f77SDag-Erling Smørgrav 	*rrset = packed_rrset_copy_region(k, region, *worker->env.now);
620b7579f77SDag-Erling Smørgrav 	lock_rw_unlock(&k->entry.lock);
621b7579f77SDag-Erling Smørgrav 
622b7579f77SDag-Erling Smørgrav 	return (*rrset != NULL);
623b7579f77SDag-Erling Smørgrav }
624b7579f77SDag-Erling Smørgrav 
625b7579f77SDag-Erling Smørgrav /** load a msg entry */
626b7579f77SDag-Erling Smørgrav static int
load_msg(RES * ssl,sldns_buffer * buf,struct worker * worker)6277da0adf7SDag-Erling Smørgrav load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
628b7579f77SDag-Erling Smørgrav {
629b7579f77SDag-Erling Smørgrav 	struct regional* region = worker->scratchpad;
630b7579f77SDag-Erling Smørgrav 	struct query_info qinf;
631b7579f77SDag-Erling Smørgrav 	struct reply_info rep;
63217d15b25SDag-Erling Smørgrav 	char* s = (char*)sldns_buffer_begin(buf);
63317d15b25SDag-Erling Smørgrav 	unsigned int flags, qdcount, security, an, ns, ar;
63417d15b25SDag-Erling Smørgrav 	long long ttl;
635b7579f77SDag-Erling Smørgrav 	size_t i;
636b7579f77SDag-Erling Smørgrav 	int go_on = 1;
6378f76bb7dSCy Schubert 	int ede;
6388f76bb7dSCy Schubert 	int consumed = 0;
6398f76bb7dSCy Schubert 	char* ede_str = NULL;
640b7579f77SDag-Erling Smørgrav 
641b7579f77SDag-Erling Smørgrav 	regional_free_all(region);
642b7579f77SDag-Erling Smørgrav 
643b7579f77SDag-Erling Smørgrav 	if(strncmp(s, "msg ", 4) != 0) {
644b7579f77SDag-Erling Smørgrav 		log_warn("error expected msg but got %s", s);
645b7579f77SDag-Erling Smørgrav 		return 0;
646b7579f77SDag-Erling Smørgrav 	}
647b7579f77SDag-Erling Smørgrav 	s += 4;
64817d15b25SDag-Erling Smørgrav 	s = load_qinfo(s, &qinf, region);
649b7579f77SDag-Erling Smørgrav 	if(!s) {
650b7579f77SDag-Erling Smørgrav 		return 0;
651b7579f77SDag-Erling Smørgrav 	}
652b7579f77SDag-Erling Smørgrav 
653b7579f77SDag-Erling Smørgrav 	/* read remainder of line */
6548f76bb7dSCy Schubert 	/* note the last space before any possible EDE text */
6558f76bb7dSCy Schubert 	if(sscanf(s, " %u %u " ARG_LL "d %u %u %u %u %d %n", &flags, &qdcount, &ttl,
6568f76bb7dSCy Schubert 		&security, &an, &ns, &ar, &ede, &consumed) != 8) {
657b7579f77SDag-Erling Smørgrav 		log_warn("error cannot parse numbers: %s", s);
658b7579f77SDag-Erling Smørgrav 		return 0;
659b7579f77SDag-Erling Smørgrav 	}
6608f76bb7dSCy Schubert 	/* there may be EDE text after the numbers */
6618f76bb7dSCy Schubert 	if(consumed > 0 && (size_t)consumed < strlen(s))
6628f76bb7dSCy Schubert 		ede_str = s + consumed;
6638f76bb7dSCy Schubert 	memset(&rep, 0, sizeof(rep));
664b7579f77SDag-Erling Smørgrav 	rep.flags = (uint16_t)flags;
665b7579f77SDag-Erling Smørgrav 	rep.qdcount = (uint16_t)qdcount;
66617d15b25SDag-Erling Smørgrav 	rep.ttl = (time_t)ttl;
667b7579f77SDag-Erling Smørgrav 	rep.prefetch_ttl = PREFETCH_TTL_CALC(rep.ttl);
6684c75e3aaSDag-Erling Smørgrav 	rep.serve_expired_ttl = rep.ttl + SERVE_EXPIRED_TTL;
669b7579f77SDag-Erling Smørgrav 	rep.security = (enum sec_status)security;
67009a3aaf3SDag-Erling Smørgrav 	if(an > RR_COUNT_MAX || ns > RR_COUNT_MAX || ar > RR_COUNT_MAX) {
67109a3aaf3SDag-Erling Smørgrav 		log_warn("error too many rrsets");
67209a3aaf3SDag-Erling Smørgrav 		return 0; /* protect against integer overflow in alloc */
67309a3aaf3SDag-Erling Smørgrav 	}
674b7579f77SDag-Erling Smørgrav 	rep.an_numrrsets = (size_t)an;
675b7579f77SDag-Erling Smørgrav 	rep.ns_numrrsets = (size_t)ns;
676b7579f77SDag-Erling Smørgrav 	rep.ar_numrrsets = (size_t)ar;
677b7579f77SDag-Erling Smørgrav 	rep.rrset_count = (size_t)an+(size_t)ns+(size_t)ar;
6788f76bb7dSCy Schubert 	rep.reason_bogus = (sldns_ede_code)ede;
6798f76bb7dSCy Schubert 	rep.reason_bogus_str = ede_str?(char*)regional_strdup(region, ede_str):NULL;
680b7579f77SDag-Erling Smørgrav 	rep.rrsets = (struct ub_packed_rrset_key**)regional_alloc_zero(
681b7579f77SDag-Erling Smørgrav 		region, sizeof(struct ub_packed_rrset_key*)*rep.rrset_count);
682b7579f77SDag-Erling Smørgrav 
683b7579f77SDag-Erling Smørgrav 	/* fill repinfo with references */
684b7579f77SDag-Erling Smørgrav 	for(i=0; i<rep.rrset_count; i++) {
685b7579f77SDag-Erling Smørgrav 		if(!load_ref(ssl, buf, worker, region, &rep.rrsets[i],
686b7579f77SDag-Erling Smørgrav 			&go_on)) {
687b7579f77SDag-Erling Smørgrav 			return 0;
688b7579f77SDag-Erling Smørgrav 		}
689b7579f77SDag-Erling Smørgrav 	}
690b7579f77SDag-Erling Smørgrav 
691b7579f77SDag-Erling Smørgrav 	if(!go_on)
692b7579f77SDag-Erling Smørgrav 		return 1; /* skip this one, not all references satisfied */
693b7579f77SDag-Erling Smørgrav 
694790c6b24SCy Schubert 	if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags,
695790c6b24SCy Schubert 		*worker->env.now)) {
696b7579f77SDag-Erling Smørgrav 		log_warn("error out of memory");
697b7579f77SDag-Erling Smørgrav 		return 0;
698b7579f77SDag-Erling Smørgrav 	}
699b7579f77SDag-Erling Smørgrav 	return 1;
700b7579f77SDag-Erling Smørgrav }
701b7579f77SDag-Erling Smørgrav 
702b7579f77SDag-Erling Smørgrav /** load msg cache */
703b7579f77SDag-Erling Smørgrav static int
load_msg_cache(RES * ssl,struct worker * worker)7047da0adf7SDag-Erling Smørgrav load_msg_cache(RES* ssl, struct worker* worker)
705b7579f77SDag-Erling Smørgrav {
70617d15b25SDag-Erling Smørgrav 	sldns_buffer* buf = worker->env.scratch_buffer;
707b7579f77SDag-Erling Smørgrav 	if(!read_fixed(ssl, buf, "START_MSG_CACHE")) return 0;
708b7579f77SDag-Erling Smørgrav 	while(ssl_read_buf(ssl, buf) &&
70917d15b25SDag-Erling Smørgrav 		strcmp((char*)sldns_buffer_begin(buf), "END_MSG_CACHE")!=0) {
710b7579f77SDag-Erling Smørgrav 		if(!load_msg(ssl, buf, worker))
711b7579f77SDag-Erling Smørgrav 			return 0;
712b7579f77SDag-Erling Smørgrav 	}
713b7579f77SDag-Erling Smørgrav 	return 1;
714b7579f77SDag-Erling Smørgrav }
715b7579f77SDag-Erling Smørgrav 
716b7579f77SDag-Erling Smørgrav int
load_cache(RES * ssl,struct worker * worker)7177da0adf7SDag-Erling Smørgrav load_cache(RES* ssl, struct worker* worker)
718b7579f77SDag-Erling Smørgrav {
719b7579f77SDag-Erling Smørgrav 	if(!load_rrset_cache(ssl, worker))
720b7579f77SDag-Erling Smørgrav 		return 0;
721b7579f77SDag-Erling Smørgrav 	if(!load_msg_cache(ssl, worker))
722b7579f77SDag-Erling Smørgrav 		return 0;
723b7579f77SDag-Erling Smørgrav 	return read_fixed(ssl, worker->env.scratch_buffer, "EOF");
724b7579f77SDag-Erling Smørgrav }
725b7579f77SDag-Erling Smørgrav 
726b7579f77SDag-Erling Smørgrav /** print details on a delegation point */
727b7579f77SDag-Erling Smørgrav static void
print_dp_details(RES * ssl,struct worker * worker,struct delegpt * dp)7287da0adf7SDag-Erling Smørgrav print_dp_details(RES* ssl, struct worker* worker, struct delegpt* dp)
729b7579f77SDag-Erling Smørgrav {
730b7579f77SDag-Erling Smørgrav 	char buf[257];
731b7579f77SDag-Erling Smørgrav 	struct delegpt_addr* a;
73217d15b25SDag-Erling Smørgrav 	int lame, dlame, rlame, rto, edns_vs, to, delay,
733b7579f77SDag-Erling Smørgrav 		tA = 0, tAAAA = 0, tother = 0;
73417d15b25SDag-Erling Smørgrav 	long long entry_ttl;
735b7579f77SDag-Erling Smørgrav 	struct rtt_info ri;
736b7579f77SDag-Erling Smørgrav 	uint8_t edns_lame_known;
737b7579f77SDag-Erling Smørgrav 	for(a = dp->target_list; a; a = a->next_target) {
738b7579f77SDag-Erling Smørgrav 		addr_to_str(&a->addr, a->addrlen, buf, sizeof(buf));
739b7579f77SDag-Erling Smørgrav 		if(!ssl_printf(ssl, "%-16s\t", buf))
740b7579f77SDag-Erling Smørgrav 			return;
741b7579f77SDag-Erling Smørgrav 		if(a->bogus) {
742b7579f77SDag-Erling Smørgrav 			if(!ssl_printf(ssl, "Address is BOGUS. "))
743b7579f77SDag-Erling Smørgrav 				return;
744b7579f77SDag-Erling Smørgrav 		}
745b7579f77SDag-Erling Smørgrav 		/* lookup in infra cache */
746b7579f77SDag-Erling Smørgrav 		delay=0;
747b7579f77SDag-Erling Smørgrav 		entry_ttl = infra_get_host_rto(worker->env.infra_cache,
748b7579f77SDag-Erling Smørgrav 			&a->addr, a->addrlen, dp->name, dp->namelen,
749b7579f77SDag-Erling Smørgrav 			&ri, &delay, *worker->env.now, &tA, &tAAAA, &tother);
750b7579f77SDag-Erling Smørgrav 		if(entry_ttl == -2 && ri.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
751b7579f77SDag-Erling Smørgrav 			if(!ssl_printf(ssl, "expired, rto %d msec, tA %d "
752b7579f77SDag-Erling Smørgrav 				"tAAAA %d tother %d.\n", ri.rto, tA, tAAAA,
753b7579f77SDag-Erling Smørgrav 				tother))
754b7579f77SDag-Erling Smørgrav 				return;
755b7579f77SDag-Erling Smørgrav 			continue;
756b7579f77SDag-Erling Smørgrav 		}
757b7579f77SDag-Erling Smørgrav 		if(entry_ttl == -1 || entry_ttl == -2) {
758b7579f77SDag-Erling Smørgrav 			if(!ssl_printf(ssl, "not in infra cache.\n"))
759b7579f77SDag-Erling Smørgrav 				return;
760b7579f77SDag-Erling Smørgrav 			continue; /* skip stuff not in infra cache */
761b7579f77SDag-Erling Smørgrav 		}
762b7579f77SDag-Erling Smørgrav 
763b7579f77SDag-Erling Smørgrav 		/* uses type_A because most often looked up, but other
764b7579f77SDag-Erling Smørgrav 		 * lameness won't be reported then */
765b7579f77SDag-Erling Smørgrav 		if(!infra_get_lame_rtt(worker->env.infra_cache,
766b7579f77SDag-Erling Smørgrav 			&a->addr, a->addrlen, dp->name, dp->namelen,
767b7579f77SDag-Erling Smørgrav 			LDNS_RR_TYPE_A, &lame, &dlame, &rlame, &rto,
768b7579f77SDag-Erling Smørgrav 			*worker->env.now)) {
769b7579f77SDag-Erling Smørgrav 			if(!ssl_printf(ssl, "not in infra cache.\n"))
770b7579f77SDag-Erling Smørgrav 				return;
771b7579f77SDag-Erling Smørgrav 			continue; /* skip stuff not in infra cache */
772b7579f77SDag-Erling Smørgrav 		}
77317d15b25SDag-Erling Smørgrav 		if(!ssl_printf(ssl, "%s%s%s%srto %d msec, ttl " ARG_LL "d, "
77417d15b25SDag-Erling Smørgrav 			"ping %d var %d rtt %d, tA %d, tAAAA %d, tother %d",
775b7579f77SDag-Erling Smørgrav 			lame?"LAME ":"", dlame?"NoDNSSEC ":"",
776b7579f77SDag-Erling Smørgrav 			a->lame?"AddrWasParentSide ":"",
777b7579f77SDag-Erling Smørgrav 			rlame?"NoAuthButRecursive ":"", rto, entry_ttl,
778b7579f77SDag-Erling Smørgrav 			ri.srtt, ri.rttvar, rtt_notimeout(&ri),
779b7579f77SDag-Erling Smørgrav 			tA, tAAAA, tother))
780b7579f77SDag-Erling Smørgrav 			return;
781b7579f77SDag-Erling Smørgrav 		if(delay)
782b7579f77SDag-Erling Smørgrav 			if(!ssl_printf(ssl, ", probedelay %d", delay))
783b7579f77SDag-Erling Smørgrav 				return;
784b7579f77SDag-Erling Smørgrav 		if(infra_host(worker->env.infra_cache, &a->addr, a->addrlen,
785b7579f77SDag-Erling Smørgrav 			dp->name, dp->namelen, *worker->env.now, &edns_vs,
786b7579f77SDag-Erling Smørgrav 			&edns_lame_known, &to)) {
787b7579f77SDag-Erling Smørgrav 			if(edns_vs == -1) {
788b7579f77SDag-Erling Smørgrav 				if(!ssl_printf(ssl, ", noEDNS%s.",
789b7579f77SDag-Erling Smørgrav 					edns_lame_known?" probed":" assumed"))
790b7579f77SDag-Erling Smørgrav 					return;
791b7579f77SDag-Erling Smørgrav 			} else {
792b7579f77SDag-Erling Smørgrav 				if(!ssl_printf(ssl, ", EDNS %d%s.", edns_vs,
793b7579f77SDag-Erling Smørgrav 					edns_lame_known?" probed":" assumed"))
794b7579f77SDag-Erling Smørgrav 					return;
795b7579f77SDag-Erling Smørgrav 			}
796b7579f77SDag-Erling Smørgrav 		}
797b7579f77SDag-Erling Smørgrav 		if(!ssl_printf(ssl, "\n"))
798b7579f77SDag-Erling Smørgrav 			return;
799b7579f77SDag-Erling Smørgrav 	}
800b7579f77SDag-Erling Smørgrav }
801b7579f77SDag-Erling Smørgrav 
802b7579f77SDag-Erling Smørgrav /** print main dp info */
803b7579f77SDag-Erling Smørgrav static void
print_dp_main(RES * ssl,struct delegpt * dp,struct dns_msg * msg)8047da0adf7SDag-Erling Smørgrav print_dp_main(RES* ssl, struct delegpt* dp, struct dns_msg* msg)
805b7579f77SDag-Erling Smørgrav {
806b7579f77SDag-Erling Smørgrav 	size_t i, n_ns, n_miss, n_addr, n_res, n_avail;
807b7579f77SDag-Erling Smørgrav 
808b7579f77SDag-Erling Smørgrav 	/* print the dp */
809b7579f77SDag-Erling Smørgrav 	if(msg)
810b7579f77SDag-Erling Smørgrav 	    for(i=0; i<msg->rep->rrset_count; i++) {
811b7579f77SDag-Erling Smørgrav 		struct ub_packed_rrset_key* k = msg->rep->rrsets[i];
812b7579f77SDag-Erling Smørgrav 		struct packed_rrset_data* d =
813b7579f77SDag-Erling Smørgrav 			(struct packed_rrset_data*)k->entry.data;
814b7579f77SDag-Erling Smørgrav 		if(d->security == sec_status_bogus) {
815b7579f77SDag-Erling Smørgrav 			if(!ssl_printf(ssl, "Address is BOGUS:\n"))
816b7579f77SDag-Erling Smørgrav 				return;
817b7579f77SDag-Erling Smørgrav 		}
818b7579f77SDag-Erling Smørgrav 		if(!dump_rrset(ssl, k, d, 0))
819b7579f77SDag-Erling Smørgrav 			return;
820b7579f77SDag-Erling Smørgrav 	    }
821b7579f77SDag-Erling Smørgrav 	delegpt_count_ns(dp, &n_ns, &n_miss);
822b7579f77SDag-Erling Smørgrav 	delegpt_count_addr(dp, &n_addr, &n_res, &n_avail);
823b7579f77SDag-Erling Smørgrav 	/* since dp has not been used by iterator, all are available*/
824b7579f77SDag-Erling Smørgrav 	if(!ssl_printf(ssl, "Delegation with %d names, of which %d "
825b7579f77SDag-Erling Smørgrav 		"can be examined to query further addresses.\n"
826b7579f77SDag-Erling Smørgrav 		"%sIt provides %d IP addresses.\n",
827b7579f77SDag-Erling Smørgrav 		(int)n_ns, (int)n_miss, (dp->bogus?"It is BOGUS. ":""),
828b7579f77SDag-Erling Smørgrav 		(int)n_addr))
829b7579f77SDag-Erling Smørgrav 		return;
830b7579f77SDag-Erling Smørgrav }
831b7579f77SDag-Erling Smørgrav 
print_deleg_lookup(RES * ssl,struct worker * worker,uint8_t * nm,size_t nmlen,int ATTR_UNUSED (nmlabs))8327da0adf7SDag-Erling Smørgrav int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
833b7579f77SDag-Erling Smørgrav 	size_t nmlen, int ATTR_UNUSED(nmlabs))
834b7579f77SDag-Erling Smørgrav {
835b7579f77SDag-Erling Smørgrav 	/* deep links into the iterator module */
836b7579f77SDag-Erling Smørgrav 	struct delegpt* dp;
837b7579f77SDag-Erling Smørgrav 	struct dns_msg* msg;
838b7579f77SDag-Erling Smørgrav 	struct regional* region = worker->scratchpad;
839b7579f77SDag-Erling Smørgrav 	char b[260];
840b7579f77SDag-Erling Smørgrav 	struct query_info qinfo;
841b7579f77SDag-Erling Smørgrav 	struct iter_hints_stub* stub;
842*335c7cdaSCy Schubert 	int nolock = 0;
843b7579f77SDag-Erling Smørgrav 	regional_free_all(region);
844b7579f77SDag-Erling Smørgrav 	qinfo.qname = nm;
845b7579f77SDag-Erling Smørgrav 	qinfo.qname_len = nmlen;
846b7579f77SDag-Erling Smørgrav 	qinfo.qtype = LDNS_RR_TYPE_A;
847b7579f77SDag-Erling Smørgrav 	qinfo.qclass = LDNS_RR_CLASS_IN;
848bc892140SDag-Erling Smørgrav 	qinfo.local_alias = NULL;
849b7579f77SDag-Erling Smørgrav 
850b7579f77SDag-Erling Smørgrav 	dname_str(nm, b);
851b7579f77SDag-Erling Smørgrav 	if(!ssl_printf(ssl, "The following name servers are used for lookup "
852b7579f77SDag-Erling Smørgrav 		"of %s\n", b))
853b7579f77SDag-Erling Smørgrav 		return 0;
854b7579f77SDag-Erling Smørgrav 
855*335c7cdaSCy Schubert 	dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass, nolock);
856b7579f77SDag-Erling Smørgrav 	if(dp) {
857*335c7cdaSCy Schubert 		if(!ssl_printf(ssl, "forwarding request:\n")) {
858*335c7cdaSCy Schubert 			lock_rw_unlock(&worker->env.fwds->lock);
859b7579f77SDag-Erling Smørgrav 			return 0;
860*335c7cdaSCy Schubert 		}
861b7579f77SDag-Erling Smørgrav 		print_dp_main(ssl, dp, NULL);
862b7579f77SDag-Erling Smørgrav 		print_dp_details(ssl, worker, dp);
863*335c7cdaSCy Schubert 		lock_rw_unlock(&worker->env.fwds->lock);
864b7579f77SDag-Erling Smørgrav 		return 1;
865b7579f77SDag-Erling Smørgrav 	}
866b7579f77SDag-Erling Smørgrav 
867b7579f77SDag-Erling Smørgrav 	while(1) {
868b7579f77SDag-Erling Smørgrav 		dp = dns_cache_find_delegation(&worker->env, nm, nmlen,
869b7579f77SDag-Erling Smørgrav 			qinfo.qtype, qinfo.qclass, region, &msg,
870790c6b24SCy Schubert 			*worker->env.now, 0, NULL, 0);
871b7579f77SDag-Erling Smørgrav 		if(!dp) {
872b7579f77SDag-Erling Smørgrav 			return ssl_printf(ssl, "no delegation from "
873b7579f77SDag-Erling Smørgrav 				"cache; goes to configured roots\n");
874b7579f77SDag-Erling Smørgrav 		}
875b7579f77SDag-Erling Smørgrav 		/* go up? */
876a39a5a69SCy Schubert 		if(iter_dp_is_useless(&qinfo, BIT_RD, dp,
877a39a5a69SCy Schubert 			(worker->env.cfg->do_ip4 && worker->back->num_ip4 != 0),
8788f76bb7dSCy Schubert 			(worker->env.cfg->do_ip6 && worker->back->num_ip6 != 0),
8798f76bb7dSCy Schubert 			worker->env.cfg->do_nat64)) {
880b7579f77SDag-Erling Smørgrav 			print_dp_main(ssl, dp, msg);
881b7579f77SDag-Erling Smørgrav 			print_dp_details(ssl, worker, dp);
882b7579f77SDag-Erling Smørgrav 			if(!ssl_printf(ssl, "cache delegation was "
883b7579f77SDag-Erling Smørgrav 				"useless (no IP addresses)\n"))
884b7579f77SDag-Erling Smørgrav 				return 0;
885b7579f77SDag-Erling Smørgrav 			if(dname_is_root(nm)) {
886b7579f77SDag-Erling Smørgrav 				/* goes to root config */
887b7579f77SDag-Erling Smørgrav 				return ssl_printf(ssl, "no delegation from "
888b7579f77SDag-Erling Smørgrav 					"cache; goes to configured roots\n");
889b7579f77SDag-Erling Smørgrav 			} else {
890b7579f77SDag-Erling Smørgrav 				/* useless, goes up */
891b7579f77SDag-Erling Smørgrav 				nm = dp->name;
892b7579f77SDag-Erling Smørgrav 				nmlen = dp->namelen;
893b7579f77SDag-Erling Smørgrav 				dname_remove_label(&nm, &nmlen);
894b7579f77SDag-Erling Smørgrav 				dname_str(nm, b);
895b7579f77SDag-Erling Smørgrav 				if(!ssl_printf(ssl, "going up, lookup %s\n", b))
896b7579f77SDag-Erling Smørgrav 					return 0;
897b7579f77SDag-Erling Smørgrav 				continue;
898b7579f77SDag-Erling Smørgrav 			}
899b7579f77SDag-Erling Smørgrav 		}
900b7579f77SDag-Erling Smørgrav 		stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass,
901*335c7cdaSCy Schubert 			dp, nolock);
902b7579f77SDag-Erling Smørgrav 		if(stub) {
903b7579f77SDag-Erling Smørgrav 			if(stub->noprime) {
904b7579f77SDag-Erling Smørgrav 				if(!ssl_printf(ssl, "The noprime stub servers "
905*335c7cdaSCy Schubert 					"are used:\n")) {
906*335c7cdaSCy Schubert 					lock_rw_unlock(&worker->env.hints->lock);
907b7579f77SDag-Erling Smørgrav 					return 0;
908*335c7cdaSCy Schubert 				}
909b7579f77SDag-Erling Smørgrav 			} else {
910b7579f77SDag-Erling Smørgrav 				if(!ssl_printf(ssl, "The stub is primed "
911*335c7cdaSCy Schubert 						"with servers:\n")) {
912*335c7cdaSCy Schubert 					lock_rw_unlock(&worker->env.hints->lock);
913b7579f77SDag-Erling Smørgrav 					return 0;
914b7579f77SDag-Erling Smørgrav 				}
915*335c7cdaSCy Schubert 			}
916b7579f77SDag-Erling Smørgrav 			print_dp_main(ssl, stub->dp, NULL);
917b7579f77SDag-Erling Smørgrav 			print_dp_details(ssl, worker, stub->dp);
918*335c7cdaSCy Schubert 			lock_rw_unlock(&worker->env.hints->lock);
919b7579f77SDag-Erling Smørgrav 		} else {
920b7579f77SDag-Erling Smørgrav 			print_dp_main(ssl, dp, msg);
921b7579f77SDag-Erling Smørgrav 			print_dp_details(ssl, worker, dp);
922b7579f77SDag-Erling Smørgrav 		}
923b7579f77SDag-Erling Smørgrav 		break;
924b7579f77SDag-Erling Smørgrav 	}
925b7579f77SDag-Erling Smørgrav 
926b7579f77SDag-Erling Smørgrav 	return 1;
927b7579f77SDag-Erling Smørgrav }
928