xref: /freebsd/contrib/unbound/services/cache/infra.c (revision 3d32dc633c5e21bf15dd0d968734efe72776afdc)
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 /** ratelimit value for client ip addresses,
65  *  in queries per second. */
66 int infra_ip_ratelimit = 0;
67 
68 size_t
69 infra_sizefunc(void* k, void* ATTR_UNUSED(d))
70 {
71 	struct infra_key* key = (struct infra_key*)k;
72 	return sizeof(*key) + sizeof(struct infra_data) + key->namelen
73 		+ lock_get_mem(&key->entry.lock);
74 }
75 
76 int
77 infra_compfunc(void* key1, void* key2)
78 {
79 	struct infra_key* k1 = (struct infra_key*)key1;
80 	struct infra_key* k2 = (struct infra_key*)key2;
81 	int r = sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen);
82 	if(r != 0)
83 		return r;
84 	if(k1->namelen != k2->namelen) {
85 		if(k1->namelen < k2->namelen)
86 			return -1;
87 		return 1;
88 	}
89 	return query_dname_compare(k1->zonename, k2->zonename);
90 }
91 
92 void
93 infra_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
94 {
95 	struct infra_key* key = (struct infra_key*)k;
96 	if(!key)
97 		return;
98 	lock_rw_destroy(&key->entry.lock);
99 	free(key->zonename);
100 	free(key);
101 }
102 
103 void
104 infra_deldatafunc(void* d, void* ATTR_UNUSED(arg))
105 {
106 	struct infra_data* data = (struct infra_data*)d;
107 	free(data);
108 }
109 
110 size_t
111 rate_sizefunc(void* k, void* ATTR_UNUSED(d))
112 {
113 	struct rate_key* key = (struct rate_key*)k;
114 	return sizeof(*key) + sizeof(struct rate_data) + key->namelen
115 		+ lock_get_mem(&key->entry.lock);
116 }
117 
118 int
119 rate_compfunc(void* key1, void* key2)
120 {
121 	struct rate_key* k1 = (struct rate_key*)key1;
122 	struct rate_key* k2 = (struct rate_key*)key2;
123 	if(k1->namelen != k2->namelen) {
124 		if(k1->namelen < k2->namelen)
125 			return -1;
126 		return 1;
127 	}
128 	return query_dname_compare(k1->name, k2->name);
129 }
130 
131 void
132 rate_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
133 {
134 	struct rate_key* key = (struct rate_key*)k;
135 	if(!key)
136 		return;
137 	lock_rw_destroy(&key->entry.lock);
138 	free(key->name);
139 	free(key);
140 }
141 
142 void
143 rate_deldatafunc(void* d, void* ATTR_UNUSED(arg))
144 {
145 	struct rate_data* data = (struct rate_data*)d;
146 	free(data);
147 }
148 
149 /** find or create element in domainlimit tree */
150 static struct domain_limit_data* domain_limit_findcreate(
151 	struct infra_cache* infra, char* name)
152 {
153 	uint8_t* nm;
154 	int labs;
155 	size_t nmlen;
156 	struct domain_limit_data* d;
157 
158 	/* parse name */
159 	nm = sldns_str2wire_dname(name, &nmlen);
160 	if(!nm) {
161 		log_err("could not parse %s", name);
162 		return NULL;
163 	}
164 	labs = dname_count_labels(nm);
165 
166 	/* can we find it? */
167 	d = (struct domain_limit_data*)name_tree_find(&infra->domain_limits,
168 		nm, nmlen, labs, LDNS_RR_CLASS_IN);
169 	if(d) {
170 		free(nm);
171 		return d;
172 	}
173 
174 	/* create it */
175 	d = (struct domain_limit_data*)calloc(1, sizeof(*d));
176 	if(!d) {
177 		free(nm);
178 		return NULL;
179 	}
180 	d->node.node.key = &d->node;
181 	d->node.name = nm;
182 	d->node.len = nmlen;
183 	d->node.labs = labs;
184 	d->node.dclass = LDNS_RR_CLASS_IN;
185 	d->lim = -1;
186 	d->below = -1;
187 	if(!name_tree_insert(&infra->domain_limits, &d->node, nm, nmlen,
188 		labs, LDNS_RR_CLASS_IN)) {
189 		log_err("duplicate element in domainlimit tree");
190 		free(nm);
191 		free(d);
192 		return NULL;
193 	}
194 	return d;
195 }
196 
197 /** insert rate limit configuration into lookup tree */
198 static int infra_ratelimit_cfg_insert(struct infra_cache* infra,
199 	struct config_file* cfg)
200 {
201 	struct config_str2list* p;
202 	struct domain_limit_data* d;
203 	for(p = cfg->ratelimit_for_domain; p; p = p->next) {
204 		d = domain_limit_findcreate(infra, p->str);
205 		if(!d)
206 			return 0;
207 		d->lim = atoi(p->str2);
208 	}
209 	for(p = cfg->ratelimit_below_domain; p; p = p->next) {
210 		d = domain_limit_findcreate(infra, p->str);
211 		if(!d)
212 			return 0;
213 		d->below = atoi(p->str2);
214 	}
215 	return 1;
216 }
217 
218 struct infra_cache*
219 infra_create(struct config_file* cfg)
220 {
221 	struct infra_cache* infra = (struct infra_cache*)calloc(1,
222 		sizeof(struct infra_cache));
223 	size_t maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+
224 		sizeof(struct infra_data)+INFRA_BYTES_NAME);
225 	infra->hosts = slabhash_create(cfg->infra_cache_slabs,
226 		INFRA_HOST_STARTSIZE, maxmem, &infra_sizefunc, &infra_compfunc,
227 		&infra_delkeyfunc, &infra_deldatafunc, NULL);
228 	if(!infra->hosts) {
229 		free(infra);
230 		return NULL;
231 	}
232 	infra->host_ttl = cfg->host_ttl;
233 	name_tree_init(&infra->domain_limits);
234 	infra_dp_ratelimit = cfg->ratelimit;
235 	infra->domain_rates = slabhash_create(cfg->ratelimit_slabs,
236 		INFRA_HOST_STARTSIZE, cfg->ratelimit_size,
237 		&rate_sizefunc, &rate_compfunc, &rate_delkeyfunc,
238 		&rate_deldatafunc, NULL);
239 	if(!infra->domain_rates) {
240 		infra_delete(infra);
241 		return NULL;
242 	}
243 	/* insert config data into ratelimits */
244 	if(!infra_ratelimit_cfg_insert(infra, cfg)) {
245 		infra_delete(infra);
246 		return NULL;
247 	}
248 	name_tree_init_parents(&infra->domain_limits);
249 	infra_ip_ratelimit = cfg->ip_ratelimit;
250 	infra->client_ip_rates = slabhash_create(cfg->ip_ratelimit_slabs,
251 	    INFRA_HOST_STARTSIZE, cfg->ip_ratelimit_size, &ip_rate_sizefunc,
252 	    &ip_rate_compfunc, &ip_rate_delkeyfunc, &ip_rate_deldatafunc, NULL);
253 	if(!infra->client_ip_rates) {
254 		infra_delete(infra);
255 		return NULL;
256 	}
257 	return infra;
258 }
259 
260 /** delete domain_limit entries */
261 static void domain_limit_free(rbnode_type* n, void* ATTR_UNUSED(arg))
262 {
263 	if(n) {
264 		free(((struct domain_limit_data*)n)->node.name);
265 		free(n);
266 	}
267 }
268 
269 void
270 infra_delete(struct infra_cache* infra)
271 {
272 	if(!infra)
273 		return;
274 	slabhash_delete(infra->hosts);
275 	slabhash_delete(infra->domain_rates);
276 	traverse_postorder(&infra->domain_limits, domain_limit_free, NULL);
277 	slabhash_delete(infra->client_ip_rates);
278 	free(infra);
279 }
280 
281 struct infra_cache*
282 infra_adjust(struct infra_cache* infra, struct config_file* cfg)
283 {
284 	size_t maxmem;
285 	if(!infra)
286 		return infra_create(cfg);
287 	infra->host_ttl = cfg->host_ttl;
288 	maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+
289 		sizeof(struct infra_data)+INFRA_BYTES_NAME);
290 	if(maxmem != slabhash_get_size(infra->hosts) ||
291 		cfg->infra_cache_slabs != infra->hosts->size) {
292 		infra_delete(infra);
293 		infra = infra_create(cfg);
294 	}
295 	return infra;
296 }
297 
298 /** calculate the hash value for a host key
299  *  set use_port to a non-0 number to use the port in
300  *  the hash calculation; 0 to ignore the port.*/
301 static hashvalue_type
302 hash_addr(struct sockaddr_storage* addr, socklen_t addrlen,
303   int use_port)
304 {
305 	hashvalue_type h = 0xab;
306 	/* select the pieces to hash, some OS have changing data inside */
307 	if(addr_is_ip6(addr, addrlen)) {
308 		struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr;
309 		h = hashlittle(&in6->sin6_family, sizeof(in6->sin6_family), h);
310 		if(use_port){
311 			h = hashlittle(&in6->sin6_port, sizeof(in6->sin6_port), h);
312 		}
313 		h = hashlittle(&in6->sin6_addr, INET6_SIZE, h);
314 	} else {
315 		struct sockaddr_in* in = (struct sockaddr_in*)addr;
316 		h = hashlittle(&in->sin_family, sizeof(in->sin_family), h);
317 		if(use_port){
318 			h = hashlittle(&in->sin_port, sizeof(in->sin_port), h);
319 		}
320 		h = hashlittle(&in->sin_addr, INET_SIZE, h);
321 	}
322 	return h;
323 }
324 
325 /** calculate infra hash for a key */
326 static hashvalue_type
327 hash_infra(struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name)
328 {
329 	return dname_query_hash(name, hash_addr(addr, addrlen, 1));
330 }
331 
332 /** lookup version that does not check host ttl (you check it) */
333 struct lruhash_entry*
334 infra_lookup_nottl(struct infra_cache* infra, struct sockaddr_storage* addr,
335 	socklen_t addrlen, uint8_t* name, size_t namelen, int wr)
336 {
337 	struct infra_key k;
338 	k.addrlen = addrlen;
339 	memcpy(&k.addr, addr, addrlen);
340 	k.namelen = namelen;
341 	k.zonename = name;
342 	k.entry.hash = hash_infra(addr, addrlen, name);
343 	k.entry.key = (void*)&k;
344 	k.entry.data = NULL;
345 	return slabhash_lookup(infra->hosts, k.entry.hash, &k, wr);
346 }
347 
348 /** init the data elements */
349 static void
350 data_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
351 	time_t timenow)
352 {
353 	struct infra_data* data = (struct infra_data*)e->data;
354 	data->ttl = timenow + infra->host_ttl;
355 	rtt_init(&data->rtt);
356 	data->edns_version = 0;
357 	data->edns_lame_known = 0;
358 	data->probedelay = 0;
359 	data->isdnsseclame = 0;
360 	data->rec_lame = 0;
361 	data->lame_type_A = 0;
362 	data->lame_other = 0;
363 	data->timeout_A = 0;
364 	data->timeout_AAAA = 0;
365 	data->timeout_other = 0;
366 }
367 
368 /**
369  * Create and init a new entry for a host
370  * @param infra: infra structure with config parameters.
371  * @param addr: host address.
372  * @param addrlen: length of addr.
373  * @param name: name of zone
374  * @param namelen: length of name.
375  * @param tm: time now.
376  * @return: the new entry or NULL on malloc failure.
377  */
378 static struct lruhash_entry*
379 new_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
380 	socklen_t addrlen, uint8_t* name, size_t namelen, time_t tm)
381 {
382 	struct infra_data* data;
383 	struct infra_key* key = (struct infra_key*)malloc(sizeof(*key));
384 	if(!key)
385 		return NULL;
386 	data = (struct infra_data*)malloc(sizeof(struct infra_data));
387 	if(!data) {
388 		free(key);
389 		return NULL;
390 	}
391 	key->zonename = memdup(name, namelen);
392 	if(!key->zonename) {
393 		free(key);
394 		free(data);
395 		return NULL;
396 	}
397 	key->namelen = namelen;
398 	lock_rw_init(&key->entry.lock);
399 	key->entry.hash = hash_infra(addr, addrlen, name);
400 	key->entry.key = (void*)key;
401 	key->entry.data = (void*)data;
402 	key->addrlen = addrlen;
403 	memcpy(&key->addr, addr, addrlen);
404 	data_entry_init(infra, &key->entry, tm);
405 	return &key->entry;
406 }
407 
408 int
409 infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
410         socklen_t addrlen, uint8_t* nm, size_t nmlen, time_t timenow,
411 	int* edns_vs, uint8_t* edns_lame_known, int* to)
412 {
413 	struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
414 		nm, nmlen, 0);
415 	struct infra_data* data;
416 	int wr = 0;
417 	if(e && ((struct infra_data*)e->data)->ttl < timenow) {
418 		/* it expired, try to reuse existing entry */
419 		int old = ((struct infra_data*)e->data)->rtt.rto;
420 		uint8_t tA = ((struct infra_data*)e->data)->timeout_A;
421 		uint8_t tAAAA = ((struct infra_data*)e->data)->timeout_AAAA;
422 		uint8_t tother = ((struct infra_data*)e->data)->timeout_other;
423 		lock_rw_unlock(&e->lock);
424 		e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1);
425 		if(e) {
426 			/* if its still there we have a writelock, init */
427 			/* re-initialise */
428 			/* do not touch lameness, it may be valid still */
429 			data_entry_init(infra, e, timenow);
430 			wr = 1;
431 			/* TOP_TIMEOUT remains on reuse */
432 			if(old >= USEFUL_SERVER_TOP_TIMEOUT) {
433 				((struct infra_data*)e->data)->rtt.rto
434 					= USEFUL_SERVER_TOP_TIMEOUT;
435 				((struct infra_data*)e->data)->timeout_A = tA;
436 				((struct infra_data*)e->data)->timeout_AAAA = tAAAA;
437 				((struct infra_data*)e->data)->timeout_other = tother;
438 			}
439 		}
440 	}
441 	if(!e) {
442 		/* insert new entry */
443 		if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
444 			return 0;
445 		data = (struct infra_data*)e->data;
446 		*edns_vs = data->edns_version;
447 		*edns_lame_known = data->edns_lame_known;
448 		*to = rtt_timeout(&data->rtt);
449 		slabhash_insert(infra->hosts, e->hash, e, data, NULL);
450 		return 1;
451 	}
452 	/* use existing entry */
453 	data = (struct infra_data*)e->data;
454 	*edns_vs = data->edns_version;
455 	*edns_lame_known = data->edns_lame_known;
456 	*to = rtt_timeout(&data->rtt);
457 	if(*to >= PROBE_MAXRTO && rtt_notimeout(&data->rtt)*4 <= *to) {
458 		/* delay other queries, this is the probe query */
459 		if(!wr) {
460 			lock_rw_unlock(&e->lock);
461 			e = infra_lookup_nottl(infra, addr,addrlen,nm,nmlen, 1);
462 			if(!e) { /* flushed from cache real fast, no use to
463 				allocate just for the probedelay */
464 				return 1;
465 			}
466 			data = (struct infra_data*)e->data;
467 		}
468 		/* add 999 to round up the timeout value from msec to sec,
469 		 * then add a whole second so it is certain that this probe
470 		 * has timed out before the next is allowed */
471 		data->probedelay = timenow + ((*to)+1999)/1000;
472 	}
473 	lock_rw_unlock(&e->lock);
474 	return 1;
475 }
476 
477 int
478 infra_set_lame(struct infra_cache* infra, struct sockaddr_storage* addr,
479 	socklen_t addrlen, uint8_t* nm, size_t nmlen, time_t timenow,
480 	int dnsseclame, int reclame, uint16_t qtype)
481 {
482 	struct infra_data* data;
483 	struct lruhash_entry* e;
484 	int needtoinsert = 0;
485 	e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1);
486 	if(!e) {
487 		/* insert it */
488 		if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) {
489 			log_err("set_lame: malloc failure");
490 			return 0;
491 		}
492 		needtoinsert = 1;
493 	} else if( ((struct infra_data*)e->data)->ttl < timenow) {
494 		/* expired, reuse existing entry */
495 		data_entry_init(infra, e, timenow);
496 	}
497 	/* got an entry, now set the zone lame */
498 	data = (struct infra_data*)e->data;
499 	/* merge data (if any) */
500 	if(dnsseclame)
501 		data->isdnsseclame = 1;
502 	if(reclame)
503 		data->rec_lame = 1;
504 	if(!dnsseclame && !reclame && qtype == LDNS_RR_TYPE_A)
505 		data->lame_type_A = 1;
506 	if(!dnsseclame  && !reclame && qtype != LDNS_RR_TYPE_A)
507 		data->lame_other = 1;
508 	/* done */
509 	if(needtoinsert)
510 		slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
511 	else 	{ lock_rw_unlock(&e->lock); }
512 	return 1;
513 }
514 
515 void
516 infra_update_tcp_works(struct infra_cache* infra,
517         struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm,
518 	size_t nmlen)
519 {
520 	struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
521 		nm, nmlen, 1);
522 	struct infra_data* data;
523 	if(!e)
524 		return; /* doesn't exist */
525 	data = (struct infra_data*)e->data;
526 	if(data->rtt.rto >= RTT_MAX_TIMEOUT)
527 		/* do not disqualify this server altogether, it is better
528 		 * than nothing */
529 		data->rtt.rto = RTT_MAX_TIMEOUT-1000;
530 	lock_rw_unlock(&e->lock);
531 }
532 
533 int
534 infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr,
535 	socklen_t addrlen, uint8_t* nm, size_t nmlen, int qtype,
536 	int roundtrip, int orig_rtt, time_t timenow)
537 {
538 	struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
539 		nm, nmlen, 1);
540 	struct infra_data* data;
541 	int needtoinsert = 0;
542 	int rto = 1;
543 	if(!e) {
544 		if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
545 			return 0;
546 		needtoinsert = 1;
547 	} else if(((struct infra_data*)e->data)->ttl < timenow) {
548 		data_entry_init(infra, e, timenow);
549 	}
550 	/* have an entry, update the rtt */
551 	data = (struct infra_data*)e->data;
552 	if(roundtrip == -1) {
553 		rtt_lost(&data->rtt, orig_rtt);
554 		if(qtype == LDNS_RR_TYPE_A) {
555 			if(data->timeout_A < TIMEOUT_COUNT_MAX)
556 				data->timeout_A++;
557 		} else if(qtype == LDNS_RR_TYPE_AAAA) {
558 			if(data->timeout_AAAA < TIMEOUT_COUNT_MAX)
559 				data->timeout_AAAA++;
560 		} else {
561 			if(data->timeout_other < TIMEOUT_COUNT_MAX)
562 				data->timeout_other++;
563 		}
564 	} else {
565 		/* if we got a reply, but the old timeout was above server
566 		 * selection height, delete the timeout so the server is
567 		 * fully available again */
568 		if(rtt_unclamped(&data->rtt) >= USEFUL_SERVER_TOP_TIMEOUT)
569 			rtt_init(&data->rtt);
570 		rtt_update(&data->rtt, roundtrip);
571 		data->probedelay = 0;
572 		if(qtype == LDNS_RR_TYPE_A)
573 			data->timeout_A = 0;
574 		else if(qtype == LDNS_RR_TYPE_AAAA)
575 			data->timeout_AAAA = 0;
576 		else	data->timeout_other = 0;
577 	}
578 	if(data->rtt.rto > 0)
579 		rto = data->rtt.rto;
580 
581 	if(needtoinsert)
582 		slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
583 	else 	{ lock_rw_unlock(&e->lock); }
584 	return rto;
585 }
586 
587 long long infra_get_host_rto(struct infra_cache* infra,
588         struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm,
589 	size_t nmlen, struct rtt_info* rtt, int* delay, time_t timenow,
590 	int* tA, int* tAAAA, int* tother)
591 {
592 	struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
593 		nm, nmlen, 0);
594 	struct infra_data* data;
595 	long long ttl = -2;
596 	if(!e) return -1;
597 	data = (struct infra_data*)e->data;
598 	if(data->ttl >= timenow) {
599 		ttl = (long long)(data->ttl - timenow);
600 		memmove(rtt, &data->rtt, sizeof(*rtt));
601 		if(timenow < data->probedelay)
602 			*delay = (int)(data->probedelay - timenow);
603 		else	*delay = 0;
604 	}
605 	*tA = (int)data->timeout_A;
606 	*tAAAA = (int)data->timeout_AAAA;
607 	*tother = (int)data->timeout_other;
608 	lock_rw_unlock(&e->lock);
609 	return ttl;
610 }
611 
612 int
613 infra_edns_update(struct infra_cache* infra, struct sockaddr_storage* addr,
614 	socklen_t addrlen, uint8_t* nm, size_t nmlen, int edns_version,
615 	time_t timenow)
616 {
617 	struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
618 		nm, nmlen, 1);
619 	struct infra_data* data;
620 	int needtoinsert = 0;
621 	if(!e) {
622 		if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow)))
623 			return 0;
624 		needtoinsert = 1;
625 	} else if(((struct infra_data*)e->data)->ttl < timenow) {
626 		data_entry_init(infra, e, timenow);
627 	}
628 	/* have an entry, update the rtt, and the ttl */
629 	data = (struct infra_data*)e->data;
630 	/* do not update if noEDNS and stored is yesEDNS */
631 	if(!(edns_version == -1 && (data->edns_version != -1 &&
632 		data->edns_lame_known))) {
633 		data->edns_version = edns_version;
634 		data->edns_lame_known = 1;
635 	}
636 
637 	if(needtoinsert)
638 		slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
639 	else 	{ lock_rw_unlock(&e->lock); }
640 	return 1;
641 }
642 
643 int
644 infra_get_lame_rtt(struct infra_cache* infra,
645         struct sockaddr_storage* addr, socklen_t addrlen,
646         uint8_t* name, size_t namelen, uint16_t qtype,
647 	int* lame, int* dnsseclame, int* reclame, int* rtt, time_t timenow)
648 {
649 	struct infra_data* host;
650 	struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
651 		name, namelen, 0);
652 	if(!e)
653 		return 0;
654 	host = (struct infra_data*)e->data;
655 	*rtt = rtt_unclamped(&host->rtt);
656 	if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay
657 		&& rtt_notimeout(&host->rtt)*4 <= host->rtt.rto) {
658 		/* single probe for this domain, and we are not probing */
659 		/* unless the query type allows a probe to happen */
660 		if(qtype == LDNS_RR_TYPE_A) {
661 			if(host->timeout_A >= TIMEOUT_COUNT_MAX)
662 				*rtt = USEFUL_SERVER_TOP_TIMEOUT;
663 			else	*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
664 		} else if(qtype == LDNS_RR_TYPE_AAAA) {
665 			if(host->timeout_AAAA >= TIMEOUT_COUNT_MAX)
666 				*rtt = USEFUL_SERVER_TOP_TIMEOUT;
667 			else	*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
668 		} else {
669 			if(host->timeout_other >= TIMEOUT_COUNT_MAX)
670 				*rtt = USEFUL_SERVER_TOP_TIMEOUT;
671 			else	*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
672 		}
673 	}
674 	if(timenow > host->ttl) {
675 		/* expired entry */
676 		/* see if this can be a re-probe of an unresponsive server */
677 		/* minus 1000 because that is outside of the RTTBAND, so
678 		 * blacklisted servers stay blacklisted if this is chosen */
679 		if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
680 			lock_rw_unlock(&e->lock);
681 			*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
682 			*lame = 0;
683 			*dnsseclame = 0;
684 			*reclame = 0;
685 			return 1;
686 		}
687 		lock_rw_unlock(&e->lock);
688 		return 0;
689 	}
690 	/* check lameness first */
691 	if(host->lame_type_A && qtype == LDNS_RR_TYPE_A) {
692 		lock_rw_unlock(&e->lock);
693 		*lame = 1;
694 		*dnsseclame = 0;
695 		*reclame = 0;
696 		return 1;
697 	} else if(host->lame_other && qtype != LDNS_RR_TYPE_A) {
698 		lock_rw_unlock(&e->lock);
699 		*lame = 1;
700 		*dnsseclame = 0;
701 		*reclame = 0;
702 		return 1;
703 	} else if(host->isdnsseclame) {
704 		lock_rw_unlock(&e->lock);
705 		*lame = 0;
706 		*dnsseclame = 1;
707 		*reclame = 0;
708 		return 1;
709 	} else if(host->rec_lame) {
710 		lock_rw_unlock(&e->lock);
711 		*lame = 0;
712 		*dnsseclame = 0;
713 		*reclame = 1;
714 		return 1;
715 	}
716 	/* no lameness for this type of query */
717 	lock_rw_unlock(&e->lock);
718 	*lame = 0;
719 	*dnsseclame = 0;
720 	*reclame = 0;
721 	return 1;
722 }
723 
724 int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
725 	size_t namelen)
726 {
727 	int labs = dname_count_labels(name);
728 	struct domain_limit_data* d = (struct domain_limit_data*)
729 		name_tree_lookup(&infra->domain_limits, name, namelen, labs,
730 		LDNS_RR_CLASS_IN);
731 	if(!d) return infra_dp_ratelimit;
732 
733 	if(d->node.labs == labs && d->lim != -1)
734 		return d->lim; /* exact match */
735 
736 	/* find 'below match' */
737 	if(d->node.labs == labs)
738 		d = (struct domain_limit_data*)d->node.parent;
739 	while(d) {
740 		if(d->below != -1)
741 			return d->below;
742 		d = (struct domain_limit_data*)d->node.parent;
743 	}
744 	return infra_dp_ratelimit;
745 }
746 
747 size_t ip_rate_sizefunc(void* k, void* ATTR_UNUSED(d))
748 {
749 	struct ip_rate_key* key = (struct ip_rate_key*)k;
750 	return sizeof(*key) + sizeof(struct ip_rate_data)
751 		+ lock_get_mem(&key->entry.lock);
752 }
753 
754 int ip_rate_compfunc(void* key1, void* key2)
755 {
756 	struct ip_rate_key* k1 = (struct ip_rate_key*)key1;
757 	struct ip_rate_key* k2 = (struct ip_rate_key*)key2;
758 	return sockaddr_cmp_addr(&k1->addr, k1->addrlen,
759 		&k2->addr, k2->addrlen);
760 }
761 
762 void ip_rate_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
763 {
764 	struct ip_rate_key* key = (struct ip_rate_key*)k;
765 	if(!key)
766 		return;
767 	lock_rw_destroy(&key->entry.lock);
768 	free(key);
769 }
770 
771 /** find data item in array, for write access, caller unlocks */
772 static struct lruhash_entry* infra_find_ratedata(struct infra_cache* infra,
773 	uint8_t* name, size_t namelen, int wr)
774 {
775 	struct rate_key key;
776 	hashvalue_type h = dname_query_hash(name, 0xab);
777 	memset(&key, 0, sizeof(key));
778 	key.name = name;
779 	key.namelen = namelen;
780 	key.entry.hash = h;
781 	return slabhash_lookup(infra->domain_rates, h, &key, wr);
782 }
783 
784 /** find data item in array for ip addresses */
785 static struct lruhash_entry* infra_find_ip_ratedata(struct infra_cache* infra,
786 	struct comm_reply* repinfo, int wr)
787 {
788 	struct ip_rate_key key;
789 	hashvalue_type h = hash_addr(&(repinfo->addr),
790 		repinfo->addrlen, 0);
791 	memset(&key, 0, sizeof(key));
792 	key.addr = repinfo->addr;
793 	key.addrlen = repinfo->addrlen;
794 	key.entry.hash = h;
795 	return slabhash_lookup(infra->client_ip_rates, h, &key, wr);
796 }
797 
798 /** create rate data item for name, number 1 in now */
799 static void infra_create_ratedata(struct infra_cache* infra,
800 	uint8_t* name, size_t namelen, time_t timenow)
801 {
802 	hashvalue_type h = dname_query_hash(name, 0xab);
803 	struct rate_key* k = (struct rate_key*)calloc(1, sizeof(*k));
804 	struct rate_data* d = (struct rate_data*)calloc(1, sizeof(*d));
805 	if(!k || !d) {
806 		free(k);
807 		free(d);
808 		return; /* alloc failure */
809 	}
810 	k->namelen = namelen;
811 	k->name = memdup(name, namelen);
812 	if(!k->name) {
813 		free(k);
814 		free(d);
815 		return; /* alloc failure */
816 	}
817 	lock_rw_init(&k->entry.lock);
818 	k->entry.hash = h;
819 	k->entry.key = k;
820 	k->entry.data = d;
821 	d->qps[0] = 1;
822 	d->timestamp[0] = timenow;
823 	slabhash_insert(infra->domain_rates, h, &k->entry, d, NULL);
824 }
825 
826 /** create rate data item for ip address */
827 static void infra_ip_create_ratedata(struct infra_cache* infra,
828 	struct comm_reply* repinfo, time_t timenow)
829 {
830 	hashvalue_type h = hash_addr(&(repinfo->addr),
831 	repinfo->addrlen, 0);
832 	struct ip_rate_key* k = (struct ip_rate_key*)calloc(1, sizeof(*k));
833 	struct ip_rate_data* d = (struct ip_rate_data*)calloc(1, sizeof(*d));
834 	if(!k || !d) {
835 		free(k);
836 		free(d);
837 		return; /* alloc failure */
838 	}
839 	k->addr = repinfo->addr;
840 	k->addrlen = repinfo->addrlen;
841 	lock_rw_init(&k->entry.lock);
842 	k->entry.hash = h;
843 	k->entry.key = k;
844 	k->entry.data = d;
845 	d->qps[0] = 1;
846 	d->timestamp[0] = timenow;
847 	slabhash_insert(infra->client_ip_rates, h, &k->entry, d, NULL);
848 }
849 
850 /** find the second and return its rate counter, if none, remove oldest */
851 static int* infra_rate_find_second(void* data, time_t t)
852 {
853 	struct rate_data* d = (struct rate_data*)data;
854 	int i, oldest;
855 	for(i=0; i<RATE_WINDOW; i++) {
856 		if(d->timestamp[i] == t)
857 			return &(d->qps[i]);
858 	}
859 	/* remove oldest timestamp, and insert it at t with 0 qps */
860 	oldest = 0;
861 	for(i=0; i<RATE_WINDOW; i++) {
862 		if(d->timestamp[i] < d->timestamp[oldest])
863 			oldest = i;
864 	}
865 	d->timestamp[oldest] = t;
866 	d->qps[oldest] = 0;
867 	return &(d->qps[oldest]);
868 }
869 
870 int infra_rate_max(void* data, time_t now)
871 {
872 	struct rate_data* d = (struct rate_data*)data;
873 	int i, max = 0;
874 	for(i=0; i<RATE_WINDOW; i++) {
875 		if(now-d->timestamp[i] <= RATE_WINDOW) {
876 			if(d->qps[i] > max)
877 				max = d->qps[i];
878 		}
879 	}
880 	return max;
881 }
882 
883 int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
884 	size_t namelen, time_t timenow)
885 {
886 	int lim, max;
887 	struct lruhash_entry* entry;
888 
889 	if(!infra_dp_ratelimit)
890 		return 1; /* not enabled */
891 
892 	/* find ratelimit */
893 	lim = infra_find_ratelimit(infra, name, namelen);
894 	if(!lim)
895 		return 1; /* disabled for this domain */
896 
897 	/* find or insert ratedata */
898 	entry = infra_find_ratedata(infra, name, namelen, 1);
899 	if(entry) {
900 		int premax = infra_rate_max(entry->data, timenow);
901 		int* cur = infra_rate_find_second(entry->data, timenow);
902 		(*cur)++;
903 		max = infra_rate_max(entry->data, timenow);
904 		lock_rw_unlock(&entry->lock);
905 
906 		if(premax < lim && max >= lim) {
907 			char buf[257];
908 			dname_str(name, buf);
909 			verbose(VERB_OPS, "ratelimit exceeded %s %d", buf, lim);
910 		}
911 		return (max < lim);
912 	}
913 
914 	/* create */
915 	infra_create_ratedata(infra, name, namelen, timenow);
916 	return (1 < lim);
917 }
918 
919 void infra_ratelimit_dec(struct infra_cache* infra, uint8_t* name,
920 	size_t namelen, time_t timenow)
921 {
922 	struct lruhash_entry* entry;
923 	int* cur;
924 	if(!infra_dp_ratelimit)
925 		return; /* not enabled */
926 	entry = infra_find_ratedata(infra, name, namelen, 1);
927 	if(!entry) return; /* not cached */
928 	cur = infra_rate_find_second(entry->data, timenow);
929 	if((*cur) > 0)
930 		(*cur)--;
931 	lock_rw_unlock(&entry->lock);
932 }
933 
934 int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name,
935 	size_t namelen, time_t timenow)
936 {
937 	struct lruhash_entry* entry;
938 	int lim, max;
939 	if(!infra_dp_ratelimit)
940 		return 0; /* not enabled */
941 
942 	/* find ratelimit */
943 	lim = infra_find_ratelimit(infra, name, namelen);
944 	if(!lim)
945 		return 0; /* disabled for this domain */
946 
947 	/* find current rate */
948 	entry = infra_find_ratedata(infra, name, namelen, 0);
949 	if(!entry)
950 		return 0; /* not cached */
951 	max = infra_rate_max(entry->data, timenow);
952 	lock_rw_unlock(&entry->lock);
953 
954 	return (max >= lim);
955 }
956 
957 size_t
958 infra_get_mem(struct infra_cache* infra)
959 {
960 	size_t s = sizeof(*infra) + slabhash_get_mem(infra->hosts);
961 	if(infra->domain_rates) s += slabhash_get_mem(infra->domain_rates);
962 	if(infra->client_ip_rates) s += slabhash_get_mem(infra->client_ip_rates);
963 	/* ignore domain_limits because walk through tree is big */
964 	return s;
965 }
966 
967 int infra_ip_ratelimit_inc(struct infra_cache* infra,
968   struct comm_reply* repinfo, time_t timenow)
969 {
970 	int max;
971 	struct lruhash_entry* entry;
972 
973 	/* not enabled */
974 	if(!infra_ip_ratelimit) {
975 		return 1;
976 	}
977 	/* find or insert ratedata */
978 	entry = infra_find_ip_ratedata(infra, repinfo, 1);
979 	if(entry) {
980 		int premax = infra_rate_max(entry->data, timenow);
981 		int* cur = infra_rate_find_second(entry->data, timenow);
982 		(*cur)++;
983 		max = infra_rate_max(entry->data, timenow);
984 		lock_rw_unlock(&entry->lock);
985 
986 		if(premax < infra_ip_ratelimit && max >= infra_ip_ratelimit) {
987 			char client_ip[128];
988 			addr_to_str((struct sockaddr_storage *)&repinfo->addr,
989 				repinfo->addrlen, client_ip, sizeof(client_ip));
990 			verbose(VERB_OPS, "ratelimit exceeded %s %d", client_ip,
991 				infra_ip_ratelimit);
992 		}
993 		return (max <= infra_ip_ratelimit);
994 	}
995 
996 	/* create */
997 	infra_ip_create_ratedata(infra, repinfo, timenow);
998 	return 1;
999 }
1000