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