1118611Snjl/* 2118611Snjl * util/data/packed_rrset.c - data storage for a set of resource records. 3118611Snjl * 4118611Snjl * Copyright (c) 2007, NLnet Labs. All rights reserved. 5118611Snjl * 6118611Snjl * This software is open source. 7118611Snjl * 8118611Snjl * Redistribution and use in source and binary forms, with or without 9118611Snjl * modification, are permitted provided that the following conditions 10118611Snjl * are met: 11118611Snjl * 12118611Snjl * Redistributions of source code must retain the above copyright notice, 13118611Snjl * this list of conditions and the following disclaimer. 14118611Snjl * 15118611Snjl * Redistributions in binary form must reproduce the above copyright notice, 16118611Snjl * this list of conditions and the following disclaimer in the documentation 17118611Snjl * and/or other materials provided with the distribution. 18118611Snjl * 19118611Snjl * Neither the name of the NLNET LABS nor the names of its contributors may 20118611Snjl * be used to endorse or promote products derived from this software without 21118611Snjl * specific prior written permission. 22118611Snjl * 23118611Snjl * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24118611Snjl * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25118611Snjl * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26118611Snjl * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27118611Snjl * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28118611Snjl * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29118611Snjl * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30118611Snjl * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31118611Snjl * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32118611Snjl * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33118611Snjl * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34118611Snjl */ 35118611Snjl 36118611Snjl/** 37118611Snjl * \file 38118611Snjl * 39118611Snjl * This file contains the data storage for RRsets. 40118611Snjl */ 41118611Snjl 42118611Snjl#include "config.h" 43118611Snjl#include "util/data/msgparse.h" 44118611Snjl#include "util/data/packed_rrset.h" 45118611Snjl#include "util/data/dname.h" 46118611Snjl#include "util/storage/lookup3.h" 47118611Snjl#include "util/log.h" 48118611Snjl#include "util/alloc.h" 49118611Snjl#include "util/regional.h" 50118611Snjl#include "util/net_help.h" 51118611Snjl#include "sldns/rrdef.h" 52118611Snjl#include "sldns/sbuffer.h" 53118611Snjl#include "sldns/wire2str.h" 54118611Snjl 55118611Snjlvoid 56118611Snjlub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey, 57118611Snjl struct alloc_cache* alloc) 58118611Snjl{ 59118611Snjl if(!pkey) 60118611Snjl return; 61118611Snjl free(pkey->entry.data); 62118611Snjl pkey->entry.data = NULL; 63118611Snjl free(pkey->rk.dname); 64118611Snjl pkey->rk.dname = NULL; 65118611Snjl pkey->id = 0; 66118611Snjl alloc_special_release(alloc, pkey); 67118611Snjl} 68118611Snjl 69118611Snjlsize_t 70118611Snjlub_rrset_sizefunc(void* key, void* data) 71118611Snjl{ 72118611Snjl struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key; 73118611Snjl struct packed_rrset_data* d = (struct packed_rrset_data*)data; 74118611Snjl size_t s = sizeof(struct ub_packed_rrset_key) + k->rk.dname_len; 75118611Snjl s += packed_rrset_sizeof(d) + lock_get_mem(&k->entry.lock); 76118611Snjl return s; 77118611Snjl} 78118611Snjl 79118611Snjlsize_t 80118611Snjlpacked_rrset_sizeof(struct packed_rrset_data* d) 81118611Snjl{ 82118611Snjl size_t s; 83118611Snjl if(d->rrsig_count > 0) { 84118611Snjl s = ((uint8_t*)d->rr_data[d->count+d->rrsig_count-1] - 85118611Snjl (uint8_t*)d) + d->rr_len[d->count+d->rrsig_count-1]; 86118611Snjl } else { 87118611Snjl log_assert(d->count > 0); 88118611Snjl s = ((uint8_t*)d->rr_data[d->count-1] - (uint8_t*)d) + 89118611Snjl d->rr_len[d->count-1]; 90118611Snjl } 91118611Snjl return s; 92118611Snjl} 93118611Snjl 94118611Snjlint 95118611Snjlub_rrset_compare(void* k1, void* k2) 96118611Snjl{ 97118611Snjl struct ub_packed_rrset_key* key1 = (struct ub_packed_rrset_key*)k1; 98118611Snjl struct ub_packed_rrset_key* key2 = (struct ub_packed_rrset_key*)k2; 99118611Snjl int c; 100118611Snjl if(key1 == key2) 101118611Snjl return 0; 102118611Snjl if(key1->rk.type != key2->rk.type) { 103118611Snjl if(key1->rk.type < key2->rk.type) 104118611Snjl return -1; 105118611Snjl return 1; 106118611Snjl } 107118611Snjl if(key1->rk.dname_len != key2->rk.dname_len) { 108118611Snjl if(key1->rk.dname_len < key2->rk.dname_len) 109118611Snjl return -1; 110118611Snjl return 1; 111118611Snjl } 112118611Snjl if((c=query_dname_compare(key1->rk.dname, key2->rk.dname)) != 0) 113118611Snjl return c; 114118611Snjl if(key1->rk.rrset_class != key2->rk.rrset_class) { 115118611Snjl if(key1->rk.rrset_class < key2->rk.rrset_class) 116118611Snjl return -1; 117118611Snjl return 1; 118118611Snjl } 119118611Snjl if(key1->rk.flags != key2->rk.flags) { 120118611Snjl if(key1->rk.flags < key2->rk.flags) 121118611Snjl return -1; 122118611Snjl return 1; 123118611Snjl } 124118611Snjl return 0; 125118611Snjl} 126118611Snjl 127118611Snjlvoid 128118611Snjlub_rrset_key_delete(void* key, void* userdata) 129118611Snjl{ 130118611Snjl struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key; 131118611Snjl struct alloc_cache* a = (struct alloc_cache*)userdata; 132118611Snjl k->id = 0; 133118611Snjl free(k->rk.dname); 134118611Snjl k->rk.dname = NULL; 135118611Snjl alloc_special_release(a, k); 136118611Snjl} 137118611Snjl 138118611Snjlvoid 139118611Snjlrrset_data_delete(void* data, void* ATTR_UNUSED(userdata)) 140118611Snjl{ 141118611Snjl struct packed_rrset_data* d = (struct packed_rrset_data*)data; 142118611Snjl free(d); 143118611Snjl} 144118611Snjl 145118611Snjlint 146118611Snjlrrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2) 147118611Snjl{ 148118611Snjl size_t i; 149118611Snjl size_t total; 150118611Snjl if(d1->count != d2->count || d1->rrsig_count != d2->rrsig_count) 151118611Snjl return 0; 152118611Snjl total = d1->count + d1->rrsig_count; 153118611Snjl for(i=0; i<total; i++) { 154118611Snjl if(d1->rr_len[i] != d2->rr_len[i]) 155118611Snjl return 0; 156118611Snjl if(memcmp(d1->rr_data[i], d2->rr_data[i], d1->rr_len[i]) != 0) 157118611Snjl return 0; 158118611Snjl } 159118611Snjl return 1; 160118611Snjl} 161118611Snjl 162118611Snjlhashvalue_type 163118611Snjlrrset_key_hash(struct packed_rrset_key* key) 164118611Snjl{ 165118611Snjl /* type is hashed in host order */ 166118611Snjl uint16_t t = ntohs(key->type); 167118611Snjl /* Note this MUST be identical to pkt_hash_rrset in msgparse.c */ 168118611Snjl /* this routine does not have a compressed name */ 169118611Snjl hashvalue_type h = 0xab; 170118611Snjl h = dname_query_hash(key->dname, h); 171118611Snjl h = hashlittle(&t, sizeof(t), h); 172118611Snjl h = hashlittle(&key->rrset_class, sizeof(uint16_t), h); 173118611Snjl h = hashlittle(&key->flags, sizeof(uint32_t), h); 174118611Snjl return h; 175118611Snjl} 176118611Snjl 177118611Snjlvoid 178118611Snjlpacked_rrset_ptr_fixup(struct packed_rrset_data* data) 179118611Snjl{ 180118611Snjl size_t i; 181118611Snjl size_t total = data->count + data->rrsig_count; 182118611Snjl uint8_t* nextrdata; 183118611Snjl /* fixup pointers in packed rrset data */ 184118611Snjl data->rr_len = (size_t*)((uint8_t*)data + 185118611Snjl sizeof(struct packed_rrset_data)); 186118611Snjl data->rr_data = (uint8_t**)&(data->rr_len[total]); 187118611Snjl data->rr_ttl = (time_t*)&(data->rr_data[total]); 188118611Snjl nextrdata = (uint8_t*)&(data->rr_ttl[total]); 189118611Snjl for(i=0; i<total; i++) { 190118611Snjl data->rr_data[i] = nextrdata; 191118611Snjl nextrdata += data->rr_len[i]; 192118611Snjl } 193118611Snjl} 194118611Snjl 195118611Snjlvoid 196118611Snjlget_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname, 197118611Snjl size_t* dname_len) 198118611Snjl{ 199118611Snjl struct packed_rrset_data* d; 200118611Snjl size_t len; 201118611Snjl if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_CNAME && 202118611Snjl ntohs(rrset->rk.type) != LDNS_RR_TYPE_DNAME) 203118611Snjl return; 204118611Snjl d = (struct packed_rrset_data*)rrset->entry.data; 205118611Snjl if(d->count < 1) 206118611Snjl return; 207118611Snjl if(d->rr_len[0] < 3) /* at least rdatalen + 0byte root label */ 208118611Snjl return; 209118611Snjl len = sldns_read_uint16(d->rr_data[0]); 210118611Snjl if(len != d->rr_len[0] - sizeof(uint16_t)) 211118611Snjl return; 212118611Snjl if(dname_valid(d->rr_data[0]+sizeof(uint16_t), len) != len) 213118611Snjl return; 214118611Snjl *dname = d->rr_data[0]+sizeof(uint16_t); 215118611Snjl *dname_len = len; 216118611Snjl} 217118611Snjl 218118611Snjlvoid 219118611Snjlpacked_rrset_ttl_add(struct packed_rrset_data* data, time_t add) 220118611Snjl{ 221118611Snjl size_t i; 222118611Snjl size_t total = data->count + data->rrsig_count; 223118611Snjl data->ttl_add = add; 224118611Snjl data->ttl += add; 225118611Snjl for(i=0; i<total; i++) 226118611Snjl data->rr_ttl[i] += add; 227118611Snjl} 228118611Snjl 229118611Snjlconst char* 230118611Snjlrrset_trust_to_string(enum rrset_trust s) 231118611Snjl{ 232118611Snjl switch(s) { 233118611Snjl case rrset_trust_none: return "rrset_trust_none"; 234118611Snjl case rrset_trust_add_noAA: return "rrset_trust_add_noAA"; 235118611Snjl case rrset_trust_auth_noAA: return "rrset_trust_auth_noAA"; 236118611Snjl case rrset_trust_add_AA: return "rrset_trust_add_AA"; 237118611Snjl case rrset_trust_nonauth_ans_AA:return "rrset_trust_nonauth_ans_AA"; 238118611Snjl case rrset_trust_ans_noAA: return "rrset_trust_ans_noAA"; 239118611Snjl case rrset_trust_glue: return "rrset_trust_glue"; 240118611Snjl case rrset_trust_auth_AA: return "rrset_trust_auth_AA"; 241118611Snjl case rrset_trust_ans_AA: return "rrset_trust_ans_AA"; 242118611Snjl case rrset_trust_sec_noglue: return "rrset_trust_sec_noglue"; 243118611Snjl case rrset_trust_prim_noglue: return "rrset_trust_prim_noglue"; 244118611Snjl case rrset_trust_validated: return "rrset_trust_validated"; 245118611Snjl case rrset_trust_ultimate: return "rrset_trust_ultimate"; 246118611Snjl } 247118611Snjl return "unknown_rrset_trust_value"; 248118611Snjl} 249118611Snjl 250118611Snjlconst char* 251118611Snjlsec_status_to_string(enum sec_status s) 252118611Snjl{ 253118611Snjl switch(s) { 254118611Snjl case sec_status_unchecked: return "sec_status_unchecked"; 255118611Snjl case sec_status_bogus: return "sec_status_bogus"; 256118611Snjl case sec_status_indeterminate: return "sec_status_indeterminate"; 257118611Snjl case sec_status_insecure: return "sec_status_insecure"; 258118611Snjl case sec_status_secure_sentinel_fail: return "sec_status_secure_sentinel_fail"; 259118611Snjl case sec_status_secure: return "sec_status_secure"; 260118611Snjl } 261118611Snjl return "unknown_sec_status_value"; 262118611Snjl} 263118611Snjl 264118611Snjlvoid log_rrset_key(enum verbosity_value v, const char* str, 265118611Snjl struct ub_packed_rrset_key* rrset) 266118611Snjl{ 267118611Snjl if(verbosity >= v) 268118611Snjl log_nametypeclass(v, str, rrset->rk.dname, 269118611Snjl ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class)); 270118611Snjl} 271118611Snjl 272118611Snjlint packed_rr_to_string(struct ub_packed_rrset_key* rrset, size_t i, 273118611Snjl time_t now, char* dest, size_t dest_len) 274118611Snjl{ 275118611Snjl struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> 276118611Snjl entry.data; 277118611Snjl uint8_t rr[65535]; 278118611Snjl size_t rlen = rrset->rk.dname_len + 2 + 2 + 4 + d->rr_len[i]; 279118611Snjl time_t adjust = 0; 280118611Snjl log_assert(dest_len > 0 && dest); 281118611Snjl if(rlen > dest_len) { 282118611Snjl dest[0] = 0; 283118611Snjl return 0; 284118611Snjl } 285118611Snjl memmove(rr, rrset->rk.dname, rrset->rk.dname_len); 286118611Snjl if(i < d->count) 287118611Snjl memmove(rr+rrset->rk.dname_len, &rrset->rk.type, 2); 288118611Snjl else sldns_write_uint16(rr+rrset->rk.dname_len, LDNS_RR_TYPE_RRSIG); 289118611Snjl memmove(rr+rrset->rk.dname_len+2, &rrset->rk.rrset_class, 2); 290118611Snjl adjust = SERVE_ORIGINAL_TTL ? d->ttl_add : now; 291118611Snjl if (d->rr_ttl[i] < adjust) adjust = d->rr_ttl[i]; /* Prevent negative TTL overflow */ 292118611Snjl sldns_write_uint32(rr+rrset->rk.dname_len+4, 293118611Snjl (uint32_t)(d->rr_ttl[i]-adjust)); 294118611Snjl memmove(rr+rrset->rk.dname_len+8, d->rr_data[i], d->rr_len[i]); 295118611Snjl if(sldns_wire2str_rr_buf(rr, rlen, dest, dest_len) == -1) { 296118611Snjl log_info("rrbuf failure %d %s", (int)d->rr_len[i], dest); 297118611Snjl dest[0] = 0; 298118611Snjl return 0; 299118611Snjl } 300118611Snjl return 1; 301118611Snjl} 302118611Snjl 303118611Snjlvoid log_packed_rrset(enum verbosity_value v, const char* str, 304118611Snjl struct ub_packed_rrset_key* rrset) 305118611Snjl{ 306118611Snjl struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> 307118611Snjl entry.data; 308118611Snjl char buf[65535]; 309118611Snjl size_t i; 310118611Snjl if(verbosity < v) 311118611Snjl return; 312118611Snjl for(i=0; i<d->count+d->rrsig_count; i++) { 313118611Snjl if(!packed_rr_to_string(rrset, i, 0, buf, sizeof(buf))) { 314118611Snjl log_info("%s: rr %d wire2str-error", str, (int)i); 315118611Snjl } else { 316118611Snjl log_info("%s: %s", str, buf); 317118611Snjl } 318118611Snjl } 319118611Snjl} 320118611Snjl 321118611Snjltime_t 322118611Snjlub_packed_rrset_ttl(struct ub_packed_rrset_key* key) 323118611Snjl{ 324118611Snjl struct packed_rrset_data* d = (struct packed_rrset_data*)key-> 325118611Snjl entry.data; 326118611Snjl return d->ttl; 327118611Snjl} 328118611Snjl 329118611Snjlstruct ub_packed_rrset_key* 330118611Snjlpacked_rrset_copy_region(struct ub_packed_rrset_key* key, 331118611Snjl struct regional* region, time_t now) 332118611Snjl{ 333118611Snjl struct ub_packed_rrset_key* ck = regional_alloc(region, 334118611Snjl sizeof(struct ub_packed_rrset_key)); 335118611Snjl struct packed_rrset_data* d; 336118611Snjl struct packed_rrset_data* data = (struct packed_rrset_data*) 337118611Snjl key->entry.data; 338118611Snjl size_t dsize, i; 339118611Snjl time_t adjust = 0; 340118611Snjl if(!ck) 341118611Snjl return NULL; 342118611Snjl ck->id = key->id; 343118611Snjl memset(&ck->entry, 0, sizeof(ck->entry)); 344118611Snjl ck->entry.hash = key->entry.hash; 345118611Snjl ck->entry.key = ck; 346118611Snjl ck->rk = key->rk; 347118611Snjl ck->rk.dname = regional_alloc_init(region, key->rk.dname, 348118611Snjl key->rk.dname_len); 349118611Snjl if(!ck->rk.dname) 350118611Snjl return NULL; 351118611Snjl dsize = packed_rrset_sizeof(data); 352118611Snjl d = (struct packed_rrset_data*)regional_alloc_init(region, data, dsize); 353118611Snjl if(!d) 354118611Snjl return NULL; 355118611Snjl ck->entry.data = d; 356118611Snjl packed_rrset_ptr_fixup(d); 357118611Snjl /* make TTLs relative - once per rrset */ 358118611Snjl adjust = SERVE_ORIGINAL_TTL ? data->ttl_add : now; 359118611Snjl for(i=0; i<d->count + d->rrsig_count; i++) { 360118611Snjl if(d->rr_ttl[i] < adjust) 361118611Snjl d->rr_ttl[i] = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0; 362118611Snjl else d->rr_ttl[i] -= adjust; 363118611Snjl } 364118611Snjl if(d->ttl < adjust) 365118611Snjl d->ttl = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0; 366118611Snjl else d->ttl -= adjust; 367118611Snjl d->ttl_add = 0; /* TTLs have been made relative */ 368118611Snjl return ck; 369118611Snjl} 370118611Snjl 371118611Snjlstruct ub_packed_rrset_key* 372118611Snjlpacked_rrset_copy_alloc(struct ub_packed_rrset_key* key, 373118611Snjl struct alloc_cache* alloc, time_t now) 374118611Snjl{ 375118611Snjl struct packed_rrset_data* fd, *dd; 376118611Snjl struct ub_packed_rrset_key* dk = alloc_special_obtain(alloc); 377118611Snjl if(!dk) return NULL; 378118611Snjl fd = (struct packed_rrset_data*)key->entry.data; 379118611Snjl dk->entry.hash = key->entry.hash; 380118611Snjl dk->rk = key->rk; 381118611Snjl dk->rk.dname = (uint8_t*)memdup(key->rk.dname, key->rk.dname_len); 382118611Snjl if(!dk->rk.dname) { 383118611Snjl alloc_special_release(alloc, dk); 384118611Snjl return NULL; 385118611Snjl } 386118611Snjl dd = (struct packed_rrset_data*)memdup(fd, packed_rrset_sizeof(fd)); 387118611Snjl if(!dd) { 388118611Snjl free(dk->rk.dname); 389118611Snjl alloc_special_release(alloc, dk); 390118611Snjl return NULL; 391118611Snjl } 392118611Snjl packed_rrset_ptr_fixup(dd); 393118611Snjl dk->entry.data = (void*)dd; 394118611Snjl packed_rrset_ttl_add(dd, now); 395118611Snjl return dk; 396118611Snjl} 397118611Snjl 398118611Snjlint 399118611Snjlpacked_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len, 400118611Snjl size_t* index) 401118611Snjl{ 402118611Snjl size_t i; 403118611Snjl for(i=0; i<d->count; i++) { 404118611Snjl if(d->rr_len[i] != len) 405118611Snjl continue; 406118611Snjl if(memcmp(d->rr_data[i], rdata, len) == 0) { 407118611Snjl *index = i; 408118611Snjl return 1; 409118611Snjl } 410118611Snjl } 411118611Snjl return 0; 412118611Snjl} 413118611Snjl