msgreply.h revision 307729
1251876Speter/* 2251876Speter * util/data/msgreply.h - store message and reply data. 3251876Speter * 4251876Speter * Copyright (c) 2007, NLnet Labs. All rights reserved. 5251876Speter * 6251876Speter * This software is open source. 7251876Speter * 8251876Speter * Redistribution and use in source and binary forms, with or without 9251876Speter * modification, are permitted provided that the following conditions 10251876Speter * are met: 11251876Speter * 12251876Speter * Redistributions of source code must retain the above copyright notice, 13251876Speter * this list of conditions and the following disclaimer. 14251876Speter * 15251876Speter * Redistributions in binary form must reproduce the above copyright notice, 16251876Speter * this list of conditions and the following disclaimer in the documentation 17251876Speter * and/or other materials provided with the distribution. 18251876Speter * 19251876Speter * Neither the name of the NLNET LABS nor the names of its contributors may 20251876Speter * be used to endorse or promote products derived from this software without 21251876Speter * specific prior written permission. 22251876Speter * 23251876Speter * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24251876Speter * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25251876Speter * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26251876Speter * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27251876Speter * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28251876Speter * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29251876Speter * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30251876Speter * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31251876Speter * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32251876Speter * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33251876Speter * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34251876Speter */ 35251876Speter 36251876Speter/** 37251876Speter * \file 38251876Speter * 39251876Speter * This file contains a data structure to store a message and its reply. 40251876Speter */ 41251876Speter 42251876Speter#ifndef UTIL_DATA_MSGREPLY_H 43251876Speter#define UTIL_DATA_MSGREPLY_H 44251876Speter#include "util/storage/lruhash.h" 45251876Speter#include "util/data/packed_rrset.h" 46251876Speterstruct sldns_buffer; 47251876Speterstruct comm_reply; 48251876Speterstruct alloc_cache; 49251876Speterstruct iovec; 50251876Speterstruct regional; 51251876Speterstruct edns_data; 52251876Speterstruct msg_parse; 53251876Speterstruct rrset_parse; 54251876Speter 55251876Speter/** calculate the prefetch TTL as 90% of original. Calculation 56251876Speter * without numerical overflow (uin32_t) */ 57251876Speter#define PREFETCH_TTL_CALC(ttl) ((ttl) - (ttl)/10) 58251876Speter 59251876Speter/** 60251876Speter * Structure to store query information that makes answers to queries 61251876Speter * different. 62251876Speter */ 63251876Speterstruct query_info { 64251876Speter /** 65251876Speter * Salient data on the query: qname, in wireformat. 66251876Speter * can be allocated or a pointer to outside buffer. 67251876Speter * User has to keep track on the status of this. 68251876Speter */ 69251876Speter uint8_t* qname; 70251876Speter /** length of qname (including last 0 octet) */ 71251876Speter size_t qname_len; 72251876Speter /** qtype, host byte order */ 73251876Speter uint16_t qtype; 74251876Speter /** qclass, host byte order */ 75251876Speter uint16_t qclass; 76251876Speter}; 77251876Speter 78251876Speter/** 79251876Speter * Information to reference an rrset 80251876Speter */ 81251876Speterstruct rrset_ref { 82251876Speter /** the key with lock, and ptr to packed data. */ 83251876Speter struct ub_packed_rrset_key* key; 84251876Speter /** id needed */ 85251876Speter rrset_id_t id; 86251876Speter}; 87251876Speter 88251876Speter/** 89251876Speter * Structure to store DNS query and the reply packet. 90251876Speter * To use it, copy over the flags from reply and modify using flags from 91251876Speter * the query (RD,CD if not AA). prepend ID. 92251876Speter * 93251876Speter * Memory layout is: 94251876Speter * o struct 95251876Speter * o rrset_ref array 96251876Speter * o packed_rrset_key* array. 97251876Speter * 98251876Speter * Memory layout is sometimes not packed, when the message is synthesized, 99251876Speter * for easy of the generation. It is allocated packed when it is copied 100251876Speter * from the region allocation to the malloc allocation. 101251876Speter */ 102251876Speterstruct reply_info { 103251876Speter /** the flags for the answer, host byte order. */ 104251876Speter uint16_t flags; 105251876Speter 106251876Speter /** 107251876Speter * This flag informs unbound the answer is authoritative and 108251876Speter * the AA flag should be preserved. 109251876Speter */ 110251876Speter uint8_t authoritative; 111251876Speter 112251876Speter /** 113251876Speter * Number of RRs in the query section. 114251876Speter * If qdcount is not 0, then it is 1, and the data that appears 115251876Speter * in the reply is the same as the query_info. 116251876Speter * Host byte order. 117251876Speter */ 118251876Speter uint8_t qdcount; 119251876Speter 120251876Speter /** 32 bit padding to pad struct member alignment to 64 bits. */ 121251876Speter uint32_t padding; 122251876Speter 123251876Speter /** 124251876Speter * TTL of the entire reply (for negative caching). 125251876Speter * only for use when there are 0 RRsets in this message. 126251876Speter * if there are RRsets, check those instead. 127251876Speter */ 128251876Speter time_t ttl; 129251876Speter 130251876Speter /** 131251876Speter * TTL for prefetch. After it has expired, a prefetch is suitable. 132251876Speter * Smaller than the TTL, otherwise the prefetch would not happen. 133251876Speter */ 134251876Speter time_t prefetch_ttl; 135251876Speter 136251876Speter /** 137251876Speter * The security status from DNSSEC validation of this message. 138251876Speter */ 139251876Speter enum sec_status security; 140251876Speter 141251876Speter /** 142251876Speter * Number of RRsets in each section. 143251876Speter * The answer section. Add up the RRs in every RRset to calculate 144251876Speter * the number of RRs, and the count for the dns packet. 145251876Speter * The number of RRs in RRsets can change due to RRset updates. 146251876Speter */ 147251876Speter size_t an_numrrsets; 148251876Speter 149251876Speter /** Count of authority section RRsets */ 150251876Speter size_t ns_numrrsets; 151251876Speter /** Count of additional section RRsets */ 152251876Speter size_t ar_numrrsets; 153251876Speter 154251876Speter /** number of RRsets: an_numrrsets + ns_numrrsets + ar_numrrsets */ 155251876Speter size_t rrset_count; 156251876Speter 157251876Speter /** 158251876Speter * List of pointers (only) to the rrsets in the order in which 159251876Speter * they appear in the reply message. 160251876Speter * Number of elements is ancount+nscount+arcount RRsets. 161251876Speter * This is a pointer to that array. 162251876Speter * Use the accessor function for access. 163251876Speter */ 164251876Speter struct ub_packed_rrset_key** rrsets; 165251876Speter 166251876Speter /** 167251876Speter * Packed array of ids (see counts) and pointers to packed_rrset_key. 168251876Speter * The number equals ancount+nscount+arcount RRsets. 169251876Speter * These are sorted in ascending pointer, the locking order. So 170251876Speter * this list can be locked (and id, ttl checked), to see if 171251876Speter * all the data is available and recent enough. 172251876Speter * 173251876Speter * This is defined as an array of size 1, so that the compiler 174251876Speter * associates the identifier with this position in the structure. 175251876Speter * Array bound overflow on this array then gives access to the further 176251876Speter * elements of the array, which are allocated after the main structure. 177251876Speter * 178251876Speter * It could be more pure to define as array of size 0, ref[0]. 179251876Speter * But ref[1] may be less confusing for compilers. 180251876Speter * Use the accessor function for access. 181251876Speter */ 182251876Speter struct rrset_ref ref[1]; 183251876Speter}; 184251876Speter 185251876Speter/** 186251876Speter * Structure to keep hash table entry for message replies. 187251876Speter */ 188251876Speterstruct msgreply_entry { 189251876Speter /** the hash table key */ 190251876Speter struct query_info key; 191251876Speter /** the hash table entry, data is struct reply_info* */ 192251876Speter struct lruhash_entry entry; 193251876Speter}; 194251876Speter 195251876Speter/** 196251876Speter * Constructor for replyinfo. 197251876Speter * @param region: where to allocate the results, pass NULL to use malloc. 198251876Speter * @param flags: flags for the replyinfo. 199251876Speter * @param qd: qd count 200251876Speter * @param ttl: TTL of replyinfo 201251876Speter * @param prettl: prefetch ttl 202251876Speter * @param an: an count 203251876Speter * @param ns: ns count 204251876Speter * @param ar: ar count 205251876Speter * @param total: total rrset count (presumably an+ns+ar). 206251876Speter * @param sec: security status of the reply info. 207251876Speter * @return the reply_info base struct with the array for putting the rrsets 208251876Speter * in. The array has been zeroed. Returns NULL on malloc failure. 209251876Speter */ 210251876Speterstruct reply_info* 211251876Speterconstruct_reply_info_base(struct regional* region, uint16_t flags, size_t qd, 212251876Speter time_t ttl, time_t prettl, size_t an, size_t ns, size_t ar, 213251876Speter size_t total, enum sec_status sec); 214251876Speter 215251876Speter/** 216251876Speter * Parse wire query into a queryinfo structure, return 0 on parse error. 217251876Speter * initialises the (prealloced) queryinfo structure as well. 218251876Speter * This query structure contains a pointer back info the buffer! 219251876Speter * This pointer avoids memory allocation. allocqname does memory allocation. 220251876Speter * @param m: the prealloced queryinfo structure to put query into. 221251876Speter * must be unused, or _clear()ed. 222251876Speter * @param query: the wireformat packet query. starts with ID. 223251876Speter * @return: 0 on format error. 224251876Speter */ 225251876Speterint query_info_parse(struct query_info* m, struct sldns_buffer* query); 226251876Speter 227251876Speter/** 228251876Speter * Parse query reply. 229251876Speter * Fills in preallocated query_info structure (with ptr into buffer). 230251876Speter * Allocates reply_info and packed_rrsets. These are not yet added to any 231251876Speter * caches or anything, this is only parsing. Returns formerror on qdcount > 1. 232251876Speter * @param pkt: the packet buffer. Must be positioned after the query section. 233251876Speter * @param alloc: creates packed rrset key structures. 234251876Speter * @param rep: allocated reply_info is returned (only on no error). 235251876Speter * @param qinf: query_info is returned (only on no error). 236251876Speter * @param region: where to store temporary data (for parsing). 237251876Speter * @param edns: where to store edns information, does not need to be inited. 238251876Speter * @return: zero is OK, or DNS error code in case of error 239251876Speter * o FORMERR for parse errors. 240251876Speter * o SERVFAIL for memory allocation errors. 241251876Speter */ 242251876Speterint reply_info_parse(struct sldns_buffer* pkt, struct alloc_cache* alloc, 243251876Speter struct query_info* qinf, struct reply_info** rep, 244251876Speter struct regional* region, struct edns_data* edns); 245251876Speter 246251876Speter/** 247251876Speter * Allocate and decompress parsed message and rrsets. 248251876Speter * @param pkt: for name decompression. 249251876Speter * @param msg: parsed message in scratch region. 250251876Speter * @param alloc: alloc cache for special rrset key structures. 251251876Speter * Not used if region!=NULL, it can be NULL in that case. 252251876Speter * @param qinf: where to store query info. 253251876Speter * qinf itself is allocated by the caller. 254251876Speter * @param rep: reply info is allocated and returned. 255251876Speter * @param region: if this parameter is NULL then malloc and the alloc is used. 256251876Speter * otherwise, everything is allocated in this region. 257251876Speter * In a region, no special rrset key structures are needed (not shared), 258251876Speter * and no rrset_ref array in the reply is built up. 259251876Speter * @return 0 if allocation failed. 260251876Speter */ 261251876Speterint parse_create_msg(struct sldns_buffer* pkt, struct msg_parse* msg, 262251876Speter struct alloc_cache* alloc, struct query_info* qinf, 263251876Speter struct reply_info** rep, struct regional* region); 264251876Speter 265251876Speter/** 266251876Speter * Sorts the ref array. 267251876Speter * @param rep: reply info. rrsets must be filled in. 268251876Speter */ 269251876Spetervoid reply_info_sortref(struct reply_info* rep); 270251876Speter 271251876Speter/** 272251876Speter * Set TTLs inside the replyinfo to absolute values. 273251876Speter * @param rep: reply info. rrsets must be filled in. 274251876Speter * Also refs must be filled in. 275251876Speter * @param timenow: the current time. 276251876Speter */ 277251876Spetervoid reply_info_set_ttls(struct reply_info* rep, time_t timenow); 278251876Speter 279251876Speter/** 280251876Speter * Delete reply_info and packed_rrsets (while they are not yet added to the 281251876Speter * hashtables.). Returns rrsets to the alloc cache. 282251876Speter * @param rep: reply_info to delete. 283251876Speter * @param alloc: where to return rrset structures to. 284251876Speter */ 285251876Spetervoid reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc); 286251876Speter 287251876Speter/** 288251876Speter * Compare two queryinfo structures, on query and type, class. 289251876Speter * It is _not_ sorted in canonical ordering. 290251876Speter * @param m1: struct query_info* , void* here to ease use as function pointer. 291251876Speter * @param m2: struct query_info* , void* here to ease use as function pointer. 292251876Speter * @return: 0 = same, -1 m1 is smaller, +1 m1 is larger. 293251876Speter */ 294251876Speterint query_info_compare(void* m1, void* m2); 295251876Speter 296251876Speter/** clear out query info structure */ 297251876Spetervoid query_info_clear(struct query_info* m); 298251876Speter 299251876Speter/** calculate size of struct query_info + reply_info */ 300251876Spetersize_t msgreply_sizefunc(void* k, void* d); 301251876Speter 302251876Speter/** delete msgreply_entry key structure */ 303251876Spetervoid query_entry_delete(void *q, void* arg); 304251876Speter 305251876Speter/** delete reply_info data structure */ 306251876Spetervoid reply_info_delete(void* d, void* arg); 307251876Speter 308251876Speter/** calculate hash value of query_info, lowercases the qname, 309251876Speter * uses CD flag for AAAA qtype */ 310251876Speterhashvalue_t query_info_hash(struct query_info *q, uint16_t flags); 311251876Speter 312251876Speter/** 313251876Speter * Setup query info entry 314251876Speter * @param q: query info to copy. Emptied as if clear is called. 315251876Speter * @param r: reply to init data. 316251876Speter * @param h: hash value. 317251876Speter * @return: newly allocated message reply cache item. 318251876Speter */ 319251876Speterstruct msgreply_entry* query_info_entrysetup(struct query_info* q, 320251876Speter struct reply_info* r, hashvalue_t h); 321251876Speter 322251876Speter/** 323251876Speter * Copy reply_info and all rrsets in it and allocate. 324251876Speter * @param rep: what to copy, probably inside region, no ref[] array in it. 325251876Speter * @param alloc: how to allocate rrset keys. 326251876Speter * Not used if region!=NULL, it can be NULL in that case. 327251876Speter * @param region: if this parameter is NULL then malloc and the alloc is used. 328251876Speter * otherwise, everything is allocated in this region. 329251876Speter * In a region, no special rrset key structures are needed (not shared), 330251876Speter * and no rrset_ref array in the reply is built up. 331251876Speter * @return new reply info or NULL on memory error. 332251876Speter */ 333251876Speterstruct reply_info* reply_info_copy(struct reply_info* rep, 334251876Speter struct alloc_cache* alloc, struct regional* region); 335251876Speter 336251876Speter/** 337251876Speter * Copy a parsed rrset into given key, decompressing and allocating rdata. 338251876Speter * @param pkt: packet for decompression 339251876Speter * @param msg: the parser message (for flags for trust). 340251876Speter * @param pset: the parsed rrset to copy. 341251876Speter * @param region: if NULL - malloc, else data is allocated in this region. 342251876Speter * @param pk: a freshly obtained rrsetkey structure. No dname is set yet, 343251876Speter * will be set on return. 344251876Speter * Note that TTL will still be relative on return. 345251876Speter * @return false on alloc failure. 346251876Speter */ 347251876Speterint parse_copy_decompress_rrset(struct sldns_buffer* pkt, struct msg_parse* msg, 348251876Speter struct rrset_parse *pset, struct regional* region, 349251876Speter struct ub_packed_rrset_key* pk); 350251876Speter 351251876Speter/** 352251876Speter * Find final cname target in reply, the one matching qinfo. Follows CNAMEs. 353251876Speter * @param qinfo: what to start with. 354251876Speter * @param rep: looks in answer section of this message. 355251876Speter * @return: pointer dname, or NULL if not found. 356251876Speter */ 357251876Speteruint8_t* reply_find_final_cname_target(struct query_info* qinfo, 358251876Speter struct reply_info* rep); 359251876Speter 360251876Speter/** 361251876Speter * Check if cname chain in cached reply is still valid. 362251876Speter * @param qinfo: query info with query name. 363251876Speter * @param rep: reply to check. 364251876Speter * @return: true if valid, false if invalid. 365251876Speter */ 366251876Speterint reply_check_cname_chain(struct query_info* qinfo, struct reply_info* rep); 367251876Speter 368251876Speter/** 369251876Speter * Check security status of all RRs in the message. 370251876Speter * @param rep: reply to check 371251876Speter * @return: true if all RRs are secure. False if not. 372251876Speter * True if there are zero RRs. 373251876Speter */ 374251876Speterint reply_all_rrsets_secure(struct reply_info* rep); 375251876Speter 376251876Speter/** 377251876Speter * Find answer rrset in reply, the one matching qinfo. Follows CNAMEs, so the 378251876Speter * result may have a different owner name. 379251876Speter * @param qinfo: what to look for. 380251876Speter * @param rep: looks in answer section of this message. 381251876Speter * @return: pointer to rrset, or NULL if not found. 382251876Speter */ 383251876Speterstruct ub_packed_rrset_key* reply_find_answer_rrset(struct query_info* qinfo, 384251876Speter struct reply_info* rep); 385251876Speter 386251876Speter/** 387251876Speter * Find rrset in reply, inside the answer section. Does not follow CNAMEs. 388251876Speter * @param rep: looks in answer section of this message. 389251876Speter * @param name: what to look for. 390251876Speter * @param namelen: length of name. 391251876Speter * @param type: looks for (host order). 392251876Speter * @param dclass: looks for (host order). 393251876Speter * @return: pointer to rrset, or NULL if not found. 394251876Speter */ 395251876Speterstruct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep, 396251876Speter uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass); 397251876Speter 398251876Speter/** 399251876Speter * Find rrset in reply, inside the authority section. Does not follow CNAMEs. 400251876Speter * @param rep: looks in authority section of this message. 401251876Speter * @param name: what to look for. 402251876Speter * @param namelen: length of name. 403251876Speter * @param type: looks for (host order). 404251876Speter * @param dclass: looks for (host order). 405251876Speter * @return: pointer to rrset, or NULL if not found. 406251876Speter */ 407251876Speterstruct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep, 408251876Speter uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass); 409251876Speter 410251876Speter/** 411251876Speter * Find rrset in reply, inside any section. Does not follow CNAMEs. 412251876Speter * @param rep: looks in answer,authority and additional section of this message. 413251876Speter * @param name: what to look for. 414251876Speter * @param namelen: length of name. 415251876Speter * @param type: looks for (host order). 416251876Speter * @param dclass: looks for (host order). 417251876Speter * @return: pointer to rrset, or NULL if not found. 418251876Speter */ 419251876Speterstruct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep, 420251876Speter uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass); 421251876Speter 422251876Speter/** 423251876Speter * Debug send the query info and reply info to the log in readable form. 424251876Speter * @param str: descriptive string printed with packet content. 425251876Speter * @param qinfo: query section. 426251876Speter * @param rep: rest of message. 427251876Speter */ 428251876Spetervoid log_dns_msg(const char* str, struct query_info* qinfo, 429251876Speter struct reply_info* rep); 430251876Speter 431251876Speter/** 432251876Speter * Print string with neat domain name, type, class from query info. 433251876Speter * @param v: at what verbosity level to print this. 434251876Speter * @param str: string of message. 435251876Speter * @param qinf: query info structure with name, type and class. 436251876Speter */ 437251876Spetervoid log_query_info(enum verbosity_value v, const char* str, 438251876Speter struct query_info* qinf); 439251876Speter 440251876Speter/** 441251876Speter * Append edns option to edns data structure 442251876Speter */ 443251876Speterint edns_opt_append(struct edns_data* edns, struct regional* region, 444251876Speter uint16_t code, size_t len, uint8_t* data); 445251876Speter 446251876Speter/** 447251876Speter * Find edns option in edns list 448251876Speter * @param list: list of edns options (eg. edns.opt_list) 449251876Speter * @param code: opt code to find. 450251876Speter * @return NULL or the edns_option element. 451251876Speter */ 452251876Speterstruct edns_option* edns_opt_find(struct edns_option* list, uint16_t code); 453251876Speter 454251876Speter/** 455251876Speter * Transform edns data structure from query structure into reply structure. 456251876Speter * In place transform, for errors and cache replies. 457251876Speter * @param edns: on input contains the edns from the query. On output contains 458251876Speter * the edns for the answer. Add new options to the opt_list to put them 459251876Speter * in the answer (allocated in the region, with edns_opt_append). 460251876Speter * @param region: to allocate stuff in. 461251876Speter * @return false on failure (servfail to client, or for some error encodings, 462251876Speter * no EDNS options in the answer). 463251876Speter */ 464251876Speterint edns_opt_inplace_reply(struct edns_data* edns, struct regional* region); 465251876Speter 466251876Speter/** 467251876Speter * Copy edns option list allocated to the new region 468251876Speter */ 469251876Speterstruct edns_option* edns_opt_copy_region(struct edns_option* list, 470251876Speter struct regional* region); 471251876Speter 472251876Speter/** 473251876Speter * Copy edns option list allocated with malloc 474251876Speter */ 475251876Speterstruct edns_option* edns_opt_copy_alloc(struct edns_option* list); 476251876Speter 477251876Speter/** 478251876Speter * Free edns option list allocated with malloc 479251876Speter */ 480251876Spetervoid edns_opt_list_free(struct edns_option* list); 481251876Speter 482251876Speter/** 483251876Speter * Compare an edns option. (not entire list). Also compares contents. 484251876Speter */ 485251876Speterint edns_opt_compare(struct edns_option* p, struct edns_option* q); 486251876Speter 487251876Speter/** 488251876Speter * Compare edns option lists, also the order and contents of edns-options. 489251876Speter */ 490251876Speterint edns_opt_list_compare(struct edns_option* p, struct edns_option* q); 491251876Speter 492251876Speter#endif /* UTIL_DATA_MSGREPLY_H */ 493251876Speter