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
query_get_dname_offset(struct query * query,domain_type * domain)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
query_overflow(query_type * q)240 query_overflow(query_type *q)
241 {
242 return buffer_position(q->packet) > (q->maxlen - q->reserved_space);
243 }
244 #endif /* QUERY_H */
245