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
|
/*
* 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"
enum query_state {
QUERY_PROCESSED,
QUERY_DISCARDED,
QUERY_IN_AXFR
};
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 addr;
#else
struct sockaddr_in addr;
#endif
socklen_t 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;
/* 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 change the RCODE to NXDOMAIN and no longer add
* SOA records to the authority section in case of NXDOMAIN
* and NODATA.
* Also includes number of DNAMES followed.
*/
int cname_count;
/* Used for dname compression. */
uint16_t compressed_dname_count;
domain_type *compressed_dnames[MAXRRSPP];
/*
* 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;
#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);
/*
* 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);
/*
* 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);
/*
* 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);
}
static inline int
query_overflow_nsid(query_type *q, uint16_t nsid_len)
{
return buffer_position(q->packet) > (q->maxlen - q->reserved_space - nsid_len);
}
#endif /* _QUERY_H_ */
|