1238106Sdes/* 2238106Sdes * util/data/msgreply.h - store message and reply data. 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 a data structure to store a message and its reply. 40238106Sdes */ 41238106Sdes 42238106Sdes#ifndef UTIL_DATA_MSGREPLY_H 43238106Sdes#define UTIL_DATA_MSGREPLY_H 44238106Sdes#include "util/storage/lruhash.h" 45238106Sdes#include "util/data/packed_rrset.h" 46269257Sdesstruct sldns_buffer; 47238106Sdesstruct comm_reply; 48238106Sdesstruct alloc_cache; 49238106Sdesstruct iovec; 50238106Sdesstruct regional; 51238106Sdesstruct edns_data; 52238106Sdesstruct msg_parse; 53238106Sdesstruct rrset_parse; 54238106Sdes 55238106Sdes/** calculate the prefetch TTL as 90% of original. Calculation 56238106Sdes * without numerical overflow (uin32_t) */ 57238106Sdes#define PREFETCH_TTL_CALC(ttl) ((ttl) - (ttl)/10) 58238106Sdes 59238106Sdes/** 60238106Sdes * Structure to store query information that makes answers to queries 61238106Sdes * different. 62238106Sdes */ 63238106Sdesstruct query_info { 64238106Sdes /** 65238106Sdes * Salient data on the query: qname, in wireformat. 66238106Sdes * can be allocated or a pointer to outside buffer. 67238106Sdes * User has to keep track on the status of this. 68238106Sdes */ 69238106Sdes uint8_t* qname; 70238106Sdes /** length of qname (including last 0 octet) */ 71238106Sdes size_t qname_len; 72238106Sdes /** qtype, host byte order */ 73238106Sdes uint16_t qtype; 74238106Sdes /** qclass, host byte order */ 75238106Sdes uint16_t qclass; 76238106Sdes}; 77238106Sdes 78238106Sdes/** 79238106Sdes * Information to reference an rrset 80238106Sdes */ 81238106Sdesstruct rrset_ref { 82238106Sdes /** the key with lock, and ptr to packed data. */ 83238106Sdes struct ub_packed_rrset_key* key; 84238106Sdes /** id needed */ 85238106Sdes rrset_id_t id; 86238106Sdes}; 87238106Sdes 88238106Sdes/** 89238106Sdes * Structure to store DNS query and the reply packet. 90238106Sdes * To use it, copy over the flags from reply and modify using flags from 91238106Sdes * the query (RD,CD if not AA). prepend ID. 92238106Sdes * 93238106Sdes * Memory layout is: 94238106Sdes * o struct 95238106Sdes * o rrset_ref array 96238106Sdes * o packed_rrset_key* array. 97238106Sdes * 98238106Sdes * Memory layout is sometimes not packed, when the message is synthesized, 99238106Sdes * for easy of the generation. It is allocated packed when it is copied 100238106Sdes * from the region allocation to the malloc allocation. 101238106Sdes */ 102238106Sdesstruct reply_info { 103238106Sdes /** the flags for the answer, host byte order. */ 104238106Sdes uint16_t flags; 105238106Sdes 106238106Sdes /** 107238106Sdes * This flag informs unbound the answer is authoritative and 108238106Sdes * the AA flag should be preserved. 109238106Sdes */ 110238106Sdes uint8_t authoritative; 111238106Sdes 112238106Sdes /** 113238106Sdes * Number of RRs in the query section. 114238106Sdes * If qdcount is not 0, then it is 1, and the data that appears 115238106Sdes * in the reply is the same as the query_info. 116238106Sdes * Host byte order. 117238106Sdes */ 118238106Sdes uint8_t qdcount; 119238106Sdes 120269257Sdes /** 32 bit padding to pad struct member alignment to 64 bits. */ 121269257Sdes uint32_t padding; 122269257Sdes 123238106Sdes /** 124238106Sdes * TTL of the entire reply (for negative caching). 125238106Sdes * only for use when there are 0 RRsets in this message. 126238106Sdes * if there are RRsets, check those instead. 127238106Sdes */ 128269257Sdes time_t ttl; 129238106Sdes 130238106Sdes /** 131238106Sdes * TTL for prefetch. After it has expired, a prefetch is suitable. 132238106Sdes * Smaller than the TTL, otherwise the prefetch would not happen. 133238106Sdes */ 134269257Sdes time_t prefetch_ttl; 135238106Sdes 136238106Sdes /** 137238106Sdes * The security status from DNSSEC validation of this message. 138238106Sdes */ 139238106Sdes enum sec_status security; 140238106Sdes 141238106Sdes /** 142238106Sdes * Number of RRsets in each section. 143238106Sdes * The answer section. Add up the RRs in every RRset to calculate 144238106Sdes * the number of RRs, and the count for the dns packet. 145238106Sdes * The number of RRs in RRsets can change due to RRset updates. 146238106Sdes */ 147238106Sdes size_t an_numrrsets; 148238106Sdes 149238106Sdes /** Count of authority section RRsets */ 150238106Sdes size_t ns_numrrsets; 151238106Sdes /** Count of additional section RRsets */ 152238106Sdes size_t ar_numrrsets; 153238106Sdes 154238106Sdes /** number of RRsets: an_numrrsets + ns_numrrsets + ar_numrrsets */ 155238106Sdes size_t rrset_count; 156238106Sdes 157238106Sdes /** 158238106Sdes * List of pointers (only) to the rrsets in the order in which 159238106Sdes * they appear in the reply message. 160238106Sdes * Number of elements is ancount+nscount+arcount RRsets. 161238106Sdes * This is a pointer to that array. 162238106Sdes * Use the accessor function for access. 163238106Sdes */ 164238106Sdes struct ub_packed_rrset_key** rrsets; 165238106Sdes 166238106Sdes /** 167238106Sdes * Packed array of ids (see counts) and pointers to packed_rrset_key. 168238106Sdes * The number equals ancount+nscount+arcount RRsets. 169238106Sdes * These are sorted in ascending pointer, the locking order. So 170238106Sdes * this list can be locked (and id, ttl checked), to see if 171238106Sdes * all the data is available and recent enough. 172238106Sdes * 173238106Sdes * This is defined as an array of size 1, so that the compiler 174238106Sdes * associates the identifier with this position in the structure. 175238106Sdes * Array bound overflow on this array then gives access to the further 176238106Sdes * elements of the array, which are allocated after the main structure. 177238106Sdes * 178238106Sdes * It could be more pure to define as array of size 0, ref[0]. 179238106Sdes * But ref[1] may be less confusing for compilers. 180238106Sdes * Use the accessor function for access. 181238106Sdes */ 182238106Sdes struct rrset_ref ref[1]; 183238106Sdes}; 184238106Sdes 185238106Sdes/** 186238106Sdes * Structure to keep hash table entry for message replies. 187238106Sdes */ 188238106Sdesstruct msgreply_entry { 189238106Sdes /** the hash table key */ 190238106Sdes struct query_info key; 191238106Sdes /** the hash table entry, data is struct reply_info* */ 192238106Sdes struct lruhash_entry entry; 193238106Sdes}; 194238106Sdes 195285206Sdes/** 196285206Sdes * Constructor for replyinfo. 197285206Sdes * @param region: where to allocate the results, pass NULL to use malloc. 198285206Sdes * @param flags: flags for the replyinfo. 199285206Sdes * @param qd: qd count 200285206Sdes * @param ttl: TTL of replyinfo 201285206Sdes * @param prettl: prefetch ttl 202285206Sdes * @param an: an count 203285206Sdes * @param ns: ns count 204285206Sdes * @param ar: ar count 205285206Sdes * @param total: total rrset count (presumably an+ns+ar). 206285206Sdes * @param sec: security status of the reply info. 207285206Sdes * @return the reply_info base struct with the array for putting the rrsets 208285206Sdes * in. The array has been zeroed. Returns NULL on malloc failure. 209285206Sdes */ 210285206Sdesstruct reply_info* 211285206Sdesconstruct_reply_info_base(struct regional* region, uint16_t flags, size_t qd, 212285206Sdes time_t ttl, time_t prettl, size_t an, size_t ns, size_t ar, 213285206Sdes size_t total, enum sec_status sec); 214285206Sdes 215238106Sdes/** 216238106Sdes * Parse wire query into a queryinfo structure, return 0 on parse error. 217238106Sdes * initialises the (prealloced) queryinfo structure as well. 218238106Sdes * This query structure contains a pointer back info the buffer! 219238106Sdes * This pointer avoids memory allocation. allocqname does memory allocation. 220238106Sdes * @param m: the prealloced queryinfo structure to put query into. 221238106Sdes * must be unused, or _clear()ed. 222238106Sdes * @param query: the wireformat packet query. starts with ID. 223238106Sdes * @return: 0 on format error. 224238106Sdes */ 225269257Sdesint query_info_parse(struct query_info* m, struct sldns_buffer* query); 226238106Sdes 227238106Sdes/** 228238106Sdes * Parse query reply. 229238106Sdes * Fills in preallocated query_info structure (with ptr into buffer). 230238106Sdes * Allocates reply_info and packed_rrsets. These are not yet added to any 231238106Sdes * caches or anything, this is only parsing. Returns formerror on qdcount > 1. 232238106Sdes * @param pkt: the packet buffer. Must be positioned after the query section. 233238106Sdes * @param alloc: creates packed rrset key structures. 234238106Sdes * @param rep: allocated reply_info is returned (only on no error). 235238106Sdes * @param qinf: query_info is returned (only on no error). 236238106Sdes * @param region: where to store temporary data (for parsing). 237238106Sdes * @param edns: where to store edns information, does not need to be inited. 238238106Sdes * @return: zero is OK, or DNS error code in case of error 239238106Sdes * o FORMERR for parse errors. 240238106Sdes * o SERVFAIL for memory allocation errors. 241238106Sdes */ 242269257Sdesint reply_info_parse(struct sldns_buffer* pkt, struct alloc_cache* alloc, 243238106Sdes struct query_info* qinf, struct reply_info** rep, 244238106Sdes struct regional* region, struct edns_data* edns); 245238106Sdes 246238106Sdes/** 247238106Sdes * Allocate and decompress parsed message and rrsets. 248238106Sdes * @param pkt: for name decompression. 249238106Sdes * @param msg: parsed message in scratch region. 250238106Sdes * @param alloc: alloc cache for special rrset key structures. 251238106Sdes * Not used if region!=NULL, it can be NULL in that case. 252238106Sdes * @param qinf: where to store query info. 253238106Sdes * qinf itself is allocated by the caller. 254238106Sdes * @param rep: reply info is allocated and returned. 255238106Sdes * @param region: if this parameter is NULL then malloc and the alloc is used. 256238106Sdes * otherwise, everything is allocated in this region. 257238106Sdes * In a region, no special rrset key structures are needed (not shared), 258238106Sdes * and no rrset_ref array in the reply is built up. 259238106Sdes * @return 0 if allocation failed. 260238106Sdes */ 261269257Sdesint parse_create_msg(struct sldns_buffer* pkt, struct msg_parse* msg, 262238106Sdes struct alloc_cache* alloc, struct query_info* qinf, 263238106Sdes struct reply_info** rep, struct regional* region); 264238106Sdes 265238106Sdes/** 266238106Sdes * Sorts the ref array. 267238106Sdes * @param rep: reply info. rrsets must be filled in. 268238106Sdes */ 269238106Sdesvoid reply_info_sortref(struct reply_info* rep); 270238106Sdes 271238106Sdes/** 272238106Sdes * Set TTLs inside the replyinfo to absolute values. 273238106Sdes * @param rep: reply info. rrsets must be filled in. 274238106Sdes * Also refs must be filled in. 275238106Sdes * @param timenow: the current time. 276238106Sdes */ 277269257Sdesvoid reply_info_set_ttls(struct reply_info* rep, time_t timenow); 278238106Sdes 279238106Sdes/** 280238106Sdes * Delete reply_info and packed_rrsets (while they are not yet added to the 281238106Sdes * hashtables.). Returns rrsets to the alloc cache. 282238106Sdes * @param rep: reply_info to delete. 283238106Sdes * @param alloc: where to return rrset structures to. 284238106Sdes */ 285238106Sdesvoid reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc); 286238106Sdes 287238106Sdes/** 288238106Sdes * Compare two queryinfo structures, on query and type, class. 289238106Sdes * It is _not_ sorted in canonical ordering. 290238106Sdes * @param m1: struct query_info* , void* here to ease use as function pointer. 291238106Sdes * @param m2: struct query_info* , void* here to ease use as function pointer. 292238106Sdes * @return: 0 = same, -1 m1 is smaller, +1 m1 is larger. 293238106Sdes */ 294238106Sdesint query_info_compare(void* m1, void* m2); 295238106Sdes 296238106Sdes/** clear out query info structure */ 297238106Sdesvoid query_info_clear(struct query_info* m); 298238106Sdes 299238106Sdes/** calculate size of struct query_info + reply_info */ 300238106Sdessize_t msgreply_sizefunc(void* k, void* d); 301238106Sdes 302238106Sdes/** delete msgreply_entry key structure */ 303238106Sdesvoid query_entry_delete(void *q, void* arg); 304238106Sdes 305238106Sdes/** delete reply_info data structure */ 306238106Sdesvoid reply_info_delete(void* d, void* arg); 307238106Sdes 308285206Sdes/** calculate hash value of query_info, lowercases the qname, 309285206Sdes * uses CD flag for AAAA qtype */ 310285206Sdeshashvalue_t query_info_hash(struct query_info *q, uint16_t flags); 311238106Sdes 312238106Sdes/** 313238106Sdes * Setup query info entry 314238106Sdes * @param q: query info to copy. Emptied as if clear is called. 315238106Sdes * @param r: reply to init data. 316238106Sdes * @param h: hash value. 317238106Sdes * @return: newly allocated message reply cache item. 318238106Sdes */ 319238106Sdesstruct msgreply_entry* query_info_entrysetup(struct query_info* q, 320238106Sdes struct reply_info* r, hashvalue_t h); 321238106Sdes 322238106Sdes/** 323238106Sdes * Copy reply_info and all rrsets in it and allocate. 324238106Sdes * @param rep: what to copy, probably inside region, no ref[] array in it. 325238106Sdes * @param alloc: how to allocate rrset keys. 326238106Sdes * Not used if region!=NULL, it can be NULL in that case. 327238106Sdes * @param region: if this parameter is NULL then malloc and the alloc is used. 328238106Sdes * otherwise, everything is allocated in this region. 329238106Sdes * In a region, no special rrset key structures are needed (not shared), 330238106Sdes * and no rrset_ref array in the reply is built up. 331238106Sdes * @return new reply info or NULL on memory error. 332238106Sdes */ 333238106Sdesstruct reply_info* reply_info_copy(struct reply_info* rep, 334238106Sdes struct alloc_cache* alloc, struct regional* region); 335238106Sdes 336238106Sdes/** 337238106Sdes * Copy a parsed rrset into given key, decompressing and allocating rdata. 338238106Sdes * @param pkt: packet for decompression 339238106Sdes * @param msg: the parser message (for flags for trust). 340238106Sdes * @param pset: the parsed rrset to copy. 341238106Sdes * @param region: if NULL - malloc, else data is allocated in this region. 342238106Sdes * @param pk: a freshly obtained rrsetkey structure. No dname is set yet, 343238106Sdes * will be set on return. 344238106Sdes * Note that TTL will still be relative on return. 345238106Sdes * @return false on alloc failure. 346238106Sdes */ 347269257Sdesint parse_copy_decompress_rrset(struct sldns_buffer* pkt, struct msg_parse* msg, 348238106Sdes struct rrset_parse *pset, struct regional* region, 349238106Sdes struct ub_packed_rrset_key* pk); 350238106Sdes 351238106Sdes/** 352238106Sdes * Find final cname target in reply, the one matching qinfo. Follows CNAMEs. 353238106Sdes * @param qinfo: what to start with. 354238106Sdes * @param rep: looks in answer section of this message. 355238106Sdes * @return: pointer dname, or NULL if not found. 356238106Sdes */ 357238106Sdesuint8_t* reply_find_final_cname_target(struct query_info* qinfo, 358238106Sdes struct reply_info* rep); 359238106Sdes 360238106Sdes/** 361238106Sdes * Check if cname chain in cached reply is still valid. 362291767Sdes * @param qinfo: query info with query name. 363238106Sdes * @param rep: reply to check. 364238106Sdes * @return: true if valid, false if invalid. 365238106Sdes */ 366291767Sdesint reply_check_cname_chain(struct query_info* qinfo, struct reply_info* rep); 367238106Sdes 368238106Sdes/** 369238106Sdes * Check security status of all RRs in the message. 370238106Sdes * @param rep: reply to check 371238106Sdes * @return: true if all RRs are secure. False if not. 372238106Sdes * True if there are zero RRs. 373238106Sdes */ 374238106Sdesint reply_all_rrsets_secure(struct reply_info* rep); 375238106Sdes 376238106Sdes/** 377238106Sdes * Find answer rrset in reply, the one matching qinfo. Follows CNAMEs, so the 378238106Sdes * result may have a different owner name. 379238106Sdes * @param qinfo: what to look for. 380238106Sdes * @param rep: looks in answer section of this message. 381238106Sdes * @return: pointer to rrset, or NULL if not found. 382238106Sdes */ 383238106Sdesstruct ub_packed_rrset_key* reply_find_answer_rrset(struct query_info* qinfo, 384238106Sdes struct reply_info* rep); 385238106Sdes 386238106Sdes/** 387238106Sdes * Find rrset in reply, inside the answer section. Does not follow CNAMEs. 388238106Sdes * @param rep: looks in answer section of this message. 389238106Sdes * @param name: what to look for. 390238106Sdes * @param namelen: length of name. 391238106Sdes * @param type: looks for (host order). 392238106Sdes * @param dclass: looks for (host order). 393238106Sdes * @return: pointer to rrset, or NULL if not found. 394238106Sdes */ 395238106Sdesstruct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep, 396238106Sdes uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass); 397238106Sdes 398238106Sdes/** 399238106Sdes * Find rrset in reply, inside the authority section. Does not follow CNAMEs. 400238106Sdes * @param rep: looks in authority section of this message. 401238106Sdes * @param name: what to look for. 402238106Sdes * @param namelen: length of name. 403238106Sdes * @param type: looks for (host order). 404238106Sdes * @param dclass: looks for (host order). 405238106Sdes * @return: pointer to rrset, or NULL if not found. 406238106Sdes */ 407238106Sdesstruct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep, 408238106Sdes uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass); 409238106Sdes 410238106Sdes/** 411238106Sdes * Find rrset in reply, inside any section. Does not follow CNAMEs. 412238106Sdes * @param rep: looks in answer,authority and additional section of this message. 413238106Sdes * @param name: what to look for. 414238106Sdes * @param namelen: length of name. 415238106Sdes * @param type: looks for (host order). 416238106Sdes * @param dclass: looks for (host order). 417238106Sdes * @return: pointer to rrset, or NULL if not found. 418238106Sdes */ 419238106Sdesstruct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep, 420238106Sdes uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass); 421238106Sdes 422238106Sdes/** 423238106Sdes * Debug send the query info and reply info to the log in readable form. 424238106Sdes * @param str: descriptive string printed with packet content. 425238106Sdes * @param qinfo: query section. 426238106Sdes * @param rep: rest of message. 427238106Sdes */ 428238106Sdesvoid log_dns_msg(const char* str, struct query_info* qinfo, 429238106Sdes struct reply_info* rep); 430238106Sdes 431238106Sdes/** 432238106Sdes * Print string with neat domain name, type, class from query info. 433238106Sdes * @param v: at what verbosity level to print this. 434238106Sdes * @param str: string of message. 435238106Sdes * @param qinf: query info structure with name, type and class. 436238106Sdes */ 437238106Sdesvoid log_query_info(enum verbosity_value v, const char* str, 438238106Sdes struct query_info* qinf); 439238106Sdes 440238106Sdes#endif /* UTIL_DATA_MSGREPLY_H */ 441