git: f44e67d120ad - main - MFV d60fa10fd872db7e3d8cb1e161cfdae026c43b14:

Cy Schubert cy at FreeBSD.org
Wed Feb 10 04:27:43 UTC 2021


The branch main has been updated by cy:

URL: https://cgit.FreeBSD.org/src/commit/?id=f44e67d120ad78ef7894241b519ee79fd190a16e

commit f44e67d120ad78ef7894241b519ee79fd190a16e
Merge: 1e811efbc591 d60fa10fd872
Author:     Cy Schubert <cy at FreeBSD.org>
AuthorDate: 2021-02-10 04:25:05 +0000
Commit:     Cy Schubert <cy at FreeBSD.org>
CommitDate: 2021-02-10 04:27:25 +0000

    MFV d60fa10fd872db7e3d8cb1e161cfdae026c43b14:
    
    Update unbound 1.13.0 --> 1.13.1.
    
    Includes numerous bugfixes documented at:
    https://www.nlnetlabs.nl/projects/unbound/download/#unbound-1-13-1
    
    MFC after:      1 month

 contrib/unbound/Makefile.in                        | 516 ++++++++++++---------
 contrib/unbound/aclocal.m4                         |   8 +-
 contrib/unbound/acx_nlnetlabs.m4                   |  60 ++-
 contrib/unbound/acx_python.m4                      |   6 +-
 contrib/unbound/cachedb/cachedb.c                  |   1 +
 contrib/unbound/config.guess                       |  20 +-
 contrib/unbound/config.h.in                        |   3 +-
 contrib/unbound/config.sub                         |  20 +-
 contrib/unbound/configure                          | 137 +++---
 contrib/unbound/configure.ac                       | 197 ++++----
 .../contrib/build-unbound-localzone-from-hosts.pl  |   0
 .../unbound/contrib/create_unbound_ad_servers.sh   |   0
 contrib/unbound/contrib/parseunbound.pl            |   0
 contrib/unbound/contrib/unbound_cache.sh           |   0
 contrib/unbound/contrib/warmup.sh                  |   0
 contrib/unbound/daemon/remote.c                    |  55 +++
 contrib/unbound/daemon/worker.c                    |  22 +-
 contrib/unbound/dns64/dns64.c                      |  43 +-
 contrib/unbound/dnscrypt/dnscrypt.m4               |   2 +-
 contrib/unbound/dnstap/dnstap.m4                   |   2 +-
 contrib/unbound/dnstap/unbound-dnstap-socket.c     |   9 +-
 contrib/unbound/doc/Changelog                      | 131 +++++-
 contrib/unbound/doc/FEATURES                       |   1 +
 contrib/unbound/doc/README                         |   2 +-
 contrib/unbound/doc/TODO                           |   1 -
 contrib/unbound/doc/example.conf.in                |  32 +-
 contrib/unbound/doc/libunbound.3.in                |   4 +-
 contrib/unbound/doc/unbound-anchor.8.in            |   2 +-
 contrib/unbound/doc/unbound-checkconf.8.in         |   2 +-
 contrib/unbound/doc/unbound-control.8.in           |   8 +-
 contrib/unbound/doc/unbound-host.1.in              |   2 +-
 contrib/unbound/doc/unbound.8.in                   |   4 +-
 contrib/unbound/doc/unbound.conf.5.in              |  60 ++-
 contrib/unbound/doc/unbound.doxygen                |   6 +-
 contrib/unbound/dynlibmod/dynlibmod.c              |  20 +-
 contrib/unbound/dynlibmod/dynlibmod.h              |   4 +-
 contrib/unbound/dynlibmod/examples/helloworld.c    |  14 +-
 contrib/unbound/ipset/ipset.c                      |   0
 contrib/unbound/ipset/ipset.h                      |   0
 contrib/unbound/libunbound/libworker.c             |   4 +
 contrib/unbound/ltmain.sh                          |   0
 contrib/unbound/respip/respip.c                    |   2 +-
 contrib/unbound/services/authzone.c                |  17 +-
 contrib/unbound/services/cache/rrset.c             |   2 +
 contrib/unbound/services/listen_dnsport.c          |  14 +-
 contrib/unbound/services/listen_dnsport.h          |   2 +-
 contrib/unbound/services/localzone.c               | 107 ++++-
 contrib/unbound/services/localzone.h               |   7 +
 contrib/unbound/services/mesh.c                    |  38 +-
 contrib/unbound/services/outside_network.c         |  77 ++-
 contrib/unbound/services/outside_network.h         |   2 +
 contrib/unbound/services/rpz.c                     |  21 +-
 contrib/unbound/services/rpz.h                     |  13 +
 contrib/unbound/smallapp/unbound-anchor.c          |  67 +--
 contrib/unbound/smallapp/unbound-control.c         | 105 ++++-
 contrib/unbound/smallapp/worker_cb.c               |   3 +
 contrib/unbound/util/config_file.c                 |  71 ++-
 contrib/unbound/util/config_file.h                 |  27 ++
 contrib/unbound/util/configlexer.lex               |   6 +
 contrib/unbound/util/configparser.y                |  87 +++-
 contrib/unbound/util/configyyrename.h              |   6 +
 contrib/unbound/util/data/msgencode.c              |  63 ++-
 contrib/unbound/util/data/msgparse.c               |   2 +
 contrib/unbound/util/data/msgparse.h               |   4 +
 contrib/unbound/util/data/msgreply.c               |  36 +-
 contrib/unbound/util/data/msgreply.h               |  20 +-
 contrib/unbound/util/data/packed_rrset.c           |  17 +-
 contrib/unbound/util/data/packed_rrset.h           |   3 +
 contrib/unbound/util/edns.c                        |  16 +
 contrib/unbound/util/iana_ports.inc                |   2 +-
 contrib/unbound/util/module.h                      |   4 +-
 contrib/unbound/util/net_help.c                    |   2 +-
 contrib/unbound/util/netevent.c                    | 122 ++++-
 contrib/unbound/util/netevent.h                    |  12 +
 contrib/unbound/util/storage/lruhash.c             |   4 +-
 contrib/unbound/validator/autotrust.c              |   1 +
 usr.sbin/unbound/config.h                          |   6 +-
 77 files changed, 1700 insertions(+), 686 deletions(-)

diff --cc contrib/unbound/contrib/build-unbound-localzone-from-hosts.pl
index c11bbc330795,c11bbc330795..c11bbc330795
mode 100755,100644..100644
--- a/contrib/unbound/contrib/build-unbound-localzone-from-hosts.pl
+++ b/contrib/unbound/contrib/build-unbound-localzone-from-hosts.pl
diff --cc contrib/unbound/contrib/create_unbound_ad_servers.sh
index 49fdbffedfaf,49fdbffedfaf..49fdbffedfaf
mode 100755,100644..100644
--- a/contrib/unbound/contrib/create_unbound_ad_servers.sh
+++ b/contrib/unbound/contrib/create_unbound_ad_servers.sh
diff --cc contrib/unbound/contrib/parseunbound.pl
index 1d294b13288d,1d294b13288d..1d294b13288d
mode 100755,100644..100644
--- a/contrib/unbound/contrib/parseunbound.pl
+++ b/contrib/unbound/contrib/parseunbound.pl
diff --cc contrib/unbound/contrib/unbound_cache.sh
index b3e876ba9012,b3e876ba9012..b3e876ba9012
mode 100755,100644..100644
--- a/contrib/unbound/contrib/unbound_cache.sh
+++ b/contrib/unbound/contrib/unbound_cache.sh
diff --cc contrib/unbound/contrib/warmup.sh
index b4d9135a68dd,b4d9135a68dd..b4d9135a68dd
mode 100755,100644..100644
--- a/contrib/unbound/contrib/warmup.sh
+++ b/contrib/unbound/contrib/warmup.sh
diff --cc contrib/unbound/doc/unbound-checkconf.8.in
index abcd45c8b811,000000000000..ed9db8ffa82c
mode 100644,000000..100644
--- a/contrib/unbound/doc/unbound-checkconf.8.in
+++ b/contrib/unbound/doc/unbound-checkconf.8.in
@@@ -1,52 -1,0 +1,52 @@@
- .TH "unbound-checkconf" "8" "Dec  3, 2020" "NLnet Labs" "unbound 1.13.0"
++.TH "unbound-checkconf" "8" "Feb  9, 2021" "NLnet Labs" "unbound 1.13.1"
 +.\"
 +.\" unbound-checkconf.8 -- unbound configuration checker manual
 +.\"
 +.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
 +.\"
 +.\" See LICENSE for the license.
 +.\"
 +.\"
 +.SH "NAME"
 +.B unbound\-checkconf
 +\- Check unbound configuration file for errors.
 +.SH "SYNOPSIS"
 +.B unbound\-checkconf
 +.RB [ \-h ]
 +.RB [ \-f ]
 +.RB [ \-o
 +.IR option ]
 +.RI [ cfgfile ]
 +.SH "DESCRIPTION"
 +.B Unbound\-checkconf
 +checks the configuration file for the
 +\fIunbound\fR(8)
 +DNS resolver for syntax and other errors. 
 +The config file syntax is described in 
 +\fIunbound.conf\fR(5).
 +.P
 +The available options are:
 +.TP
 +.B \-h
 +Show the version and commandline option help.
 +.TP
 +.B \-f
 +Print full pathname, with chroot applied to it.  Use with the \-o option.
 +.TP
 +.B \-o\fI option
 +If given, after checking the config file the value of this option is 
 +printed to stdout.  For "" (disabled) options an empty line is printed.
 +.TP
 +.I cfgfile
 +The config file to read with settings for unbound. It is checked.
 +If omitted, the config file at the default location is checked.
 +.SH "EXIT CODE"
 +The unbound\-checkconf program exits with status code 1 on error, 
 +0 for a correct config file.
 +.SH "FILES"
 +.TP
 +.I @ub_conf_file@
 +unbound configuration file.
 +.SH "SEE ALSO"
 +\fIunbound.conf\fR(5), 
 +\fIunbound\fR(8).
diff --cc contrib/unbound/ipset/ipset.c
index f6e2c4a9d8a6,f6e2c4a9d8a6..f6e2c4a9d8a6
mode 100755,100644..100644
--- a/contrib/unbound/ipset/ipset.c
+++ b/contrib/unbound/ipset/ipset.c
diff --cc contrib/unbound/ipset/ipset.h
index f60a8be8c837,f60a8be8c837..f60a8be8c837
mode 100755,100644..100644
--- a/contrib/unbound/ipset/ipset.h
+++ b/contrib/unbound/ipset/ipset.h
diff --cc contrib/unbound/ltmain.sh
index 7f3523d335c5,7f3523d335c5..7f3523d335c5
mode 100755,100644..100644
--- a/contrib/unbound/ltmain.sh
+++ b/contrib/unbound/ltmain.sh
diff --cc contrib/unbound/services/authzone.c
index a43a25def993,000000000000..ecd63ec144f5
mode 100644,000000..100644
--- a/contrib/unbound/services/authzone.c
+++ b/contrib/unbound/services/authzone.c
@@@ -1,6969 -1,0 +1,6974 @@@
 +/*
 + * services/authzone.c - authoritative zone that is locally hosted.
 + *
 + * Copyright (c) 2017, NLnet Labs. All rights reserved.
 + *
 + * This software is open source.
 + * 
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 
 + * Redistributions of source code must retain the above copyright notice,
 + * this list of conditions and the following disclaimer.
 + * 
 + * Redistributions in binary form must reproduce the above copyright notice,
 + * this list of conditions and the following disclaimer in the documentation
 + * and/or other materials provided with the distribution.
 + * 
 + * Neither the name of the NLNET LABS nor the names of its contributors may
 + * be used to endorse or promote products derived from this software without
 + * specific prior written permission.
 + * 
 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + */
 +
 +/**
 + * \file
 + *
 + * This file contains the functions for an authority zone.  This zone
 + * is queried by the iterator, just like a stub or forward zone, but then
 + * the data is locally held.
 + */
 +
 +#include "config.h"
 +#include "services/authzone.h"
 +#include "util/data/dname.h"
 +#include "util/data/msgparse.h"
 +#include "util/data/msgreply.h"
 +#include "util/data/msgencode.h"
 +#include "util/data/packed_rrset.h"
 +#include "util/regional.h"
 +#include "util/net_help.h"
 +#include "util/netevent.h"
 +#include "util/config_file.h"
 +#include "util/log.h"
 +#include "util/module.h"
 +#include "util/random.h"
 +#include "services/cache/dns.h"
 +#include "services/outside_network.h"
 +#include "services/listen_dnsport.h"
 +#include "services/mesh.h"
 +#include "sldns/rrdef.h"
 +#include "sldns/pkthdr.h"
 +#include "sldns/sbuffer.h"
 +#include "sldns/str2wire.h"
 +#include "sldns/wire2str.h"
 +#include "sldns/parseutil.h"
 +#include "sldns/keyraw.h"
 +#include "validator/val_nsec3.h"
 +#include "validator/val_secalgo.h"
 +#include <ctype.h>
 +
 +/** bytes to use for NSEC3 hash buffer. 20 for sha1 */
 +#define N3HASHBUFLEN 32
 +/** max number of CNAMEs we are willing to follow (in one answer) */
 +#define MAX_CNAME_CHAIN 8
 +/** timeout for probe packets for SOA */
 +#define AUTH_PROBE_TIMEOUT 100 /* msec */
 +/** when to stop with SOA probes (when exponential timeouts exceed this) */
 +#define AUTH_PROBE_TIMEOUT_STOP 1000 /* msec */
 +/* auth transfer timeout for TCP connections, in msec */
 +#define AUTH_TRANSFER_TIMEOUT 10000 /* msec */
 +/* auth transfer max backoff for failed tranfers and probes */
 +#define AUTH_TRANSFER_MAX_BACKOFF 86400 /* sec */
 +/* auth http port number */
 +#define AUTH_HTTP_PORT 80
 +/* auth https port number */
 +#define AUTH_HTTPS_PORT 443
 +/* max depth for nested $INCLUDEs */
 +#define MAX_INCLUDE_DEPTH 10
 +/** number of timeouts before we fallback from IXFR to AXFR,
 + * because some versions of servers (eg. dnsmasq) drop IXFR packets. */
 +#define NUM_TIMEOUTS_FALLBACK_IXFR 3
 +
 +/** pick up nextprobe task to start waiting to perform transfer actions */
 +static void xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
 +	int failure, int lookup_only);
 +/** move to sending the probe packets, next if fails. task_probe */
 +static void xfr_probe_send_or_end(struct auth_xfer* xfr,
 +	struct module_env* env);
 +/** pick up probe task with specified(or NULL) destination first,
 + * or transfer task if nothing to probe, or false if already in progress */
 +static int xfr_start_probe(struct auth_xfer* xfr, struct module_env* env,
 +	struct auth_master* spec);
 +/** delete xfer structure (not its tree entry) */
 +static void auth_xfer_delete(struct auth_xfer* xfr);
 +
 +/** create new dns_msg */
 +static struct dns_msg*
 +msg_create(struct regional* region, struct query_info* qinfo)
 +{
 +	struct dns_msg* msg = (struct dns_msg*)regional_alloc(region,
 +		sizeof(struct dns_msg));
 +	if(!msg)
 +		return NULL;
 +	msg->qinfo.qname = regional_alloc_init(region, qinfo->qname,
 +		qinfo->qname_len);
 +	if(!msg->qinfo.qname)
 +		return NULL;
 +	msg->qinfo.qname_len = qinfo->qname_len;
 +	msg->qinfo.qtype = qinfo->qtype;
 +	msg->qinfo.qclass = qinfo->qclass;
 +	msg->qinfo.local_alias = NULL;
 +	/* non-packed reply_info, because it needs to grow the array */
 +	msg->rep = (struct reply_info*)regional_alloc_zero(region,
 +		sizeof(struct reply_info)-sizeof(struct rrset_ref));
 +	if(!msg->rep)
 +		return NULL;
 +	msg->rep->flags = (uint16_t)(BIT_QR | BIT_AA);
 +	msg->rep->authoritative = 1;
 +	msg->rep->qdcount = 1;
 +	/* rrsets is NULL, no rrsets yet */
 +	return msg;
 +}
 +
 +/** grow rrset array by one in msg */
 +static int
 +msg_grow_array(struct regional* region, struct dns_msg* msg)
 +{
 +	if(msg->rep->rrsets == NULL) {
 +		msg->rep->rrsets = regional_alloc_zero(region,
 +			sizeof(struct ub_packed_rrset_key*)*(msg->rep->rrset_count+1));
 +		if(!msg->rep->rrsets)
 +			return 0;
 +	} else {
 +		struct ub_packed_rrset_key** rrsets_old = msg->rep->rrsets;
 +		msg->rep->rrsets = regional_alloc_zero(region,
 +			sizeof(struct ub_packed_rrset_key*)*(msg->rep->rrset_count+1));
 +		if(!msg->rep->rrsets)
 +			return 0;
 +		memmove(msg->rep->rrsets, rrsets_old,
 +			sizeof(struct ub_packed_rrset_key*)*msg->rep->rrset_count);
 +	}
 +	return 1;
 +}
 +
 +/** get ttl of rrset */
 +static time_t
 +get_rrset_ttl(struct ub_packed_rrset_key* k)
 +{
 +	struct packed_rrset_data* d = (struct packed_rrset_data*)
 +		k->entry.data;
 +	return d->ttl;
 +}
 +
 +/** Copy rrset into region from domain-datanode and packet rrset */
 +static struct ub_packed_rrset_key*
 +auth_packed_rrset_copy_region(struct auth_zone* z, struct auth_data* node,
 +	struct auth_rrset* rrset, struct regional* region, time_t adjust)
 +{
 +	struct ub_packed_rrset_key key;
 +	memset(&key, 0, sizeof(key));
 +	key.entry.key = &key;
 +	key.entry.data = rrset->data;
 +	key.rk.dname = node->name;
 +	key.rk.dname_len = node->namelen;
 +	key.rk.type = htons(rrset->type);
 +	key.rk.rrset_class = htons(z->dclass);
 +	key.entry.hash = rrset_key_hash(&key.rk);
 +	return packed_rrset_copy_region(&key, region, adjust);
 +}
 +
 +/** fix up msg->rep TTL and prefetch ttl */
 +static void
 +msg_ttl(struct dns_msg* msg)
 +{
 +	if(msg->rep->rrset_count == 0) return;
 +	if(msg->rep->rrset_count == 1) {
 +		msg->rep->ttl = get_rrset_ttl(msg->rep->rrsets[0]);
 +		msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
 +		msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
 +	} else if(get_rrset_ttl(msg->rep->rrsets[msg->rep->rrset_count-1]) <
 +		msg->rep->ttl) {
 +		msg->rep->ttl = get_rrset_ttl(msg->rep->rrsets[
 +			msg->rep->rrset_count-1]);
 +		msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
 +		msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
 +	}
 +}
 +
 +/** see if rrset is a duplicate in the answer message */
 +static int
 +msg_rrset_duplicate(struct dns_msg* msg, uint8_t* nm, size_t nmlen,
 +	uint16_t type, uint16_t dclass)
 +{
 +	size_t i;
 +	for(i=0; i<msg->rep->rrset_count; i++) {
 +		struct ub_packed_rrset_key* k = msg->rep->rrsets[i];
 +		if(ntohs(k->rk.type) == type && k->rk.dname_len == nmlen &&
 +			ntohs(k->rk.rrset_class) == dclass &&
 +			query_dname_compare(k->rk.dname, nm) == 0)
 +			return 1;
 +	}
 +	return 0;
 +}
 +
 +/** add rrset to answer section (no auth, add rrsets yet) */
 +static int
 +msg_add_rrset_an(struct auth_zone* z, struct regional* region,
 +	struct dns_msg* msg, struct auth_data* node, struct auth_rrset* rrset)
 +{
 +	log_assert(msg->rep->ns_numrrsets == 0);
 +	log_assert(msg->rep->ar_numrrsets == 0);
 +	if(!rrset || !node)
 +		return 1;
 +	if(msg_rrset_duplicate(msg, node->name, node->namelen, rrset->type,
 +		z->dclass))
 +		return 1;
 +	/* grow array */
 +	if(!msg_grow_array(region, msg))
 +		return 0;
 +	/* copy it */
 +	if(!(msg->rep->rrsets[msg->rep->rrset_count] =
 +		auth_packed_rrset_copy_region(z, node, rrset, region, 0)))
 +		return 0;
 +	msg->rep->rrset_count++;
 +	msg->rep->an_numrrsets++;
 +	msg_ttl(msg);
 +	return 1;
 +}
 +
 +/** add rrset to authority section (no additonal section rrsets yet) */
 +static int
 +msg_add_rrset_ns(struct auth_zone* z, struct regional* region,
 +	struct dns_msg* msg, struct auth_data* node, struct auth_rrset* rrset)
 +{
 +	log_assert(msg->rep->ar_numrrsets == 0);
 +	if(!rrset || !node)
 +		return 1;
 +	if(msg_rrset_duplicate(msg, node->name, node->namelen, rrset->type,
 +		z->dclass))
 +		return 1;
 +	/* grow array */
 +	if(!msg_grow_array(region, msg))
 +		return 0;
 +	/* copy it */
 +	if(!(msg->rep->rrsets[msg->rep->rrset_count] =
 +		auth_packed_rrset_copy_region(z, node, rrset, region, 0)))
 +		return 0;
 +	msg->rep->rrset_count++;
 +	msg->rep->ns_numrrsets++;
 +	msg_ttl(msg);
 +	return 1;
 +}
 +
 +/** add rrset to additional section */
 +static int
 +msg_add_rrset_ar(struct auth_zone* z, struct regional* region,
 +	struct dns_msg* msg, struct auth_data* node, struct auth_rrset* rrset)
 +{
 +	if(!rrset || !node)
 +		return 1;
 +	if(msg_rrset_duplicate(msg, node->name, node->namelen, rrset->type,
 +		z->dclass))
 +		return 1;
 +	/* grow array */
 +	if(!msg_grow_array(region, msg))
 +		return 0;
 +	/* copy it */
 +	if(!(msg->rep->rrsets[msg->rep->rrset_count] =
 +		auth_packed_rrset_copy_region(z, node, rrset, region, 0)))
 +		return 0;
 +	msg->rep->rrset_count++;
 +	msg->rep->ar_numrrsets++;
 +	msg_ttl(msg);
 +	return 1;
 +}
 +
 +struct auth_zones* auth_zones_create(void)
 +{
 +	struct auth_zones* az = (struct auth_zones*)calloc(1, sizeof(*az));
 +	if(!az) {
 +		log_err("out of memory");
 +		return NULL;
 +	}
 +	rbtree_init(&az->ztree, &auth_zone_cmp);
 +	rbtree_init(&az->xtree, &auth_xfer_cmp);
 +	lock_rw_init(&az->lock);
 +	lock_protect(&az->lock, &az->ztree, sizeof(az->ztree));
 +	lock_protect(&az->lock, &az->xtree, sizeof(az->xtree));
 +	/* also lock protects the rbnode's in struct auth_zone, auth_xfer */
 +	lock_rw_init(&az->rpz_lock);
 +	lock_protect(&az->rpz_lock, &az->rpz_first, sizeof(az->rpz_first));
 +	return az;
 +}
 +
 +int auth_zone_cmp(const void* z1, const void* z2)
 +{
 +	/* first sort on class, so that hierarchy can be maintained within
 +	 * a class */
 +	struct auth_zone* a = (struct auth_zone*)z1;
 +	struct auth_zone* b = (struct auth_zone*)z2;
 +	int m;
 +	if(a->dclass != b->dclass) {
 +		if(a->dclass < b->dclass)
 +			return -1;
 +		return 1;
 +	}
 +	/* sorted such that higher zones sort before lower zones (their
 +	 * contents) */
 +	return dname_lab_cmp(a->name, a->namelabs, b->name, b->namelabs, &m);
 +}
 +
 +int auth_data_cmp(const void* z1, const void* z2)
 +{
 +	struct auth_data* a = (struct auth_data*)z1;
 +	struct auth_data* b = (struct auth_data*)z2;
 +	int m;
 +	/* canonical sort, because DNSSEC needs that */
 +	return dname_canon_lab_cmp(a->name, a->namelabs, b->name,
 +		b->namelabs, &m);
 +}
 +
 +int auth_xfer_cmp(const void* z1, const void* z2)
 +{
 +	/* first sort on class, so that hierarchy can be maintained within
 +	 * a class */
 +	struct auth_xfer* a = (struct auth_xfer*)z1;
 +	struct auth_xfer* b = (struct auth_xfer*)z2;
 +	int m;
 +	if(a->dclass != b->dclass) {
 +		if(a->dclass < b->dclass)
 +			return -1;
 +		return 1;
 +	}
 +	/* sorted such that higher zones sort before lower zones (their
 +	 * contents) */
 +	return dname_lab_cmp(a->name, a->namelabs, b->name, b->namelabs, &m);
 +}
 +
 +/** delete auth rrset node */
 +static void
 +auth_rrset_delete(struct auth_rrset* rrset)
 +{
 +	if(!rrset) return;
 +	free(rrset->data);
 +	free(rrset);
 +}
 +
 +/** delete auth data domain node */
 +static void
 +auth_data_delete(struct auth_data* n)
 +{
 +	struct auth_rrset* p, *np;
 +	if(!n) return;
 +	p = n->rrsets;
 +	while(p) {
 +		np = p->next;
 +		auth_rrset_delete(p);
 +		p = np;
 +	}
 +	free(n->name);
 +	free(n);
 +}
 +
 +/** helper traverse to delete zones */
 +static void
 +auth_data_del(rbnode_type* n, void* ATTR_UNUSED(arg))
 +{
 +	struct auth_data* z = (struct auth_data*)n->key;
 +	auth_data_delete(z);
 +}
 +
 +/** delete an auth zone structure (tree remove must be done elsewhere) */
 +static void
 +auth_zone_delete(struct auth_zone* z, struct auth_zones* az)
 +{
 +	if(!z) return;
 +	lock_rw_destroy(&z->lock);
 +	traverse_postorder(&z->data, auth_data_del, NULL);
 +
 +	if(az && z->rpz) {
 +		/* keep RPZ linked list intact */
 +		lock_rw_wrlock(&az->rpz_lock);
 +		if(z->rpz_az_prev)
 +			z->rpz_az_prev->rpz_az_next = z->rpz_az_next;
 +		else
 +			az->rpz_first = z->rpz_az_next;
 +		if(z->rpz_az_next)
 +			z->rpz_az_next->rpz_az_prev = z->rpz_az_prev;
 +		lock_rw_unlock(&az->rpz_lock);
 +	}
 +	if(z->rpz)
 +		rpz_delete(z->rpz);
 +	free(z->name);
 +	free(z->zonefile);
 +	free(z);
 +}
 +
 +struct auth_zone*
 +auth_zone_create(struct auth_zones* az, uint8_t* nm, size_t nmlen,
 +	uint16_t dclass)
 +{
 +	struct auth_zone* z = (struct auth_zone*)calloc(1, sizeof(*z));
 +	if(!z) {
 +		return NULL;
 +	}
 +	z->node.key = z;
 +	z->dclass = dclass;
 +	z->namelen = nmlen;
 +	z->namelabs = dname_count_labels(nm);
 +	z->name = memdup(nm, nmlen);
 +	if(!z->name) {
 +		free(z);
 +		return NULL;
 +	}
 +	rbtree_init(&z->data, &auth_data_cmp);
 +	lock_rw_init(&z->lock);
 +	lock_protect(&z->lock, &z->name, sizeof(*z)-sizeof(rbnode_type)-
 +			sizeof(&z->rpz_az_next)-sizeof(&z->rpz_az_prev));
 +	lock_rw_wrlock(&z->lock);
 +	/* z lock protects all, except rbtree itself and the rpz linked list
 +	 * pointers, which are protected using az->lock */
 +	if(!rbtree_insert(&az->ztree, &z->node)) {
 +		lock_rw_unlock(&z->lock);
 +		auth_zone_delete(z, NULL);
 +		log_warn("duplicate auth zone");
 +		return NULL;
 +	}
 +	return z;
 +}
 +
 +struct auth_zone*
 +auth_zone_find(struct auth_zones* az, uint8_t* nm, size_t nmlen,
 +	uint16_t dclass)
 +{
 +	struct auth_zone key;
 +	key.node.key = &key;
 +	key.dclass = dclass;
 +	key.name = nm;
 +	key.namelen = nmlen;
 +	key.namelabs = dname_count_labels(nm);
 +	return (struct auth_zone*)rbtree_search(&az->ztree, &key);
 +}
 +
 +struct auth_xfer*
 +auth_xfer_find(struct auth_zones* az, uint8_t* nm, size_t nmlen,
 +	uint16_t dclass)
 +{
 +	struct auth_xfer key;
 +	key.node.key = &key;
 +	key.dclass = dclass;
 +	key.name = nm;
 +	key.namelen = nmlen;
 +	key.namelabs = dname_count_labels(nm);
 +	return (struct auth_xfer*)rbtree_search(&az->xtree, &key);
 +}
 +
 +/** find an auth zone or sorted less-or-equal, return true if exact */
 +static int
 +auth_zone_find_less_equal(struct auth_zones* az, uint8_t* nm, size_t nmlen,
 +	uint16_t dclass, struct auth_zone** z)
 +{
 +	struct auth_zone key;
 +	key.node.key = &key;
 +	key.dclass = dclass;
 +	key.name = nm;
 +	key.namelen = nmlen;
 +	key.namelabs = dname_count_labels(nm);
 +	return rbtree_find_less_equal(&az->ztree, &key, (rbnode_type**)z);
 +}
 +
 +
 +/** find the auth zone that is above the given name */
 +struct auth_zone*
 +auth_zones_find_zone(struct auth_zones* az, uint8_t* name, size_t name_len,
 +	uint16_t dclass)
 +{
 +	uint8_t* nm = name;
 +	size_t nmlen = name_len;
 +	struct auth_zone* z;
 +	if(auth_zone_find_less_equal(az, nm, nmlen, dclass, &z)) {
 +		/* exact match */
 +		return z;
 +	} else {
 +		/* less-or-nothing */
 +		if(!z) return NULL; /* nothing smaller, nothing above it */
 +		/* we found smaller name; smaller may be above the name,
 +		 * but not below it. */
 +		nm = dname_get_shared_topdomain(z->name, name);
 +		dname_count_size_labels(nm, &nmlen);
 +		z = NULL;
 +	}
 +
 +	/* search up */
 +	while(!z) {
 +		z = auth_zone_find(az, nm, nmlen, dclass);
 +		if(z) return z;
 +		if(dname_is_root(nm)) break;
 +		dname_remove_label(&nm, &nmlen);
 +	}
 +	return NULL;
 +}
 +
 +/** find or create zone with name str. caller must have lock on az. 
 + * returns a wrlocked zone */
 +static struct auth_zone*
 +auth_zones_find_or_add_zone(struct auth_zones* az, char* name)
 +{
 +	uint8_t nm[LDNS_MAX_DOMAINLEN+1];
 +	size_t nmlen = sizeof(nm);
 +	struct auth_zone* z;
 +
 +	if(sldns_str2wire_dname_buf(name, nm, &nmlen) != 0) {
 +		log_err("cannot parse auth zone name: %s", name);
 +		return 0;
 +	}
 +	z = auth_zone_find(az, nm, nmlen, LDNS_RR_CLASS_IN);
 +	if(!z) {
 +		/* not found, create the zone */
 +		z = auth_zone_create(az, nm, nmlen, LDNS_RR_CLASS_IN);
 +	} else {
 +		lock_rw_wrlock(&z->lock);
 +	}
 +	return z;
 +}
 +
 +/** find or create xfer zone with name str. caller must have lock on az. 
 + * returns a locked xfer */
 +static struct auth_xfer*
 +auth_zones_find_or_add_xfer(struct auth_zones* az, struct auth_zone* z)
 +{
 +	struct auth_xfer* x;
 +	x = auth_xfer_find(az, z->name, z->namelen, z->dclass);
 +	if(!x) {
 +		/* not found, create the zone */
 +		x = auth_xfer_create(az, z);
 +	} else {
 +		lock_basic_lock(&x->lock);
 +	}
 +	return x;
 +}
 +
 +int
 +auth_zone_set_zonefile(struct auth_zone* z, char* zonefile)
 +{
 +	if(z->zonefile) free(z->zonefile);
 +	if(zonefile == NULL) {
 +		z->zonefile = NULL;
 +	} else {
 +		z->zonefile = strdup(zonefile);
 +		if(!z->zonefile) {
 +			log_err("malloc failure");
 +			return 0;
 +		}
 +	}
 +	return 1;
 +}
 +
 +/** set auth zone fallback. caller must have lock on zone */
 +int
 +auth_zone_set_fallback(struct auth_zone* z, char* fallbackstr)
 +{
 +	if(strcmp(fallbackstr, "yes") != 0 && strcmp(fallbackstr, "no") != 0){
 +		log_err("auth zone fallback, expected yes or no, got %s",
 +			fallbackstr);
 +		return 0;
 +	}
 +	z->fallback_enabled = (strcmp(fallbackstr, "yes")==0);
 +	return 1;
 +}
 +
 +/** create domain with the given name */
 +static struct auth_data*
 +az_domain_create(struct auth_zone* z, uint8_t* nm, size_t nmlen)
 +{
 +	struct auth_data* n = (struct auth_data*)malloc(sizeof(*n));
 +	if(!n) return NULL;
 +	memset(n, 0, sizeof(*n));
 +	n->node.key = n;
 +	n->name = memdup(nm, nmlen);
 +	if(!n->name) {
 +		free(n);
 +		return NULL;
 +	}
 +	n->namelen = nmlen;
 +	n->namelabs = dname_count_labels(nm);
 +	if(!rbtree_insert(&z->data, &n->node)) {
 +		log_warn("duplicate auth domain name");
 +		free(n->name);
 +		free(n);
 +		return NULL;
 +	}
 +	return n;
 +}
 +
 +/** find domain with exactly the given name */
 +static struct auth_data*
 +az_find_name(struct auth_zone* z, uint8_t* nm, size_t nmlen)
 +{
 +	struct auth_zone key;
 +	key.node.key = &key;
 +	key.name = nm;
 +	key.namelen = nmlen;
 +	key.namelabs = dname_count_labels(nm);
 +	return (struct auth_data*)rbtree_search(&z->data, &key);
 +}
 +
 +/** Find domain name (or closest match) */
 +static void
 +az_find_domain(struct auth_zone* z, struct query_info* qinfo, int* node_exact,
 +	struct auth_data** node)
 +{
 +	struct auth_zone key;
 +	key.node.key = &key;
 +	key.name = qinfo->qname;
 +	key.namelen = qinfo->qname_len;
 +	key.namelabs = dname_count_labels(key.name);
 +	*node_exact = rbtree_find_less_equal(&z->data, &key,
 +		(rbnode_type**)node);
 +}
 +
 +/** find or create domain with name in zone */
 +static struct auth_data*
 +az_domain_find_or_create(struct auth_zone* z, uint8_t* dname,
 +	size_t dname_len)
 +{
 +	struct auth_data* n = az_find_name(z, dname, dname_len);
 +	if(!n) {
 +		n = az_domain_create(z, dname, dname_len);
 +	}
 +	return n;
 +}
 +
 +/** find rrset of given type in the domain */
 +static struct auth_rrset*
 +az_domain_rrset(struct auth_data* n, uint16_t t)
 +{
 +	struct auth_rrset* rrset;
 +	if(!n) return NULL;
 +	rrset = n->rrsets;
 +	while(rrset) {
 +		if(rrset->type == t)
 +			return rrset;
 +		rrset = rrset->next;
 +	}
 +	return NULL;
 +}
 +
 +/** remove rrset of this type from domain */
 +static void
 +domain_remove_rrset(struct auth_data* node, uint16_t rr_type)
 +{
 +	struct auth_rrset* rrset, *prev;
 +	if(!node) return;
 +	prev = NULL;
 +	rrset = node->rrsets;
 +	while(rrset) {
 +		if(rrset->type == rr_type) {
 +			/* found it, now delete it */
 +			if(prev) prev->next = rrset->next;
 +			else	node->rrsets = rrset->next;
 +			auth_rrset_delete(rrset);
 +			return;
 +		}
 +		prev = rrset;
 +		rrset = rrset->next;
 +	}
 +}
 +
 +/** find an rrsig index in the rrset.  returns true if found */
 +static int
 +az_rrset_find_rrsig(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
 +	size_t* index)
 +{
 +	size_t i;
 +	for(i=d->count; i<d->count + d->rrsig_count; i++) {
 +		if(d->rr_len[i] != len)
 +			continue;
 +		if(memcmp(d->rr_data[i], rdata, len) == 0) {
 +			*index = i;
 +			return 1;
 +		}
 +	}
 +	return 0;
 +}
 +
 +/** see if rdata is duplicate */
 +static int
 +rdata_duplicate(struct packed_rrset_data* d, uint8_t* rdata, size_t len)
 +{
 +	size_t i;
 +	for(i=0; i<d->count + d->rrsig_count; i++) {
 +		if(d->rr_len[i] != len)
 +			continue;
 +		if(memcmp(d->rr_data[i], rdata, len) == 0)
 +			return 1;
 +	}
 +	return 0;
 +}
 +
 +/** get rrsig type covered from rdata.
 + * @param rdata: rdata in wireformat, starting with 16bit rdlength.
 + * @param rdatalen: length of rdata buffer.
 + * @return type covered (or 0).
 + */
 +static uint16_t
 +rrsig_rdata_get_type_covered(uint8_t* rdata, size_t rdatalen)
 +{
 +	if(rdatalen < 4)
 +		return 0;
 +	return sldns_read_uint16(rdata+2);
 +}
 +
 +/** remove RR from existing RRset. Also sig, if it is a signature.
 + * reallocates the packed rrset for a new one, false on alloc failure */
 +static int
 +rrset_remove_rr(struct auth_rrset* rrset, size_t index)
 +{
 +	struct packed_rrset_data* d, *old = rrset->data;
 +	size_t i;
 +	if(index >= old->count + old->rrsig_count)
 +		return 0; /* index out of bounds */
 +	d = (struct packed_rrset_data*)calloc(1, packed_rrset_sizeof(old) - (
 +		sizeof(size_t) + sizeof(uint8_t*) + sizeof(time_t) +
 +		old->rr_len[index]));
 +	if(!d) {
 +		log_err("malloc failure");
 +		return 0;
 +	}
 +	d->ttl = old->ttl;
 +	d->count = old->count;
 +	d->rrsig_count = old->rrsig_count;
 +	if(index < d->count) d->count--;
 +	else d->rrsig_count--;
 +	d->trust = old->trust;
 +	d->security = old->security;
 +
 +	/* set rr_len, needed for ptr_fixup */
 +	d->rr_len = (size_t*)((uint8_t*)d +
 +		sizeof(struct packed_rrset_data));
 +	if(index > 0)
 +		memmove(d->rr_len, old->rr_len, (index)*sizeof(size_t));
 +	if(index+1 < old->count+old->rrsig_count)
 +		memmove(&d->rr_len[index], &old->rr_len[index+1],
 +		(old->count+old->rrsig_count - (index+1))*sizeof(size_t));
 +	packed_rrset_ptr_fixup(d);
 +
 +	/* move over ttls */
 +	if(index > 0)
 +		memmove(d->rr_ttl, old->rr_ttl, (index)*sizeof(time_t));
 +	if(index+1 < old->count+old->rrsig_count)
 +		memmove(&d->rr_ttl[index], &old->rr_ttl[index+1],
 +		(old->count+old->rrsig_count - (index+1))*sizeof(time_t));
 +	
 +	/* move over rr_data */
 +	for(i=0; i<d->count+d->rrsig_count; i++) {
 +		size_t oldi;
 +		if(i < index) oldi = i;
 +		else oldi = i+1;
 +		memmove(d->rr_data[i], old->rr_data[oldi], d->rr_len[i]);
 +	}
 +
 +	/* recalc ttl (lowest of remaining RR ttls) */
 +	if(d->count + d->rrsig_count > 0)
 +		d->ttl = d->rr_ttl[0];
 +	for(i=0; i<d->count+d->rrsig_count; i++) {
 +		if(d->rr_ttl[i] < d->ttl)
 +			d->ttl = d->rr_ttl[i];
 +	}
 +
 +	free(rrset->data);
 +	rrset->data = d;
*** 14663 LINES SKIPPED ***


More information about the dev-commits-src-main mailing list