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