val_kcache.c revision 269257
172847Sgshapiro/* 250472Speter * validator/val_kcache.c - validator key shared cache with validated keys 372847Sgshapiro * 472847Sgshapiro * Copyright (c) 2007, NLnet Labs. All rights reserved. 572847Sgshapiro * 672847Sgshapiro * This software is open source. 772847Sgshapiro * 872847Sgshapiro * Redistribution and use in source and binary forms, with or without 972847Sgshapiro * modification, are permitted provided that the following conditions 1072847Sgshapiro * are met: 1172847Sgshapiro * 1272847Sgshapiro * Redistributions of source code must retain the above copyright notice, 1372847Sgshapiro * this list of conditions and the following disclaimer. 1493315Sgshapiro * 1593853Sgshapiro * Redistributions in binary form must reproduce the above copyright notice, 1693853Sgshapiro * this list of conditions and the following disclaimer in the documentation 1793853Sgshapiro * and/or other materials provided with the distribution. 1893853Sgshapiro * 1993853Sgshapiro * Neither the name of the NLNET LABS nor the names of its contributors may 2093853Sgshapiro * be used to endorse or promote products derived from this software without 2193853Sgshapiro * specific prior written permission. 2293853Sgshapiro * 2372847Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2493853Sgshapiro * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2593853Sgshapiro * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2693853Sgshapiro * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2793853Sgshapiro * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2893853Sgshapiro * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2993853Sgshapiro * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3093853Sgshapiro * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3193315Sgshapiro * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3293315Sgshapiro * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3393315Sgshapiro * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3493315Sgshapiro */ 3593315Sgshapiro 3672847Sgshapiro/** 3772847Sgshapiro * \file 3872847Sgshapiro * 3972847Sgshapiro * This file contains functions for dealing with the validator key cache. 4072847Sgshapiro */ 4172847Sgshapiro#include "config.h" 4272847Sgshapiro#include "validator/val_kcache.h" 4372847Sgshapiro#include "validator/val_kentry.h" 4494676Sgshapiro#include "util/log.h" 4594676Sgshapiro#include "util/config_file.h" 4672847Sgshapiro#include "util/data/dname.h" 47117286Sgshapiro#include "util/module.h" 4872847Sgshapiro 4976622Sgshapirostruct key_cache* 5076622Sgshapirokey_cache_create(struct config_file* cfg) 5194676Sgshapiro{ 52117291Sgshapiro struct key_cache* kcache = (struct key_cache*)calloc(1, 53117291Sgshapiro sizeof(*kcache)); 54117291Sgshapiro size_t numtables, start_size, maxmem; 5594676Sgshapiro if(!kcache) { 56117286Sgshapiro log_err("malloc failure"); 57117291Sgshapiro return NULL; 58117291Sgshapiro } 59117291Sgshapiro numtables = cfg->key_cache_slabs; 6072847Sgshapiro start_size = HASH_DEFAULT_STARTARRAY; 6172847Sgshapiro maxmem = cfg->key_cache_size; 6272847Sgshapiro kcache->slab = slabhash_create(numtables, start_size, maxmem, 6372847Sgshapiro &key_entry_sizefunc, &key_entry_compfunc, 6472847Sgshapiro &key_entry_delkeyfunc, &key_entry_deldatafunc, NULL); 6572847Sgshapiro if(!kcache->slab) { 6639146Sbrian log_err("malloc failure"); 6776622Sgshapiro free(kcache); 6876622Sgshapiro return NULL; 6976622Sgshapiro } 7076622Sgshapiro return kcache; 7184684Sgshapiro} 7276622Sgshapiro 7376622Sgshapirovoid 7476622Sgshapirokey_cache_delete(struct key_cache* kcache) 75117291Sgshapiro{ 76117291Sgshapiro if(!kcache) 77130157Sgshapiro return; 7894676Sgshapiro slabhash_delete(kcache->slab); 79117291Sgshapiro free(kcache); 80117291Sgshapiro} 81117291Sgshapiro 82117291Sgshapirovoid 8373209Sgshapirokey_cache_insert(struct key_cache* kcache, struct key_entry_key* kkey, 8430581Sjmb struct module_qstate* qstate) 8594676Sgshapiro{ 8694676Sgshapiro struct key_entry_key* k = key_entry_copy(kkey); 8794676Sgshapiro if(!k) 8894676Sgshapiro return; 8972847Sgshapiro if(key_entry_isbad(k) && qstate->errinf && 9057947Srwatson qstate->env->cfg->val_log_level >= 2) { 9172847Sgshapiro /* on malloc failure there is simply no reason string */ 9272847Sgshapiro key_entry_set_reason(k, errinf_to_str(qstate)); 9372847Sgshapiro } 9472847Sgshapiro key_entry_hash(k); 9572847Sgshapiro slabhash_insert(kcache->slab, k->entry.hash, &k->entry, 9672847Sgshapiro k->entry.data, NULL); 9793765Sru} 9893765Sru 9972847Sgshapiro/** 10057947Srwatson * Lookup exactly in the key cache. Returns pointer to locked entry. 10172847Sgshapiro * Caller must unlock it after use. 10293853Sgshapiro * @param kcache: the key cache. 10372847Sgshapiro * @param name: for what name to look; uncompressed wireformat 10493853Sgshapiro * @param namelen: length of the name. 10557947Srwatson * @param key_class: class of the key. 10672847Sgshapiro * @param wr: set true to get a writelock. 10772847Sgshapiro * @return key entry, locked, or NULL if not found. No TTL checking is 10872847Sgshapiro * performed. 10972847Sgshapiro */ 11072847Sgshapirostatic struct key_entry_key* 11172847Sgshapirokey_cache_search(struct key_cache* kcache, uint8_t* name, size_t namelen, 11264567Sgshapiro uint16_t key_class, int wr) 11397200Sgshapiro{ 11497200Sgshapiro struct lruhash_entry* e; 11597200Sgshapiro struct key_entry_key lookfor; 11672847Sgshapiro lookfor.entry.key = &lookfor; 117117286Sgshapiro lookfor.name = name; 11857947Srwatson lookfor.namelen = namelen; 11972847Sgshapiro lookfor.key_class = key_class; 12072847Sgshapiro key_entry_hash(&lookfor); 12172847Sgshapiro e = slabhash_lookup(kcache->slab, lookfor.entry.hash, &lookfor, wr); 12272847Sgshapiro if(!e) 12372847Sgshapiro return NULL; 12475074Sgshapiro return (struct key_entry_key*)e->key; 12575074Sgshapiro} 12672847Sgshapiro 12772847Sgshapirostruct key_entry_key* 12875073Sgshapirokey_cache_obtain(struct key_cache* kcache, uint8_t* name, size_t namelen, 12972847Sgshapiro uint16_t key_class, struct regional* region, time_t now) 13075074Sgshapiro{ 13157947Srwatson /* keep looking until we find a nonexpired entry */ 13275073Sgshapiro while(1) { 13372847Sgshapiro struct key_entry_key* k = key_cache_search(kcache, name, 13472847Sgshapiro namelen, key_class, 0); 13572847Sgshapiro if(k) { 13672847Sgshapiro /* see if TTL is OK */ 13757947Srwatson struct key_entry_data* d = (struct key_entry_data*) 13872847Sgshapiro k->entry.data; 13972847Sgshapiro if(now <= d->ttl) { 14072847Sgshapiro /* copy and return it */ 14172847Sgshapiro struct key_entry_key* retkey = 14272847Sgshapiro key_entry_copy_toregion(k, region); 143117286Sgshapiro lock_rw_unlock(&k->entry.lock); 14472847Sgshapiro return retkey; 14572847Sgshapiro } 14672847Sgshapiro lock_rw_unlock(&k->entry.lock); 147117286Sgshapiro } 14875074Sgshapiro /* snip off first label to continue */ 14997200Sgshapiro if(dname_is_root(name)) 15072847Sgshapiro break; 15172847Sgshapiro dname_remove_label(&name, &namelen); 152117286Sgshapiro } 15375073Sgshapiro return NULL; 15497200Sgshapiro} 15575073Sgshapiro 15675073Sgshapirosize_t 15772847Sgshapirokey_cache_get_mem(struct key_cache* kcache) 15872847Sgshapiro{ 15972847Sgshapiro return sizeof(*kcache) + slabhash_get_mem(kcache->slab); 16072847Sgshapiro} 16172847Sgshapiro 16272847Sgshapirovoid key_cache_remove(struct key_cache* kcache, 16372847Sgshapiro uint8_t* name, size_t namelen, uint16_t key_class) 16472847Sgshapiro{ 165117286Sgshapiro struct key_entry_key lookfor; 16672847Sgshapiro lookfor.entry.key = &lookfor; 167117286Sgshapiro lookfor.name = name; 16880175Sgshapiro lookfor.namelen = namelen; 169117286Sgshapiro lookfor.key_class = key_class; 17072847Sgshapiro key_entry_hash(&lookfor); 17172847Sgshapiro slabhash_remove(kcache->slab, lookfor.entry.hash, &lookfor); 17272847Sgshapiro} 17372847Sgshapiro