mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
The setfilename() function uses case-insensitive strcasestr() when matching the possible tokens, but then one of the token parsers uses case-sensitive INSIST checks which can assert when, for example, matching '%X' and INSIST only accepts '%x'. The case-insensitivity is documented, which means it's the parser that needs to be fixed, not the matcher. Convert the character to lowercase before checking the token's validity.
2130 lines
46 KiB
C
2130 lines
46 KiB
C
/*
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
*
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
* information regarding copyright ownership.
|
|
*/
|
|
|
|
/*! \file */
|
|
|
|
#include <isc/async.h> /* WMM: remove include */
|
|
#include <isc/random.h> /* WMM: remove include */
|
|
|
|
#include <dns/kasp.h>
|
|
#include <dns/peer.h>
|
|
#include <dns/request.h>
|
|
#include <dns/ssu.h>
|
|
#include <dns/stats.h>
|
|
#include <dns/view.h>
|
|
#include <dns/zone.h>
|
|
#include <dns/zoneproperties.h>
|
|
|
|
#include "zone_p.h"
|
|
|
|
static void
|
|
default_journal(dns_zone_t *zone);
|
|
static void
|
|
zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
|
|
static void
|
|
zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
|
|
static void
|
|
zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
|
|
|
|
static void
|
|
free_rad_rcu(struct rcu_head *rcu_head) {
|
|
dns_rad_t *rad = caa_container_of(rcu_head, dns_rad_t, rcu_head);
|
|
dns_fixedname_invalidate(&rad->fname);
|
|
|
|
isc_mem_putanddetach(&rad->mctx, rad, sizeof(*rad));
|
|
}
|
|
|
|
/*
|
|
* Single shot.
|
|
*/
|
|
void
|
|
dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
|
|
char namebuf[1024];
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(rdclass != dns_rdataclass_none);
|
|
|
|
/*
|
|
* Test and set.
|
|
*/
|
|
LOCK_ZONE(zone);
|
|
INSIST(zone != zone->raw);
|
|
REQUIRE(zone->rdclass == dns_rdataclass_none ||
|
|
zone->rdclass == rdclass);
|
|
zone->rdclass = rdclass;
|
|
|
|
if (zone->strnamerd != NULL) {
|
|
isc_mem_free(zone->mctx, zone->strnamerd);
|
|
}
|
|
if (zone->strrdclass != NULL) {
|
|
isc_mem_free(zone->mctx, zone->strrdclass);
|
|
}
|
|
|
|
zone_namerd_tostr(zone, namebuf, sizeof namebuf);
|
|
zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
|
|
zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
|
|
zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
|
|
|
|
if (dns__zone_inline_secure(zone)) {
|
|
dns_zone_setclass(zone->raw, rdclass);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
dns_rdataclass_t
|
|
dns_zone_getclass(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->rdclass;
|
|
}
|
|
|
|
void
|
|
dns_zone_setnotifytype(dns_zone_t *zone, dns_rdatatype_t type,
|
|
dns_notifytype_t notifytype) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
switch (type) {
|
|
case dns_rdatatype_soa:
|
|
zone->notifysoa.notifytype = notifytype;
|
|
break;
|
|
case dns_rdatatype_cds:
|
|
INSIST(notifytype == dns_notifytype_no ||
|
|
notifytype == dns_notifytype_yes);
|
|
zone->notifycds.notifytype = notifytype;
|
|
break;
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setcheckdstype(dns_zone_t *zone, dns_checkdstype_t checkdstype) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
zone->checkdstype = checkdstype;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
/*
|
|
* Single shot.
|
|
*/
|
|
void
|
|
dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
|
|
char namebuf[1024];
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(type != dns_zone_none);
|
|
|
|
/*
|
|
* Test and set.
|
|
*/
|
|
LOCK_ZONE(zone);
|
|
REQUIRE(zone->type == dns_zone_none || zone->type == type);
|
|
zone->type = type;
|
|
|
|
if (zone->strnamerd != NULL) {
|
|
isc_mem_free(zone->mctx, zone->strnamerd);
|
|
}
|
|
|
|
zone_namerd_tostr(zone, namebuf, sizeof namebuf);
|
|
zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
|
|
size_t size = 0;
|
|
unsigned int i;
|
|
void *mem;
|
|
char **tmp, *tmp2, *base;
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(argv != NULL && *argv == NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
size = ISC_CHECKED_MUL(zone->db_argc + 1, sizeof(char *));
|
|
for (i = 0; i < zone->db_argc; i++) {
|
|
size += strlen(zone->db_argv[i]) + 1;
|
|
}
|
|
mem = isc_mem_allocate(mctx, size);
|
|
{
|
|
tmp = mem;
|
|
tmp2 = mem;
|
|
base = mem;
|
|
tmp2 += ISC_CHECKED_MUL(zone->db_argc + 1, sizeof(char *));
|
|
for (i = 0; i < zone->db_argc; i++) {
|
|
*tmp++ = tmp2;
|
|
strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
|
|
tmp2 += strlen(tmp2) + 1;
|
|
}
|
|
*tmp = NULL;
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
*argv = mem;
|
|
}
|
|
|
|
void
|
|
dns_zone_setdbtype(dns_zone_t *zone, unsigned int dbargc,
|
|
const char *const *dbargv) {
|
|
char **argv = NULL;
|
|
unsigned int i;
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(dbargc >= 1);
|
|
REQUIRE(dbargv != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
|
|
/* Set up a new database argument list. */
|
|
argv = isc_mem_cget(zone->mctx, dbargc, sizeof(*argv));
|
|
for (i = 0; i < dbargc; i++) {
|
|
argv[i] = NULL;
|
|
}
|
|
for (i = 0; i < dbargc; i++) {
|
|
argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
|
|
}
|
|
|
|
/* Free the old list. */
|
|
dns__zone_freedbargs(zone);
|
|
|
|
zone->db_argc = dbargc;
|
|
zone->db_argv = argv;
|
|
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
dns__zone_setview_helper(zone, view);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
dns_view_t *
|
|
dns_zone_getview(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->view;
|
|
}
|
|
|
|
void
|
|
dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
|
|
char namebuf[1024];
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(origin != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
INSIST(zone != zone->raw);
|
|
if (dns_name_dynamic(&zone->origin)) {
|
|
dns_name_free(&zone->origin, zone->mctx);
|
|
dns_name_init(&zone->origin);
|
|
}
|
|
dns_name_dup(origin, zone->mctx, &zone->origin);
|
|
|
|
if (zone->strnamerd != NULL) {
|
|
isc_mem_free(zone->mctx, zone->strnamerd);
|
|
}
|
|
if (zone->strname != NULL) {
|
|
isc_mem_free(zone->mctx, zone->strname);
|
|
}
|
|
|
|
zone_namerd_tostr(zone, namebuf, sizeof namebuf);
|
|
zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
|
|
zone_name_tostr(zone, namebuf, sizeof namebuf);
|
|
zone->strname = isc_mem_strdup(zone->mctx, namebuf);
|
|
|
|
if (dns__zone_inline_secure(zone)) {
|
|
dns_zone_setorigin(zone->raw, origin);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
static void
|
|
setstring(dns_zone_t *zone, char **field, const char *value) {
|
|
char *copy;
|
|
|
|
if (value != NULL) {
|
|
copy = isc_mem_strdup(zone->mctx, value);
|
|
} else {
|
|
copy = NULL;
|
|
}
|
|
|
|
if (*field != NULL) {
|
|
isc_mem_free(zone->mctx, *field);
|
|
}
|
|
|
|
*field = copy;
|
|
}
|
|
|
|
typedef struct foundtoken foundtoken_t;
|
|
typedef struct token_names token_names_t;
|
|
typedef isc_result_t (*tokenparse_t)(const token_names_t *names,
|
|
const foundtoken_t *token,
|
|
isc_buffer_t *b);
|
|
|
|
struct foundtoken {
|
|
const char *pos;
|
|
size_t len;
|
|
tokenparse_t parse;
|
|
};
|
|
|
|
struct token_names {
|
|
dns_name_t *zonename;
|
|
const char *viewname;
|
|
const char *typename;
|
|
};
|
|
|
|
static int
|
|
foundtoken_order(const void *a, const void *b) {
|
|
/* sort char pointers in order of which occurs first in memory */
|
|
return ((foundtoken_t *)a)->pos - ((foundtoken_t *)b)->pos;
|
|
}
|
|
|
|
static isc_result_t
|
|
putmem(isc_buffer_t *b, const char *base, size_t length) {
|
|
size_t space = isc_buffer_availablelength(b) - 1;
|
|
if (space < length) {
|
|
isc_buffer_putmem(b, (const unsigned char *)base, space);
|
|
return ISC_R_NOSPACE;
|
|
}
|
|
|
|
isc_buffer_putmem(b, (const unsigned char *)base, length);
|
|
return ISC_R_SUCCESS;
|
|
}
|
|
|
|
static isc_result_t
|
|
tokenparse_type(const token_names_t *names, const foundtoken_t *token,
|
|
isc_buffer_t *b) {
|
|
UNUSED(token);
|
|
|
|
return putmem(b, names->typename, strlen(names->typename));
|
|
}
|
|
|
|
static isc_result_t
|
|
tokenparse_name(const token_names_t *names,
|
|
const foundtoken_t *token ISC_ATTR_UNUSED, isc_buffer_t *b) {
|
|
char name[DNS_NAME_FORMATSIZE];
|
|
|
|
dns_name_format(names->zonename, name, sizeof(name));
|
|
return putmem(b, name, strlen(name));
|
|
}
|
|
|
|
static isc_result_t
|
|
tokenparse_view(const token_names_t *names, const foundtoken_t *token,
|
|
isc_buffer_t *b) {
|
|
UNUSED(token);
|
|
|
|
return putmem(b, names->viewname, strlen(names->viewname));
|
|
}
|
|
|
|
static isc_result_t
|
|
tokenparse_char(const token_names_t *names, const foundtoken_t *token,
|
|
isc_buffer_t *b) {
|
|
char name[DNS_NAME_FORMATSIZE];
|
|
size_t chartokidx;
|
|
char c;
|
|
|
|
dns_name_format(names->zonename, name, sizeof(name));
|
|
|
|
chartokidx = token->pos[token->len - 1] - '1';
|
|
INSIST(chartokidx <= 2);
|
|
if (chartokidx < strlen(name)) {
|
|
c = name[chartokidx];
|
|
} else {
|
|
c = '.';
|
|
}
|
|
return putmem(b, &c, 1);
|
|
}
|
|
|
|
static isc_result_t
|
|
tokenparse_label(const token_names_t *names, const foundtoken_t *token,
|
|
isc_buffer_t *b) {
|
|
isc_result_t result;
|
|
char buf[DNS_NAME_FORMATSIZE];
|
|
dns_fixedname_t ft;
|
|
dns_name_t *target = dns_fixedname_initname(&ft);
|
|
unsigned int labels;
|
|
char labeltokidx;
|
|
int ilabel = -1;
|
|
|
|
dns_name_copy(dns_rootname, target);
|
|
labels = dns_name_countlabels(names->zonename);
|
|
|
|
labeltokidx = isc_ascii_tolower(token->pos[token->len - 1]);
|
|
if (token->len == 2) {
|
|
/*
|
|
* %z, %y, %x pattern
|
|
*/
|
|
INSIST(labeltokidx >= 'x' && labeltokidx <= 'z');
|
|
} else {
|
|
/*
|
|
* $label1, $label2, $label3 pattern
|
|
*/
|
|
INSIST(labeltokidx >= '1' && labeltokidx <= '3');
|
|
}
|
|
|
|
if (labeltokidx == '1' || labeltokidx == 'z') {
|
|
ilabel = labels - 1;
|
|
} else if (labeltokidx == '2' || labeltokidx == 'y') {
|
|
ilabel = labels - 2;
|
|
} else if (labeltokidx == '3' || labeltokidx == 'x') {
|
|
ilabel = labels - 3;
|
|
}
|
|
|
|
if (ilabel >= 0) {
|
|
dns_name_getlabelsequence(names->zonename, ilabel, 1, target);
|
|
}
|
|
dns_name_format(target, buf, sizeof(buf));
|
|
result = putmem(b, buf, strlen(buf));
|
|
|
|
return result;
|
|
}
|
|
|
|
typedef struct {
|
|
const char *name;
|
|
tokenparse_t parse;
|
|
} token_t;
|
|
static const token_t tokens[] = {
|
|
{ "$type", tokenparse_type }, { "$name", tokenparse_name },
|
|
{ "$view", tokenparse_view }, { "$char1", tokenparse_char },
|
|
{ "$char2", tokenparse_char }, { "$char3", tokenparse_char },
|
|
{ "$label1", tokenparse_label }, { "$label2", tokenparse_label },
|
|
{ "$label3", tokenparse_label }, { "%t", tokenparse_type },
|
|
{ "%s", tokenparse_name }, { "%v", tokenparse_view },
|
|
{ "%1", tokenparse_char }, { "%2", tokenparse_char },
|
|
{ "%3", tokenparse_char }, { "%z", tokenparse_label },
|
|
{ "%y", tokenparse_label }, { "%x", tokenparse_label }
|
|
};
|
|
|
|
/*
|
|
* Set the masterfile field, expanding:
|
|
*
|
|
* - $name or "%s" to the zone name
|
|
* - $type or "%t" to the zone type
|
|
* - $view or "%v" to the view name.
|
|
* - $char1 or "%1" to the first character of the zone name
|
|
* - $char2 or "%2" to the second character of the zone name (or a dot if
|
|
* there is no second character)
|
|
* - $char3 or "%3" to the third character of the zone name (or a dot if
|
|
* there is no third character)
|
|
* - $label1 or "%z" to the toplevel domain of the zone (or a dot if it is
|
|
* the TLD)
|
|
* - $label2 or "%y" to the next label under the toplevel domain (or a dot if
|
|
* there is no next label)
|
|
* - $label2 or "%x" to the next-next label under the toplevel domain (or a
|
|
* dot if there is no next-next label)
|
|
*
|
|
* Cap the length at PATH_MAX.
|
|
*/
|
|
void
|
|
dns_zone_expandzonefile(isc_buffer_t *b, const char *filename,
|
|
const dns_name_t *zonename, const char *viewname,
|
|
const char *typename) {
|
|
isc_result_t result;
|
|
foundtoken_t founds[ARRAY_SIZE(tokens)];
|
|
dns_fixedname_t fz;
|
|
size_t tags = 0;
|
|
token_names_t names = { .zonename = dns_fixedname_initname(&fz),
|
|
.viewname = viewname,
|
|
.typename = typename };
|
|
|
|
REQUIRE(zonename != NULL);
|
|
REQUIRE(filename != NULL);
|
|
REQUIRE(typename != NULL);
|
|
|
|
if (viewname == NULL) {
|
|
names.viewname = "";
|
|
}
|
|
|
|
/* Normalize the name by converting to lower case */
|
|
result = dns_name_downcase(zonename, names.zonename);
|
|
INSIST(result == ISC_R_SUCCESS);
|
|
|
|
for (size_t i = 0; i < ARRAY_SIZE(tokens); i++) {
|
|
const token_t *token = &tokens[i];
|
|
const char *p = strcasestr(filename, token->name);
|
|
|
|
if (p != NULL) {
|
|
founds[tags++] =
|
|
(foundtoken_t){ .pos = p,
|
|
.len = strlen(token->name),
|
|
.parse = token->parse };
|
|
}
|
|
}
|
|
|
|
if (tags == 0) {
|
|
putmem(b, filename, strlen(filename));
|
|
goto cleanup;
|
|
}
|
|
|
|
/* sort the tag offsets in order of occurrence */
|
|
qsort(founds, tags, sizeof(foundtoken_t), foundtoken_order);
|
|
|
|
const char *p = filename;
|
|
for (size_t i = 0; i < tags; i++) {
|
|
foundtoken_t *token = &founds[i];
|
|
|
|
CHECK(putmem(b, p, token->pos - p));
|
|
|
|
p = token->pos;
|
|
INSIST(p != NULL);
|
|
CHECK(token->parse(&names, token, b));
|
|
|
|
/* Advance the input pointer past the token */
|
|
p += founds[i].len;
|
|
}
|
|
|
|
const char *end = filename + strlen(filename);
|
|
putmem(b, p, end - p);
|
|
|
|
cleanup:
|
|
isc_buffer_putuint8(b, 0);
|
|
}
|
|
|
|
static void
|
|
setfilename(dns_zone_t *zone, char **field, const char *value) {
|
|
char filename[PATH_MAX];
|
|
isc_buffer_t b;
|
|
|
|
if (value == NULL) {
|
|
*field = NULL;
|
|
return;
|
|
}
|
|
|
|
isc_buffer_init(&b, filename, sizeof(filename));
|
|
dns_zone_expandzonefile(&b, value, &zone->origin,
|
|
zone->view != NULL ? zone->view->name : NULL,
|
|
dns_zonetype_name(zone->type));
|
|
setstring(zone, field, filename);
|
|
}
|
|
|
|
void
|
|
dns_zone_setfile(dns_zone_t *zone, const char *file, const char *initial_file,
|
|
dns_masterformat_t format, const dns_master_style_t *style) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(zone->stream == NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
setfilename(zone, &zone->masterfile, file);
|
|
setstring(zone, &zone->initfile, initial_file);
|
|
zone->masterformat = format;
|
|
if (format == dns_masterformat_text) {
|
|
zone->masterstyle = style;
|
|
}
|
|
default_journal(zone);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
const char *
|
|
dns_zone_getfile(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->masterfile;
|
|
}
|
|
|
|
void
|
|
dns_zone_setstream(dns_zone_t *zone, const FILE *stream,
|
|
dns_masterformat_t format, const dns_master_style_t *style) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(stream != NULL);
|
|
REQUIRE(zone->masterfile == NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
zone->stream = stream;
|
|
zone->masterformat = format;
|
|
if (format == dns_masterformat_text) {
|
|
zone->masterstyle = style;
|
|
}
|
|
default_journal(zone);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
dns_ttl_t
|
|
dns_zone_getmaxttl(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->maxttl;
|
|
}
|
|
|
|
void
|
|
dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (maxttl != 0) {
|
|
DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_CHECKTTL);
|
|
} else {
|
|
DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_CHECKTTL);
|
|
}
|
|
zone->maxttl = maxttl;
|
|
UNLOCK_ZONE(zone);
|
|
|
|
return;
|
|
}
|
|
|
|
static void
|
|
default_journal(dns_zone_t *zone) {
|
|
char *journal;
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(LOCKED_ZONE(zone));
|
|
|
|
if (zone->masterfile != NULL) {
|
|
/* Calculate string length including '\0'. */
|
|
int len = strlen(zone->masterfile) + sizeof(".jnl");
|
|
journal = isc_mem_allocate(zone->mctx, len);
|
|
strlcpy(journal, zone->masterfile, len);
|
|
strlcat(journal, ".jnl", len);
|
|
} else {
|
|
journal = NULL;
|
|
}
|
|
setstring(zone, &zone->journal, journal);
|
|
if (journal != NULL) {
|
|
isc_mem_free(zone->mctx, journal);
|
|
}
|
|
}
|
|
|
|
void
|
|
dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
setstring(zone, &zone->journal, myjournal);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
char *
|
|
dns_zone_getjournal(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->journal;
|
|
}
|
|
|
|
isc_mem_t *
|
|
dns_zone_getmctx(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->mctx;
|
|
}
|
|
|
|
dns_zonemgr_t *
|
|
dns_zone_getmgr(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->zmgr;
|
|
}
|
|
|
|
void
|
|
dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (zone->kasp != NULL) {
|
|
dns_kasp_detach(&zone->kasp);
|
|
}
|
|
if (kasp != NULL) {
|
|
dns_kasp_attach(kasp, &zone->kasp);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setdefaultkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (zone->defaultkasp != NULL) {
|
|
dns_kasp_detach(&zone->defaultkasp);
|
|
}
|
|
if (kasp != NULL) {
|
|
dns_kasp_attach(kasp, &zone->defaultkasp);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
dns_kasp_t *
|
|
dns_zone_getkasp(dns_zone_t *zone) {
|
|
dns_kasp_t *kasp = NULL;
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (dns__zone_inline_raw(zone) && zone->secure != NULL) {
|
|
kasp = zone->secure->kasp;
|
|
} else {
|
|
kasp = zone->kasp;
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
|
|
return kasp;
|
|
}
|
|
|
|
void
|
|
dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(xfrsource != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
zone->xfrsource4 = *xfrsource;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_getxfrsource4(dns_zone_t *zone, isc_sockaddr_t *xfrsource) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(xfrsource != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
*xfrsource = zone->xfrsource4;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(xfrsource != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
zone->xfrsource6 = *xfrsource;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_getxfrsource6(dns_zone_t *zone, isc_sockaddr_t *xfrsource) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(xfrsource != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
*xfrsource = zone->xfrsource6;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(parentalsrc != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
zone->parentalsrc4 = *parentalsrc;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_getparentalsrc4(dns_zone_t *zone, isc_sockaddr_t *parentalsrc) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(parentalsrc != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
*parentalsrc = zone->parentalsrc4;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
zone->parentalsrc6 = *parentalsrc;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_getparentalsrc6(dns_zone_t *zone, isc_sockaddr_t *parentalsrc) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(parentalsrc != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
*parentalsrc = zone->parentalsrc6;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setnotifysrc4(dns_zone_t *zone, dns_rdatatype_t type,
|
|
const isc_sockaddr_t *notifysrc) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(notifysrc != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
switch (type) {
|
|
case dns_rdatatype_soa:
|
|
zone->notifysoa.notifysrc4 = *notifysrc;
|
|
break;
|
|
case dns_rdatatype_cds:
|
|
zone->notifycds.notifysrc4 = *notifysrc;
|
|
break;
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setnotifysrc6(dns_zone_t *zone, dns_rdatatype_t type,
|
|
const isc_sockaddr_t *notifysrc) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(notifysrc != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
switch (type) {
|
|
case dns_rdatatype_soa:
|
|
zone->notifysoa.notifysrc6 = *notifysrc;
|
|
break;
|
|
case dns_rdatatype_cds:
|
|
zone->notifycds.notifysrc6 = *notifysrc;
|
|
break;
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
static bool
|
|
has_pf(isc_sockaddr_t *addresses, size_t count, int pf) {
|
|
for (size_t i = 0; i < count; i++) {
|
|
if (isc_sockaddr_pf(&addresses[i]) == pf) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static void
|
|
report_no_active_addresses(dns_zone_t *zone, isc_sockaddr_t *addresses,
|
|
size_t count, const char *what) {
|
|
if (isc_net_probeipv4() == ISC_R_DISABLED) {
|
|
if (!has_pf(addresses, count, AF_INET6)) {
|
|
dns_zone_log(zone, ISC_LOG_NOTICE,
|
|
"IPv4 disabled and no IPv6 %s", what);
|
|
}
|
|
} else if (isc_net_probeipv6() == ISC_R_DISABLED) {
|
|
if (!has_pf(addresses, count, AF_INET)) {
|
|
dns_zone_log(zone, ISC_LOG_NOTICE,
|
|
"IPv6 disabled and no IPv4 %s", what);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
setremote(dns_zone_t *zone, dns_remote_t *remote, const char *remotestr,
|
|
isc_sockaddr_t *addresses, isc_sockaddr_t *sources,
|
|
dns_name_t **keynames, dns_name_t **tlsnames, bool refresh,
|
|
bool report, uint32_t count) {
|
|
dns_remote_t newremote;
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(DNS_REMOTE_VALID(remote));
|
|
|
|
newremote.magic = DNS_REMOTE_MAGIC;
|
|
newremote.addresses = addresses;
|
|
newremote.sources = sources;
|
|
newremote.keynames = keynames;
|
|
newremote.tlsnames = tlsnames;
|
|
newremote.addrcnt = count;
|
|
|
|
if (dns_remote_equal(remote, &newremote)) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* The refresh code assumes that 'servers' wouldn't change under it.
|
|
* If it will change then kill off any current refresh in progress
|
|
* and update the primaries info. If it won't change then we can just
|
|
* unlock and exit.
|
|
*/
|
|
if (zone->request != NULL && refresh) {
|
|
dns_request_cancel(zone->request);
|
|
}
|
|
|
|
dns_remote_clear(remote);
|
|
|
|
/*
|
|
* If count == 0, don't allocate any space for servers.
|
|
*/
|
|
if (count == 0) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Now set up the address and key lists.
|
|
*/
|
|
if (report) {
|
|
report_no_active_addresses(zone, addresses, count, remotestr);
|
|
}
|
|
|
|
dns_remote_init(remote, count, addresses, sources, keynames, tlsnames,
|
|
true, zone->mctx);
|
|
}
|
|
|
|
void
|
|
dns_zone_setalsonotify(dns_zone_t *zone, isc_sockaddr_t *addresses,
|
|
isc_sockaddr_t *sources, dns_name_t **keynames,
|
|
dns_name_t **tlsnames, uint32_t count) {
|
|
bool refresh = false;
|
|
bool report = false;
|
|
|
|
LOCK_ZONE(zone);
|
|
setremote(zone, &zone->alsonotify, "also-notify", addresses, sources,
|
|
keynames, tlsnames, refresh, report, count);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setprimaries(dns_zone_t *zone, isc_sockaddr_t *addresses,
|
|
isc_sockaddr_t *sources, dns_name_t **keynames,
|
|
dns_name_t **tlsnames, uint32_t count) {
|
|
bool refresh = true;
|
|
bool report = true;
|
|
|
|
LOCK_ZONE(zone);
|
|
setremote(zone, &zone->primaries, "primaries", addresses, sources,
|
|
keynames, tlsnames, refresh, report, count);
|
|
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOPRIMARIES);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setparentals(dns_zone_t *zone, isc_sockaddr_t *addresses,
|
|
isc_sockaddr_t *sources, dns_name_t **keynames,
|
|
dns_name_t **tlsnames, uint32_t count) {
|
|
bool refresh = false;
|
|
bool report = true;
|
|
|
|
LOCK_ZONE(zone);
|
|
setremote(zone, &zone->parentals, "parental-agents", addresses, sources,
|
|
keynames, tlsnames, refresh, report, count);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setcdsendpoints(dns_zone_t *zone, isc_sockaddr_t *addresses,
|
|
isc_sockaddr_t *sources, dns_name_t **keynames,
|
|
dns_name_t **tlsnames, uint32_t count) {
|
|
bool refresh = false;
|
|
bool report = false;
|
|
|
|
LOCK_ZONE(zone);
|
|
setremote(zone, &zone->cds_endpoints, "cds-endpoints", addresses,
|
|
sources, keynames, tlsnames, refresh, report, count);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
isc_result_t
|
|
dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
|
|
if (zone->db == NULL) {
|
|
result = DNS_R_NOTLOADED;
|
|
} else {
|
|
dns_db_attach(zone->db, dpb);
|
|
}
|
|
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(zone->type == dns_zone_staticstub);
|
|
|
|
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
|
|
REQUIRE(zone->db == NULL);
|
|
dns_db_attach(db, &zone->db);
|
|
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
|
|
}
|
|
|
|
void
|
|
dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(val > 0);
|
|
|
|
zone->minrefresh = val;
|
|
}
|
|
|
|
void
|
|
dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(val > 0);
|
|
|
|
zone->maxrefresh = val;
|
|
}
|
|
|
|
void
|
|
dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(val > 0);
|
|
|
|
zone->minretry = val;
|
|
}
|
|
|
|
void
|
|
dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(val > 0);
|
|
|
|
zone->maxretry = val;
|
|
}
|
|
|
|
uint32_t
|
|
dns_zone_getmaxrecords(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->maxrecords;
|
|
}
|
|
|
|
void
|
|
dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
zone->maxrecords = val;
|
|
}
|
|
|
|
void
|
|
dns_zone_setmaxrrperset(dns_zone_t *zone, uint32_t val) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
zone->maxrrperset = val;
|
|
if (zone->db != NULL) {
|
|
dns_db_setmaxrrperset(zone->db, val);
|
|
}
|
|
}
|
|
|
|
void
|
|
dns_zone_setmaxtypepername(dns_zone_t *zone, uint32_t val) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
zone->maxtypepername = val;
|
|
if (zone->db != NULL) {
|
|
dns_db_setmaxtypepername(zone->db, val);
|
|
}
|
|
}
|
|
|
|
void
|
|
dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
dns_zone_clearnotifyacl(zone);
|
|
|
|
LOCK_ZONE(zone);
|
|
dns_acl_attach(acl, &zone->notifysoa.notify_acl);
|
|
dns_acl_attach(acl, &zone->notifycds.notify_acl);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
dns_zone_clearqueryacl(zone);
|
|
|
|
LOCK_ZONE(zone);
|
|
dns_acl_attach(acl, &zone->query_acl);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
dns_zone_clearqueryonacl(zone);
|
|
|
|
LOCK_ZONE(zone);
|
|
dns_acl_attach(acl, &zone->queryon_acl);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
dns_zone_clearupdateacl(zone);
|
|
|
|
LOCK_ZONE(zone);
|
|
dns_acl_attach(acl, &zone->update_acl);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
dns_zone_clearforwardacl(zone);
|
|
|
|
LOCK_ZONE(zone);
|
|
dns_acl_attach(acl, &zone->forward_acl);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
dns_zone_clearxfracl(zone);
|
|
|
|
LOCK_ZONE(zone);
|
|
dns_acl_attach(acl, &zone->xfr_acl);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
dns_acl_t *
|
|
dns_zone_getqueryacl(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->query_acl;
|
|
}
|
|
|
|
dns_acl_t *
|
|
dns_zone_getqueryonacl(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->queryon_acl;
|
|
}
|
|
|
|
dns_acl_t *
|
|
dns_zone_getupdateacl(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->update_acl;
|
|
}
|
|
|
|
dns_acl_t *
|
|
dns_zone_getforwardacl(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->forward_acl;
|
|
}
|
|
|
|
dns_acl_t *
|
|
dns_zone_getxfracl(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->xfr_acl;
|
|
}
|
|
|
|
void
|
|
dns_zone_clearupdateacl(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (zone->update_acl != NULL) {
|
|
dns_acl_detach(&zone->update_acl);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_clearforwardacl(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (zone->forward_acl != NULL) {
|
|
dns_acl_detach(&zone->forward_acl);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_clearnotifyacl(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (zone->notifysoa.notify_acl != NULL) {
|
|
dns_acl_detach(&zone->notifysoa.notify_acl);
|
|
}
|
|
if (zone->notifycds.notify_acl != NULL) {
|
|
dns_acl_detach(&zone->notifycds.notify_acl);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_clearqueryacl(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (zone->query_acl != NULL) {
|
|
dns_acl_detach(&zone->query_acl);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_clearqueryonacl(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (zone->queryon_acl != NULL) {
|
|
dns_acl_detach(&zone->queryon_acl);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_clearxfracl(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (zone->xfr_acl != NULL) {
|
|
dns_acl_detach(&zone->xfr_acl);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
bool
|
|
dns_zone_getupdatedisabled(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
return zone->update_disabled;
|
|
}
|
|
|
|
void
|
|
dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
zone->update_disabled = state;
|
|
}
|
|
|
|
bool
|
|
dns_zone_getzeronosoattl(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
return zone->zero_no_soa_ttl;
|
|
}
|
|
|
|
void
|
|
dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
zone->zero_no_soa_ttl = state;
|
|
}
|
|
|
|
void
|
|
dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
zone->check_names = severity;
|
|
}
|
|
|
|
dns_severity_t
|
|
dns_zone_getchecknames(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->check_names;
|
|
}
|
|
|
|
void
|
|
dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
zone->journalsize = size;
|
|
}
|
|
|
|
int32_t
|
|
dns_zone_getjournalsize(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->journalsize;
|
|
}
|
|
|
|
static void
|
|
zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
|
|
isc_result_t result = ISC_R_FAILURE;
|
|
isc_buffer_t buffer;
|
|
|
|
REQUIRE(buf != NULL);
|
|
REQUIRE(length > 1U);
|
|
|
|
/*
|
|
* Leave space for terminating '\0'.
|
|
*/
|
|
isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
|
|
if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
|
|
if (dns_name_dynamic(&zone->origin)) {
|
|
result = dns_name_totext(
|
|
&zone->origin, DNS_NAME_OMITFINALDOT, &buffer);
|
|
}
|
|
if (result != ISC_R_SUCCESS &&
|
|
isc_buffer_availablelength(&buffer) >=
|
|
(sizeof("<UNKNOWN>") - 1))
|
|
{
|
|
isc_buffer_putstr(&buffer, "<UNKNOWN>");
|
|
}
|
|
|
|
if (isc_buffer_availablelength(&buffer) > 0) {
|
|
isc_buffer_putstr(&buffer, "/");
|
|
}
|
|
(void)dns_rdataclass_totext(zone->rdclass, &buffer);
|
|
}
|
|
|
|
if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
|
|
strcmp(zone->view->name, "_default") != 0 &&
|
|
strlen(zone->view->name) < isc_buffer_availablelength(&buffer))
|
|
{
|
|
isc_buffer_putstr(&buffer, "/");
|
|
isc_buffer_putstr(&buffer, zone->view->name);
|
|
}
|
|
if (dns__zone_inline_secure(zone) &&
|
|
9U < isc_buffer_availablelength(&buffer))
|
|
{
|
|
isc_buffer_putstr(&buffer, " (signed)");
|
|
}
|
|
if (dns__zone_inline_raw(zone) &&
|
|
11U < isc_buffer_availablelength(&buffer))
|
|
{
|
|
isc_buffer_putstr(&buffer, " (unsigned)");
|
|
}
|
|
|
|
buf[isc_buffer_usedlength(&buffer)] = '\0';
|
|
}
|
|
|
|
static void
|
|
zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
|
|
isc_result_t result = ISC_R_FAILURE;
|
|
isc_buffer_t buffer;
|
|
|
|
REQUIRE(buf != NULL);
|
|
REQUIRE(length > 1U);
|
|
|
|
/*
|
|
* Leave space for terminating '\0'.
|
|
*/
|
|
isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
|
|
if (dns_name_dynamic(&zone->origin)) {
|
|
result = dns_name_totext(&zone->origin, DNS_NAME_OMITFINALDOT,
|
|
&buffer);
|
|
}
|
|
if (result != ISC_R_SUCCESS &&
|
|
isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
|
|
{
|
|
isc_buffer_putstr(&buffer, "<UNKNOWN>");
|
|
}
|
|
|
|
buf[isc_buffer_usedlength(&buffer)] = '\0';
|
|
}
|
|
|
|
static void
|
|
zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
|
|
isc_buffer_t buffer;
|
|
|
|
REQUIRE(buf != NULL);
|
|
REQUIRE(length > 1U);
|
|
|
|
/*
|
|
* Leave space for terminating '\0'.
|
|
*/
|
|
isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
|
|
(void)dns_rdataclass_totext(zone->rdclass, &buffer);
|
|
|
|
buf[isc_buffer_usedlength(&buffer)] = '\0';
|
|
}
|
|
|
|
void
|
|
dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(buf != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
zone_namerd_tostr(zone, buf, length);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(buf != NULL);
|
|
zone_name_tostr(zone, buf, length);
|
|
}
|
|
|
|
void
|
|
dns_zone_setminxfrratein(dns_zone_t *zone, uint32_t bytes, uint32_t seconds) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
zone->minxfrratebytesin = bytes;
|
|
zone->minxfrratesecondsin = seconds;
|
|
}
|
|
|
|
uint32_t
|
|
dns_zone_getminxfrratebytesin(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->minxfrratebytesin;
|
|
}
|
|
|
|
uint32_t
|
|
dns_zone_getminxfrratesecondsin(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->minxfrratesecondsin;
|
|
}
|
|
|
|
void
|
|
dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
zone->maxxfrin = maxxfrin;
|
|
}
|
|
|
|
uint32_t
|
|
dns_zone_getmaxxfrin(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->maxxfrin;
|
|
}
|
|
|
|
void
|
|
dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
zone->maxxfrout = maxxfrout;
|
|
}
|
|
|
|
uint32_t
|
|
dns_zone_getmaxxfrout(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->maxxfrout;
|
|
}
|
|
|
|
dns_zonetype_t
|
|
dns_zone_gettype(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->type;
|
|
}
|
|
|
|
dns_name_t *
|
|
dns_zone_getorigin(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return &zone->origin;
|
|
}
|
|
|
|
void
|
|
dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
if (idlein == 0) {
|
|
idlein = DNS_DEFAULT_IDLEIN;
|
|
}
|
|
zone->idlein = idlein;
|
|
}
|
|
|
|
uint32_t
|
|
dns_zone_getidlein(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->idlein;
|
|
}
|
|
|
|
void
|
|
dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
zone->idleout = idleout;
|
|
}
|
|
|
|
uint32_t
|
|
dns_zone_getidleout(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->idleout;
|
|
}
|
|
|
|
void
|
|
dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(table != NULL);
|
|
REQUIRE(*table == NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
if (zone->ssutable != NULL) {
|
|
dns_ssutable_attach(zone->ssutable, table);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (zone->ssutable != NULL) {
|
|
dns_ssutable_detach(&zone->ssutable);
|
|
}
|
|
if (table != NULL) {
|
|
dns_ssutable_attach(table, &zone->ssutable);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
zone->sigvalidityinterval = interval;
|
|
}
|
|
|
|
uint32_t
|
|
dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->sigvalidityinterval;
|
|
}
|
|
|
|
void
|
|
dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
zone->keyvalidityinterval = interval;
|
|
}
|
|
|
|
uint32_t
|
|
dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->keyvalidityinterval;
|
|
}
|
|
|
|
void
|
|
dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
|
|
isc_time_t now;
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
zone->sigresigninginterval = interval;
|
|
dns__zone_set_resigntime(zone);
|
|
if (zone->loop != NULL) {
|
|
now = isc_time_now();
|
|
dns__zone_settimer(zone, &now);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
uint32_t
|
|
dns_zone_getsigresigninginterval(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->sigresigninginterval;
|
|
}
|
|
|
|
void
|
|
dns_zone_getsourceaddr(dns_zone_t *zone, isc_sockaddr_t *sourceaddr) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(sourceaddr != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
INSIST(dns_remote_count(&zone->primaries) > 0);
|
|
*sourceaddr = zone->sourceaddr;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
isc_result_t
|
|
dns_zone_getprimaryaddr(dns_zone_t *zone, isc_sockaddr_t *primaryaddr) {
|
|
isc_result_t result = ISC_R_NOMORE;
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(primaryaddr != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
INSIST(dns_remote_count(&zone->primaries) > 0);
|
|
if (!dns_remote_done(&zone->primaries)) {
|
|
*primaryaddr = dns_remote_curraddr(&zone->primaries);
|
|
result = ISC_R_SUCCESS;
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
|
|
return result;
|
|
}
|
|
|
|
isc_time_t
|
|
dns_zone_getxfrintime(dns_zone_t *zone) {
|
|
isc_time_t xfrintime;
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
xfrintime = zone->xfrintime;
|
|
UNLOCK_ZONE(zone);
|
|
|
|
return xfrintime;
|
|
}
|
|
|
|
void
|
|
dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(zone->stats == NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
zone->stats = NULL;
|
|
isc_stats_attach(stats, &zone->stats);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (zone->requeststats_on && stats == NULL) {
|
|
zone->requeststats_on = false;
|
|
} else if (!zone->requeststats_on && stats != NULL) {
|
|
if (zone->requeststats == NULL) {
|
|
isc_stats_attach(stats, &zone->requeststats);
|
|
}
|
|
zone->requeststats_on = true;
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setrcvquerystats(dns_zone_t *zone, isc_statsmulti_t *stats) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (zone->requeststats_on && stats != NULL) {
|
|
if (zone->rcvquerystats == NULL) {
|
|
isc_statsmulti_attach(stats, &zone->rcvquerystats);
|
|
zone->requeststats_on = true;
|
|
}
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
if (stats != NULL && zone->dnssecsignstats == NULL) {
|
|
dns_stats_attach(stats, &zone->dnssecsignstats);
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
dns_stats_t *
|
|
dns_zone_getdnssecsignstats(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->dnssecsignstats;
|
|
}
|
|
|
|
isc_stats_t *
|
|
dns_zone_getrequeststats(dns_zone_t *zone) {
|
|
/*
|
|
* We don't lock zone for efficiency reason. This is not catastrophic
|
|
* because requeststats must always be valid when requeststats_on is
|
|
* true.
|
|
* Some counters may be incremented while requeststats_on is becoming
|
|
* false, or some cannot be incremented just after the statistics are
|
|
* installed, but it shouldn't matter much in practice.
|
|
*/
|
|
if (zone->requeststats_on) {
|
|
return zone->requeststats;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Return the received query stats bucket
|
|
* see note from dns_zone_getrequeststats()
|
|
*/
|
|
isc_statsmulti_t *
|
|
dns_zone_getrcvquerystats(dns_zone_t *zone) {
|
|
if (zone->requeststats_on) {
|
|
return zone->rcvquerystats;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
void
|
|
dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
setstring(zone, &zone->keydirectory, directory);
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
const char *
|
|
dns_zone_getkeydirectory(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->keydirectory;
|
|
}
|
|
|
|
void
|
|
dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
zone->checkmx = checkmx;
|
|
}
|
|
|
|
void
|
|
dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
zone->checksrv = checksrv;
|
|
}
|
|
|
|
void
|
|
dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
zone->checkns = checkns;
|
|
}
|
|
|
|
void
|
|
dns_zone_setcheckisservedby(dns_zone_t *zone,
|
|
dns_checkisservedbyfunc_t checkisservedby) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
zone->checkisservedby = checkisservedby;
|
|
}
|
|
|
|
void
|
|
dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
zone->isself = isself;
|
|
zone->isselfarg = arg;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns__zone_getisself(dns_zone_t *zone, dns_isselffunc_t *isself, void **arg) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(isself != NULL);
|
|
REQUIRE(arg != NULL && *arg == NULL);
|
|
|
|
*isself = zone->isself;
|
|
*arg = zone->isselfarg;
|
|
}
|
|
|
|
void
|
|
dns_zone_setnotifydefer(dns_zone_t *zone, dns_rdatatype_t type,
|
|
uint32_t defer) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
switch (type) {
|
|
case dns_rdatatype_soa:
|
|
zone->notifysoa.notifydefer = defer;
|
|
break;
|
|
case dns_rdatatype_cds:
|
|
/* not applicable to NOTIFY(CDS), unused */
|
|
zone->notifycds.notifydefer = defer;
|
|
break;
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setnotifydelay(dns_zone_t *zone, dns_rdatatype_t type,
|
|
uint32_t delay) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
switch (type) {
|
|
case dns_rdatatype_soa:
|
|
zone->notifysoa.notifydelay = delay;
|
|
break;
|
|
case dns_rdatatype_cds:
|
|
/* not applicable to NOTIFY(CDS), unused */
|
|
zone->notifycds.notifydelay = delay;
|
|
break;
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
if (nodes == 0) {
|
|
nodes = 1;
|
|
}
|
|
zone->nodes = nodes;
|
|
}
|
|
|
|
void
|
|
dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
/*
|
|
* We treat signatures as a signed value so explicitly
|
|
* limit its range here.
|
|
*/
|
|
if (signatures > INT32_MAX) {
|
|
signatures = INT32_MAX;
|
|
} else if (signatures == 0) {
|
|
signatures = 1;
|
|
}
|
|
zone->signatures = signatures;
|
|
}
|
|
|
|
uint32_t
|
|
dns_zone_getsignatures(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
return zone->signatures;
|
|
}
|
|
|
|
void
|
|
dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
zone->privatetype = type;
|
|
}
|
|
|
|
dns_rdatatype_t
|
|
dns_zone_getprivatetype(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
return zone->privatetype;
|
|
}
|
|
|
|
void
|
|
dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
zone->automatic = automatic;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
bool
|
|
dns_zone_getautomatic(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
return zone->automatic;
|
|
}
|
|
|
|
void
|
|
dns_zone_setadded(dns_zone_t *zone, bool added) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
zone->added = added;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
bool
|
|
dns_zone_getadded(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
return zone->added;
|
|
}
|
|
|
|
void
|
|
dns_zone_setmodded(dns_zone_t *zone, bool modded) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
zone->modded = modded;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
bool
|
|
dns_zone_getmodded(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
return zone->modded;
|
|
}
|
|
|
|
isc_result_t
|
|
dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
if (interval == 0) {
|
|
return ISC_R_RANGE;
|
|
}
|
|
/* Maximum value: 24 hours (3600 minutes) */
|
|
if (interval > (24 * 60)) {
|
|
interval = (24 * 60);
|
|
}
|
|
/* Multiply by 60 for seconds */
|
|
zone->refreshkeyinterval = interval * 60;
|
|
return ISC_R_SUCCESS;
|
|
}
|
|
|
|
void
|
|
dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
zone->requestixfr = flag;
|
|
}
|
|
|
|
bool
|
|
dns_zone_getrequestixfr(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
return zone->requestixfr;
|
|
}
|
|
|
|
void
|
|
dns_zone_setrequestixfrmaxdiffs(dns_zone_t *zone, uint32_t maxdiffs) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
zone->requestixfr_maxdiffs = maxdiffs;
|
|
}
|
|
|
|
bool
|
|
dns_zone_getrequestixfrmaxdiffs(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
return zone->requestixfr_maxdiffs;
|
|
}
|
|
|
|
void
|
|
dns_zone_setixfrratio(dns_zone_t *zone, uint32_t ratio) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
zone->ixfr_ratio = ratio;
|
|
}
|
|
|
|
uint32_t
|
|
dns_zone_getixfrratio(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
return zone->ixfr_ratio;
|
|
}
|
|
|
|
void
|
|
dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
zone->requestexpire = flag;
|
|
}
|
|
|
|
bool
|
|
dns_zone_getrequestexpire(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
return zone->requestexpire;
|
|
}
|
|
|
|
void
|
|
dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
zone->updatemethod = method;
|
|
}
|
|
|
|
dns_updatemethod_t
|
|
dns_zone_getserialupdatemethod(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
return zone->updatemethod;
|
|
}
|
|
|
|
void
|
|
dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(loadtime != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
*loadtime = zone->loadtime;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(expiretime != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
*expiretime = zone->expiretime;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(refreshtime != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
*refreshtime = zone->refreshtime;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(refreshkeytime != NULL);
|
|
|
|
LOCK_ZONE(zone);
|
|
*refreshkeytime = zone->refreshkeytime;
|
|
UNLOCK_ZONE(zone);
|
|
}
|
|
|
|
void
|
|
dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
zone->statlevel = level;
|
|
}
|
|
|
|
dns_zonestat_level_t
|
|
dns_zone_getstatlevel(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->statlevel;
|
|
}
|
|
|
|
unsigned int
|
|
dns_zone_gettid(dns_zone_t *zone) {
|
|
return zone->tid;
|
|
}
|
|
|
|
isc_loop_t *
|
|
dns_zone_getloop(dns_zone_t *zone) {
|
|
return zone->loop;
|
|
}
|
|
|
|
isc_result_t
|
|
dns_zone_getrad(dns_zone_t *zone, dns_name_t *name) {
|
|
isc_result_t result = ISC_R_NOTFOUND;
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(DNS_NAME_VALID(name));
|
|
|
|
rcu_read_lock();
|
|
dns_rad_t *rad = rcu_dereference(zone->rad);
|
|
if (rad != NULL) {
|
|
dns_name_t *inner = dns_fixedname_name(&rad->fname);
|
|
dns_name_copy(inner, name);
|
|
result = ISC_R_SUCCESS;
|
|
}
|
|
rcu_read_unlock();
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
dns_zone_setrad(dns_zone_t *zone, dns_name_t *name) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(name == NULL || DNS_NAME_VALID(name));
|
|
|
|
rcu_read_lock();
|
|
dns_rad_t *new_rad = NULL;
|
|
if (name != NULL) {
|
|
new_rad = isc_mem_get(zone->mctx, sizeof(*new_rad));
|
|
*new_rad = (dns_rad_t){};
|
|
dns_fixedname_init(&new_rad->fname);
|
|
|
|
isc_mem_attach(zone->mctx, &new_rad->mctx);
|
|
dns_name_copy(name, dns_fixedname_name(&new_rad->fname));
|
|
}
|
|
dns_rad_t *xchg_rad = rcu_xchg_pointer(&zone->rad, new_rad);
|
|
|
|
if (xchg_rad != NULL) {
|
|
call_rcu(&xchg_rad->rcu_head, free_rad_rcu);
|
|
}
|
|
rcu_read_unlock();
|
|
}
|
|
|
|
void *
|
|
dns_zone_gethooktable(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
return zone->hooktable;
|
|
}
|
|
|
|
void
|
|
dns_zone_sethooktable(dns_zone_t *zone, void *hooktable,
|
|
void (*hooktable_free)(isc_mem_t *, void **)) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
REQUIRE(zone->hooktable == NULL);
|
|
REQUIRE(zone->hooktable_free == NULL);
|
|
|
|
zone->hooktable = hooktable;
|
|
zone->hooktable_free = hooktable_free;
|
|
}
|
|
|
|
void
|
|
dns_zone_setcfg(dns_zone_t *zone, const char *cfg) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
if (zone->cfg != NULL) {
|
|
isc_mem_free(zone->mctx, zone->cfg);
|
|
}
|
|
if (cfg != NULL) {
|
|
zone->cfg = isc_mem_strdup(zone->mctx, cfg);
|
|
}
|
|
}
|
|
|
|
const char *
|
|
dns_zone_getcfg(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->cfg;
|
|
}
|
|
|
|
/*
|
|
* Get the transport type used for the SOA query to the current primary server
|
|
* before an ongoing incoming zone transfer.
|
|
*
|
|
* Requires:
|
|
* The zone is locked by the caller.
|
|
*/
|
|
static dns_transport_type_t
|
|
get_request_transport_type(dns_zone_t *zone) {
|
|
dns_transport_type_t transport_type = DNS_TRANSPORT_NONE;
|
|
|
|
if (zone->transport != NULL) {
|
|
transport_type = dns_transport_get_type(zone->transport);
|
|
} else {
|
|
transport_type = (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC))
|
|
? DNS_TRANSPORT_TCP
|
|
: DNS_TRANSPORT_UDP;
|
|
|
|
/* Check if the peer is forced to always use TCP. */
|
|
if (transport_type != DNS_TRANSPORT_TCP &&
|
|
!dns_remote_done(&zone->primaries))
|
|
{
|
|
isc_result_t result;
|
|
isc_sockaddr_t primaryaddr;
|
|
isc_netaddr_t primaryip;
|
|
dns_peer_t *peer = NULL;
|
|
|
|
primaryaddr = dns_remote_curraddr(&zone->primaries);
|
|
isc_netaddr_fromsockaddr(&primaryip, &primaryaddr);
|
|
result = dns_peerlist_peerbyaddr(zone->view->peers,
|
|
&primaryip, &peer);
|
|
if (result == ISC_R_SUCCESS && peer != NULL) {
|
|
bool usetcp;
|
|
result = dns_peer_getforcetcp(peer, &usetcp);
|
|
if (result == ISC_R_SUCCESS && usetcp) {
|
|
transport_type = DNS_TRANSPORT_TCP;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return transport_type;
|
|
}
|
|
|
|
dns_transport_type_t
|
|
dns_zone_getrequesttransporttype(dns_zone_t *zone) {
|
|
dns_transport_type_t transport_type;
|
|
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
LOCK_ZONE(zone);
|
|
transport_type = get_request_transport_type(zone);
|
|
UNLOCK_ZONE(zone);
|
|
|
|
return transport_type;
|
|
}
|
|
|
|
dns_keystorelist_t *
|
|
dns_zone_getkeystores(dns_zone_t *zone) {
|
|
return zone->zmgr->keystores;
|
|
}
|
|
|
|
isc_stats_t *
|
|
dns_zone_getgluecachestats(dns_zone_t *zone) {
|
|
REQUIRE(DNS_ZONE_VALID(zone));
|
|
|
|
return zone->gluecachestats;
|
|
}
|