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 24269257Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25269257Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26269257Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27269257Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28269257Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29269257Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30269257Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31269257Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32269257Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33269257Sdes * 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" 50291767Sdes#include "sldns/rrdef.h" 51291767Sdes#include "sldns/sbuffer.h" 52291767Sdes#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; 60238106Sdes if(pkey->entry.data) 61238106Sdes free(pkey->entry.data); 62238106Sdes pkey->entry.data = NULL; 63238106Sdes if(pkey->rk.dname) 64238106Sdes free(pkey->rk.dname); 65238106Sdes pkey->rk.dname = NULL; 66238106Sdes pkey->id = 0; 67238106Sdes alloc_special_release(alloc, pkey); 68238106Sdes} 69238106Sdes 70238106Sdessize_t 71238106Sdesub_rrset_sizefunc(void* key, void* data) 72238106Sdes{ 73238106Sdes struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key; 74238106Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)data; 75238106Sdes size_t s = sizeof(struct ub_packed_rrset_key) + k->rk.dname_len; 76238106Sdes s += packed_rrset_sizeof(d) + lock_get_mem(&k->entry.lock); 77238106Sdes return s; 78238106Sdes} 79238106Sdes 80238106Sdessize_t 81238106Sdespacked_rrset_sizeof(struct packed_rrset_data* d) 82238106Sdes{ 83238106Sdes size_t s; 84238106Sdes if(d->rrsig_count > 0) { 85238106Sdes s = ((uint8_t*)d->rr_data[d->count+d->rrsig_count-1] - 86238106Sdes (uint8_t*)d) + d->rr_len[d->count+d->rrsig_count-1]; 87238106Sdes } else { 88238106Sdes log_assert(d->count > 0); 89238106Sdes s = ((uint8_t*)d->rr_data[d->count-1] - (uint8_t*)d) + 90238106Sdes d->rr_len[d->count-1]; 91238106Sdes } 92238106Sdes return s; 93238106Sdes} 94238106Sdes 95238106Sdesint 96238106Sdesub_rrset_compare(void* k1, void* k2) 97238106Sdes{ 98238106Sdes struct ub_packed_rrset_key* key1 = (struct ub_packed_rrset_key*)k1; 99238106Sdes struct ub_packed_rrset_key* key2 = (struct ub_packed_rrset_key*)k2; 100238106Sdes int c; 101238106Sdes if(key1 == key2) 102238106Sdes return 0; 103238106Sdes if(key1->rk.type != key2->rk.type) { 104238106Sdes if(key1->rk.type < key2->rk.type) 105238106Sdes return -1; 106238106Sdes return 1; 107238106Sdes } 108238106Sdes if(key1->rk.dname_len != key2->rk.dname_len) { 109238106Sdes if(key1->rk.dname_len < key2->rk.dname_len) 110238106Sdes return -1; 111238106Sdes return 1; 112238106Sdes } 113238106Sdes if((c=query_dname_compare(key1->rk.dname, key2->rk.dname)) != 0) 114238106Sdes return c; 115238106Sdes if(key1->rk.rrset_class != key2->rk.rrset_class) { 116238106Sdes if(key1->rk.rrset_class < key2->rk.rrset_class) 117238106Sdes return -1; 118238106Sdes return 1; 119238106Sdes } 120238106Sdes if(key1->rk.flags != key2->rk.flags) { 121238106Sdes if(key1->rk.flags < key2->rk.flags) 122238106Sdes return -1; 123238106Sdes return 1; 124238106Sdes } 125238106Sdes return 0; 126238106Sdes} 127238106Sdes 128238106Sdesvoid 129238106Sdesub_rrset_key_delete(void* key, void* userdata) 130238106Sdes{ 131238106Sdes struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key; 132238106Sdes struct alloc_cache* a = (struct alloc_cache*)userdata; 133238106Sdes k->id = 0; 134238106Sdes free(k->rk.dname); 135238106Sdes k->rk.dname = NULL; 136238106Sdes alloc_special_release(a, k); 137238106Sdes} 138238106Sdes 139238106Sdesvoid 140238106Sdesrrset_data_delete(void* data, void* ATTR_UNUSED(userdata)) 141238106Sdes{ 142238106Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)data; 143238106Sdes free(d); 144238106Sdes} 145238106Sdes 146238106Sdesint 147238106Sdesrrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2) 148238106Sdes{ 149238106Sdes size_t i; 150238106Sdes size_t total; 151238106Sdes if(d1->count != d2->count || d1->rrsig_count != d2->rrsig_count) 152238106Sdes return 0; 153238106Sdes total = d1->count + d1->rrsig_count; 154238106Sdes for(i=0; i<total; i++) { 155238106Sdes if(d1->rr_len[i] != d2->rr_len[i]) 156238106Sdes return 0; 157238106Sdes if(memcmp(d1->rr_data[i], d2->rr_data[i], d1->rr_len[i]) != 0) 158238106Sdes return 0; 159238106Sdes } 160238106Sdes return 1; 161238106Sdes} 162238106Sdes 163238106Sdeshashvalue_t 164238106Sdesrrset_key_hash(struct packed_rrset_key* key) 165238106Sdes{ 166238106Sdes /* type is hashed in host order */ 167238106Sdes uint16_t t = ntohs(key->type); 168238106Sdes /* Note this MUST be identical to pkt_hash_rrset in msgparse.c */ 169238106Sdes /* this routine does not have a compressed name */ 170238106Sdes hashvalue_t h = 0xab; 171238106Sdes h = dname_query_hash(key->dname, h); 172238106Sdes h = hashlittle(&t, sizeof(t), h); 173238106Sdes h = hashlittle(&key->rrset_class, sizeof(uint16_t), h); 174238106Sdes h = hashlittle(&key->flags, sizeof(uint32_t), h); 175238106Sdes return h; 176238106Sdes} 177238106Sdes 178238106Sdesvoid 179238106Sdespacked_rrset_ptr_fixup(struct packed_rrset_data* data) 180238106Sdes{ 181238106Sdes size_t i; 182238106Sdes size_t total = data->count + data->rrsig_count; 183238106Sdes uint8_t* nextrdata; 184238106Sdes /* fixup pointers in packed rrset data */ 185238106Sdes data->rr_len = (size_t*)((uint8_t*)data + 186238106Sdes sizeof(struct packed_rrset_data)); 187238106Sdes data->rr_data = (uint8_t**)&(data->rr_len[total]); 188269257Sdes data->rr_ttl = (time_t*)&(data->rr_data[total]); 189238106Sdes nextrdata = (uint8_t*)&(data->rr_ttl[total]); 190238106Sdes for(i=0; i<total; i++) { 191238106Sdes data->rr_data[i] = nextrdata; 192238106Sdes nextrdata += data->rr_len[i]; 193238106Sdes } 194238106Sdes} 195238106Sdes 196238106Sdesvoid 197238106Sdesget_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname, 198238106Sdes size_t* dname_len) 199238106Sdes{ 200238106Sdes struct packed_rrset_data* d; 201238106Sdes size_t len; 202238106Sdes if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_CNAME && 203238106Sdes ntohs(rrset->rk.type) != LDNS_RR_TYPE_DNAME) 204238106Sdes return; 205238106Sdes d = (struct packed_rrset_data*)rrset->entry.data; 206238106Sdes if(d->count < 1) 207238106Sdes return; 208238106Sdes if(d->rr_len[0] < 3) /* at least rdatalen + 0byte root label */ 209238106Sdes return; 210269257Sdes len = sldns_read_uint16(d->rr_data[0]); 211238106Sdes if(len != d->rr_len[0] - sizeof(uint16_t)) 212238106Sdes return; 213238106Sdes if(dname_valid(d->rr_data[0]+sizeof(uint16_t), len) != len) 214238106Sdes return; 215238106Sdes *dname = d->rr_data[0]+sizeof(uint16_t); 216238106Sdes *dname_len = len; 217238106Sdes} 218238106Sdes 219238106Sdesvoid 220269257Sdespacked_rrset_ttl_add(struct packed_rrset_data* data, time_t add) 221238106Sdes{ 222238106Sdes size_t i; 223238106Sdes size_t total = data->count + data->rrsig_count; 224238106Sdes data->ttl += add; 225238106Sdes for(i=0; i<total; i++) 226238106Sdes data->rr_ttl[i] += add; 227238106Sdes} 228238106Sdes 229238106Sdesconst char* 230238106Sdesrrset_trust_to_string(enum rrset_trust s) 231238106Sdes{ 232238106Sdes switch(s) { 233238106Sdes case rrset_trust_none: return "rrset_trust_none"; 234238106Sdes case rrset_trust_add_noAA: return "rrset_trust_add_noAA"; 235238106Sdes case rrset_trust_auth_noAA: return "rrset_trust_auth_noAA"; 236238106Sdes case rrset_trust_add_AA: return "rrset_trust_add_AA"; 237238106Sdes case rrset_trust_nonauth_ans_AA:return "rrset_trust_nonauth_ans_AA"; 238238106Sdes case rrset_trust_ans_noAA: return "rrset_trust_ans_noAA"; 239238106Sdes case rrset_trust_glue: return "rrset_trust_glue"; 240238106Sdes case rrset_trust_auth_AA: return "rrset_trust_auth_AA"; 241238106Sdes case rrset_trust_ans_AA: return "rrset_trust_ans_AA"; 242238106Sdes case rrset_trust_sec_noglue: return "rrset_trust_sec_noglue"; 243238106Sdes case rrset_trust_prim_noglue: return "rrset_trust_prim_noglue"; 244238106Sdes case rrset_trust_validated: return "rrset_trust_validated"; 245238106Sdes case rrset_trust_ultimate: return "rrset_trust_ultimate"; 246238106Sdes } 247238106Sdes return "unknown_rrset_trust_value"; 248238106Sdes} 249238106Sdes 250238106Sdesconst char* 251238106Sdessec_status_to_string(enum sec_status s) 252238106Sdes{ 253238106Sdes switch(s) { 254238106Sdes case sec_status_unchecked: return "sec_status_unchecked"; 255238106Sdes case sec_status_bogus: return "sec_status_bogus"; 256238106Sdes case sec_status_indeterminate: return "sec_status_indeterminate"; 257238106Sdes case sec_status_insecure: return "sec_status_insecure"; 258238106Sdes case sec_status_secure: return "sec_status_secure"; 259238106Sdes } 260238106Sdes return "unknown_sec_status_value"; 261238106Sdes} 262238106Sdes 263238106Sdesvoid log_rrset_key(enum verbosity_value v, const char* str, 264238106Sdes struct ub_packed_rrset_key* rrset) 265238106Sdes{ 266238106Sdes if(verbosity >= v) 267238106Sdes log_nametypeclass(v, str, rrset->rk.dname, 268238106Sdes ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class)); 269238106Sdes} 270238106Sdes 271269257Sdesint packed_rr_to_string(struct ub_packed_rrset_key* rrset, size_t i, 272269257Sdes time_t now, char* dest, size_t dest_len) 273269257Sdes{ 274269257Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> 275269257Sdes entry.data; 276269257Sdes uint8_t rr[65535]; 277269257Sdes size_t rlen = rrset->rk.dname_len + 2 + 2 + 4 + d->rr_len[i]; 278269257Sdes log_assert(dest_len > 0 && dest); 279269257Sdes if(rlen > dest_len) { 280269257Sdes dest[0] = 0; 281269257Sdes return 0; 282269257Sdes } 283269257Sdes memmove(rr, rrset->rk.dname, rrset->rk.dname_len); 284269257Sdes if(i < d->count) 285269257Sdes memmove(rr+rrset->rk.dname_len, &rrset->rk.type, 2); 286269257Sdes else sldns_write_uint16(rr+rrset->rk.dname_len, LDNS_RR_TYPE_RRSIG); 287269257Sdes memmove(rr+rrset->rk.dname_len+2, &rrset->rk.rrset_class, 2); 288269257Sdes sldns_write_uint32(rr+rrset->rk.dname_len+4, 289269257Sdes (uint32_t)(d->rr_ttl[i]-now)); 290269257Sdes memmove(rr+rrset->rk.dname_len+8, d->rr_data[i], d->rr_len[i]); 291269257Sdes if(sldns_wire2str_rr_buf(rr, rlen, dest, dest_len) == -1) { 292269257Sdes log_info("rrbuf failure %d %s", (int)d->rr_len[i], dest); 293269257Sdes dest[0] = 0; 294269257Sdes return 0; 295269257Sdes } 296269257Sdes return 1; 297269257Sdes} 298269257Sdes 299269257Sdesvoid log_packed_rrset(enum verbosity_value v, const char* str, 300269257Sdes struct ub_packed_rrset_key* rrset) 301269257Sdes{ 302269257Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> 303269257Sdes entry.data; 304269257Sdes char buf[65535]; 305269257Sdes size_t i; 306269257Sdes if(verbosity < v) 307269257Sdes return; 308269257Sdes for(i=0; i<d->count+d->rrsig_count; i++) { 309269257Sdes if(!packed_rr_to_string(rrset, i, 0, buf, sizeof(buf))) { 310269257Sdes log_info("%s: rr %d wire2str-error", str, (int)i); 311269257Sdes } else { 312269257Sdes log_info("%s: %s", str, buf); 313269257Sdes } 314269257Sdes } 315269257Sdes} 316269257Sdes 317269257Sdestime_t 318238106Sdesub_packed_rrset_ttl(struct ub_packed_rrset_key* key) 319238106Sdes{ 320238106Sdes struct packed_rrset_data* d = (struct packed_rrset_data*)key-> 321238106Sdes entry.data; 322238106Sdes return d->ttl; 323238106Sdes} 324238106Sdes 325238106Sdesstruct ub_packed_rrset_key* 326238106Sdespacked_rrset_copy_region(struct ub_packed_rrset_key* key, 327269257Sdes struct regional* region, time_t now) 328238106Sdes{ 329238106Sdes struct ub_packed_rrset_key* ck = regional_alloc(region, 330238106Sdes sizeof(struct ub_packed_rrset_key)); 331238106Sdes struct packed_rrset_data* d; 332238106Sdes struct packed_rrset_data* data = (struct packed_rrset_data*) 333238106Sdes key->entry.data; 334238106Sdes size_t dsize, i; 335238106Sdes if(!ck) 336238106Sdes return NULL; 337238106Sdes ck->id = key->id; 338238106Sdes memset(&ck->entry, 0, sizeof(ck->entry)); 339238106Sdes ck->entry.hash = key->entry.hash; 340238106Sdes ck->entry.key = ck; 341238106Sdes ck->rk = key->rk; 342238106Sdes ck->rk.dname = regional_alloc_init(region, key->rk.dname, 343238106Sdes key->rk.dname_len); 344238106Sdes if(!ck->rk.dname) 345238106Sdes return NULL; 346238106Sdes dsize = packed_rrset_sizeof(data); 347238106Sdes d = (struct packed_rrset_data*)regional_alloc_init(region, data, dsize); 348238106Sdes if(!d) 349238106Sdes return NULL; 350238106Sdes ck->entry.data = d; 351238106Sdes packed_rrset_ptr_fixup(d); 352238106Sdes /* make TTLs relative - once per rrset */ 353238106Sdes for(i=0; i<d->count + d->rrsig_count; i++) { 354238106Sdes if(d->rr_ttl[i] < now) 355238106Sdes d->rr_ttl[i] = 0; 356238106Sdes else d->rr_ttl[i] -= now; 357238106Sdes } 358238106Sdes if(d->ttl < now) 359238106Sdes d->ttl = 0; 360238106Sdes else d->ttl -= now; 361238106Sdes return ck; 362238106Sdes} 363238106Sdes 364238106Sdesstruct ub_packed_rrset_key* 365238106Sdespacked_rrset_copy_alloc(struct ub_packed_rrset_key* key, 366269257Sdes struct alloc_cache* alloc, time_t now) 367238106Sdes{ 368238106Sdes struct packed_rrset_data* fd, *dd; 369238106Sdes struct ub_packed_rrset_key* dk = alloc_special_obtain(alloc); 370238106Sdes if(!dk) return NULL; 371238106Sdes fd = (struct packed_rrset_data*)key->entry.data; 372238106Sdes dk->entry.hash = key->entry.hash; 373238106Sdes dk->rk = key->rk; 374238106Sdes dk->rk.dname = (uint8_t*)memdup(key->rk.dname, key->rk.dname_len); 375238106Sdes if(!dk->rk.dname) { 376238106Sdes alloc_special_release(alloc, dk); 377238106Sdes return NULL; 378238106Sdes } 379238106Sdes dd = (struct packed_rrset_data*)memdup(fd, packed_rrset_sizeof(fd)); 380238106Sdes if(!dd) { 381238106Sdes free(dk->rk.dname); 382238106Sdes alloc_special_release(alloc, dk); 383238106Sdes return NULL; 384238106Sdes } 385238106Sdes packed_rrset_ptr_fixup(dd); 386238106Sdes dk->entry.data = (void*)dd; 387238106Sdes packed_rrset_ttl_add(dd, now); 388238106Sdes return dk; 389238106Sdes} 390