]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/unbound/services/cache/infra.c
MFV r338519:
[FreeBSD/FreeBSD.git] / contrib / unbound / services / cache / infra.c
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 }