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