1238106Sdes/* 2238106Sdes * util/data/packed_rrset.h - 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 24238106Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25238106Sdes * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26238106Sdes * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 27238106Sdes * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28238106Sdes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29238106Sdes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30238106Sdes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31238106Sdes * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32238106Sdes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33238106Sdes * POSSIBILITY OF SUCH DAMAGE. 34238106Sdes */ 35238106Sdes 36238106Sdes/** 37238106Sdes * \file 38238106Sdes * 39238106Sdes * This file contains the data storage for RRsets. 40238106Sdes */ 41238106Sdes 42238106Sdes#ifndef UTIL_DATA_PACKED_RRSET_H 43238106Sdes#define UTIL_DATA_PACKED_RRSET_H 44238106Sdes#include "util/storage/lruhash.h" 45238106Sdes#include <ldns/rr.h> 46238106Sdesstruct alloc_cache; 47238106Sdesstruct regional; 48238106Sdes 49238106Sdes/** type used to uniquely identify rrsets. Cannot be reused without 50238106Sdes * clearing the cache. */ 51238106Sdestypedef uint64_t rrset_id_t; 52238106Sdes 53238106Sdes/** this rrset is NSEC and is at zone apex (at child side of zonecut) */ 54238106Sdes#define PACKED_RRSET_NSEC_AT_APEX 0x1 55238106Sdes/** this rrset is A/AAAA and is in-zone-glue (from parent side of zonecut) */ 56238106Sdes#define PACKED_RRSET_PARENT_SIDE 0x2 57238106Sdes/** this rrset is SOA and has the negative ttl (from nxdomain or nodata), 58238106Sdes * this is set on SOA rrsets in the authority section, to keep its TTL separate 59238106Sdes * from the SOA in the answer section from a direct SOA query or ANY query. */ 60238106Sdes#define PACKED_RRSET_SOA_NEG 0x4 61238106Sdes 62238106Sdes/** 63238106Sdes * The identifying information for an RRset. 64238106Sdes */ 65238106Sdesstruct packed_rrset_key { 66238106Sdes /** 67238106Sdes * The domain name. If not null (for id=0) it is allocated, and 68238106Sdes * contains the wireformat domain name. 69238106Sdes * This dname is not canonicalized. 70238106Sdes */ 71238106Sdes uint8_t* dname; 72238106Sdes /** 73238106Sdes * Length of the domain name, including last 0 root octet. 74238106Sdes */ 75238106Sdes size_t dname_len; 76238106Sdes /** 77238106Sdes * Flags. 32bit to be easy for hashing: 78238106Sdes * o PACKED_RRSET_NSEC_AT_APEX 79238106Sdes * o PACKED_RRSET_PARENT_SIDE 80238106Sdes * o PACKED_RRSET_SOA_NEG 81238106Sdes */ 82238106Sdes uint32_t flags; 83238106Sdes /** the rrset type in network format */ 84238106Sdes uint16_t type; 85238106Sdes /** the rrset class in network format */ 86238106Sdes uint16_t rrset_class; 87238106Sdes}; 88238106Sdes 89238106Sdes/** 90238106Sdes * This structure contains an RRset. A set of resource records that 91238106Sdes * share the same domain name, type and class. 92238106Sdes * 93238106Sdes * Due to memory management and threading, the key structure cannot be 94238106Sdes * deleted, although the data can be. The id can be set to 0 to store and the 95238106Sdes * structure can be recycled with a new id. 96238106Sdes */ 97238106Sdesstruct ub_packed_rrset_key { 98238106Sdes /** 99238106Sdes * entry into hashtable. Note the lock is never destroyed, 100238106Sdes * even when this key is retired to the cache. 101238106Sdes * the data pointer (if not null) points to a struct packed_rrset. 102238106Sdes */ 103238106Sdes struct lruhash_entry entry; 104238106Sdes /** 105238106Sdes * the ID of this rrset. unique, based on threadid + sequenceno. 106238106Sdes * ids are not reused, except after flushing the cache. 107238106Sdes * zero is an unused entry, and never a valid id. 108238106Sdes * Check this value after getting entry.lock. 109238106Sdes * The other values in this struct may only be altered after changing 110238106Sdes * the id (which needs a writelock on entry.lock). 111238106Sdes */ 112238106Sdes rrset_id_t id; 113238106Sdes /** key data: dname, type and class */ 114238106Sdes struct packed_rrset_key rk; 115238106Sdes}; 116238106Sdes 117238106Sdes/** 118238106Sdes * RRset trustworthiness. Bigger value is more trust. RFC 2181. 119238106Sdes * The rrset_trust_add_noAA, rrset_trust_auth_noAA, rrset_trust_add_AA, 120238106Sdes * are mentioned as the same trustworthiness in 2181, but split up here 121238106Sdes * for ease of processing. 122238106Sdes * 123238106Sdes * rrset_trust_nonauth_ans_AA, rrset_trust_ans_noAA 124238106Sdes * are also mentioned as the same trustworthiness in 2181, but split up here 125238106Sdes * for ease of processing. 126238106Sdes * 127238106Sdes * Added trust_none for a sane initial value, smaller than anything else. 128238106Sdes * Added validated and ultimate trust for keys and rrsig validated content. 129238106Sdes */ 130238106Sdesenum rrset_trust { 131238106Sdes /** initial value for trust */ 132238106Sdes rrset_trust_none = 0, 133238106Sdes /** Additional information from non-authoritative answers */ 134238106Sdes rrset_trust_add_noAA, 135238106Sdes /** Data from the authority section of a non-authoritative answer */ 136238106Sdes rrset_trust_auth_noAA, 137238106Sdes /** Additional information from an authoritative answer */ 138238106Sdes rrset_trust_add_AA, 139238106Sdes /** non-authoritative data from the answer section of authoritative 140238106Sdes * answers */ 141238106Sdes rrset_trust_nonauth_ans_AA, 142238106Sdes /** Data from the answer section of a non-authoritative answer */ 143238106Sdes rrset_trust_ans_noAA, 144238106Sdes /** Glue from a primary zone, or glue from a zone transfer */ 145238106Sdes rrset_trust_glue, 146238106Sdes /** Data from the authority section of an authoritative answer */ 147238106Sdes rrset_trust_auth_AA, 148238106Sdes /** The authoritative data included in the answer section of an 149238106Sdes * authoritative reply */ 150238106Sdes rrset_trust_ans_AA, 151238106Sdes /** Data from a zone transfer, other than glue */ 152238106Sdes rrset_trust_sec_noglue, 153238106Sdes /** Data from a primary zone file, other than glue data */ 154238106Sdes rrset_trust_prim_noglue, 155238106Sdes /** DNSSEC(rfc4034) validated with trusted keys */ 156238106Sdes rrset_trust_validated, 157238106Sdes /** ultimately trusted, no more trust is possible; 158238106Sdes * trusted keys from the unbound configuration setup. */ 159238106Sdes rrset_trust_ultimate 160238106Sdes}; 161238106Sdes 162238106Sdes/** 163238106Sdes * Security status from validation for data. 164238106Sdes * The order is significant; more secure, more proven later. 165238106Sdes */ 166238106Sdesenum sec_status { 167238106Sdes /** UNCHECKED means that object has yet to be validated. */ 168238106Sdes sec_status_unchecked = 0, 169238106Sdes /** BOGUS means that the object (RRset or message) failed to validate 170238106Sdes * (according to local policy), but should have validated. */ 171238106Sdes sec_status_bogus, 172238106Sdes /** INDETERMINATE means that the object is insecure, but not 173238106Sdes * authoritatively so. Generally this means that the RRset is not 174238106Sdes * below a configured trust anchor. */ 175238106Sdes sec_status_indeterminate, 176238106Sdes /** INSECURE means that the object is authoritatively known to be 177238106Sdes * insecure. Generally this means that this RRset is below a trust 178238106Sdes * anchor, but also below a verified, insecure delegation. */ 179238106Sdes sec_status_insecure, 180238106Sdes /** SECURE means that the object (RRset or message) validated 181238106Sdes * according to local policy. */ 182238106Sdes sec_status_secure 183238106Sdes}; 184238106Sdes 185238106Sdes/** 186238106Sdes * RRset data. 187238106Sdes * 188238106Sdes * The data is packed, stored contiguously in memory. 189238106Sdes * memory layout: 190238106Sdes * o base struct 191238106Sdes * o rr_len size_t array 192238106Sdes * o rr_data uint8_t* array 193238106Sdes * o rr_ttl uint32_t array (after size_t and ptrs because those may be 194238106Sdes * 64bit and this array before those would make them unaligned). 195238106Sdes * Since the stuff before is 32/64bit, rr_ttl is 32 bit aligned. 196238106Sdes * o rr_data rdata wireformats 197238106Sdes * o rrsig_data rdata wireformat(s) 198238106Sdes * 199238106Sdes * Rdata is stored in wireformat. The dname is stored in wireformat. 200238106Sdes * TTLs are stored as absolute values (and could be expired). 201238106Sdes * 202238106Sdes * RRSIGs are stored in the arrays after the regular rrs. 203238106Sdes * 204238106Sdes * You need the packed_rrset_key to know dname, type, class of the 205238106Sdes * resource records in this RRset. (if signed the rrsig gives the type too). 206238106Sdes * 207238106Sdes * On the wire an RR is: 208238106Sdes * name, type, class, ttl, rdlength, rdata. 209238106Sdes * So we need to send the following per RR: 210238106Sdes * key.dname, ttl, rr_data[i]. 211238106Sdes * since key.dname ends with type and class. 212238106Sdes * and rr_data starts with the rdlength. 213238106Sdes * the ttl value to send changes due to time. 214238106Sdes */ 215238106Sdesstruct packed_rrset_data { 216238106Sdes /** TTL (in seconds like time()) of the rrset. 217238106Sdes * Same for all RRs see rfc2181(5.2). */ 218238106Sdes uint32_t ttl; 219238106Sdes /** number of rrs. */ 220238106Sdes size_t count; 221238106Sdes /** number of rrsigs, if 0 no rrsigs */ 222238106Sdes size_t rrsig_count; 223238106Sdes /** the trustworthiness of the rrset data */ 224238106Sdes enum rrset_trust trust; 225238106Sdes /** security status of the rrset data */ 226238106Sdes enum sec_status security; 227238106Sdes /** length of every rr's rdata, rr_len[i] is size of rr_data[i]. */ 228238106Sdes size_t* rr_len; 229238106Sdes /** ttl of every rr. rr_ttl[i] ttl of rr i. */ 230238106Sdes uint32_t *rr_ttl; 231238106Sdes /** 232238106Sdes * Array of pointers to every rr's rdata. 233238106Sdes * The rr_data[i] rdata is stored in uncompressed wireformat. 234238106Sdes * The first uint16_t of rr_data[i] is network format rdlength. 235238106Sdes * 236238106Sdes * rr_data[count] to rr_data[count+rrsig_count] contain the rrsig data. 237238106Sdes */ 238238106Sdes uint8_t** rr_data; 239238106Sdes}; 240238106Sdes 241238106Sdes/** 242238106Sdes * An RRset can be represented using both key and data together. 243238106Sdes * Split into key and data structures to simplify implementation of 244238106Sdes * caching schemes. 245238106Sdes */ 246238106Sdesstruct packed_rrset { 247238106Sdes /** domain name, type and class */ 248238106Sdes struct packed_rrset_key* k; 249238106Sdes /** ttl, count and rdatas (and rrsig) */ 250238106Sdes struct packed_rrset_data* d; 251238106Sdes}; 252238106Sdes 253238106Sdes/** 254238106Sdes * list of packed rrsets 255238106Sdes */ 256238106Sdesstruct packed_rrset_list { 257238106Sdes /** next in list */ 258238106Sdes struct packed_rrset_list* next; 259238106Sdes /** rrset key and data */ 260238106Sdes struct packed_rrset rrset; 261238106Sdes}; 262238106Sdes 263238106Sdes/** 264238106Sdes * Delete packed rrset key and data, not entered in hashtables yet. 265238106Sdes * Used during parsing. 266238106Sdes * @param pkey: rrset key structure with locks, key and data pointers. 267238106Sdes * @param alloc: where to return the unfree-able key structure. 268238106Sdes */ 269238106Sdesvoid ub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey, 270238106Sdes struct alloc_cache* alloc); 271238106Sdes 272238106Sdes/** 273238106Sdes * Memory size of rrset data. RRset data must be filled in correctly. 274238106Sdes * @param data: data to examine. 275238106Sdes * @return size in bytes. 276238106Sdes */ 277238106Sdessize_t packed_rrset_sizeof(struct packed_rrset_data* data); 278238106Sdes 279238106Sdes/** 280238106Sdes * Get TTL of rrset. RRset data must be filled in correctly. 281238106Sdes * @param key: rrset key, with data to examine. 282238106Sdes * @return ttl value. 283238106Sdes */ 284238106Sdesuint32_t ub_packed_rrset_ttl(struct ub_packed_rrset_key* key); 285238106Sdes 286238106Sdes/** 287238106Sdes * Calculate memory size of rrset entry. For hash table usage. 288238106Sdes * @param key: struct ub_packed_rrset_key*. 289238106Sdes * @param data: struct packed_rrset_data*. 290238106Sdes * @return size in bytes. 291238106Sdes */ 292238106Sdessize_t ub_rrset_sizefunc(void* key, void* data); 293238106Sdes 294238106Sdes/** 295238106Sdes * compares two rrset keys. 296238106Sdes * @param k1: struct ub_packed_rrset_key*. 297238106Sdes * @param k2: struct ub_packed_rrset_key*. 298238106Sdes * @return 0 if equal. 299238106Sdes */ 300238106Sdesint ub_rrset_compare(void* k1, void* k2); 301238106Sdes 302238106Sdes/** 303238106Sdes * compare two rrset data structures. 304238106Sdes * Compared rdata and rrsigdata, not the trust or ttl value. 305238106Sdes * @param d1: data to compare. 306238106Sdes * @param d2: data to compare. 307238106Sdes * @return 1 if equal. 308238106Sdes */ 309238106Sdesint rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2); 310238106Sdes 311238106Sdes/** 312238106Sdes * Old key to be deleted. RRset keys are recycled via alloc. 313238106Sdes * The id is set to 0. So that other threads, after acquiring a lock always 314238106Sdes * get the correct value, in this case the 0 deleted-special value. 315238106Sdes * @param key: struct ub_packed_rrset_key*. 316238106Sdes * @param userdata: alloc structure to use for recycling. 317238106Sdes */ 318238106Sdesvoid ub_rrset_key_delete(void* key, void* userdata); 319238106Sdes 320238106Sdes/** 321238106Sdes * Old data to be deleted. 322238106Sdes * @param data: what to delete. 323238106Sdes * @param userdata: user data ptr. 324238106Sdes */ 325238106Sdesvoid rrset_data_delete(void* data, void* userdata); 326238106Sdes 327238106Sdes/** 328238106Sdes * Calculate hash value for a packed rrset key. 329238106Sdes * @param key: the rrset key with name, type, class, flags. 330238106Sdes * @return hash value. 331238106Sdes */ 332238106Sdeshashvalue_t rrset_key_hash(struct packed_rrset_key* key); 333238106Sdes 334238106Sdes/** 335238106Sdes * Fixup pointers in fixed data packed_rrset_data blob. 336238106Sdes * After a memcpy of the data for example. Will set internal pointers right. 337238106Sdes * @param data: rrset data structure. Otherwise correctly filled in. 338238106Sdes */ 339238106Sdesvoid packed_rrset_ptr_fixup(struct packed_rrset_data* data); 340238106Sdes 341238106Sdes/** 342238106Sdes * Fixup TTLs in fixed data packed_rrset_data blob. 343238106Sdes * @param data: rrset data structure. Otherwise correctly filled in. 344238106Sdes * @param add: how many seconds to add, pass time(0) for example. 345238106Sdes */ 346238106Sdesvoid packed_rrset_ttl_add(struct packed_rrset_data* data, uint32_t add); 347238106Sdes 348238106Sdes/** 349238106Sdes * Utility procedure to extract CNAME target name from its rdata. 350238106Sdes * Failsafes; it will change passed dname to a valid dname or do nothing. 351238106Sdes * @param rrset: the rrset structure. Must be a CNAME. 352238106Sdes * Only first RR is used (multiple RRs are technically illegal anyway). 353238106Sdes * Also works on type DNAME. Returns target name. 354238106Sdes * @param dname: this pointer is updated to point into the cname rdata. 355238106Sdes * If a failsafe fails, nothing happens to the pointer (such as the 356238106Sdes * rdata was not a valid dname, not a CNAME, ...). 357238106Sdes * @param dname_len: length of dname is returned. 358238106Sdes */ 359238106Sdesvoid get_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname, 360238106Sdes size_t* dname_len); 361238106Sdes 362238106Sdes/** 363238106Sdes * Get a printable string for a rrset trust value 364238106Sdes * @param s: rrset trust value 365238106Sdes * @return printable string. 366238106Sdes */ 367238106Sdesconst char* rrset_trust_to_string(enum rrset_trust s); 368238106Sdes 369238106Sdes/** 370238106Sdes * Get a printable string for a security status value 371238106Sdes * @param s: security status 372238106Sdes * @return printable string. 373238106Sdes */ 374238106Sdesconst char* sec_status_to_string(enum sec_status s); 375238106Sdes 376238106Sdes/** 377238106Sdes * Print string with neat domain name, type, class from rrset. 378238106Sdes * @param v: at what verbosity level to print this. 379238106Sdes * @param str: string of message. 380238106Sdes * @param rrset: structure with name, type and class. 381238106Sdes */ 382238106Sdesvoid log_rrset_key(enum verbosity_value v, const char* str, 383238106Sdes struct ub_packed_rrset_key* rrset); 384238106Sdes 385238106Sdes/** 386238106Sdes * Allocate rrset in region - no more locks needed 387238106Sdes * @param key: a (just from rrset cache looked up) rrset key + valid, 388238106Sdes * packed data record. 389238106Sdes * @param region: where to alloc the copy 390238106Sdes * @param now: adjust the TTLs to be relative (subtract from all TTLs). 391238106Sdes * @return new region-alloced rrset key or NULL on alloc failure. 392238106Sdes */ 393238106Sdesstruct ub_packed_rrset_key* packed_rrset_copy_region( 394238106Sdes struct ub_packed_rrset_key* key, struct regional* region, 395238106Sdes uint32_t now); 396238106Sdes 397238106Sdes/** 398238106Sdes * Allocate rrset with malloc (from region or you are holding the lock). 399238106Sdes * @param key: key with data entry. 400238106Sdes * @param alloc: alloc_cache to create rrset_keys 401238106Sdes * @param now: adjust the TTLs to be absolute (add to all TTLs). 402238106Sdes * @return new region-alloced rrset key or NULL on alloc failure. 403238106Sdes */ 404238106Sdesstruct ub_packed_rrset_key* packed_rrset_copy_alloc( 405238106Sdes struct ub_packed_rrset_key* key, struct alloc_cache* alloc, 406238106Sdes uint32_t now); 407238106Sdes 408238106Sdes/** 409238106Sdes * Create a ub_packed_rrset_key allocated on the heap. 410238106Sdes * It therefore does not have the correct ID value, and cannot be used 411238106Sdes * inside the cache. It can be used in storage outside of the cache. 412238106Sdes * Keys for the cache have to be obtained from alloc.h . 413238106Sdes * @param rrset: the ldns rr set. 414238106Sdes * @return key allocated or NULL on failure. 415238106Sdes */ 416238106Sdesstruct ub_packed_rrset_key* ub_packed_rrset_heap_key(ldns_rr_list* rrset); 417238106Sdes 418238106Sdes/** 419238106Sdes * Create packed_rrset data on the heap. 420238106Sdes * @param rrset: the ldns rr set with the data to copy. 421238106Sdes * @return data allocated or NULL on failure. 422238106Sdes */ 423238106Sdesstruct packed_rrset_data* packed_rrset_heap_data(ldns_rr_list* rrset); 424238106Sdes 425238106Sdes/** 426238106Sdes * Convert packed rrset to ldns rr list. 427238106Sdes * @param rrset: packed rrset. 428238106Sdes * @param buf: scratch buffer. 429238106Sdes * @return rr list or NULL on failure. 430238106Sdes */ 431238106Sdesldns_rr_list* packed_rrset_to_rr_list(struct ub_packed_rrset_key* rrset, 432238106Sdes ldns_buffer* buf); 433238106Sdes 434238106Sdes#endif /* UTIL_DATA_PACKED_RRSET_H */ 435