]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - contrib/unbound/services/cache/infra.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.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 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 }