xref: /openbsd-src/usr.sbin/nsd/query.h (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
1 /*
2  * query.h -- manipulation with the queries
3  *
4  * Copyright (c) 2001-2011, 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 domain used to answer the query.  */
80 	domain_type *domain;
81 
82 	/* The delegation domain, if any.  */
83 	domain_type *delegation_domain;
84 
85 	/* The delegation NS rrset, if any.  */
86 	rrset_type *delegation_rrset;
87 
88 	/* Original opcode.  */
89 	uint8_t opcode;
90 
91 	/*
92 	 * The number of CNAMES followed.  After a CNAME is followed
93 	 * we no longer change the RCODE to NXDOMAIN and no longer add
94 	 * SOA records to the authority section in case of NXDOMAIN
95 	 * and NODATA.
96 	 * Also includes number of DNAMES followed.
97 	 */
98 	int cname_count;
99 
100 	/* Used for dname compression.  */
101 	uint16_t     compressed_dname_count;
102 	domain_type *compressed_dnames[MAXRRSPP];
103 
104 	 /*
105 	  * Indexed by domain->number, index 0 is reserved for the
106 	  * query name when generated from a wildcard record.
107 	  */
108 	uint16_t    *compressed_dname_offsets;
109 	uint32_t compressed_dname_offsets_size;
110 
111 	/* number of temporary domains used for the query */
112 	uint32_t number_temporary_domains;
113 
114 	/*
115 	 * Used for AXFR processing.
116 	 */
117 	int          axfr_is_done;
118 	zone_type   *axfr_zone;
119 	domain_type *axfr_current_domain;
120 	rrset_type  *axfr_current_rrset;
121 	uint16_t     axfr_current_rr;
122 };
123 
124 
125 /* Check if the last write resulted in an overflow.  */
126 static inline int query_overflow(struct query *q);
127 
128 /*
129  * Store the offset of the specified domain in the dname compression
130  * table.
131  */
132 void query_put_dname_offset(struct query *query,
133 			    domain_type  *domain,
134 			    uint16_t      offset);
135 /*
136  * Lookup the offset of the specified domain in the dname compression
137  * table.  Offset 0 is used to indicate the domain is not yet in the
138  * compression table.
139  */
140 static inline
141 uint16_t query_get_dname_offset(struct query *query, domain_type *domain)
142 {
143 	return query->compressed_dname_offsets[domain->number];
144 }
145 
146 /*
147  * Remove all compressed dnames that have an offset that points beyond
148  * the end of the current answer.  This must be done after some RRs
149  * are truncated and before adding new RRs.  Otherwise dnames may be
150  * compressed using truncated data!
151  */
152 void query_clear_dname_offsets(struct query *query, size_t max_offset);
153 
154 /*
155  * Clear the compression tables.
156  */
157 void query_clear_compression_tables(struct query *query);
158 
159 /*
160  * Enter the specified domain into the compression table starting at
161  * the specified offset.
162  */
163 void query_add_compression_domain(struct query *query,
164 				  domain_type  *domain,
165 				  uint16_t      offset);
166 
167 
168 /*
169  * Create a new query structure.
170  */
171 query_type *query_create(region_type *region,
172 			 uint16_t *compressed_dname_offsets,
173 			 uint32_t compressed_dname_size);
174 
175 /*
176  * Reset a query structure so it is ready for receiving and processing
177  * a new query.
178  */
179 void query_reset(query_type *query, size_t maxlen, int is_tcp);
180 
181 /*
182  * Process a query and write the response in the query I/O buffer.
183  */
184 query_state_type query_process(query_type *q, nsd_type *nsd);
185 
186 /*
187  * Prepare the query structure for writing the response. The packet
188  * data up-to the current packet limit is preserved. This usually
189  * includes the packet header and question section. Space is reserved
190  * for the optional EDNS record, if required.
191  */
192 void query_prepare_response(query_type *q);
193 
194 /*
195  * Add EDNS0 information to the response if required.
196  */
197 void query_add_optional(query_type *q, nsd_type *nsd);
198 
199 /*
200  * Write an error response into the query structure with the indicated
201  * RCODE.
202  */
203 query_state_type query_error(query_type *q, nsd_rc_type rcode);
204 
205 static inline int
206 query_overflow(query_type *q)
207 {
208 	return buffer_position(q->packet) > (q->maxlen - q->reserved_space);
209 }
210 static inline int
211 query_overflow_nsid(query_type *q, uint16_t nsid_len)
212 {
213         return buffer_position(q->packet) > (q->maxlen - q->reserved_space - nsid_len);
214 }
215 #endif /* _QUERY_H_ */
216