1238106Sdes/* 2238106Sdes * util/data/packed_rrset.c - data storage for a set of resource records. 3238106Sdes * 4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved. 5238106Sdes * 6238106Sdes * This software is open source. 7238106Sdes * 8238106Sdes * Redistribution and use in source and binary forms, with or without 9238106Sdes * modification, are permitted provided that the following conditions 10238106Sdes * are met: 11238106Sdes * 12238106Sdes * Redistributions of source code must retain the above copyright notice, 13238106Sdes * this list of conditions and the following disclaimer. 14238106Sdes * 15238106Sdes * Redistributions in binary form must reproduce the above copyright notice, 16238106Sdes * this list of conditions and the following disclaimer in the documentation 17238106Sdes * and/or other materials provided with the distribution. 18238106Sdes * 19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may 20238106Sdes * be used to endorse or promote products derived from this software without 21238106Sdes * specific prior written permission. 22238106Sdes * 23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24266114Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25266114Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26266114Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27266114Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28266114Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29266114Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30266114Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31266114Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32266114Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33266114Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34238106Sdes */ 35238106Sdes 36238106Sdes/** 37238106Sdes * \file 38238106Sdes * 39238106Sdes * This file contains the data storage for RRsets. 40238106Sdes */ 41238106Sdes 42238106Sdes#include "config.h" 43238106Sdes#include "util/data/packed_rrset.h" 44238106Sdes#include "util/data/dname.h" 45238106Sdes#include "util/storage/lookup3.h" 46238106Sdes#include "util/log.h" 47238106Sdes#include "util/alloc.h" 48238106Sdes#include "util/regional.h" 49238106Sdes#include "util/net_help.h" 50287917Sdes#include "sldns/rrdef.h" 51287917Sdes#include "sldns/sbuffer.h" 52287917Sdes#include "sldns/wire2str.h" 53238106Sdes 54238106Sdesvoid 55238106Sdesub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey, 56238106Sdes struct alloc_cache* alloc) 57238106Sdes{ 58238106Sdes if(!pkey) 59238106Sdes return; 60296415Sdes free(pkey->entry.data); 61238106Sdes pkey->entry.data = NULL; 62296415Sdes free(pkey->rk.dname); 63238106Sdes pkey->rk.dname = NULL; 64238106Sdes pkey->id = 0; 65238106Sdes alloc_special_release(alloc, pkey); 66238106Sdes} 67238106Sdes 68238106Sdessize_t 69238106Sdesub_rrset_sizefunc(void* key, void* data) 70238106Sdes{ 71238106Sdes struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key; 72238106Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)data; 73238106Sdes size_t s = sizeof(struct ub_packed_rrset_key) + k->rk.dname_len; 74238106Sdes s += packed_rrset_sizeof(d) + lock_get_mem(&k->entry.lock); 75238106Sdes return s; 76238106Sdes} 77238106Sdes 78238106Sdessize_t 79238106Sdespacked_rrset_sizeof(struct packed_rrset_data* d) 80238106Sdes{ 81238106Sdes size_t s; 82238106Sdes if(d->rrsig_count > 0) { 83238106Sdes s = ((uint8_t*)d->rr_data[d->count+d->rrsig_count-1] - 84238106Sdes (uint8_t*)d) + d->rr_len[d->count+d->rrsig_count-1]; 85238106Sdes } else { 86238106Sdes log_assert(d->count > 0); 87238106Sdes s = ((uint8_t*)d->rr_data[d->count-1] - (uint8_t*)d) + 88238106Sdes d->rr_len[d->count-1]; 89238106Sdes } 90238106Sdes return s; 91238106Sdes} 92238106Sdes 93238106Sdesint 94238106Sdesub_rrset_compare(void* k1, void* k2) 95238106Sdes{ 96238106Sdes struct ub_packed_rrset_key* key1 = (struct ub_packed_rrset_key*)k1; 97238106Sdes struct ub_packed_rrset_key* key2 = (struct ub_packed_rrset_key*)k2; 98238106Sdes int c; 99238106Sdes if(key1 == key2) 100238106Sdes return 0; 101238106Sdes if(key1->rk.type != key2->rk.type) { 102238106Sdes if(key1->rk.type < key2->rk.type) 103238106Sdes return -1; 104238106Sdes return 1; 105238106Sdes } 106238106Sdes if(key1->rk.dname_len != key2->rk.dname_len) { 107238106Sdes if(key1->rk.dname_len < key2->rk.dname_len) 108238106Sdes return -1; 109238106Sdes return 1; 110238106Sdes } 111238106Sdes if((c=query_dname_compare(key1->rk.dname, key2->rk.dname)) != 0) 112238106Sdes return c; 113238106Sdes if(key1->rk.rrset_class != key2->rk.rrset_class) { 114238106Sdes if(key1->rk.rrset_class < key2->rk.rrset_class) 115238106Sdes return -1; 116238106Sdes return 1; 117238106Sdes } 118238106Sdes if(key1->rk.flags != key2->rk.flags) { 119238106Sdes if(key1->rk.flags < key2->rk.flags) 120238106Sdes return -1; 121238106Sdes return 1; 122238106Sdes } 123238106Sdes return 0; 124238106Sdes} 125238106Sdes 126238106Sdesvoid 127238106Sdesub_rrset_key_delete(void* key, void* userdata) 128238106Sdes{ 129238106Sdes struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key; 130238106Sdes struct alloc_cache* a = (struct alloc_cache*)userdata; 131238106Sdes k->id = 0; 132238106Sdes free(k->rk.dname); 133238106Sdes k->rk.dname = NULL; 134238106Sdes alloc_special_release(a, k); 135238106Sdes} 136238106Sdes 137238106Sdesvoid 138238106Sdesrrset_data_delete(void* data, void* ATTR_UNUSED(userdata)) 139238106Sdes{ 140238106Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)data; 141238106Sdes free(d); 142238106Sdes} 143238106Sdes 144238106Sdesint 145238106Sdesrrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2) 146238106Sdes{ 147238106Sdes size_t i; 148238106Sdes size_t total; 149238106Sdes if(d1->count != d2->count || d1->rrsig_count != d2->rrsig_count) 150238106Sdes return 0; 151238106Sdes total = d1->count + d1->rrsig_count; 152238106Sdes for(i=0; i<total; i++) { 153238106Sdes if(d1->rr_len[i] != d2->rr_len[i]) 154238106Sdes return 0; 155238106Sdes if(memcmp(d1->rr_data[i], d2->rr_data[i], d1->rr_len[i]) != 0) 156238106Sdes return 0; 157238106Sdes } 158238106Sdes return 1; 159238106Sdes} 160238106Sdes 161238106Sdeshashvalue_t 162238106Sdesrrset_key_hash(struct packed_rrset_key* key) 163238106Sdes{ 164238106Sdes /* type is hashed in host order */ 165238106Sdes uint16_t t = ntohs(key->type); 166238106Sdes /* Note this MUST be identical to pkt_hash_rrset in msgparse.c */ 167238106Sdes /* this routine does not have a compressed name */ 168238106Sdes hashvalue_t h = 0xab; 169238106Sdes h = dname_query_hash(key->dname, h); 170238106Sdes h = hashlittle(&t, sizeof(t), h); 171238106Sdes h = hashlittle(&key->rrset_class, sizeof(uint16_t), h); 172238106Sdes h = hashlittle(&key->flags, sizeof(uint32_t), h); 173238106Sdes return h; 174238106Sdes} 175238106Sdes 176238106Sdesvoid 177238106Sdespacked_rrset_ptr_fixup(struct packed_rrset_data* data) 178238106Sdes{ 179238106Sdes size_t i; 180238106Sdes size_t total = data->count + data->rrsig_count; 181238106Sdes uint8_t* nextrdata; 182238106Sdes /* fixup pointers in packed rrset data */ 183238106Sdes data->rr_len = (size_t*)((uint8_t*)data + 184238106Sdes sizeof(struct packed_rrset_data)); 185238106Sdes data->rr_data = (uint8_t**)&(data->rr_len[total]); 186266114Sdes data->rr_ttl = (time_t*)&(data->rr_data[total]); 187238106Sdes nextrdata = (uint8_t*)&(data->rr_ttl[total]); 188238106Sdes for(i=0; i<total; i++) { 189238106Sdes data->rr_data[i] = nextrdata; 190238106Sdes nextrdata += data->rr_len[i]; 191238106Sdes } 192238106Sdes} 193238106Sdes 194238106Sdesvoid 195238106Sdesget_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname, 196238106Sdes size_t* dname_len) 197238106Sdes{ 198238106Sdes struct packed_rrset_data* d; 199238106Sdes size_t len; 200238106Sdes if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_CNAME && 201238106Sdes ntohs(rrset->rk.type) != LDNS_RR_TYPE_DNAME) 202238106Sdes return; 203238106Sdes d = (struct packed_rrset_data*)rrset->entry.data; 204238106Sdes if(d->count < 1) 205238106Sdes return; 206238106Sdes if(d->rr_len[0] < 3) /* at least rdatalen + 0byte root label */ 207238106Sdes return; 208266114Sdes len = sldns_read_uint16(d->rr_data[0]); 209238106Sdes if(len != d->rr_len[0] - sizeof(uint16_t)) 210238106Sdes return; 211238106Sdes if(dname_valid(d->rr_data[0]+sizeof(uint16_t), len) != len) 212238106Sdes return; 213238106Sdes *dname = d->rr_data[0]+sizeof(uint16_t); 214238106Sdes *dname_len = len; 215238106Sdes} 216238106Sdes 217238106Sdesvoid 218266114Sdespacked_rrset_ttl_add(struct packed_rrset_data* data, time_t add) 219238106Sdes{ 220238106Sdes size_t i; 221238106Sdes size_t total = data->count + data->rrsig_count; 222238106Sdes data->ttl += add; 223238106Sdes for(i=0; i<total; i++) 224238106Sdes data->rr_ttl[i] += add; 225238106Sdes} 226238106Sdes 227238106Sdesconst char* 228238106Sdesrrset_trust_to_string(enum rrset_trust s) 229238106Sdes{ 230238106Sdes switch(s) { 231238106Sdes case rrset_trust_none: return "rrset_trust_none"; 232238106Sdes case rrset_trust_add_noAA: return "rrset_trust_add_noAA"; 233238106Sdes case rrset_trust_auth_noAA: return "rrset_trust_auth_noAA"; 234238106Sdes case rrset_trust_add_AA: return "rrset_trust_add_AA"; 235238106Sdes case rrset_trust_nonauth_ans_AA:return "rrset_trust_nonauth_ans_AA"; 236238106Sdes case rrset_trust_ans_noAA: return "rrset_trust_ans_noAA"; 237238106Sdes case rrset_trust_glue: return "rrset_trust_glue"; 238238106Sdes case rrset_trust_auth_AA: return "rrset_trust_auth_AA"; 239238106Sdes case rrset_trust_ans_AA: return "rrset_trust_ans_AA"; 240238106Sdes case rrset_trust_sec_noglue: return "rrset_trust_sec_noglue"; 241238106Sdes case rrset_trust_prim_noglue: return "rrset_trust_prim_noglue"; 242238106Sdes case rrset_trust_validated: return "rrset_trust_validated"; 243238106Sdes case rrset_trust_ultimate: return "rrset_trust_ultimate"; 244238106Sdes } 245238106Sdes return "unknown_rrset_trust_value"; 246238106Sdes} 247238106Sdes 248238106Sdesconst char* 249238106Sdessec_status_to_string(enum sec_status s) 250238106Sdes{ 251238106Sdes switch(s) { 252238106Sdes case sec_status_unchecked: return "sec_status_unchecked"; 253238106Sdes case sec_status_bogus: return "sec_status_bogus"; 254238106Sdes case sec_status_indeterminate: return "sec_status_indeterminate"; 255238106Sdes case sec_status_insecure: return "sec_status_insecure"; 256238106Sdes case sec_status_secure: return "sec_status_secure"; 257238106Sdes } 258238106Sdes return "unknown_sec_status_value"; 259238106Sdes} 260238106Sdes 261238106Sdesvoid log_rrset_key(enum verbosity_value v, const char* str, 262238106Sdes struct ub_packed_rrset_key* rrset) 263238106Sdes{ 264238106Sdes if(verbosity >= v) 265238106Sdes log_nametypeclass(v, str, rrset->rk.dname, 266238106Sdes ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class)); 267238106Sdes} 268238106Sdes 269266114Sdesint packed_rr_to_string(struct ub_packed_rrset_key* rrset, size_t i, 270266114Sdes time_t now, char* dest, size_t dest_len) 271266114Sdes{ 272266114Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> 273266114Sdes entry.data; 274266114Sdes uint8_t rr[65535]; 275266114Sdes size_t rlen = rrset->rk.dname_len + 2 + 2 + 4 + d->rr_len[i]; 276266114Sdes log_assert(dest_len > 0 && dest); 277266114Sdes if(rlen > dest_len) { 278266114Sdes dest[0] = 0; 279266114Sdes return 0; 280266114Sdes } 281266114Sdes memmove(rr, rrset->rk.dname, rrset->rk.dname_len); 282266114Sdes if(i < d->count) 283266114Sdes memmove(rr+rrset->rk.dname_len, &rrset->rk.type, 2); 284266114Sdes else sldns_write_uint16(rr+rrset->rk.dname_len, LDNS_RR_TYPE_RRSIG); 285266114Sdes memmove(rr+rrset->rk.dname_len+2, &rrset->rk.rrset_class, 2); 286266114Sdes sldns_write_uint32(rr+rrset->rk.dname_len+4, 287266114Sdes (uint32_t)(d->rr_ttl[i]-now)); 288266114Sdes memmove(rr+rrset->rk.dname_len+8, d->rr_data[i], d->rr_len[i]); 289266114Sdes if(sldns_wire2str_rr_buf(rr, rlen, dest, dest_len) == -1) { 290266114Sdes log_info("rrbuf failure %d %s", (int)d->rr_len[i], dest); 291266114Sdes dest[0] = 0; 292266114Sdes return 0; 293266114Sdes } 294266114Sdes return 1; 295266114Sdes} 296266114Sdes 297266114Sdesvoid log_packed_rrset(enum verbosity_value v, const char* str, 298266114Sdes struct ub_packed_rrset_key* rrset) 299266114Sdes{ 300266114Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> 301266114Sdes entry.data; 302266114Sdes char buf[65535]; 303266114Sdes size_t i; 304266114Sdes if(verbosity < v) 305266114Sdes return; 306266114Sdes for(i=0; i<d->count+d->rrsig_count; i++) { 307266114Sdes if(!packed_rr_to_string(rrset, i, 0, buf, sizeof(buf))) { 308266114Sdes log_info("%s: rr %d wire2str-error", str, (int)i); 309266114Sdes } else { 310266114Sdes log_info("%s: %s", str, buf); 311266114Sdes } 312266114Sdes } 313266114Sdes} 314266114Sdes 315266114Sdestime_t 316238106Sdesub_packed_rrset_ttl(struct ub_packed_rrset_key* key) 317238106Sdes{ 318238106Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)key-> 319238106Sdes entry.data; 320238106Sdes return d->ttl; 321238106Sdes} 322238106Sdes 323238106Sdesstruct ub_packed_rrset_key* 324238106Sdespacked_rrset_copy_region(struct ub_packed_rrset_key* key, 325266114Sdes struct regional* region, time_t now) 326238106Sdes{ 327238106Sdes struct ub_packed_rrset_key* ck = regional_alloc(region, 328238106Sdes sizeof(struct ub_packed_rrset_key)); 329238106Sdes struct packed_rrset_data* d; 330238106Sdes struct packed_rrset_data* data = (struct packed_rrset_data*) 331238106Sdes key->entry.data; 332238106Sdes size_t dsize, i; 333238106Sdes if(!ck) 334238106Sdes return NULL; 335238106Sdes ck->id = key->id; 336238106Sdes memset(&ck->entry, 0, sizeof(ck->entry)); 337238106Sdes ck->entry.hash = key->entry.hash; 338238106Sdes ck->entry.key = ck; 339238106Sdes ck->rk = key->rk; 340238106Sdes ck->rk.dname = regional_alloc_init(region, key->rk.dname, 341238106Sdes key->rk.dname_len); 342238106Sdes if(!ck->rk.dname) 343238106Sdes return NULL; 344238106Sdes dsize = packed_rrset_sizeof(data); 345238106Sdes d = (struct packed_rrset_data*)regional_alloc_init(region, data, dsize); 346238106Sdes if(!d) 347238106Sdes return NULL; 348238106Sdes ck->entry.data = d; 349238106Sdes packed_rrset_ptr_fixup(d); 350238106Sdes /* make TTLs relative - once per rrset */ 351238106Sdes for(i=0; i<d->count + d->rrsig_count; i++) { 352238106Sdes if(d->rr_ttl[i] < now) 353238106Sdes d->rr_ttl[i] = 0; 354238106Sdes else d->rr_ttl[i] -= now; 355238106Sdes } 356238106Sdes if(d->ttl < now) 357238106Sdes d->ttl = 0; 358238106Sdes else d->ttl -= now; 359238106Sdes return ck; 360238106Sdes} 361238106Sdes 362238106Sdesstruct ub_packed_rrset_key* 363238106Sdespacked_rrset_copy_alloc(struct ub_packed_rrset_key* key, 364266114Sdes struct alloc_cache* alloc, time_t now) 365238106Sdes{ 366238106Sdes struct packed_rrset_data* fd, *dd; 367238106Sdes struct ub_packed_rrset_key* dk = alloc_special_obtain(alloc); 368238106Sdes if(!dk) return NULL; 369238106Sdes fd = (struct packed_rrset_data*)key->entry.data; 370238106Sdes dk->entry.hash = key->entry.hash; 371238106Sdes dk->rk = key->rk; 372238106Sdes dk->rk.dname = (uint8_t*)memdup(key->rk.dname, key->rk.dname_len); 373238106Sdes if(!dk->rk.dname) { 374238106Sdes alloc_special_release(alloc, dk); 375238106Sdes return NULL; 376238106Sdes } 377238106Sdes dd = (struct packed_rrset_data*)memdup(fd, packed_rrset_sizeof(fd)); 378238106Sdes if(!dd) { 379238106Sdes free(dk->rk.dname); 380238106Sdes alloc_special_release(alloc, dk); 381238106Sdes return NULL; 382238106Sdes } 383238106Sdes packed_rrset_ptr_fixup(dd); 384238106Sdes dk->entry.data = (void*)dd; 385238106Sdes packed_rrset_ttl_add(dd, now); 386238106Sdes return dk; 387238106Sdes} 388