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