unbound/validator/val_kentry.c
Wouter Wijngaards cedeaa8316 ds2ke and nsec work.
git-svn-id: file:///svn/unbound/trunk@529 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-17 11:41:49 +00:00

305 lines
8.1 KiB
C

/*
* validator/val_kentry.c - validator key entry definition.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions for dealing with validator key entries.
*/
#include "config.h"
#include "validator/val_kentry.h"
#include "util/data/packed_rrset.h"
#include "util/data/dname.h"
#include "util/storage/lookup3.h"
#include "util/region-allocator.h"
#include "util/net_help.h"
size_t
key_entry_sizefunc(void* key, void* data)
{
struct key_entry_key* kk = (struct key_entry_key*)key;
struct key_entry_data* kd = (struct key_entry_data*)data;
size_t s = sizeof(*kk) + kk->namelen;
s += sizeof(*kd) + lock_get_mem(&kk->entry.lock);
if(kd->rrset_data)
s += packed_rrset_sizeof(kd->rrset_data);
return s;
}
int
key_entry_compfunc(void* k1, void* k2)
{
struct key_entry_key* n1 = (struct key_entry_key*)k1;
struct key_entry_key* n2 = (struct key_entry_key*)k2;
if(n1->key_class != n2->key_class) {
if(n1->key_class < n2->key_class)
return -1;
return 1;
}
return query_dname_compare(n1->name, n2->name);
}
void
key_entry_delkeyfunc(void* key, void* ATTR_UNUSED(userarg), int islocked)
{
struct key_entry_key* kk = (struct key_entry_key*)key;
if(!key)
return;
if(islocked) {
lock_rw_unlock(&kk->entry.lock);
}
free(kk->name);
free(kk);
}
void
key_entry_deldatafunc(void* data, void* ATTR_UNUSED(userarg))
{
struct key_entry_data* kd = (struct key_entry_data*)data;
free(kd->rrset_data);
free(kd);
}
void
key_entry_hash(struct key_entry_key* kk)
{
kk->entry.hash = 0x654;
kk->entry.hash = hashlittle(&kk->key_class, sizeof(kk->key_class),
kk->entry.hash);
kk->entry.hash = dname_query_hash(kk->name, kk->entry.hash);
}
struct key_entry_key*
key_entry_copy_toregion(struct key_entry_key* kkey, struct region* region)
{
struct key_entry_key* newk;
newk = region_alloc_init(region, kkey, sizeof(*kkey));
if(!newk)
return NULL;
newk->name = region_alloc_init(region, kkey->name, kkey->namelen);
if(!newk->name)
return NULL;
newk->entry.key = newk;
if(newk->entry.data) {
/* copy data element */
struct key_entry_data *d = (struct key_entry_data*)
kkey->entry.data;
struct key_entry_data *newd;
newd = region_alloc_init(region, d, sizeof(*d));
if(!newd)
return NULL;
/* copy rrset */
if(d->rrset_data) {
newd->rrset_data = region_alloc_init(region,
d->rrset_data,
packed_rrset_sizeof(d->rrset_data));
if(!newd->rrset_data)
return NULL;
packed_rrset_ptr_fixup(newd->rrset_data);
}
newk->entry.data = newd;
}
return newk;
}
struct key_entry_key*
key_entry_copy(struct key_entry_key* kkey)
{
struct key_entry_key* newk;
if(!kkey)
return NULL;
newk = memdup(kkey, sizeof(*kkey));
if(!newk)
return NULL;
newk->name = memdup(kkey->name, kkey->namelen);
if(!newk->name) {
free(newk);
return NULL;
}
lock_rw_init(&newk->entry.lock);
newk->entry.key = newk;
if(newk->entry.data) {
/* copy data element */
struct key_entry_data *d = (struct key_entry_data*)
kkey->entry.data;
struct key_entry_data *newd;
newd = memdup(d, sizeof(*d));
if(!newd) {
free(newk->name);
free(newk);
return NULL;
}
/* copy rrset */
if(d->rrset_data) {
newd->rrset_data = memdup(d->rrset_data,
packed_rrset_sizeof(d->rrset_data));
if(!newd->rrset_data) {
free(newd);
free(newk->name);
free(newk);
return NULL;
}
packed_rrset_ptr_fixup(newd->rrset_data);
}
newk->entry.data = newd;
}
return newk;
}
int
key_entry_isnull(struct key_entry_key* kkey)
{
struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
return (!d->isbad && d->rrset_data == NULL);
}
int
key_entry_isgood(struct key_entry_key* kkey)
{
struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
return (!d->isbad && d->rrset_data != NULL);
}
int
key_entry_isbad(struct key_entry_key* kkey)
{
struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
return (int)(d->isbad);
}
/** setup key entry in region */
static int
key_entry_setup(struct region* region,
uint8_t* name, size_t namelen, uint16_t dclass,
struct key_entry_key** k, struct key_entry_data** d)
{
*k = region_alloc(region, sizeof(**k));
if(!*k)
return 0;
memset(*k, 0, sizeof(**k));
(*k)->entry.key = *k;
(*k)->name = region_alloc_init(region, name, namelen);
if(!(*k)->name)
return 0;
(*k)->namelen = namelen;
(*k)->key_class = dclass;
*d = region_alloc(region, sizeof(**d));
if(!*d)
return 0;
(*k)->entry.data = *d;
return 1;
}
struct key_entry_key*
key_entry_create_null(struct region* region,
uint8_t* name, size_t namelen, uint16_t dclass, uint32_t ttl)
{
struct key_entry_key* k;
struct key_entry_data* d;
if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
return NULL;
d->ttl = time(0) + ttl;
d->isbad = 0;
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
d->rrset_data = NULL;
return k;
}
struct key_entry_key*
key_entry_create_rrset(struct region* region,
uint8_t* name, size_t namelen, uint16_t dclass,
struct ub_packed_rrset_key* rrset)
{
struct key_entry_key* k;
struct key_entry_data* d;
struct packed_rrset_data* rd = (struct packed_rrset_data*)
rrset->entry.data;
if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
return NULL;
log_info("New key entry TTL is now+%d", (int)rd->ttl);
d->ttl = rd->ttl + time(NULL);
d->isbad = 0;
d->rrset_type = ntohs(rrset->rk.type);
d->rrset_data = (struct packed_rrset_data*)region_alloc_init(region,
rd, packed_rrset_sizeof(rd));
if(!d->rrset_data)
return NULL;
packed_rrset_ptr_fixup(d->rrset_data);
return k;
}
struct key_entry_key*
key_entry_create_bad(struct region* region,
uint8_t* name, size_t namelen, uint16_t dclass)
{
struct key_entry_key* k;
struct key_entry_data* d;
if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
return NULL;
d->ttl = 0;
d->isbad = 1;
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
d->rrset_data = NULL;
return k;
}
struct ub_packed_rrset_key*
key_entry_get_rrset(struct key_entry_key* kkey, struct region* region)
{
struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
struct ub_packed_rrset_key* rrk;
struct packed_rrset_data* rrd;
if(!d || !d->rrset_data)
return NULL;
rrk = region_alloc(region, sizeof(*rrk));
if(!rrk)
return NULL;
memset(rrk, 0, sizeof(*rrk));
rrk->rk.dname = region_alloc_init(region, kkey->name, kkey->namelen);
if(!rrk->rk.dname)
return NULL;
rrk->rk.dname_len = kkey->namelen;
rrk->rk.type = htons(d->rrset_type);
rrk->rk.rrset_class = htons(kkey->key_class);
rrk->entry.key = rrk;
rrd = region_alloc_init(region, d->rrset_data,
packed_rrset_sizeof(d->rrset_data));
if(!rrd)
return NULL;
rrk->entry.data = rrd;
packed_rrset_ptr_fixup(rrd);
return rrk;
}