1238106Sdes/* 2238106Sdes * util/data/msgparse.h - parse wireformat DNS messages. 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 * \file 37238106Sdes * Contains message parsing data structures. 38238106Sdes * These point back into the packet buffer. 39238106Sdes * 40238106Sdes * During parsing RRSIGS are put together with the rrsets they (claim to) sign. 41238106Sdes * This process works as follows: 42238106Sdes * o if RRSIG follows the data rrset, it is added to the rrset rrsig list. 43238106Sdes * o if no matching data rrset is found, the RRSIG becomes a new rrset. 44238106Sdes * o If the data rrset later follows the RRSIG 45238106Sdes * o See if the RRSIG rrset contains multiple types, and needs to 46238106Sdes * have the rrsig(s) for that data type split off. 47238106Sdes * o Put the data rr as data type in the rrset and rrsig in list. 48238106Sdes * o RRSIGs are allowed to move to a different section. The section of 49238106Sdes * the data item is used for the final rrset. 50238106Sdes * o multiple signatures over an RRset are possible. 51238106Sdes * 52238106Sdes * For queries of qtype=RRSIG, some special handling is needed, to avoid 53238106Sdes * splitting the RRSIG in the answer section. 54238106Sdes * o duplicate, not split, RRSIGs from the answer section, if qtype=RRSIG. 55238106Sdes * o check for doubles in the rrsig list when adding an RRSIG to data, 56238106Sdes * so that a data rrset is signed by RRSIGs with different rdata. 57238106Sdes * when qtype=RRSIG. 58238106Sdes * This will move the RRSIG from the answer section to sign the data further 59238106Sdes * in the packet (if possible). If then after that, more RRSIGs are found 60238106Sdes * that sign the data as well, doubles are removed. 61238106Sdes */ 62238106Sdes 63238106Sdes#ifndef UTIL_DATA_MSGPARSE_H 64238106Sdes#define UTIL_DATA_MSGPARSE_H 65238106Sdes#include "util/storage/lruhash.h" 66291767Sdes#include "sldns/pkthdr.h" 67291767Sdes#include "sldns/rrdef.h" 68269257Sdesstruct sldns_buffer; 69238106Sdesstruct rrset_parse; 70238106Sdesstruct rr_parse; 71238106Sdesstruct regional; 72238106Sdes 73238106Sdes/** number of buckets in parse rrset hash table. Must be power of 2. */ 74238106Sdes#define PARSE_TABLE_SIZE 32 75238106Sdes/** Maximum TTL that is allowed. */ 76269257Sdesextern time_t MAX_TTL; 77238106Sdes/** Minimum TTL that is allowed. */ 78269257Sdesextern time_t MIN_TTL; 79291767Sdes/** Maximum Negative TTL that is allowed */ 80291767Sdesextern time_t MAX_NEG_TTL; 81238106Sdes/** Negative cache time (for entries without any RRs.) */ 82238106Sdes#define NORR_TTL 5 /* seconds */ 83238106Sdes 84238106Sdes/** 85238106Sdes * Data stored in scratch pad memory during parsing. 86238106Sdes * Stores the data that will enter into the msgreply and packet result. 87238106Sdes */ 88238106Sdesstruct msg_parse { 89238106Sdes /** id from message, network format. */ 90238106Sdes uint16_t id; 91238106Sdes /** flags from message, host format. */ 92238106Sdes uint16_t flags; 93238106Sdes /** count of RRs, host format */ 94238106Sdes uint16_t qdcount; 95238106Sdes /** count of RRs, host format */ 96238106Sdes uint16_t ancount; 97238106Sdes /** count of RRs, host format */ 98238106Sdes uint16_t nscount; 99238106Sdes /** count of RRs, host format */ 100238106Sdes uint16_t arcount; 101238106Sdes /** count of RRsets per section. */ 102238106Sdes size_t an_rrsets; 103238106Sdes /** count of RRsets per section. */ 104238106Sdes size_t ns_rrsets; 105238106Sdes /** count of RRsets per section. */ 106238106Sdes size_t ar_rrsets; 107238106Sdes /** total number of rrsets found. */ 108238106Sdes size_t rrset_count; 109238106Sdes 110238106Sdes /** query dname (pointer to start location in packet, NULL if none */ 111238106Sdes uint8_t* qname; 112238106Sdes /** length of query dname in octets, 0 if none */ 113238106Sdes size_t qname_len; 114238106Sdes /** query type, host order. 0 if qdcount=0 */ 115238106Sdes uint16_t qtype; 116238106Sdes /** query class, host order. 0 if qdcount=0 */ 117238106Sdes uint16_t qclass; 118238106Sdes 119238106Sdes /** 120238106Sdes * Hash table array used during parsing to lookup rrset types. 121238106Sdes * Based on name, type, class. Same hash value as in rrset cache. 122238106Sdes */ 123238106Sdes struct rrset_parse* hashtable[PARSE_TABLE_SIZE]; 124238106Sdes 125238106Sdes /** linked list of rrsets that have been found (in order). */ 126238106Sdes struct rrset_parse* rrset_first; 127238106Sdes /** last element of rrset list. */ 128238106Sdes struct rrset_parse* rrset_last; 129238106Sdes}; 130238106Sdes 131238106Sdes/** 132238106Sdes * Data stored for an rrset during parsing. 133238106Sdes */ 134238106Sdesstruct rrset_parse { 135238106Sdes /** next in hash bucket */ 136238106Sdes struct rrset_parse* rrset_bucket_next; 137238106Sdes /** next in list of all rrsets */ 138238106Sdes struct rrset_parse* rrset_all_next; 139238106Sdes /** hash value of rrset */ 140238106Sdes hashvalue_t hash; 141238106Sdes /** which section was it found in: one of 142238106Sdes * LDNS_SECTION_ANSWER, LDNS_SECTION_AUTHORITY, LDNS_SECTION_ADDITIONAL 143238106Sdes */ 144269257Sdes sldns_pkt_section section; 145238106Sdes /** start of (possibly compressed) dname in packet */ 146238106Sdes uint8_t* dname; 147238106Sdes /** length of the dname uncompressed wireformat */ 148238106Sdes size_t dname_len; 149238106Sdes /** type, host order. */ 150238106Sdes uint16_t type; 151238106Sdes /** class, network order. var name so that it is not a c++ keyword. */ 152238106Sdes uint16_t rrset_class; 153238106Sdes /** the flags for the rrset, like for packedrrset */ 154238106Sdes uint32_t flags; 155238106Sdes /** number of RRs in the rr list */ 156238106Sdes size_t rr_count; 157238106Sdes /** sum of RR rdata sizes */ 158238106Sdes size_t size; 159238106Sdes /** linked list of RRs in this rrset. */ 160238106Sdes struct rr_parse* rr_first; 161238106Sdes /** last in list of RRs in this rrset. */ 162238106Sdes struct rr_parse* rr_last; 163238106Sdes /** number of RRSIGs over this rrset. */ 164238106Sdes size_t rrsig_count; 165238106Sdes /** linked list of RRsig RRs over this rrset. */ 166238106Sdes struct rr_parse* rrsig_first; 167238106Sdes /** last in list of RRSIG RRs over this rrset. */ 168238106Sdes struct rr_parse* rrsig_last; 169238106Sdes}; 170238106Sdes 171238106Sdes/** 172238106Sdes * Data stored for an RR during parsing. 173238106Sdes */ 174238106Sdesstruct rr_parse { 175238106Sdes /** 176238106Sdes * Pointer to the RR. Points to start of TTL value in the packet. 177238106Sdes * Rdata length and rdata follow it. 178238106Sdes * its dname, type and class are the same and stored for the rrset. 179238106Sdes */ 180238106Sdes uint8_t* ttl_data; 181238106Sdes /** true if ttl_data is not part of the packet, but elsewhere in mem. 182238106Sdes * Set for generated CNAMEs for DNAMEs. */ 183238106Sdes int outside_packet; 184238106Sdes /** the length of the rdata if allocated (with no dname compression)*/ 185238106Sdes size_t size; 186238106Sdes /** next in list of RRs. */ 187238106Sdes struct rr_parse* next; 188238106Sdes}; 189238106Sdes 190238106Sdes/** Check if label length is first octet of a compression pointer, pass u8. */ 191238106Sdes#define LABEL_IS_PTR(x) ( ((x)&0xc0) == 0xc0 ) 192238106Sdes/** Calculate destination offset of a compression pointer. pass first and 193238106Sdes * second octets of the compression pointer. */ 194238106Sdes#define PTR_OFFSET(x, y) ( ((x)&0x3f)<<8 | (y) ) 195238106Sdes/** create a compression pointer to the given offset. */ 196238106Sdes#define PTR_CREATE(offset) ((uint16_t)(0xc000 | (offset))) 197238106Sdes 198238106Sdes/** error codes, extended with EDNS, so > 15. */ 199238106Sdes#define EDNS_RCODE_BADVERS 16 /** bad EDNS version */ 200238106Sdes/** largest valid compression offset */ 201238106Sdes#define PTR_MAX_OFFSET 0x3fff 202238106Sdes 203238106Sdes/** 204238106Sdes * EDNS data storage 205238106Sdes * EDNS rdata is ignored. 206238106Sdes */ 207238106Sdesstruct edns_data { 208238106Sdes /** if EDNS OPT record was present */ 209238106Sdes int edns_present; 210238106Sdes /** Extended RCODE */ 211238106Sdes uint8_t ext_rcode; 212238106Sdes /** The EDNS version number */ 213238106Sdes uint8_t edns_version; 214238106Sdes /** the EDNS bits field from ttl (host order): Z */ 215238106Sdes uint16_t bits; 216238106Sdes /** UDP reassembly size. */ 217238106Sdes uint16_t udp_size; 218238106Sdes}; 219238106Sdes 220238106Sdes/** 221238106Sdes * Obtain size in the packet of an rr type, that is before dname type. 222238106Sdes * Do TYPE_DNAME, and type STR, yourself. Gives size for most regular types. 223238106Sdes * @param rdf: the rdf type from the descriptor. 224238106Sdes * @return: size in octets. 0 on failure. 225238106Sdes */ 226269257Sdessize_t get_rdf_size(sldns_rdf_type rdf); 227238106Sdes 228238106Sdes/** 229238106Sdes * Parse the packet. 230238106Sdes * @param pkt: packet, position at call must be at start of packet. 231238106Sdes * at end position is after packet. 232238106Sdes * @param msg: where to store results. 233238106Sdes * @param region: how to alloc results. 234238106Sdes * @return: 0 if OK, or rcode on error. 235238106Sdes */ 236269257Sdesint parse_packet(struct sldns_buffer* pkt, struct msg_parse* msg, 237238106Sdes struct regional* region); 238238106Sdes 239238106Sdes/** 240238106Sdes * After parsing the packet, extract EDNS data from packet. 241238106Sdes * If not present this is noted in the data structure. 242238106Sdes * If a parse error happens, an error code is returned. 243238106Sdes * 244238106Sdes * Quirks: 245238106Sdes * o ignores OPT rdata. 246238106Sdes * o ignores OPT owner name. 247238106Sdes * o ignores extra OPT records, except the last one in the packet. 248238106Sdes * 249238106Sdes * @param msg: parsed message structure. Modified on exit, if EDNS was present 250238106Sdes * it is removed from the additional section. 251238106Sdes * @param edns: the edns data is stored here. Does not have to be initialised. 252238106Sdes * @return: 0 on success. or an RCODE on an error. 253238106Sdes * RCODE formerr if OPT in wrong section, and so on. 254238106Sdes */ 255238106Sdesint parse_extract_edns(struct msg_parse* msg, struct edns_data* edns); 256238106Sdes 257238106Sdes/** 258238106Sdes * If EDNS data follows a query section, extract it and initialize edns struct. 259238106Sdes * @param pkt: the packet. position at start must be right after the query 260238106Sdes * section. At end, right after EDNS data or no movement if failed. 261238106Sdes * @param edns: the edns data allocated by the caller. Does not have to be 262238106Sdes * initialised. 263238106Sdes * @return: 0 on success, or an RCODE on error. 264238106Sdes * RCODE formerr if OPT is badly formatted and so on. 265238106Sdes */ 266269257Sdesint parse_edns_from_pkt(struct sldns_buffer* pkt, struct edns_data* edns); 267238106Sdes 268238106Sdes/** 269238106Sdes * Calculate hash value for rrset in packet. 270238106Sdes * @param pkt: the packet. 271238106Sdes * @param dname: pointer to uncompressed dname, or compressed dname in packet. 272238106Sdes * @param type: rrset type in host order. 273238106Sdes * @param dclass: rrset class in network order. 274238106Sdes * @param rrset_flags: rrset flags (same as packed_rrset flags). 275238106Sdes * @return hash value 276238106Sdes */ 277269257Sdeshashvalue_t pkt_hash_rrset(struct sldns_buffer* pkt, uint8_t* dname, uint16_t type, 278238106Sdes uint16_t dclass, uint32_t rrset_flags); 279238106Sdes 280238106Sdes/** 281238106Sdes * Lookup in msg hashtable to find a rrset. 282238106Sdes * @param msg: with the hashtable. 283238106Sdes * @param pkt: packet for compressed names. 284238106Sdes * @param h: hash value 285238106Sdes * @param rrset_flags: flags of rrset sought for. 286238106Sdes * @param dname: name of rrset sought for. 287238106Sdes * @param dnamelen: len of dname. 288238106Sdes * @param type: rrset type, host order. 289238106Sdes * @param dclass: rrset class, network order. 290238106Sdes * @return NULL or the rrset_parse if found. 291238106Sdes */ 292238106Sdesstruct rrset_parse* msgparse_hashtable_lookup(struct msg_parse* msg, 293269257Sdes struct sldns_buffer* pkt, hashvalue_t h, uint32_t rrset_flags, 294238106Sdes uint8_t* dname, size_t dnamelen, uint16_t type, uint16_t dclass); 295238106Sdes 296238106Sdes/** 297238106Sdes * Remove rrset from hash table. 298238106Sdes * @param msg: with hashtable. 299238106Sdes * @param rrset: with hash value and id info. 300238106Sdes */ 301238106Sdesvoid msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset); 302238106Sdes 303238106Sdes#endif /* UTIL_DATA_MSGPARSE_H */ 304