1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
|
/*
* query.h -- manipulation with the queries
*
* Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
*
* See LICENSE for the license.
*
*/
#ifndef QUERY_H
#define QUERY_H
#include <assert.h>
#include <string.h>
#include "namedb.h"
#include "nsd.h"
#include "packet.h"
#include "tsig.h"
struct ixfr_data;
enum query_state {
QUERY_PROCESSED,
QUERY_DISCARDED,
QUERY_IN_AXFR,
QUERY_IN_IXFR
};
typedef enum query_state query_state_type;
/* Query as we pass it around */
typedef struct query query_type;
struct query {
/*
* Memory region freed whenever the query is reset.
*/
region_type *region;
/*
* The address the query was received from.
*/
#ifdef INET6
struct sockaddr_storage remote_addr;
#else
struct sockaddr_in remote_addr;
#endif
socklen_t remote_addrlen;
/* if set, the request came through a proxy */
int is_proxied;
/* the client address
* the same as remote_addr if not proxied */
#ifdef INET6
struct sockaddr_storage client_addr;
#else
struct sockaddr_in client_addr;
#endif
socklen_t client_addrlen;
/*
* Maximum supported query size.
*/
size_t maxlen;
/*
* Space reserved for optional records like EDNS.
*/
size_t reserved_space;
/* EDNS information provided by the client. */
edns_record_type edns;
/* TSIG record information and running hash for query-response */
tsig_record_type tsig;
/* tsig actions can be overridden, for axfr transfer. */
int tsig_prepare_it, tsig_update_it, tsig_sign_it;
int tcp;
uint16_t tcplen;
buffer_type *packet;
#ifdef HAVE_SSL
/*
* TLS objects.
*/
SSL* tls;
SSL* tls_auth;
char* cert_cn;
#endif
/* Normalized query domain name. */
const dname_type *qname;
/* Query type and class in host byte order. */
uint16_t qtype;
uint16_t qclass;
/* The zone used to answer the query. */
zone_type *zone;
/* The delegation domain, if any. */
domain_type *delegation_domain;
/* The delegation NS rrset, if any. */
rrset_type *delegation_rrset;
/* Original opcode. */
uint8_t opcode;
/*
* The number of CNAMES followed. After a CNAME is followed
* we no longer clear AA for a delegation and do not REFUSE
* or SERVFAIL if the destination zone of the CNAME does not exist,
* or is configured but not present.
* Also includes number of DNAMES followed.
*/
int cname_count;
/* Used for dname compression. */
uint16_t compressed_dname_count;
domain_type **compressed_dnames;
/*
* Indexed by domain->number, index 0 is reserved for the
* query name when generated from a wildcard record.
*/
uint16_t *compressed_dname_offsets;
size_t compressed_dname_offsets_size;
/* number of temporary domains used for the query */
size_t number_temporary_domains;
/*
* Used for AXFR processing.
*/
int axfr_is_done;
zone_type *axfr_zone;
domain_type *axfr_current_domain;
rrset_type *axfr_current_rrset;
uint16_t axfr_current_rr;
/* Used for IXFR processing,
* indicates if the zone transfer is done, connection can close. */
int ixfr_is_done;
/* the ixfr data that is processed */
struct ixfr_data* ixfr_data;
/* the ixfr data that is the last segment */
struct ixfr_data* ixfr_end_data;
/* ixfr count of newsoa bytes added, 0 none, len means done */
size_t ixfr_count_newsoa;
/* ixfr count of oldsoa bytes added, 0 none, len means done */
size_t ixfr_count_oldsoa;
/* ixfr count of del bytes added, 0 none, len means done */
size_t ixfr_count_del;
/* ixfr count of add bytes added, 0 none, len means done */
size_t ixfr_count_add;
/* position for the end of SOA record, for UDP truncation */
size_t ixfr_pos_of_newsoa;
#ifdef RATELIMIT
/* if we encountered a wildcard, its domain */
domain_type *wildcard_domain;
#endif
};
/* Check if the last write resulted in an overflow. */
static inline int query_overflow(struct query *q);
/*
* Store the offset of the specified domain in the dname compression
* table.
*/
void query_put_dname_offset(struct query *query,
domain_type *domain,
uint16_t offset);
/*
* Lookup the offset of the specified domain in the dname compression
* table. Offset 0 is used to indicate the domain is not yet in the
* compression table.
*/
static inline
uint16_t query_get_dname_offset(struct query *query, domain_type *domain)
{
return query->compressed_dname_offsets[domain->number];
}
/*
* Remove all compressed dnames that have an offset that points beyond
* the end of the current answer. This must be done after some RRs
* are truncated and before adding new RRs. Otherwise dnames may be
* compressed using truncated data!
*/
void query_clear_dname_offsets(struct query *query, size_t max_offset);
/*
* Clear the compression tables.
*/
void query_clear_compression_tables(struct query *query);
/*
* Enter the specified domain into the compression table starting at
* the specified offset.
*/
void query_add_compression_domain(struct query *query,
domain_type *domain,
uint16_t offset);
/*
* Create a new query structure.
*/
query_type *query_create(region_type *region,
uint16_t *compressed_dname_offsets,
size_t compressed_dname_size,
domain_type **compressed_dnames);
/*
* Create a new query structure with buffer pointing to existing memory.
*/
query_type *query_create_with_buffer(region_type *region,
uint16_t *compressed_dname_offsets,
size_t compressed_dname_size,
domain_type **compressed_dnames,
struct buffer *buffer);
/*
* Replace the query's buffer data.
*/
void query_set_buffer_data(query_type *q, void *data, size_t data_capacity);
/*
* Reset a query structure so it is ready for receiving and processing
* a new query.
*/
void query_reset(query_type *query, size_t maxlen, int is_tcp);
/*
* Process a query and write the response in the query I/O buffer.
*/
query_state_type query_process(query_type *q, nsd_type *nsd, uint32_t *now_p);
/*
* Prepare the query structure for writing the response. The packet
* data up-to the current packet limit is preserved. This usually
* includes the packet header and question section. Space is reserved
* for the optional EDNS record, if required.
*/
void query_prepare_response(query_type *q);
/*
* Add EDNS0 information to the response if required.
*/
void query_add_optional(query_type *q, nsd_type *nsd, uint32_t *now_p);
/*
* Write an error response into the query structure with the indicated
* RCODE.
*/
query_state_type query_error(query_type *q, nsd_rc_type rcode);
static inline int
query_overflow(query_type *q)
{
return buffer_position(q->packet) > (q->maxlen - q->reserved_space);
}
#endif /* QUERY_H */
|