packed_rrset.h revision 285206
12311Sjkh/* 22311Sjkh * util/data/packed_rrset.h - data storage for a set of resource records. 32311Sjkh * 42311Sjkh * Copyright (c) 2007, NLnet Labs. All rights reserved. 52311Sjkh * 62311Sjkh * This software is open source. 72311Sjkh * 82311Sjkh * Redistribution and use in source and binary forms, with or without 92311Sjkh * modification, are permitted provided that the following conditions 102311Sjkh * are met: 112311Sjkh * 122311Sjkh * Redistributions of source code must retain the above copyright notice, 132311Sjkh * this list of conditions and the following disclaimer. 142311Sjkh * 152311Sjkh * Redistributions in binary form must reproduce the above copyright notice, 162311Sjkh * this list of conditions and the following disclaimer in the documentation 172311Sjkh * and/or other materials provided with the distribution. 182311Sjkh * 192311Sjkh * Neither the name of the NLNET LABS nor the names of its contributors may 202311Sjkh * be used to endorse or promote products derived from this software without 212311Sjkh * specific prior written permission. 222311Sjkh * 232311Sjkh * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 242311Sjkh * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 252311Sjkh * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 262311Sjkh * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 272311Sjkh * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 282311Sjkh * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 292311Sjkh * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 302311Sjkh * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 312311Sjkh * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 322311Sjkh * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 332311Sjkh * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 342311Sjkh */ 352311Sjkh 362311Sjkh/** 372311Sjkh * \file 382311Sjkh * 392311Sjkh * This file contains the data storage for RRsets. 402311Sjkh */ 412311Sjkh 422311Sjkh#ifndef UTIL_DATA_PACKED_RRSET_H 432311Sjkh#define UTIL_DATA_PACKED_RRSET_H 442311Sjkh#include "util/storage/lruhash.h" 452311Sjkhstruct alloc_cache; 462311Sjkhstruct regional; 472311Sjkh 482311Sjkh/** type used to uniquely identify rrsets. Cannot be reused without 492311Sjkh * clearing the cache. */ 502311Sjkhtypedef uint64_t rrset_id_t; 512311Sjkh 522311Sjkh/** this rrset is NSEC and is at zone apex (at child side of zonecut) */ 532311Sjkh#define PACKED_RRSET_NSEC_AT_APEX 0x1 542311Sjkh/** this rrset is A/AAAA and is in-zone-glue (from parent side of zonecut) */ 552311Sjkh#define PACKED_RRSET_PARENT_SIDE 0x2 562311Sjkh/** this rrset is SOA and has the negative ttl (from nxdomain or nodata), 572311Sjkh * this is set on SOA rrsets in the authority section, to keep its TTL separate 582311Sjkh * from the SOA in the answer section from a direct SOA query or ANY query. */ 592311Sjkh#define PACKED_RRSET_SOA_NEG 0x4 602311Sjkh 612311Sjkh/** 622311Sjkh * The identifying information for an RRset. 632311Sjkh */ 642311Sjkhstruct packed_rrset_key { 652311Sjkh /** 662311Sjkh * The domain name. If not null (for id=0) it is allocated, and 672311Sjkh * contains the wireformat domain name. 682311Sjkh * This dname is not canonicalized. 692311Sjkh */ 702311Sjkh uint8_t* dname; 712311Sjkh /** 722311Sjkh * Length of the domain name, including last 0 root octet. 732311Sjkh */ 742311Sjkh size_t dname_len; 752311Sjkh /** 762311Sjkh * Flags. 32bit to be easy for hashing: 772311Sjkh * o PACKED_RRSET_NSEC_AT_APEX 782311Sjkh * o PACKED_RRSET_PARENT_SIDE 792311Sjkh * o PACKED_RRSET_SOA_NEG 802311Sjkh */ 812311Sjkh uint32_t flags; 822311Sjkh /** the rrset type in network format */ 832311Sjkh uint16_t type; 842311Sjkh /** the rrset class in network format */ 852311Sjkh uint16_t rrset_class; 862311Sjkh}; 872311Sjkh 882311Sjkh/** 892311Sjkh * This structure contains an RRset. A set of resource records that 902311Sjkh * share the same domain name, type and class. 912311Sjkh * 922311Sjkh * Due to memory management and threading, the key structure cannot be 932311Sjkh * deleted, although the data can be. The id can be set to 0 to store and the 942311Sjkh * structure can be recycled with a new id. 952311Sjkh */ 962311Sjkhstruct ub_packed_rrset_key { 972311Sjkh /** 982311Sjkh * entry into hashtable. Note the lock is never destroyed, 992311Sjkh * even when this key is retired to the cache. 1002311Sjkh * the data pointer (if not null) points to a struct packed_rrset. 1012311Sjkh */ 1022311Sjkh struct lruhash_entry entry; 1032311Sjkh /** 1042311Sjkh * the ID of this rrset. unique, based on threadid + sequenceno. 1052311Sjkh * ids are not reused, except after flushing the cache. 1062311Sjkh * zero is an unused entry, and never a valid id. 1072311Sjkh * Check this value after getting entry.lock. 1082311Sjkh * The other values in this struct may only be altered after changing 1092311Sjkh * the id (which needs a writelock on entry.lock). 1102311Sjkh */ 1112311Sjkh rrset_id_t id; 1122311Sjkh /** key data: dname, type and class */ 1132311Sjkh struct packed_rrset_key rk; 1142311Sjkh}; 1152311Sjkh 1162311Sjkh/** 1172311Sjkh * RRset trustworthiness. Bigger value is more trust. RFC 2181. 1182311Sjkh * The rrset_trust_add_noAA, rrset_trust_auth_noAA, rrset_trust_add_AA, 1192311Sjkh * are mentioned as the same trustworthiness in 2181, but split up here 1202311Sjkh * for ease of processing. 1212311Sjkh * 1222311Sjkh * rrset_trust_nonauth_ans_AA, rrset_trust_ans_noAA 1232311Sjkh * are also mentioned as the same trustworthiness in 2181, but split up here 1242311Sjkh * for ease of processing. 1252311Sjkh * 1262311Sjkh * Added trust_none for a sane initial value, smaller than anything else. 1272311Sjkh * Added validated and ultimate trust for keys and rrsig validated content. 1282311Sjkh */ 1292311Sjkhenum rrset_trust { 1302311Sjkh /** initial value for trust */ 1312311Sjkh rrset_trust_none = 0, 1322311Sjkh /** Additional information from non-authoritative answers */ 1332311Sjkh rrset_trust_add_noAA, 1342311Sjkh /** Data from the authority section of a non-authoritative answer */ 1352311Sjkh rrset_trust_auth_noAA, 1362311Sjkh /** Additional information from an authoritative answer */ 1372311Sjkh rrset_trust_add_AA, 1382311Sjkh /** non-authoritative data from the answer section of authoritative 1392311Sjkh * answers */ 1402311Sjkh rrset_trust_nonauth_ans_AA, 1412311Sjkh /** Data from the answer section of a non-authoritative answer */ 1422311Sjkh rrset_trust_ans_noAA, 1432311Sjkh /** Glue from a primary zone, or glue from a zone transfer */ 1442311Sjkh rrset_trust_glue, 1452311Sjkh /** Data from the authority section of an authoritative answer */ 1462311Sjkh rrset_trust_auth_AA, 1472311Sjkh /** The authoritative data included in the answer section of an 1482311Sjkh * authoritative reply */ 1492311Sjkh rrset_trust_ans_AA, 1502311Sjkh /** Data from a zone transfer, other than glue */ 1512311Sjkh rrset_trust_sec_noglue, 1522311Sjkh /** Data from a primary zone file, other than glue data */ 1532311Sjkh rrset_trust_prim_noglue, 1542311Sjkh /** DNSSEC(rfc4034) validated with trusted keys */ 1552311Sjkh rrset_trust_validated, 1562311Sjkh /** ultimately trusted, no more trust is possible; 1572311Sjkh * trusted keys from the unbound configuration setup. */ 1582311Sjkh rrset_trust_ultimate 1592311Sjkh}; 1602311Sjkh 1612311Sjkh/** 1622311Sjkh * Security status from validation for data. 1632311Sjkh * The order is significant; more secure, more proven later. 1642311Sjkh */ 1652311Sjkhenum sec_status { 1662311Sjkh /** UNCHECKED means that object has yet to be validated. */ 1672311Sjkh sec_status_unchecked = 0, 1682311Sjkh /** BOGUS means that the object (RRset or message) failed to validate 1692311Sjkh * (according to local policy), but should have validated. */ 1702311Sjkh sec_status_bogus, 1712311Sjkh /** INDETERMINATE means that the object is insecure, but not 1722311Sjkh * authoritatively so. Generally this means that the RRset is not 1732311Sjkh * below a configured trust anchor. */ 1742311Sjkh sec_status_indeterminate, 1752311Sjkh /** INSECURE means that the object is authoritatively known to be 1762311Sjkh * insecure. Generally this means that this RRset is below a trust 1772311Sjkh * anchor, but also below a verified, insecure delegation. */ 1782311Sjkh sec_status_insecure, 1792311Sjkh /** SECURE means that the object (RRset or message) validated 1802311Sjkh * according to local policy. */ 1812311Sjkh sec_status_secure 1822311Sjkh}; 1832311Sjkh 1842311Sjkh/** 1852311Sjkh * RRset data. 1862311Sjkh * 1872311Sjkh * The data is packed, stored contiguously in memory. 1882311Sjkh * memory layout: 1892311Sjkh * o base struct 1902311Sjkh * o rr_len size_t array 1912311Sjkh * o rr_data uint8_t* array 1922311Sjkh * o rr_ttl time_t array (after size_t and ptrs because those may be 1932311Sjkh * 64bit and this array before those would make them unaligned). 1942311Sjkh * Since the stuff before is 32/64bit, rr_ttl is 32 bit aligned. 1952311Sjkh * o rr_data rdata wireformats 1962311Sjkh * o rrsig_data rdata wireformat(s) 1972311Sjkh * 1982311Sjkh * Rdata is stored in wireformat. The dname is stored in wireformat. 1992311Sjkh * TTLs are stored as absolute values (and could be expired). 2002311Sjkh * 2012311Sjkh * RRSIGs are stored in the arrays after the regular rrs. 2022311Sjkh * 2032311Sjkh * You need the packed_rrset_key to know dname, type, class of the 2042311Sjkh * resource records in this RRset. (if signed the rrsig gives the type too). 2052311Sjkh * 2062311Sjkh * On the wire an RR is: 2072311Sjkh * name, type, class, ttl, rdlength, rdata. 2082311Sjkh * So we need to send the following per RR: 2092311Sjkh * key.dname, ttl, rr_data[i]. 2102311Sjkh * since key.dname ends with type and class. 2112311Sjkh * and rr_data starts with the rdlength. 2122311Sjkh * the ttl value to send changes due to time. 2132311Sjkh */ 2142311Sjkhstruct packed_rrset_data { 2152311Sjkh /** TTL (in seconds like time()) of the rrset. 2162311Sjkh * Same for all RRs see rfc2181(5.2). */ 2172311Sjkh time_t ttl; 2182311Sjkh /** number of rrs. */ 2192311Sjkh size_t count; 2202311Sjkh /** number of rrsigs, if 0 no rrsigs */ 2212311Sjkh size_t rrsig_count; 2222311Sjkh /** the trustworthiness of the rrset data */ 2232311Sjkh enum rrset_trust trust; 2242311Sjkh /** security status of the rrset data */ 2252311Sjkh enum sec_status security; 2262311Sjkh /** length of every rr's rdata, rr_len[i] is size of rr_data[i]. */ 2272311Sjkh size_t* rr_len; 2282311Sjkh /** ttl of every rr. rr_ttl[i] ttl of rr i. */ 2292311Sjkh time_t *rr_ttl; 2302311Sjkh /** 2312311Sjkh * Array of pointers to every rr's rdata. 2322311Sjkh * The rr_data[i] rdata is stored in uncompressed wireformat. 2332311Sjkh * The first uint16_t of rr_data[i] is network format rdlength. 2342311Sjkh * 2352311Sjkh * rr_data[count] to rr_data[count+rrsig_count] contain the rrsig data. 2362311Sjkh */ 2372311Sjkh uint8_t** rr_data; 2382311Sjkh}; 2392311Sjkh 2402311Sjkh/** 2412311Sjkh * An RRset can be represented using both key and data together. 2422311Sjkh * Split into key and data structures to simplify implementation of 2432311Sjkh * caching schemes. 2442311Sjkh */ 2452311Sjkhstruct packed_rrset { 2462311Sjkh /** domain name, type and class */ 2472311Sjkh struct packed_rrset_key* k; 2482311Sjkh /** ttl, count and rdatas (and rrsig) */ 2492311Sjkh struct packed_rrset_data* d; 2502311Sjkh}; 2512311Sjkh 2522311Sjkh/** 2532311Sjkh * list of packed rrsets 2542311Sjkh */ 2552311Sjkhstruct packed_rrset_list { 2562311Sjkh /** next in list */ 2572311Sjkh struct packed_rrset_list* next; 2582311Sjkh /** rrset key and data */ 2592311Sjkh struct packed_rrset rrset; 2602311Sjkh}; 2612311Sjkh 2622311Sjkh/** 2632311Sjkh * Delete packed rrset key and data, not entered in hashtables yet. 2642311Sjkh * Used during parsing. 2652311Sjkh * @param pkey: rrset key structure with locks, key and data pointers. 2662311Sjkh * @param alloc: where to return the unfree-able key structure. 2672311Sjkh */ 2682311Sjkhvoid ub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey, 2692311Sjkh struct alloc_cache* alloc); 2702311Sjkh 2712311Sjkh/** 2722311Sjkh * Memory size of rrset data. RRset data must be filled in correctly. 2732311Sjkh * @param data: data to examine. 2742311Sjkh * @return size in bytes. 2752311Sjkh */ 2762311Sjkhsize_t packed_rrset_sizeof(struct packed_rrset_data* data); 2772311Sjkh 2782311Sjkh/** 2792311Sjkh * Get TTL of rrset. RRset data must be filled in correctly. 2802311Sjkh * @param key: rrset key, with data to examine. 2812311Sjkh * @return ttl value. 2822311Sjkh */ 2832311Sjkhtime_t ub_packed_rrset_ttl(struct ub_packed_rrset_key* key); 2842311Sjkh 2852311Sjkh/** 2862311Sjkh * Calculate memory size of rrset entry. For hash table usage. 2872311Sjkh * @param key: struct ub_packed_rrset_key*. 2882311Sjkh * @param data: struct packed_rrset_data*. 2892311Sjkh * @return size in bytes. 2902311Sjkh */ 2912311Sjkhsize_t ub_rrset_sizefunc(void* key, void* data); 2922311Sjkh 2932311Sjkh/** 2942311Sjkh * compares two rrset keys. 2952311Sjkh * @param k1: struct ub_packed_rrset_key*. 2962311Sjkh * @param k2: struct ub_packed_rrset_key*. 2972311Sjkh * @return 0 if equal. 2982311Sjkh */ 2992311Sjkhint ub_rrset_compare(void* k1, void* k2); 3002311Sjkh 3012311Sjkh/** 3022311Sjkh * compare two rrset data structures. 3032311Sjkh * Compared rdata and rrsigdata, not the trust or ttl value. 3042311Sjkh * @param d1: data to compare. 3052311Sjkh * @param d2: data to compare. 3062311Sjkh * @return 1 if equal. 3072311Sjkh */ 3082311Sjkhint rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2); 3092311Sjkh 3102311Sjkh/** 3112311Sjkh * Old key to be deleted. RRset keys are recycled via alloc. 3122311Sjkh * The id is set to 0. So that other threads, after acquiring a lock always 3132311Sjkh * get the correct value, in this case the 0 deleted-special value. 3142311Sjkh * @param key: struct ub_packed_rrset_key*. 3152311Sjkh * @param userdata: alloc structure to use for recycling. 3162311Sjkh */ 3172311Sjkhvoid ub_rrset_key_delete(void* key, void* userdata); 3182311Sjkh 3192311Sjkh/** 3202311Sjkh * Old data to be deleted. 3212311Sjkh * @param data: what to delete. 3222311Sjkh * @param userdata: user data ptr. 3232311Sjkh */ 3242311Sjkhvoid rrset_data_delete(void* data, void* userdata); 3252311Sjkh 3262311Sjkh/** 3272311Sjkh * Calculate hash value for a packed rrset key. 3282311Sjkh * @param key: the rrset key with name, type, class, flags. 3292311Sjkh * @return hash value. 3302311Sjkh */ 3312311Sjkhhashvalue_t rrset_key_hash(struct packed_rrset_key* key); 3322311Sjkh 3332311Sjkh/** 3342311Sjkh * Fixup pointers in fixed data packed_rrset_data blob. 3352311Sjkh * After a memcpy of the data for example. Will set internal pointers right. 3362311Sjkh * @param data: rrset data structure. Otherwise correctly filled in. 3372311Sjkh */ 3382311Sjkhvoid packed_rrset_ptr_fixup(struct packed_rrset_data* data); 3392311Sjkh 3402311Sjkh/** 3412311Sjkh * Fixup TTLs in fixed data packed_rrset_data blob. 3422311Sjkh * @param data: rrset data structure. Otherwise correctly filled in. 3432311Sjkh * @param add: how many seconds to add, pass time(0) for example. 3442311Sjkh */ 3452311Sjkhvoid packed_rrset_ttl_add(struct packed_rrset_data* data, time_t add); 3462311Sjkh 3472311Sjkh/** 3482311Sjkh * Utility procedure to extract CNAME target name from its rdata. 3492311Sjkh * Failsafes; it will change passed dname to a valid dname or do nothing. 3502311Sjkh * @param rrset: the rrset structure. Must be a CNAME. 3512311Sjkh * Only first RR is used (multiple RRs are technically illegal anyway). 3522311Sjkh * Also works on type DNAME. Returns target name. 3532311Sjkh * @param dname: this pointer is updated to point into the cname rdata. 3542311Sjkh * If a failsafe fails, nothing happens to the pointer (such as the 3552311Sjkh * rdata was not a valid dname, not a CNAME, ...). 3562311Sjkh * @param dname_len: length of dname is returned. 3572311Sjkh */ 3582311Sjkhvoid get_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname, 3592311Sjkh size_t* dname_len); 3602311Sjkh 3612311Sjkh/** 3622311Sjkh * Get a printable string for a rrset trust value 3632311Sjkh * @param s: rrset trust value 3642311Sjkh * @return printable string. 3652311Sjkh */ 3662311Sjkhconst char* rrset_trust_to_string(enum rrset_trust s); 3672311Sjkh 3682311Sjkh/** 3692311Sjkh * Get a printable string for a security status value 3702311Sjkh * @param s: security status 3712311Sjkh * @return printable string. 3722311Sjkh */ 3732311Sjkhconst char* sec_status_to_string(enum sec_status s); 3742311Sjkh 3752311Sjkh/** 3762311Sjkh * Print string with neat domain name, type, class from rrset. 3772311Sjkh * @param v: at what verbosity level to print this. 3782311Sjkh * @param str: string of message. 3792311Sjkh * @param rrset: structure with name, type and class. 3802311Sjkh */ 3812311Sjkhvoid log_rrset_key(enum verbosity_value v, const char* str, 3822311Sjkh struct ub_packed_rrset_key* rrset); 3832311Sjkh 3842311Sjkh/** 3852311Sjkh * Convert RR from RRset to string. 3862311Sjkh * @param rrset: structure with data. 3872311Sjkh * @param i: index of rr or RRSIG. 3882311Sjkh * @param now: time that is subtracted from ttl before printout. Can be 0. 3892311Sjkh * @param dest: destination string buffer. Must be nonNULL. 3902311Sjkh * @param dest_len: length of dest buffer (>0). 3912311Sjkh * @return false on failure. 3922311Sjkh */ 3932311Sjkhint packed_rr_to_string(struct ub_packed_rrset_key* rrset, size_t i, 3942311Sjkh time_t now, char* dest, size_t dest_len); 3952311Sjkh 3962311Sjkh/** 3972311Sjkh * Print the string with prefix, one rr per line. 3982311Sjkh * @param v: at what verbosity level to print this. 3992311Sjkh * @param str: string of message. 4002311Sjkh * @param rrset: with name, and rdata, and rrsigs. 4012311Sjkh */ 4022311Sjkhvoid log_packed_rrset(enum verbosity_value v, const char* str, 4032311Sjkh struct ub_packed_rrset_key* rrset); 4042311Sjkh 4052311Sjkh/** 4062311Sjkh * Allocate rrset in region - no more locks needed 4072311Sjkh * @param key: a (just from rrset cache looked up) rrset key + valid, 4082311Sjkh * packed data record. 4092311Sjkh * @param region: where to alloc the copy 4102311Sjkh * @param now: adjust the TTLs to be relative (subtract from all TTLs). 4112311Sjkh * @return new region-alloced rrset key or NULL on alloc failure. 4122311Sjkh */ 4132311Sjkhstruct ub_packed_rrset_key* packed_rrset_copy_region( 4142311Sjkh struct ub_packed_rrset_key* key, struct regional* region, 4152311Sjkh time_t now); 4162311Sjkh 4172311Sjkh/** 4182311Sjkh * Allocate rrset with malloc (from region or you are holding the lock). 4192311Sjkh * @param key: key with data entry. 4202311Sjkh * @param alloc: alloc_cache to create rrset_keys 4212311Sjkh * @param now: adjust the TTLs to be absolute (add to all TTLs). 4222311Sjkh * @return new region-alloced rrset key or NULL on alloc failure. 4232311Sjkh */ 4242311Sjkhstruct ub_packed_rrset_key* packed_rrset_copy_alloc( 4252311Sjkh struct ub_packed_rrset_key* key, struct alloc_cache* alloc, 4262311Sjkh time_t now); 4272311Sjkh 4282311Sjkh#endif /* UTIL_DATA_PACKED_RRSET_H */ 4292311Sjkh