xref: /netbsd/external/bsd/nsd/dist/query.h (revision 66a1527d)
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