162ac0c33Sjakob /*
262ac0c33Sjakob * query.c -- nsd(8) the resolver.
362ac0c33Sjakob *
4dd5b221eSsthen * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
562ac0c33Sjakob *
662ac0c33Sjakob * See LICENSE for the license.
762ac0c33Sjakob *
862ac0c33Sjakob */
962ac0c33Sjakob
10d11a62c8Ssthen #include "config.h"
1162ac0c33Sjakob
1262ac0c33Sjakob #include <sys/types.h>
1362ac0c33Sjakob #include <sys/socket.h>
1462ac0c33Sjakob #include <netinet/in.h>
1562ac0c33Sjakob #include <arpa/inet.h>
1662ac0c33Sjakob #include <assert.h>
1762ac0c33Sjakob #include <ctype.h>
1862ac0c33Sjakob #include <errno.h>
1962ac0c33Sjakob #include <limits.h>
2062ac0c33Sjakob #include <stddef.h>
2162ac0c33Sjakob #include <stdio.h>
2262ac0c33Sjakob #include <stdlib.h>
2362ac0c33Sjakob #include <string.h>
2462ac0c33Sjakob #include <time.h>
2562ac0c33Sjakob #include <unistd.h>
2662ac0c33Sjakob #include <netdb.h>
2762ac0c33Sjakob
2862ac0c33Sjakob #include "answer.h"
2962ac0c33Sjakob #include "axfr.h"
3062ac0c33Sjakob #include "dns.h"
3162ac0c33Sjakob #include "dname.h"
3262ac0c33Sjakob #include "nsd.h"
3362ac0c33Sjakob #include "namedb.h"
3462ac0c33Sjakob #include "query.h"
3562ac0c33Sjakob #include "util.h"
3662ac0c33Sjakob #include "options.h"
3762ac0c33Sjakob #include "nsec3.h"
3862ac0c33Sjakob #include "tsig.h"
3962ac0c33Sjakob
4062ac0c33Sjakob /* [Bug #253] Adding unnecessary NS RRset may lead to undesired truncation.
41f72b2965Sjakob * This function determines if the final response packet needs the NS RRset
42f72b2965Sjakob * included. Currently, it will only return negative if QTYPE == DNSKEY|DS.
43f72b2965Sjakob * This way, resolvers won't fallback to TCP unnecessarily when priming
44f72b2965Sjakob * trust anchors.
4562ac0c33Sjakob */
4662ac0c33Sjakob static int answer_needs_ns(struct query *query);
4762ac0c33Sjakob
4862ac0c33Sjakob static int add_rrset(struct query *query,
4962ac0c33Sjakob answer_type *answer,
5062ac0c33Sjakob rr_section_type section,
5162ac0c33Sjakob domain_type *owner,
5262ac0c33Sjakob rrset_type *rrset);
5362ac0c33Sjakob
5462ac0c33Sjakob static void answer_authoritative(struct nsd *nsd,
5562ac0c33Sjakob struct query *q,
5662ac0c33Sjakob answer_type *answer,
57dd5b221eSsthen size_t domain_number,
5862ac0c33Sjakob int exact,
5962ac0c33Sjakob domain_type *closest_match,
6062ac0c33Sjakob domain_type *closest_encloser,
6162ac0c33Sjakob const dname_type *qname);
6262ac0c33Sjakob
6362ac0c33Sjakob static void answer_lookup_zone(struct nsd *nsd, struct query *q,
64dd5b221eSsthen answer_type *answer, size_t domain_number,
6562ac0c33Sjakob int exact, domain_type *closest_match,
6662ac0c33Sjakob domain_type *closest_encloser,
6762ac0c33Sjakob const dname_type *qname);
6862ac0c33Sjakob
6962ac0c33Sjakob void
query_put_dname_offset(struct query * q,domain_type * domain,uint16_t offset)7062ac0c33Sjakob query_put_dname_offset(struct query *q, domain_type *domain, uint16_t offset)
7162ac0c33Sjakob {
7262ac0c33Sjakob assert(q);
7362ac0c33Sjakob assert(domain);
7462ac0c33Sjakob assert(domain->number > 0);
7562ac0c33Sjakob
7662ac0c33Sjakob if (offset > MAX_COMPRESSION_OFFSET)
7762ac0c33Sjakob return;
7862ac0c33Sjakob if (q->compressed_dname_count >= MAX_COMPRESSED_DNAMES)
7962ac0c33Sjakob return;
8062ac0c33Sjakob
8162ac0c33Sjakob q->compressed_dname_offsets[domain->number] = offset;
8262ac0c33Sjakob q->compressed_dnames[q->compressed_dname_count] = domain;
8362ac0c33Sjakob ++q->compressed_dname_count;
8462ac0c33Sjakob }
8562ac0c33Sjakob
8662ac0c33Sjakob void
query_clear_dname_offsets(struct query * q,size_t max_offset)8762ac0c33Sjakob query_clear_dname_offsets(struct query *q, size_t max_offset)
8862ac0c33Sjakob {
8962ac0c33Sjakob while (q->compressed_dname_count > 0
9062ac0c33Sjakob && (q->compressed_dname_offsets[q->compressed_dnames[q->compressed_dname_count - 1]->number]
9162ac0c33Sjakob >= max_offset))
9262ac0c33Sjakob {
9362ac0c33Sjakob q->compressed_dname_offsets[q->compressed_dnames[q->compressed_dname_count - 1]->number] = 0;
9462ac0c33Sjakob --q->compressed_dname_count;
9562ac0c33Sjakob }
9662ac0c33Sjakob }
9762ac0c33Sjakob
9862ac0c33Sjakob void
query_clear_compression_tables(struct query * q)9962ac0c33Sjakob query_clear_compression_tables(struct query *q)
10062ac0c33Sjakob {
10162ac0c33Sjakob uint16_t i;
10262ac0c33Sjakob
10362ac0c33Sjakob for (i = 0; i < q->compressed_dname_count; ++i) {
10462ac0c33Sjakob assert(q->compressed_dnames);
10562ac0c33Sjakob q->compressed_dname_offsets[q->compressed_dnames[i]->number] = 0;
10662ac0c33Sjakob }
10762ac0c33Sjakob q->compressed_dname_count = 0;
10862ac0c33Sjakob }
10962ac0c33Sjakob
11062ac0c33Sjakob void
query_add_compression_domain(struct query * q,domain_type * domain,uint16_t offset)11162ac0c33Sjakob query_add_compression_domain(struct query *q, domain_type *domain, uint16_t offset)
11262ac0c33Sjakob {
11362ac0c33Sjakob while (domain->parent) {
11462ac0c33Sjakob DEBUG(DEBUG_NAME_COMPRESSION, 2,
11562ac0c33Sjakob (LOG_INFO, "query dname: %s, number: %lu, offset: %u\n",
116dd5b221eSsthen domain_to_string(domain),
11762ac0c33Sjakob (unsigned long) domain->number,
11862ac0c33Sjakob offset));
11962ac0c33Sjakob query_put_dname_offset(q, domain, offset);
12062ac0c33Sjakob offset += label_length(dname_name(domain_dname(domain))) + 1;
12162ac0c33Sjakob domain = domain->parent;
12262ac0c33Sjakob }
12362ac0c33Sjakob }
12462ac0c33Sjakob
12562ac0c33Sjakob /*
12662ac0c33Sjakob * Generate an error response with the specified RCODE.
12762ac0c33Sjakob */
12862ac0c33Sjakob query_state_type
query_error(struct query * q,nsd_rc_type rcode)12962ac0c33Sjakob query_error (struct query *q, nsd_rc_type rcode)
13062ac0c33Sjakob {
13162ac0c33Sjakob if (rcode == NSD_RC_DISCARD) {
13262ac0c33Sjakob return QUERY_DISCARDED;
13362ac0c33Sjakob }
13462ac0c33Sjakob
13562ac0c33Sjakob buffer_clear(q->packet);
13662ac0c33Sjakob
13762ac0c33Sjakob QR_SET(q->packet); /* This is an answer. */
138e3d8a0a5Ssthen AD_CLR(q->packet);
13962ac0c33Sjakob RCODE_SET(q->packet, (int) rcode); /* Error code. */
14062ac0c33Sjakob
14162ac0c33Sjakob /* Truncate the question as well... */
14262ac0c33Sjakob QDCOUNT_SET(q->packet, 0);
14362ac0c33Sjakob ANCOUNT_SET(q->packet, 0);
14462ac0c33Sjakob NSCOUNT_SET(q->packet, 0);
14562ac0c33Sjakob ARCOUNT_SET(q->packet, 0);
14662ac0c33Sjakob buffer_set_position(q->packet, QHEADERSZ);
14762ac0c33Sjakob return QUERY_PROCESSED;
14862ac0c33Sjakob }
14962ac0c33Sjakob
1508d8f1862Ssthen static int
query_ratelimit_err(nsd_type * nsd)1518d8f1862Ssthen query_ratelimit_err(nsd_type* nsd)
1528d8f1862Ssthen {
1538d8f1862Ssthen time_t now = time(NULL);
1548d8f1862Ssthen if(nsd->err_limit_time == now) {
1558d8f1862Ssthen /* see if limit is exceeded for this second */
1568d8f1862Ssthen if(nsd->err_limit_count++ > ERROR_RATELIMIT)
1578d8f1862Ssthen return 1;
1588d8f1862Ssthen } else {
1598d8f1862Ssthen /* new second, new limits */
1608d8f1862Ssthen nsd->err_limit_time = now;
1618d8f1862Ssthen nsd->err_limit_count = 1;
1628d8f1862Ssthen }
1638d8f1862Ssthen return 0;
1648d8f1862Ssthen }
1658d8f1862Ssthen
16662ac0c33Sjakob static query_state_type
query_formerr(struct query * query,nsd_type * nsd)1678d8f1862Ssthen query_formerr (struct query *query, nsd_type* nsd)
16862ac0c33Sjakob {
16962ac0c33Sjakob int opcode = OPCODE(query->packet);
1708d8f1862Ssthen if(query_ratelimit_err(nsd))
1718d8f1862Ssthen return QUERY_DISCARDED;
17262ac0c33Sjakob FLAGS_SET(query->packet, FLAGS(query->packet) & 0x0100U);
17362ac0c33Sjakob /* Preserve the RD flag. Clear the rest. */
17462ac0c33Sjakob OPCODE_SET(query->packet, opcode);
17562ac0c33Sjakob return query_error(query, NSD_RC_FORMAT);
17662ac0c33Sjakob }
17762ac0c33Sjakob
17862ac0c33Sjakob static void
query_cleanup(void * data)17962ac0c33Sjakob query_cleanup(void *data)
18062ac0c33Sjakob {
18162ac0c33Sjakob query_type *query = (query_type *) data;
18262ac0c33Sjakob region_destroy(query->region);
18362ac0c33Sjakob }
18462ac0c33Sjakob
18562ac0c33Sjakob query_type *
query_create(region_type * region,uint16_t * compressed_dname_offsets,size_t compressed_dname_size,domain_type ** compressed_dnames)18662ac0c33Sjakob query_create(region_type *region, uint16_t *compressed_dname_offsets,
187bfd0b123Sflorian size_t compressed_dname_size, domain_type **compressed_dnames)
18862ac0c33Sjakob {
18962ac0c33Sjakob query_type *query
19062ac0c33Sjakob = (query_type *) region_alloc_zero(region, sizeof(query_type));
19162ac0c33Sjakob /* create region with large block size, because the initial chunk
19262ac0c33Sjakob saves many mallocs in the server */
19362ac0c33Sjakob query->region = region_create_custom(xalloc, free, 16384, 16384/8, 32, 0);
19462ac0c33Sjakob query->compressed_dname_offsets = compressed_dname_offsets;
195bfd0b123Sflorian query->compressed_dnames = compressed_dnames;
19662ac0c33Sjakob query->packet = buffer_create(region, QIOBUFSZ);
19762ac0c33Sjakob region_add_cleanup(region, query_cleanup, query);
19862ac0c33Sjakob query->compressed_dname_offsets_size = compressed_dname_size;
19962ac0c33Sjakob tsig_create_record(&query->tsig, region);
20062ac0c33Sjakob query->tsig_prepare_it = 1;
20162ac0c33Sjakob query->tsig_update_it = 1;
20262ac0c33Sjakob query->tsig_sign_it = 1;
20362ac0c33Sjakob return query;
20462ac0c33Sjakob }
20562ac0c33Sjakob
20662ac0c33Sjakob void
query_reset(query_type * q,size_t maxlen,int is_tcp)20762ac0c33Sjakob query_reset(query_type *q, size_t maxlen, int is_tcp)
20862ac0c33Sjakob {
20962ac0c33Sjakob /*
21062ac0c33Sjakob * As long as less than 4Kb (region block size) has been used,
21162ac0c33Sjakob * this call to free_all is free, the block is saved for re-use,
21262ac0c33Sjakob * so no malloc() or free() calls are done.
21362ac0c33Sjakob * at present use of the region is for:
21462ac0c33Sjakob * o query qname dname_type (255 max).
21562ac0c33Sjakob * o wildcard expansion domain_type (7*ptr+u32+2bytes)+(5*ptr nsec3)
21662ac0c33Sjakob * o wildcard expansion for additional section domain_type.
21762ac0c33Sjakob * o nsec3 hashed name(s) (3 dnames for a nonexist_proof,
21862ac0c33Sjakob * one proof per wildcard and for nx domain).
21962ac0c33Sjakob */
22062ac0c33Sjakob region_free_all(q->region);
221b71395eaSflorian q->remote_addrlen = (socklen_t)sizeof(q->remote_addr);
222b71395eaSflorian q->client_addrlen = (socklen_t)sizeof(q->client_addr);
223b71395eaSflorian q->is_proxied = 0;
22462ac0c33Sjakob q->maxlen = maxlen;
22562ac0c33Sjakob q->reserved_space = 0;
22662ac0c33Sjakob buffer_clear(q->packet);
22762ac0c33Sjakob edns_init_record(&q->edns);
22862ac0c33Sjakob tsig_init_record(&q->tsig, NULL, NULL);
22962ac0c33Sjakob q->tsig_prepare_it = 1;
23062ac0c33Sjakob q->tsig_update_it = 1;
23162ac0c33Sjakob q->tsig_sign_it = 1;
23262ac0c33Sjakob q->tcp = is_tcp;
23362ac0c33Sjakob q->qname = NULL;
23462ac0c33Sjakob q->qtype = 0;
23562ac0c33Sjakob q->qclass = 0;
23662ac0c33Sjakob q->zone = NULL;
23762ac0c33Sjakob q->opcode = 0;
23862ac0c33Sjakob q->cname_count = 0;
23962ac0c33Sjakob q->delegation_domain = NULL;
24062ac0c33Sjakob q->delegation_rrset = NULL;
24162ac0c33Sjakob q->compressed_dname_count = 0;
24262ac0c33Sjakob q->number_temporary_domains = 0;
24362ac0c33Sjakob
24462ac0c33Sjakob q->axfr_is_done = 0;
24562ac0c33Sjakob q->axfr_zone = NULL;
24662ac0c33Sjakob q->axfr_current_domain = NULL;
24762ac0c33Sjakob q->axfr_current_rrset = NULL;
24862ac0c33Sjakob q->axfr_current_rr = 0;
24975343be4Ssthen
2504564029fSflorian q->ixfr_is_done = 0;
2514564029fSflorian q->ixfr_data = NULL;
2524564029fSflorian q->ixfr_count_newsoa = 0;
2534564029fSflorian q->ixfr_count_oldsoa = 0;
2544564029fSflorian q->ixfr_count_del = 0;
2554564029fSflorian q->ixfr_count_add = 0;
2564564029fSflorian
25775343be4Ssthen #ifdef RATELIMIT
25875343be4Ssthen q->wildcard_domain = NULL;
25975343be4Ssthen #endif
26062ac0c33Sjakob }
26162ac0c33Sjakob
26262ac0c33Sjakob /* get a temporary domain number (or 0=failure) */
26362ac0c33Sjakob static domain_type*
query_get_tempdomain(struct query * q)26462ac0c33Sjakob query_get_tempdomain(struct query *q)
26562ac0c33Sjakob {
26662ac0c33Sjakob static domain_type d[EXTRA_DOMAIN_NUMBERS];
26762ac0c33Sjakob if(q->number_temporary_domains >= EXTRA_DOMAIN_NUMBERS)
26862ac0c33Sjakob return 0;
26962ac0c33Sjakob q->number_temporary_domains ++;
27062ac0c33Sjakob memset(&d[q->number_temporary_domains-1], 0, sizeof(domain_type));
27162ac0c33Sjakob d[q->number_temporary_domains-1].number = q->compressed_dname_offsets_size +
27262ac0c33Sjakob q->number_temporary_domains - 1;
27362ac0c33Sjakob return &d[q->number_temporary_domains-1];
27462ac0c33Sjakob }
27562ac0c33Sjakob
27662ac0c33Sjakob static void
query_addtxt(struct query * q,const uint8_t * dname,uint16_t klass,uint32_t ttl,const char * txt)27762ac0c33Sjakob query_addtxt(struct query *q,
27862ac0c33Sjakob const uint8_t *dname,
27962ac0c33Sjakob uint16_t klass,
28062ac0c33Sjakob uint32_t ttl,
28162ac0c33Sjakob const char *txt)
28262ac0c33Sjakob {
28362ac0c33Sjakob size_t txt_length = strlen(txt);
28462ac0c33Sjakob uint8_t len = (uint8_t) txt_length;
28562ac0c33Sjakob
28662ac0c33Sjakob assert(txt_length <= UCHAR_MAX);
28762ac0c33Sjakob
28862ac0c33Sjakob /* Add the dname */
28962ac0c33Sjakob if (dname >= buffer_begin(q->packet)
29062ac0c33Sjakob && dname <= buffer_current(q->packet))
29162ac0c33Sjakob {
29262ac0c33Sjakob buffer_write_u16(q->packet,
29362ac0c33Sjakob 0xc000 | (dname - buffer_begin(q->packet)));
29462ac0c33Sjakob } else {
29562ac0c33Sjakob buffer_write(q->packet, dname + 1, *dname);
29662ac0c33Sjakob }
29762ac0c33Sjakob
29862ac0c33Sjakob buffer_write_u16(q->packet, TYPE_TXT);
29962ac0c33Sjakob buffer_write_u16(q->packet, klass);
30062ac0c33Sjakob buffer_write_u32(q->packet, ttl);
30162ac0c33Sjakob buffer_write_u16(q->packet, len + 1);
30262ac0c33Sjakob buffer_write_u8(q->packet, len);
30362ac0c33Sjakob buffer_write(q->packet, txt, len);
30462ac0c33Sjakob }
30562ac0c33Sjakob
30662ac0c33Sjakob /*
30762ac0c33Sjakob * Parse the question section of a query. The normalized query name
30862ac0c33Sjakob * is stored in QUERY->name, the class in QUERY->klass, and the type
30962ac0c33Sjakob * in QUERY->type.
31062ac0c33Sjakob */
31162ac0c33Sjakob static int
process_query_section(query_type * query)31262ac0c33Sjakob process_query_section(query_type *query)
31362ac0c33Sjakob {
31462ac0c33Sjakob uint8_t qnamebuf[MAXDOMAINLEN];
31562ac0c33Sjakob
31662ac0c33Sjakob buffer_set_position(query->packet, QHEADERSZ);
31762ac0c33Sjakob /* Lets parse the query name and convert it to lower case. */
31862ac0c33Sjakob if(!packet_read_query_section(query->packet, qnamebuf,
31962ac0c33Sjakob &query->qtype, &query->qclass))
32062ac0c33Sjakob return 0;
32162ac0c33Sjakob query->qname = dname_make(query->region, qnamebuf, 1);
32262ac0c33Sjakob return 1;
32362ac0c33Sjakob }
32462ac0c33Sjakob
32562ac0c33Sjakob
32662ac0c33Sjakob /*
32762ac0c33Sjakob * Process an optional EDNS OPT record. Sets QUERY->EDNS to 0 if
32862ac0c33Sjakob * there was no EDNS record, to -1 if there was an invalid or
32962ac0c33Sjakob * unsupported EDNS record, and to 1 otherwise. Updates QUERY->MAXLEN
33062ac0c33Sjakob * if the EDNS record specifies a maximum supported response length.
33162ac0c33Sjakob *
33262ac0c33Sjakob * Return NSD_RC_FORMAT on failure, NSD_RC_OK on success.
33362ac0c33Sjakob */
33462ac0c33Sjakob static nsd_rc_type
process_edns(nsd_type * nsd,struct query * q)33562ac0c33Sjakob process_edns(nsd_type* nsd, struct query *q)
33662ac0c33Sjakob {
33762ac0c33Sjakob if (q->edns.status == EDNS_ERROR) {
338d11a62c8Ssthen /* The only error is VERSION not implemented */
33962ac0c33Sjakob return NSD_RC_FORMAT;
34062ac0c33Sjakob }
34162ac0c33Sjakob
34262ac0c33Sjakob if (q->edns.status == EDNS_OK) {
34362ac0c33Sjakob /* Only care about UDP size larger than normal... */
34462ac0c33Sjakob if (!q->tcp && q->edns.maxlen > UDP_MAX_MESSAGE_LEN) {
34562ac0c33Sjakob size_t edns_size;
34662ac0c33Sjakob #if defined(INET6)
347b71395eaSflorian if (q->client_addr.ss_family == AF_INET6) {
34862ac0c33Sjakob edns_size = nsd->ipv6_edns_size;
34962ac0c33Sjakob } else
35062ac0c33Sjakob #endif
35162ac0c33Sjakob edns_size = nsd->ipv4_edns_size;
35262ac0c33Sjakob
35362ac0c33Sjakob if (q->edns.maxlen < edns_size) {
35462ac0c33Sjakob q->maxlen = q->edns.maxlen;
35562ac0c33Sjakob } else {
35662ac0c33Sjakob q->maxlen = edns_size;
35762ac0c33Sjakob }
35862ac0c33Sjakob
35962ac0c33Sjakob #if defined(INET6) && !defined(IPV6_USE_MIN_MTU) && !defined(IPV6_MTU)
36062ac0c33Sjakob /*
36162ac0c33Sjakob * Use IPv6 minimum MTU to avoid sending
36262ac0c33Sjakob * packets that are too large for some links.
36362ac0c33Sjakob * IPv6 will not automatically fragment in
36462ac0c33Sjakob * this case (unlike IPv4).
36562ac0c33Sjakob */
366b71395eaSflorian if (q->client_addr.ss_family == AF_INET6
36762ac0c33Sjakob && q->maxlen > IPV6_MIN_MTU)
36862ac0c33Sjakob {
36962ac0c33Sjakob q->maxlen = IPV6_MIN_MTU;
37062ac0c33Sjakob }
37162ac0c33Sjakob #endif
37262ac0c33Sjakob }
37362ac0c33Sjakob
37462ac0c33Sjakob /* Strip the OPT resource record off... */
37562ac0c33Sjakob buffer_set_position(q->packet, q->edns.position);
37662ac0c33Sjakob buffer_set_limit(q->packet, q->edns.position);
37762ac0c33Sjakob ARCOUNT_SET(q->packet, ARCOUNT(q->packet) - 1);
37862ac0c33Sjakob }
37962ac0c33Sjakob return NSD_RC_OK;
38062ac0c33Sjakob }
38162ac0c33Sjakob
38262ac0c33Sjakob /*
38362ac0c33Sjakob * Processes TSIG.
38462ac0c33Sjakob * Sets error when tsig does not verify on the query.
38562ac0c33Sjakob */
38662ac0c33Sjakob static nsd_rc_type
process_tsig(struct query * q)38762ac0c33Sjakob process_tsig(struct query* q)
38862ac0c33Sjakob {
38962ac0c33Sjakob if(q->tsig.status == TSIG_ERROR)
39062ac0c33Sjakob return NSD_RC_FORMAT;
39162ac0c33Sjakob if(q->tsig.status == TSIG_OK) {
39262ac0c33Sjakob if(!tsig_from_query(&q->tsig)) {
393dd5b221eSsthen char a[128];
394b71395eaSflorian addr2str(&q->client_addr, a, sizeof(a));
395dd5b221eSsthen log_msg(LOG_ERR, "query: bad tsig (%s) for key %s from %s",
396dd5b221eSsthen tsig_error(q->tsig.error_code),
397dd5b221eSsthen dname_to_string(q->tsig.key_name, NULL), a);
39875343be4Ssthen return NSD_RC_NOTAUTH;
39962ac0c33Sjakob }
40062ac0c33Sjakob buffer_set_limit(q->packet, q->tsig.position);
40162ac0c33Sjakob ARCOUNT_SET(q->packet, ARCOUNT(q->packet) - 1);
40262ac0c33Sjakob tsig_prepare(&q->tsig);
40362ac0c33Sjakob tsig_update(&q->tsig, q->packet, buffer_limit(q->packet));
40462ac0c33Sjakob if(!tsig_verify(&q->tsig)) {
405dd5b221eSsthen char a[128];
406b71395eaSflorian addr2str(&q->client_addr, a, sizeof(a));
407dd5b221eSsthen log_msg(LOG_ERR, "query: bad tsig signature for key %s from %s",
408dd5b221eSsthen dname_to_string(q->tsig.key->name, NULL), a);
40975343be4Ssthen return NSD_RC_NOTAUTH;
41062ac0c33Sjakob }
41162ac0c33Sjakob DEBUG(DEBUG_XFRD,1, (LOG_INFO, "query good tsig signature for %s",
41262ac0c33Sjakob dname_to_string(q->tsig.key->name, NULL)));
41362ac0c33Sjakob }
41462ac0c33Sjakob return NSD_RC_OK;
41562ac0c33Sjakob }
41662ac0c33Sjakob
41762ac0c33Sjakob /*
41862ac0c33Sjakob * Check notify acl and forward to xfrd (or return an error).
41962ac0c33Sjakob */
42062ac0c33Sjakob static query_state_type
answer_notify(struct nsd * nsd,struct query * query)42162ac0c33Sjakob answer_notify(struct nsd* nsd, struct query *query)
42262ac0c33Sjakob {
42372f0a8e9Ssthen int acl_num, acl_num_xfr;
424fe5fe5f6Sflorian struct acl_options *why;
42562ac0c33Sjakob nsd_rc_type rc;
42662ac0c33Sjakob
427fe5fe5f6Sflorian struct zone_options* zone_opt;
42862ac0c33Sjakob DEBUG(DEBUG_XFRD,1, (LOG_INFO, "got notify %s processing acl",
42962ac0c33Sjakob dname_to_string(query->qname, NULL)));
43062ac0c33Sjakob
43162ac0c33Sjakob zone_opt = zone_options_find(nsd->options, query->qname);
43262ac0c33Sjakob if(!zone_opt)
43362ac0c33Sjakob return query_error(query, NSD_RC_NXDOMAIN);
43462ac0c33Sjakob
43562ac0c33Sjakob if(!nsd->this_child) /* we are in debug mode or something */
43662ac0c33Sjakob return query_error(query, NSD_RC_SERVFAIL);
43762ac0c33Sjakob
43862ac0c33Sjakob if(!tsig_find_rr(&query->tsig, query->packet)) {
43962ac0c33Sjakob DEBUG(DEBUG_XFRD,2, (LOG_ERR, "bad tsig RR format"));
44062ac0c33Sjakob return query_error(query, NSD_RC_FORMAT);
44162ac0c33Sjakob }
44262ac0c33Sjakob rc = process_tsig(query);
44362ac0c33Sjakob if(rc != NSD_RC_OK)
44462ac0c33Sjakob return query_error(query, rc);
44562ac0c33Sjakob
44662ac0c33Sjakob /* check if it passes acl */
447b71395eaSflorian if(query->is_proxied && acl_check_incoming_block_proxy(
448b71395eaSflorian zone_opt->pattern->allow_notify, query, &why) == -1) {
449b71395eaSflorian /* the proxy address is blocked */
450b71395eaSflorian if (verbosity >= 2) {
451b71395eaSflorian char address[128], proxy[128];
452b71395eaSflorian addr2str(&query->client_addr, address, sizeof(address));
453b71395eaSflorian addr2str(&query->remote_addr, proxy, sizeof(proxy));
454b71395eaSflorian VERBOSITY(2, (LOG_INFO, "notify for %s from %s via proxy %s refused because of proxy, %s %s",
455b71395eaSflorian dname_to_string(query->qname, NULL),
456b71395eaSflorian address, proxy,
457b71395eaSflorian (why?why->ip_address_spec:"."),
458b71395eaSflorian (why ? ( why->nokey ? "NOKEY"
459b71395eaSflorian : why->blocked ? "BLOCKED"
460b71395eaSflorian : why->key_name )
461b71395eaSflorian : "no acl matches")));
462b71395eaSflorian }
463b71395eaSflorian return query_error(query, NSD_RC_REFUSE);
464b71395eaSflorian }
465dd5b221eSsthen if((acl_num = acl_check_incoming(zone_opt->pattern->allow_notify, query,
46662ac0c33Sjakob &why)) != -1)
46762ac0c33Sjakob {
46862ac0c33Sjakob sig_atomic_t mode = NSD_PASS_TO_XFRD;
46962ac0c33Sjakob int s = nsd->this_child->parent_fd;
47062ac0c33Sjakob uint16_t sz;
47162ac0c33Sjakob uint32_t acl_send = htonl(acl_num);
4720b3518aaSsthen uint32_t acl_xfr;
47362ac0c33Sjakob size_t pos;
4740b3518aaSsthen
4750b3518aaSsthen /* Find priority candidate for request XFR. -1 if no match */
4760b3518aaSsthen acl_num_xfr = acl_check_incoming(
477dd5b221eSsthen zone_opt->pattern->request_xfr, query, NULL);
478dd5b221eSsthen
4790b3518aaSsthen acl_xfr = htonl(acl_num_xfr);
4800b3518aaSsthen
481dd5b221eSsthen assert(why);
48262ac0c33Sjakob DEBUG(DEBUG_XFRD,1, (LOG_INFO, "got notify %s passed acl %s %s",
48362ac0c33Sjakob dname_to_string(query->qname, NULL),
48462ac0c33Sjakob why->ip_address_spec,
48562ac0c33Sjakob why->nokey?"NOKEY":
48662ac0c33Sjakob (why->blocked?"BLOCKED":why->key_name)));
48762ac0c33Sjakob sz = buffer_limit(query->packet);
48862ac0c33Sjakob if(buffer_limit(query->packet) > MAX_PACKET_SIZE)
48962ac0c33Sjakob return query_error(query, NSD_RC_SERVFAIL);
49062ac0c33Sjakob /* forward to xfrd for processing
49162ac0c33Sjakob Note. Blocking IPC I/O, but acl is OK. */
49262ac0c33Sjakob sz = htons(sz);
49362ac0c33Sjakob if(!write_socket(s, &mode, sizeof(mode)) ||
49462ac0c33Sjakob !write_socket(s, &sz, sizeof(sz)) ||
49562ac0c33Sjakob !write_socket(s, buffer_begin(query->packet),
49662ac0c33Sjakob buffer_limit(query->packet)) ||
49772f0a8e9Ssthen !write_socket(s, &acl_send, sizeof(acl_send)) ||
49872f0a8e9Ssthen !write_socket(s, &acl_xfr, sizeof(acl_xfr))) {
49962ac0c33Sjakob log_msg(LOG_ERR, "error in IPC notify server2main, %s",
50062ac0c33Sjakob strerror(errno));
50162ac0c33Sjakob return query_error(query, NSD_RC_SERVFAIL);
50262ac0c33Sjakob }
5038d8f1862Ssthen if(verbosity >= 1) {
5048d8f1862Ssthen uint32_t serial = 0;
5058d8f1862Ssthen char address[128];
506b71395eaSflorian addr2str(&query->client_addr, address, sizeof(address));
5078d8f1862Ssthen if(packet_find_notify_serial(query->packet, &serial))
5088d8f1862Ssthen VERBOSITY(1, (LOG_INFO, "notify for %s from %s serial %u",
5098d8f1862Ssthen dname_to_string(query->qname, NULL), address,
5108d8f1862Ssthen (unsigned)serial));
5118d8f1862Ssthen else
5128d8f1862Ssthen VERBOSITY(1, (LOG_INFO, "notify for %s from %s",
5138d8f1862Ssthen dname_to_string(query->qname, NULL), address));
5148d8f1862Ssthen }
51562ac0c33Sjakob
51662ac0c33Sjakob /* create notify reply - keep same query contents */
51762ac0c33Sjakob QR_SET(query->packet); /* This is an answer. */
51862ac0c33Sjakob AA_SET(query->packet); /* we are authoritative. */
51962ac0c33Sjakob ANCOUNT_SET(query->packet, 0);
52062ac0c33Sjakob NSCOUNT_SET(query->packet, 0);
52162ac0c33Sjakob ARCOUNT_SET(query->packet, 0);
52262ac0c33Sjakob RCODE_SET(query->packet, RCODE_OK); /* Error code. */
52362ac0c33Sjakob /* position is right after the query */
52462ac0c33Sjakob pos = buffer_position(query->packet);
52562ac0c33Sjakob buffer_clear(query->packet);
52662ac0c33Sjakob buffer_set_position(query->packet, pos);
52762ac0c33Sjakob /* tsig is added in add_additional later (if needed) */
52862ac0c33Sjakob return QUERY_PROCESSED;
52962ac0c33Sjakob }
5303b0b19f7Sjakob
5318d8f1862Ssthen if (verbosity >= 2) {
5323b0b19f7Sjakob char address[128];
533b71395eaSflorian addr2str(&query->client_addr, address, sizeof(address));
5348d8f1862Ssthen VERBOSITY(2, (LOG_INFO, "notify for %s from %s refused, %s %s",
53562ac0c33Sjakob dname_to_string(query->qname, NULL),
5363b0b19f7Sjakob address,
537b71395eaSflorian (why?why->ip_address_spec:"."),
538b71395eaSflorian (why ? ( why->nokey ? "NOKEY"
539b71395eaSflorian : why->blocked ? "BLOCKED"
540b71395eaSflorian : why->key_name )
541b71395eaSflorian : "no acl matches")));
5423b0b19f7Sjakob }
5433b0b19f7Sjakob
54462ac0c33Sjakob return query_error(query, NSD_RC_REFUSE);
54562ac0c33Sjakob }
54662ac0c33Sjakob
54762ac0c33Sjakob
54862ac0c33Sjakob /*
54962ac0c33Sjakob * Answer a query in the CHAOS class.
55062ac0c33Sjakob */
55162ac0c33Sjakob static query_state_type
answer_chaos(struct nsd * nsd,query_type * q)55262ac0c33Sjakob answer_chaos(struct nsd *nsd, query_type *q)
55362ac0c33Sjakob {
55462ac0c33Sjakob AA_CLR(q->packet);
55562ac0c33Sjakob switch (q->qtype) {
55662ac0c33Sjakob case TYPE_ANY:
55762ac0c33Sjakob case TYPE_TXT:
55862ac0c33Sjakob if ((q->qname->name_size == 11
55962ac0c33Sjakob && memcmp(dname_name(q->qname), "\002id\006server", 11) == 0) ||
56062ac0c33Sjakob (q->qname->name_size == 15
56162ac0c33Sjakob && memcmp(dname_name(q->qname), "\010hostname\004bind", 15) == 0))
56262ac0c33Sjakob {
563eab1363eSsthen if(!nsd->options->hide_identity) {
56462ac0c33Sjakob /* Add ID */
56562ac0c33Sjakob query_addtxt(q,
56662ac0c33Sjakob buffer_begin(q->packet) + QHEADERSZ,
56762ac0c33Sjakob CLASS_CH,
56862ac0c33Sjakob 0,
56962ac0c33Sjakob nsd->identity);
57062ac0c33Sjakob ANCOUNT_SET(q->packet, ANCOUNT(q->packet) + 1);
571eab1363eSsthen } else {
572eab1363eSsthen RCODE_SET(q->packet, RCODE_REFUSE);
5738d298c9fSsthen /* RFC8914 - Extended DNS Errors
5748d298c9fSsthen * 4.19. Extended DNS Error Code 18 - Prohibited */
5758d298c9fSsthen q->edns.ede = EDE_PROHIBITED;
576eab1363eSsthen }
57762ac0c33Sjakob } else if ((q->qname->name_size == 16
57862ac0c33Sjakob && memcmp(dname_name(q->qname), "\007version\006server", 16) == 0) ||
57962ac0c33Sjakob (q->qname->name_size == 14
58062ac0c33Sjakob && memcmp(dname_name(q->qname), "\007version\004bind", 14) == 0))
58162ac0c33Sjakob {
58262ac0c33Sjakob if(!nsd->options->hide_version) {
58362ac0c33Sjakob /* Add version */
58462ac0c33Sjakob query_addtxt(q,
58562ac0c33Sjakob buffer_begin(q->packet) + QHEADERSZ,
58662ac0c33Sjakob CLASS_CH,
58762ac0c33Sjakob 0,
58862ac0c33Sjakob nsd->version);
58962ac0c33Sjakob ANCOUNT_SET(q->packet, ANCOUNT(q->packet) + 1);
59062ac0c33Sjakob } else {
59162ac0c33Sjakob RCODE_SET(q->packet, RCODE_REFUSE);
5928d298c9fSsthen /* RFC8914 - Extended DNS Errors
5938d298c9fSsthen * 4.19. Extended DNS Error Code 18 - Prohibited */
5948d298c9fSsthen q->edns.ede = EDE_PROHIBITED;
59562ac0c33Sjakob }
59603739794Sbrad } else {
59703739794Sbrad RCODE_SET(q->packet, RCODE_REFUSE);
5988d298c9fSsthen /* RFC8914 - Extended DNS Errors
5998d298c9fSsthen * 4.22. Extended DNS Error Code 21 - Not Supported */
6008d298c9fSsthen q->edns.ede = EDE_NOT_SUPPORTED;
6018d298c9fSsthen
60262ac0c33Sjakob }
60362ac0c33Sjakob break;
60462ac0c33Sjakob default:
60562ac0c33Sjakob RCODE_SET(q->packet, RCODE_REFUSE);
6068d298c9fSsthen /* RFC8914 - Extended DNS Errors
6078d298c9fSsthen * 4.22. Extended DNS Error Code 21 - Not Supported */
6088d298c9fSsthen q->edns.ede = EDE_NOT_SUPPORTED;
60962ac0c33Sjakob break;
61062ac0c33Sjakob }
61162ac0c33Sjakob
61262ac0c33Sjakob return QUERY_PROCESSED;
61362ac0c33Sjakob }
61462ac0c33Sjakob
61562ac0c33Sjakob
61662ac0c33Sjakob /*
61762ac0c33Sjakob * Find the covering NSEC for a non-existent domain name. Normally
61862ac0c33Sjakob * the NSEC will be located at CLOSEST_MATCH, except when it is an
61962ac0c33Sjakob * empty non-terminal. In this case the NSEC may be located at the
62062ac0c33Sjakob * previous domain name (in canonical ordering).
62162ac0c33Sjakob */
62262ac0c33Sjakob static domain_type *
find_covering_nsec(domain_type * closest_match,zone_type * zone,rrset_type ** nsec_rrset)62362ac0c33Sjakob find_covering_nsec(domain_type *closest_match,
62462ac0c33Sjakob zone_type *zone,
62562ac0c33Sjakob rrset_type **nsec_rrset)
62662ac0c33Sjakob {
62762ac0c33Sjakob assert(closest_match);
62862ac0c33Sjakob assert(nsec_rrset);
62962ac0c33Sjakob
63062ac0c33Sjakob /* loop away temporary created domains. For real ones it is &RBTREE_NULL */
631c1e73312Sflorian #ifdef USE_RADIX_TREE
632dd5b221eSsthen while (closest_match->rnode == NULL)
633c1e73312Sflorian #else
634c1e73312Sflorian while (closest_match->node.parent == NULL)
635c1e73312Sflorian #endif
63662ac0c33Sjakob closest_match = closest_match->parent;
63762ac0c33Sjakob while (closest_match) {
63862ac0c33Sjakob *nsec_rrset = domain_find_rrset(closest_match, zone, TYPE_NSEC);
63962ac0c33Sjakob if (*nsec_rrset) {
64062ac0c33Sjakob return closest_match;
64162ac0c33Sjakob }
64262ac0c33Sjakob if (closest_match == zone->apex) {
64362ac0c33Sjakob /* Don't look outside the current zone. */
64462ac0c33Sjakob return NULL;
64562ac0c33Sjakob }
64662ac0c33Sjakob closest_match = domain_previous(closest_match);
64762ac0c33Sjakob }
64862ac0c33Sjakob return NULL;
64962ac0c33Sjakob }
65062ac0c33Sjakob
65162ac0c33Sjakob
65262ac0c33Sjakob struct additional_rr_types
65362ac0c33Sjakob {
65462ac0c33Sjakob uint16_t rr_type;
65562ac0c33Sjakob rr_section_type rr_section;
65662ac0c33Sjakob };
65762ac0c33Sjakob
65862ac0c33Sjakob struct additional_rr_types default_additional_rr_types[] = {
65962ac0c33Sjakob { TYPE_A, ADDITIONAL_A_SECTION },
66062ac0c33Sjakob { TYPE_AAAA, ADDITIONAL_AAAA_SECTION },
66162ac0c33Sjakob { 0, (rr_section_type) 0 }
66262ac0c33Sjakob };
66362ac0c33Sjakob
664275a8d89Sflorian struct additional_rr_types swap_aaaa_additional_rr_types[] = {
665275a8d89Sflorian { TYPE_AAAA, ADDITIONAL_A_SECTION },
666275a8d89Sflorian { TYPE_A, ADDITIONAL_AAAA_SECTION },
667275a8d89Sflorian { 0, (rr_section_type) 0 }
668275a8d89Sflorian };
669275a8d89Sflorian
67062ac0c33Sjakob struct additional_rr_types rt_additional_rr_types[] = {
67162ac0c33Sjakob { TYPE_A, ADDITIONAL_A_SECTION },
67262ac0c33Sjakob { TYPE_AAAA, ADDITIONAL_AAAA_SECTION },
67362ac0c33Sjakob { TYPE_X25, ADDITIONAL_OTHER_SECTION },
67462ac0c33Sjakob { TYPE_ISDN, ADDITIONAL_OTHER_SECTION },
67562ac0c33Sjakob { 0, (rr_section_type) 0 }
67662ac0c33Sjakob };
67762ac0c33Sjakob
67862ac0c33Sjakob static void
add_additional_rrsets(struct query * query,answer_type * answer,rrset_type * master_rrset,size_t rdata_index,int allow_glue,struct additional_rr_types types[])67962ac0c33Sjakob add_additional_rrsets(struct query *query, answer_type *answer,
68062ac0c33Sjakob rrset_type *master_rrset, size_t rdata_index,
68162ac0c33Sjakob int allow_glue, struct additional_rr_types types[])
68262ac0c33Sjakob {
68362ac0c33Sjakob size_t i;
68462ac0c33Sjakob
68562ac0c33Sjakob assert(query);
68662ac0c33Sjakob assert(answer);
68762ac0c33Sjakob assert(master_rrset);
68862ac0c33Sjakob assert(rdata_atom_is_domain(rrset_rrtype(master_rrset), rdata_index));
68962ac0c33Sjakob
69062ac0c33Sjakob for (i = 0; i < master_rrset->rr_count; ++i) {
69162ac0c33Sjakob int j;
69262ac0c33Sjakob domain_type *additional = rdata_atom_domain(master_rrset->rrs[i].rdatas[rdata_index]);
69362ac0c33Sjakob domain_type *match = additional;
69462ac0c33Sjakob
69562ac0c33Sjakob assert(additional);
69662ac0c33Sjakob
69762ac0c33Sjakob if (!allow_glue && domain_is_glue(match, query->zone))
69862ac0c33Sjakob continue;
69962ac0c33Sjakob
70062ac0c33Sjakob /*
70162ac0c33Sjakob * Check to see if we need to generate the dependent
70262ac0c33Sjakob * based on a wildcard domain.
70362ac0c33Sjakob */
70462ac0c33Sjakob while (!match->is_existing) {
70562ac0c33Sjakob match = match->parent;
70662ac0c33Sjakob }
70762ac0c33Sjakob if (additional != match && domain_wildcard_child(match)) {
70862ac0c33Sjakob domain_type *wildcard_child = domain_wildcard_child(match);
70962ac0c33Sjakob domain_type *temp = (domain_type *) region_alloc(
71062ac0c33Sjakob query->region, sizeof(domain_type));
711c1e73312Sflorian #ifdef USE_RADIX_TREE
712dd5b221eSsthen temp->rnode = NULL;
713dd5b221eSsthen temp->dname = additional->dname;
714c1e73312Sflorian #else
715fe5fe5f6Sflorian memcpy(&temp->node, &additional->node, sizeof(rbnode_type));
716c1e73312Sflorian temp->node.parent = NULL;
717c1e73312Sflorian #endif
71862ac0c33Sjakob temp->number = additional->number;
71962ac0c33Sjakob temp->parent = match;
72062ac0c33Sjakob temp->wildcard_child_closest_match = temp;
72162ac0c33Sjakob temp->rrsets = wildcard_child->rrsets;
72262ac0c33Sjakob temp->is_existing = wildcard_child->is_existing;
72362ac0c33Sjakob additional = temp;
72462ac0c33Sjakob }
72562ac0c33Sjakob
72662ac0c33Sjakob for (j = 0; types[j].rr_type != 0; ++j) {
72762ac0c33Sjakob rrset_type *rrset = domain_find_rrset(
72862ac0c33Sjakob additional, query->zone, types[j].rr_type);
72962ac0c33Sjakob if (rrset) {
73062ac0c33Sjakob answer_add_rrset(answer, types[j].rr_section,
73162ac0c33Sjakob additional, rrset);
73262ac0c33Sjakob }
73362ac0c33Sjakob }
73462ac0c33Sjakob }
73562ac0c33Sjakob }
73662ac0c33Sjakob
73762ac0c33Sjakob static int
answer_needs_ns(struct query * query)73862ac0c33Sjakob answer_needs_ns(struct query* query)
73962ac0c33Sjakob {
74062ac0c33Sjakob assert(query);
741f72b2965Sjakob /* Currently, only troublesome for DNSKEY and DS,
742f72b2965Sjakob * cuz their RRSETs are quite large. */
743a1bac035Sflorian return (query->qtype != TYPE_DNSKEY && query->qtype != TYPE_DS
744a1bac035Sflorian && query->qtype != TYPE_ANY);
74562ac0c33Sjakob }
74662ac0c33Sjakob
74762ac0c33Sjakob static int
add_rrset(struct query * query,answer_type * answer,rr_section_type section,domain_type * owner,rrset_type * rrset)74862ac0c33Sjakob add_rrset(struct query *query,
74962ac0c33Sjakob answer_type *answer,
75062ac0c33Sjakob rr_section_type section,
75162ac0c33Sjakob domain_type *owner,
75262ac0c33Sjakob rrset_type *rrset)
75362ac0c33Sjakob {
75462ac0c33Sjakob int result;
75562ac0c33Sjakob
75662ac0c33Sjakob assert(query);
75762ac0c33Sjakob assert(answer);
75862ac0c33Sjakob assert(owner);
75962ac0c33Sjakob assert(rrset);
76062ac0c33Sjakob assert(rrset_rrclass(rrset) == CLASS_IN);
76162ac0c33Sjakob
76262ac0c33Sjakob result = answer_add_rrset(answer, section, owner, rrset);
763db7d0d02Sflorian if(minimal_responses && section != AUTHORITY_SECTION &&
764db7d0d02Sflorian query->qtype != TYPE_NS)
765db7d0d02Sflorian return result;
76662ac0c33Sjakob switch (rrset_rrtype(rrset)) {
76762ac0c33Sjakob case TYPE_NS:
7686e9bf1eeSflorian #if defined(INET6)
769275a8d89Sflorian /* if query over IPv6, swap A and AAAA; put AAAA first */
77062ac0c33Sjakob add_additional_rrsets(query, answer, rrset, 0, 1,
771b71395eaSflorian (query->client_addr.ss_family == AF_INET6)?
772275a8d89Sflorian swap_aaaa_additional_rr_types:
77362ac0c33Sjakob default_additional_rr_types);
7746e9bf1eeSflorian #else
7756e9bf1eeSflorian add_additional_rrsets(query, answer, rrset, 0, 1,
7766e9bf1eeSflorian default_additional_rr_types);
7776e9bf1eeSflorian #endif
77862ac0c33Sjakob break;
77962ac0c33Sjakob case TYPE_MB:
78062ac0c33Sjakob add_additional_rrsets(query, answer, rrset, 0, 0,
78162ac0c33Sjakob default_additional_rr_types);
78262ac0c33Sjakob break;
78362ac0c33Sjakob case TYPE_MX:
78462ac0c33Sjakob case TYPE_KX:
78562ac0c33Sjakob add_additional_rrsets(query, answer, rrset, 1, 0,
78662ac0c33Sjakob default_additional_rr_types);
78762ac0c33Sjakob break;
78862ac0c33Sjakob case TYPE_RT:
78962ac0c33Sjakob add_additional_rrsets(query, answer, rrset, 1, 0,
79062ac0c33Sjakob rt_additional_rr_types);
79162ac0c33Sjakob break;
792c1e73312Sflorian case TYPE_SRV:
793c1e73312Sflorian add_additional_rrsets(query, answer, rrset, 3, 0,
794c1e73312Sflorian default_additional_rr_types);
795c1e73312Sflorian break;
79662ac0c33Sjakob default:
79762ac0c33Sjakob break;
79862ac0c33Sjakob }
79962ac0c33Sjakob
80062ac0c33Sjakob return result;
80162ac0c33Sjakob }
80262ac0c33Sjakob
80362ac0c33Sjakob
80462ac0c33Sjakob /* returns 0 on error, or the domain number for to_name.
80562ac0c33Sjakob from_name is changes to to_name by the DNAME rr.
80662ac0c33Sjakob DNAME rr is from src to dest.
80762ac0c33Sjakob closest encloser encloses the to_name. */
808dd5b221eSsthen static size_t
query_synthesize_cname(struct query * q,struct answer * answer,const dname_type * from_name,const dname_type * to_name,domain_type * src,domain_type * to_closest_encloser,domain_type ** to_closest_match,uint32_t ttl)80962ac0c33Sjakob query_synthesize_cname(struct query* q, struct answer* answer, const dname_type* from_name,
81062ac0c33Sjakob const dname_type* to_name, domain_type* src, domain_type* to_closest_encloser,
81121c23707Sbrad domain_type** to_closest_match, uint32_t ttl)
81262ac0c33Sjakob {
81362ac0c33Sjakob /* add temporary domains for from_name and to_name and all
81462ac0c33Sjakob their (not allocated yet) parents */
81562ac0c33Sjakob /* any domains below src are not_existing (because of DNAME at src) */
81662ac0c33Sjakob int i;
8178d298c9fSsthen size_t j;
81862ac0c33Sjakob domain_type* cname_domain;
81962ac0c33Sjakob domain_type* cname_dest;
82062ac0c33Sjakob rrset_type* rrset;
82162ac0c33Sjakob
82262ac0c33Sjakob domain_type* lastparent = src;
82362ac0c33Sjakob assert(q && answer && from_name && to_name && src && to_closest_encloser);
82462ac0c33Sjakob assert(to_closest_match);
8258d298c9fSsthen
8268d298c9fSsthen /* check for loop by duplicate CNAME rrset synthesized */
8278d298c9fSsthen for(j=0; j<answer->rrset_count; ++j) {
8288d298c9fSsthen if(answer->section[j] == ANSWER_SECTION &&
8298d298c9fSsthen answer->rrsets[j]->rr_count == 1 &&
8308d298c9fSsthen answer->rrsets[j]->rrs[0].type == TYPE_CNAME &&
8318d298c9fSsthen dname_compare(domain_dname(answer->rrsets[j]->rrs[0].owner), from_name) == 0 &&
8328d298c9fSsthen answer->rrsets[j]->rrs[0].rdata_count == 1 &&
8338d298c9fSsthen dname_compare(domain_dname(answer->rrsets[j]->rrs[0].rdatas->domain), to_name) == 0) {
8348d298c9fSsthen DEBUG(DEBUG_QUERY,2, (LOG_INFO, "loop for synthesized CNAME rrset for query %s", dname_to_string(q->qname, NULL)));
8358d298c9fSsthen return 0;
8368d298c9fSsthen }
8378d298c9fSsthen }
8388d298c9fSsthen
8398d298c9fSsthen /* allocate source part */
84062ac0c33Sjakob for(i=0; i < from_name->label_count - domain_dname(src)->label_count; i++)
84162ac0c33Sjakob {
84262ac0c33Sjakob domain_type* newdom = query_get_tempdomain(q);
84362ac0c33Sjakob if(!newdom)
84462ac0c33Sjakob return 0;
84562ac0c33Sjakob newdom->is_existing = 1;
84662ac0c33Sjakob newdom->parent = lastparent;
847c1e73312Sflorian #ifdef USE_RADIX_TREE
848dd5b221eSsthen newdom->dname
849c1e73312Sflorian #else
850c1e73312Sflorian newdom->node.key
851c1e73312Sflorian #endif
852dd5b221eSsthen = dname_partial_copy(q->region,
85362ac0c33Sjakob from_name, domain_dname(src)->label_count + i + 1);
85462ac0c33Sjakob if(dname_compare(domain_dname(newdom), q->qname) == 0) {
85562ac0c33Sjakob /* 0 good for query name, otherwise new number */
85662ac0c33Sjakob newdom->number = 0;
85762ac0c33Sjakob }
85862ac0c33Sjakob DEBUG(DEBUG_QUERY,2, (LOG_INFO, "created temp domain src %d. %s nr %d", i,
859dd5b221eSsthen domain_to_string(newdom), (int)newdom->number));
86062ac0c33Sjakob lastparent = newdom;
86162ac0c33Sjakob }
86262ac0c33Sjakob cname_domain = lastparent;
86362ac0c33Sjakob
86462ac0c33Sjakob /* allocate dest part */
86562ac0c33Sjakob lastparent = to_closest_encloser;
86662ac0c33Sjakob for(i=0; i < to_name->label_count - domain_dname(to_closest_encloser)->label_count;
86762ac0c33Sjakob i++)
86862ac0c33Sjakob {
86962ac0c33Sjakob domain_type* newdom = query_get_tempdomain(q);
87062ac0c33Sjakob if(!newdom)
87162ac0c33Sjakob return 0;
87262ac0c33Sjakob newdom->is_existing = 0;
87362ac0c33Sjakob newdom->parent = lastparent;
874c1e73312Sflorian #ifdef USE_RADIX_TREE
875dd5b221eSsthen newdom->dname
876c1e73312Sflorian #else
877c1e73312Sflorian newdom->node.key
878c1e73312Sflorian #endif
879dd5b221eSsthen = dname_partial_copy(q->region,
88062ac0c33Sjakob to_name, domain_dname(to_closest_encloser)->label_count + i + 1);
88162ac0c33Sjakob DEBUG(DEBUG_QUERY,2, (LOG_INFO, "created temp domain dest %d. %s nr %d", i,
882dd5b221eSsthen domain_to_string(newdom), (int)newdom->number));
88362ac0c33Sjakob lastparent = newdom;
88462ac0c33Sjakob }
88562ac0c33Sjakob cname_dest = lastparent;
88662ac0c33Sjakob *to_closest_match = cname_dest;
88762ac0c33Sjakob
88862ac0c33Sjakob /* allocate the CNAME RR */
88962ac0c33Sjakob rrset = (rrset_type*) region_alloc(q->region, sizeof(rrset_type));
89062ac0c33Sjakob memset(rrset, 0, sizeof(rrset_type));
89162ac0c33Sjakob rrset->zone = q->zone;
89262ac0c33Sjakob rrset->rr_count = 1;
89362ac0c33Sjakob rrset->rrs = (rr_type*) region_alloc(q->region, sizeof(rr_type));
89462ac0c33Sjakob memset(rrset->rrs, 0, sizeof(rr_type));
89562ac0c33Sjakob rrset->rrs->owner = cname_domain;
89621c23707Sbrad rrset->rrs->ttl = ttl;
89762ac0c33Sjakob rrset->rrs->type = TYPE_CNAME;
89862ac0c33Sjakob rrset->rrs->klass = CLASS_IN;
89962ac0c33Sjakob rrset->rrs->rdata_count = 1;
90062ac0c33Sjakob rrset->rrs->rdatas = (rdata_atom_type*)region_alloc(q->region,
90162ac0c33Sjakob sizeof(rdata_atom_type));
90262ac0c33Sjakob rrset->rrs->rdatas->domain = cname_dest;
90362ac0c33Sjakob
90462ac0c33Sjakob if(!add_rrset(q, answer, ANSWER_SECTION, cname_domain, rrset)) {
9058d298c9fSsthen DEBUG(DEBUG_QUERY,2, (LOG_INFO, "could not add synthesized CNAME rrset to packet for query %s", dname_to_string(q->qname, NULL)));
9068d298c9fSsthen /* failure to add CNAME; likely is a loop, the same twice */
9078d298c9fSsthen return 0;
90862ac0c33Sjakob }
90962ac0c33Sjakob
91062ac0c33Sjakob return cname_dest->number;
91162ac0c33Sjakob }
91262ac0c33Sjakob
91362ac0c33Sjakob /*
91462ac0c33Sjakob * Answer delegation information.
91562ac0c33Sjakob *
91662ac0c33Sjakob * DNSSEC: Include the DS RRset if present. Otherwise include an NSEC
91762ac0c33Sjakob * record proving the DS RRset does not exist.
91862ac0c33Sjakob */
91962ac0c33Sjakob static void
answer_delegation(query_type * query,answer_type * answer)92062ac0c33Sjakob answer_delegation(query_type *query, answer_type *answer)
92162ac0c33Sjakob {
92262ac0c33Sjakob assert(answer);
92362ac0c33Sjakob assert(query->delegation_domain);
92462ac0c33Sjakob assert(query->delegation_rrset);
92562ac0c33Sjakob
9265bcb494bSjakob if (query->cname_count == 0) {
92762ac0c33Sjakob AA_CLR(query->packet);
9285bcb494bSjakob } else {
9295bcb494bSjakob AA_SET(query->packet);
9305bcb494bSjakob }
9315bcb494bSjakob
93262ac0c33Sjakob add_rrset(query,
93362ac0c33Sjakob answer,
93462ac0c33Sjakob AUTHORITY_SECTION,
93562ac0c33Sjakob query->delegation_domain,
93662ac0c33Sjakob query->delegation_rrset);
93762ac0c33Sjakob if (query->edns.dnssec_ok && zone_is_secure(query->zone)) {
93862ac0c33Sjakob rrset_type *rrset;
93962ac0c33Sjakob if ((rrset = domain_find_rrset(query->delegation_domain, query->zone, TYPE_DS))) {
94062ac0c33Sjakob add_rrset(query, answer, AUTHORITY_SECTION,
94162ac0c33Sjakob query->delegation_domain, rrset);
94262ac0c33Sjakob #ifdef NSEC3
943dd5b221eSsthen } else if (query->zone->nsec3_param) {
94462ac0c33Sjakob nsec3_answer_delegation(query, answer);
94562ac0c33Sjakob #endif
94662ac0c33Sjakob } else if ((rrset = domain_find_rrset(query->delegation_domain, query->zone, TYPE_NSEC))) {
94762ac0c33Sjakob add_rrset(query, answer, AUTHORITY_SECTION,
94862ac0c33Sjakob query->delegation_domain, rrset);
94962ac0c33Sjakob }
95062ac0c33Sjakob }
95162ac0c33Sjakob }
95262ac0c33Sjakob
95362ac0c33Sjakob
95462ac0c33Sjakob /*
95562ac0c33Sjakob * Answer SOA information.
95662ac0c33Sjakob */
95762ac0c33Sjakob static void
answer_soa(struct query * query,answer_type * answer)95862ac0c33Sjakob answer_soa(struct query *query, answer_type *answer)
95962ac0c33Sjakob {
96062ac0c33Sjakob if (query->qclass != CLASS_ANY) {
96162ac0c33Sjakob add_rrset(query, answer,
96262ac0c33Sjakob AUTHORITY_SECTION,
96362ac0c33Sjakob query->zone->apex,
96462ac0c33Sjakob query->zone->soa_nx_rrset);
96562ac0c33Sjakob }
96662ac0c33Sjakob }
96762ac0c33Sjakob
96862ac0c33Sjakob
96962ac0c33Sjakob /*
97062ac0c33Sjakob * Answer that the domain name exists but there is no RRset with the
97162ac0c33Sjakob * requested type.
97262ac0c33Sjakob *
97362ac0c33Sjakob * DNSSEC: Include the correct NSEC record proving that the type does
97462ac0c33Sjakob * not exist. In the wildcard no data (3.1.3.4) case the wildcard IS
97562ac0c33Sjakob * NOT expanded, so the ORIGINAL parameter must point to the original
97662ac0c33Sjakob * wildcard entry, not to the generated entry.
97762ac0c33Sjakob */
97862ac0c33Sjakob static void
answer_nodata(struct query * query,answer_type * answer,domain_type * original)97962ac0c33Sjakob answer_nodata(struct query *query, answer_type *answer, domain_type *original)
98062ac0c33Sjakob {
98162ac0c33Sjakob answer_soa(query, answer);
98262ac0c33Sjakob
98362ac0c33Sjakob #ifdef NSEC3
984dd5b221eSsthen if (query->edns.dnssec_ok && query->zone->nsec3_param) {
98562ac0c33Sjakob nsec3_answer_nodata(query, answer, original);
98662ac0c33Sjakob } else
98762ac0c33Sjakob #endif
98862ac0c33Sjakob if (query->edns.dnssec_ok && zone_is_secure(query->zone)) {
98962ac0c33Sjakob domain_type *nsec_domain;
99062ac0c33Sjakob rrset_type *nsec_rrset;
99162ac0c33Sjakob
99262ac0c33Sjakob nsec_domain = find_covering_nsec(original, query->zone, &nsec_rrset);
99362ac0c33Sjakob if (nsec_domain) {
99462ac0c33Sjakob add_rrset(query, answer, AUTHORITY_SECTION, nsec_domain, nsec_rrset);
99562ac0c33Sjakob }
99662ac0c33Sjakob }
99762ac0c33Sjakob }
99862ac0c33Sjakob
99962ac0c33Sjakob static void
answer_nxdomain(query_type * query,answer_type * answer)100062ac0c33Sjakob answer_nxdomain(query_type *query, answer_type *answer)
100162ac0c33Sjakob {
100262ac0c33Sjakob RCODE_SET(query->packet, RCODE_NXDOMAIN);
100362ac0c33Sjakob answer_soa(query, answer);
100462ac0c33Sjakob }
100562ac0c33Sjakob
100662ac0c33Sjakob
100762ac0c33Sjakob /*
100862ac0c33Sjakob * Answer domain information (or SOA if we do not have an RRset for
100962ac0c33Sjakob * the type specified by the query).
101062ac0c33Sjakob */
101162ac0c33Sjakob static void
answer_domain(struct nsd * nsd,struct query * q,answer_type * answer,domain_type * domain,domain_type * original)101262ac0c33Sjakob answer_domain(struct nsd* nsd, struct query *q, answer_type *answer,
101362ac0c33Sjakob domain_type *domain, domain_type *original)
101462ac0c33Sjakob {
101562ac0c33Sjakob rrset_type *rrset;
101662ac0c33Sjakob
101762ac0c33Sjakob if (q->qtype == TYPE_ANY) {
1018308d2509Sflorian rrset_type *preferred_rrset = NULL;
1019308d2509Sflorian rrset_type *normal_rrset = NULL;
1020308d2509Sflorian rrset_type *non_preferred_rrset = NULL;
1021308d2509Sflorian
1022308d2509Sflorian /*
1023308d2509Sflorian * Minimize response size for ANY, with one RRset
1024308d2509Sflorian * according to RFC 8482(4.1).
1025308d2509Sflorian * Prefers popular and not large rtypes (A,AAAA,...)
1026308d2509Sflorian * lowering large ones (DNSKEY,RRSIG,...).
1027308d2509Sflorian */
102862ac0c33Sjakob for (rrset = domain_find_any_rrset(domain, q->zone); rrset; rrset = rrset->next) {
102962ac0c33Sjakob if (rrset->zone == q->zone
103062ac0c33Sjakob #ifdef NSEC3
103162ac0c33Sjakob && rrset_rrtype(rrset) != TYPE_NSEC3
103262ac0c33Sjakob #endif
103362ac0c33Sjakob /*
103462ac0c33Sjakob * Don't include the RRSIG RRset when
103562ac0c33Sjakob * DNSSEC is used, because it is added
103662ac0c33Sjakob * automatically on an per-RRset basis.
103762ac0c33Sjakob */
103862ac0c33Sjakob && !(q->edns.dnssec_ok
103962ac0c33Sjakob && zone_is_secure(q->zone)
104062ac0c33Sjakob && rrset_rrtype(rrset) == TYPE_RRSIG))
104162ac0c33Sjakob {
1042308d2509Sflorian switch(rrset_rrtype(rrset)) {
1043308d2509Sflorian case TYPE_A:
1044308d2509Sflorian case TYPE_AAAA:
1045308d2509Sflorian case TYPE_SOA:
1046308d2509Sflorian case TYPE_MX:
1047308d2509Sflorian case TYPE_PTR:
1048308d2509Sflorian preferred_rrset = rrset;
1049a1bac035Sflorian break;
1050308d2509Sflorian case TYPE_DNSKEY:
1051308d2509Sflorian case TYPE_RRSIG:
1052308d2509Sflorian case TYPE_NSEC:
1053308d2509Sflorian non_preferred_rrset = rrset;
1054308d2509Sflorian break;
1055308d2509Sflorian default:
1056308d2509Sflorian normal_rrset = rrset;
1057308d2509Sflorian }
1058308d2509Sflorian if (preferred_rrset) break;
105962ac0c33Sjakob }
106062ac0c33Sjakob }
1061308d2509Sflorian if (preferred_rrset) {
1062308d2509Sflorian add_rrset(q, answer, ANSWER_SECTION, domain, preferred_rrset);
1063308d2509Sflorian } else if (normal_rrset) {
1064308d2509Sflorian add_rrset(q, answer, ANSWER_SECTION, domain, normal_rrset);
1065308d2509Sflorian } else if (non_preferred_rrset) {
1066308d2509Sflorian add_rrset(q, answer, ANSWER_SECTION, domain, non_preferred_rrset);
1067308d2509Sflorian } else {
106862ac0c33Sjakob answer_nodata(q, answer, original);
106962ac0c33Sjakob return;
107062ac0c33Sjakob }
107162ac0c33Sjakob #ifdef NSEC3
107262ac0c33Sjakob } else if (q->qtype == TYPE_NSEC3) {
107362ac0c33Sjakob answer_nodata(q, answer, original);
107462ac0c33Sjakob return;
107562ac0c33Sjakob #endif
107662ac0c33Sjakob } else if ((rrset = domain_find_rrset(domain, q->zone, q->qtype))) {
107762ac0c33Sjakob add_rrset(q, answer, ANSWER_SECTION, domain, rrset);
107862ac0c33Sjakob } else if ((rrset = domain_find_rrset(domain, q->zone, TYPE_CNAME))) {
107962ac0c33Sjakob int added;
108062ac0c33Sjakob
108162ac0c33Sjakob /*
108262ac0c33Sjakob * If the CNAME is not added it is already in the
108362ac0c33Sjakob * answer, so we have a CNAME loop. Don't follow the
108462ac0c33Sjakob * CNAME target in this case.
108562ac0c33Sjakob */
108662ac0c33Sjakob added = add_rrset(q, answer, ANSWER_SECTION, domain, rrset);
108762ac0c33Sjakob assert(rrset->rr_count > 0);
108862ac0c33Sjakob if (added) {
108962ac0c33Sjakob /* only process first CNAME record */
109062ac0c33Sjakob domain_type *closest_match = rdata_atom_domain(rrset->rrs[0].rdatas[0]);
109162ac0c33Sjakob domain_type *closest_encloser = closest_match;
109262ac0c33Sjakob zone_type* origzone = q->zone;
109362ac0c33Sjakob ++q->cname_count;
109462ac0c33Sjakob
109562ac0c33Sjakob answer_lookup_zone(nsd, q, answer, closest_match->number,
109662ac0c33Sjakob closest_match == closest_encloser,
109762ac0c33Sjakob closest_match, closest_encloser,
109862ac0c33Sjakob domain_dname(closest_match));
109962ac0c33Sjakob q->zone = origzone;
110062ac0c33Sjakob }
11015bcb494bSjakob return;
110262ac0c33Sjakob } else {
110362ac0c33Sjakob answer_nodata(q, answer, original);
110462ac0c33Sjakob return;
110562ac0c33Sjakob }
110662ac0c33Sjakob
1107db7d0d02Sflorian if (q->qclass != CLASS_ANY && q->zone->ns_rrset && answer_needs_ns(q)
1108db7d0d02Sflorian && !minimal_responses) {
11095bcb494bSjakob add_rrset(q, answer, OPTIONAL_AUTHORITY_SECTION, q->zone->apex,
111062ac0c33Sjakob q->zone->ns_rrset);
111162ac0c33Sjakob }
111262ac0c33Sjakob }
111362ac0c33Sjakob
111462ac0c33Sjakob
111562ac0c33Sjakob /*
111662ac0c33Sjakob * Answer with authoritative data. If a wildcard is matched the owner
111762ac0c33Sjakob * name will be expanded to the domain name specified by
111862ac0c33Sjakob * DOMAIN_NUMBER. DOMAIN_NUMBER 0 (zero) is reserved for the original
111962ac0c33Sjakob * query name.
112062ac0c33Sjakob *
112162ac0c33Sjakob * DNSSEC: Include the necessary NSEC records in case the request
112262ac0c33Sjakob * domain name does not exist and/or a wildcard match does not exist.
112362ac0c33Sjakob */
112462ac0c33Sjakob static void
answer_authoritative(struct nsd * nsd,struct query * q,answer_type * answer,size_t domain_number,int exact,domain_type * closest_match,domain_type * closest_encloser,const dname_type * qname)112562ac0c33Sjakob answer_authoritative(struct nsd *nsd,
112662ac0c33Sjakob struct query *q,
112762ac0c33Sjakob answer_type *answer,
1128dd5b221eSsthen size_t domain_number,
112962ac0c33Sjakob int exact,
113062ac0c33Sjakob domain_type *closest_match,
113162ac0c33Sjakob domain_type *closest_encloser,
113262ac0c33Sjakob const dname_type *qname)
113362ac0c33Sjakob {
113462ac0c33Sjakob domain_type *match;
113562ac0c33Sjakob domain_type *original = closest_match;
1136275a8d89Sflorian domain_type *dname_ce;
11378d298c9fSsthen domain_type *wildcard_child;
113862ac0c33Sjakob rrset_type *rrset;
113962ac0c33Sjakob
114062ac0c33Sjakob #ifdef NSEC3
114162ac0c33Sjakob if(exact && domain_has_only_NSEC3(closest_match, q->zone)) {
114262ac0c33Sjakob exact = 0; /* pretend it does not exist */
114362ac0c33Sjakob if(closest_encloser->parent)
114462ac0c33Sjakob closest_encloser = closest_encloser->parent;
114562ac0c33Sjakob }
114662ac0c33Sjakob #endif /* NSEC3 */
1147275a8d89Sflorian if((dname_ce = find_dname_above(closest_encloser, q->zone)) != NULL) {
1148275a8d89Sflorian /* occlude the found data, the DNAME is closest_encloser */
1149275a8d89Sflorian closest_encloser = dname_ce;
1150275a8d89Sflorian exact = 0;
1151275a8d89Sflorian }
115262ac0c33Sjakob
115362ac0c33Sjakob if (exact) {
115462ac0c33Sjakob match = closest_match;
115562ac0c33Sjakob } else if ((rrset=domain_find_rrset(closest_encloser, q->zone, TYPE_DNAME))) {
115662ac0c33Sjakob /* process DNAME */
115762ac0c33Sjakob const dname_type* name = qname;
11588d298c9fSsthen domain_type* src = closest_encloser;
115962ac0c33Sjakob domain_type *dest = rdata_atom_domain(rrset->rrs[0].rdatas[0]);
11608d298c9fSsthen const dname_type* newname;
11618d298c9fSsthen size_t newnum = 0;
11628d298c9fSsthen zone_type* origzone = q->zone;
116362ac0c33Sjakob assert(rrset->rr_count > 0);
116462ac0c33Sjakob if(domain_number != 0) /* we followed CNAMEs or DNAMEs */
116562ac0c33Sjakob name = domain_dname(closest_match);
116662ac0c33Sjakob DEBUG(DEBUG_QUERY,2, (LOG_INFO, "expanding DNAME for q=%s", dname_to_string(name, NULL)));
116762ac0c33Sjakob DEBUG(DEBUG_QUERY,2, (LOG_INFO, "->src is %s",
1168dd5b221eSsthen domain_to_string(closest_encloser)));
116962ac0c33Sjakob DEBUG(DEBUG_QUERY,2, (LOG_INFO, "->dest is %s",
1170dd5b221eSsthen domain_to_string(dest)));
11718d298c9fSsthen if(!add_rrset(q, answer, ANSWER_SECTION, closest_encloser, rrset)) {
11728d298c9fSsthen /* stop if DNAME loops, when added second time */
11738d298c9fSsthen if(dname_is_subdomain(domain_dname(dest), domain_dname(src))) {
11748d298c9fSsthen return;
11758d298c9fSsthen }
11768d298c9fSsthen }
11778d298c9fSsthen newname = dname_replace(q->region, name,
117862ac0c33Sjakob domain_dname(src), domain_dname(dest));
117962ac0c33Sjakob ++q->cname_count;
118062ac0c33Sjakob if(!newname) { /* newname too long */
118162ac0c33Sjakob RCODE_SET(q->packet, RCODE_YXDOMAIN);
11828d298c9fSsthen /* RFC 8914 - Extended DNS Errors
11838d298c9fSsthen * 4.21. Extended DNS Error Code 0 - Other */
11848d298c9fSsthen ASSIGN_EDE_CODE_AND_STRING_LITERAL(q->edns.ede,
11858d298c9fSsthen EDE_OTHER, "DNAME expansion became too large");
118662ac0c33Sjakob return;
118762ac0c33Sjakob }
118862ac0c33Sjakob DEBUG(DEBUG_QUERY,2, (LOG_INFO, "->result is %s", dname_to_string(newname, NULL)));
118962ac0c33Sjakob /* follow the DNAME */
1190b90bb40eSsthen (void)namedb_lookup(nsd->db, newname, &closest_match, &closest_encloser);
119162ac0c33Sjakob /* synthesize CNAME record */
119262ac0c33Sjakob newnum = query_synthesize_cname(q, answer, name, newname,
119321c23707Sbrad src, closest_encloser, &closest_match, rrset->rrs[0].ttl);
119462ac0c33Sjakob if(!newnum) {
119562ac0c33Sjakob /* could not synthesize the CNAME. */
119662ac0c33Sjakob /* return previous CNAMEs to make resolver recurse for us */
119762ac0c33Sjakob return;
119862ac0c33Sjakob }
11998d298c9fSsthen if(q->qtype == TYPE_CNAME) {
12008d298c9fSsthen /* The synthesized CNAME is the answer to
12018d298c9fSsthen * that query, same as BIND does for query
12028d298c9fSsthen * of type CNAME */
12038d298c9fSsthen return;
12048d298c9fSsthen }
120562ac0c33Sjakob
120662ac0c33Sjakob answer_lookup_zone(nsd, q, answer, newnum,
120762ac0c33Sjakob closest_match == closest_encloser,
120862ac0c33Sjakob closest_match, closest_encloser, newname);
120962ac0c33Sjakob q->zone = origzone;
121062ac0c33Sjakob return;
12118d298c9fSsthen } else if ((wildcard_child=domain_wildcard_child(closest_encloser))!=NULL &&
12128d298c9fSsthen wildcard_child->is_existing) {
121362ac0c33Sjakob /* Generate the domain from the wildcard. */
121475343be4Ssthen #ifdef RATELIMIT
121575343be4Ssthen q->wildcard_domain = wildcard_child;
121675343be4Ssthen #endif
121762ac0c33Sjakob
121862ac0c33Sjakob match = (domain_type *) region_alloc(q->region,
121962ac0c33Sjakob sizeof(domain_type));
1220c1e73312Sflorian #ifdef USE_RADIX_TREE
1221dd5b221eSsthen match->rnode = NULL;
1222dd5b221eSsthen match->dname = wildcard_child->dname;
1223c1e73312Sflorian #else
1224fe5fe5f6Sflorian memcpy(&match->node, &wildcard_child->node, sizeof(rbnode_type));
1225c1e73312Sflorian match->node.parent = NULL;
1226c1e73312Sflorian #endif
122762ac0c33Sjakob match->parent = closest_encloser;
122862ac0c33Sjakob match->wildcard_child_closest_match = match;
122962ac0c33Sjakob match->number = domain_number;
123062ac0c33Sjakob match->rrsets = wildcard_child->rrsets;
123162ac0c33Sjakob match->is_existing = wildcard_child->is_existing;
123262ac0c33Sjakob #ifdef NSEC3
1233dd5b221eSsthen match->nsec3 = wildcard_child->nsec3;
1234dd5b221eSsthen /* copy over these entries:
12355bcb494bSjakob match->nsec3_is_exact = wildcard_child->nsec3_is_exact;
1236dd5b221eSsthen match->nsec3_cover = wildcard_child->nsec3_cover;
123762ac0c33Sjakob match->nsec3_wcard_child_cover = wildcard_child->nsec3_wcard_child_cover;
123862ac0c33Sjakob match->nsec3_ds_parent_is_exact = wildcard_child->nsec3_ds_parent_is_exact;
123962ac0c33Sjakob match->nsec3_ds_parent_cover = wildcard_child->nsec3_ds_parent_cover;
1240dd5b221eSsthen */
1241dd5b221eSsthen
1242dd5b221eSsthen if (q->edns.dnssec_ok && q->zone->nsec3_param) {
124362ac0c33Sjakob /* Only add nsec3 wildcard data when do bit is set */
1244dd5b221eSsthen nsec3_answer_wildcard(q, answer, wildcard_child, qname);
124562ac0c33Sjakob }
124662ac0c33Sjakob #endif
124762ac0c33Sjakob
124862ac0c33Sjakob /*
124962ac0c33Sjakob * Remember the original domain in case a Wildcard No
125062ac0c33Sjakob * Data (3.1.3.4) response needs to be generated. In
125162ac0c33Sjakob * this particular case the wildcard IS NOT
125262ac0c33Sjakob * expanded.
125362ac0c33Sjakob */
125462ac0c33Sjakob original = wildcard_child;
125562ac0c33Sjakob } else {
125662ac0c33Sjakob match = NULL;
125762ac0c33Sjakob }
125862ac0c33Sjakob
12592fd875a4Ssthen /* Authoritative zone. */
126062ac0c33Sjakob #ifdef NSEC3
1261dd5b221eSsthen if (q->edns.dnssec_ok && q->zone->nsec3_param) {
126262ac0c33Sjakob nsec3_answer_authoritative(&match, q, answer,
1263dd5b221eSsthen closest_encloser, qname);
126462ac0c33Sjakob } else
126562ac0c33Sjakob #endif
126662ac0c33Sjakob if (q->edns.dnssec_ok && zone_is_secure(q->zone)) {
126762ac0c33Sjakob if (match != closest_encloser) {
126862ac0c33Sjakob domain_type *nsec_domain;
126962ac0c33Sjakob rrset_type *nsec_rrset;
127062ac0c33Sjakob
127162ac0c33Sjakob /*
127262ac0c33Sjakob * No match found or generated from wildcard,
127362ac0c33Sjakob * include NSEC record.
127462ac0c33Sjakob */
127562ac0c33Sjakob nsec_domain = find_covering_nsec(closest_match, q->zone, &nsec_rrset);
127662ac0c33Sjakob if (nsec_domain) {
127762ac0c33Sjakob add_rrset(q, answer, AUTHORITY_SECTION, nsec_domain, nsec_rrset);
127862ac0c33Sjakob }
127962ac0c33Sjakob }
128062ac0c33Sjakob if (!match) {
128162ac0c33Sjakob domain_type *nsec_domain;
128262ac0c33Sjakob rrset_type *nsec_rrset;
128362ac0c33Sjakob
128462ac0c33Sjakob /*
128562ac0c33Sjakob * No match and no wildcard. Include NSEC
128662ac0c33Sjakob * proving there is no wildcard.
128762ac0c33Sjakob */
1288a1bac035Sflorian if(closest_encloser && (nsec_domain =
1289a1bac035Sflorian find_covering_nsec(closest_encloser->
1290a1bac035Sflorian wildcard_child_closest_match, q->zone,
1291a1bac035Sflorian &nsec_rrset)) != NULL) {
129262ac0c33Sjakob add_rrset(q, answer, AUTHORITY_SECTION, nsec_domain, nsec_rrset);
129362ac0c33Sjakob }
129462ac0c33Sjakob }
129562ac0c33Sjakob }
129662ac0c33Sjakob
129762ac0c33Sjakob #ifdef NSEC3
129862ac0c33Sjakob if (RCODE(q->packet)!=RCODE_OK) {
129962ac0c33Sjakob return; /* nsec3 collision failure */
130062ac0c33Sjakob }
130162ac0c33Sjakob #endif
130262ac0c33Sjakob if (match) {
130362ac0c33Sjakob answer_domain(nsd, q, answer, match, original);
130462ac0c33Sjakob } else {
130562ac0c33Sjakob answer_nxdomain(q, answer);
130662ac0c33Sjakob }
130762ac0c33Sjakob }
130862ac0c33Sjakob
130962ac0c33Sjakob /*
131062ac0c33Sjakob * qname may be different after CNAMEs have been followed from query->qname.
131162ac0c33Sjakob */
131262ac0c33Sjakob static void
answer_lookup_zone(struct nsd * nsd,struct query * q,answer_type * answer,size_t domain_number,int exact,domain_type * closest_match,domain_type * closest_encloser,const dname_type * qname)131362ac0c33Sjakob answer_lookup_zone(struct nsd *nsd, struct query *q, answer_type *answer,
1314dd5b221eSsthen size_t domain_number, int exact, domain_type *closest_match,
131562ac0c33Sjakob domain_type *closest_encloser, const dname_type *qname)
131662ac0c33Sjakob {
13175435475dSsthen zone_type* origzone = q->zone;
13185fab9a23Sbrad q->zone = domain_find_zone(nsd->db, closest_encloser);
131962ac0c33Sjakob if (!q->zone) {
13205fab9a23Sbrad /* no zone for this */
13218d298c9fSsthen if(q->cname_count == 0) {
13225fab9a23Sbrad RCODE_SET(q->packet, RCODE_REFUSE);
13238d298c9fSsthen /* RFC 8914 - Extended DNS Errors
13248d298c9fSsthen * 4.21. Extended DNS Error Code 20 - Not Authoritative */
13258d298c9fSsthen q->edns.ede = EDE_NOT_AUTHORITATIVE;
13268d298c9fSsthen }
13275fab9a23Sbrad return;
13285fab9a23Sbrad }
1329bfd0b123Sflorian assert(closest_encloser); /* otherwise, no q->zone would be found */
13308d298c9fSsthen if(q->zone->opts && q->zone->opts->pattern
13318d298c9fSsthen && q->zone->opts->pattern->allow_query) {
13328d298c9fSsthen struct acl_options *why = NULL;
13338d298c9fSsthen
13348d298c9fSsthen /* check if it passes acl */
1335b71395eaSflorian if(q->is_proxied && acl_check_incoming_block_proxy(
1336b71395eaSflorian q->zone->opts->pattern->allow_query, q, &why) == -1) {
1337b71395eaSflorian /* the proxy address is blocked */
1338b71395eaSflorian if (verbosity >= 2) {
1339b71395eaSflorian char address[128], proxy[128];
1340b71395eaSflorian addr2str(&q->client_addr, address, sizeof(address));
1341b71395eaSflorian addr2str(&q->remote_addr, proxy, sizeof(proxy));
1342b71395eaSflorian VERBOSITY(2, (LOG_INFO, "query %s from %s via proxy %s refused because of proxy, %s %s",
1343b71395eaSflorian dname_to_string(q->qname, NULL),
1344b71395eaSflorian address, proxy,
1345b71395eaSflorian (why?why->ip_address_spec:"."),
1346b71395eaSflorian (why ? ( why->nokey ? "NOKEY"
1347b71395eaSflorian : why->blocked ? "BLOCKED"
1348b71395eaSflorian : why->key_name )
1349b71395eaSflorian : "no acl matches")));
1350b71395eaSflorian }
1351b71395eaSflorian /* no zone for this */
1352b71395eaSflorian if(q->cname_count == 0) {
1353b71395eaSflorian RCODE_SET(q->packet, RCODE_REFUSE);
1354b71395eaSflorian /* RFC8914 - Extended DNS Errors
1355b71395eaSflorian * 4.19. Extended DNS Error Code 18 - Prohibited */
1356b71395eaSflorian q->edns.ede = EDE_PROHIBITED;
1357b71395eaSflorian }
1358b71395eaSflorian return;
1359b71395eaSflorian }
13608d298c9fSsthen if(acl_check_incoming(
13618d298c9fSsthen q->zone->opts->pattern->allow_query, q, &why) != -1) {
13628d298c9fSsthen assert(why);
13638d298c9fSsthen DEBUG(DEBUG_QUERY,1, (LOG_INFO, "query %s passed acl %s %s",
13648d298c9fSsthen dname_to_string(q->qname, NULL),
13658d298c9fSsthen why->ip_address_spec,
13668d298c9fSsthen why->nokey?"NOKEY":
13678d298c9fSsthen (why->blocked?"BLOCKED":why->key_name)));
1368*bf87c3c0Sflorian } else if(q->qtype == TYPE_SOA
1369*bf87c3c0Sflorian && 0 == dname_compare(q->qname,
1370*bf87c3c0Sflorian (const dname_type*)q->zone->opts->node.key)
1371*bf87c3c0Sflorian && -1 != acl_check_incoming(
1372*bf87c3c0Sflorian q->zone->opts->pattern->provide_xfr, q,&why)) {
1373*bf87c3c0Sflorian assert(why);
1374*bf87c3c0Sflorian DEBUG(DEBUG_QUERY,1, (LOG_INFO, "SOA apex query %s "
1375*bf87c3c0Sflorian "passed request-xfr acl %s %s",
1376*bf87c3c0Sflorian dname_to_string(q->qname, NULL),
1377*bf87c3c0Sflorian why->ip_address_spec,
1378*bf87c3c0Sflorian why->nokey?"NOKEY":
1379*bf87c3c0Sflorian (why->blocked?"BLOCKED":why->key_name)));
13808d298c9fSsthen } else {
13818d298c9fSsthen if (verbosity >= 2) {
13828d298c9fSsthen char address[128];
1383b71395eaSflorian addr2str(&q->client_addr, address, sizeof(address));
13848d298c9fSsthen VERBOSITY(2, (LOG_INFO, "query %s from %s refused, %s %s",
13858d298c9fSsthen dname_to_string(q->qname, NULL),
13868d298c9fSsthen address,
13878d298c9fSsthen why ? ( why->nokey ? "NOKEY"
13888d298c9fSsthen : why->blocked ? "BLOCKED"
13898d298c9fSsthen : why->key_name )
13908d298c9fSsthen : "no acl matches",
13918d298c9fSsthen why?why->ip_address_spec:"."));
13928d298c9fSsthen }
13938d298c9fSsthen /* no zone for this */
13948d298c9fSsthen if(q->cname_count == 0) {
13958d298c9fSsthen RCODE_SET(q->packet, RCODE_REFUSE);
13968d298c9fSsthen /* RFC8914 - Extended DNS Errors
13978d298c9fSsthen * 4.19. Extended DNS Error Code 18 - Prohibited */
13988d298c9fSsthen q->edns.ede = EDE_PROHIBITED;
13998d298c9fSsthen }
14008d298c9fSsthen return;
14018d298c9fSsthen }
14028d298c9fSsthen }
14035fab9a23Sbrad if(!q->zone->apex || !q->zone->soa_rrset) {
14045fab9a23Sbrad /* zone is configured but not loaded */
14058d298c9fSsthen if(q->cname_count == 0) {
140662ac0c33Sjakob RCODE_SET(q->packet, RCODE_SERVFAIL);
14078d298c9fSsthen /* RFC 8914 - Extended DNS Errors
14088d298c9fSsthen * 4.15. Extended DNS Error Code 14 - Not Ready */
14098d298c9fSsthen q->edns.ede = EDE_NOT_READY;
14108d298c9fSsthen ASSIGN_EDE_CODE_AND_STRING_LITERAL(q->edns.ede,
14118d298c9fSsthen EDE_NOT_READY, "Zone is configured but not loaded");
14128d298c9fSsthen }
141362ac0c33Sjakob return;
141462ac0c33Sjakob }
14155435475dSsthen
14165435475dSsthen /*
14175435475dSsthen * If confine-to-zone is set to yes do not return additional
14185435475dSsthen * information for a zone with a different apex from the query zone.
14195435475dSsthen */
14205435475dSsthen if (nsd->options->confine_to_zone &&
14215435475dSsthen (origzone != NULL && dname_compare(domain_dname(origzone->apex), domain_dname(q->zone->apex)) != 0)) {
14225435475dSsthen return;
14235435475dSsthen }
14245435475dSsthen
1425275a8d89Sflorian /* now move up the closest encloser until it exists, previous
1426275a8d89Sflorian * (possibly empty) closest encloser was useful to finding the zone
1427275a8d89Sflorian * (for empty zones too), but now we want actual data nodes */
1428275a8d89Sflorian if (closest_encloser && !closest_encloser->is_existing) {
1429275a8d89Sflorian exact = 0;
1430275a8d89Sflorian while (closest_encloser != NULL && !closest_encloser->is_existing)
1431275a8d89Sflorian closest_encloser = closest_encloser->parent;
1432275a8d89Sflorian }
143362ac0c33Sjakob
143462ac0c33Sjakob /*
143562ac0c33Sjakob * See RFC 4035 (DNSSEC protocol) section 3.1.4.1 Responding
143662ac0c33Sjakob * to Queries for DS RRs.
143762ac0c33Sjakob */
143862ac0c33Sjakob if (exact && q->qtype == TYPE_DS && closest_encloser == q->zone->apex) {
143962ac0c33Sjakob /*
144062ac0c33Sjakob * Type DS query at a zone cut, use the responsible
144162ac0c33Sjakob * parent zone to generate the answer if we are
144262ac0c33Sjakob * authoritative for the parent zone.
144362ac0c33Sjakob */
14446e9bf1eeSflorian zone_type *zone = domain_find_parent_zone(nsd->db, q->zone);
1445ee5153b7Sflorian if (zone) {
144662ac0c33Sjakob q->zone = zone;
1447ee5153b7Sflorian if(!q->zone->apex || !q->zone->soa_rrset) {
1448ee5153b7Sflorian /* zone is configured but not loaded */
14498d298c9fSsthen if(q->cname_count == 0) {
1450ee5153b7Sflorian RCODE_SET(q->packet, RCODE_SERVFAIL);
14518d298c9fSsthen /* RFC 8914 - Extended DNS Errors
14528d298c9fSsthen * 4.15. Extended DNS Error Code 14 - Not Ready */
14538d298c9fSsthen ASSIGN_EDE_CODE_AND_STRING_LITERAL(
14548d298c9fSsthen q->edns.ede, EDE_NOT_READY,
14558d298c9fSsthen "Zone is configured but not loaded");
14568d298c9fSsthen }
1457ee5153b7Sflorian return;
1458ee5153b7Sflorian }
1459ee5153b7Sflorian }
146062ac0c33Sjakob }
146162ac0c33Sjakob
146262ac0c33Sjakob /* see if the zone has expired (for secondary zones) */
1463dd5b221eSsthen if(q->zone && q->zone->opts && q->zone->opts->pattern &&
1464dd5b221eSsthen q->zone->opts->pattern->request_xfr != 0 && !q->zone->is_ok) {
14658d298c9fSsthen if(q->cname_count == 0) {
146662ac0c33Sjakob RCODE_SET(q->packet, RCODE_SERVFAIL);
14678d298c9fSsthen /* RFC 8914 - Extended DNS Errors
14688d298c9fSsthen * 4.25. Extended DNS Error Code 24 - Invalid Data */
14698d298c9fSsthen ASSIGN_EDE_CODE_AND_STRING_LITERAL(q->edns.ede,
14708d298c9fSsthen EDE_INVALID_DATA, "Zone has expired");
14718d298c9fSsthen }
147262ac0c33Sjakob return;
147362ac0c33Sjakob }
147462ac0c33Sjakob
147562ac0c33Sjakob if (exact && q->qtype == TYPE_DS && closest_encloser == q->zone->apex) {
147662ac0c33Sjakob /*
147762ac0c33Sjakob * Type DS query at the zone apex (and the server is
14782fd875a4Ssthen * not authoritative for the parent zone).
147962ac0c33Sjakob */
148062ac0c33Sjakob if (q->qclass == CLASS_ANY) {
148162ac0c33Sjakob AA_CLR(q->packet);
148262ac0c33Sjakob } else {
148362ac0c33Sjakob AA_SET(q->packet);
148462ac0c33Sjakob }
148562ac0c33Sjakob answer_nodata(q, answer, closest_encloser);
148662ac0c33Sjakob } else {
148762ac0c33Sjakob q->delegation_domain = domain_find_ns_rrsets(
148862ac0c33Sjakob closest_encloser, q->zone, &q->delegation_rrset);
1489275a8d89Sflorian if(q->delegation_domain && find_dname_above(q->delegation_domain, q->zone)) {
1490275a8d89Sflorian q->delegation_domain = NULL; /* use higher DNAME */
1491275a8d89Sflorian }
149262ac0c33Sjakob
149362ac0c33Sjakob if (!q->delegation_domain
1494a904e103Sflorian || !q->delegation_rrset
149562ac0c33Sjakob || (exact && q->qtype == TYPE_DS && closest_encloser == q->delegation_domain))
149662ac0c33Sjakob {
149762ac0c33Sjakob if (q->qclass == CLASS_ANY) {
149862ac0c33Sjakob AA_CLR(q->packet);
149962ac0c33Sjakob } else {
150062ac0c33Sjakob AA_SET(q->packet);
150162ac0c33Sjakob }
150262ac0c33Sjakob answer_authoritative(nsd, q, answer, domain_number, exact,
150362ac0c33Sjakob closest_match, closest_encloser, qname);
150462ac0c33Sjakob }
150562ac0c33Sjakob else {
150662ac0c33Sjakob answer_delegation(q, answer);
150762ac0c33Sjakob }
150862ac0c33Sjakob }
150962ac0c33Sjakob }
151062ac0c33Sjakob
151162ac0c33Sjakob static void
answer_query(struct nsd * nsd,struct query * q)151262ac0c33Sjakob answer_query(struct nsd *nsd, struct query *q)
151362ac0c33Sjakob {
151462ac0c33Sjakob domain_type *closest_match;
151562ac0c33Sjakob domain_type *closest_encloser;
151662ac0c33Sjakob int exact;
151762ac0c33Sjakob uint16_t offset;
151862ac0c33Sjakob answer_type answer;
151962ac0c33Sjakob
152062ac0c33Sjakob answer_init(&answer);
152162ac0c33Sjakob
152262ac0c33Sjakob exact = namedb_lookup(nsd->db, q->qname, &closest_match, &closest_encloser);
152362ac0c33Sjakob
152462ac0c33Sjakob answer_lookup_zone(nsd, q, &answer, 0, exact, closest_match,
152562ac0c33Sjakob closest_encloser, q->qname);
1526c1404d4fSbrad ZTATUP2(nsd, q->zone, opcode, q->opcode);
1527c1404d4fSbrad ZTATUP2(nsd, q->zone, qtype, q->qtype);
1528c1404d4fSbrad ZTATUP2(nsd, q->zone, qclass, q->qclass);
152962ac0c33Sjakob
153062ac0c33Sjakob offset = dname_label_offsets(q->qname)[domain_dname(closest_encloser)->label_count - 1] + QHEADERSZ;
153162ac0c33Sjakob query_add_compression_domain(q, closest_encloser, offset);
1532d11a62c8Ssthen encode_answer(q, &answer);
153362ac0c33Sjakob query_clear_compression_tables(q);
153462ac0c33Sjakob }
153562ac0c33Sjakob
153662ac0c33Sjakob void
query_prepare_response(query_type * q)1537c1e73312Sflorian query_prepare_response(query_type *q)
153862ac0c33Sjakob {
153962ac0c33Sjakob uint16_t flags;
154062ac0c33Sjakob
154162ac0c33Sjakob /*
154262ac0c33Sjakob * Preserve the data up-to the current packet's limit.
154362ac0c33Sjakob */
154462ac0c33Sjakob buffer_set_position(q->packet, buffer_limit(q->packet));
154562ac0c33Sjakob buffer_set_limit(q->packet, buffer_capacity(q->packet));
154662ac0c33Sjakob
154762ac0c33Sjakob /*
154862ac0c33Sjakob * Reserve space for the EDNS records if required.
154962ac0c33Sjakob */
155062ac0c33Sjakob q->reserved_space = edns_reserved_space(&q->edns);
155162ac0c33Sjakob q->reserved_space += tsig_reserved_space(&q->tsig);
155262ac0c33Sjakob
155362ac0c33Sjakob /* Update the flags. */
155462ac0c33Sjakob flags = FLAGS(q->packet);
155562ac0c33Sjakob flags &= 0x0100U; /* Preserve the RD flag. */
155662ac0c33Sjakob /* CD flag must be cleared for auth answers */
155762ac0c33Sjakob flags |= 0x8000U; /* Set the QR flag. */
155862ac0c33Sjakob FLAGS_SET(q->packet, flags);
155962ac0c33Sjakob }
156062ac0c33Sjakob
156162ac0c33Sjakob /*
156262ac0c33Sjakob * Processes the query.
156362ac0c33Sjakob *
156462ac0c33Sjakob */
156562ac0c33Sjakob query_state_type
query_process(query_type * q,nsd_type * nsd,uint32_t * now_p)1566063644e9Sflorian query_process(query_type *q, nsd_type *nsd, uint32_t *now_p)
156762ac0c33Sjakob {
156862ac0c33Sjakob /* The query... */
156962ac0c33Sjakob nsd_rc_type rc;
157062ac0c33Sjakob query_state_type query_state;
157162ac0c33Sjakob uint16_t arcount;
157262ac0c33Sjakob
157362ac0c33Sjakob /* Sanity checks */
157462ac0c33Sjakob if (buffer_limit(q->packet) < QHEADERSZ) {
157562ac0c33Sjakob /* packet too small to contain DNS header.
157662ac0c33Sjakob Now packet investigation macros will work without problems. */
157762ac0c33Sjakob return QUERY_DISCARDED;
157862ac0c33Sjakob }
157962ac0c33Sjakob if (QR(q->packet)) {
158062ac0c33Sjakob /* Not a query? Drop it on the floor. */
158162ac0c33Sjakob return QUERY_DISCARDED;
158262ac0c33Sjakob }
158362ac0c33Sjakob
15843126abd5Ssthen /* check opcode early on, because new opcodes may have different
15853126abd5Ssthen * specification of the meaning of the rest of the packet */
15863126abd5Ssthen q->opcode = OPCODE(q->packet);
15873126abd5Ssthen if(q->opcode != OPCODE_QUERY && q->opcode != OPCODE_NOTIFY) {
15883126abd5Ssthen if(query_ratelimit_err(nsd))
15893126abd5Ssthen return QUERY_DISCARDED;
1590308d2509Sflorian if(nsd->options->drop_updates && q->opcode == OPCODE_UPDATE)
1591308d2509Sflorian return QUERY_DISCARDED;
15923126abd5Ssthen return query_error(q, NSD_RC_IMPL);
15933126abd5Ssthen }
15943126abd5Ssthen
1595d11a62c8Ssthen if (RCODE(q->packet) != RCODE_OK || !process_query_section(q)) {
15968d8f1862Ssthen return query_formerr(q, nsd);
159762ac0c33Sjakob }
159862ac0c33Sjakob
159962ac0c33Sjakob /* Update statistics. */
160062ac0c33Sjakob STATUP2(nsd, opcode, q->opcode);
160162ac0c33Sjakob STATUP2(nsd, qtype, q->qtype);
160262ac0c33Sjakob STATUP2(nsd, qclass, q->qclass);
160362ac0c33Sjakob
160462ac0c33Sjakob if (q->opcode != OPCODE_QUERY) {
160562ac0c33Sjakob if (q->opcode == OPCODE_NOTIFY) {
160662ac0c33Sjakob return answer_notify(nsd, q);
160762ac0c33Sjakob } else {
16088d8f1862Ssthen if(query_ratelimit_err(nsd))
16098d8f1862Ssthen return QUERY_DISCARDED;
161062ac0c33Sjakob return query_error(q, NSD_RC_IMPL);
161162ac0c33Sjakob }
161262ac0c33Sjakob }
161362ac0c33Sjakob
161462ac0c33Sjakob /* Dont bother to answer more than one question at once... */
1615d11a62c8Ssthen if (QDCOUNT(q->packet) != 1) {
1616977db6e5Sflorian if(QDCOUNT(q->packet) == 0 && ANCOUNT(q->packet) == 0 &&
1617977db6e5Sflorian NSCOUNT(q->packet) == 0 && ARCOUNT(q->packet) == 1 &&
1618977db6e5Sflorian buffer_limit(q->packet) >= QHEADERSZ+OPT_LEN+
1619977db6e5Sflorian OPT_RDATA) {
1620977db6e5Sflorian /* add edns section to answer */
1621977db6e5Sflorian buffer_set_position(q->packet, QHEADERSZ);
1622977db6e5Sflorian if (edns_parse_record(&q->edns, q->packet, q, nsd)) {
1623977db6e5Sflorian if(process_edns(nsd, q) == NSD_RC_OK) {
1624977db6e5Sflorian int opcode = OPCODE(q->packet);
1625977db6e5Sflorian (void)query_error(q, NSD_RC_FORMAT);
1626063644e9Sflorian query_add_optional(q, nsd, now_p);
1627977db6e5Sflorian FLAGS_SET(q->packet, FLAGS(q->packet) & 0x0100U);
1628977db6e5Sflorian /* Preserve the RD flag. Clear the rest. */
1629977db6e5Sflorian OPCODE_SET(q->packet, opcode);
1630977db6e5Sflorian QR_SET(q->packet);
1631977db6e5Sflorian return QUERY_PROCESSED;
1632977db6e5Sflorian }
1633977db6e5Sflorian }
1634977db6e5Sflorian }
163562ac0c33Sjakob FLAGS_SET(q->packet, 0);
16368d8f1862Ssthen return query_formerr(q, nsd);
163762ac0c33Sjakob }
1638d11a62c8Ssthen /* Ignore settings of flags */
163962ac0c33Sjakob
164062ac0c33Sjakob /* Dont allow any records in the answer or authority section...
164162ac0c33Sjakob except for IXFR queries. */
164262ac0c33Sjakob if (ANCOUNT(q->packet) != 0 ||
164362ac0c33Sjakob (q->qtype!=TYPE_IXFR && NSCOUNT(q->packet) != 0)) {
16448d8f1862Ssthen return query_formerr(q, nsd);
164562ac0c33Sjakob }
164662ac0c33Sjakob if(q->qtype==TYPE_IXFR && NSCOUNT(q->packet) > 0) {
1647308d2509Sflorian unsigned int i; /* skip ixfr soa information data here */
1648308d2509Sflorian unsigned int nscount = (unsigned)NSCOUNT(q->packet);
1649308d2509Sflorian /* define a bound on the number of extraneous records allowed,
1650308d2509Sflorian * we expect 1, a SOA serial record, and no more.
1651308d2509Sflorian * perhaps RRSIGs (but not needed), otherwise we do not
1652308d2509Sflorian * understand what this means. We do not want too many
1653308d2509Sflorian * because the high iteration counts slow down. */
1654308d2509Sflorian if(nscount > 64) return query_formerr(q, nsd);
1655308d2509Sflorian for(i=0; i< nscount; i++)
165662ac0c33Sjakob if(!packet_skip_rr(q->packet, 0))
16578d8f1862Ssthen return query_formerr(q, nsd);
165862ac0c33Sjakob }
165962ac0c33Sjakob
166062ac0c33Sjakob arcount = ARCOUNT(q->packet);
16618d298c9fSsthen /* A TSIG RR is not allowed before the EDNS OPT RR.
16628d298c9fSsthen * In RFC6891 (about EDNS) it says:
16639c620270Ssthen * "The placement flexibility for the OPT RR does not
16649c620270Ssthen * override the need for the TSIG or SIG(0) RRs to be
16659c620270Ssthen * the last in the additional section whenever they are
16669c620270Ssthen * present."
16678d298c9fSsthen * And in RFC8945 (about TSIG) it says:
16688d298c9fSsthen * "If multiple TSIG records are detected or a TSIG record is
16698d298c9fSsthen * present in any other position, the DNS message is dropped
16708d298c9fSsthen * and a response with RCODE 1 (FORMERR) MUST be returned."
16719c620270Ssthen */
16729c620270Ssthen /* See if there is an OPT RR. */
167362ac0c33Sjakob if (arcount > 0) {
1674c1e73312Sflorian if (edns_parse_record(&q->edns, q->packet, q, nsd))
167562ac0c33Sjakob --arcount;
167662ac0c33Sjakob }
16779c620270Ssthen /* See if there is a TSIG RR. */
167862ac0c33Sjakob if (arcount > 0 && q->tsig.status == TSIG_NOT_PRESENT) {
167962ac0c33Sjakob /* see if tsig is after the edns record */
168062ac0c33Sjakob if (!tsig_parse_rr(&q->tsig, q->packet))
16818d8f1862Ssthen return query_formerr(q, nsd);
168262ac0c33Sjakob if(q->tsig.status != TSIG_NOT_PRESENT)
168362ac0c33Sjakob --arcount;
168462ac0c33Sjakob }
16859c620270Ssthen /* If more RRs left in Add. Section, FORMERR. */
168662ac0c33Sjakob if (arcount > 0) {
16878d8f1862Ssthen return query_formerr(q, nsd);
168862ac0c33Sjakob }
168962ac0c33Sjakob
169062ac0c33Sjakob /* Do we have any trailing garbage? */
169162ac0c33Sjakob #ifdef STRICT_MESSAGE_PARSE
169262ac0c33Sjakob if (buffer_remaining(q->packet) > 0) {
169362ac0c33Sjakob /* If we're strict.... */
16948d8f1862Ssthen return query_formerr(q, nsd);
169562ac0c33Sjakob }
169662ac0c33Sjakob #endif
169762ac0c33Sjakob /* Remove trailing garbage. */
169862ac0c33Sjakob buffer_set_limit(q->packet, buffer_position(q->packet));
169962ac0c33Sjakob
170062ac0c33Sjakob rc = process_tsig(q);
170162ac0c33Sjakob if (rc != NSD_RC_OK) {
170262ac0c33Sjakob return query_error(q, rc);
170362ac0c33Sjakob }
170462ac0c33Sjakob rc = process_edns(nsd, q);
170562ac0c33Sjakob if (rc != NSD_RC_OK) {
170662ac0c33Sjakob /* We should not return FORMERR, but BADVERS (=16).
170762ac0c33Sjakob * BADVERS is created with Ext. RCODE, followed by RCODE.
170862ac0c33Sjakob * Ext. RCODE is set to 1, RCODE must be 0 (getting 0x10 = 16).
170962ac0c33Sjakob * Thus RCODE = NOERROR = NSD_RC_OK. */
1710ac5517e4Sflorian RCODE_SET(q->packet, NSD_RC_OK);
1711ac5517e4Sflorian buffer_clear(q->packet);
1712ac5517e4Sflorian buffer_set_position(q->packet,
1713ac5517e4Sflorian QHEADERSZ + 4 + q->qname->name_size);
1714ac5517e4Sflorian QR_SET(q->packet);
1715ac5517e4Sflorian AD_CLR(q->packet);
1716ac5517e4Sflorian QDCOUNT_SET(q->packet, 1);
1717ac5517e4Sflorian ANCOUNT_SET(q->packet, 0);
1718ac5517e4Sflorian NSCOUNT_SET(q->packet, 0);
1719ac5517e4Sflorian ARCOUNT_SET(q->packet, 0);
1720ac5517e4Sflorian return QUERY_PROCESSED;
172162ac0c33Sjakob }
172262ac0c33Sjakob
1723063644e9Sflorian if (q->edns.cookie_status == COOKIE_UNVERIFIED)
1724063644e9Sflorian cookie_verify(q, nsd, now_p);
1725063644e9Sflorian
1726c1e73312Sflorian query_prepare_response(q);
172762ac0c33Sjakob
172862ac0c33Sjakob if (q->qclass != CLASS_IN && q->qclass != CLASS_ANY) {
172962ac0c33Sjakob if (q->qclass == CLASS_CH) {
173062ac0c33Sjakob return answer_chaos(nsd, q);
173162ac0c33Sjakob } else {
17328d298c9fSsthen /* RFC8914 - Extended DNS Errors
17338d298c9fSsthen * 4.22. Extended DNS Error Code 21 - Not Supported */
17348d298c9fSsthen q->edns.ede = EDE_NOT_SUPPORTED;
17358d298c9fSsthen return query_error(q, RCODE_REFUSE);
173662ac0c33Sjakob }
173762ac0c33Sjakob }
173862ac0c33Sjakob query_state = answer_axfr_ixfr(nsd, q);
17394564029fSflorian if (query_state == QUERY_PROCESSED || query_state == QUERY_IN_AXFR
17404564029fSflorian || query_state == QUERY_IN_IXFR) {
174162ac0c33Sjakob return query_state;
174262ac0c33Sjakob }
1743b3163e5fSflorian if(q->qtype == TYPE_ANY && nsd->options->refuse_any && !q->tcp) {
1744b3163e5fSflorian TC_SET(q->packet);
1745b3163e5fSflorian return query_error(q, NSD_RC_OK);
1746b3163e5fSflorian }
174762ac0c33Sjakob
174862ac0c33Sjakob answer_query(nsd, q);
174962ac0c33Sjakob
175062ac0c33Sjakob return QUERY_PROCESSED;
175162ac0c33Sjakob }
175262ac0c33Sjakob
175362ac0c33Sjakob void
query_add_optional(query_type * q,nsd_type * nsd,uint32_t * now_p)1754063644e9Sflorian query_add_optional(query_type *q, nsd_type *nsd, uint32_t *now_p)
175562ac0c33Sjakob {
175662ac0c33Sjakob struct edns_data *edns = &nsd->edns_ipv4;
175762ac0c33Sjakob #if defined(INET6)
1758b71395eaSflorian if (q->client_addr.ss_family == AF_INET6) {
175962ac0c33Sjakob edns = &nsd->edns_ipv6;
176062ac0c33Sjakob }
176162ac0c33Sjakob #endif
1762129edcbcSphessler if (RCODE(q->packet) == RCODE_FORMAT) {
1763129edcbcSphessler return;
1764129edcbcSphessler }
176562ac0c33Sjakob switch (q->edns.status) {
176662ac0c33Sjakob case EDNS_NOT_PRESENT:
176762ac0c33Sjakob break;
176862ac0c33Sjakob case EDNS_OK:
17695bcb494bSjakob if (q->edns.dnssec_ok) edns->ok[7] = 0x80;
17705bcb494bSjakob else edns->ok[7] = 0x00;
177162ac0c33Sjakob buffer_write(q->packet, edns->ok, OPT_LEN);
17728d298c9fSsthen
17738d298c9fSsthen /* Add Extended DNS Error (RFC8914)
17748d298c9fSsthen * to verify that we stay in bounds */
17758d298c9fSsthen if (q->edns.ede >= 0)
17768d298c9fSsthen q->edns.opt_reserved_space +=
17778d298c9fSsthen 6 + ( q->edns.ede_text_len
17788d298c9fSsthen ? q->edns.ede_text_len : 0);
17798d298c9fSsthen
1780c1e73312Sflorian if(q->edns.opt_reserved_space == 0 || !buffer_available(
1781c1e73312Sflorian q->packet, 2+q->edns.opt_reserved_space)) {
1782c1e73312Sflorian /* fill with NULLs */
1783c1e73312Sflorian buffer_write(q->packet, edns->rdata_none, OPT_RDATA);
1784c1e73312Sflorian } else {
178562ac0c33Sjakob /* rdata length */
1786c1e73312Sflorian buffer_write_u16(q->packet, q->edns.opt_reserved_space);
1787c1e73312Sflorian /* edns options */
1788c1e73312Sflorian if(q->edns.nsid) {
178962ac0c33Sjakob /* nsid opt header */
179062ac0c33Sjakob buffer_write(q->packet, edns->nsid, OPT_HDR);
179162ac0c33Sjakob /* nsid payload */
179262ac0c33Sjakob buffer_write(q->packet, nsd->nsid, nsd->nsid_len);
1793c1e73312Sflorian }
1794063644e9Sflorian if(q->edns.cookie_status != COOKIE_NOT_PRESENT) {
1795063644e9Sflorian /* cookie opt header */
1796063644e9Sflorian buffer_write(q->packet, edns->cookie, OPT_HDR);
1797063644e9Sflorian /* cookie payload */
1798063644e9Sflorian cookie_create(q, nsd, now_p);
1799063644e9Sflorian buffer_write(q->packet, q->edns.cookie, 24);
1800063644e9Sflorian }
18018d298c9fSsthen /* Append Extended DNS Error (RFC8914) option if needed */
18028d298c9fSsthen if (q->edns.ede >= 0) { /* < 0 means no EDE */
18038d298c9fSsthen /* OPTION-CODE */
18048d298c9fSsthen buffer_write_u16(q->packet, EDE_CODE);
18058d298c9fSsthen /* OPTION-LENGTH */
18068d298c9fSsthen buffer_write_u16(q->packet,
18078d298c9fSsthen 2 + ( q->edns.ede_text_len
18088d298c9fSsthen ? q->edns.ede_text_len : 0));
18098d298c9fSsthen /* INFO-CODE */
18108d298c9fSsthen buffer_write_u16(q->packet, q->edns.ede);
18118d298c9fSsthen /* EXTRA-TEXT */
18128d298c9fSsthen if (q->edns.ede_text_len)
18138d298c9fSsthen buffer_write(q->packet,
18148d298c9fSsthen q->edns.ede_text,
18158d298c9fSsthen q->edns.ede_text_len);
18168d298c9fSsthen }
181762ac0c33Sjakob }
181862ac0c33Sjakob ARCOUNT_SET(q->packet, ARCOUNT(q->packet) + 1);
181962ac0c33Sjakob STATUP(nsd, edns);
1820c1404d4fSbrad ZTATUP(nsd, q->zone, edns);
182162ac0c33Sjakob break;
182262ac0c33Sjakob case EDNS_ERROR:
18235bcb494bSjakob if (q->edns.dnssec_ok) edns->error[7] = 0x80;
18245bcb494bSjakob else edns->error[7] = 0x00;
182562ac0c33Sjakob buffer_write(q->packet, edns->error, OPT_LEN);
182662ac0c33Sjakob buffer_write(q->packet, edns->rdata_none, OPT_RDATA);
182762ac0c33Sjakob ARCOUNT_SET(q->packet, ARCOUNT(q->packet) + 1);
182862ac0c33Sjakob STATUP(nsd, ednserr);
1829c1404d4fSbrad ZTATUP(nsd, q->zone, ednserr);
183062ac0c33Sjakob break;
183162ac0c33Sjakob }
183262ac0c33Sjakob
183362ac0c33Sjakob if (q->tsig.status != TSIG_NOT_PRESENT) {
183462ac0c33Sjakob if (q->tsig.status == TSIG_ERROR ||
183562ac0c33Sjakob q->tsig.error_code != TSIG_ERROR_NOERROR) {
183662ac0c33Sjakob tsig_error_reply(&q->tsig);
183762ac0c33Sjakob tsig_append_rr(&q->tsig, q->packet);
183862ac0c33Sjakob ARCOUNT_SET(q->packet, ARCOUNT(q->packet) + 1);
183962ac0c33Sjakob } else if(q->tsig.status == TSIG_OK &&
184062ac0c33Sjakob q->tsig.error_code == TSIG_ERROR_NOERROR)
184162ac0c33Sjakob {
184262ac0c33Sjakob if(q->tsig_prepare_it)
184362ac0c33Sjakob tsig_prepare(&q->tsig);
184462ac0c33Sjakob if(q->tsig_update_it)
184562ac0c33Sjakob tsig_update(&q->tsig, q->packet, buffer_position(q->packet));
184662ac0c33Sjakob if(q->tsig_sign_it) {
184762ac0c33Sjakob tsig_sign(&q->tsig);
184862ac0c33Sjakob tsig_append_rr(&q->tsig, q->packet);
184962ac0c33Sjakob ARCOUNT_SET(q->packet, ARCOUNT(q->packet) + 1);
185062ac0c33Sjakob }
185162ac0c33Sjakob }
185262ac0c33Sjakob }
185362ac0c33Sjakob }
1854