xref: /openbsd-src/usr.sbin/nsd/query.h (revision b71395ea3d4830c6fd338870b804059761b8292d)
162ac0c33Sjakob /*
262ac0c33Sjakob  * query.h -- manipulation with the queries
362ac0c33Sjakob  *
4d3fecca9Ssthen  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
562ac0c33Sjakob  *
662ac0c33Sjakob  * See LICENSE for the license.
762ac0c33Sjakob  *
862ac0c33Sjakob  */
962ac0c33Sjakob 
103efee2e1Sflorian #ifndef QUERY_H
113efee2e1Sflorian #define QUERY_H
1262ac0c33Sjakob 
1362ac0c33Sjakob #include <assert.h>
1462ac0c33Sjakob #include <string.h>
1562ac0c33Sjakob 
1662ac0c33Sjakob #include "namedb.h"
1762ac0c33Sjakob #include "nsd.h"
1862ac0c33Sjakob #include "packet.h"
1962ac0c33Sjakob #include "tsig.h"
204564029fSflorian struct ixfr_data;
2162ac0c33Sjakob 
2262ac0c33Sjakob enum query_state {
2362ac0c33Sjakob 	QUERY_PROCESSED,
2462ac0c33Sjakob 	QUERY_DISCARDED,
254564029fSflorian 	QUERY_IN_AXFR,
264564029fSflorian 	QUERY_IN_IXFR
2762ac0c33Sjakob };
2862ac0c33Sjakob typedef enum query_state query_state_type;
2962ac0c33Sjakob 
3062ac0c33Sjakob /* Query as we pass it around */
3162ac0c33Sjakob typedef struct query query_type;
3262ac0c33Sjakob struct query {
3362ac0c33Sjakob 	/*
3462ac0c33Sjakob 	 * Memory region freed whenever the query is reset.
3562ac0c33Sjakob 	 */
3662ac0c33Sjakob 	region_type *region;
3762ac0c33Sjakob 
3862ac0c33Sjakob 	/*
3962ac0c33Sjakob 	 * The address the query was received from.
4062ac0c33Sjakob 	 */
4162ac0c33Sjakob #ifdef INET6
42*b71395eaSflorian 	struct sockaddr_storage remote_addr;
4362ac0c33Sjakob #else
44*b71395eaSflorian 	struct sockaddr_in remote_addr;
4562ac0c33Sjakob #endif
46*b71395eaSflorian 	socklen_t remote_addrlen;
47*b71395eaSflorian 
48*b71395eaSflorian 	/* if set, the request came through a proxy */
49*b71395eaSflorian 	int is_proxied;
50*b71395eaSflorian 	/* the client address
51*b71395eaSflorian 	 * the same as remote_addr if not proxied */
52*b71395eaSflorian #ifdef INET6
53*b71395eaSflorian 	struct sockaddr_storage client_addr;
54*b71395eaSflorian #else
55*b71395eaSflorian 	struct sockaddr_in client_addr;
56*b71395eaSflorian #endif
57*b71395eaSflorian 	socklen_t client_addrlen;
5862ac0c33Sjakob 
5962ac0c33Sjakob 	/*
6062ac0c33Sjakob 	 * Maximum supported query size.
6162ac0c33Sjakob 	 */
6262ac0c33Sjakob 	size_t maxlen;
6362ac0c33Sjakob 
6462ac0c33Sjakob 	/*
6562ac0c33Sjakob 	 * Space reserved for optional records like EDNS.
6662ac0c33Sjakob 	 */
6762ac0c33Sjakob 	size_t reserved_space;
6862ac0c33Sjakob 
6962ac0c33Sjakob 	/* EDNS information provided by the client.  */
7062ac0c33Sjakob 	edns_record_type edns;
7162ac0c33Sjakob 
7262ac0c33Sjakob 	/* TSIG record information and running hash for query-response */
7362ac0c33Sjakob 	tsig_record_type tsig;
7462ac0c33Sjakob 	/* tsig actions can be overridden, for axfr transfer. */
7562ac0c33Sjakob 	int tsig_prepare_it, tsig_update_it, tsig_sign_it;
7662ac0c33Sjakob 
7762ac0c33Sjakob 	int tcp;
7862ac0c33Sjakob 	uint16_t tcplen;
7962ac0c33Sjakob 
8062ac0c33Sjakob 	buffer_type *packet;
8162ac0c33Sjakob 
8262ac0c33Sjakob 	/* Normalized query domain name.  */
8362ac0c33Sjakob 	const dname_type *qname;
8462ac0c33Sjakob 
8562ac0c33Sjakob 	/* Query type and class in host byte order.  */
8662ac0c33Sjakob 	uint16_t qtype;
8762ac0c33Sjakob 	uint16_t qclass;
8862ac0c33Sjakob 
8962ac0c33Sjakob 	/* The zone used to answer the query.  */
9062ac0c33Sjakob 	zone_type *zone;
9162ac0c33Sjakob 
9262ac0c33Sjakob 	/* The delegation domain, if any.  */
9362ac0c33Sjakob 	domain_type *delegation_domain;
9462ac0c33Sjakob 
9562ac0c33Sjakob 	/* The delegation NS rrset, if any.  */
9662ac0c33Sjakob 	rrset_type *delegation_rrset;
9762ac0c33Sjakob 
9862ac0c33Sjakob 	/* Original opcode.  */
9962ac0c33Sjakob 	uint8_t opcode;
10062ac0c33Sjakob 
10162ac0c33Sjakob 	/*
10262ac0c33Sjakob 	 * The number of CNAMES followed.  After a CNAME is followed
103977db6e5Sflorian 	 * we no longer clear AA for a delegation and do not REFUSE
104977db6e5Sflorian 	 * or SERVFAIL if the destination zone of the CNAME does not exist,
105977db6e5Sflorian 	 * or is configured but not present.
10662ac0c33Sjakob 	 * Also includes number of DNAMES followed.
10762ac0c33Sjakob 	 */
10862ac0c33Sjakob 	int cname_count;
10962ac0c33Sjakob 
11062ac0c33Sjakob 	/* Used for dname compression.  */
11162ac0c33Sjakob 	uint16_t     compressed_dname_count;
112bfd0b123Sflorian 	domain_type **compressed_dnames;
11362ac0c33Sjakob 
11462ac0c33Sjakob 	 /*
11562ac0c33Sjakob 	  * Indexed by domain->number, index 0 is reserved for the
11662ac0c33Sjakob 	  * query name when generated from a wildcard record.
11762ac0c33Sjakob 	  */
11862ac0c33Sjakob 	uint16_t    *compressed_dname_offsets;
119d3fecca9Ssthen 	size_t compressed_dname_offsets_size;
12062ac0c33Sjakob 
12162ac0c33Sjakob 	/* number of temporary domains used for the query */
122d3fecca9Ssthen 	size_t number_temporary_domains;
12362ac0c33Sjakob 
12462ac0c33Sjakob 	/*
12562ac0c33Sjakob 	 * Used for AXFR processing.
12662ac0c33Sjakob 	 */
12762ac0c33Sjakob 	int          axfr_is_done;
12862ac0c33Sjakob 	zone_type   *axfr_zone;
12962ac0c33Sjakob 	domain_type *axfr_current_domain;
13062ac0c33Sjakob 	rrset_type  *axfr_current_rrset;
13162ac0c33Sjakob 	uint16_t     axfr_current_rr;
1322c1ae072Ssthen 
1334564029fSflorian 	/* Used for IXFR processing,
1344564029fSflorian 	 * indicates if the zone transfer is done, connection can close. */
1354564029fSflorian 	int ixfr_is_done;
1364564029fSflorian 	/* the ixfr data that is processed */
1374564029fSflorian 	struct ixfr_data* ixfr_data;
1384564029fSflorian 	/* the ixfr data that is the last segment */
1394564029fSflorian 	struct ixfr_data* ixfr_end_data;
1404564029fSflorian 	/* ixfr count of newsoa bytes added, 0 none, len means done */
1414564029fSflorian 	size_t ixfr_count_newsoa;
1424564029fSflorian 	/* ixfr count of oldsoa bytes added, 0 none, len means done */
1434564029fSflorian 	size_t ixfr_count_oldsoa;
1444564029fSflorian 	/* ixfr count of del bytes added, 0 none, len means done */
1454564029fSflorian 	size_t ixfr_count_del;
1464564029fSflorian 	/* ixfr count of add bytes added, 0 none, len means done */
1474564029fSflorian 	size_t ixfr_count_add;
1484564029fSflorian 	/* position for the end of SOA record, for UDP truncation */
1494564029fSflorian 	size_t ixfr_pos_of_newsoa;
1504564029fSflorian 
1512c1ae072Ssthen #ifdef RATELIMIT
1522c1ae072Ssthen 	/* if we encountered a wildcard, its domain */
1532c1ae072Ssthen 	domain_type *wildcard_domain;
1542c1ae072Ssthen #endif
15562ac0c33Sjakob };
15662ac0c33Sjakob 
15762ac0c33Sjakob 
15862ac0c33Sjakob /* Check if the last write resulted in an overflow.  */
15962ac0c33Sjakob static inline int query_overflow(struct query *q);
16062ac0c33Sjakob 
16162ac0c33Sjakob /*
16262ac0c33Sjakob  * Store the offset of the specified domain in the dname compression
16362ac0c33Sjakob  * table.
16462ac0c33Sjakob  */
16562ac0c33Sjakob void query_put_dname_offset(struct query *query,
16662ac0c33Sjakob 			    domain_type  *domain,
16762ac0c33Sjakob 			    uint16_t      offset);
16862ac0c33Sjakob /*
16962ac0c33Sjakob  * Lookup the offset of the specified domain in the dname compression
17062ac0c33Sjakob  * table.  Offset 0 is used to indicate the domain is not yet in the
17162ac0c33Sjakob  * compression table.
17262ac0c33Sjakob  */
17362ac0c33Sjakob static inline
query_get_dname_offset(struct query * query,domain_type * domain)17462ac0c33Sjakob uint16_t query_get_dname_offset(struct query *query, domain_type *domain)
17562ac0c33Sjakob {
17662ac0c33Sjakob 	return query->compressed_dname_offsets[domain->number];
17762ac0c33Sjakob }
17862ac0c33Sjakob 
17962ac0c33Sjakob /*
18062ac0c33Sjakob  * Remove all compressed dnames that have an offset that points beyond
18162ac0c33Sjakob  * the end of the current answer.  This must be done after some RRs
18262ac0c33Sjakob  * are truncated and before adding new RRs.  Otherwise dnames may be
18362ac0c33Sjakob  * compressed using truncated data!
18462ac0c33Sjakob  */
18562ac0c33Sjakob void query_clear_dname_offsets(struct query *query, size_t max_offset);
18662ac0c33Sjakob 
18762ac0c33Sjakob /*
18862ac0c33Sjakob  * Clear the compression tables.
18962ac0c33Sjakob  */
19062ac0c33Sjakob void query_clear_compression_tables(struct query *query);
19162ac0c33Sjakob 
19262ac0c33Sjakob /*
19362ac0c33Sjakob  * Enter the specified domain into the compression table starting at
19462ac0c33Sjakob  * the specified offset.
19562ac0c33Sjakob  */
19662ac0c33Sjakob void query_add_compression_domain(struct query *query,
19762ac0c33Sjakob 				  domain_type  *domain,
19862ac0c33Sjakob 				  uint16_t      offset);
19962ac0c33Sjakob 
20062ac0c33Sjakob 
20162ac0c33Sjakob /*
20262ac0c33Sjakob  * Create a new query structure.
20362ac0c33Sjakob  */
20462ac0c33Sjakob query_type *query_create(region_type *region,
20562ac0c33Sjakob 			 uint16_t *compressed_dname_offsets,
206bfd0b123Sflorian 			 size_t compressed_dname_size,
207bfd0b123Sflorian 			 domain_type **compressed_dnames);
20862ac0c33Sjakob 
20962ac0c33Sjakob /*
21062ac0c33Sjakob  * Reset a query structure so it is ready for receiving and processing
21162ac0c33Sjakob  * a new query.
21262ac0c33Sjakob  */
21362ac0c33Sjakob void query_reset(query_type *query, size_t maxlen, int is_tcp);
21462ac0c33Sjakob 
21562ac0c33Sjakob /*
21662ac0c33Sjakob  * Process a query and write the response in the query I/O buffer.
21762ac0c33Sjakob  */
218063644e9Sflorian query_state_type query_process(query_type *q, nsd_type *nsd, uint32_t *now_p);
21962ac0c33Sjakob 
22062ac0c33Sjakob /*
22162ac0c33Sjakob  * Prepare the query structure for writing the response. The packet
22262ac0c33Sjakob  * data up-to the current packet limit is preserved. This usually
22362ac0c33Sjakob  * includes the packet header and question section. Space is reserved
22462ac0c33Sjakob  * for the optional EDNS record, if required.
22562ac0c33Sjakob  */
226c1e73312Sflorian void query_prepare_response(query_type *q);
22762ac0c33Sjakob 
22862ac0c33Sjakob /*
22962ac0c33Sjakob  * Add EDNS0 information to the response if required.
23062ac0c33Sjakob  */
231063644e9Sflorian void query_add_optional(query_type *q, nsd_type *nsd, uint32_t *now_p);
23262ac0c33Sjakob 
23362ac0c33Sjakob /*
23462ac0c33Sjakob  * Write an error response into the query structure with the indicated
23562ac0c33Sjakob  * RCODE.
23662ac0c33Sjakob  */
23762ac0c33Sjakob query_state_type query_error(query_type *q, nsd_rc_type rcode);
23862ac0c33Sjakob 
23962ac0c33Sjakob static inline int
query_overflow(query_type * q)24062ac0c33Sjakob query_overflow(query_type *q)
24162ac0c33Sjakob {
24262ac0c33Sjakob 	return buffer_position(q->packet) > (q->maxlen - q->reserved_space);
24362ac0c33Sjakob }
2443efee2e1Sflorian #endif /* QUERY_H */
245