xref: /openbsd/usr.sbin/nsd/query.h (revision b71395ea)
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