Bug Summary

File:src/usr.sbin/nsd/namedb.h
Warning:line 275, column 24
Access to field 'dname' results in a dereference of a null pointer (loaded from variable 'domain')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name query.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/nsd/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I . -I /usr/src/usr.sbin/nsd -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/nsd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/nsd/query.c

/usr/src/usr.sbin/nsd/query.c

1/*
2 * query.c -- nsd(8) the resolver.
3 *
4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
5 *
6 * See LICENSE for the license.
7 *
8 */
9
10#include "config.h"
11
12#include <sys/types.h>
13#include <sys/socket.h>
14#include <netinet/in.h>
15#include <arpa/inet.h>
16#include <assert.h>
17#include <ctype.h>
18#include <errno(*__errno()).h>
19#include <limits.h>
20#include <stddef.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <time.h>
25#include <unistd.h>
26#include <netdb.h>
27
28#include "answer.h"
29#include "axfr.h"
30#include "dns.h"
31#include "dname.h"
32#include "nsd.h"
33#include "namedb.h"
34#include "query.h"
35#include "util.h"
36#include "options.h"
37#include "nsec3.h"
38#include "tsig.h"
39
40/* [Bug #253] Adding unnecessary NS RRset may lead to undesired truncation.
41 * This function determines if the final response packet needs the NS RRset
42 * included. Currently, it will only return negative if QTYPE == DNSKEY|DS.
43 * This way, resolvers won't fallback to TCP unnecessarily when priming
44 * trust anchors.
45 */
46static int answer_needs_ns(struct query *query);
47
48static int add_rrset(struct query *query,
49 answer_type *answer,
50 rr_section_type section,
51 domain_type *owner,
52 rrset_type *rrset);
53
54static void answer_authoritative(struct nsd *nsd,
55 struct query *q,
56 answer_type *answer,
57 size_t domain_number,
58 int exact,
59 domain_type *closest_match,
60 domain_type *closest_encloser,
61 const dname_type *qname);
62
63static void answer_lookup_zone(struct nsd *nsd, struct query *q,
64 answer_type *answer, size_t domain_number,
65 int exact, domain_type *closest_match,
66 domain_type *closest_encloser,
67 const dname_type *qname);
68
69void
70query_put_dname_offset(struct query *q, domain_type *domain, uint16_t offset)
71{
72 assert(q)((void)0);
73 assert(domain)((void)0);
74 assert(domain->number > 0)((void)0);
75
76 if (offset > MAX_COMPRESSION_OFFSET16383)
77 return;
78 if (q->compressed_dname_count >= MAX_COMPRESSED_DNAMES10240)
79 return;
80
81 q->compressed_dname_offsets[domain->number] = offset;
82 q->compressed_dnames[q->compressed_dname_count] = domain;
83 ++q->compressed_dname_count;
84}
85
86void
87query_clear_dname_offsets(struct query *q, size_t max_offset)
88{
89 while (q->compressed_dname_count > 0
90 && (q->compressed_dname_offsets[q->compressed_dnames[q->compressed_dname_count - 1]->number]
91 >= max_offset))
92 {
93 q->compressed_dname_offsets[q->compressed_dnames[q->compressed_dname_count - 1]->number] = 0;
94 --q->compressed_dname_count;
95 }
96}
97
98void
99query_clear_compression_tables(struct query *q)
100{
101 uint16_t i;
102
103 for (i = 0; i < q->compressed_dname_count; ++i) {
104 assert(q->compressed_dnames)((void)0);
105 q->compressed_dname_offsets[q->compressed_dnames[i]->number] = 0;
106 }
107 q->compressed_dname_count = 0;
108}
109
110void
111query_add_compression_domain(struct query *q, domain_type *domain, uint16_t offset)
112{
113 while (domain->parent) {
114 DEBUG(DEBUG_NAME_COMPRESSION, 2,
115 (LOG_INFO, "query dname: %s, number: %lu, offset: %u\n",
116 domain_to_string(domain),
117 (unsigned long) domain->number,
118 offset));
119 query_put_dname_offset(q, domain, offset);
120 offset += label_length(dname_name(domain_dname(domain))) + 1;
121 domain = domain->parent;
122 }
123}
124
125/*
126 * Generate an error response with the specified RCODE.
127 */
128query_state_type
129query_error (struct query *q, nsd_rc_type rcode)
130{
131 if (rcode == NSD_RC_DISCARD) {
132 return QUERY_DISCARDED;
133 }
134
135 buffer_clear(q->packet);
136
137 QR_SET(q->packet)(*buffer_at((q->packet), 2) |= 0x80U); /* This is an answer. */
138 AD_CLR(q->packet)(*buffer_at((q->packet), 3) &= ~0x20U);
139 RCODE_SET(q->packet, (int) rcode)(*buffer_at((q->packet), 3) = (*buffer_at((q->packet), 3
) & ~0x0fU) | ((int) rcode))
; /* Error code. */
140
141 /* Truncate the question as well... */
142 QDCOUNT_SET(q->packet, 0)(buffer_write_u16_at((q->packet), 4, (0)));
143 ANCOUNT_SET(q->packet, 0)(buffer_write_u16_at((q->packet), 6, (0)));
144 NSCOUNT_SET(q->packet, 0)(buffer_write_u16_at((q->packet), 8, (0)));
145 ARCOUNT_SET(q->packet, 0)(buffer_write_u16_at((q->packet), 10, (0)));
146 buffer_set_position(q->packet, QHEADERSZ12);
147 return QUERY_PROCESSED;
148}
149
150static int
151query_ratelimit_err(nsd_type* nsd)
152{
153 time_t now = time(NULL((void *)0));
154 if(nsd->err_limit_time == now) {
155 /* see if limit is exceeded for this second */
156 if(nsd->err_limit_count++ > ERROR_RATELIMIT100)
157 return 1;
158 } else {
159 /* new second, new limits */
160 nsd->err_limit_time = now;
161 nsd->err_limit_count = 1;
162 }
163 return 0;
164}
165
166static query_state_type
167query_formerr (struct query *query, nsd_type* nsd)
168{
169 int opcode = OPCODE(query->packet)((*buffer_at((query->packet), 2) & 0x78U) >> 3);
170 if(query_ratelimit_err(nsd))
171 return QUERY_DISCARDED;
172 FLAGS_SET(query->packet, FLAGS(query->packet) & 0x0100U)(buffer_write_u16_at((query->packet), 2, ((buffer_read_u16_at
((query->packet), 2)) & 0x0100U)))
;
173 /* Preserve the RD flag. Clear the rest. */
174 OPCODE_SET(query->packet, opcode)(*buffer_at((query->packet), 2) = (*buffer_at((query->packet
), 2) & ~0x78U) | ((opcode) << 3))
;
175 return query_error(query, NSD_RC_FORMAT);
176}
177
178static void
179query_cleanup(void *data)
180{
181 query_type *query = (query_type *) data;
182 region_destroy(query->region);
183}
184
185query_type *
186query_create(region_type *region, uint16_t *compressed_dname_offsets,
187 size_t compressed_dname_size, domain_type **compressed_dnames)
188{
189 query_type *query
190 = (query_type *) region_alloc_zero(region, sizeof(query_type));
191 /* create region with large block size, because the initial chunk
192 saves many mallocs in the server */
193 query->region = region_create_custom(xalloc, free, 16384, 16384/8, 32, 0);
194 query->compressed_dname_offsets = compressed_dname_offsets;
195 query->compressed_dnames = compressed_dnames;
196 query->packet = buffer_create(region, QIOBUFSZ(65535 + (255 + sizeof(uint32_t) + 4*sizeof(uint16_t) + 65535
))
);
197 region_add_cleanup(region, query_cleanup, query);
198 query->compressed_dname_offsets_size = compressed_dname_size;
199 tsig_create_record(&query->tsig, region);
200 query->tsig_prepare_it = 1;
201 query->tsig_update_it = 1;
202 query->tsig_sign_it = 1;
203 return query;
204}
205
206void
207query_reset(query_type *q, size_t maxlen, int is_tcp)
208{
209 /*
210 * As long as less than 4Kb (region block size) has been used,
211 * this call to free_all is free, the block is saved for re-use,
212 * so no malloc() or free() calls are done.
213 * at present use of the region is for:
214 * o query qname dname_type (255 max).
215 * o wildcard expansion domain_type (7*ptr+u32+2bytes)+(5*ptr nsec3)
216 * o wildcard expansion for additional section domain_type.
217 * o nsec3 hashed name(s) (3 dnames for a nonexist_proof,
218 * one proof per wildcard and for nx domain).
219 */
220 region_free_all(q->region);
221 q->remote_addrlen = (socklen_t)sizeof(q->remote_addr);
222 q->client_addrlen = (socklen_t)sizeof(q->client_addr);
223 q->is_proxied = 0;
224 q->maxlen = maxlen;
225 q->reserved_space = 0;
226 buffer_clear(q->packet);
227 edns_init_record(&q->edns);
228 tsig_init_record(&q->tsig, NULL((void *)0), NULL((void *)0));
229 q->tsig_prepare_it = 1;
230 q->tsig_update_it = 1;
231 q->tsig_sign_it = 1;
232 q->tcp = is_tcp;
233 q->qname = NULL((void *)0);
234 q->qtype = 0;
235 q->qclass = 0;
236 q->zone = NULL((void *)0);
237 q->opcode = 0;
238 q->cname_count = 0;
239 q->delegation_domain = NULL((void *)0);
240 q->delegation_rrset = NULL((void *)0);
241 q->compressed_dname_count = 0;
242 q->number_temporary_domains = 0;
243
244 q->axfr_is_done = 0;
245 q->axfr_zone = NULL((void *)0);
246 q->axfr_current_domain = NULL((void *)0);
247 q->axfr_current_rrset = NULL((void *)0);
248 q->axfr_current_rr = 0;
249
250 q->ixfr_is_done = 0;
251 q->ixfr_data = NULL((void *)0);
252 q->ixfr_count_newsoa = 0;
253 q->ixfr_count_oldsoa = 0;
254 q->ixfr_count_del = 0;
255 q->ixfr_count_add = 0;
256
257#ifdef RATELIMIT
258 q->wildcard_domain = NULL((void *)0);
259#endif
260}
261
262/* get a temporary domain number (or 0=failure) */
263static domain_type*
264query_get_tempdomain(struct query *q)
265{
266 static domain_type d[EXTRA_DOMAIN_NUMBERS1024];
267 if(q->number_temporary_domains >= EXTRA_DOMAIN_NUMBERS1024)
268 return 0;
269 q->number_temporary_domains ++;
270 memset(&d[q->number_temporary_domains-1], 0, sizeof(domain_type));
271 d[q->number_temporary_domains-1].number = q->compressed_dname_offsets_size +
272 q->number_temporary_domains - 1;
273 return &d[q->number_temporary_domains-1];
274}
275
276static void
277query_addtxt(struct query *q,
278 const uint8_t *dname,
279 uint16_t klass,
280 uint32_t ttl,
281 const char *txt)
282{
283 size_t txt_length = strlen(txt);
284 uint8_t len = (uint8_t) txt_length;
285
286 assert(txt_length <= UCHAR_MAX)((void)0);
287
288 /* Add the dname */
289 if (dname >= buffer_begin(q->packet)
290 && dname <= buffer_current(q->packet))
291 {
292 buffer_write_u16(q->packet,
293 0xc000 | (dname - buffer_begin(q->packet)));
294 } else {
295 buffer_write(q->packet, dname + 1, *dname);
296 }
297
298 buffer_write_u16(q->packet, TYPE_TXT16);
299 buffer_write_u16(q->packet, klass);
300 buffer_write_u32(q->packet, ttl);
301 buffer_write_u16(q->packet, len + 1);
302 buffer_write_u8(q->packet, len);
303 buffer_write(q->packet, txt, len);
304}
305
306/*
307 * Parse the question section of a query. The normalized query name
308 * is stored in QUERY->name, the class in QUERY->klass, and the type
309 * in QUERY->type.
310 */
311static int
312process_query_section(query_type *query)
313{
314 uint8_t qnamebuf[MAXDOMAINLEN255];
315
316 buffer_set_position(query->packet, QHEADERSZ12);
317 /* Lets parse the query name and convert it to lower case. */
318 if(!packet_read_query_section(query->packet, qnamebuf,
319 &query->qtype, &query->qclass))
320 return 0;
321 query->qname = dname_make(query->region, qnamebuf, 1);
322 return 1;
323}
324
325
326/*
327 * Process an optional EDNS OPT record. Sets QUERY->EDNS to 0 if
328 * there was no EDNS record, to -1 if there was an invalid or
329 * unsupported EDNS record, and to 1 otherwise. Updates QUERY->MAXLEN
330 * if the EDNS record specifies a maximum supported response length.
331 *
332 * Return NSD_RC_FORMAT on failure, NSD_RC_OK on success.
333 */
334static nsd_rc_type
335process_edns(nsd_type* nsd, struct query *q)
336{
337 if (q->edns.status == EDNS_ERROR) {
338 /* The only error is VERSION not implemented */
339 return NSD_RC_FORMAT;
340 }
341
342 if (q->edns.status == EDNS_OK) {
343 /* Only care about UDP size larger than normal... */
344 if (!q->tcp && q->edns.maxlen > UDP_MAX_MESSAGE_LEN512) {
345 size_t edns_size;
346#if defined(INET6)
347 if (q->client_addr.ss_family == AF_INET624) {
348 edns_size = nsd->ipv6_edns_size;
349 } else
350#endif
351 edns_size = nsd->ipv4_edns_size;
352
353 if (q->edns.maxlen < edns_size) {
354 q->maxlen = q->edns.maxlen;
355 } else {
356 q->maxlen = edns_size;
357 }
358
359#if defined(INET6) && !defined(IPV6_USE_MIN_MTU42) && !defined(IPV6_MTU)
360 /*
361 * Use IPv6 minimum MTU to avoid sending
362 * packets that are too large for some links.
363 * IPv6 will not automatically fragment in
364 * this case (unlike IPv4).
365 */
366 if (q->client_addr.ss_family == AF_INET624
367 && q->maxlen > IPV6_MIN_MTU1280)
368 {
369 q->maxlen = IPV6_MIN_MTU1280;
370 }
371#endif
372 }
373
374 /* Strip the OPT resource record off... */
375 buffer_set_position(q->packet, q->edns.position);
376 buffer_set_limit(q->packet, q->edns.position);
377 ARCOUNT_SET(q->packet, ARCOUNT(q->packet) - 1)(buffer_write_u16_at((q->packet), 10, ((buffer_read_u16_at
((q->packet), 10)) - 1)))
;
378 }
379 return NSD_RC_OK;
380}
381
382/*
383 * Processes TSIG.
384 * Sets error when tsig does not verify on the query.
385 */
386static nsd_rc_type
387process_tsig(struct query* q)
388{
389 if(q->tsig.status == TSIG_ERROR)
390 return NSD_RC_FORMAT;
391 if(q->tsig.status == TSIG_OK) {
392 if(!tsig_from_query(&q->tsig)) {
393 char a[128];
394 addr2str(&q->client_addr, a, sizeof(a));
395 log_msg(LOG_ERR3, "query: bad tsig (%s) for key %s from %s",
396 tsig_error(q->tsig.error_code),
397 dname_to_string(q->tsig.key_name, NULL((void *)0)), a);
398 return NSD_RC_NOTAUTH;
399 }
400 buffer_set_limit(q->packet, q->tsig.position);
401 ARCOUNT_SET(q->packet, ARCOUNT(q->packet) - 1)(buffer_write_u16_at((q->packet), 10, ((buffer_read_u16_at
((q->packet), 10)) - 1)))
;
402 tsig_prepare(&q->tsig);
403 tsig_update(&q->tsig, q->packet, buffer_limit(q->packet));
404 if(!tsig_verify(&q->tsig)) {
405 char a[128];
406 addr2str(&q->client_addr, a, sizeof(a));
407 log_msg(LOG_ERR3, "query: bad tsig signature for key %s from %s",
408 dname_to_string(q->tsig.key->name, NULL((void *)0)), a);
409 return NSD_RC_NOTAUTH;
410 }
411 DEBUG(DEBUG_XFRD,1, (LOG_INFO, "query good tsig signature for %s",
412 dname_to_string(q->tsig.key->name, NULL)));
413 }
414 return NSD_RC_OK;
415}
416
417/*
418 * Check notify acl and forward to xfrd (or return an error).
419 */
420static query_state_type
421answer_notify(struct nsd* nsd, struct query *query)
422{
423 int acl_num, acl_num_xfr;
424 struct acl_options *why;
425 nsd_rc_type rc;
426
427 struct zone_options* zone_opt;
428 DEBUG(DEBUG_XFRD,1, (LOG_INFO, "got notify %s processing acl",
429 dname_to_string(query->qname, NULL)));
430
431 zone_opt = zone_options_find(nsd->options, query->qname);
432 if(!zone_opt)
433 return query_error(query, NSD_RC_NXDOMAIN);
434
435 if(!nsd->this_child) /* we are in debug mode or something */
436 return query_error(query, NSD_RC_SERVFAIL);
437
438 if(!tsig_find_rr(&query->tsig, query->packet)) {
439 DEBUG(DEBUG_XFRD,2, (LOG_ERR, "bad tsig RR format"));
440 return query_error(query, NSD_RC_FORMAT);
441 }
442 rc = process_tsig(query);
443 if(rc != NSD_RC_OK)
444 return query_error(query, rc);
445
446 /* check if it passes acl */
447 if(query->is_proxied && acl_check_incoming_block_proxy(
448 zone_opt->pattern->allow_notify, query, &why) == -1) {
449 /* the proxy address is blocked */
450 if (verbosity >= 2) {
451 char address[128], proxy[128];
452 addr2str(&query->client_addr, address, sizeof(address));
453 addr2str(&query->remote_addr, proxy, sizeof(proxy));
454 VERBOSITY(2, (LOG_INFO, "notify for %s from %s via proxy %s refused because of proxy, %s %s",do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, proxy
, (why?why->ip_address_spec:"."), (why ? ( why->nokey ?
"NOKEY" : why->blocked ? "BLOCKED" : why->key_name ) :
"no acl matches")) ; } } while (0)
455 dname_to_string(query->qname, NULL),do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, proxy
, (why?why->ip_address_spec:"."), (why ? ( why->nokey ?
"NOKEY" : why->blocked ? "BLOCKED" : why->key_name ) :
"no acl matches")) ; } } while (0)
456 address, proxy,do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, proxy
, (why?why->ip_address_spec:"."), (why ? ( why->nokey ?
"NOKEY" : why->blocked ? "BLOCKED" : why->key_name ) :
"no acl matches")) ; } } while (0)
457 (why?why->ip_address_spec:"."),do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, proxy
, (why?why->ip_address_spec:"."), (why ? ( why->nokey ?
"NOKEY" : why->blocked ? "BLOCKED" : why->key_name ) :
"no acl matches")) ; } } while (0)
458 (why ? ( why->nokey ? "NOKEY"do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, proxy
, (why?why->ip_address_spec:"."), (why ? ( why->nokey ?
"NOKEY" : why->blocked ? "BLOCKED" : why->key_name ) :
"no acl matches")) ; } } while (0)
459 : why->blocked ? "BLOCKED"do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, proxy
, (why?why->ip_address_spec:"."), (why ? ( why->nokey ?
"NOKEY" : why->blocked ? "BLOCKED" : why->key_name ) :
"no acl matches")) ; } } while (0)
460 : why->key_name )do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, proxy
, (why?why->ip_address_spec:"."), (why ? ( why->nokey ?
"NOKEY" : why->blocked ? "BLOCKED" : why->key_name ) :
"no acl matches")) ; } } while (0)
461 : "no acl matches")))do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, proxy
, (why?why->ip_address_spec:"."), (why ? ( why->nokey ?
"NOKEY" : why->blocked ? "BLOCKED" : why->key_name ) :
"no acl matches")) ; } } while (0)
;
462 }
463 return query_error(query, NSD_RC_REFUSE);
464 }
465 if((acl_num = acl_check_incoming(zone_opt->pattern->allow_notify, query,
466 &why)) != -1)
467 {
468 sig_atomic_t mode = NSD_PASS_TO_XFRD6;
469 int s = nsd->this_child->parent_fd;
470 uint16_t sz;
471 uint32_t acl_send = htonl(acl_num)(__uint32_t)(__builtin_constant_p(acl_num) ? (__uint32_t)(((__uint32_t
)(acl_num) & 0xff) << 24 | ((__uint32_t)(acl_num) &
0xff00) << 8 | ((__uint32_t)(acl_num) & 0xff0000) >>
8 | ((__uint32_t)(acl_num) & 0xff000000) >> 24) : __swap32md
(acl_num))
;
472 uint32_t acl_xfr;
473 size_t pos;
474
475 /* Find priority candidate for request XFR. -1 if no match */
476 acl_num_xfr = acl_check_incoming(
477 zone_opt->pattern->request_xfr, query, NULL((void *)0));
478
479 acl_xfr = htonl(acl_num_xfr)(__uint32_t)(__builtin_constant_p(acl_num_xfr) ? (__uint32_t)
(((__uint32_t)(acl_num_xfr) & 0xff) << 24 | ((__uint32_t
)(acl_num_xfr) & 0xff00) << 8 | ((__uint32_t)(acl_num_xfr
) & 0xff0000) >> 8 | ((__uint32_t)(acl_num_xfr) &
0xff000000) >> 24) : __swap32md(acl_num_xfr))
;
480
481 assert(why)((void)0);
482 DEBUG(DEBUG_XFRD,1, (LOG_INFO, "got notify %s passed acl %s %s",
483 dname_to_string(query->qname, NULL),
484 why->ip_address_spec,
485 why->nokey?"NOKEY":
486 (why->blocked?"BLOCKED":why->key_name)));
487 sz = buffer_limit(query->packet);
488 if(buffer_limit(query->packet) > MAX_PACKET_SIZE65535)
489 return query_error(query, NSD_RC_SERVFAIL);
490 /* forward to xfrd for processing
491 Note. Blocking IPC I/O, but acl is OK. */
492 sz = htons(sz)(__uint16_t)(__builtin_constant_p(sz) ? (__uint16_t)(((__uint16_t
)(sz) & 0xffU) << 8 | ((__uint16_t)(sz) & 0xff00U
) >> 8) : __swap16md(sz))
;
493 if(!write_socket(s, &mode, sizeof(mode)) ||
494 !write_socket(s, &sz, sizeof(sz)) ||
495 !write_socket(s, buffer_begin(query->packet),
496 buffer_limit(query->packet)) ||
497 !write_socket(s, &acl_send, sizeof(acl_send)) ||
498 !write_socket(s, &acl_xfr, sizeof(acl_xfr))) {
499 log_msg(LOG_ERR3, "error in IPC notify server2main, %s",
500 strerror(errno(*__errno())));
501 return query_error(query, NSD_RC_SERVFAIL);
502 }
503 if(verbosity >= 1) {
504 uint32_t serial = 0;
505 char address[128];
506 addr2str(&query->client_addr, address, sizeof(address));
507 if(packet_find_notify_serial(query->packet, &serial))
508 VERBOSITY(1, (LOG_INFO, "notify for %s from %s serial %u",do { if ((1) <= verbosity) { log_msg (6, "notify for %s from %s serial %u"
, dname_to_string(query->qname, ((void *)0)), address, (unsigned
)serial) ; } } while (0)
509 dname_to_string(query->qname, NULL), address,do { if ((1) <= verbosity) { log_msg (6, "notify for %s from %s serial %u"
, dname_to_string(query->qname, ((void *)0)), address, (unsigned
)serial) ; } } while (0)
510 (unsigned)serial))do { if ((1) <= verbosity) { log_msg (6, "notify for %s from %s serial %u"
, dname_to_string(query->qname, ((void *)0)), address, (unsigned
)serial) ; } } while (0)
;
511 else
512 VERBOSITY(1, (LOG_INFO, "notify for %s from %s",do { if ((1) <= verbosity) { log_msg (6, "notify for %s from %s"
, dname_to_string(query->qname, ((void *)0)), address) ; }
} while (0)
513 dname_to_string(query->qname, NULL), address))do { if ((1) <= verbosity) { log_msg (6, "notify for %s from %s"
, dname_to_string(query->qname, ((void *)0)), address) ; }
} while (0)
;
514 }
515
516 /* create notify reply - keep same query contents */
517 QR_SET(query->packet)(*buffer_at((query->packet), 2) |= 0x80U); /* This is an answer. */
518 AA_SET(query->packet)(*buffer_at((query->packet), 2) |= 0x04U); /* we are authoritative. */
519 ANCOUNT_SET(query->packet, 0)(buffer_write_u16_at((query->packet), 6, (0)));
520 NSCOUNT_SET(query->packet, 0)(buffer_write_u16_at((query->packet), 8, (0)));
521 ARCOUNT_SET(query->packet, 0)(buffer_write_u16_at((query->packet), 10, (0)));
522 RCODE_SET(query->packet, RCODE_OK)(*buffer_at((query->packet), 3) = (*buffer_at((query->packet
), 3) & ~0x0fU) | (0))
; /* Error code. */
523 /* position is right after the query */
524 pos = buffer_position(query->packet);
525 buffer_clear(query->packet);
526 buffer_set_position(query->packet, pos);
527 /* tsig is added in add_additional later (if needed) */
528 return QUERY_PROCESSED;
529 }
530
531 if (verbosity >= 2) {
532 char address[128];
533 addr2str(&query->client_addr, address, sizeof(address));
534 VERBOSITY(2, (LOG_INFO, "notify for %s from %s refused, %s %s",do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s refused, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, (why
?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
535 dname_to_string(query->qname, NULL),do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s refused, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, (why
?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
536 address,do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s refused, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, (why
?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
537 (why?why->ip_address_spec:"."),do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s refused, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, (why
?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
538 (why ? ( why->nokey ? "NOKEY"do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s refused, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, (why
?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
539 : why->blocked ? "BLOCKED"do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s refused, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, (why
?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
540 : why->key_name )do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s refused, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, (why
?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
541 : "no acl matches")))do { if ((2) <= verbosity) { log_msg (6, "notify for %s from %s refused, %s %s"
, dname_to_string(query->qname, ((void *)0)), address, (why
?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
;
542 }
543
544 return query_error(query, NSD_RC_REFUSE);
545}
546
547
548/*
549 * Answer a query in the CHAOS class.
550 */
551static query_state_type
552answer_chaos(struct nsd *nsd, query_type *q)
553{
554 AA_CLR(q->packet)(*buffer_at((q->packet), 2) &= ~0x04U);
555 switch (q->qtype) {
556 case TYPE_ANY255:
557 case TYPE_TXT16:
558 if ((q->qname->name_size == 11
559 && memcmp(dname_name(q->qname), "\002id\006server", 11) == 0) ||
560 (q->qname->name_size == 15
561 && memcmp(dname_name(q->qname), "\010hostname\004bind", 15) == 0))
562 {
563 if(!nsd->options->hide_identity) {
564 /* Add ID */
565 query_addtxt(q,
566 buffer_begin(q->packet) + QHEADERSZ12,
567 CLASS_CH3,
568 0,
569 nsd->identity);
570 ANCOUNT_SET(q->packet, ANCOUNT(q->packet) + 1)(buffer_write_u16_at((q->packet), 6, ((buffer_read_u16_at(
(q->packet), 6)) + 1)))
;
571 } else {
572 RCODE_SET(q->packet, RCODE_REFUSE)(*buffer_at((q->packet), 3) = (*buffer_at((q->packet), 3
) & ~0x0fU) | (5))
;
573 /* RFC8914 - Extended DNS Errors
574 * 4.19. Extended DNS Error Code 18 - Prohibited */
575 q->edns.ede = EDE_PROHIBITED18;
576 }
577 } else if ((q->qname->name_size == 16
578 && memcmp(dname_name(q->qname), "\007version\006server", 16) == 0) ||
579 (q->qname->name_size == 14
580 && memcmp(dname_name(q->qname), "\007version\004bind", 14) == 0))
581 {
582 if(!nsd->options->hide_version) {
583 /* Add version */
584 query_addtxt(q,
585 buffer_begin(q->packet) + QHEADERSZ12,
586 CLASS_CH3,
587 0,
588 nsd->version);
589 ANCOUNT_SET(q->packet, ANCOUNT(q->packet) + 1)(buffer_write_u16_at((q->packet), 6, ((buffer_read_u16_at(
(q->packet), 6)) + 1)))
;
590 } else {
591 RCODE_SET(q->packet, RCODE_REFUSE)(*buffer_at((q->packet), 3) = (*buffer_at((q->packet), 3
) & ~0x0fU) | (5))
;
592 /* RFC8914 - Extended DNS Errors
593 * 4.19. Extended DNS Error Code 18 - Prohibited */
594 q->edns.ede = EDE_PROHIBITED18;
595 }
596 } else {
597 RCODE_SET(q->packet, RCODE_REFUSE)(*buffer_at((q->packet), 3) = (*buffer_at((q->packet), 3
) & ~0x0fU) | (5))
;
598 /* RFC8914 - Extended DNS Errors
599 * 4.22. Extended DNS Error Code 21 - Not Supported */
600 q->edns.ede = EDE_NOT_SUPPORTED21;
601
602 }
603 break;
604 default:
605 RCODE_SET(q->packet, RCODE_REFUSE)(*buffer_at((q->packet), 3) = (*buffer_at((q->packet), 3
) & ~0x0fU) | (5))
;
606 /* RFC8914 - Extended DNS Errors
607 * 4.22. Extended DNS Error Code 21 - Not Supported */
608 q->edns.ede = EDE_NOT_SUPPORTED21;
609 break;
610 }
611
612 return QUERY_PROCESSED;
613}
614
615
616/*
617 * Find the covering NSEC for a non-existent domain name. Normally
618 * the NSEC will be located at CLOSEST_MATCH, except when it is an
619 * empty non-terminal. In this case the NSEC may be located at the
620 * previous domain name (in canonical ordering).
621 */
622static domain_type *
623find_covering_nsec(domain_type *closest_match,
624 zone_type *zone,
625 rrset_type **nsec_rrset)
626{
627 assert(closest_match)((void)0);
628 assert(nsec_rrset)((void)0);
629
630 /* loop away temporary created domains. For real ones it is &RBTREE_NULL */
631#ifdef USE_RADIX_TREE
632 while (closest_match->rnode == NULL((void *)0))
633#else
634 while (closest_match->node.parent == NULL((void *)0))
635#endif
636 closest_match = closest_match->parent;
637 while (closest_match) {
638 *nsec_rrset = domain_find_rrset(closest_match, zone, TYPE_NSEC47);
639 if (*nsec_rrset) {
640 return closest_match;
641 }
642 if (closest_match == zone->apex) {
643 /* Don't look outside the current zone. */
644 return NULL((void *)0);
645 }
646 closest_match = domain_previous(closest_match);
647 }
648 return NULL((void *)0);
649}
650
651
652struct additional_rr_types
653{
654 uint16_t rr_type;
655 rr_section_type rr_section;
656};
657
658struct additional_rr_types default_additional_rr_types[] = {
659 { TYPE_A1, ADDITIONAL_A_SECTION },
660 { TYPE_AAAA28, ADDITIONAL_AAAA_SECTION },
661 { 0, (rr_section_type) 0 }
662};
663
664struct additional_rr_types swap_aaaa_additional_rr_types[] = {
665 { TYPE_AAAA28, ADDITIONAL_A_SECTION },
666 { TYPE_A1, ADDITIONAL_AAAA_SECTION },
667 { 0, (rr_section_type) 0 }
668};
669
670struct additional_rr_types rt_additional_rr_types[] = {
671 { TYPE_A1, ADDITIONAL_A_SECTION },
672 { TYPE_AAAA28, ADDITIONAL_AAAA_SECTION },
673 { TYPE_X2519, ADDITIONAL_OTHER_SECTION },
674 { TYPE_ISDN20, ADDITIONAL_OTHER_SECTION },
675 { 0, (rr_section_type) 0 }
676};
677
678static void
679add_additional_rrsets(struct query *query, answer_type *answer,
680 rrset_type *master_rrset, size_t rdata_index,
681 int allow_glue, struct additional_rr_types types[])
682{
683 size_t i;
684
685 assert(query)((void)0);
686 assert(answer)((void)0);
687 assert(master_rrset)((void)0);
688 assert(rdata_atom_is_domain(rrset_rrtype(master_rrset), rdata_index))((void)0);
689
690 for (i = 0; i < master_rrset->rr_count; ++i) {
691 int j;
692 domain_type *additional = rdata_atom_domain(master_rrset->rrs[i].rdatas[rdata_index]);
693 domain_type *match = additional;
694
695 assert(additional)((void)0);
696
697 if (!allow_glue && domain_is_glue(match, query->zone))
698 continue;
699
700 /*
701 * Check to see if we need to generate the dependent
702 * based on a wildcard domain.
703 */
704 while (!match->is_existing) {
705 match = match->parent;
706 }
707 if (additional != match && domain_wildcard_child(match)) {
708 domain_type *wildcard_child = domain_wildcard_child(match);
709 domain_type *temp = (domain_type *) region_alloc(
710 query->region, sizeof(domain_type));
711#ifdef USE_RADIX_TREE
712 temp->rnode = NULL((void *)0);
713 temp->dname = additional->dname;
714#else
715 memcpy(&temp->node, &additional->node, sizeof(rbnode_type));
716 temp->node.parent = NULL((void *)0);
717#endif
718 temp->number = additional->number;
719 temp->parent = match;
720 temp->wildcard_child_closest_match = temp;
721 temp->rrsets = wildcard_child->rrsets;
722 temp->is_existing = wildcard_child->is_existing;
723 additional = temp;
724 }
725
726 for (j = 0; types[j].rr_type != 0; ++j) {
727 rrset_type *rrset = domain_find_rrset(
728 additional, query->zone, types[j].rr_type);
729 if (rrset) {
730 answer_add_rrset(answer, types[j].rr_section,
731 additional, rrset);
732 }
733 }
734 }
735}
736
737static int
738answer_needs_ns(struct query* query)
739{
740 assert(query)((void)0);
741 /* Currently, only troublesome for DNSKEY and DS,
742 * cuz their RRSETs are quite large. */
743 return (query->qtype != TYPE_DNSKEY48 && query->qtype != TYPE_DS43
744 && query->qtype != TYPE_ANY255);
745}
746
747static int
748add_rrset(struct query *query,
749 answer_type *answer,
750 rr_section_type section,
751 domain_type *owner,
752 rrset_type *rrset)
753{
754 int result;
755
756 assert(query)((void)0);
757 assert(answer)((void)0);
758 assert(owner)((void)0);
759 assert(rrset)((void)0);
760 assert(rrset_rrclass(rrset) == CLASS_IN)((void)0);
761
762 result = answer_add_rrset(answer, section, owner, rrset);
763 if(minimal_responses && section != AUTHORITY_SECTION &&
764 query->qtype != TYPE_NS2)
765 return result;
766 switch (rrset_rrtype(rrset)) {
767 case TYPE_NS2:
768#if defined(INET6)
769 /* if query over IPv6, swap A and AAAA; put AAAA first */
770 add_additional_rrsets(query, answer, rrset, 0, 1,
771 (query->client_addr.ss_family == AF_INET624)?
772 swap_aaaa_additional_rr_types:
773 default_additional_rr_types);
774#else
775 add_additional_rrsets(query, answer, rrset, 0, 1,
776 default_additional_rr_types);
777#endif
778 break;
779 case TYPE_MB7:
780 add_additional_rrsets(query, answer, rrset, 0, 0,
781 default_additional_rr_types);
782 break;
783 case TYPE_MX15:
784 case TYPE_KX36:
785 add_additional_rrsets(query, answer, rrset, 1, 0,
786 default_additional_rr_types);
787 break;
788 case TYPE_RT21:
789 add_additional_rrsets(query, answer, rrset, 1, 0,
790 rt_additional_rr_types);
791 break;
792 case TYPE_SRV33:
793 add_additional_rrsets(query, answer, rrset, 3, 0,
794 default_additional_rr_types);
795 break;
796 default:
797 break;
798 }
799
800 return result;
801}
802
803
804/* returns 0 on error, or the domain number for to_name.
805 from_name is changes to to_name by the DNAME rr.
806 DNAME rr is from src to dest.
807 closest encloser encloses the to_name. */
808static size_t
809query_synthesize_cname(struct query* q, struct answer* answer, const dname_type* from_name,
810 const dname_type* to_name, domain_type* src, domain_type* to_closest_encloser,
811 domain_type** to_closest_match, uint32_t ttl)
812{
813 /* add temporary domains for from_name and to_name and all
814 their (not allocated yet) parents */
815 /* any domains below src are not_existing (because of DNAME at src) */
816 int i;
817 size_t j;
818 domain_type* cname_domain;
819 domain_type* cname_dest;
820 rrset_type* rrset;
821
822 domain_type* lastparent = src;
823 assert(q && answer && from_name && to_name && src && to_closest_encloser)((void)0);
824 assert(to_closest_match)((void)0);
825
826 /* check for loop by duplicate CNAME rrset synthesized */
827 for(j=0; j<answer->rrset_count; ++j) {
828 if(answer->section[j] == ANSWER_SECTION &&
829 answer->rrsets[j]->rr_count == 1 &&
830 answer->rrsets[j]->rrs[0].type == TYPE_CNAME5 &&
831 dname_compare(domain_dname(answer->rrsets[j]->rrs[0].owner), from_name) == 0 &&
832 answer->rrsets[j]->rrs[0].rdata_count == 1 &&
833 dname_compare(domain_dname(answer->rrsets[j]->rrs[0].rdatas->domain), to_name) == 0) {
834 DEBUG(DEBUG_QUERY,2, (LOG_INFO, "loop for synthesized CNAME rrset for query %s", dname_to_string(q->qname, NULL)));
835 return 0;
836 }
837 }
838
839 /* allocate source part */
840 for(i=0; i < from_name->label_count - domain_dname(src)->label_count; i++)
841 {
842 domain_type* newdom = query_get_tempdomain(q);
843 if(!newdom)
844 return 0;
845 newdom->is_existing = 1;
846 newdom->parent = lastparent;
847#ifdef USE_RADIX_TREE
848 newdom->dname
849#else
850 newdom->node.key
851#endif
852 = dname_partial_copy(q->region,
853 from_name, domain_dname(src)->label_count + i + 1);
854 if(dname_compare(domain_dname(newdom), q->qname) == 0) {
855 /* 0 good for query name, otherwise new number */
856 newdom->number = 0;
857 }
858 DEBUG(DEBUG_QUERY,2, (LOG_INFO, "created temp domain src %d. %s nr %d", i,
859 domain_to_string(newdom), (int)newdom->number));
860 lastparent = newdom;
861 }
862 cname_domain = lastparent;
863
864 /* allocate dest part */
865 lastparent = to_closest_encloser;
866 for(i=0; i < to_name->label_count - domain_dname(to_closest_encloser)->label_count;
867 i++)
868 {
869 domain_type* newdom = query_get_tempdomain(q);
870 if(!newdom)
871 return 0;
872 newdom->is_existing = 0;
873 newdom->parent = lastparent;
874#ifdef USE_RADIX_TREE
875 newdom->dname
876#else
877 newdom->node.key
878#endif
879 = dname_partial_copy(q->region,
880 to_name, domain_dname(to_closest_encloser)->label_count + i + 1);
881 DEBUG(DEBUG_QUERY,2, (LOG_INFO, "created temp domain dest %d. %s nr %d", i,
882 domain_to_string(newdom), (int)newdom->number));
883 lastparent = newdom;
884 }
885 cname_dest = lastparent;
886 *to_closest_match = cname_dest;
887
888 /* allocate the CNAME RR */
889 rrset = (rrset_type*) region_alloc(q->region, sizeof(rrset_type));
890 memset(rrset, 0, sizeof(rrset_type));
891 rrset->zone = q->zone;
892 rrset->rr_count = 1;
893 rrset->rrs = (rr_type*) region_alloc(q->region, sizeof(rr_type));
894 memset(rrset->rrs, 0, sizeof(rr_type));
895 rrset->rrs->owner = cname_domain;
896 rrset->rrs->ttl = ttl;
897 rrset->rrs->type = TYPE_CNAME5;
898 rrset->rrs->klass = CLASS_IN1;
899 rrset->rrs->rdata_count = 1;
900 rrset->rrs->rdatas = (rdata_atom_type*)region_alloc(q->region,
901 sizeof(rdata_atom_type));
902 rrset->rrs->rdatas->domain = cname_dest;
903
904 if(!add_rrset(q, answer, ANSWER_SECTION, cname_domain, rrset)) {
905 DEBUG(DEBUG_QUERY,2, (LOG_INFO, "could not add synthesized CNAME rrset to packet for query %s", dname_to_string(q->qname, NULL)));
906 /* failure to add CNAME; likely is a loop, the same twice */
907 return 0;
908 }
909
910 return cname_dest->number;
911}
912
913/*
914 * Answer delegation information.
915 *
916 * DNSSEC: Include the DS RRset if present. Otherwise include an NSEC
917 * record proving the DS RRset does not exist.
918 */
919static void
920answer_delegation(query_type *query, answer_type *answer)
921{
922 assert(answer)((void)0);
923 assert(query->delegation_domain)((void)0);
924 assert(query->delegation_rrset)((void)0);
925
926 if (query->cname_count == 0) {
927 AA_CLR(query->packet)(*buffer_at((query->packet), 2) &= ~0x04U);
928 } else {
929 AA_SET(query->packet)(*buffer_at((query->packet), 2) |= 0x04U);
930 }
931
932 add_rrset(query,
933 answer,
934 AUTHORITY_SECTION,
935 query->delegation_domain,
936 query->delegation_rrset);
937 if (query->edns.dnssec_ok && zone_is_secure(query->zone)) {
938 rrset_type *rrset;
939 if ((rrset = domain_find_rrset(query->delegation_domain, query->zone, TYPE_DS43))) {
940 add_rrset(query, answer, AUTHORITY_SECTION,
941 query->delegation_domain, rrset);
942#ifdef NSEC3
943 } else if (query->zone->nsec3_param) {
944 nsec3_answer_delegation(query, answer);
945#endif
946 } else if ((rrset = domain_find_rrset(query->delegation_domain, query->zone, TYPE_NSEC47))) {
947 add_rrset(query, answer, AUTHORITY_SECTION,
948 query->delegation_domain, rrset);
949 }
950 }
951}
952
953
954/*
955 * Answer SOA information.
956 */
957static void
958answer_soa(struct query *query, answer_type *answer)
959{
960 if (query->qclass != CLASS_ANY255) {
961 add_rrset(query, answer,
962 AUTHORITY_SECTION,
963 query->zone->apex,
964 query->zone->soa_nx_rrset);
965 }
966}
967
968
969/*
970 * Answer that the domain name exists but there is no RRset with the
971 * requested type.
972 *
973 * DNSSEC: Include the correct NSEC record proving that the type does
974 * not exist. In the wildcard no data (3.1.3.4) case the wildcard IS
975 * NOT expanded, so the ORIGINAL parameter must point to the original
976 * wildcard entry, not to the generated entry.
977 */
978static void
979answer_nodata(struct query *query, answer_type *answer, domain_type *original)
980{
981 answer_soa(query, answer);
982
983#ifdef NSEC3
984 if (query->edns.dnssec_ok && query->zone->nsec3_param) {
985 nsec3_answer_nodata(query, answer, original);
986 } else
987#endif
988 if (query->edns.dnssec_ok && zone_is_secure(query->zone)) {
989 domain_type *nsec_domain;
990 rrset_type *nsec_rrset;
991
992 nsec_domain = find_covering_nsec(original, query->zone, &nsec_rrset);
993 if (nsec_domain) {
994 add_rrset(query, answer, AUTHORITY_SECTION, nsec_domain, nsec_rrset);
995 }
996 }
997}
998
999static void
1000answer_nxdomain(query_type *query, answer_type *answer)
1001{
1002 RCODE_SET(query->packet, RCODE_NXDOMAIN)(*buffer_at((query->packet), 3) = (*buffer_at((query->packet
), 3) & ~0x0fU) | (3))
;
1003 answer_soa(query, answer);
1004}
1005
1006
1007/*
1008 * Answer domain information (or SOA if we do not have an RRset for
1009 * the type specified by the query).
1010 */
1011static void
1012answer_domain(struct nsd* nsd, struct query *q, answer_type *answer,
1013 domain_type *domain, domain_type *original)
1014{
1015 rrset_type *rrset;
1016
1017 if (q->qtype == TYPE_ANY255) {
1018 rrset_type *preferred_rrset = NULL((void *)0);
1019 rrset_type *normal_rrset = NULL((void *)0);
1020 rrset_type *non_preferred_rrset = NULL((void *)0);
1021
1022 /*
1023 * Minimize response size for ANY, with one RRset
1024 * according to RFC 8482(4.1).
1025 * Prefers popular and not large rtypes (A,AAAA,...)
1026 * lowering large ones (DNSKEY,RRSIG,...).
1027 */
1028 for (rrset = domain_find_any_rrset(domain, q->zone); rrset; rrset = rrset->next) {
1029 if (rrset->zone == q->zone
1030#ifdef NSEC3
1031 && rrset_rrtype(rrset) != TYPE_NSEC350
1032#endif
1033 /*
1034 * Don't include the RRSIG RRset when
1035 * DNSSEC is used, because it is added
1036 * automatically on an per-RRset basis.
1037 */
1038 && !(q->edns.dnssec_ok
1039 && zone_is_secure(q->zone)
1040 && rrset_rrtype(rrset) == TYPE_RRSIG46))
1041 {
1042 switch(rrset_rrtype(rrset)) {
1043 case TYPE_A1:
1044 case TYPE_AAAA28:
1045 case TYPE_SOA6:
1046 case TYPE_MX15:
1047 case TYPE_PTR12:
1048 preferred_rrset = rrset;
1049 break;
1050 case TYPE_DNSKEY48:
1051 case TYPE_RRSIG46:
1052 case TYPE_NSEC47:
1053 non_preferred_rrset = rrset;
1054 break;
1055 default:
1056 normal_rrset = rrset;
1057 }
1058 if (preferred_rrset) break;
1059 }
1060 }
1061 if (preferred_rrset) {
1062 add_rrset(q, answer, ANSWER_SECTION, domain, preferred_rrset);
1063 } else if (normal_rrset) {
1064 add_rrset(q, answer, ANSWER_SECTION, domain, normal_rrset);
1065 } else if (non_preferred_rrset) {
1066 add_rrset(q, answer, ANSWER_SECTION, domain, non_preferred_rrset);
1067 } else {
1068 answer_nodata(q, answer, original);
1069 return;
1070 }
1071#ifdef NSEC3
1072 } else if (q->qtype == TYPE_NSEC350) {
1073 answer_nodata(q, answer, original);
1074 return;
1075#endif
1076 } else if ((rrset = domain_find_rrset(domain, q->zone, q->qtype))) {
1077 add_rrset(q, answer, ANSWER_SECTION, domain, rrset);
1078 } else if ((rrset = domain_find_rrset(domain, q->zone, TYPE_CNAME5))) {
1079 int added;
1080
1081 /*
1082 * If the CNAME is not added it is already in the
1083 * answer, so we have a CNAME loop. Don't follow the
1084 * CNAME target in this case.
1085 */
1086 added = add_rrset(q, answer, ANSWER_SECTION, domain, rrset);
1087 assert(rrset->rr_count > 0)((void)0);
1088 if (added) {
1089 /* only process first CNAME record */
1090 domain_type *closest_match = rdata_atom_domain(rrset->rrs[0].rdatas[0]);
1091 domain_type *closest_encloser = closest_match;
1092 zone_type* origzone = q->zone;
1093 ++q->cname_count;
1094
1095 answer_lookup_zone(nsd, q, answer, closest_match->number,
1096 closest_match == closest_encloser,
1097 closest_match, closest_encloser,
1098 domain_dname(closest_match));
1099 q->zone = origzone;
1100 }
1101 return;
1102 } else {
1103 answer_nodata(q, answer, original);
1104 return;
1105 }
1106
1107 if (q->qclass != CLASS_ANY255 && q->zone->ns_rrset && answer_needs_ns(q)
1108 && !minimal_responses) {
1109 add_rrset(q, answer, OPTIONAL_AUTHORITY_SECTION, q->zone->apex,
1110 q->zone->ns_rrset);
1111 }
1112}
1113
1114
1115/*
1116 * Answer with authoritative data. If a wildcard is matched the owner
1117 * name will be expanded to the domain name specified by
1118 * DOMAIN_NUMBER. DOMAIN_NUMBER 0 (zero) is reserved for the original
1119 * query name.
1120 *
1121 * DNSSEC: Include the necessary NSEC records in case the request
1122 * domain name does not exist and/or a wildcard match does not exist.
1123 */
1124static void
1125answer_authoritative(struct nsd *nsd,
1126 struct query *q,
1127 answer_type *answer,
1128 size_t domain_number,
1129 int exact,
1130 domain_type *closest_match,
1131 domain_type *closest_encloser,
1132 const dname_type *qname)
1133{
1134 domain_type *match;
1135 domain_type *original = closest_match;
1136 domain_type *dname_ce;
1137 domain_type *wildcard_child;
1138 rrset_type *rrset;
1139
1140#ifdef NSEC3
1141 if(exact
13.1
'exact' is 0
13.1
'exact' is 0
&& domain_has_only_NSEC3(closest_match, q->zone)) {
1142 exact = 0; /* pretend it does not exist */
1143 if(closest_encloser->parent)
1144 closest_encloser = closest_encloser->parent;
1145 }
1146#endif /* NSEC3 */
1147 if((dname_ce = find_dname_above(closest_encloser, q->zone)) != NULL((void *)0)) {
14
Assuming the condition is false
15
Taking false branch
1148 /* occlude the found data, the DNAME is closest_encloser */
1149 closest_encloser = dname_ce;
1150 exact = 0;
1151 }
1152
1153 if (exact
15.1
'exact' is 0
15.1
'exact' is 0
) {
16
Taking false branch
1154 match = closest_match;
1155 } else if ((rrset=domain_find_rrset(closest_encloser, q->zone, TYPE_DNAME39))) {
17
Assuming 'rrset' is non-null
18
Taking true branch
1156 /* process DNAME */
1157 const dname_type* name = qname;
1158 domain_type* src = closest_encloser;
19
'src' initialized to a null pointer value
1159 domain_type *dest = rdata_atom_domain(rrset->rrs[0].rdatas[0]);
1160 const dname_type* newname;
1161 size_t newnum = 0;
1162 zone_type* origzone = q->zone;
1163 assert(rrset->rr_count > 0)((void)0);
1164 if(domain_number != 0) /* we followed CNAMEs or DNAMEs */
20
Assuming 'domain_number' is equal to 0
21
Taking false branch
1165 name = domain_dname(closest_match);
1166 DEBUG(DEBUG_QUERY,2, (LOG_INFO, "expanding DNAME for q=%s", dname_to_string(name, NULL)));
1167 DEBUG(DEBUG_QUERY,2, (LOG_INFO, "->src is %s",
1168 domain_to_string(closest_encloser)));
1169 DEBUG(DEBUG_QUERY,2, (LOG_INFO, "->dest is %s",
1170 domain_to_string(dest)));
1171 if(!add_rrset(q, answer, ANSWER_SECTION, closest_encloser, rrset)) {
22
Assuming the condition is false
23
Taking false branch
1172 /* stop if DNAME loops, when added second time */
1173 if(dname_is_subdomain(domain_dname(dest), domain_dname(src))) {
1174 return;
1175 }
1176 }
1177 newname = dname_replace(q->region, name,
1178 domain_dname(src), domain_dname(dest));
24
Passing null pointer value via 1st parameter 'domain'
25
Calling 'domain_dname'
1179 ++q->cname_count;
1180 if(!newname) { /* newname too long */
1181 RCODE_SET(q->packet, RCODE_YXDOMAIN)(*buffer_at((q->packet), 3) = (*buffer_at((q->packet), 3
) & ~0x0fU) | (6))
;
1182 /* RFC 8914 - Extended DNS Errors
1183 * 4.21. Extended DNS Error Code 0 - Other */
1184 ASSIGN_EDE_CODE_AND_STRING_LITERAL(q->edns.ede,do { q->edns.ede = (0); q->edns.ede_text = ("DNAME expansion became too large"
""); q->edns.ede_text_len = sizeof("DNAME expansion became too large"
) - 1; } while (0)
1185 EDE_OTHER, "DNAME expansion became too large")do { q->edns.ede = (0); q->edns.ede_text = ("DNAME expansion became too large"
""); q->edns.ede_text_len = sizeof("DNAME expansion became too large"
) - 1; } while (0)
;
1186 return;
1187 }
1188 DEBUG(DEBUG_QUERY,2, (LOG_INFO, "->result is %s", dname_to_string(newname, NULL)));
1189 /* follow the DNAME */
1190 (void)namedb_lookup(nsd->db, newname, &closest_match, &closest_encloser);
1191 /* synthesize CNAME record */
1192 newnum = query_synthesize_cname(q, answer, name, newname,
1193 src, closest_encloser, &closest_match, rrset->rrs[0].ttl);
1194 if(!newnum) {
1195 /* could not synthesize the CNAME. */
1196 /* return previous CNAMEs to make resolver recurse for us */
1197 return;
1198 }
1199 if(q->qtype == TYPE_CNAME5) {
1200 /* The synthesized CNAME is the answer to
1201 * that query, same as BIND does for query
1202 * of type CNAME */
1203 return;
1204 }
1205
1206 answer_lookup_zone(nsd, q, answer, newnum,
1207 closest_match == closest_encloser,
1208 closest_match, closest_encloser, newname);
1209 q->zone = origzone;
1210 return;
1211 } else if ((wildcard_child=domain_wildcard_child(closest_encloser))!=NULL((void *)0) &&
1212 wildcard_child->is_existing) {
1213 /* Generate the domain from the wildcard. */
1214#ifdef RATELIMIT
1215 q->wildcard_domain = wildcard_child;
1216#endif
1217
1218 match = (domain_type *) region_alloc(q->region,
1219 sizeof(domain_type));
1220#ifdef USE_RADIX_TREE
1221 match->rnode = NULL((void *)0);
1222 match->dname = wildcard_child->dname;
1223#else
1224 memcpy(&match->node, &wildcard_child->node, sizeof(rbnode_type));
1225 match->node.parent = NULL((void *)0);
1226#endif
1227 match->parent = closest_encloser;
1228 match->wildcard_child_closest_match = match;
1229 match->number = domain_number;
1230 match->rrsets = wildcard_child->rrsets;
1231 match->is_existing = wildcard_child->is_existing;
1232#ifdef NSEC3
1233 match->nsec3 = wildcard_child->nsec3;
1234 /* copy over these entries:
1235 match->nsec3_is_exact = wildcard_child->nsec3_is_exact;
1236 match->nsec3_cover = wildcard_child->nsec3_cover;
1237 match->nsec3_wcard_child_cover = wildcard_child->nsec3_wcard_child_cover;
1238 match->nsec3_ds_parent_is_exact = wildcard_child->nsec3_ds_parent_is_exact;
1239 match->nsec3_ds_parent_cover = wildcard_child->nsec3_ds_parent_cover;
1240 */
1241
1242 if (q->edns.dnssec_ok && q->zone->nsec3_param) {
1243 /* Only add nsec3 wildcard data when do bit is set */
1244 nsec3_answer_wildcard(q, answer, wildcard_child, qname);
1245 }
1246#endif
1247
1248 /*
1249 * Remember the original domain in case a Wildcard No
1250 * Data (3.1.3.4) response needs to be generated. In
1251 * this particular case the wildcard IS NOT
1252 * expanded.
1253 */
1254 original = wildcard_child;
1255 } else {
1256 match = NULL((void *)0);
1257 }
1258
1259 /* Authoritative zone. */
1260#ifdef NSEC3
1261 if (q->edns.dnssec_ok && q->zone->nsec3_param) {
1262 nsec3_answer_authoritative(&match, q, answer,
1263 closest_encloser, qname);
1264 } else
1265#endif
1266 if (q->edns.dnssec_ok && zone_is_secure(q->zone)) {
1267 if (match != closest_encloser) {
1268 domain_type *nsec_domain;
1269 rrset_type *nsec_rrset;
1270
1271 /*
1272 * No match found or generated from wildcard,
1273 * include NSEC record.
1274 */
1275 nsec_domain = find_covering_nsec(closest_match, q->zone, &nsec_rrset);
1276 if (nsec_domain) {
1277 add_rrset(q, answer, AUTHORITY_SECTION, nsec_domain, nsec_rrset);
1278 }
1279 }
1280 if (!match) {
1281 domain_type *nsec_domain;
1282 rrset_type *nsec_rrset;
1283
1284 /*
1285 * No match and no wildcard. Include NSEC
1286 * proving there is no wildcard.
1287 */
1288 if(closest_encloser && (nsec_domain =
1289 find_covering_nsec(closest_encloser->
1290 wildcard_child_closest_match, q->zone,
1291 &nsec_rrset)) != NULL((void *)0)) {
1292 add_rrset(q, answer, AUTHORITY_SECTION, nsec_domain, nsec_rrset);
1293 }
1294 }
1295 }
1296
1297#ifdef NSEC3
1298 if (RCODE(q->packet)(*buffer_at((q->packet), 3) & 0x0fU)!=RCODE_OK0) {
1299 return; /* nsec3 collision failure */
1300 }
1301#endif
1302 if (match) {
1303 answer_domain(nsd, q, answer, match, original);
1304 } else {
1305 answer_nxdomain(q, answer);
1306 }
1307}
1308
1309/*
1310 * qname may be different after CNAMEs have been followed from query->qname.
1311 */
1312static void
1313answer_lookup_zone(struct nsd *nsd, struct query *q, answer_type *answer,
1314 size_t domain_number, int exact, domain_type *closest_match,
1315 domain_type *closest_encloser, const dname_type *qname)
1316{
1317 zone_type* origzone = q->zone;
1318 q->zone = domain_find_zone(nsd->db, closest_encloser);
1319 if (!q->zone) {
1
Assuming field 'zone' is non-null
2
Taking false branch
1320 /* no zone for this */
1321 if(q->cname_count == 0) {
1322 RCODE_SET(q->packet, RCODE_REFUSE)(*buffer_at((q->packet), 3) = (*buffer_at((q->packet), 3
) & ~0x0fU) | (5))
;
1323 /* RFC 8914 - Extended DNS Errors
1324 * 4.21. Extended DNS Error Code 20 - Not Authoritative */
1325 q->edns.ede = EDE_NOT_AUTHORITATIVE20;
1326 }
1327 return;
1328 }
1329 assert(closest_encloser)((void)0); /* otherwise, no q->zone would be found */
1330 if(q->zone->opts && q->zone->opts->pattern
3
Assuming field 'opts' is null
1331 && q->zone->opts->pattern->allow_query) {
1332 struct acl_options *why = NULL((void *)0);
1333
1334 /* check if it passes acl */
1335 if(q->is_proxied && acl_check_incoming_block_proxy(
1336 q->zone->opts->pattern->allow_query, q, &why) == -1) {
1337 /* the proxy address is blocked */
1338 if (verbosity >= 2) {
1339 char address[128], proxy[128];
1340 addr2str(&q->client_addr, address, sizeof(address));
1341 addr2str(&q->remote_addr, proxy, sizeof(proxy));
1342 VERBOSITY(2, (LOG_INFO, "query %s from %s via proxy %s refused because of proxy, %s %s",do { if ((2) <= verbosity) { log_msg (6, "query %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, proxy, (
why?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
1343 dname_to_string(q->qname, NULL),do { if ((2) <= verbosity) { log_msg (6, "query %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, proxy, (
why?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
1344 address, proxy,do { if ((2) <= verbosity) { log_msg (6, "query %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, proxy, (
why?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
1345 (why?why->ip_address_spec:"."),do { if ((2) <= verbosity) { log_msg (6, "query %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, proxy, (
why?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
1346 (why ? ( why->nokey ? "NOKEY"do { if ((2) <= verbosity) { log_msg (6, "query %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, proxy, (
why?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
1347 : why->blocked ? "BLOCKED"do { if ((2) <= verbosity) { log_msg (6, "query %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, proxy, (
why?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
1348 : why->key_name )do { if ((2) <= verbosity) { log_msg (6, "query %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, proxy, (
why?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
1349 : "no acl matches")))do { if ((2) <= verbosity) { log_msg (6, "query %s from %s via proxy %s refused because of proxy, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, proxy, (
why?why->ip_address_spec:"."), (why ? ( why->nokey ? "NOKEY"
: why->blocked ? "BLOCKED" : why->key_name ) : "no acl matches"
)) ; } } while (0)
;
1350 }
1351 /* no zone for this */
1352 if(q->cname_count == 0) {
1353 RCODE_SET(q->packet, RCODE_REFUSE)(*buffer_at((q->packet), 3) = (*buffer_at((q->packet), 3
) & ~0x0fU) | (5))
;
1354 /* RFC8914 - Extended DNS Errors
1355 * 4.19. Extended DNS Error Code 18 - Prohibited */
1356 q->edns.ede = EDE_PROHIBITED18;
1357 }
1358 return;
1359 }
1360 if(acl_check_incoming(
1361 q->zone->opts->pattern->allow_query, q, &why) != -1) {
1362 assert(why)((void)0);
1363 DEBUG(DEBUG_QUERY,1, (LOG_INFO, "query %s passed acl %s %s",
1364 dname_to_string(q->qname, NULL),
1365 why->ip_address_spec,
1366 why->nokey?"NOKEY":
1367 (why->blocked?"BLOCKED":why->key_name)));
1368 } else {
1369 if (verbosity >= 2) {
1370 char address[128];
1371 addr2str(&q->client_addr, address, sizeof(address));
1372 VERBOSITY(2, (LOG_INFO, "query %s from %s refused, %s %s",do { if ((2) <= verbosity) { log_msg (6, "query %s from %s refused, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, why ? (
why->nokey ? "NOKEY" : why->blocked ? "BLOCKED" : why->
key_name ) : "no acl matches", why?why->ip_address_spec:"."
) ; } } while (0)
1373 dname_to_string(q->qname, NULL),do { if ((2) <= verbosity) { log_msg (6, "query %s from %s refused, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, why ? (
why->nokey ? "NOKEY" : why->blocked ? "BLOCKED" : why->
key_name ) : "no acl matches", why?why->ip_address_spec:"."
) ; } } while (0)
1374 address,do { if ((2) <= verbosity) { log_msg (6, "query %s from %s refused, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, why ? (
why->nokey ? "NOKEY" : why->blocked ? "BLOCKED" : why->
key_name ) : "no acl matches", why?why->ip_address_spec:"."
) ; } } while (0)
1375 why ? ( why->nokey ? "NOKEY"do { if ((2) <= verbosity) { log_msg (6, "query %s from %s refused, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, why ? (
why->nokey ? "NOKEY" : why->blocked ? "BLOCKED" : why->
key_name ) : "no acl matches", why?why->ip_address_spec:"."
) ; } } while (0)
1376 : why->blocked ? "BLOCKED"do { if ((2) <= verbosity) { log_msg (6, "query %s from %s refused, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, why ? (
why->nokey ? "NOKEY" : why->blocked ? "BLOCKED" : why->
key_name ) : "no acl matches", why?why->ip_address_spec:"."
) ; } } while (0)
1377 : why->key_name )do { if ((2) <= verbosity) { log_msg (6, "query %s from %s refused, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, why ? (
why->nokey ? "NOKEY" : why->blocked ? "BLOCKED" : why->
key_name ) : "no acl matches", why?why->ip_address_spec:"."
) ; } } while (0)
1378 : "no acl matches",do { if ((2) <= verbosity) { log_msg (6, "query %s from %s refused, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, why ? (
why->nokey ? "NOKEY" : why->blocked ? "BLOCKED" : why->
key_name ) : "no acl matches", why?why->ip_address_spec:"."
) ; } } while (0)
1379 why?why->ip_address_spec:"."))do { if ((2) <= verbosity) { log_msg (6, "query %s from %s refused, %s %s"
, dname_to_string(q->qname, ((void *)0)), address, why ? (
why->nokey ? "NOKEY" : why->blocked ? "BLOCKED" : why->
key_name ) : "no acl matches", why?why->ip_address_spec:"."
) ; } } while (0)
;
1380 }
1381 /* no zone for this */
1382 if(q->cname_count == 0) {
1383 RCODE_SET(q->packet, RCODE_REFUSE)(*buffer_at((q->packet), 3) = (*buffer_at((q->packet), 3
) & ~0x0fU) | (5))
;
1384 /* RFC8914 - Extended DNS Errors
1385 * 4.19. Extended DNS Error Code 18 - Prohibited */
1386 q->edns.ede = EDE_PROHIBITED18;
1387 }
1388 return;
1389 }
1390 }
1391 if(!q->zone->apex || !q->zone->soa_rrset) {
4
Assuming field 'apex' is non-null
5
Assuming field 'soa_rrset' is non-null
1392 /* zone is configured but not loaded */
1393 if(q->cname_count == 0) {
1394 RCODE_SET(q->packet, RCODE_SERVFAIL)(*buffer_at((q->packet), 3) = (*buffer_at((q->packet), 3
) & ~0x0fU) | (2))
;
1395 /* RFC 8914 - Extended DNS Errors
1396 * 4.15. Extended DNS Error Code 14 - Not Ready */
1397 q->edns.ede = EDE_NOT_READY14;
1398 ASSIGN_EDE_CODE_AND_STRING_LITERAL(q->edns.ede,do { q->edns.ede = (14); q->edns.ede_text = ("Zone is configured but not loaded"
""); q->edns.ede_text_len = sizeof("Zone is configured but not loaded"
) - 1; } while (0)
1399 EDE_NOT_READY, "Zone is configured but not loaded")do { q->edns.ede = (14); q->edns.ede_text = ("Zone is configured but not loaded"
""); q->edns.ede_text_len = sizeof("Zone is configured but not loaded"
) - 1; } while (0)
;
1400 }
1401 return;
1402 }
1403
1404 /*
1405 * If confine-to-zone is set to yes do not return additional
1406 * information for a zone with a different apex from the query zone.
1407 */
1408 if (nsd->options->confine_to_zone &&
6
Assuming field 'confine_to_zone' is 0
1409 (origzone != NULL((void *)0) && dname_compare(domain_dname(origzone->apex), domain_dname(q->zone->apex)) != 0)) {
1410 return;
1411 }
1412
1413 /* now move up the closest encloser until it exists, previous
1414 * (possibly empty) closest encloser was useful to finding the zone
1415 * (for empty zones too), but now we want actual data nodes */
1416 if (closest_encloser && !closest_encloser->is_existing) {
7
Assuming 'closest_encloser' is null
1417 exact = 0;
1418 while (closest_encloser != NULL((void *)0) && !closest_encloser->is_existing)
1419 closest_encloser = closest_encloser->parent;
1420 }
1421
1422 /*
1423 * See RFC 4035 (DNSSEC protocol) section 3.1.4.1 Responding
1424 * to Queries for DS RRs.
1425 */
1426 if (exact && q->qtype == TYPE_DS43 && closest_encloser == q->zone->apex) {
8
Assuming 'exact' is 0
1427 /*
1428 * Type DS query at a zone cut, use the responsible
1429 * parent zone to generate the answer if we are
1430 * authoritative for the parent zone.
1431 */
1432 zone_type *zone = domain_find_parent_zone(nsd->db, q->zone);
1433 if (zone) {
1434 q->zone = zone;
1435 if(!q->zone->apex || !q->zone->soa_rrset) {
1436 /* zone is configured but not loaded */
1437 if(q->cname_count == 0) {
1438 RCODE_SET(q->packet, RCODE_SERVFAIL)(*buffer_at((q->packet), 3) = (*buffer_at((q->packet), 3
) & ~0x0fU) | (2))
;
1439 /* RFC 8914 - Extended DNS Errors
1440 * 4.15. Extended DNS Error Code 14 - Not Ready */
1441 ASSIGN_EDE_CODE_AND_STRING_LITERAL(do { q->edns.ede = (14); q->edns.ede_text = ("Zone is configured but not loaded"
""); q->edns.ede_text_len = sizeof("Zone is configured but not loaded"
) - 1; } while (0)
1442 q->edns.ede, EDE_NOT_READY,do { q->edns.ede = (14); q->edns.ede_text = ("Zone is configured but not loaded"
""); q->edns.ede_text_len = sizeof("Zone is configured but not loaded"
) - 1; } while (0)
1443 "Zone is configured but not loaded")do { q->edns.ede = (14); q->edns.ede_text = ("Zone is configured but not loaded"
""); q->edns.ede_text_len = sizeof("Zone is configured but not loaded"
) - 1; } while (0)
;
1444 }
1445 return;
1446 }
1447 }
1448 }
1449
1450 /* see if the zone has expired (for secondary zones) */
1451 if(q->zone
8.1
Field 'zone' is non-null
8.1
Field 'zone' is non-null
&& q->zone->opts
8.2
Field 'opts' is null
8.2
Field 'opts' is null
&& q->zone->opts->pattern &&
1452 q->zone->opts->pattern->request_xfr != 0 && !q->zone->is_ok) {
1453 if(q->cname_count == 0) {
1454 RCODE_SET(q->packet, RCODE_SERVFAIL)(*buffer_at((q->packet), 3) = (*buffer_at((q->packet), 3
) & ~0x0fU) | (2))
;
1455 /* RFC 8914 - Extended DNS Errors
1456 * 4.25. Extended DNS Error Code 24 - Invalid Data */
1457 ASSIGN_EDE_CODE_AND_STRING_LITERAL(q->edns.ede,do { q->edns.ede = (24); q->edns.ede_text = ("Zone has expired"
""); q->edns.ede_text_len = sizeof("Zone has expired") - 1
; } while (0)
1458 EDE_INVALID_DATA, "Zone has expired")do { q->edns.ede = (24); q->edns.ede_text = ("Zone has expired"
""); q->edns.ede_text_len = sizeof("Zone has expired") - 1
; } while (0)
;
1459 }
1460 return;
1461 }
1462
1463 if (exact
8.3
'exact' is 0
8.3
'exact' is 0
&& q->qtype == TYPE_DS43 && closest_encloser == q->zone->apex) {
1464 /*
1465 * Type DS query at the zone apex (and the server is
1466 * not authoritative for the parent zone).
1467 */
1468 if (q->qclass == CLASS_ANY255) {
1469 AA_CLR(q->packet)(*buffer_at((q->packet), 2) &= ~0x04U);
1470 } else {
1471 AA_SET(q->packet)(*buffer_at((q->packet), 2) |= 0x04U);
1472 }
1473 answer_nodata(q, answer, closest_encloser);
1474 } else {
1475 q->delegation_domain = domain_find_ns_rrsets(
1476 closest_encloser, q->zone, &q->delegation_rrset);
1477 if(q->delegation_domain && find_dname_above(q->delegation_domain, q->zone)) {
9
Assuming field 'delegation_domain' is null
1478 q->delegation_domain = NULL((void *)0); /* use higher DNAME */
1479 }
1480
1481 if (!q->delegation_domain
9.1
Field 'delegation_domain' is null
9.1
Field 'delegation_domain' is null
1482 || !q->delegation_rrset 1483 || (exact && q->qtype == TYPE_DS43 && closest_encloser == q->delegation_domain)) 1484 { 1485 if (q->qclass == CLASS_ANY255) {
10
Assuming field 'qclass' is not equal to CLASS_ANY
11
Taking false branch
1486 AA_CLR(q->packet)(*buffer_at((q->packet), 2) &= ~0x04U); 1487 } else { 1488 AA_SET(q->packet)(*buffer_at((q->packet), 2) |= 0x04U); 1489 } 1490 answer_authoritative(nsd, q, answer, domain_number, exact,
13
Calling 'answer_authoritative'
1491 closest_match, closest_encloser, qname);
12
Passing null pointer value via 7th parameter 'closest_encloser'
1492 } 1493 else { 1494 answer_delegation(q, answer); 1495 } 1496 } 1497} 1498 1499static void 1500answer_query(struct nsd *nsd, struct query *q) 1501{ 1502 domain_type *closest_match; 1503 domain_type *closest_encloser; 1504 int exact; 1505 uint16_t offset; 1506 answer_type answer; 1507 1508 answer_init(&answer); 1509 1510 exact = namedb_lookup(nsd->db, q->qname, &closest_match, &closest_encloser); 1511 1512 answer_lookup_zone(nsd, q, &answer, 0, exact, closest_match, 1513 closest_encloser, q->qname); 1514 ZTATUP2(nsd, q->zone, opcode, q->opcode); 1515 ZTATUP2(nsd, q->zone, qtype, q->qtype); 1516 ZTATUP2(nsd, q->zone, qclass, q->qclass); 1517 1518 offset = dname_label_offsets(q->qname)[domain_dname(closest_encloser)->label_count - 1] + QHEADERSZ12; 1519 query_add_compression_domain(q, closest_encloser, offset); 1520 encode_answer(q, &answer); 1521 query_clear_compression_tables(q); 1522} 1523 1524void 1525query_prepare_response(query_type *q) 1526{ 1527 uint16_t flags; 1528 1529 /* 1530 * Preserve the data up-to the current packet's limit. 1531 */ 1532 buffer_set_position(q->packet, buffer_limit(q->packet)); 1533 buffer_set_limit(q->packet, buffer_capacity(q->packet)); 1534 1535 /* 1536 * Reserve space for the EDNS records if required. 1537 */ 1538 q->reserved_space = edns_reserved_space(&q->edns); 1539 q->reserved_space += tsig_reserved_space(&q->tsig); 1540 1541 /* Update the flags. */ 1542 flags = FLAGS(q->packet)(buffer_read_u16_at((q->packet), 2)); 1543 flags &= 0x0100U; /* Preserve the RD flag. */ 1544 /* CD flag must be cleared for auth answers */ 1545 flags |= 0x8000U; /* Set the QR flag. */ 1546 FLAGS_SET(q->packet, flags)(buffer_write_u16_at((q->packet), 2, (flags))); 1547} 1548 1549/* 1550 * Processes the query. 1551 * 1552 */ 1553query_state_type 1554query_process(query_type *q, nsd_type *nsd, uint32_t *now_p) 1555{ 1556 /* The query... */ 1557 nsd_rc_type rc; 1558 query_state_type query_state; 1559 uint16_t arcount; 1560 1561 /* Sanity checks */ 1562 if (buffer_limit(q->packet) < QHEADERSZ12) { 1563 /* packet too small to contain DNS header. 1564 Now packet investigation macros will work without problems. */ 1565 return QUERY_DISCARDED; 1566 } 1567 if (QR(q->packet)(*buffer_at((q->packet), 2) & 0x80U)) { 1568 /* Not a query? Drop it on the floor. */ 1569 return QUERY_DISCARDED; 1570 } 1571 1572 /* check opcode early on, because new opcodes may have different 1573 * specification of the meaning of the rest of the packet */ 1574 q->opcode = OPCODE(q->packet)((*buffer_at((q->packet), 2) & 0x78U) >> 3); 1575 if(q->opcode != OPCODE_QUERY0 && q->opcode != OPCODE_NOTIFY4) { 1576 if(query_ratelimit_err(nsd)) 1577 return QUERY_DISCARDED; 1578 if(nsd->options->drop_updates && q->opcode == OPCODE_UPDATE5) 1579 return QUERY_DISCARDED; 1580 return query_error(q, NSD_RC_IMPL); 1581 } 1582 1583 if (RCODE(q->packet)(*buffer_at((q->packet), 3) & 0x0fU) != RCODE_OK0 || !process_query_section(q)) { 1584 return query_formerr(q, nsd); 1585 } 1586 1587 /* Update statistics. */ 1588 STATUP2(nsd, opcode, q->opcode)nsd->st->opcode[(q->opcode) <= ((sizeof(nsd->st
->opcode) / sizeof(nsd->st->opcode[0]) - 1) - 1) ? q
->opcode : (sizeof(nsd->st->opcode) / sizeof(nsd->
st->opcode[0]) - 1)]++
; 1589 STATUP2(nsd, qtype, q->qtype)nsd->st->qtype[(q->qtype) <= ((sizeof(nsd->st->
qtype) / sizeof(nsd->st->qtype[0]) - 1) - 1) ? q->qtype
: (sizeof(nsd->st->qtype) / sizeof(nsd->st->qtype
[0]) - 1)]++
; 1590 STATUP2(nsd, qclass, q->qclass)nsd->st->qclass[(q->qclass) <= ((sizeof(nsd->st
->qclass) / sizeof(nsd->st->qclass[0]) - 1) - 1) ? q
->qclass : (sizeof(nsd->st->qclass) / sizeof(nsd->
st->qclass[0]) - 1)]++
; 1591 1592 if (q->opcode != OPCODE_QUERY0) { 1593 if (q->opcode == OPCODE_NOTIFY4) { 1594 return answer_notify(nsd, q); 1595 } else { 1596 if(query_ratelimit_err(nsd)) 1597 return QUERY_DISCARDED; 1598 return query_error(q, NSD_RC_IMPL); 1599 } 1600 } 1601 1602 /* Dont bother to answer more than one question at once... */ 1603 if (QDCOUNT(q->packet)(buffer_read_u16_at((q->packet), 4)) != 1) { 1604 if(QDCOUNT(q->packet)(buffer_read_u16_at((q->packet), 4)) == 0 && ANCOUNT(q->packet)(buffer_read_u16_at((q->packet), 6)) == 0 && 1605 NSCOUNT(q->packet)(buffer_read_u16_at((q->packet), 8)) == 0 && ARCOUNT(q->packet)(buffer_read_u16_at((q->packet), 10)) == 1 && 1606 buffer_limit(q->packet) >= QHEADERSZ12+OPT_LEN9U+ 1607 OPT_RDATA2) { 1608 /* add edns section to answer */ 1609 buffer_set_position(q->packet, QHEADERSZ12); 1610 if (edns_parse_record(&q->edns, q->packet, q, nsd)) { 1611 if(process_edns(nsd, q) == NSD_RC_OK) { 1612 int opcode = OPCODE(q->packet)((*buffer_at((q->packet), 2) & 0x78U) >> 3); 1613 (void)query_error(q, NSD_RC_FORMAT); 1614 query_add_optional(q, nsd, now_p); 1615 FLAGS_SET(q->packet, FLAGS(q->packet) & 0x0100U)(buffer_write_u16_at((q->packet), 2, ((buffer_read_u16_at(
(q->packet), 2)) & 0x0100U)))
; 1616 /* Preserve the RD flag. Clear the rest. */ 1617 OPCODE_SET(q->packet, opcode)(*buffer_at((q->packet), 2) = (*buffer_at((q->packet), 2
) & ~0x78U) | ((opcode) << 3))
; 1618 QR_SET(q->packet)(*buffer_at((q->packet), 2) |= 0x80U); 1619 return QUERY_PROCESSED; 1620 } 1621 } 1622 } 1623 FLAGS_SET(q->packet, 0)(buffer_write_u16_at((q->packet), 2, (0))); 1624 return query_formerr(q, nsd); 1625 } 1626 /* Ignore settings of flags */ 1627 1628 /* Dont allow any records in the answer or authority section... 1629 except for IXFR queries. */ 1630 if (ANCOUNT(q->packet)(buffer_read_u16_at((q->packet), 6)) != 0 || 1631 (q->qtype!=TYPE_IXFR251 && NSCOUNT(q->packet)(buffer_read_u16_at((q->packet), 8)) != 0)) { 1632 return query_formerr(q, nsd); 1633 } 1634 if(q->qtype==TYPE_IXFR251 && NSCOUNT(q->packet)(buffer_read_u16_at((q->packet), 8)) > 0) { 1635 unsigned int i; /* skip ixfr soa information data here */ 1636 unsigned int nscount = (unsigned)NSCOUNT(q->packet)(buffer_read_u16_at((q->packet), 8)); 1637 /* define a bound on the number of extraneous records allowed, 1638 * we expect 1, a SOA serial record, and no more. 1639 * perhaps RRSIGs (but not needed), otherwise we do not 1640 * understand what this means. We do not want too many 1641 * because the high iteration counts slow down. */ 1642 if(nscount > 64) return query_formerr(q, nsd); 1643 for(i=0; i< nscount; i++) 1644 if(!packet_skip_rr(q->packet, 0)) 1645 return query_formerr(q, nsd); 1646 } 1647 1648 arcount = ARCOUNT(q->packet)(buffer_read_u16_at((q->packet), 10)); 1649 /* A TSIG RR is not allowed before the EDNS OPT RR. 1650 * In RFC6891 (about EDNS) it says: 1651 * "The placement flexibility for the OPT RR does not 1652 * override the need for the TSIG or SIG(0) RRs to be 1653 * the last in the additional section whenever they are 1654 * present." 1655 * And in RFC8945 (about TSIG) it says: 1656 * "If multiple TSIG records are detected or a TSIG record is 1657 * present in any other position, the DNS message is dropped 1658 * and a response with RCODE 1 (FORMERR) MUST be returned." 1659 */ 1660 /* See if there is an OPT RR. */ 1661 if (arcount > 0) { 1662 if (edns_parse_record(&q->edns, q->packet, q, nsd)) 1663 --arcount; 1664 } 1665 /* See if there is a TSIG RR. */ 1666 if (arcount > 0 && q->tsig.status == TSIG_NOT_PRESENT) { 1667 /* see if tsig is after the edns record */ 1668 if (!tsig_parse_rr(&q->tsig, q->packet)) 1669 return query_formerr(q, nsd); 1670 if(q->tsig.status != TSIG_NOT_PRESENT) 1671 --arcount; 1672 } 1673 /* If more RRs left in Add. Section, FORMERR. */ 1674 if (arcount > 0) { 1675 return query_formerr(q, nsd); 1676 } 1677 1678 /* Do we have any trailing garbage? */ 1679#ifdef STRICT_MESSAGE_PARSE 1680 if (buffer_remaining(q->packet) > 0) { 1681 /* If we're strict.... */ 1682 return query_formerr(q, nsd); 1683 } 1684#endif 1685 /* Remove trailing garbage. */ 1686 buffer_set_limit(q->packet, buffer_position(q->packet)); 1687 1688 rc = process_tsig(q); 1689 if (rc != NSD_RC_OK) { 1690 return query_error(q, rc); 1691 } 1692 rc = process_edns(nsd, q); 1693 if (rc != NSD_RC_OK) { 1694 /* We should not return FORMERR, but BADVERS (=16). 1695 * BADVERS is created with Ext. RCODE, followed by RCODE. 1696 * Ext. RCODE is set to 1, RCODE must be 0 (getting 0x10 = 16). 1697 * Thus RCODE = NOERROR = NSD_RC_OK. */ 1698 RCODE_SET(q->packet, NSD_RC_OK)(*buffer_at((q->packet), 3) = (*buffer_at((q->packet), 3
) & ~0x0fU) | (NSD_RC_OK))
; 1699 buffer_clear(q->packet); 1700 buffer_set_position(q->packet, 1701 QHEADERSZ12 + 4 + q->qname->name_size); 1702 QR_SET(q->packet)(*buffer_at((q->packet), 2) |= 0x80U); 1703 AD_CLR(q->packet)(*buffer_at((q->packet), 3) &= ~0x20U); 1704 QDCOUNT_SET(q->packet, 1)(buffer_write_u16_at((q->packet), 4, (1))); 1705 ANCOUNT_SET(q->packet, 0)(buffer_write_u16_at((q->packet), 6, (0))); 1706 NSCOUNT_SET(q->packet, 0)(buffer_write_u16_at((q->packet), 8, (0))); 1707 ARCOUNT_SET(q->packet, 0)(buffer_write_u16_at((q->packet), 10, (0))); 1708 return QUERY_PROCESSED; 1709 } 1710 1711 if (q->edns.cookie_status == COOKIE_UNVERIFIED) 1712 cookie_verify(q, nsd, now_p); 1713 1714 query_prepare_response(q); 1715 1716 if (q->qclass != CLASS_IN1 && q->qclass != CLASS_ANY255) { 1717 if (q->qclass == CLASS_CH3) { 1718 return answer_chaos(nsd, q); 1719 } else { 1720 /* RFC8914 - Extended DNS Errors 1721 * 4.22. Extended DNS Error Code 21 - Not Supported */ 1722 q->edns.ede = EDE_NOT_SUPPORTED21; 1723 return query_error(q, RCODE_REFUSE5); 1724 } 1725 } 1726 query_state = answer_axfr_ixfr(nsd, q); 1727 if (query_state == QUERY_PROCESSED || query_state == QUERY_IN_AXFR 1728 || query_state == QUERY_IN_IXFR) { 1729 return query_state; 1730 } 1731 if(q->qtype == TYPE_ANY255 && nsd->options->refuse_any && !q->tcp) { 1732 TC_SET(q->packet)(*buffer_at((q->packet), 2) |= 0x02U); 1733 return query_error(q, NSD_RC_OK); 1734 } 1735 1736 answer_query(nsd, q); 1737 1738 return QUERY_PROCESSED; 1739} 1740 1741void 1742query_add_optional(query_type *q, nsd_type *nsd, uint32_t *now_p) 1743{ 1744 struct edns_data *edns = &nsd->edns_ipv4; 1745#if defined(INET6) 1746 if (q->client_addr.ss_family == AF_INET624) { 1747 edns = &nsd->edns_ipv6; 1748 } 1749#endif 1750 if (RCODE(q->packet)(*buffer_at((q->packet), 3) & 0x0fU) == RCODE_FORMAT1) { 1751 return; 1752 } 1753 switch (q->edns.status) { 1754 case EDNS_NOT_PRESENT: 1755 break; 1756 case EDNS_OK: 1757 if (q->edns.dnssec_ok) edns->ok[7] = 0x80; 1758 else edns->ok[7] = 0x00; 1759 buffer_write(q->packet, edns->ok, OPT_LEN9U); 1760 1761 /* Add Extended DNS Error (RFC8914) 1762 * to verify that we stay in bounds */ 1763 if (q->edns.ede >= 0) 1764 q->edns.opt_reserved_space += 1765 6 + ( q->edns.ede_text_len 1766 ? q->edns.ede_text_len : 0); 1767 1768 if(q->edns.opt_reserved_space == 0 || !buffer_available( 1769 q->packet, 2+q->edns.opt_reserved_space)) { 1770 /* fill with NULLs */ 1771 buffer_write(q->packet, edns->rdata_none, OPT_RDATA2); 1772 } else { 1773 /* rdata length */ 1774 buffer_write_u16(q->packet, q->edns.opt_reserved_space); 1775 /* edns options */ 1776 if(q->edns.nsid) { 1777 /* nsid opt header */ 1778 buffer_write(q->packet, edns->nsid, OPT_HDR4U); 1779 /* nsid payload */ 1780 buffer_write(q->packet, nsd->nsid, nsd->nsid_len); 1781 } 1782 if(q->edns.cookie_status != COOKIE_NOT_PRESENT) { 1783 /* cookie opt header */ 1784 buffer_write(q->packet, edns->cookie, OPT_HDR4U); 1785 /* cookie payload */ 1786 cookie_create(q, nsd, now_p); 1787 buffer_write(q->packet, q->edns.cookie, 24); 1788 } 1789 /* Append Extended DNS Error (RFC8914) option if needed */ 1790 if (q->edns.ede >= 0) { /* < 0 means no EDE */ 1791 /* OPTION-CODE */ 1792 buffer_write_u16(q->packet, EDE_CODE15); 1793 /* OPTION-LENGTH */ 1794 buffer_write_u16(q->packet, 1795 2 + ( q->edns.ede_text_len 1796 ? q->edns.ede_text_len : 0)); 1797 /* INFO-CODE */ 1798 buffer_write_u16(q->packet, q->edns.ede); 1799 /* EXTRA-TEXT */ 1800 if (q->edns.ede_text_len) 1801 buffer_write(q->packet, 1802 q->edns.ede_text, 1803 q->edns.ede_text_len); 1804 } 1805 } 1806 ARCOUNT_SET(q->packet, ARCOUNT(q->packet) + 1)(buffer_write_u16_at((q->packet), 10, ((buffer_read_u16_at
((q->packet), 10)) + 1)))
; 1807 STATUP(nsd, edns)nsd->st->edns++; 1808 ZTATUP(nsd, q->zone, edns); 1809 break; 1810 case EDNS_ERROR: 1811 if (q->edns.dnssec_ok) edns->error[7] = 0x80; 1812 else edns->error[7] = 0x00; 1813 buffer_write(q->packet, edns->error, OPT_LEN9U); 1814 buffer_write(q->packet, edns->rdata_none, OPT_RDATA2); 1815 ARCOUNT_SET(q->packet, ARCOUNT(q->packet) + 1)(buffer_write_u16_at((q->packet), 10, ((buffer_read_u16_at
((q->packet), 10)) + 1)))
; 1816 STATUP(nsd, ednserr)nsd->st->ednserr++; 1817 ZTATUP(nsd, q->zone, ednserr); 1818 break; 1819 } 1820 1821 if (q->tsig.status != TSIG_NOT_PRESENT) { 1822 if (q->tsig.status == TSIG_ERROR || 1823 q->tsig.error_code != TSIG_ERROR_NOERROR0) { 1824 tsig_error_reply(&q->tsig); 1825 tsig_append_rr(&q->tsig, q->packet); 1826 ARCOUNT_SET(q->packet, ARCOUNT(q->packet) + 1)(buffer_write_u16_at((q->packet), 10, ((buffer_read_u16_at
((q->packet), 10)) + 1)))
; 1827 } else if(q->tsig.status == TSIG_OK && 1828 q->tsig.error_code == TSIG_ERROR_NOERROR0) 1829 { 1830 if(q->tsig_prepare_it) 1831 tsig_prepare(&q->tsig); 1832 if(q->tsig_update_it) 1833 tsig_update(&q->tsig, q->packet, buffer_position(q->packet)); 1834 if(q->tsig_sign_it) { 1835 tsig_sign(&q->tsig); 1836 tsig_append_rr(&q->tsig, q->packet); 1837 ARCOUNT_SET(q->packet, ARCOUNT(q->packet) + 1)(buffer_write_u16_at((q->packet), 10, ((buffer_read_u16_at
((q->packet), 10)) + 1)))
; 1838 } 1839 } 1840 } 1841}

/usr/src/usr.sbin/nsd/namedb.h

1/*
2 * namedb.h -- nsd(8) internal namespace database definitions
3 *
4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
5 *
6 * See LICENSE for the license.
7 *
8 */
9
10#ifndef NAMEDB_H
11#define NAMEDB_H
12
13#include <stdio.h>
14
15#include "dname.h"
16#include "dns.h"
17#include "radtree.h"
18#include "rbtree.h"
19struct zone_options;
20struct nsd_options;
21struct udb_base;
22struct udb_ptr;
23struct nsd;
24struct zone_ixfr;
25
26typedef union rdata_atom rdata_atom_type;
27typedef struct rrset rrset_type;
28typedef struct rr rr_type;
29
30/*
31 * A domain name table supporting fast insert and search operations.
32 */
33typedef struct domain_table domain_table_type;
34typedef struct domain domain_type;
35typedef struct zone zone_type;
36typedef struct namedb namedb_type;
37
38struct domain_table
39{
40 region_type* region;
41#ifdef USE_RADIX_TREE
42 struct radtree *nametree;
43#else
44 rbtree_type *names_to_domains;
45#endif
46 domain_type* root;
47 /* ptr to biggest domain.number and last in list.
48 * the root is the lowest and first in the list. */
49 domain_type *numlist_last;
50#ifdef NSEC3
51 /* the prehash list, start of the list */
52 domain_type* prehash_list;
53#endif /* NSEC3 */
54};
55
56#ifdef NSEC3
57typedef struct nsec3_hash_node nsec3_hash_node_type;
58struct nsec3_hash_node {
59 /* hash value */
60 uint8_t hash[NSEC3_HASH_LEN20];
61 /* entry in the hashtree */
62 rbnode_type node;
63} ATTR_PACKED;
64
65typedef struct nsec3_hash_wc_node nsec3_hash_wc_node_type;
66struct nsec3_hash_wc_node {
67 nsec3_hash_node_type hash;
68 nsec3_hash_node_type wc;
69};
70
71struct nsec3_domain_data {
72 /* (if nsec3 chain complete) always the covering nsec3 record */
73 domain_type* nsec3_cover;
74 /* the nsec3 that covers the wildcard child of this domain. */
75 domain_type* nsec3_wcard_child_cover;
76 /* for the DS case we must answer on the parent side of zone cut */
77 domain_type* nsec3_ds_parent_cover;
78 /* NSEC3 domains to prehash, prev and next on the list or cleared */
79 domain_type* prehash_prev, *prehash_next;
80 /* entry in the nsec3tree (for NSEC3s in the chain in use) */
81 rbnode_type nsec3_node;
82
83 /* node for the precompiled domain and the precompiled wildcard */
84 nsec3_hash_wc_node_type* hash_wc;
85
86 /* node for the precompiled parent ds */
87 nsec3_hash_node_type* ds_parent_hash;
88
89 /* if the domain has an NSEC3 for it, use cover ptr to get it. */
90 unsigned nsec3_is_exact : 1;
91 /* same but on parent side */
92 unsigned nsec3_ds_parent_is_exact : 1;
93} ATTR_PACKED;
94#endif /* NSEC3 */
95
96struct domain
97{
98#ifdef USE_RADIX_TREE
99 struct radnode* rnode;
100 const dname_type* dname;
101#else
102 rbnode_type node;
103#endif
104 domain_type* parent;
105 domain_type* wildcard_child_closest_match;
106 rrset_type* rrsets;
107#ifdef NSEC3
108 struct nsec3_domain_data* nsec3;
109#endif
110 /* double-linked list sorted by domain.number */
111 domain_type* numlist_prev, *numlist_next;
112 uint32_t number; /* Unique domain name number. */
113 uint32_t usage; /* number of ptrs to this from RRs(in rdata) and
114 from zone-apex pointers, also the root has one
115 more to make sure it cannot be deleted. */
116
117 /*
118 * This domain name exists (see wildcard clarification draft).
119 */
120 unsigned is_existing : 1;
121 unsigned is_apex : 1;
122} ATTR_PACKED;
123
124struct zone
125{
126 struct radnode *node; /* this entry in zonetree */
127 domain_type* apex;
128 rrset_type* soa_rrset;
129 rrset_type* soa_nx_rrset; /* see bug #103 */
130 rrset_type* ns_rrset;
131#ifdef NSEC3
132 rr_type* nsec3_param; /* NSEC3PARAM RR of chain in use or NULL */
133 domain_type* nsec3_last; /* last domain with nsec3, wraps */
134 /* in these trees, the root contains an elem ptr to the radtree* */
135 rbtree_type* nsec3tree; /* tree with relevant NSEC3 domains */
136 rbtree_type* hashtree; /* tree, hashed NSEC3precompiled domains */
137 rbtree_type* wchashtree; /* tree, wildcard hashed domains */
138 rbtree_type* dshashtree; /* tree, ds-parent-hash domains */
139#endif
140 struct zone_options* opts;
141 struct zone_ixfr* ixfr;
142 char* filename; /* set if read from file, which file */
143 char* logstr; /* set for zone xfer, the log string */
144 struct timespec mtime; /* time of last modification */
145 unsigned zonestatid; /* array index for zone stats */
146 unsigned is_secure : 1; /* zone uses DNSSEC */
147 unsigned is_ok : 1; /* zone has not expired */
148 unsigned is_changed : 1; /* zone changes must be written to disk */
149 unsigned is_updated : 1; /* zone was changed by XFR */
150 unsigned is_skipped : 1; /* subsequent zone updates are skipped */
151 unsigned is_checked : 1; /* zone already verified */
152 unsigned is_bad : 1; /* zone failed verification */
153} ATTR_PACKED;
154
155/* a RR in DNS */
156struct rr {
157 domain_type* owner;
158 rdata_atom_type* rdatas;
159 uint32_t ttl;
160 uint16_t type;
161 uint16_t klass;
162 uint16_t rdata_count;
163} ATTR_PACKED;
164
165/*
166 * An RRset consists of at least one RR. All RRs are from the same
167 * zone.
168 */
169struct rrset
170{
171 rrset_type* next;
172 zone_type* zone;
173 rr_type* rrs;
174 uint16_t rr_count;
175} ATTR_PACKED;
176
177/*
178 * The field used is based on the wireformat the atom is stored in.
179 * The allowed wireformats are defined by the rdata_wireformat_type
180 * enumeration.
181 */
182union rdata_atom
183{
184 /* RDATA_WF_COMPRESSED_DNAME, RDATA_WF_UNCOMPRESSED_DNAME */
185 domain_type* domain;
186
187 /* Default. */
188 uint16_t* data;
189};
190
191/*
192 * Create a new domain_table containing only the root domain.
193 */
194domain_table_type *domain_table_create(region_type *region);
195
196/*
197 * Search the domain table for a match and the closest encloser.
198 */
199int domain_table_search(domain_table_type* table,
200 const dname_type* dname,
201 domain_type **closest_match,
202 domain_type **closest_encloser);
203
204/*
205 * The number of domains stored in the table (minimum is one for the
206 * root domain).
207 */
208static inline uint32_t
209domain_table_count(domain_table_type* table)
210{
211#ifdef USE_RADIX_TREE
212 return table->nametree->count;
213#else
214 return table->names_to_domains->count;
215#endif
216}
217
218/*
219 * Find the specified dname in the domain_table. NULL is returned if
220 * there is no exact match.
221 */
222domain_type* domain_table_find(domain_table_type* table,
223 const dname_type* dname);
224
225/*
226 * Insert a domain name in the domain table. If the domain name is
227 * not yet present in the table it is copied and a new dname_info node
228 * is created (as well as for the missing parent domain names, if
229 * any). Otherwise the domain_type that is already in the
230 * domain_table is returned.
231 */
232domain_type *domain_table_insert(domain_table_type *table,
233 const dname_type *dname);
234
235/* put domain into nsec3 hash space tree */
236void zone_add_domain_in_hash_tree(region_type* region, rbtree_type** tree,
237 int (*cmpf)(const void*, const void*), domain_type* domain,
238 rbnode_type* node);
239void zone_del_domain_in_hash_tree(rbtree_type* tree, rbnode_type* node);
240void hash_tree_delete(region_type* region, rbtree_type* tree);
241void prehash_clear(domain_table_type* table);
242void prehash_add(domain_table_type* table, domain_type* domain);
243void prehash_del(domain_table_type* table, domain_type* domain);
244int domain_is_prehash(domain_table_type* table, domain_type* domain);
245
246/*
247 * Add an RRset to the specified domain. Updates the is_existing flag
248 * as required.
249 */
250void domain_add_rrset(domain_type* domain, rrset_type* rrset);
251
252rrset_type* domain_find_rrset(domain_type* domain, zone_type* zone, uint16_t type);
253rrset_type* domain_find_any_rrset(domain_type* domain, zone_type* zone);
254
255zone_type* domain_find_zone(namedb_type* db, domain_type* domain);
256zone_type* domain_find_parent_zone(namedb_type* db, zone_type* zone);
257
258domain_type* domain_find_ns_rrsets(domain_type* domain, zone_type* zone, rrset_type **ns);
259/* find DNAME rrset in domain->parent or higher and return that domain */
260domain_type * find_dname_above(domain_type* domain, zone_type* zone);
261
262int domain_is_glue(domain_type* domain, zone_type* zone);
263
264rrset_type* domain_find_non_cname_rrset(domain_type* domain, zone_type* zone);
265
266domain_type* domain_wildcard_child(domain_type* domain);
267domain_type *domain_previous_existing_child(domain_type* domain);
268
269int zone_is_secure(zone_type* zone);
270
271static inline dname_type *
272domain_dname(domain_type* domain)
273{
274#ifdef USE_RADIX_TREE
275 return (dname_type *) domain->dname;
26
Access to field 'dname' results in a dereference of a null pointer (loaded from variable 'domain')
276#else
277 return (dname_type *) domain->node.key;
278#endif
279}
280
281static inline const dname_type *
282domain_dname_const(const domain_type* domain)
283{
284#ifdef USE_RADIX_TREE
285 return domain->dname;
286#else
287 return (const dname_type *) domain->node.key;
288#endif
289}
290
291static inline domain_type *
292domain_previous(domain_type* domain)
293{
294#ifdef USE_RADIX_TREE
295 struct radnode* prev = radix_prev(domain->rnode);
296 return prev == NULL((void *)0) ? NULL((void *)0) : (domain_type*)prev->elem;
297#else
298 rbnode_type *prev = rbtree_previous((rbnode_type *) domain);
299 return prev == RBTREE_NULL&rbtree_null_node ? NULL((void *)0) : (domain_type *) prev;
300#endif
301}
302
303static inline domain_type *
304domain_next(domain_type* domain)
305{
306#ifdef USE_RADIX_TREE
307 struct radnode* next = radix_next(domain->rnode);
308 return next == NULL((void *)0) ? NULL((void *)0) : (domain_type*)next->elem;
309#else
310 rbnode_type *next = rbtree_next((rbnode_type *) domain);
311 return next == RBTREE_NULL&rbtree_null_node ? NULL((void *)0) : (domain_type *) next;
312#endif
313}
314
315/* easy comparison for subdomain, true if d1 is subdomain of d2. */
316static inline int domain_is_subdomain(domain_type* d1, domain_type* d2)
317{ return dname_is_subdomain(domain_dname(d1), domain_dname(d2)); }
318/* easy printout, to static buffer of dname_to_string, fqdn. */
319static inline const char* domain_to_string(domain_type* domain)
320{ return dname_to_string(domain_dname(domain), NULL((void *)0)); }
321
322/*
323 * The type covered by the signature in the specified RRSIG RR.
324 */
325uint16_t rr_rrsig_type_covered(rr_type* rr);
326
327struct namedb
328{
329 region_type* region;
330 domain_table_type* domains;
331 struct radtree* zonetree;
332 /* the timestamp on the ixfr.db file */
333 struct timeval diff_timestamp;
334 /* if diff_skip=1, diff_pos contains the nsd.diff place to continue */
335 uint8_t diff_skip;
336 off_t diff_pos;
337};
338
339static inline int rdata_atom_is_domain(uint16_t type, size_t index);
340static inline int rdata_atom_is_literal_domain(uint16_t type, size_t index);
341
342static inline domain_type *
343rdata_atom_domain(rdata_atom_type atom)
344{
345 return atom.domain;
346}
347
348static inline uint16_t
349rdata_atom_size(rdata_atom_type atom)
350{
351 return *atom.data;
352}
353
354static inline uint8_t *
355rdata_atom_data(rdata_atom_type atom)
356{
357 return (uint8_t *) (atom.data + 1);
358}
359
360
361/* Find the zone for the specified dname in DB. */
362zone_type *namedb_find_zone(namedb_type *db, const dname_type *dname);
363/*
364 * Delete a domain name from the domain table. Removes dname_info node.
365 * Only deletes if usage is 0, has no rrsets and no children. Checks parents
366 * for deletion as well. Adjusts numberlist(domain.number), and
367 * wcard_child closest match.
368 */
369void domain_table_deldomain(namedb_type* db, domain_type* domain);
370
371/** dbcreate.c */
372int print_rrs(FILE* out, struct zone* zone);
373/** marshal rdata into buffer, must be MAX_RDLENGTH in size */
374size_t rr_marshal_rdata(rr_type* rr, uint8_t* rdata, size_t sz);
375/* dbaccess.c */
376int namedb_lookup (struct namedb* db,
377 const dname_type* dname,
378 domain_type **closest_match,
379 domain_type **closest_encloser);
380/* pass number of children (to alloc in dirty array */
381struct namedb *namedb_open(struct nsd_options* opt);
382void namedb_close(struct namedb* db);
383/* free ixfr data stored for zones */
384void namedb_free_ixfr(struct namedb* db);
385void namedb_check_zonefiles(struct nsd* nsd, struct nsd_options* opt,
386 struct udb_base* taskudb, struct udb_ptr* last_task);
387void namedb_check_zonefile(struct nsd* nsd, struct udb_base* taskudb,
388 struct udb_ptr* last_task, struct zone_options* zo);
389/** zone one zonefile into memory and revert on parse error, write to udb */
390void namedb_read_zonefile(struct nsd* nsd, struct zone* zone,
391 struct udb_base* taskudb, struct udb_ptr* last_task);
392zone_type* namedb_zone_create(namedb_type* db, const dname_type* dname,
393 struct zone_options* zopt);
394void namedb_zone_delete(namedb_type* db, zone_type* zone);
395void namedb_write_zonefile(struct nsd* nsd, struct zone_options* zopt);
396void namedb_write_zonefiles(struct nsd* nsd, struct nsd_options* options);
397int create_dirs(const char* path);
398int file_get_mtime(const char* file, struct timespec* mtime, int* nonexist);
399void allocate_domain_nsec3(domain_table_type *table, domain_type *result);
400
401static inline int
402rdata_atom_is_domain(uint16_t type, size_t index)
403{
404 const rrtype_descriptor_type *descriptor
405 = rrtype_descriptor_by_type(type);
406 return (index < descriptor->maximum
407 && (descriptor->wireformat[index] == RDATA_WF_COMPRESSED_DNAME
408 || descriptor->wireformat[index] == RDATA_WF_UNCOMPRESSED_DNAME));
409}
410
411static inline int
412rdata_atom_is_literal_domain(uint16_t type, size_t index)
413{
414 const rrtype_descriptor_type *descriptor
415 = rrtype_descriptor_by_type(type);
416 return (index < descriptor->maximum
417 && (descriptor->wireformat[index] == RDATA_WF_LITERAL_DNAME));
418}
419
420static inline rdata_wireformat_type
421rdata_atom_wireformat_type(uint16_t type, size_t index)
422{
423 const rrtype_descriptor_type *descriptor
424 = rrtype_descriptor_by_type(type);
425 assert(index < descriptor->maximum)((void)0);
426 return (rdata_wireformat_type) descriptor->wireformat[index];
427}
428
429static inline uint16_t
430rrset_rrtype(rrset_type* rrset)
431{
432 assert(rrset)((void)0);
433 assert(rrset->rr_count > 0)((void)0);
434 return rrset->rrs[0].type;
435}
436
437static inline uint16_t
438rrset_rrclass(rrset_type* rrset)
439{
440 assert(rrset)((void)0);
441 assert(rrset->rr_count > 0)((void)0);
442 return rrset->rrs[0].klass;
443}
444
445/*
446 * zone_rr_iter can be used to iterate over all RRs in a given zone. the
447 * SOA RRSET is guaranteed to be returned first.
448 */
449typedef struct zone_rr_iter zone_rr_iter_type;
450
451struct zone_rr_iter {
452 zone_type *zone;
453 domain_type *domain;
454 rrset_type *rrset;
455 ssize_t index;
456};
457
458void zone_rr_iter_init(zone_rr_iter_type *iter, zone_type *zone);
459
460rr_type *zone_rr_iter_next(zone_rr_iter_type *iter);
461
462#endif /* NAMEDB_H */