Bug Summary

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

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