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