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