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 struct ixfr_data; 21 22 enum query_state { 23 QUERY_PROCESSED, 24 QUERY_DISCARDED, 25 QUERY_IN_AXFR, 26 QUERY_IN_IXFR 27 }; 28 typedef enum query_state query_state_type; 29 30 /* Query as we pass it around */ 31 typedef struct query query_type; 32 struct query { 33 /* 34 * Memory region freed whenever the query is reset. 35 */ 36 region_type *region; 37 38 /* 39 * The address the query was received from. 40 */ 41 #ifdef INET6 42 struct sockaddr_storage remote_addr; 43 #else 44 struct sockaddr_in remote_addr; 45 #endif 46 socklen_t remote_addrlen; 47 48 /* if set, the request came through a proxy */ 49 int is_proxied; 50 /* the client address 51 * the same as remote_addr if not proxied */ 52 #ifdef INET6 53 struct sockaddr_storage client_addr; 54 #else 55 struct sockaddr_in client_addr; 56 #endif 57 socklen_t client_addrlen; 58 59 /* 60 * Maximum supported query size. 61 */ 62 size_t maxlen; 63 64 /* 65 * Space reserved for optional records like EDNS. 66 */ 67 size_t reserved_space; 68 69 /* EDNS information provided by the client. */ 70 edns_record_type edns; 71 72 /* TSIG record information and running hash for query-response */ 73 tsig_record_type tsig; 74 /* tsig actions can be overridden, for axfr transfer. */ 75 int tsig_prepare_it, tsig_update_it, tsig_sign_it; 76 77 int tcp; 78 uint16_t tcplen; 79 80 buffer_type *packet; 81 82 /* Normalized query domain name. */ 83 const dname_type *qname; 84 85 /* Query type and class in host byte order. */ 86 uint16_t qtype; 87 uint16_t qclass; 88 89 /* The zone used to answer the query. */ 90 zone_type *zone; 91 92 /* The delegation domain, if any. */ 93 domain_type *delegation_domain; 94 95 /* The delegation NS rrset, if any. */ 96 rrset_type *delegation_rrset; 97 98 /* Original opcode. */ 99 uint8_t opcode; 100 101 /* 102 * The number of CNAMES followed. After a CNAME is followed 103 * we no longer clear AA for a delegation and do not REFUSE 104 * or SERVFAIL if the destination zone of the CNAME does not exist, 105 * or is configured but not present. 106 * Also includes number of DNAMES followed. 107 */ 108 int cname_count; 109 110 /* Used for dname compression. */ 111 uint16_t compressed_dname_count; 112 domain_type **compressed_dnames; 113 114 /* 115 * Indexed by domain->number, index 0 is reserved for the 116 * query name when generated from a wildcard record. 117 */ 118 uint16_t *compressed_dname_offsets; 119 size_t compressed_dname_offsets_size; 120 121 /* number of temporary domains used for the query */ 122 size_t number_temporary_domains; 123 124 /* 125 * Used for AXFR processing. 126 */ 127 int axfr_is_done; 128 zone_type *axfr_zone; 129 domain_type *axfr_current_domain; 130 rrset_type *axfr_current_rrset; 131 uint16_t axfr_current_rr; 132 133 /* Used for IXFR processing, 134 * indicates if the zone transfer is done, connection can close. */ 135 int ixfr_is_done; 136 /* the ixfr data that is processed */ 137 struct ixfr_data* ixfr_data; 138 /* the ixfr data that is the last segment */ 139 struct ixfr_data* ixfr_end_data; 140 /* ixfr count of newsoa bytes added, 0 none, len means done */ 141 size_t ixfr_count_newsoa; 142 /* ixfr count of oldsoa bytes added, 0 none, len means done */ 143 size_t ixfr_count_oldsoa; 144 /* ixfr count of del bytes added, 0 none, len means done */ 145 size_t ixfr_count_del; 146 /* ixfr count of add bytes added, 0 none, len means done */ 147 size_t ixfr_count_add; 148 /* position for the end of SOA record, for UDP truncation */ 149 size_t ixfr_pos_of_newsoa; 150 151 #ifdef RATELIMIT 152 /* if we encountered a wildcard, its domain */ 153 domain_type *wildcard_domain; 154 #endif 155 }; 156 157 158 /* Check if the last write resulted in an overflow. */ 159 static inline int query_overflow(struct query *q); 160 161 /* 162 * Store the offset of the specified domain in the dname compression 163 * table. 164 */ 165 void query_put_dname_offset(struct query *query, 166 domain_type *domain, 167 uint16_t offset); 168 /* 169 * Lookup the offset of the specified domain in the dname compression 170 * table. Offset 0 is used to indicate the domain is not yet in the 171 * compression table. 172 */ 173 static inline 174 uint16_t query_get_dname_offset(struct query *query, domain_type *domain) 175 { 176 return query->compressed_dname_offsets[domain->number]; 177 } 178 179 /* 180 * Remove all compressed dnames that have an offset that points beyond 181 * the end of the current answer. This must be done after some RRs 182 * are truncated and before adding new RRs. Otherwise dnames may be 183 * compressed using truncated data! 184 */ 185 void query_clear_dname_offsets(struct query *query, size_t max_offset); 186 187 /* 188 * Clear the compression tables. 189 */ 190 void query_clear_compression_tables(struct query *query); 191 192 /* 193 * Enter the specified domain into the compression table starting at 194 * the specified offset. 195 */ 196 void query_add_compression_domain(struct query *query, 197 domain_type *domain, 198 uint16_t offset); 199 200 201 /* 202 * Create a new query structure. 203 */ 204 query_type *query_create(region_type *region, 205 uint16_t *compressed_dname_offsets, 206 size_t compressed_dname_size, 207 domain_type **compressed_dnames); 208 209 /* 210 * Reset a query structure so it is ready for receiving and processing 211 * a new query. 212 */ 213 void query_reset(query_type *query, size_t maxlen, int is_tcp); 214 215 /* 216 * Process a query and write the response in the query I/O buffer. 217 */ 218 query_state_type query_process(query_type *q, nsd_type *nsd, uint32_t *now_p); 219 220 /* 221 * Prepare the query structure for writing the response. The packet 222 * data up-to the current packet limit is preserved. This usually 223 * includes the packet header and question section. Space is reserved 224 * for the optional EDNS record, if required. 225 */ 226 void query_prepare_response(query_type *q); 227 228 /* 229 * Add EDNS0 information to the response if required. 230 */ 231 void query_add_optional(query_type *q, nsd_type *nsd, uint32_t *now_p); 232 233 /* 234 * Write an error response into the query structure with the indicated 235 * RCODE. 236 */ 237 query_state_type query_error(query_type *q, nsd_rc_type rcode); 238 239 static inline int 240 query_overflow(query_type *q) 241 { 242 return buffer_position(q->packet) > (q->maxlen - q->reserved_space); 243 } 244 #endif /* QUERY_H */ 245