xref: /freebsd/contrib/unbound/services/cache/infra.c (revision c9dbb1cc52b063bbd9ab078a7afc89a8696da659)
1 /*
2  * services/cache/infra.c - infrastructure cache, server rtt and capabilities
3  *
4  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5  *
6  * This software is open source.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * Neither the name of the NLNET LABS nor the names of its contributors may
20  * be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /**
37  * \file
38  *
39  * This file contains the infrastructure cache.
40  */
41 #include "config.h"
42 #include "sldns/rrdef.h"
43 #include "sldns/str2wire.h"
44 #include "services/cache/infra.h"
45 #include "util/storage/slabhash.h"
46 #include "util/storage/lookup3.h"
47 #include "util/data/dname.h"
48 #include "util/log.h"
49 #include "util/net_help.h"
50 #include "util/config_file.h"
51 #include "iterator/iterator.h"
52 
53 /** Timeout when only a single probe query per IP is allowed. */
54 #define PROBE_MAXRTO 12000 /* in msec */
55 
56 /** number of timeouts for a type when the domain can be blocked ;
57  * even if another type has completely rtt maxed it, the different type
58  * can do this number of packets (until those all timeout too) */
59 #define TIMEOUT_COUNT_MAX 3
60 
61 /** ratelimit value for delegation point */
62 int infra_dp_ratelimit = 0;
63 
64 size_t
65 infra_sizefunc(void* k, void* ATTR_UNUSED(d))
66 {
67 	struct infra_key* key = (struct infra_key*)k;
68 	return sizeof(*key) + sizeof(struct infra_data) + key->namelen
69 		+ lock_get_mem(&key->entry.lock);
70 }
71 
72 int
73 infra_compfunc(void* key1, void* key2)
74 {
75 	struct infra_key* k1 = (struct infra_key*)key1;
76 	struct infra_key* k2 = (struct infra_key*)key2;
77 	int r = sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen);
78 	if(r != 0)
79 		return r;
80 	if(k1->namelen != k2->namelen) {
81 		if(k1->namelen < k2->namelen)
82 			return -1;
83 		return 1;
84 	}
85 	return query_dname_compare(k1->zonename, k2->zonename);
86 }
87 
88 void
89 infra_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
90 {
91 	struct infra_key* key = (struct infra_key*)k;
92 	if(!key)
93 		return;
94 	lock_rw_destroy(&key->entry.lock);
95 	free(key->zonename);
96 	free(key);
97 }
98 
99 void
100 infra_deldatafunc(void* d, void* ATTR_UNUSED(arg))
101 {
102 	struct infra_data* data = (struct infra_data*)d;
103 	free(data);
104 }
105 
106 size_t
107 rate_sizefunc(void* k, void* ATTR_UNUSED(d))
108 {
109 	struct rate_key* key = (struct rate_key*)k;
110 	return sizeof(*key) + sizeof(struct rate_data) + key->namelen
111 		+ lock_get_mem(&key->entry.lock);
112 }
113 
114 int
115 rate_compfunc(void* key1, void* key2)
116 {
117 	struct rate_key* k1 = (struct rate_key*)key1;
118 	struct rate_key* k2 = (struct rate_key*)key2;
119 	if(k1->namelen != k2->namelen) {
120 		if(k1->namelen < k2->namelen)
121 			return -1;
122 		return 1;
123 	}
124 	return query_dname_compare(k1->name, k2->name);
125 }
126 
127 void
128 rate_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
129 {
130 	struct rate_key* key = (struct rate_key*)k;
131 	if(!key)
132 		return;
133 	lock_rw_destroy(&key->entry.lock);
134 	free(key->name);
135 	free(key);
136 }
137 
138 void
139 rate_deldatafunc(void* d, void* ATTR_UNUSED(arg))
140 {
141 	struct rate_data* data = (struct rate_data*)d;
142 	free(data);
143 }
144 
145 /** find or create element in domainlimit tree */
146 static struct domain_limit_data* domain_limit_findcreate(
147 	struct infra_cache* infra, char* name)
148 {
149 	uint8_t* nm;
150 	int labs;
151 	size_t nmlen;
152 	struct domain_limit_data* d;
153 
154 	/* parse name */
155 	nm = sldns_str2wire_dname(name, &nmlen);
156 	if(!nm) {
157 		log_err("could not parse %s", name);
158 		return NULL;
159 	}
160 	labs = dname_count_labels(nm);
161 
162 	/* can we find it? */
163 	d = (struct domain_limit_data*)name_tree_find(&infra->domain_limits,
164 		nm, nmlen, labs, LDNS_RR_CLASS_IN);
165 	if(d) {
166 		free(nm);
167 		return d;
168 	}
169 
170 	/* create it */
171 	d = (struct domain_limit_data*)calloc(1, sizeof(*d));
172 	if(!d) {
173 		free(nm);
174 		return NULL;
175 	}
176 	d->node.node.key = &d->node;
177 	d->node.name = nm;
178 	d->node.len = nmlen;
179 	d->node.labs = labs;
180 	d->node.dclass = LDNS_RR_CLASS_IN;
181 	d->lim = -1;
182 	d->below = -1;
183 	if(!name_tree_insert(&infra->domain_limits, &d->node, nm, nmlen,
184 		labs, LDNS_RR_CLASS_IN)) {
185 		log_err("duplicate element in domainlimit tree");
186 		free(nm);
187 		free(d);
188 		return NULL;
189 	}
190 	return d;
191 }
192 
193 /** insert rate limit configuration into lookup tree */
194 static int infra_ratelimit_cfg_insert(struct infra_cache* infra,
195 	struct config_file* cfg)
196 {
197 	struct config_str2list* p;
198 	struct domain_limit_data* d;
199 	for(p = cfg->ratelimit_for_domain; p; p = p->next) {
200 		d = domain_limit_findcreate(infra, p->str);
201 		if(!d)
202 			return 0;
203 		d->lim = atoi(p->str2);
204 	}
205 	for(p = cfg->ratelimit_below_domain; p; p = p->next) {
206 		d = domain_limit_findcreate(infra, p->str);
207 		if(!d)
208 			return 0;
209 		d->below = atoi(p->str2);
210 	}
211 	return 1;
212 }
213 
214 struct infra_cache*
215 infra_create(struct config_file* cfg)
216 {
217 	struct infra_cache* infra = (struct infra_cache*)calloc(1,
218 		sizeof(struct infra_cache));
219 	size_t maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+
220 		sizeof(struct infra_data)+INFRA_BYTES_NAME);
221 	infra->hosts = slabhash_create(cfg->infra_cache_slabs,
222 		INFRA_HOST_STARTSIZE, maxmem, &infra_sizefunc, &infra_compfunc,
223 		&infra_delkeyfunc, &infra_deldatafunc, NULL);
224 	if(!infra->hosts) {
225 		free(infra);
226 		return NULL;
227 	}
228 	infra->host_ttl = cfg->host_ttl;
229 	name_tree_init(&infra->domain_limits);
230 	infra_dp_ratelimit = cfg->ratelimit;
231 	if(cfg->ratelimit != 0) {
232 		infra->domain_rates = slabhash_create(cfg->ratelimit_slabs,
233 			INFRA_HOST_STARTSIZE, cfg->ratelimit_size,
234 			&rate_sizefunc, &rate_compfunc, &rate_delkeyfunc,
235 			&rate_deldatafunc, NULL);
236 		if(!infra->domain_rates) {
237 			infra_delete(infra);
238 			return NULL;
239 		}
240 		/* insert config data into ratelimits */
241 		if(!infra_ratelimit_cfg_insert(infra, cfg)) {
242 			infra_delete(infra);
243 			return NULL;
244 		}
245 		name_tree_init_parents(&infra->domain_limits);
246 	}
247 	return infra;
248 }
249 
250 /** delete domain_limit entries */
251 static void domain_limit_free(rbnode_t* n, void* ATTR_UNUSED(arg))
252 {
253 	if(n) {
254 		free(((struct domain_limit_data*)n)->node.name);
255 		free(n);
256 	}
257 }
258 
259 void
260 infra_delete(struct infra_cache* infra)
261 {
262 	if(!infra)
263 		return;
264 	slabhash_delete(infra->hosts);
265 	slabhash_delete(infra->domain_rates);
266 	traverse_postorder(&infra->domain_limits, domain_limit_free, NULL);
267 	free(infra);
268 }
269 
270 struct infra_cache*
271 infra_adjust(struct infra_cache* infra, struct config_file* cfg)
272 {
273 	size_t maxmem;
274 	if(!infra)
275 		return infra_create(cfg);
276 	infra->host_ttl = cfg->host_ttl;
277 	maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+
278 		sizeof(struct infra_data)+INFRA_BYTES_NAME);
279 	if(maxmem != slabhash_get_size(infra->hosts) ||
280 		cfg->infra_cache_slabs != infra->hosts->size) {
281 		infra_delete(infra);
282 		infra = infra_create(cfg);
283 	}
284 	return infra;
285 }
286 
287 /** calculate the hash value for a host key */
288 static hashvalue_t
289 hash_addr(struct sockaddr_storage* addr, socklen_t addrlen)
290 {
291 	hashvalue_t h = 0xab;
292 	/* select the pieces to hash, some OS have changing data inside */
293 	if(addr_is_ip6(addr, addrlen)) {
294 		struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr;
295 		h = hashlittle(&in6->sin6_family, sizeof(in6->sin6_family), h);
296 		h = hashlittle(&in6->sin6_port, sizeof(in6->sin6_port), h);
297 		h = hashlittle(&in6->sin6_addr, INET6_SIZE, h);
298 	} else {
299 		struct sockaddr_in* in = (struct sockaddr_in*)addr;
300 		h = hashlittle(&in->sin_family, sizeof(in->sin_family), h);
301 		h = hashlittle(&in->sin_port, sizeof(in->sin_port), h);
302 		h = hashlittle(&in->sin_addr, INET_SIZE, h);
303 	}
304 	return h;
305 }
306 
307 /** calculate infra hash for a key */
308 static hashvalue_t
309 hash_infra(struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name)
310 {
311 	return dname_query_hash(name, hash_addr(addr, addrlen));
312 }
313 
314 /** lookup version that does not check host ttl (you check it) */
315 struct lruhash_entry*
316 infra_lookup_nottl(struct infra_cache* infra, struct sockaddr_storage* addr,
317 	socklen_t addrlen, uint8_t* name, size_t namelen, int wr)
318 {
319 	struct infra_key k;
320 	k.addrlen = addrlen;
321 	memcpy(&k.addr, addr, addrlen);
322 	k.namelen = namelen;
323 	k.zonename = name;
324 	k.entry.hash = hash_infra(addr, addrlen, name);
325 	k.entry.key = (void*)&k;
326 	k.entry.data = NULL;
327 	return slabhash_lookup(infra->hosts, k.entry.hash, &k, wr);
328 }
329 
330 /** init the data elements */
331 static void
332 data_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
333 	time_t timenow)
334 {
335 	struct infra_data* data = (struct infra_data*)e->data;
336 	data->ttl = timenow + infra->host_ttl;
337 	rtt_init(&data->rtt);
338 	data->edns_version = 0;
339 	data->edns_lame_known = 0;
340 	data->probedelay = 0;
341 	data->isdnsseclame = 0;
342 	data->rec_lame = 0;
343 	data->lame_type_A = 0;
344 	data->lame_other = 0;
345 	data->timeout_A = 0;
346 	data->timeout_AAAA = 0;
347 	data->timeout_other = 0;
348 }
349 
350 /**
351  * Create and init a new entry for a host
352  * @param infra: infra structure with config parameters.
353  * @param addr: host address.
354  * @param addrlen: length of addr.
355  * @param name: name of zone
356  * @param namelen: length of name.
357  * @param tm: time now.
358  * @return: the new entry or NULL on malloc failure.
359  */
360 static struct lruhash_entry*
361 new_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
362 	socklen_t addrlen, uint8_t* name, size_t namelen, time_t tm)
363 {
364 	struct infra_data* data;
365 	struct infra_key* key = (struct infra_key*)malloc(sizeof(*key));
366 	if(!key)
367 		return NULL;
368 	data = (struct infra_data*)malloc(sizeof(struct infra_data));
369 	if(!data) {
370 		free(key);
371 		return NULL;
372 	}
373 	key->zonename = memdup(name, namelen);
374 	if(!key->zonename) {
375 		free(key);
376 		free(data);
377 		return NULL;
378 	}
379 	key->namelen = namelen;
380 	lock_rw_init(&key->entry.lock);
381 	key->entry.hash = hash_infra(addr, addrlen, name);
382 	key->entry.key = (void*)key;
383 	key->entry.data = (void*)data;
384 	key->addrlen = addrlen;
385 	memcpy(&key->addr, addr, addrlen);
386 	data_entry_init(infra, &key->entry, tm);
387 	return &key->entry;
388 }
389 
390 int
391 infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
392         socklen_t addrlen, uint8_t* nm, size_t nmlen, time_t timenow,
393 	int* edns_vs, uint8_t* edns_lame_known, int* to)
394 {
395 	struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
396 		nm, nmlen, 0);
397 	struct infra_data* data;
398 	int wr = 0;
399 	if(e && ((struct infra_data*)e->data)->ttl < timenow) {
400 		/* it expired, try to reuse existing entry */
401 		int old = ((struct infra_data*)e->data)->rtt.rto;
402 		uint8_t tA = ((struct infra_data*)e->data)->timeout_A;
403 		uint8_t tAAAA = ((struct infra_data*)e->data)->timeout_AAAA;
404 		uint8_t tother = ((struct infra_data*)e->data)->timeout_other;
405 		lock_rw_unlock(&e->lock);
406 		e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1);
407 		if(e) {
408 			/* if its still there we have a writelock, init */
409 			/* re-initialise */
410 			/* do not touch lameness, it may be valid still */
411 			data_entry_init(infra, e, timenow);
412 			wr = 1;
413 			/* TOP_TIMEOUT remains on reuse */
414 			if(old >= USEFUL_SERVER_TOP_TIMEOUT) {
415 				((struct infra_data*)e->data)->rtt.rto
416 					= USEFUL_SERVER_TOP_TIMEOUT;
417 				((struct infra_data*)e->data)->timeout_A = tA;
418 				((struct infra_data*)e->data)->timeout_AAAA = tAAAA;
419 				((struct infra_data*)e->data)->timeout_other = tother;
420 			}
421 		}
422 	}
423 	if(!e) {
424 		/* insert new entry */
425 		if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
426 			return 0;
427 		data = (struct infra_data*)e->data;
428 		*edns_vs = data->edns_version;
429 		*edns_lame_known = data->edns_lame_known;
430 		*to = rtt_timeout(&data->rtt);
431 		slabhash_insert(infra->hosts, e->hash, e, data, NULL);
432 		return 1;
433 	}
434 	/* use existing entry */
435 	data = (struct infra_data*)e->data;
436 	*edns_vs = data->edns_version;
437 	*edns_lame_known = data->edns_lame_known;
438 	*to = rtt_timeout(&data->rtt);
439 	if(*to >= PROBE_MAXRTO && rtt_notimeout(&data->rtt)*4 <= *to) {
440 		/* delay other queries, this is the probe query */
441 		if(!wr) {
442 			lock_rw_unlock(&e->lock);
443 			e = infra_lookup_nottl(infra, addr,addrlen,nm,nmlen, 1);
444 			if(!e) { /* flushed from cache real fast, no use to
445 				allocate just for the probedelay */
446 				return 1;
447 			}
448 			data = (struct infra_data*)e->data;
449 		}
450 		/* add 999 to round up the timeout value from msec to sec,
451 		 * then add a whole second so it is certain that this probe
452 		 * has timed out before the next is allowed */
453 		data->probedelay = timenow + ((*to)+1999)/1000;
454 	}
455 	lock_rw_unlock(&e->lock);
456 	return 1;
457 }
458 
459 int
460 infra_set_lame(struct infra_cache* infra, struct sockaddr_storage* addr,
461 	socklen_t addrlen, uint8_t* nm, size_t nmlen, time_t timenow,
462 	int dnsseclame, int reclame, uint16_t qtype)
463 {
464 	struct infra_data* data;
465 	struct lruhash_entry* e;
466 	int needtoinsert = 0;
467 	e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1);
468 	if(!e) {
469 		/* insert it */
470 		if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) {
471 			log_err("set_lame: malloc failure");
472 			return 0;
473 		}
474 		needtoinsert = 1;
475 	} else if( ((struct infra_data*)e->data)->ttl < timenow) {
476 		/* expired, reuse existing entry */
477 		data_entry_init(infra, e, timenow);
478 	}
479 	/* got an entry, now set the zone lame */
480 	data = (struct infra_data*)e->data;
481 	/* merge data (if any) */
482 	if(dnsseclame)
483 		data->isdnsseclame = 1;
484 	if(reclame)
485 		data->rec_lame = 1;
486 	if(!dnsseclame && !reclame && qtype == LDNS_RR_TYPE_A)
487 		data->lame_type_A = 1;
488 	if(!dnsseclame  && !reclame && qtype != LDNS_RR_TYPE_A)
489 		data->lame_other = 1;
490 	/* done */
491 	if(needtoinsert)
492 		slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
493 	else 	{ lock_rw_unlock(&e->lock); }
494 	return 1;
495 }
496 
497 void
498 infra_update_tcp_works(struct infra_cache* infra,
499         struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm,
500 	size_t nmlen)
501 {
502 	struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
503 		nm, nmlen, 1);
504 	struct infra_data* data;
505 	if(!e)
506 		return; /* doesn't exist */
507 	data = (struct infra_data*)e->data;
508 	if(data->rtt.rto >= RTT_MAX_TIMEOUT)
509 		/* do not disqualify this server altogether, it is better
510 		 * than nothing */
511 		data->rtt.rto = RTT_MAX_TIMEOUT-1000;
512 	lock_rw_unlock(&e->lock);
513 }
514 
515 int
516 infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr,
517 	socklen_t addrlen, uint8_t* nm, size_t nmlen, int qtype,
518 	int roundtrip, int orig_rtt, time_t timenow)
519 {
520 	struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
521 		nm, nmlen, 1);
522 	struct infra_data* data;
523 	int needtoinsert = 0;
524 	int rto = 1;
525 	if(!e) {
526 		if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
527 			return 0;
528 		needtoinsert = 1;
529 	} else if(((struct infra_data*)e->data)->ttl < timenow) {
530 		data_entry_init(infra, e, timenow);
531 	}
532 	/* have an entry, update the rtt */
533 	data = (struct infra_data*)e->data;
534 	if(roundtrip == -1) {
535 		rtt_lost(&data->rtt, orig_rtt);
536 		if(qtype == LDNS_RR_TYPE_A) {
537 			if(data->timeout_A < TIMEOUT_COUNT_MAX)
538 				data->timeout_A++;
539 		} else if(qtype == LDNS_RR_TYPE_AAAA) {
540 			if(data->timeout_AAAA < TIMEOUT_COUNT_MAX)
541 				data->timeout_AAAA++;
542 		} else {
543 			if(data->timeout_other < TIMEOUT_COUNT_MAX)
544 				data->timeout_other++;
545 		}
546 	} else {
547 		/* if we got a reply, but the old timeout was above server
548 		 * selection height, delete the timeout so the server is
549 		 * fully available again */
550 		if(rtt_unclamped(&data->rtt) >= USEFUL_SERVER_TOP_TIMEOUT)
551 			rtt_init(&data->rtt);
552 		rtt_update(&data->rtt, roundtrip);
553 		data->probedelay = 0;
554 		if(qtype == LDNS_RR_TYPE_A)
555 			data->timeout_A = 0;
556 		else if(qtype == LDNS_RR_TYPE_AAAA)
557 			data->timeout_AAAA = 0;
558 		else	data->timeout_other = 0;
559 	}
560 	if(data->rtt.rto > 0)
561 		rto = data->rtt.rto;
562 
563 	if(needtoinsert)
564 		slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
565 	else 	{ lock_rw_unlock(&e->lock); }
566 	return rto;
567 }
568 
569 long long infra_get_host_rto(struct infra_cache* infra,
570         struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm,
571 	size_t nmlen, struct rtt_info* rtt, int* delay, time_t timenow,
572 	int* tA, int* tAAAA, int* tother)
573 {
574 	struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
575 		nm, nmlen, 0);
576 	struct infra_data* data;
577 	long long ttl = -2;
578 	if(!e) return -1;
579 	data = (struct infra_data*)e->data;
580 	if(data->ttl >= timenow) {
581 		ttl = (long long)(data->ttl - timenow);
582 		memmove(rtt, &data->rtt, sizeof(*rtt));
583 		if(timenow < data->probedelay)
584 			*delay = (int)(data->probedelay - timenow);
585 		else	*delay = 0;
586 	}
587 	*tA = (int)data->timeout_A;
588 	*tAAAA = (int)data->timeout_AAAA;
589 	*tother = (int)data->timeout_other;
590 	lock_rw_unlock(&e->lock);
591 	return ttl;
592 }
593 
594 int
595 infra_edns_update(struct infra_cache* infra, struct sockaddr_storage* addr,
596 	socklen_t addrlen, uint8_t* nm, size_t nmlen, int edns_version,
597 	time_t timenow)
598 {
599 	struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
600 		nm, nmlen, 1);
601 	struct infra_data* data;
602 	int needtoinsert = 0;
603 	if(!e) {
604 		if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
605 			return 0;
606 		needtoinsert = 1;
607 	} else if(((struct infra_data*)e->data)->ttl < timenow) {
608 		data_entry_init(infra, e, timenow);
609 	}
610 	/* have an entry, update the rtt, and the ttl */
611 	data = (struct infra_data*)e->data;
612 	/* do not update if noEDNS and stored is yesEDNS */
613 	if(!(edns_version == -1 && (data->edns_version != -1 &&
614 		data->edns_lame_known))) {
615 		data->edns_version = edns_version;
616 		data->edns_lame_known = 1;
617 	}
618 
619 	if(needtoinsert)
620 		slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
621 	else 	{ lock_rw_unlock(&e->lock); }
622 	return 1;
623 }
624 
625 int
626 infra_get_lame_rtt(struct infra_cache* infra,
627         struct sockaddr_storage* addr, socklen_t addrlen,
628         uint8_t* name, size_t namelen, uint16_t qtype,
629 	int* lame, int* dnsseclame, int* reclame, int* rtt, time_t timenow)
630 {
631 	struct infra_data* host;
632 	struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
633 		name, namelen, 0);
634 	if(!e)
635 		return 0;
636 	host = (struct infra_data*)e->data;
637 	*rtt = rtt_unclamped(&host->rtt);
638 	if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay
639 		&& rtt_notimeout(&host->rtt)*4 <= host->rtt.rto) {
640 		/* single probe for this domain, and we are not probing */
641 		/* unless the query type allows a probe to happen */
642 		if(qtype == LDNS_RR_TYPE_A) {
643 			if(host->timeout_A >= TIMEOUT_COUNT_MAX)
644 				*rtt = USEFUL_SERVER_TOP_TIMEOUT;
645 			else	*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
646 		} else if(qtype == LDNS_RR_TYPE_AAAA) {
647 			if(host->timeout_AAAA >= TIMEOUT_COUNT_MAX)
648 				*rtt = USEFUL_SERVER_TOP_TIMEOUT;
649 			else	*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
650 		} else {
651 			if(host->timeout_other >= TIMEOUT_COUNT_MAX)
652 				*rtt = USEFUL_SERVER_TOP_TIMEOUT;
653 			else	*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
654 		}
655 	}
656 	if(timenow > host->ttl) {
657 		/* expired entry */
658 		/* see if this can be a re-probe of an unresponsive server */
659 		/* minus 1000 because that is outside of the RTTBAND, so
660 		 * blacklisted servers stay blacklisted if this is chosen */
661 		if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
662 			lock_rw_unlock(&e->lock);
663 			*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
664 			*lame = 0;
665 			*dnsseclame = 0;
666 			*reclame = 0;
667 			return 1;
668 		}
669 		lock_rw_unlock(&e->lock);
670 		return 0;
671 	}
672 	/* check lameness first */
673 	if(host->lame_type_A && qtype == LDNS_RR_TYPE_A) {
674 		lock_rw_unlock(&e->lock);
675 		*lame = 1;
676 		*dnsseclame = 0;
677 		*reclame = 0;
678 		return 1;
679 	} else if(host->lame_other && qtype != LDNS_RR_TYPE_A) {
680 		lock_rw_unlock(&e->lock);
681 		*lame = 1;
682 		*dnsseclame = 0;
683 		*reclame = 0;
684 		return 1;
685 	} else if(host->isdnsseclame) {
686 		lock_rw_unlock(&e->lock);
687 		*lame = 0;
688 		*dnsseclame = 1;
689 		*reclame = 0;
690 		return 1;
691 	} else if(host->rec_lame) {
692 		lock_rw_unlock(&e->lock);
693 		*lame = 0;
694 		*dnsseclame = 0;
695 		*reclame = 1;
696 		return 1;
697 	}
698 	/* no lameness for this type of query */
699 	lock_rw_unlock(&e->lock);
700 	*lame = 0;
701 	*dnsseclame = 0;
702 	*reclame = 0;
703 	return 1;
704 }
705 
706 int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
707 	size_t namelen)
708 {
709 	int labs = dname_count_labels(name);
710 	struct domain_limit_data* d = (struct domain_limit_data*)
711 		name_tree_lookup(&infra->domain_limits, name, namelen, labs,
712 		LDNS_RR_CLASS_IN);
713 	if(!d) return infra_dp_ratelimit;
714 
715 	if(d->node.labs == labs && d->lim != -1)
716 		return d->lim; /* exact match */
717 
718 	/* find 'below match' */
719 	if(d->node.labs == labs)
720 		d = (struct domain_limit_data*)d->node.parent;
721 	while(d) {
722 		if(d->below != -1)
723 			return d->below;
724 		d = (struct domain_limit_data*)d->node.parent;
725 	}
726 	return infra_dp_ratelimit;
727 }
728 
729 /** find data item in array, for write access, caller unlocks */
730 static struct lruhash_entry* infra_find_ratedata(struct infra_cache* infra,
731 	uint8_t* name, size_t namelen, int wr)
732 {
733 	struct rate_key key;
734 	hashvalue_t h = dname_query_hash(name, 0xab);
735 	memset(&key, 0, sizeof(key));
736 	key.name = name;
737 	key.namelen = namelen;
738 	key.entry.hash = h;
739 	return slabhash_lookup(infra->domain_rates, h, &key, wr);
740 }
741 
742 /** create rate data item for name, number 1 in now */
743 static void infra_create_ratedata(struct infra_cache* infra,
744 	uint8_t* name, size_t namelen, time_t timenow)
745 {
746 	hashvalue_t h = dname_query_hash(name, 0xab);
747 	struct rate_key* k = (struct rate_key*)calloc(1, sizeof(*k));
748 	struct rate_data* d = (struct rate_data*)calloc(1, sizeof(*d));
749 	if(!k || !d) {
750 		free(k);
751 		free(d);
752 		return; /* alloc failure */
753 	}
754 	k->namelen = namelen;
755 	k->name = memdup(name, namelen);
756 	if(!k->name) {
757 		free(k);
758 		free(d);
759 		return; /* alloc failure */
760 	}
761 	lock_rw_init(&k->entry.lock);
762 	k->entry.hash = h;
763 	k->entry.key = k;
764 	k->entry.data = d;
765 	d->qps[0] = 1;
766 	d->timestamp[0] = timenow;
767 	slabhash_insert(infra->domain_rates, h, &k->entry, d, NULL);
768 }
769 
770 /** find the second and return its rate counter, if none, remove oldest */
771 static int* infra_rate_find_second(void* data, time_t t)
772 {
773 	struct rate_data* d = (struct rate_data*)data;
774 	int i, oldest;
775 	for(i=0; i<RATE_WINDOW; i++) {
776 		if(d->timestamp[i] == t)
777 			return &(d->qps[i]);
778 	}
779 	/* remove oldest timestamp, and insert it at t with 0 qps */
780 	oldest = 0;
781 	for(i=0; i<RATE_WINDOW; i++) {
782 		if(d->timestamp[i] < d->timestamp[oldest])
783 			oldest = i;
784 	}
785 	d->timestamp[oldest] = t;
786 	d->qps[oldest] = 0;
787 	return &(d->qps[oldest]);
788 }
789 
790 int infra_rate_max(void* data, time_t now)
791 {
792 	struct rate_data* d = (struct rate_data*)data;
793 	int i, max = 0;
794 	for(i=0; i<RATE_WINDOW; i++) {
795 		if(now-d->timestamp[i] <= RATE_WINDOW) {
796 			if(d->qps[i] > max)
797 				max = d->qps[i];
798 		}
799 	}
800 	return max;
801 }
802 
803 int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
804 	size_t namelen, time_t timenow)
805 {
806 	int lim, max;
807 	struct lruhash_entry* entry;
808 
809 	if(!infra_dp_ratelimit)
810 		return 1; /* not enabled */
811 
812 	/* find ratelimit */
813 	lim = infra_find_ratelimit(infra, name, namelen);
814 
815 	/* find or insert ratedata */
816 	entry = infra_find_ratedata(infra, name, namelen, 1);
817 	if(entry) {
818 		int premax = infra_rate_max(entry->data, timenow);
819 		int* cur = infra_rate_find_second(entry->data, timenow);
820 		(*cur)++;
821 		max = infra_rate_max(entry->data, timenow);
822 		lock_rw_unlock(&entry->lock);
823 
824 		if(premax < lim && max >= lim) {
825 			char buf[257];
826 			dname_str(name, buf);
827 			verbose(VERB_OPS, "ratelimit exceeded %s %d", buf, lim);
828 		}
829 		return (max < lim);
830 	}
831 
832 	/* create */
833 	infra_create_ratedata(infra, name, namelen, timenow);
834 	return (1 < lim);
835 }
836 
837 void infra_ratelimit_dec(struct infra_cache* infra, uint8_t* name,
838 	size_t namelen, time_t timenow)
839 {
840 	struct lruhash_entry* entry;
841 	int* cur;
842 	if(!infra_dp_ratelimit)
843 		return; /* not enabled */
844 	entry = infra_find_ratedata(infra, name, namelen, 1);
845 	if(!entry) return; /* not cached */
846 	cur = infra_rate_find_second(entry->data, timenow);
847 	if((*cur) > 0)
848 		(*cur)--;
849 	lock_rw_unlock(&entry->lock);
850 }
851 
852 int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name,
853 	size_t namelen, time_t timenow)
854 {
855 	struct lruhash_entry* entry;
856 	int lim, max;
857 	if(!infra_dp_ratelimit)
858 		return 0; /* not enabled */
859 
860 	/* find ratelimit */
861 	lim = infra_find_ratelimit(infra, name, namelen);
862 
863 	/* find current rate */
864 	entry = infra_find_ratedata(infra, name, namelen, 0);
865 	if(!entry)
866 		return 0; /* not cached */
867 	max = infra_rate_max(entry->data, timenow);
868 	lock_rw_unlock(&entry->lock);
869 
870 	return (max >= lim);
871 }
872 
873 size_t
874 infra_get_mem(struct infra_cache* infra)
875 {
876 	size_t s = sizeof(*infra) + slabhash_get_mem(infra->hosts);
877 	if(infra->domain_rates) s += slabhash_get_mem(infra->domain_rates);
878 	/* ignore domain_limits because walk through tree is big */
879 	return s;
880 }
881