1 /* 2 * query.h -- manipulation with the queries 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 #ifndef _QUERY_H_ 11 #define _QUERY_H_ 12 13 #include <assert.h> 14 #include <string.h> 15 16 #include "namedb.h" 17 #include "nsd.h" 18 #include "packet.h" 19 #include "tsig.h" 20 21 enum query_state { 22 QUERY_PROCESSED, 23 QUERY_DISCARDED, 24 QUERY_IN_AXFR 25 }; 26 typedef enum query_state query_state_type; 27 28 /* Query as we pass it around */ 29 typedef struct query query_type; 30 struct query { 31 /* 32 * Memory region freed whenever the query is reset. 33 */ 34 region_type *region; 35 36 /* 37 * The address the query was received from. 38 */ 39 #ifdef INET6 40 struct sockaddr_storage addr; 41 #else 42 struct sockaddr_in addr; 43 #endif 44 socklen_t addrlen; 45 46 /* 47 * Maximum supported query size. 48 */ 49 size_t maxlen; 50 51 /* 52 * Space reserved for optional records like EDNS. 53 */ 54 size_t reserved_space; 55 56 /* EDNS information provided by the client. */ 57 edns_record_type edns; 58 59 /* TSIG record information and running hash for query-response */ 60 tsig_record_type tsig; 61 /* tsig actions can be overridden, for axfr transfer. */ 62 int tsig_prepare_it, tsig_update_it, tsig_sign_it; 63 64 int tcp; 65 uint16_t tcplen; 66 67 buffer_type *packet; 68 69 /* Normalized query domain name. */ 70 const dname_type *qname; 71 72 /* Query type and class in host byte order. */ 73 uint16_t qtype; 74 uint16_t qclass; 75 76 /* The zone used to answer the query. */ 77 zone_type *zone; 78 79 /* The delegation domain, if any. */ 80 domain_type *delegation_domain; 81 82 /* The delegation NS rrset, if any. */ 83 rrset_type *delegation_rrset; 84 85 /* Original opcode. */ 86 uint8_t opcode; 87 88 /* 89 * The number of CNAMES followed. After a CNAME is followed 90 * we no longer change the RCODE to NXDOMAIN and no longer add 91 * SOA records to the authority section in case of NXDOMAIN 92 * and NODATA. 93 * Also includes number of DNAMES followed. 94 */ 95 int cname_count; 96 97 /* Used for dname compression. */ 98 uint16_t compressed_dname_count; 99 domain_type **compressed_dnames; 100 101 /* 102 * Indexed by domain->number, index 0 is reserved for the 103 * query name when generated from a wildcard record. 104 */ 105 uint16_t *compressed_dname_offsets; 106 size_t compressed_dname_offsets_size; 107 108 /* number of temporary domains used for the query */ 109 size_t number_temporary_domains; 110 111 /* 112 * Used for AXFR processing. 113 */ 114 int axfr_is_done; 115 zone_type *axfr_zone; 116 domain_type *axfr_current_domain; 117 rrset_type *axfr_current_rrset; 118 uint16_t axfr_current_rr; 119 120 #ifdef RATELIMIT 121 /* if we encountered a wildcard, its domain */ 122 domain_type *wildcard_domain; 123 #endif 124 }; 125 126 127 /* Check if the last write resulted in an overflow. */ 128 static inline int query_overflow(struct query *q); 129 130 /* 131 * Store the offset of the specified domain in the dname compression 132 * table. 133 */ 134 void query_put_dname_offset(struct query *query, 135 domain_type *domain, 136 uint16_t offset); 137 /* 138 * Lookup the offset of the specified domain in the dname compression 139 * table. Offset 0 is used to indicate the domain is not yet in the 140 * compression table. 141 */ 142 static inline 143 uint16_t query_get_dname_offset(struct query *query, domain_type *domain) 144 { 145 return query->compressed_dname_offsets[domain->number]; 146 } 147 148 /* 149 * Remove all compressed dnames that have an offset that points beyond 150 * the end of the current answer. This must be done after some RRs 151 * are truncated and before adding new RRs. Otherwise dnames may be 152 * compressed using truncated data! 153 */ 154 void query_clear_dname_offsets(struct query *query, size_t max_offset); 155 156 /* 157 * Clear the compression tables. 158 */ 159 void query_clear_compression_tables(struct query *query); 160 161 /* 162 * Enter the specified domain into the compression table starting at 163 * the specified offset. 164 */ 165 void query_add_compression_domain(struct query *query, 166 domain_type *domain, 167 uint16_t offset); 168 169 170 /* 171 * Create a new query structure. 172 */ 173 query_type *query_create(region_type *region, 174 uint16_t *compressed_dname_offsets, 175 size_t compressed_dname_size, 176 domain_type **compressed_dnames); 177 178 /* 179 * Reset a query structure so it is ready for receiving and processing 180 * a new query. 181 */ 182 void query_reset(query_type *query, size_t maxlen, int is_tcp); 183 184 /* 185 * Process a query and write the response in the query I/O buffer. 186 */ 187 query_state_type query_process(query_type *q, nsd_type *nsd); 188 189 /* 190 * Prepare the query structure for writing the response. The packet 191 * data up-to the current packet limit is preserved. This usually 192 * includes the packet header and question section. Space is reserved 193 * for the optional EDNS record, if required. 194 */ 195 void query_prepare_response(query_type *q); 196 197 /* 198 * Add EDNS0 information to the response if required. 199 */ 200 void query_add_optional(query_type *q, nsd_type *nsd); 201 202 /* 203 * Write an error response into the query structure with the indicated 204 * RCODE. 205 */ 206 query_state_type query_error(query_type *q, nsd_rc_type rcode); 207 208 static inline int 209 query_overflow(query_type *q) 210 { 211 return buffer_position(q->packet) > (q->maxlen - q->reserved_space); 212 } 213 #endif /* _QUERY_H_ */ 214