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