packed_rrset.c revision 291767
1180740Sdes/* 2180740Sdes * util/data/packed_rrset.c - data storage for a set of resource records. 3226046Sdes * 4226046Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved. 5226046Sdes * 6180740Sdes * This software is open source. 7180740Sdes * 8180740Sdes * Redistribution and use in source and binary forms, with or without 9180740Sdes * modification, are permitted provided that the following conditions 10180740Sdes * are met: 11180740Sdes * 12180740Sdes * Redistributions of source code must retain the above copyright notice, 13180746Sdes * this list of conditions and the following disclaimer. 14180746Sdes * 15180746Sdes * Redistributions in binary form must reproduce the above copyright notice, 16180740Sdes * this list of conditions and the following disclaimer in the documentation 17180740Sdes * and/or other materials provided with the distribution. 18180740Sdes * 19240075Sdes * Neither the name of the NLNET LABS nor the names of its contributors may 20240075Sdes * be used to endorse or promote products derived from this software without 21240075Sdes * specific prior written permission. 22180740Sdes * 23180740Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24180740Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25180740Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26180740Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27180740Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28180740Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29180740Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30180740Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31180746Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32180746Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33180746Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34180740Sdes */ 35180740Sdes 36180740Sdes/** 37180740Sdes * \file 38180740Sdes * 39180740Sdes * This file contains the data storage for RRsets. 40180740Sdes */ 41180740Sdes 42180740Sdes#include "config.h" 43180740Sdes#include "util/data/packed_rrset.h" 44180740Sdes#include "util/data/dname.h" 45180740Sdes#include "util/storage/lookup3.h" 46180740Sdes#include "util/log.h" 47180750Sdes#include "util/alloc.h" 48180750Sdes#include "util/regional.h" 49180750Sdes#include "util/net_help.h" 50262566Sdes#include "sldns/rrdef.h" 51262566Sdes#include "sldns/sbuffer.h" 52262566Sdes#include "sldns/wire2str.h" 53262566Sdes 54180740Sdesvoid 55180740Sdesub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey, 56180740Sdes struct alloc_cache* alloc) 57180740Sdes{ 58180740Sdes if(!pkey) 59180740Sdes return; 60180740Sdes if(pkey->entry.data) 61180740Sdes free(pkey->entry.data); 62180740Sdes pkey->entry.data = NULL; 63180740Sdes if(pkey->rk.dname) 64180740Sdes free(pkey->rk.dname); 65180740Sdes pkey->rk.dname = NULL; 66180740Sdes pkey->id = 0; 67180740Sdes alloc_special_release(alloc, pkey); 68180740Sdes} 69180740Sdes 70180740Sdessize_t 71180740Sdesub_rrset_sizefunc(void* key, void* data) 72180740Sdes{ 73180740Sdes struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key; 74180740Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)data; 75180746Sdes size_t s = sizeof(struct ub_packed_rrset_key) + k->rk.dname_len; 76180746Sdes s += packed_rrset_sizeof(d) + lock_get_mem(&k->entry.lock); 77180746Sdes return s; 78180740Sdes} 79180740Sdes 80180740Sdessize_t 81262566Sdespacked_rrset_sizeof(struct packed_rrset_data* d) 82248619Sdes{ 83248619Sdes size_t s; 84197679Sdes if(d->rrsig_count > 0) { 85197679Sdes s = ((uint8_t*)d->rr_data[d->count+d->rrsig_count-1] - 86197679Sdes (uint8_t*)d) + d->rr_len[d->count+d->rrsig_count-1]; 87180740Sdes } else { 88180740Sdes log_assert(d->count > 0); 89180740Sdes s = ((uint8_t*)d->rr_data[d->count-1] - (uint8_t*)d) + 90180740Sdes d->rr_len[d->count-1]; 91180740Sdes } 92180740Sdes return s; 93180740Sdes} 94180740Sdes 95180740Sdesint 96180740Sdesub_rrset_compare(void* k1, void* k2) 97180740Sdes{ 98180740Sdes struct ub_packed_rrset_key* key1 = (struct ub_packed_rrset_key*)k1; 99180740Sdes struct ub_packed_rrset_key* key2 = (struct ub_packed_rrset_key*)k2; 100180740Sdes int c; 101180740Sdes if(key1 == key2) 102180740Sdes return 0; 103180740Sdes if(key1->rk.type != key2->rk.type) { 104180740Sdes if(key1->rk.type < key2->rk.type) 105180740Sdes return -1; 106180740Sdes return 1; 107180740Sdes } 108180740Sdes if(key1->rk.dname_len != key2->rk.dname_len) { 109180740Sdes if(key1->rk.dname_len < key2->rk.dname_len) 110180740Sdes return -1; 111180740Sdes return 1; 112180740Sdes } 113180740Sdes if((c=query_dname_compare(key1->rk.dname, key2->rk.dname)) != 0) 114180740Sdes return c; 115180740Sdes if(key1->rk.rrset_class != key2->rk.rrset_class) { 116180740Sdes if(key1->rk.rrset_class < key2->rk.rrset_class) 117180740Sdes return -1; 118180740Sdes return 1; 119180740Sdes } 120180740Sdes if(key1->rk.flags != key2->rk.flags) { 121180740Sdes if(key1->rk.flags < key2->rk.flags) 122180740Sdes return -1; 123180740Sdes return 1; 124180740Sdes } 125180740Sdes return 0; 126180740Sdes} 127180740Sdes 128180740Sdesvoid 129180740Sdesub_rrset_key_delete(void* key, void* userdata) 130180740Sdes{ 131180740Sdes struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key; 132180740Sdes struct alloc_cache* a = (struct alloc_cache*)userdata; 133180740Sdes k->id = 0; 134180740Sdes free(k->rk.dname); 135204917Sdes k->rk.dname = NULL; 136204917Sdes alloc_special_release(a, k); 137204917Sdes} 138221420Sdes 139221420Sdesvoid 140221420Sdesrrset_data_delete(void* data, void* ATTR_UNUSED(userdata)) 141197679Sdes{ 142180750Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)data; 143180750Sdes free(d); 144197679Sdes} 145197679Sdes 146197679Sdesint 147180740Sdesrrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2) 148180740Sdes{ 149180740Sdes size_t i; 150180740Sdes size_t total; 151180740Sdes if(d1->count != d2->count || d1->rrsig_count != d2->rrsig_count) 152180740Sdes return 0; 153180740Sdes total = d1->count + d1->rrsig_count; 154180740Sdes for(i=0; i<total; i++) { 155180740Sdes if(d1->rr_len[i] != d2->rr_len[i]) 156180740Sdes return 0; 157180740Sdes if(memcmp(d1->rr_data[i], d2->rr_data[i], d1->rr_len[i]) != 0) 158180740Sdes return 0; 159221420Sdes } 160221420Sdes return 1; 161221420Sdes} 162180740Sdes 163180740Sdeshashvalue_t 164180740Sdesrrset_key_hash(struct packed_rrset_key* key) 165180740Sdes{ 166180740Sdes /* type is hashed in host order */ 167180740Sdes uint16_t t = ntohs(key->type); 168180740Sdes /* Note this MUST be identical to pkt_hash_rrset in msgparse.c */ 169180740Sdes /* this routine does not have a compressed name */ 170180740Sdes hashvalue_t h = 0xab; 171180740Sdes h = dname_query_hash(key->dname, h); 172180740Sdes h = hashlittle(&t, sizeof(t), h); 173180740Sdes h = hashlittle(&key->rrset_class, sizeof(uint16_t), h); 174180740Sdes h = hashlittle(&key->flags, sizeof(uint32_t), h); 175180740Sdes return h; 176180740Sdes} 177180740Sdes 178180740Sdesvoid 179180740Sdespacked_rrset_ptr_fixup(struct packed_rrset_data* data) 180180740Sdes{ 181180740Sdes size_t i; 182180740Sdes size_t total = data->count + data->rrsig_count; 183180740Sdes uint8_t* nextrdata; 184180740Sdes /* fixup pointers in packed rrset data */ 185180740Sdes data->rr_len = (size_t*)((uint8_t*)data + 186180750Sdes sizeof(struct packed_rrset_data)); 187180750Sdes data->rr_data = (uint8_t**)&(data->rr_len[total]); 188180750Sdes data->rr_ttl = (time_t*)&(data->rr_data[total]); 189262566Sdes nextrdata = (uint8_t*)&(data->rr_ttl[total]); 190262566Sdes for(i=0; i<total; i++) { 191262566Sdes data->rr_data[i] = nextrdata; 192180750Sdes nextrdata += data->rr_len[i]; 193180750Sdes } 194180750Sdes} 195180740Sdes 196180740Sdesvoid 197180740Sdesget_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname, 198180740Sdes size_t* dname_len) 199180740Sdes{ 200180740Sdes struct packed_rrset_data* d; 201180744Sdes size_t len; 202180744Sdes if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_CNAME && 203180744Sdes ntohs(rrset->rk.type) != LDNS_RR_TYPE_DNAME) 204180740Sdes return; 205180740Sdes d = (struct packed_rrset_data*)rrset->entry.data; 206180740Sdes if(d->count < 1) 207180746Sdes return; 208180746Sdes if(d->rr_len[0] < 3) /* at least rdatalen + 0byte root label */ 209180746Sdes return; 210180740Sdes len = sldns_read_uint16(d->rr_data[0]); 211180740Sdes if(len != d->rr_len[0] - sizeof(uint16_t)) 212180740Sdes return; 213180740Sdes if(dname_valid(d->rr_data[0]+sizeof(uint16_t), len) != len) 214180740Sdes return; 215180740Sdes *dname = d->rr_data[0]+sizeof(uint16_t); 216180740Sdes *dname_len = len; 217180740Sdes} 218180740Sdes 219180740Sdesvoid 220180740Sdespacked_rrset_ttl_add(struct packed_rrset_data* data, time_t add) 221180740Sdes{ 222262566Sdes size_t i; 223262566Sdes size_t total = data->count + data->rrsig_count; 224262566Sdes data->ttl += add; 225180740Sdes for(i=0; i<total; i++) 226180740Sdes data->rr_ttl[i] += add; 227180740Sdes} 228262566Sdes 229262566Sdesconst char* 230262566Sdesrrset_trust_to_string(enum rrset_trust s) 231262566Sdes{ 232262566Sdes switch(s) { 233262566Sdes case rrset_trust_none: return "rrset_trust_none"; 234262566Sdes case rrset_trust_add_noAA: return "rrset_trust_add_noAA"; 235262566Sdes case rrset_trust_auth_noAA: return "rrset_trust_auth_noAA"; 236262566Sdes case rrset_trust_add_AA: return "rrset_trust_add_AA"; 237262566Sdes case rrset_trust_nonauth_ans_AA:return "rrset_trust_nonauth_ans_AA"; 238262566Sdes case rrset_trust_ans_noAA: return "rrset_trust_ans_noAA"; 239262566Sdes case rrset_trust_glue: return "rrset_trust_glue"; 240262566Sdes case rrset_trust_auth_AA: return "rrset_trust_auth_AA"; 241262566Sdes case rrset_trust_ans_AA: return "rrset_trust_ans_AA"; 242262566Sdes case rrset_trust_sec_noglue: return "rrset_trust_sec_noglue"; 243262566Sdes case rrset_trust_prim_noglue: return "rrset_trust_prim_noglue"; 244262566Sdes case rrset_trust_validated: return "rrset_trust_validated"; 245262566Sdes case rrset_trust_ultimate: return "rrset_trust_ultimate"; 246221420Sdes } 247221420Sdes return "unknown_rrset_trust_value"; 248221420Sdes} 249248619Sdes 250248619Sdesconst char* 251248619Sdessec_status_to_string(enum sec_status s) 252180740Sdes{ 253180740Sdes switch(s) { 254180740Sdes case sec_status_unchecked: return "sec_status_unchecked"; 255180740Sdes case sec_status_bogus: return "sec_status_bogus"; 256180740Sdes case sec_status_indeterminate: return "sec_status_indeterminate"; 257180740Sdes case sec_status_insecure: return "sec_status_insecure"; 258262566Sdes case sec_status_secure: return "sec_status_secure"; 259262566Sdes } 260262566Sdes return "unknown_sec_status_value"; 261180740Sdes} 262180740Sdes 263180740Sdesvoid log_rrset_key(enum verbosity_value v, const char* str, 264255767Sdes struct ub_packed_rrset_key* rrset) 265255767Sdes{ 266255767Sdes if(verbosity >= v) 267180740Sdes log_nametypeclass(v, str, rrset->rk.dname, 268180740Sdes ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class)); 269180740Sdes} 270180740Sdes 271180740Sdesint packed_rr_to_string(struct ub_packed_rrset_key* rrset, size_t i, 272180740Sdes time_t now, char* dest, size_t dest_len) 273180740Sdes{ 274180740Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> 275180740Sdes entry.data; 276180740Sdes uint8_t rr[65535]; 277180740Sdes size_t rlen = rrset->rk.dname_len + 2 + 2 + 4 + d->rr_len[i]; 278180740Sdes log_assert(dest_len > 0 && dest); 279255767Sdes if(rlen > dest_len) { 280255767Sdes dest[0] = 0; 281255767Sdes return 0; 282180740Sdes } 283180740Sdes memmove(rr, rrset->rk.dname, rrset->rk.dname_len); 284180740Sdes if(i < d->count) 285180740Sdes memmove(rr+rrset->rk.dname_len, &rrset->rk.type, 2); 286180740Sdes else sldns_write_uint16(rr+rrset->rk.dname_len, LDNS_RR_TYPE_RRSIG); 287180740Sdes memmove(rr+rrset->rk.dname_len+2, &rrset->rk.rrset_class, 2); 288180740Sdes sldns_write_uint32(rr+rrset->rk.dname_len+4, 289180740Sdes (uint32_t)(d->rr_ttl[i]-now)); 290180740Sdes memmove(rr+rrset->rk.dname_len+8, d->rr_data[i], d->rr_len[i]); 291180740Sdes if(sldns_wire2str_rr_buf(rr, rlen, dest, dest_len) == -1) { 292180740Sdes log_info("rrbuf failure %d %s", (int)d->rr_len[i], dest); 293180740Sdes dest[0] = 0; 294180740Sdes return 0; 295180740Sdes } 296180740Sdes return 1; 297180740Sdes} 298180740Sdes 299180740Sdesvoid log_packed_rrset(enum verbosity_value v, const char* str, 300180740Sdes struct ub_packed_rrset_key* rrset) 301180740Sdes{ 302248619Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> 303248619Sdes entry.data; 304248619Sdes char buf[65535]; 305248619Sdes size_t i; 306255767Sdes if(verbosity < v) 307255767Sdes return; 308255767Sdes for(i=0; i<d->count+d->rrsig_count; i++) { 309255767Sdes if(!packed_rr_to_string(rrset, i, 0, buf, sizeof(buf))) { 310180740Sdes log_info("%s: rr %d wire2str-error", str, (int)i); 311180740Sdes } else { 312180740Sdes log_info("%s: %s", str, buf); 313180740Sdes } 314180740Sdes } 315180740Sdes} 316180740Sdes 317180740Sdestime_t 318180740Sdesub_packed_rrset_ttl(struct ub_packed_rrset_key* key) 319180740Sdes{ 320180740Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)key-> 321180740Sdes entry.data; 322180740Sdes return d->ttl; 323180740Sdes} 324180740Sdes 325180740Sdesstruct ub_packed_rrset_key* 326180744Sdespacked_rrset_copy_region(struct ub_packed_rrset_key* key, 327180744Sdes struct regional* region, time_t now) 328180744Sdes{ 329180744Sdes struct ub_packed_rrset_key* ck = regional_alloc(region, 330255767Sdes sizeof(struct ub_packed_rrset_key)); 331255767Sdes struct packed_rrset_data* d; 332255767Sdes struct packed_rrset_data* data = (struct packed_rrset_data*) 333255767Sdes key->entry.data; 334180744Sdes size_t dsize, i; 335180744Sdes if(!ck) 336180744Sdes return NULL; 337180744Sdes ck->id = key->id; 338180740Sdes memset(&ck->entry, 0, sizeof(ck->entry)); 339180740Sdes ck->entry.hash = key->entry.hash; 340180740Sdes ck->entry.key = ck; 341180740Sdes ck->rk = key->rk; 342180740Sdes ck->rk.dname = regional_alloc_init(region, key->rk.dname, 343180740Sdes key->rk.dname_len); 344180740Sdes if(!ck->rk.dname) 345180740Sdes return NULL; 346180740Sdes dsize = packed_rrset_sizeof(data); 347180740Sdes d = (struct packed_rrset_data*)regional_alloc_init(region, data, dsize); 348180740Sdes if(!d) 349180740Sdes return NULL; 350180740Sdes ck->entry.data = d; 351180740Sdes packed_rrset_ptr_fixup(d); 352180740Sdes /* make TTLs relative - once per rrset */ 353180740Sdes for(i=0; i<d->count + d->rrsig_count; i++) { 354180740Sdes if(d->rr_ttl[i] < now) 355180740Sdes d->rr_ttl[i] = 0; 356180740Sdes else d->rr_ttl[i] -= now; 357180740Sdes } 358180740Sdes if(d->ttl < now) 359180740Sdes d->ttl = 0; 360180740Sdes else d->ttl -= now; 361180740Sdes return ck; 362180740Sdes} 363180740Sdes 364180740Sdesstruct ub_packed_rrset_key* 365180740Sdespacked_rrset_copy_alloc(struct ub_packed_rrset_key* key, 366255767Sdes struct alloc_cache* alloc, time_t now) 367255767Sdes{ 368255767Sdes struct packed_rrset_data* fd, *dd; 369180740Sdes struct ub_packed_rrset_key* dk = alloc_special_obtain(alloc); 370180740Sdes if(!dk) return NULL; 371180740Sdes fd = (struct packed_rrset_data*)key->entry.data; 372180740Sdes dk->entry.hash = key->entry.hash; 373180740Sdes dk->rk = key->rk; 374180740Sdes dk->rk.dname = (uint8_t*)memdup(key->rk.dname, key->rk.dname_len); 375180740Sdes if(!dk->rk.dname) { 376180740Sdes alloc_special_release(alloc, dk); 377180740Sdes return NULL; 378180740Sdes } 379180740Sdes dd = (struct packed_rrset_data*)memdup(fd, packed_rrset_sizeof(fd)); 380180740Sdes if(!dd) { 381180740Sdes free(dk->rk.dname); 382180740Sdes alloc_special_release(alloc, dk); 383180740Sdes return NULL; 384221420Sdes } 385221420Sdes packed_rrset_ptr_fixup(dd); 386221420Sdes dk->entry.data = (void*)dd; 387248619Sdes packed_rrset_ttl_add(dd, now); 388248619Sdes return dk; 389248619Sdes} 390255767Sdes