File: [cvs.NetBSD.org] / src / external / mpl / bind / dist / lib / dns / view.c (download)
Revision 1.1.1.2 (vendor branch), Wed Jan 9 16:48:21 2019 UTC (5 years, 3 months ago) by christos
Branch: ISC
CVS Tags: bind-9-14-1, bind-9-13-7, bind-9-13-5-W1 Changes since 1.1.1.1: +200 -208
lines
Jump into the 9.13 train since the 9.12 train is about to expire (March 2019).
--- 9.13.5-W1 released ---
5113. [port] Fixed a Windows build error.
--- 9.13.5 released ---
5108. [bug] Named could fail to determine bottom of zone when
removing out of date keys leading to invalid NSEC
and NSEC3 records being added to the zone. [GL #771]
5107. [bug] 'host -U' did not work. [GL #769]
5106. [experimental] A new "plugin" mechanism has been added to allow
extension of query processing functionality through
the use of dynamically loadable libraries. A
"filter-aaaa.so" plugin has been implemented,
replacing the filter-aaaa feature that was formerly
implemented as a native part of BIND.
The "filter-aaaa", "filter-aaaa-on-v4" and
"filter-aaaa-on-v6" options can no longer be
configured using native named.conf syntax. However,
loading the filter-aaaa.so plugin and setting its
parameters provides identical functionality.
Note that the plugin API is a work in progress and
is likely to evolve as further plugins are
implemented. [GL #15]
5105. [bug] Fix a race between process_fd and socketclose in
unix socket code. [GL #744]
5104. [cleanup] Log clearer informational message when a catz zone
is overridden by a zone in named.conf.
Thanks to Tony Finch. [GL !1157]
5103. [bug] Add missing design by contract tests to dns_catz*.
[GL #748]
5102. [bug] dnssec-coverage failed to use the default TTL when
checking KSK deletion times leading to a exception.
[GL #585]
5101. [bug] Fix default installation path for Python modules and
remove the dnspython dependency accidentally introduced
by change 4970. [GL #730]
5100. [func] Pin resolver tasks to specific task queues. [GL !1117]
5099. [func] Failed mutex and conditional creations are always
fatal. [GL #674]
--- 9.13.4 released ---
5098. [func] Failed memory allocations are now fatal. [GL #674]
5097. [cleanup] Remove embedded ATF unit testing framework
from BIND source distribution. [GL !875]
5096. [func] Use multiple event loops in socket code, and
make network threads CPU-affinitive. This
significantly improves performance on large
systems. [GL #666]
5095. [test] Converted all unit tests from ATF to CMocka;
removed the source code for the ATF libraries.
Build with "configure --with-cmocka" to enable
unit testing. [GL #620]
5094. [func] Add 'dig -r' to disable reading of .digrc. [GL !970]
5093. [bug] Log lame qname-minimization servers only if they're
really lame. [GL #671]
5092. [bug] Address memory leak on SIGTERM in nsupdate when using
GSS-TSIG. [GL #558]
5091. [func] Two new global and per-view options min-cache-ttl
and min-ncache-ttl [GL #613]
5090. [bug] dig and mdig failed to properly preparse dash value
pairs when value was a seperate argument and started
with a dash. [GL #584]
5089. [bug] Restore localhost fallback in dig and host which is
used when no nameserver addresses present in
/etc/resolv.conf are usable due to the requested
address family restrictions. [GL #433]
5088. [bug] dig/host/nslookup could crash when interrupted close to
a query timeout. [GL #599]
5087. [test] Check that result tables are complete. [GL #676]
5086. [func] Log of RPZ now includes the QTYPE and QCLASS. [GL #623]
5085. [bug] win32: Restore looking up nameservers, search list,
etc. [GL #186]
5084. [placeholder]
5083. [func] Add autoconf macro AX_POSIX_SHELL, so we
can use POSIX-compatible shell features
in the scripts.
5082. [bug] Fixed a race that could cause a crash in
dig/host/nslookup. [GL #650]
5081. [func] Use per-worker queues in task manager, make task
runners CPU-affine. [GL #659]
5080. [func] Improvements to "rndc nta" user interface:
- catch and report invalid command line options
- when removing an NTA from all views, do not
abort with an error if the NTA was not found
in one of the views
- include the view name in "rndc nta -dump"
output, for consistency with the add and remove
actions
Thanks to Tony Finch. [GL !816]
5079. [func] Disable IDN processing in dig and nslookup
when not on a tty. [GL #653]
5078. [cleanup] Require python components to be explicitly disabled if
python is not available on unix platforms. [GL #601]
5077. [cleanup] Remove ip6.int support (-i) from dig and mdig.
[GL !969]
5076. [bug] "require-server-cookie" was not effective if
"rate-limit" was configured. [GL #617]
5075. [bug] Refresh nameservers from cache when sending final
query in qname minimization. [GL #16]
5074. [cleanup] Remove vector socket functions - isc_socket_recvv(),
isc_socket_sendtov(), isc_socket_sendtov2(),
isc_socket_sendv() - in order to simplify socket code.
[GL #645]
5073. [bug] Destroy a task first when destroying rpzs and catzs.
[GL #84]
5072. [bug] Add unit tests for isc_buffer_copyregion() and fix its
behavior for auto-reallocated buffers. [GL #644]
5071. [bug] Comparision of NXT records was broken. [GL #631]
5070. [bug] Record types which support a empty rdata field were
not handling the empty rdata field case. [GL #638]
5069. [bug] Fix a hang on in RPZ when named is shutdown during RPZ
zone update. [GL !907]
5068. [bug] Fix a race in RPZ with min-update-interval set to 0.
[GL #643]
5067. [bug] Don't minimize qname when sending the query
to a forwarder. [GL #361]
5066. [cleanup] Allow unquoted strings to be used as a zone names
in response-policy statements. [GL #641]
5065. [bug] Only set IPV6_USE_MIN_MTU on IPv6. [GL #553]
5064. [test] Initalize TZ environment variable before calling
dns_test_begin in dnstap_test. [GL #624]
5063. [test] In statschannel test try a few times before failing
when checking if the compressed output is the same as
uncompressed. [GL !909]
5062. [func] Use non-crypto-secure PRNG to generate nonces for
cookies. [GL !887]
5061. [protocol] Add support for EID and NIMLOC. [GL #626]
5060. [bug] GID, UID and UINFO could not be loaded using unknown
record format. [GL #627]
5059. [bug] Display a per-view list of zones in the web interface.
[GL #427]
5058. [func] Replace old message digest and hmac APIs with more
generic isc_md and isc_hmac APIs, and convert their
respective tests to cmocka. [GL #305]
5057. [protocol] Add support for ATMA. [GL #619]
5056. [placeholder]
5055. [func] A default list of primary servers for the root zone is
now built into named, allowing the "masters" statement
to be omitted when configuring an IANA root zone
mirror. [GL #564]
5054. [func] Attempts to use mirror zones with recursion disabled
are now considered a configuration error. [GL #564]
5053. [func] The only valid zone-level NOTIFY settings for mirror
zones are now "notify no;" and "notify explicit;".
[GL #564]
5052. [func] Mirror zones are now configured using "type mirror;"
rather than "mirror yes;". [GL #564]
5051. [doc] Documentation incorrectly stated that the
"server-addresses" static-stub zone option accepts
custom port numbers. [GL #582]
5050. [bug] The libirs version of getaddrinfo() was unable to parse
scoped IPv6 addresses present in /etc/resolv.conf.
[GL #187]
5049. [cleanup] QNAME minimization has been deeply refactored. [GL #16]
5048. [func] Add configure option to enable and enforce FIPS mode
in BIND 9. [GL #506]
5047. [bug] Messages logged for certain query processing failures
now include a more specific error description if it is
available. [GL #572]
5046. [bug] named could crash during shutdown if an RPZ
reload was in progress. [RT #46210]
5045. [func] Remove support for DNSSEC algorithms 3 (DSA)
and 6 (DSA-NSEC3-SHA1). [GL #22]
5044. [cleanup] If "dnssec-enable" is no, then "dnssec-validation"
now also defaults to no. [GL #388]
5043. [bug] Fix creating and validating EdDSA signatures. [GL #579]
5042. [test] Make the chained delegations in reclimit behave
like they would in a regular name server. [GL #578]
5041. [test] The chain test contains a incomplete delegation.
[GL #568]
5040. [func] Extended dnstap so that it can log UPDATE requests
and responses as separate message types. Thanks
to Greg Rabil. [GL #570]
5039. [bug] Named could fail to preserve owner name case of new
RRset. [GL #420]
5038. [bug] Chaosnet addresses were compared incorrectly.
[GL #562]
5037. [func] "allow-recursion-on" and "allow-query-cache-on"
each now default to the other if only one of them
is set, in order to be more consistent with the way
"allow-recursion" and "allow-query-cache" work.
Also we now ensure that both query-cache ACLs are
checked when determining cache access. [GL #319]
5036. [cleanup] Fixed a spacing/formatting error in some RPZ-related
error messages in the log. [GL !805]
5035. [test] Fixed errors that prevented the DNSRPS subtests
from running in the rpz and rpzrecurse system
tests. [GL #503]
5034. [bug] A race between threads could prevent zone maintenance
scheduled immediately after zone load from being
performed. [GL #542]
5033. [bug] When adding NTAs to multiple views using "rndc nta",
the text returned via rndc was incorrectly terminated
after the first line, making it look as if only one
NTA had been added. Also, it was not possible to
differentiate between views with the same name but
different classes; this has been corrected with the
addition of a "-class" option. [GL #105]
5032. [func] Add krb5-selfsub and ms-selfsub update policy rules.
[GL #511]
5031. [cleanup] Various defines in platform.h has been either dropped
if always or never triggered on supported platforms
or replaced with config.h equivalents if the defines
didn't have any impact on public headers. Workarounds
for LinuxThreads have been removed because NPTL is
available since Linux kernel 2.6.0. [GL #525]
5030. [bug] Align CMSG buffers to a 64-bit boundary, fixes crash
on architectures with strict alignment. [GL #521]
--- 9.13.3 released ---
5029. [func] Workarounds for servers that misbehave when queried
with EDNS have been removed, because these broken
servers and the workarounds for their noncompliance
cause unnecessary delays, increase code complexity,
and prevent deployment of new DNS features. See
https://dnsflagday.net for further details. [GL #150]
5028. [bug] Spread the initial RRSIG expiration times over the
entire working sig-validity-interval when signing a
zone in named to even out re-signing and transfer
loads. [GL #418]
5027. [func] Set SO_SNDBUF size on sockets. [GL #74]
5026. [bug] rndc reconfig should not touch already loaded zones.
[GL #276]
5025. [cleanup] Remove isc_keyboard family of functions. [GL #178]
5024. [func] Replace custom assembly for atomic operations with
atomic support from the compiler. The code will now use
C11 stdatomic, or __atomic, or __sync builtins with GCC
or Clang compilers, and Interlocked functions with MSVC.
[GL #10]
5023. [cleanup] Remove wrappers that try to fix broken or incomplete
implementations of IPv6, pthreads and other core
functionality required and used by BIND. [GL #192]
5022. [doc] Update ms-self, ms-subdomain, krb5-self, and
krb5-subdomain documentation. [GL !708]
5021. [bug] dig returned a non-zero exit code when it received a
reply over TCP after a retry. [GL #487]
5020. [func] RNG uses thread-local storage instead of locks, if
supported by platform. [GL #496]
5019. [cleanup] A message is now logged when ixfr-from-differences is
set at zone level for an inline-signed zone. [GL #470]
5018. [bug] Fix incorrect sizeof arguments in lib/isc/pk11.c.
[GL !588]
5017. [bug] lib/isc/pk11.c failed to unlink the session before
releasing the lock which is unsafe. [GL !589]
5016. [bug] Named could assert with overlapping filter-aaaa and
dns64 acls. [GL #445]
5015. [bug] Reloading all zones caused zone maintenance to cease
for inline-signed zones. [GL #435]
5014. [bug] Signatures loaded from the journal for the signed
version of an inline-signed zone were not scheduled for
refresh. [GL #482]
5013. [bug] A referral response with a non-empty ANSWER section was
inadvertently being treated as an error. [GL #390]
5012. [bug] Fix lock order reversal in pk11_initialize. [GL !590]
5011. [func] Remove support for unthreaded named. [GL #478]
5010. [func] New "validate-except" option specifies a list of
domains beneath which DNSSEC validation should not
be performed. [GL #237]
5009. [bug] Upon an OpenSSL failure, the first error in the OpenSSL
error queue was not logged. [GL #476]
5008. [bug] "rndc signing -nsec3param ..." requests were silently
ignored for zones which were not yet loaded or
transferred. [GL #468]
5007. [cleanup] Replace custom ISC boolean and integer data types
with C99 stdint.h and stdbool.h types. [GL #9]
5006. [cleanup] Code preparing a delegation response was extracted from
query_delegation() and query_zone_delegation() into a
separate function in order to decrease code
duplication. [GL #431]
5005. [bug] dnssec-verify, and dnssec-signzone at the verification
step, failed on some validly signed zones. [GL #442]
5004. [bug] 'rndc reconfig' could cause inline zones to stop
re-signing. [GL #439]
5003. [bug] dns_acl_isinsecure did not handle geoip elements.
[GL #406]
5002. [bug] mdig: Handle malformed +ednsopt option, support 100
+ednsopt options per query rather than 100 total and
address memory leaks if +ednsopt was specified.
[GL #410]
5001. [bug] Fix refcount errors on error paths. [GL !563]
5000. [bug] named_server_servestale() could leave the server in
exclusive mode if an error occured. [GL #441]
4999. [cleanup] Remove custom printf implementation in lib/isc/print.c.
[GL #261]
4998. [test] Make resolver and cacheclean tests more civilized.
4997. [security] named could crash during recursive processing
of DNAME records when "deny-answer-aliases" was
in use. (CVE-2018-5740) [GL #387]
4996. [bug] dig: Handle malformed +ednsopt option. [GL #403]
4995. [test] Add tests for "tcp-self" update policy. [GL !282]
4994. [bug] Trust anchor telemetry queries were not being sent
upstream for locally served zones. [GL #392]
4993. [cleanup] Remove support for silently ignoring 'no-change' deltas
from BIND 8 when processing an IXFR stream. 'no-change'
deltas will now trigger a fallback to AXFR as the
recovery mechanism. [GL #369]
4992. [bug] The wrong address was being logged for trust anchor
telemetry queries. [GL #379]
4991. [bug] "rndc reconfig" was incorrectly handling zones whose
"mirror" setting was changed. [GL #381]
4990. [bug] Prevent a possible NULL reference in pkcs11-keygen.
[GL #401]
4989. [cleanup] IDN support in dig has been reworked. IDNA2003
fallbacks were removed in the process. [GL #384]
4988. [bug] Don't synthesize NXDOMAIN from NSEC for records under
a DNAME.
--- 9.13.2 released ---
4987. [cleanup] dns_rdataslab_tordataset() and its related
dns_rdatasetmethods_t callbacks were removed as they
were not being used by anything in BIND. [GL #371]
4986. [func] When built on Linux, BIND now requires the libcap
library to set process privileges, unless capability
support is explicitly overridden with "configure
--disable-linux-caps". [GL #321]
4985. [func] Add a new slave zone option, "mirror", to enable
serving a non-authoritative copy of a zone that
is subject to DNSSEC validation before being
used. For now, this option is only meant to
facilitate deployment of an RFC 7706-style local
copy of the root zone. [GL #33]
4984. [bug] Improve handling of very large incremental
zone transfers to prevent journal corruption. [GL #339]
4983. [func] Add the ability to not return a DNS COOKIE option
when one is present in the request (answer-cookie no;).
[GL #173]
4982. [cleanup] Return FORMERR if the question section is empty
and no COOKIE option is present; this restores
older behavior except in the newly specified
COOKIE case. [GL #260]
4981. [bug] Fix race in cmsg buffer usage in socket code.
[GL #180]
4980. [bug] Named-checkconf failed to detect bad in-view targets.
[GL #288]
4979. [placeholder]
4978. [test] Fix error handling and resolver configuration in the
"rpz" system test. [GL #312]
4977. [func] When starting up, log the same details that
would be reported by 'named -V'. [GL #247]
4976. [bug] Log the label with invalid prefix length correctly
when loading RPZ zones. [GL #254]
4975. [bug] The server cookie computation for sha1 and sha256 did
not match the method described in RFC 7873. [GL #356]
4974. [bug] Restore default rrset-order to random. [GL #336]
4973. [func] verifyzone() and the functions it uses were moved to
libdns and refactored to prevent exit() from being
called upon failure. A side effect of that is that
dnssec-signzone and dnssec-verify now check for memory
leaks upon shutdown. [GL #266]
4972. [func] Declare the 'rdata' argument for dns_rdata_tostruct()
to be const. [GL #341]
4971. [bug] dnssec-signzone and dnssec-verify did not treat records
below a DNAME as out-of-zone data. [GL #298]
4970. [func] Add QNAME minimization option to resolver. [GL #16]
4969. [cleanup] Refactor zone logging functions. [GL #269]
--- 9.13.1 released ---
4968. [bug] If glue records are signed, attempt to validate them.
[GL #209]
4967. [cleanup] Add "answer-cookie" to the parser, marked obsolete.
4966. [placeholder]
4965. [func] Add support for marking options as deprecated.
[GL #322]
4964. [bug] Reduce the probabilty of double signature when deleting
a DNSKEY by checking if the node is otherwise signed
by the algorithm of the key to be deleted. [GL #240]
4963. [test] ifconfig.sh now uses "ip" instead of "ifconfig",
if available, to configure the test interfaces on
linux. [GL #302]
4962. [cleanup] Move 'named -T' processing to its own function.
[GL #316]
4961. [protocol] Remove support for ECC-GOST (GOST R 34.11-94).
[GL #295]
4960. [security] When recursion is enabled, but the "allow-recursion"
and "allow-query-cache" ACLs are not specified,
they should be limited to local networks,
but were inadvertently set to match the default
"allow-query", thus allowing remote queries.
(CVE-2018-5738) [GL #309]
4959. [func] NSID logging (enabled by the "request-nsid" option)
now has its own "nsid" category, instead of using the
"resolver" category. [GL !332]
4958. [bug] Remove redundant space from NSEC3 record. [GL #281]
4957. [func] The default setting for "dnssec-validation" is now
"auto", which activates DNSSEC validation using the
IANA root key. (The default can be changed back to
"yes", which activates DNSSEC validation only when keys
are explicitly configured in named.conf, by building
BIND with "configure --disable-auto-validation".)
[GL #30]
4956. [func] Change isc_random() to be just PRNG using xoshiro128**,
and add isc_nonce_buf() that uses CSPRNG. [GL #289]
4955. [cleanup] Silence cppcheck warnings in lib/dns/master.c.
[GL #286]
4954. [func] Messages about serving of stale answers are now
directed to the "serve-stale" logging category.
Also clarified serve-stale documentation. [GL !323]
4953. [bug] Removed the option to build the red black tree
database without a hash table; the non-hashing
version was buggy and is not needed. [GL #184]
4952. [func] Authoritative server support in named for the
EDNS CLIENT-SUBNET option (which was experimental
and not practical to deploy) has been removed.
The ECS option is still supported in dig and mdig
via the +subnet option, and can be parsed and logged
when received by named, but it is no longer used
for ACL processing. The "geoip-use-ecs" option
is now obsolete; a warning will be logged if it is
used in named.conf. "ecs" tags in an ACL definition
are also obsolete and will cause the configuration
to fail to load. [GL #32]
4951. [protocol] Add "HOME.ARPA" to list of built in empty zones as
per RFC 8375. [GL #273]
--- 9.13.0 released ---
4950. [bug] ISC_SOCKEVENTATTR_TRUNC was not be set. [GL #238]
4949. [placeholder]
4948. [bug] When request-nsid is turned on, EDNS NSID options
should be logged at level info. Since change 3741
they have been logged at debug(3) by mistake.
[GL !290]
4947. [func] Replace all random functions with isc_random(),
isc_random_buf() and isc_random_uniform() API.
[GL #221]
4946. [bug] Additional glue was not being returned by resolver
for unsigned zones since change 4596. [GL #209]
4945. [func] BIND can no longer be built without DNSSEC support.
A cryptography provder (i.e., OpenSSL or a hardware
service module with PKCS#11 support) must be
available. [GL #244]
4944. [cleanup] Silence cppcheck portability warnings in
lib/isc/tests/buffer_test.c. [GL #239]
4943. [bug] Change 4687 consumed too much memory when running
system tests with --with-tuning=large. Reduced the
hash table size to 512 entries for 'named -m record'
restoring the previous memory footprint. [GL #248]
4942. [cleanup] Consolidate multiple instances of splitting of
batchline in dig into a single function. [GL #196]
4941. [cleanup] Silence clang static analyzer warnings. [GL #196]
4940. [cleanup] Extract the loop in dns__zone_updatesigs() into
separate functions to improve code readability.
[GL #135]
4939. [test] Add basic unit tests for update_sigs(). [GL #135]
4938. [placeholder]
4937. [func] Remove support for OpenSSL < 1.0.0 [GL #191]
4936. [func] Always use OpenSSL or PKCS#11 random data providers,
and remove the --{enable,disable}-crypto-rand configure
options. [GL #165]
4935. [func] Add support for LibreSSL >= 2.7.0 (some OpenSSL 1.1.0
call were added). [GL #191]
4934. [security] The serve-stale feature could cause an assertion failure
in rbtdb.c even when stale-answer-enable was false.
Simultaneous use of stale cache records and NSEC
aggressive negative caching could trigger a recursion
loop. (CVE-2018-5737) [GL #185]
4933. [bug] Not creating signing keys for an inline signed zone
prevented changes applied to the raw zone from being
reflected in the secure zone until signing keys were
made available. [GL #159]
4932. [bug] Bumped signed serial of an inline signed zone was
logged even when an error occurred while updating
signatures. [GL #159]
4931. [func] Removed the "rbtdb64" database implementation.
[GL #217]
4930. [bug] Remove a bogus check in nslookup command line
argument processing. [GL #206]
4929. [func] Add the ability to set RA and TC in queries made by
dig (+[no]raflag, +[no]tcflag). [GL #213]
4928. [func] The "dnskey-sig-validity" option allows
"sig-validity-interval" to be overriden for signatures
covering DNSKEY RRsets. [GL #145]
4927. [placeholder]
4926. [func] Add root key sentinel support. To disable, add
'root-key-sentinel no;' to named.conf. [GL #37]
4925. [func] Several configuration options that define intervals
can now take TTL value suffixes (for example, 2h or 1d)
in addition to integer parameters. These include
max-cache-ttl, max-ncache-ttl, max-policy-ttl,
fstrm-set-reopen-interval, interface-interval, and
min-update-interval. [GL #203]
4924. [cleanup] Clean up the isc_string_* namespace and leave
only strlcpy and strlcat. [GL #178]
4923. [cleanup] Refactor socket and socket event options into
enum types. [GL !135]
4922. [bug] dnstap: Log the destination address of client
packets rather than the interface address.
[GL #197]
4921. [cleanup] Add dns_fixedname_initname() and refactor the caller
code to make usage of the new function, as a part of
refactoring dns_fixedname_*() macros were turned into
functions. [GL #183]
4920. [cleanup] Clean up libdns removing most of the backwards
compatibility wrappers.
4919. [cleanup] Clean up the isc_hash_* namespace and leave only
the FNV-1a hash implementation. [GL #178]
4918. [bug] Fix double free after keygen error in dnssec-keygen
when OpenSSL >= 1.1.0 is used and RSA_generate_key_ex
fails. [GL #109]
4917. [func] Support 64 RPZ policy zones by default. [GL #123]
4916. [func] Remove IDNA2003 support and the bundled idnkit-1.0
library.
4915. [func] Implement IDNA2008 support in dig by adding support
for libidn2. New dig option +idnin has been added,
which allows to process invalid domain names much
like dig without IDN support. libidn2 version 2.0
or higher is needed for +idnout enabled by default.
4914. [security] A bug in zone database reference counting could lead to
a crash when multiple versions of a slave zone were
transferred from a master in close succession.
(CVE-2018-5736) [GL #134]
4913. [test] Re-implemented older unit tests in bin/tests as ATF,
removed the lib/tests unit testing library. [GL #115]
4912. [test] Improved the reliability of the 'cds' system test.
[GL #136]
4911. [test] Improved the reliability of the 'mkeys' system test.
[GL #128]
4910. [func] Update util/check-changes to work on release branches.
[GL #113]
4909. [bug] named-checkconf did not detect in-view zone collisions.
[GL #125]
4908. [test] Eliminated unnecessary waiting in the allow_query
system test. Also changed its name to allow-query.
[GL #81]
4907. [test] Improved the reliability of the 'notify' system
test. [GL #59]
4906. [func] Replace getquad() with inet_pton(), completing
change #4900. [GL #56]
4905. [bug] irs_resconf_load() ignored resolv.conf syntax errors
when "domain" or "search" options were present in that
file. [GL #110]
4904. [bug] Temporarily revert change #4859. [GL #124]
4903. [bug] "check-mx fail;" did not prevent MX records containing
IP addresses from being added to a zone by a dynamic
update. [GL #112]
4902. [test] Improved the reliability of the 'ixfr' system
test. [GL #66]
4901. [func] "dig +nssearch" now lists the name servers
for a domain that time out, as well as the servers
that respond. [GL #64]
4900. [func] Remove all uses of inet_aton(). As a result of this
change, IPv4 addresses are now only accepted in
dotted-quad format. [GL #13]
4899. [test] Convert most of the remaining system tests to be able
to run in parallel, continuing the work from change
#4895. To take advantage of this, use "make -jN check",
where N is the number of processors to use. [GL #91]
4898. [func] Remove libseccomp based system-call filtering. [GL #93]
4897. [test] Update to rpz system test so that it doesn't recurse.
[GL #68]
4896. [test] cacheclean system test was not robust. [GL #82]
4895. [test] Allow some system tests to run in parallel.
[RT #46602]
4894. [bug] named could crash while rolling a dnstap output file.
[RT #46942]
4893. [bug] Address various issues reported by cppcheck. [GL #51]
4892. [bug] named could leak memory when "rndc reload" was invoked
before all zone loading actions triggered by a previous
"rndc reload" command were completed. [RT #47076]
4891. [placeholder]
4890. [func] Remove unused ondestroy callback from libisc.
[isc-projects/bind9!3]
4889. [func] Warn about the use of old root keys without the new
root key being present. Warn about dlv.isc.org's
key being present. Warn about both managed and
trusted root keys being present. [RT #43670]
4888. [test] Initialize sockets correctly in sample-update so
that the nsupdate system test will run on Windows.
[RT #47097]
4887. [test] Enable the rpzrecurse test to run on Windows.
[RT #47093]
4886. [doc] Document dig -u in manpage. [RT #47150]
4885. [security] update-policy rules that otherwise ignore the name
field now require that it be set to "." to ensure
that any type list present is properly interpreted.
[RT #47126]
4884. [bug] named could crash on shutdown due to a race between
shutdown_server() and ns__client_request(). [RT #47120]
4883. [cleanup] Improved debugging output from dnssec-cds. [RT #47026]
4882. [bug] Address potential memory leak in
dns_update_signaturesinc. [RT #47084]
4881. [bug] Only include dst_openssl.h when OpenSSL is required.
[RT #47068]
4880. [bug] Named wasn't returning the target of a cross-zone
CNAME between two served zones when recursion was
desired and available (RD=1, RA=1). (When this is
not the case, the CNAME target is deliberately
withheld to prevent accidental cache poisoning.)
[RT #47078]
4879. [bug] dns_rdata_caa:value_len field was too small.
[RT #47086]
4878. [bug] List 'ply' as a requirement for the 'isc' python
package. [RT #47065]
4877. [bug] Address integer overflow when exponentially
backing off retry intervals. [RT #47041]
4876. [bug] Address deadlock with accessing a keytable. [RT #47000]
4875. [bug] Address compile failures on older systems. [RT #47015]
4874. [bug] Wrong time display when reporting new keywarntime.
[RT #47042]
4873. [doc] Grammars for named.conf included in the ARM are now
automatically generated by the configuration parser
itself. As a side effect of the work needed to
separate zone type grammars from each other, this
also makes checking of zone statements in
named-checkconf more correct and consistent.
[RT #36957]
4872. [bug] Don't permit loading meta RR types such as TKEY
from master files. [RT #47009]
4871. [bug] Fix configure glitch in detecting stdatomic.h
support on systems with multiple compilers.
[RT #46959]
4870. [test] Update included ATF library to atf-0.21 preserving
the ATF tool. [RT #46967]
4869. [bug] Address some cases where NULL with zero length could
be passed to memmove which is undefined behavior and
can lead to bad optimization. [RT #46888]
4868. [func] dnssec-keygen can no longer generate HMAC keys.
Use tsig-keygen instead. [RT #46404]
4867. [cleanup] Normalize rndc on/off commands (validation,
querylog, serve-stale) so they all accept the
same synonyms for on/off (yes/no, true/false,
enable/disable). Thanks to Tony Finch. [RT #47022]
4866. [port] DST library initialization verifies MD5 (when MD5
was not disabled) and SHA-1 hash and HMAC support.
[RT #46764]
4865. [cleanup] Simplify handling isc_socket_sendto2() return values.
[RT #46986]
4864. [bug] named acting as a slave for a catalog zone crashed if
the latter contained a master definition without an IP
address. [RT #45999]
4863. [bug] Fix various other bugs reported by Valgrind's
memcheck tool. [RT #46978]
4862. [bug] The rdata flags for RRSIG were not being properly set
when constructing a rdataslab. [RT #46978]
4861. [bug] The isc_crc64 unit test was not endian independent.
[RT #46973]
4860. [bug] isc_int8_t should be signed char. [RT #46973]
4859. [bug] A loop was possible when attempting to validate
unsigned CNAME responses from secure zones;
this caused a delay in returning SERVFAIL and
also increased the chances of encountering
CVE-2017-3145. [RT #46839]
4858. [security] Addresses could be referenced after being freed
in resolver.c, causing an assertion failure.
(CVE-2017-3145) [RT #46839]
4857. [bug] Maintain attach/detach semantics for event->db,
event->node, event->rdataset and event->sigrdataset
in query.c. [RT #46891]
4856. [bug] 'rndc zonestatus' reported the wrong underlying type
for a inline slave zone. [RT #46875]
4855. [bug] isc_time_formatshorttimestamp produced incorrect
output. [RT #46938]
4854. [bug] query_synthcnamewildcard should stop generating the
response if query_synthwildcard fails. [RT #46939]
4853. [bug] Add REQUIRE's and INSIST's to isc_time_formatISO8601L
and isc_time_formatISO8601Lms. [RT #46916]
4852. [bug] Handle strftime() failing in isc_time_formatISO8601ms.
Add REQUIRE's and INSIST's to isc_time_formattimestamp,
isc_time_formathttptimestamp, isc_time_formatISO8601,
isc_time_formatISO8601ms. [RT #46892]
4851. [port] Support using kyua as well as atf-run to run the unit
tests. [RT #46853]
4850. [bug] Named failed to restart with multiple added zones in
lmdb database. [RT #46889]
4849. [bug] Duplicate zones could appear in the .nzf file if
addzone failed. [RT #46435]
4848. [func] Zone types "primary" and "secondary" can now be used
as synonyms for "master" and "slave" in named.conf.
[RT #46713]
4847. [bug] dnssec-dnskey-kskonly was not being honored for
CDS and CDNSKEY. [RT #46755]
4846. [test] Adjust timing values in runtime system test. Address
named.pid removal races in runtime system test.
[RT #46800]
4845. [bug] Dig (non iOS) should exit on malformed names.
[RT #46806]
4844. [test] Address memory leaks in libatf-c. [RT #46798]
4843. [bug] dnssec-signzone free hashlist on exit. [RT #46791]
4842. [bug] Conditionally compile opensslecdsa_link.c to avoid
warnings about unused function. [RT #46790]
|
/* $NetBSD: view.c,v 1.1.1.2 2019/01/09 16:48:21 christos Exp $ */
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* 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 http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*! \file */
#include <config.h>
#include <limits.h>
#include <inttypes.h>
#include <stdbool.h>
#ifdef HAVE_LMDB
#include <lmdb.h>
#endif
#include <isc/file.h>
#include <isc/hash.h>
#include <isc/lex.h>
#include <isc/print.h>
#include <isc/stats.h>
#include <isc/string.h> /* Required for HP/UX (and others?) */
#include <isc/task.h>
#include <isc/util.h>
#include <dns/acl.h>
#include <dns/adb.h>
#include <dns/badcache.h>
#include <dns/cache.h>
#include <dns/db.h>
#include <dns/dispatch.h>
#include <dns/dlz.h>
#include <dns/dns64.h>
#include <dns/dnssec.h>
#include <dns/events.h>
#include <dns/forward.h>
#include <dns/keytable.h>
#include <dns/keyvalues.h>
#include <dns/master.h>
#include <dns/masterdump.h>
#include <dns/nta.h>
#include <dns/order.h>
#include <dns/peer.h>
#include <dns/rbt.h>
#include <dns/rdataset.h>
#include <dns/request.h>
#include <dns/resolver.h>
#include <dns/result.h>
#include <dns/rpz.h>
#include <dns/rrl.h>
#include <dns/stats.h>
#include <dns/time.h>
#include <dns/tsig.h>
#include <dns/zone.h>
#include <dns/zt.h>
#define CHECK(op) \
do { result = (op); \
if (result != ISC_R_SUCCESS) goto cleanup; \
} while (0)
#define RESSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_RESSHUTDOWN) != 0)
#define ADBSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0)
#define REQSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0)
#define DNS_VIEW_DELONLYHASH 111
#define DNS_VIEW_FAILCACHESIZE 1021
static void resolver_shutdown(isc_task_t *task, isc_event_t *event);
static void adb_shutdown(isc_task_t *task, isc_event_t *event);
static void req_shutdown(isc_task_t *task, isc_event_t *event);
isc_result_t
dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
const char *name, dns_view_t **viewp)
{
dns_view_t *view;
isc_result_t result;
char buffer[1024];
/*
* Create a view.
*/
REQUIRE(name != NULL);
REQUIRE(viewp != NULL && *viewp == NULL);
view = isc_mem_get(mctx, sizeof(*view));
if (view == NULL)
return (ISC_R_NOMEMORY);
view->nta_file = NULL;
view->mctx = NULL;
isc_mem_attach(mctx, &view->mctx);
view->name = isc_mem_strdup(mctx, name);
if (view->name == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup_view;
}
result = isc_file_sanitize(NULL, view->name, "nta",
buffer, sizeof(buffer));
if (result != ISC_R_SUCCESS)
goto cleanup_name;
view->nta_file = isc_mem_strdup(mctx, buffer);
if (view->nta_file == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup_name;
}
isc_mutex_init(&view->lock);
view->zonetable = NULL;
result = dns_zt_create(mctx, rdclass, &view->zonetable);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"dns_zt_create() failed: %s",
isc_result_totext(result));
result = ISC_R_UNEXPECTED;
goto cleanup_mutex;
}
view->secroots_priv = NULL;
view->ntatable_priv = NULL;
view->fwdtable = NULL;
result = dns_fwdtable_create(mctx, &view->fwdtable);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"dns_fwdtable_create() failed: %s",
isc_result_totext(result));
result = ISC_R_UNEXPECTED;
goto cleanup_zt;
}
view->cache = NULL;
view->cachedb = NULL;
ISC_LIST_INIT(view->dlz_searched);
ISC_LIST_INIT(view->dlz_unsearched);
view->hints = NULL;
view->resolver = NULL;
view->adb = NULL;
view->requestmgr = NULL;
view->rdclass = rdclass;
view->frozen = false;
view->task = NULL;
isc_refcount_init(&view->references, 1);
view->weakrefs = 0;
view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN|
DNS_VIEWATTR_REQSHUTDOWN);
view->statickeys = NULL;
view->dynamickeys = NULL;
view->matchclients = NULL;
view->matchdestinations = NULL;
view->matchrecursiveonly = false;
result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
if (result != ISC_R_SUCCESS)
goto cleanup_references;
view->peers = NULL;
view->order = NULL;
view->delonly = NULL;
view->rootdelonly = false;
view->rootexclude = NULL;
view->adbstats = NULL;
view->resstats = NULL;
view->resquerystats = NULL;
view->cacheshared = false;
ISC_LIST_INIT(view->dns64);
view->dns64cnt = 0;
/*
* Initialize configuration data with default values.
*/
view->recursion = true;
view->qminimization = false;
view->qmin_strict = false;
view->auth_nxdomain = false; /* Was true in BIND 8 */
view->enablednssec = true;
view->enablevalidation = true;
view->acceptexpired = false;
view->use_glue_cache = false;
view->minimal_any = false;
view->minimalresponses = dns_minimal_no;
view->transfer_format = dns_one_answer;
view->cacheacl = NULL;
view->cacheonacl = NULL;
view->queryacl = NULL;
view->queryonacl = NULL;
view->recursionacl = NULL;
view->recursiononacl = NULL;
view->sortlist = NULL;
view->transferacl = NULL;
view->notifyacl = NULL;
view->updateacl = NULL;
view->upfwdacl = NULL;
view->denyansweracl = NULL;
view->nocasecompress = NULL;
view->msgcompression = true;
view->answeracl_exclude = NULL;
view->denyanswernames = NULL;
view->answernames_exclude = NULL;
view->rrl = NULL;
view->provideixfr = true;
view->maxcachettl = 7 * 24 * 3600;
view->maxncachettl = 3 * 3600;
view->nta_lifetime = 0;
view->nta_recheck = 0;
view->prefetch_eligible = 0;
view->prefetch_trigger = 0;
view->dstport = 53;
view->preferred_glue = 0;
view->flush = false;
view->dlv = NULL;
view->maxudp = 0;
view->staleanswerttl = 1;
view->staleanswersok = dns_stale_answer_conf;
view->staleanswersenable = false;
view->nocookieudp = 0;
view->padding = 0;
view->pad_acl = NULL;
view->maxbits = 0;
view->rpzs = NULL;
view->catzs = NULL;
dns_fixedname_init(&view->dlv_fixed);
view->managed_keys = NULL;
view->redirect = NULL;
view->redirectzone = NULL;
dns_fixedname_init(&view->redirectfixed);
view->requestnsid = false;
view->sendcookie = true;
view->requireservercookie = false;
view->synthfromdnssec = true;
view->trust_anchor_telemetry = true;
view->root_key_sentinel = true;
view->new_zone_dir = NULL;
view->new_zone_file = NULL;
view->new_zone_db = NULL;
view->new_zone_dbenv = NULL;
view->new_zone_mapsize = 0ULL;
view->new_zone_config = NULL;
view->cfg_destroy = NULL;
view->fail_ttl = 0;
view->failcache = NULL;
result = dns_badcache_init(view->mctx, DNS_VIEW_FAILCACHESIZE,
&view->failcache);
if (result != ISC_R_SUCCESS) {
goto cleanup_dynkeys;
}
view->v6bias = 0;
view->dtenv = NULL;
view->dttypes = 0;
view->plugins = NULL;
view->plugins_free = NULL;
view->hooktable = NULL;
view->hooktable_free = NULL;
isc_mutex_init(&view->new_zone_lock);
result = dns_order_create(view->mctx, &view->order);
if (result != ISC_R_SUCCESS) {
goto cleanup_new_zone_lock;
}
result = dns_peerlist_new(view->mctx, &view->peers);
if (result != ISC_R_SUCCESS) {
goto cleanup_order;
}
result = dns_aclenv_init(view->mctx, &view->aclenv);
if (result != ISC_R_SUCCESS) {
goto cleanup_peerlist;
}
ISC_LINK_INIT(view, link);
ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL,
DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown,
view, NULL, NULL, NULL);
ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL,
DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown,
view, NULL, NULL, NULL);
ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL,
DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown,
view, NULL, NULL, NULL);
view->viewlist = NULL;
view->magic = DNS_VIEW_MAGIC;
*viewp = view;
return (ISC_R_SUCCESS);
cleanup_peerlist:
if (view->peers != NULL) {
dns_peerlist_detach(&view->peers);
}
cleanup_order:
if (view->order != NULL) {
dns_order_detach(&view->order);
}
cleanup_new_zone_lock:
isc_mutex_destroy(&view->new_zone_lock);
dns_badcache_destroy(&view->failcache);
cleanup_dynkeys:
if (view->dynamickeys != NULL) {
dns_tsigkeyring_detach(&view->dynamickeys);
}
cleanup_references:
INSIST(isc_refcount_decrement(&view->references) > 0);
isc_refcount_destroy(&view->references);
if (view->fwdtable != NULL) {
dns_fwdtable_destroy(&view->fwdtable);
}
cleanup_zt:
if (view->zonetable != NULL) {
dns_zt_detach(&view->zonetable);
}
cleanup_mutex:
isc_mutex_destroy(&view->lock);
if (view->nta_file != NULL) {
isc_mem_free(mctx, view->nta_file);
}
cleanup_name:
isc_mem_free(mctx, view->name);
cleanup_view:
isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
return (result);
}
static inline void
destroy(dns_view_t *view) {
dns_dns64_t *dns64;
dns_dlzdb_t *dlzdb;
REQUIRE(!ISC_LINK_LINKED(view, link));
REQUIRE(isc_refcount_current(&view->references) == 0);
REQUIRE(view->weakrefs == 0);
REQUIRE(RESSHUTDOWN(view));
REQUIRE(ADBSHUTDOWN(view));
REQUIRE(REQSHUTDOWN(view));
if (view->order != NULL)
dns_order_detach(&view->order);
if (view->peers != NULL)
dns_peerlist_detach(&view->peers);
if (view->dynamickeys != NULL) {
isc_result_t result;
char template[PATH_MAX];
char keyfile[PATH_MAX];
FILE *fp = NULL;
result = isc_file_mktemplate(NULL, template, sizeof(template));
if (result == ISC_R_SUCCESS) {
(void)isc_file_openuniqueprivate(template, &fp);
}
if (fp == NULL) {
dns_tsigkeyring_detach(&view->dynamickeys);
} else {
result = dns_tsigkeyring_dumpanddetach
(&view->dynamickeys, fp);
if (result == ISC_R_SUCCESS) {
if (fclose(fp) == 0) {
result = isc_file_sanitize
(NULL, view->name, "tsigkeys",
keyfile, sizeof(keyfile));
if (result == ISC_R_SUCCESS)
result = isc_file_rename
(template, keyfile);
}
if (result != ISC_R_SUCCESS)
(void)remove(template);
} else {
(void)fclose(fp);
(void)remove(template);
}
}
}
if (view->statickeys != NULL)
dns_tsigkeyring_detach(&view->statickeys);
if (view->adb != NULL)
dns_adb_detach(&view->adb);
if (view->resolver != NULL)
dns_resolver_detach(&view->resolver);
dns_rrl_view_destroy(view);
if (view->rpzs != NULL)
dns_rpz_detach_rpzs(&view->rpzs);
if (view->catzs != NULL)
dns_catz_catzs_detach(&view->catzs);
for (dlzdb = ISC_LIST_HEAD(view->dlz_searched);
dlzdb != NULL;
dlzdb = ISC_LIST_HEAD(view->dlz_searched)) {
ISC_LIST_UNLINK(view->dlz_searched, dlzdb, link);
dns_dlzdestroy(&dlzdb);
}
for (dlzdb = ISC_LIST_HEAD(view->dlz_unsearched);
dlzdb != NULL;
dlzdb = ISC_LIST_HEAD(view->dlz_unsearched)) {
ISC_LIST_UNLINK(view->dlz_unsearched, dlzdb, link);
dns_dlzdestroy(&dlzdb);
}
if (view->requestmgr != NULL)
dns_requestmgr_detach(&view->requestmgr);
if (view->task != NULL)
isc_task_detach(&view->task);
if (view->hints != NULL)
dns_db_detach(&view->hints);
if (view->cachedb != NULL)
dns_db_detach(&view->cachedb);
if (view->cache != NULL)
dns_cache_detach(&view->cache);
if (view->nocasecompress != NULL)
dns_acl_detach(&view->nocasecompress);
if (view->matchclients != NULL)
dns_acl_detach(&view->matchclients);
if (view->matchdestinations != NULL)
dns_acl_detach(&view->matchdestinations);
if (view->cacheacl != NULL)
dns_acl_detach(&view->cacheacl);
if (view->cacheonacl != NULL)
dns_acl_detach(&view->cacheonacl);
if (view->queryacl != NULL)
dns_acl_detach(&view->queryacl);
if (view->queryonacl != NULL)
dns_acl_detach(&view->queryonacl);
if (view->recursionacl != NULL)
dns_acl_detach(&view->recursionacl);
if (view->recursiononacl != NULL)
dns_acl_detach(&view->recursiononacl);
if (view->sortlist != NULL)
dns_acl_detach(&view->sortlist);
if (view->transferacl != NULL)
dns_acl_detach(&view->transferacl);
if (view->notifyacl != NULL)
dns_acl_detach(&view->notifyacl);
if (view->updateacl != NULL)
dns_acl_detach(&view->updateacl);
if (view->upfwdacl != NULL)
dns_acl_detach(&view->upfwdacl);
if (view->denyansweracl != NULL)
dns_acl_detach(&view->denyansweracl);
if (view->pad_acl != NULL)
dns_acl_detach(&view->pad_acl);
if (view->answeracl_exclude != NULL)
dns_rbt_destroy(&view->answeracl_exclude);
if (view->denyanswernames != NULL)
dns_rbt_destroy(&view->denyanswernames);
if (view->answernames_exclude != NULL)
dns_rbt_destroy(&view->answernames_exclude);
if (view->delonly != NULL) {
dns_name_t *name;
int i;
for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
name = ISC_LIST_HEAD(view->delonly[i]);
while (name != NULL) {
ISC_LIST_UNLINK(view->delonly[i], name, link);
dns_name_free(name, view->mctx);
isc_mem_put(view->mctx, name, sizeof(*name));
name = ISC_LIST_HEAD(view->delonly[i]);
}
}
isc_mem_put(view->mctx, view->delonly, sizeof(dns_namelist_t) *
DNS_VIEW_DELONLYHASH);
view->delonly = NULL;
}
if (view->rootexclude != NULL) {
dns_name_t *name;
int i;
for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
name = ISC_LIST_HEAD(view->rootexclude[i]);
while (name != NULL) {
ISC_LIST_UNLINK(view->rootexclude[i],
name, link);
dns_name_free(name, view->mctx);
isc_mem_put(view->mctx, name, sizeof(*name));
name = ISC_LIST_HEAD(view->rootexclude[i]);
}
}
isc_mem_put(view->mctx, view->rootexclude,
sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH);
view->rootexclude = NULL;
}
if (view->adbstats != NULL)
isc_stats_detach(&view->adbstats);
if (view->resstats != NULL)
isc_stats_detach(&view->resstats);
if (view->resquerystats != NULL)
dns_stats_detach(&view->resquerystats);
if (view->secroots_priv != NULL)
dns_keytable_detach(&view->secroots_priv);
if (view->ntatable_priv != NULL)
dns_ntatable_detach(&view->ntatable_priv);
for (dns64 = ISC_LIST_HEAD(view->dns64);
dns64 != NULL;
dns64 = ISC_LIST_HEAD(view->dns64)) {
dns_dns64_unlink(&view->dns64, dns64);
dns_dns64_destroy(&dns64);
}
if (view->managed_keys != NULL)
dns_zone_detach(&view->managed_keys);
if (view->redirect != NULL)
dns_zone_detach(&view->redirect);
#ifdef HAVE_DNSTAP
if (view->dtenv != NULL)
dns_dt_detach(&view->dtenv);
#endif /* HAVE_DNSTAP */
dns_view_setnewzones(view, false, NULL, NULL, 0ULL);
if (view->new_zone_file != NULL) {
isc_mem_free(view->mctx, view->new_zone_file);
view->new_zone_file = NULL;
}
if (view->new_zone_dir != NULL) {
isc_mem_free(view->mctx, view->new_zone_dir);
view->new_zone_dir = NULL;
}
#ifdef HAVE_LMDB
if (view->new_zone_dbenv != NULL) {
mdb_env_close((MDB_env *) view->new_zone_dbenv);
view->new_zone_dbenv = NULL;
}
if (view->new_zone_db != NULL) {
isc_mem_free(view->mctx, view->new_zone_db);
view->new_zone_db = NULL;
}
#endif /* HAVE_LMDB */
dns_fwdtable_destroy(&view->fwdtable);
dns_aclenv_destroy(&view->aclenv);
if (view->failcache != NULL)
dns_badcache_destroy(&view->failcache);
isc_mutex_destroy(&view->new_zone_lock);
isc_mutex_destroy(&view->lock);
isc_mem_free(view->mctx, view->nta_file);
isc_mem_free(view->mctx, view->name);
if (view->hooktable != NULL && view->hooktable_free != NULL) {
view->hooktable_free(view->mctx, &view->hooktable);
}
if (view->plugins != NULL && view->plugins_free != NULL) {
view->plugins_free(view->mctx, &view->plugins);
}
isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
}
/*
* Return true iff 'view' may be freed.
* The caller must be holding the view lock.
*/
static bool
all_done(dns_view_t *view) {
if (isc_refcount_current(&view->references) == 0 &&
view->weakrefs == 0 &&
RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view))
return (true);
return (false);
}
void
dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
REQUIRE(DNS_VIEW_VALID(source));
REQUIRE(targetp != NULL && *targetp == NULL);
isc_refcount_increment(&source->references);
*targetp = source;
}
static void
view_flushanddetach(dns_view_t **viewp, bool flush) {
REQUIRE(viewp != NULL && DNS_VIEW_VALID(*viewp));
dns_view_t *view = *viewp;
*viewp = NULL;
if (flush) {
view->flush = flush;
}
bool done = false;
if (isc_refcount_decrement(&view->references) == 1) {
dns_zone_t *mkzone = NULL, *rdzone = NULL;
isc_refcount_destroy(&view->references);
LOCK(&view->lock);
if (!RESSHUTDOWN(view)) {
dns_resolver_shutdown(view->resolver);
}
if (!ADBSHUTDOWN(view)) {
dns_adb_shutdown(view->adb);
}
if (!REQSHUTDOWN(view)) {
dns_requestmgr_shutdown(view->requestmgr);
}
if (view->zonetable != NULL) {
if (view->flush) {
dns_zt_flushanddetach(&view->zonetable);
} else {
dns_zt_detach(&view->zonetable);
}
}
if (view->managed_keys != NULL) {
mkzone = view->managed_keys;
view->managed_keys = NULL;
if (view->flush) {
dns_zone_flush(mkzone);
}
}
if (view->redirect != NULL) {
rdzone = view->redirect;
view->redirect = NULL;
if (view->flush)
dns_zone_flush(rdzone);
}
if (view->catzs != NULL) {
dns_catz_catzs_detach(&view->catzs);
}
done = all_done(view);
UNLOCK(&view->lock);
/* Need to detach zones outside view lock */
if (mkzone != NULL) {
dns_zone_detach(&mkzone);
}
if (rdzone != NULL) {
dns_zone_detach(&rdzone);
}
}
*viewp = NULL;
if (done) {
destroy(view);
}
}
void
dns_view_flushanddetach(dns_view_t **viewp) {
view_flushanddetach(viewp, true);
}
void
dns_view_detach(dns_view_t **viewp) {
view_flushanddetach(viewp, false);
}
static isc_result_t
dialup(dns_zone_t *zone, void *dummy) {
UNUSED(dummy);
dns_zone_dialup(zone);
return (ISC_R_SUCCESS);
}
void
dns_view_dialup(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->zonetable != NULL);
(void)dns_zt_apply(view->zonetable, false, NULL, dialup, NULL);
}
void
dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) {
REQUIRE(DNS_VIEW_VALID(source));
REQUIRE(targetp != NULL && *targetp == NULL);
LOCK(&source->lock);
source->weakrefs++;
UNLOCK(&source->lock);
*targetp = source;
}
void
dns_view_weakdetach(dns_view_t **viewp) {
dns_view_t *view;
bool done = false;
REQUIRE(viewp != NULL);
view = *viewp;
REQUIRE(DNS_VIEW_VALID(view));
LOCK(&view->lock);
INSIST(view->weakrefs > 0);
view->weakrefs--;
done = all_done(view);
UNLOCK(&view->lock);
*viewp = NULL;
if (done)
destroy(view);
}
static void
resolver_shutdown(isc_task_t *task, isc_event_t *event) {
dns_view_t *view = event->ev_arg;
bool done;
REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN);
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->task == task);
UNUSED(task);
isc_event_free(&event);
LOCK(&view->lock);
view->attributes |= DNS_VIEWATTR_RESSHUTDOWN;
done = all_done(view);
UNLOCK(&view->lock);
if (done)
destroy(view);
}
static void
adb_shutdown(isc_task_t *task, isc_event_t *event) {
dns_view_t *view = event->ev_arg;
bool done;
REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN);
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->task == task);
UNUSED(task);
isc_event_free(&event);
LOCK(&view->lock);
view->attributes |= DNS_VIEWATTR_ADBSHUTDOWN;
done = all_done(view);
UNLOCK(&view->lock);
if (done)
destroy(view);
}
static void
req_shutdown(isc_task_t *task, isc_event_t *event) {
dns_view_t *view = event->ev_arg;
bool done;
REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN);
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->task == task);
UNUSED(task);
isc_event_free(&event);
LOCK(&view->lock);
view->attributes |= DNS_VIEWATTR_REQSHUTDOWN;
done = all_done(view);
UNLOCK(&view->lock);
if (done)
destroy(view);
}
isc_result_t
dns_view_createzonetable(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
REQUIRE(view->zonetable == NULL);
return (dns_zt_create(view->mctx, view->rdclass, &view->zonetable));
}
isc_result_t
dns_view_createresolver(dns_view_t *view,
isc_taskmgr_t *taskmgr,
unsigned int ntasks,
unsigned int ndisp,
isc_socketmgr_t *socketmgr,
isc_timermgr_t *timermgr,
unsigned int options,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4,
dns_dispatch_t *dispatchv6)
{
isc_result_t result;
isc_event_t *event;
isc_mem_t *mctx = NULL;
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
REQUIRE(view->resolver == NULL);
result = isc_task_create(taskmgr, 0, &view->task);
if (result != ISC_R_SUCCESS)
return (result);
isc_task_setname(view->task, "view", view);
result = dns_resolver_create(view, taskmgr, ntasks, ndisp, socketmgr,
timermgr, options, dispatchmgr,
dispatchv4, dispatchv6,
&view->resolver);
if (result != ISC_R_SUCCESS) {
isc_task_detach(&view->task);
return (result);
}
event = &view->resevent;
dns_resolver_whenshutdown(view->resolver, view->task, &event);
view->attributes &= ~DNS_VIEWATTR_RESSHUTDOWN;
result = isc_mem_create(0, 0, &mctx);
if (result != ISC_R_SUCCESS) {
dns_resolver_shutdown(view->resolver);
return (result);
}
result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb);
isc_mem_setname(mctx, "ADB", NULL);
isc_mem_detach(&mctx);
if (result != ISC_R_SUCCESS) {
dns_resolver_shutdown(view->resolver);
return (result);
}
event = &view->adbevent;
dns_adb_whenshutdown(view->adb, view->task, &event);
view->attributes &= ~DNS_VIEWATTR_ADBSHUTDOWN;
result = dns_requestmgr_create(view->mctx, timermgr, socketmgr,
dns_resolver_taskmgr(view->resolver),
dns_resolver_dispatchmgr(view->resolver),
dispatchv4, dispatchv6,
&view->requestmgr);
if (result != ISC_R_SUCCESS) {
dns_adb_shutdown(view->adb);
dns_resolver_shutdown(view->resolver);
return (result);
}
event = &view->reqevent;
dns_requestmgr_whenshutdown(view->requestmgr, view->task, &event);
view->attributes &= ~DNS_VIEWATTR_REQSHUTDOWN;
return (ISC_R_SUCCESS);
}
void
dns_view_setcache(dns_view_t *view, dns_cache_t *cache, bool shared) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
view->cacheshared = shared;
if (view->cache != NULL) {
dns_db_detach(&view->cachedb);
dns_cache_detach(&view->cache);
}
dns_cache_attach(cache, &view->cache);
dns_cache_attachdb(cache, &view->cachedb);
INSIST(DNS_DB_VALID(view->cachedb));
}
bool
dns_view_iscacheshared(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
return (view->cacheshared);
}
void
dns_view_sethints(dns_view_t *view, dns_db_t *hints) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
REQUIRE(view->hints == NULL);
REQUIRE(dns_db_iszone(hints));
dns_db_attach(hints, &view->hints);
}
void
dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(ring != NULL);
if (view->statickeys != NULL)
dns_tsigkeyring_detach(&view->statickeys);
dns_tsigkeyring_attach(ring, &view->statickeys);
}
void
dns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(ring != NULL);
if (view->dynamickeys != NULL)
dns_tsigkeyring_detach(&view->dynamickeys);
dns_tsigkeyring_attach(ring, &view->dynamickeys);
}
void
dns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(ringp != NULL && *ringp == NULL);
if (view->dynamickeys != NULL)
dns_tsigkeyring_attach(view->dynamickeys, ringp);
}
void
dns_view_restorekeyring(dns_view_t *view) {
FILE *fp;
char keyfile[PATH_MAX];
isc_result_t result;
REQUIRE(DNS_VIEW_VALID(view));
if (view->dynamickeys != NULL) {
result = isc_file_sanitize(NULL, view->name, "tsigkeys",
keyfile, sizeof(keyfile));
if (result == ISC_R_SUCCESS) {
fp = fopen(keyfile, "r");
if (fp != NULL) {
dns_keyring_restore(view->dynamickeys, fp);
(void)fclose(fp);
}
}
}
}
void
dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
REQUIRE(DNS_VIEW_VALID(view));
view->dstport = dstport;
}
void
dns_view_freeze(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
if (view->resolver != NULL) {
INSIST(view->cachedb != NULL);
dns_resolver_freeze(view->resolver);
}
view->frozen = true;
}
void
dns_view_thaw(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->frozen);
view->frozen = false;
}
isc_result_t
dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
isc_result_t result;
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
REQUIRE(view->zonetable != NULL);
result = dns_zt_mount(view->zonetable, zone);
return (result);
}
isc_result_t
dns_view_findzone(dns_view_t *view, const dns_name_t *name,
dns_zone_t **zonep)
{
isc_result_t result;
REQUIRE(DNS_VIEW_VALID(view));
LOCK(&view->lock);
if (view->zonetable != NULL) {
result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
if (result == DNS_R_PARTIALMATCH) {
dns_zone_detach(zonep);
result = ISC_R_NOTFOUND;
}
} else
result = ISC_R_NOTFOUND;
UNLOCK(&view->lock);
return (result);
}
isc_result_t
dns_view_find(dns_view_t *view, const dns_name_t *name, dns_rdatatype_t type,
isc_stdtime_t now, unsigned int options,
bool use_hints, bool use_static_stub,
dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
{
isc_result_t result;
dns_db_t *db, *zdb;
dns_dbnode_t *node, *znode;
bool is_cache, is_staticstub_zone;
dns_rdataset_t zrdataset, zsigrdataset;
dns_zone_t *zone;
/*
* Find an rdataset whose owner name is 'name', and whose type is
* 'type'.
*/
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->frozen);
REQUIRE(type != dns_rdatatype_rrsig);
REQUIRE(rdataset != NULL); /* XXXBEW - remove this */
REQUIRE(nodep == NULL || *nodep == NULL);
/*
* Initialize.
*/
dns_rdataset_init(&zrdataset);
dns_rdataset_init(&zsigrdataset);
zdb = NULL;
znode = NULL;
/*
* Find a database to answer the query.
*/
db = NULL;
node = NULL;
is_staticstub_zone = false;
zone = NULL;
LOCK(&view->lock);
if (view->zonetable != NULL)
result = dns_zt_find(view->zonetable, name, DNS_ZTFIND_MIRROR,
NULL, &zone);
else
result = ISC_R_NOTFOUND;
UNLOCK(&view->lock);
if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub &&
!use_static_stub)
result = ISC_R_NOTFOUND;
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
result = dns_zone_getdb(zone, &db);
if (result != ISC_R_SUCCESS && view->cachedb != NULL)
dns_db_attach(view->cachedb, &db);
else if (result != ISC_R_SUCCESS)
goto cleanup;
if (dns_zone_gettype(zone) == dns_zone_staticstub &&
dns_name_equal(name, dns_zone_getorigin(zone))) {
is_staticstub_zone = true;
}
} else if (result == ISC_R_NOTFOUND && view->cachedb != NULL)
dns_db_attach(view->cachedb, &db);
else
goto cleanup;
is_cache = dns_db_iscache(db);
db_find:
/*
* Now look for an answer in the database.
*/
result = dns_db_find(db, name, NULL, type, options,
now, &node, foundname, rdataset, sigrdataset);
if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) {
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
if (sigrdataset != NULL &&
dns_rdataset_isassociated(sigrdataset))
dns_rdataset_disassociate(sigrdataset);
if (node != NULL)
dns_db_detachnode(db, &node);
if (!is_cache) {
dns_db_detach(&db);
if (view->cachedb != NULL && !is_staticstub_zone) {
/*
* Either the answer is in the cache, or we
* don't know it.
* Note that if the result comes from a
* static-stub zone we stop the search here
* (see the function description in view.h).
*/
is_cache = true;
dns_db_attach(view->cachedb, &db);
goto db_find;
}
} else {
/*
* We don't have the data in the cache. If we've got
* glue from the zone, use it.
*/
if (dns_rdataset_isassociated(&zrdataset)) {
dns_rdataset_clone(&zrdataset, rdataset);
if (sigrdataset != NULL &&
dns_rdataset_isassociated(&zsigrdataset))
dns_rdataset_clone(&zsigrdataset,
sigrdataset);
result = DNS_R_GLUE;
if (db != NULL)
dns_db_detach(&db);
dns_db_attach(zdb, &db);
dns_db_attachnode(db, znode, &node);
goto cleanup;
}
}
/*
* We don't know the answer.
*/
result = ISC_R_NOTFOUND;
} else if (result == DNS_R_GLUE) {
if (view->cachedb != NULL && !is_staticstub_zone) {
/*
* We found an answer, but the cache may be better.
* Remember what we've got and go look in the cache.
*/
is_cache = true;
dns_rdataset_clone(rdataset, &zrdataset);
dns_rdataset_disassociate(rdataset);
if (sigrdataset != NULL &&
dns_rdataset_isassociated(sigrdataset)) {
dns_rdataset_clone(sigrdataset, &zsigrdataset);
dns_rdataset_disassociate(sigrdataset);
}
dns_db_attach(db, &zdb);
dns_db_attachnode(zdb, node, &znode);
dns_db_detachnode(db, &node);
dns_db_detach(&db);
dns_db_attach(view->cachedb, &db);
goto db_find;
}
/*
* Otherwise, the glue is the best answer.
*/
result = ISC_R_SUCCESS;
}
if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
if (sigrdataset != NULL &&
dns_rdataset_isassociated(sigrdataset))
dns_rdataset_disassociate(sigrdataset);
if (db != NULL) {
if (node != NULL)
dns_db_detachnode(db, &node);
dns_db_detach(&db);
}
result = dns_db_find(view->hints, name, NULL, type, options,
now, &node, foundname,
rdataset, sigrdataset);
if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) {
/*
* We just used a hint. Let the resolver know it
* should consider priming.
*/
dns_resolver_prime(view->resolver);
dns_db_attach(view->hints, &db);
result = DNS_R_HINT;
} else if (result == DNS_R_NXRRSET) {
dns_db_attach(view->hints, &db);
result = DNS_R_HINTNXRRSET;
} else if (result == DNS_R_NXDOMAIN)
result = ISC_R_NOTFOUND;
/*
* Cleanup if non-standard hints are used.
*/
if (db == NULL && node != NULL)
dns_db_detachnode(view->hints, &node);
}
cleanup:
if (dns_rdataset_isassociated(&zrdataset)) {
dns_rdataset_disassociate(&zrdataset);
if (dns_rdataset_isassociated(&zsigrdataset))
dns_rdataset_disassociate(&zsigrdataset);
}
if (zdb != NULL) {
if (znode != NULL)
dns_db_detachnode(zdb, &znode);
dns_db_detach(&zdb);
}
if (db != NULL) {
if (node != NULL) {
if (nodep != NULL)
*nodep = node;
else
dns_db_detachnode(db, &node);
}
if (dbp != NULL)
*dbp = db;
else
dns_db_detach(&db);
} else
INSIST(node == NULL);
if (zone != NULL)
dns_zone_detach(&zone);
return (result);
}
isc_result_t
dns_view_simplefind(dns_view_t *view, const dns_name_t *name,
dns_rdatatype_t type, isc_stdtime_t now,
unsigned int options, bool use_hints,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
{
isc_result_t result;
dns_fixedname_t foundname;
dns_fixedname_init(&foundname);
result = dns_view_find(view, name, type, now, options, use_hints,
false, NULL, NULL,
dns_fixedname_name(&foundname), rdataset,
sigrdataset);
if (result == DNS_R_NXDOMAIN) {
/*
* The rdataset and sigrdataset of the relevant NSEC record
* may be returned, but the caller cannot use them because
* foundname is not returned by this simplified API. We
* disassociate them here to prevent any misuse by the caller.
*/
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
if (sigrdataset != NULL &&
dns_rdataset_isassociated(sigrdataset))
dns_rdataset_disassociate(sigrdataset);
} else if (result != ISC_R_SUCCESS &&
result != DNS_R_GLUE &&
result != DNS_R_HINT &&
result != DNS_R_NCACHENXDOMAIN &&
result != DNS_R_NCACHENXRRSET &&
result != DNS_R_NXRRSET &&
result != DNS_R_HINTNXRRSET &&
result != ISC_R_NOTFOUND) {
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
if (sigrdataset != NULL &&
dns_rdataset_isassociated(sigrdataset))
dns_rdataset_disassociate(sigrdataset);
result = ISC_R_NOTFOUND;
}
return (result);
}
isc_result_t
dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
dns_name_t *fname, dns_name_t *dcname, isc_stdtime_t now,
unsigned int options, bool use_hints,
bool use_cache, dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset)
{
isc_result_t result;
dns_db_t *db;
bool is_cache, use_zone, try_hints;
dns_zone_t *zone;
dns_name_t *zfname;
dns_rdataset_t zrdataset, zsigrdataset;
dns_fixedname_t zfixedname;
unsigned int ztoptions = DNS_ZTFIND_MIRROR;
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->frozen);
db = NULL;
use_zone = false;
try_hints = false;
zfname = NULL;
/*
* Initialize.
*/
dns_fixedname_init(&zfixedname);
dns_rdataset_init(&zrdataset);
dns_rdataset_init(&zsigrdataset);
/*
* Find the right database.
*/
zone = NULL;
LOCK(&view->lock);
if (view->zonetable != NULL) {
if ((options & DNS_DBFIND_NOEXACT) != 0)
ztoptions |= DNS_ZTFIND_NOEXACT;
result = dns_zt_find(view->zonetable, name, ztoptions,
NULL, &zone);
} else
result = ISC_R_NOTFOUND;
UNLOCK(&view->lock);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
result = dns_zone_getdb(zone, &db);
if (result == ISC_R_NOTFOUND) {
/*
* We're not directly authoritative for this query name, nor
* is it a subdomain of any zone for which we're
* authoritative.
*/
if (use_cache && view->cachedb != NULL) {
/*
* We have a cache; try it.
*/
dns_db_attach(view->cachedb, &db);
} else {
/*
* Maybe we have hints...
*/
try_hints = true;
goto finish;
}
} else if (result != ISC_R_SUCCESS) {
/*
* Something is broken.
*/
goto cleanup;
}
is_cache = dns_db_iscache(db);
db_find:
/*
* Look for the zonecut.
*/
if (!is_cache) {
result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options,
now, NULL, fname, rdataset, sigrdataset);
if (result == DNS_R_DELEGATION)
result = ISC_R_SUCCESS;
else if (result != ISC_R_SUCCESS)
goto cleanup;
if (use_cache && view->cachedb != NULL && db != view->hints) {
/*
* We found an answer, but the cache may be better.
*/
zfname = dns_fixedname_name(&zfixedname);
result = dns_name_copy(fname, zfname, NULL);
if (result != ISC_R_SUCCESS)
goto cleanup;
dns_rdataset_clone(rdataset, &zrdataset);
dns_rdataset_disassociate(rdataset);
if (sigrdataset != NULL &&
dns_rdataset_isassociated(sigrdataset)) {
dns_rdataset_clone(sigrdataset, &zsigrdataset);
dns_rdataset_disassociate(sigrdataset);
}
dns_db_detach(&db);
dns_db_attach(view->cachedb, &db);
is_cache = true;
goto db_find;
}
} else {
result = dns_db_findzonecut(db, name, options, now, NULL,
fname, dcname, rdataset,
sigrdataset);
if (result == ISC_R_SUCCESS) {
if (zfname != NULL &&
(!dns_name_issubdomain(fname, zfname) ||
(dns_zone_gettype(zone) == dns_zone_staticstub &&
dns_name_equal(fname, zfname)))) {
/*
* We found a zonecut in the cache, but our
* zone delegation is better.
*/
use_zone = true;
}
} else if (result == ISC_R_NOTFOUND) {
if (zfname != NULL) {
/*
* We didn't find anything in the cache, but we
* have a zone delegation, so use it.
*/
use_zone = true;
} else {
/*
* Maybe we have hints...
*/
try_hints = true;
}
} else {
/*
* Something bad happened.
*/
goto cleanup;
}
}
finish:
if (use_zone) {
if (dns_rdataset_isassociated(rdataset)) {
dns_rdataset_disassociate(rdataset);
if (sigrdataset != NULL &&
dns_rdataset_isassociated(sigrdataset))
dns_rdataset_disassociate(sigrdataset);
}
result = dns_name_copy(zfname, fname, NULL);
if (result != ISC_R_SUCCESS)
goto cleanup;
if (dcname != NULL) {
result = dns_name_copy(zfname, dcname, NULL);
if (result != ISC_R_SUCCESS)
goto cleanup;
}
dns_rdataset_clone(&zrdataset, rdataset);
if (sigrdataset != NULL &&
dns_rdataset_isassociated(&zrdataset))
dns_rdataset_clone(&zsigrdataset, sigrdataset);
} else if (try_hints && use_hints && view->hints != NULL) {
/*
* We've found nothing so far, but we have hints.
*/
result = dns_db_find(view->hints, dns_rootname, NULL,
dns_rdatatype_ns, 0, now, NULL, fname,
rdataset, NULL);
if (result != ISC_R_SUCCESS) {
/*
* We can't even find the hints for the root
* nameservers!
*/
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
result = ISC_R_NOTFOUND;
} else if (dcname != NULL) {
dns_name_copy(fname, dcname, NULL);
}
}
cleanup:
if (dns_rdataset_isassociated(&zrdataset)) {
dns_rdataset_disassociate(&zrdataset);
if (dns_rdataset_isassociated(&zsigrdataset))
dns_rdataset_disassociate(&zsigrdataset);
}
if (db != NULL)
dns_db_detach(&db);
if (zone != NULL)
dns_zone_detach(&zone);
return (result);
}
isc_result_t
dns_viewlist_find(dns_viewlist_t *list, const char *name,
dns_rdataclass_t rdclass, dns_view_t **viewp)
{
dns_view_t *view;
REQUIRE(list != NULL);
for (view = ISC_LIST_HEAD(*list);
view != NULL;
view = ISC_LIST_NEXT(view, link)) {
if (strcmp(view->name, name) == 0 && view->rdclass == rdclass)
break;
}
if (view == NULL)
return (ISC_R_NOTFOUND);
dns_view_attach(view, viewp);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_viewlist_findzone(dns_viewlist_t *list, const dns_name_t *name,
bool allclasses, dns_rdataclass_t rdclass,
dns_zone_t **zonep)
{
dns_view_t *view;
isc_result_t result;
dns_zone_t *zone1 = NULL, *zone2 = NULL;
dns_zone_t **zp = NULL;
REQUIRE(list != NULL);
REQUIRE(zonep != NULL && *zonep == NULL);
for (view = ISC_LIST_HEAD(*list);
view != NULL;
view = ISC_LIST_NEXT(view, link)) {
if (allclasses == false && view->rdclass != rdclass)
continue;
/*
* If the zone is defined in more than one view,
* treat it as not found.
*/
zp = (zone1 == NULL) ? &zone1 : &zone2;
LOCK(&view->lock);
if (view->zonetable != NULL)
result = dns_zt_find(view->zonetable, name, 0,
NULL, zp);
else
result = ISC_R_NOTFOUND;
UNLOCK(&view->lock);
INSIST(result == ISC_R_SUCCESS ||
result == ISC_R_NOTFOUND ||
result == DNS_R_PARTIALMATCH);
/* Treat a partial match as no match */
if (result == DNS_R_PARTIALMATCH) {
dns_zone_detach(zp);
result = ISC_R_NOTFOUND;
POST(result);
}
if (zone2 != NULL) {
dns_zone_detach(&zone1);
dns_zone_detach(&zone2);
return (ISC_R_MULTIPLE);
}
}
if (zone1 != NULL) {
dns_zone_attach(zone1, zonep);
dns_zone_detach(&zone1);
return (ISC_R_SUCCESS);
}
return (ISC_R_NOTFOUND);
}
isc_result_t
dns_view_load(dns_view_t *view, bool stop, bool newonly) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->zonetable != NULL);
return (dns_zt_load(view->zonetable, stop, newonly));
}
isc_result_t
dns_view_asyncload(dns_view_t *view, bool newonly,
dns_zt_allloaded_t callback, void *arg) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->zonetable != NULL);
return (dns_zt_asyncload(view->zonetable, newonly, callback, arg));
}
isc_result_t
dns_view_gettsig(dns_view_t *view, const dns_name_t *keyname,
dns_tsigkey_t **keyp)
{
isc_result_t result;
REQUIRE(keyp != NULL && *keyp == NULL);
result = dns_tsigkey_find(keyp, keyname, NULL,
view->statickeys);
if (result == ISC_R_NOTFOUND)
result = dns_tsigkey_find(keyp, keyname, NULL,
view->dynamickeys);
return (result);
}
isc_result_t
dns_view_getpeertsig(dns_view_t *view, const isc_netaddr_t *peeraddr,
dns_tsigkey_t **keyp)
{
isc_result_t result;
dns_name_t *keyname = NULL;
dns_peer_t *peer = NULL;
result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer);
if (result != ISC_R_SUCCESS)
return (result);
result = dns_peer_getkey(peer, &keyname);
if (result != ISC_R_SUCCESS)
return (result);
result = dns_view_gettsig(view, keyname, keyp);
return ((result == ISC_R_NOTFOUND) ? ISC_R_FAILURE : result);
}
isc_result_t
dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(source != NULL);
return (dns_tsig_verify(source, msg, view->statickeys,
view->dynamickeys));
}
isc_result_t
dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
isc_result_t result;
REQUIRE(DNS_VIEW_VALID(view));
(void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name);
result = dns_master_dumptostream(view->mctx, view->cachedb, NULL,
&dns_master_style_cache,
dns_masterformat_text, NULL, fp);
if (result != ISC_R_SUCCESS)
return (result);
dns_adb_dump(view->adb, fp);
dns_resolver_printbadcache(view->resolver, fp);
dns_badcache_print(view->failcache, "SERVFAIL cache", fp);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_view_flushcache(dns_view_t *view, bool fixuponly) {
isc_result_t result;
REQUIRE(DNS_VIEW_VALID(view));
if (view->cachedb == NULL)
return (ISC_R_SUCCESS);
if (!fixuponly) {
result = dns_cache_flush(view->cache);
if (result != ISC_R_SUCCESS)
return (result);
}
dns_db_detach(&view->cachedb);
dns_cache_attachdb(view->cache, &view->cachedb);
if (view->resolver != NULL)
dns_resolver_flushbadcache(view->resolver, NULL);
if (view->failcache != NULL)
dns_badcache_flush(view->failcache);
dns_adb_flush(view->adb);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_view_flushname(dns_view_t *view, const dns_name_t *name) {
return (dns_view_flushnode(view, name, false));
}
isc_result_t
dns_view_flushnode(dns_view_t *view, const dns_name_t *name,
bool tree)
{
isc_result_t result = ISC_R_SUCCESS;
REQUIRE(DNS_VIEW_VALID(view));
if (tree) {
if (view->adb != NULL)
dns_adb_flushnames(view->adb, name);
if (view->resolver != NULL)
dns_resolver_flushbadnames(view->resolver, name);
if (view->failcache != NULL)
dns_badcache_flushtree(view->failcache, name);
} else {
if (view->adb != NULL)
dns_adb_flushname(view->adb, name);
if (view->resolver != NULL)
dns_resolver_flushbadcache(view->resolver, name);
if (view->failcache != NULL)
dns_badcache_flushname(view->failcache, name);
}
if (view->cache != NULL)
result = dns_cache_flushnode(view->cache, name, tree);
return (result);
}
isc_result_t
dns_view_adddelegationonly(dns_view_t *view, const dns_name_t *name) {
isc_result_t result;
dns_name_t *item;
uint32_t hash;
REQUIRE(DNS_VIEW_VALID(view));
if (view->delonly == NULL) {
view->delonly = isc_mem_get(view->mctx,
sizeof(dns_namelist_t) *
DNS_VIEW_DELONLYHASH);
if (view->delonly == NULL)
return (ISC_R_NOMEMORY);
for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++)
ISC_LIST_INIT(view->delonly[hash]);
}
hash = dns_name_hash(name, false) % DNS_VIEW_DELONLYHASH;
item = ISC_LIST_HEAD(view->delonly[hash]);
while (item != NULL && !dns_name_equal(item, name))
item = ISC_LIST_NEXT(item, link);
if (item != NULL)
return (ISC_R_SUCCESS);
item = isc_mem_get(view->mctx, sizeof(*item));
if (item == NULL)
return (ISC_R_NOMEMORY);
dns_name_init(item, NULL);
result = dns_name_dup(name, view->mctx, item);
if (result == ISC_R_SUCCESS)
ISC_LIST_APPEND(view->delonly[hash], item, link);
else
isc_mem_put(view->mctx, item, sizeof(*item));
return (result);
}
isc_result_t
dns_view_excludedelegationonly(dns_view_t *view, const dns_name_t *name) {
isc_result_t result;
dns_name_t *item;
uint32_t hash;
REQUIRE(DNS_VIEW_VALID(view));
if (view->rootexclude == NULL) {
view->rootexclude = isc_mem_get(view->mctx,
sizeof(dns_namelist_t) *
DNS_VIEW_DELONLYHASH);
if (view->rootexclude == NULL)
return (ISC_R_NOMEMORY);
for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++)
ISC_LIST_INIT(view->rootexclude[hash]);
}
hash = dns_name_hash(name, false) % DNS_VIEW_DELONLYHASH;
item = ISC_LIST_HEAD(view->rootexclude[hash]);
while (item != NULL && !dns_name_equal(item, name))
item = ISC_LIST_NEXT(item, link);
if (item != NULL)
return (ISC_R_SUCCESS);
item = isc_mem_get(view->mctx, sizeof(*item));
if (item == NULL)
return (ISC_R_NOMEMORY);
dns_name_init(item, NULL);
result = dns_name_dup(name, view->mctx, item);
if (result == ISC_R_SUCCESS)
ISC_LIST_APPEND(view->rootexclude[hash], item, link);
else
isc_mem_put(view->mctx, item, sizeof(*item));
return (result);
}
bool
dns_view_isdelegationonly(dns_view_t *view, const dns_name_t *name) {
dns_name_t *item;
uint32_t hash;
REQUIRE(DNS_VIEW_VALID(view));
if (!view->rootdelonly && view->delonly == NULL)
return (false);
hash = dns_name_hash(name, false) % DNS_VIEW_DELONLYHASH;
if (view->rootdelonly && dns_name_countlabels(name) <= 2) {
if (view->rootexclude == NULL)
return (true);
item = ISC_LIST_HEAD(view->rootexclude[hash]);
while (item != NULL && !dns_name_equal(item, name))
item = ISC_LIST_NEXT(item, link);
if (item == NULL)
return (true);
}
if (view->delonly == NULL)
return (false);
item = ISC_LIST_HEAD(view->delonly[hash]);
while (item != NULL && !dns_name_equal(item, name))
item = ISC_LIST_NEXT(item, link);
if (item == NULL)
return (false);
return (true);
}
void
dns_view_setrootdelonly(dns_view_t *view, bool value) {
REQUIRE(DNS_VIEW_VALID(view));
view->rootdelonly = value;
}
bool
dns_view_getrootdelonly(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
return (view->rootdelonly);
}
isc_result_t
dns_view_freezezones(dns_view_t *view, bool value) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->zonetable != NULL);
return (dns_zt_freezezones(view->zonetable, value));
}
void
dns_view_setadbstats(dns_view_t *view, isc_stats_t *stats) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
REQUIRE(view->adbstats == NULL);
isc_stats_attach(stats, &view->adbstats);
}
void
dns_view_getadbstats(dns_view_t *view, isc_stats_t **statsp) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(statsp != NULL && *statsp == NULL);
if (view->adbstats != NULL)
isc_stats_attach(view->adbstats, statsp);
}
void
dns_view_setresstats(dns_view_t *view, isc_stats_t *stats) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
REQUIRE(view->resstats == NULL);
isc_stats_attach(stats, &view->resstats);
}
void
dns_view_getresstats(dns_view_t *view, isc_stats_t **statsp) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(statsp != NULL && *statsp == NULL);
if (view->resstats != NULL)
isc_stats_attach(view->resstats, statsp);
}
void
dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
REQUIRE(view->resquerystats == NULL);
dns_stats_attach(stats, &view->resquerystats);
}
void
dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(statsp != NULL && *statsp == NULL);
if (view->resquerystats != NULL)
dns_stats_attach(view->resquerystats, statsp);
}
isc_result_t
dns_view_initntatable(dns_view_t *view,
isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr)
{
REQUIRE(DNS_VIEW_VALID(view));
if (view->ntatable_priv != NULL)
dns_ntatable_detach(&view->ntatable_priv);
return (dns_ntatable_create(view, taskmgr, timermgr,
&view->ntatable_priv));
}
isc_result_t
dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(ntp != NULL && *ntp == NULL);
if (view->ntatable_priv == NULL)
return (ISC_R_NOTFOUND);
dns_ntatable_attach(view->ntatable_priv, ntp);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) {
REQUIRE(DNS_VIEW_VALID(view));
if (view->secroots_priv != NULL)
dns_keytable_detach(&view->secroots_priv);
return (dns_keytable_create(mctx, &view->secroots_priv));
}
isc_result_t
dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) {
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(ktp != NULL && *ktp == NULL);
if (view->secroots_priv == NULL)
return (ISC_R_NOTFOUND);
dns_keytable_attach(view->secroots_priv, ktp);
return (ISC_R_SUCCESS);
}
bool
dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now,
const dns_name_t *name, const dns_name_t *anchor)
{
REQUIRE(DNS_VIEW_VALID(view));
if (view->ntatable_priv == NULL)
return (false);
return (dns_ntatable_covered(view->ntatable_priv, now, name, anchor));
}
isc_result_t
dns_view_issecuredomain(dns_view_t *view, const dns_name_t *name,
isc_stdtime_t now, bool checknta,
bool *secure_domain)
{
isc_result_t result;
bool secure = false;
dns_fixedname_t fn;
dns_name_t *anchor;
REQUIRE(DNS_VIEW_VALID(view));
if (view->secroots_priv == NULL)
return (ISC_R_NOTFOUND);
anchor = dns_fixedname_initname(&fn);
result = dns_keytable_issecuredomain(view->secroots_priv, name,
anchor, &secure);
if (result != ISC_R_SUCCESS)
return (result);
if (checknta && secure && view->ntatable_priv != NULL &&
dns_ntatable_covered(view->ntatable_priv, now, name, anchor))
secure = false;
*secure_domain = secure;
return (ISC_R_SUCCESS);
}
void
dns_view_untrust(dns_view_t *view, const dns_name_t *keyname,
dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx)
{
isc_result_t result;
unsigned char data[4096];
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_buffer_t buffer;
dst_key_t *key = NULL;
dns_keytable_t *sr = NULL;
/*
* Clear the revoke bit, if set, so that the key will match what's
* in secroots now.
*/
dnskey->flags &= ~DNS_KEYFLAG_REVOKE;
/* Convert dnskey to DST key. */
isc_buffer_init(&buffer, data, sizeof(data));
dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
dns_rdatatype_dnskey, dnskey, &buffer);
result = dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key);
if (result != ISC_R_SUCCESS)
return;
result = dns_view_getsecroots(view, &sr);
if (result == ISC_R_SUCCESS) {
result = dns_keytable_deletekeynode(sr, key);
/*
* If key was found in secroots, then it was a
* configured trust anchor, and we want to fail
* secure. If there are no other configured keys,
* then leave a null key so that we can't validate
* anymore.
*/
if (result == ISC_R_SUCCESS)
dns_keytable_marksecure(sr, keyname);
dns_keytable_detach(&sr);
}
dst_key_free(&key);
}
/*
* Create path to a directory and a filename contructed from viewname.
* This is a front-end to isc_file_sanitize(), allowing backward
* compatibility to older versions when a file couldn't be expected
* to be in the specified directory but might be in the current working
* directory instead.
*
* It first tests for the existence of a file <viewname>.<suffix> in
* 'directory'. If the file does not exist, it checks again in the
* current working directory. If it does not exist there either,
* return the path inside the directory.
*
* Returns ISC_R_SUCCESS if a path to an existing file is found or
* a new path is created; returns ISC_R_NOSPACE if the path won't
* fit in 'buflen'.
*/
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
static isc_result_t
nz_legacy(const char *directory, const char *viewname,
const char *suffix, char *buffer, size_t buflen)
{
isc_result_t result;
char newbuf[PATH_MAX];
result = isc_file_sanitize(directory, viewname, suffix,
buffer, buflen);
if (result != ISC_R_SUCCESS) {
return (result);
} else if (directory == NULL || isc_file_exists(buffer)) {
return (ISC_R_SUCCESS);
} else {
/* Save buffer */
strlcpy(newbuf, buffer, sizeof(newbuf));
}
/*
* It isn't in the specified directory; check CWD.
*/
result = isc_file_sanitize(NULL, viewname, suffix, buffer, buflen);
if (result != ISC_R_SUCCESS || isc_file_exists(buffer)) {
return (result);
}
/*
* File does not exist in either 'directory' or CWD,
* so use the path in 'directory'.
*/
strlcpy(buffer, newbuf, buflen);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_view_setnewzones(dns_view_t *view, bool allow, void *cfgctx,
void (*cfg_destroy)(void **), uint64_t mapsize)
{
isc_result_t result = ISC_R_SUCCESS;
char buffer[1024];
#ifdef HAVE_LMDB
MDB_env *env = NULL;
int status;
#endif
#ifndef HAVE_LMDB
UNUSED(mapsize);
#endif
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow);
if (view->new_zone_file != NULL) {
isc_mem_free(view->mctx, view->new_zone_file);
view->new_zone_file = NULL;
}
#ifdef HAVE_LMDB
if (view->new_zone_dbenv != NULL) {
mdb_env_close((MDB_env *) view->new_zone_dbenv);
view->new_zone_dbenv = NULL;
}
if (view->new_zone_db != NULL) {
isc_mem_free(view->mctx, view->new_zone_db);
view->new_zone_db = NULL;
}
#endif /* HAVE_LMDB */
if (view->new_zone_config != NULL) {
view->cfg_destroy(&view->new_zone_config);
view->cfg_destroy = NULL;
}
if (!allow) {
return (ISC_R_SUCCESS);
}
CHECK(nz_legacy(view->new_zone_dir, view->name, "nzf",
buffer, sizeof(buffer)));
view->new_zone_file = isc_mem_strdup(view->mctx, buffer);
if (view->new_zone_file == NULL) {
CHECK(ISC_R_NOMEMORY);
}
#ifdef HAVE_LMDB
CHECK(nz_legacy(view->new_zone_dir, view->name, "nzd",
buffer, sizeof(buffer)));
view->new_zone_db = isc_mem_strdup(view->mctx, buffer);
if (view->new_zone_db == NULL) {
CHECK(ISC_R_NOMEMORY);
}
status = mdb_env_create(&env);
if (status != MDB_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
"mdb_env_create failed: %s",
mdb_strerror(status));
CHECK(ISC_R_FAILURE);
}
if (mapsize != 0ULL) {
status = mdb_env_set_mapsize(env, mapsize);
if (status != MDB_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
"mdb_env_set_mapsize failed: %s",
mdb_strerror(status));
CHECK(ISC_R_FAILURE);
}
view->new_zone_mapsize = mapsize;
}
status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600);
if (status != MDB_SUCCESS) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
"mdb_env_open of '%s' failed: %s",
view->new_zone_db, mdb_strerror(status));
CHECK(ISC_R_FAILURE);
}
view->new_zone_dbenv = env;
env = NULL;
#endif /* HAVE_LMDB */
view->new_zone_config = cfgctx;
view->cfg_destroy = cfg_destroy;
cleanup:
if (result != ISC_R_SUCCESS) {
if (view->new_zone_file != NULL) {
isc_mem_free(view->mctx, view->new_zone_file);
view->new_zone_file = NULL;
}
#ifdef HAVE_LMDB
if (view->new_zone_db != NULL) {
isc_mem_free(view->mctx, view->new_zone_db);
view->new_zone_db = NULL;
}
if (env != NULL) {
mdb_env_close(env);
}
#endif /* HAVE_LMDB */
view->new_zone_config = NULL;
view->cfg_destroy = NULL;
}
return (result);
}
void
dns_view_setnewzonedir(dns_view_t *view, const char *dir) {
REQUIRE(DNS_VIEW_VALID(view));
if (view->new_zone_dir != NULL) {
isc_mem_free(view->mctx, view->new_zone_dir);
view->new_zone_dir = NULL;
}
if (dir == NULL) {
return;
}
view->new_zone_dir = isc_mem_strdup(view->mctx, dir);
}
const char *
dns_view_getnewzonedir(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
return (view->new_zone_dir);
}
isc_result_t
dns_view_searchdlz(dns_view_t *view, const dns_name_t *name,
unsigned int minlabels, dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo, dns_db_t **dbp)
{
dns_fixedname_t fname;
dns_name_t *zonename;
unsigned int namelabels;
unsigned int i;
isc_result_t result;
dns_dlzfindzone_t findzone;
dns_dlzdb_t *dlzdb;
dns_db_t *db, *best = NULL;
/*
* Performs checks to make sure data is as we expect it to be.
*/
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(name != NULL);
REQUIRE(dbp != NULL && *dbp == NULL);
/* setup a "fixed" dns name */
zonename = dns_fixedname_initname(&fname);
/* count the number of labels in the name */
namelabels = dns_name_countlabels(name);
for (dlzdb = ISC_LIST_HEAD(view->dlz_searched);
dlzdb != NULL;
dlzdb = ISC_LIST_NEXT(dlzdb, link))
{
REQUIRE(DNS_DLZ_VALID(dlzdb));
/*
* loop through starting with the longest domain name and
* trying shorter names portions of the name until we find a
* match, have an error, or are below the 'minlabels'
* threshold. minlabels is 0, if neither the standard
* database nor any previous DLZ database had a zone name
* match. Otherwise minlabels is the number of labels
* in that name. We need to beat that for a "better"
* match for this DLZ database to be authoritative.
*/
for (i = namelabels; i > minlabels && i > 1; i--) {
if (i == namelabels) {
result = dns_name_copy(name, zonename, NULL);
if (result != ISC_R_SUCCESS)
return (result);
} else
dns_name_split(name, i, NULL, zonename);
/* ask SDLZ driver if the zone is supported */
db = NULL;
findzone = dlzdb->implementation->methods->findzone;
result = (*findzone)(dlzdb->implementation->driverarg,
dlzdb->dbdata, dlzdb->mctx,
view->rdclass, zonename,
methods, clientinfo, &db);
if (result != ISC_R_NOTFOUND) {
if (best != NULL)
dns_db_detach(&best);
if (result == ISC_R_SUCCESS) {
INSIST(db != NULL);
dns_db_attach(db, &best);
dns_db_detach(&db);
minlabels = i;
} else {
if (db != NULL)
dns_db_detach(&db);
break;
}
} else if (db != NULL)
dns_db_detach(&db);
}
}
if (best != NULL) {
dns_db_attach(best, dbp);
dns_db_detach(&best);
return (ISC_R_SUCCESS);
}
return (ISC_R_NOTFOUND);
}
uint32_t
dns_view_getfailttl(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
return (view->fail_ttl);
}
void
dns_view_setfailttl(dns_view_t *view, uint32_t fail_ttl) {
REQUIRE(DNS_VIEW_VALID(view));
view->fail_ttl = fail_ttl;
}
isc_result_t
dns_view_saventa(dns_view_t *view) {
isc_result_t result;
bool removefile = false;
dns_ntatable_t *ntatable = NULL;
FILE *fp = NULL;
REQUIRE(DNS_VIEW_VALID(view));
if (view->nta_lifetime == 0)
return (ISC_R_SUCCESS);
/* Open NTA save file for overwrite. */
CHECK(isc_stdio_open(view->nta_file, "w", &fp));
result = dns_view_getntatable(view, &ntatable);
if (result == ISC_R_NOTFOUND) {
removefile = true;
result = ISC_R_SUCCESS;
goto cleanup;
} else
CHECK(result);
result = dns_ntatable_save(ntatable, fp);
if (result == ISC_R_NOTFOUND) {
removefile = true;
result = ISC_R_SUCCESS;
} else if (result == ISC_R_SUCCESS) {
result = isc_stdio_close(fp);
fp = NULL;
}
cleanup:
if (ntatable != NULL)
dns_ntatable_detach(&ntatable);
if (fp != NULL)
(void)isc_stdio_close(fp);
/* Don't leave half-baked NTA save files lying around. */
if (result != ISC_R_SUCCESS || removefile)
(void) isc_file_remove(view->nta_file);
return (result);
}
#define TSTR(t) ((t).value.as_textregion.base)
#define TLEN(t) ((t).value.as_textregion.length)
isc_result_t
dns_view_loadnta(dns_view_t *view) {
isc_result_t result;
dns_ntatable_t *ntatable = NULL;
isc_lex_t *lex = NULL;
isc_token_t token;
isc_stdtime_t now;
REQUIRE(DNS_VIEW_VALID(view));
if (view->nta_lifetime == 0)
return (ISC_R_SUCCESS);
CHECK(isc_lex_create(view->mctx, 1025, &lex));
CHECK(isc_lex_openfile(lex, view->nta_file));
CHECK(dns_view_getntatable(view, &ntatable));
isc_stdtime_get(&now);
for (;;) {
int options = (ISC_LEXOPT_EOL | ISC_LEXOPT_EOF);
char *name, *type, *timestamp;
size_t len;
dns_fixedname_t fn;
const dns_name_t *ntaname;
isc_buffer_t b;
isc_stdtime_t t;
bool forced;
CHECK(isc_lex_gettoken(lex, options, &token));
if (token.type == isc_tokentype_eof)
break;
else if (token.type != isc_tokentype_string)
CHECK(ISC_R_UNEXPECTEDTOKEN);
name = TSTR(token);
len = TLEN(token);
if (strcmp(name, ".") == 0)
ntaname = dns_rootname;
else {
dns_name_t *fname;
fname = dns_fixedname_initname(&fn);
isc_buffer_init(&b, name, (unsigned int)len);
isc_buffer_add(&b, (unsigned int)len);
CHECK(dns_name_fromtext(fname, &b, dns_rootname,
0, NULL));
ntaname = fname;
}
CHECK(isc_lex_gettoken(lex, options, &token));
if (token.type != isc_tokentype_string)
CHECK(ISC_R_UNEXPECTEDTOKEN);
type = TSTR(token);
if (strcmp(type, "regular") == 0)
forced = false;
else if (strcmp(type, "forced") == 0)
forced = true;
else
CHECK(ISC_R_UNEXPECTEDTOKEN);
CHECK(isc_lex_gettoken(lex, options, &token));
if (token.type != isc_tokentype_string)
CHECK(ISC_R_UNEXPECTEDTOKEN);
timestamp = TSTR(token);
CHECK(dns_time32_fromtext(timestamp, &t));
CHECK(isc_lex_gettoken(lex, options, &token));
if (token.type != isc_tokentype_eol &&
token.type != isc_tokentype_eof)
CHECK(ISC_R_UNEXPECTEDTOKEN);
if (now <= t) {
if (t > (now + 604800))
t = now + 604800;
(void) dns_ntatable_add(ntatable, ntaname,
forced, 0, t);
} else {
char nb[DNS_NAME_FORMATSIZE];
dns_name_format(ntaname, nb, sizeof(nb));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_NTA, ISC_LOG_INFO,
"ignoring expired NTA at %s", nb);
}
};
cleanup:
if (ntatable != NULL)
dns_ntatable_detach(&ntatable);
if (lex != NULL) {
isc_lex_close(lex);
isc_lex_destroy(&lex);
}
return (result);
}
void
dns_view_setviewcommit(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
LOCK(&view->lock);
if (view->redirect != NULL) {
dns_zone_setviewcommit(view->redirect);
}
if (view->managed_keys != NULL) {
dns_zone_setviewcommit(view->managed_keys);
}
if (view->zonetable != NULL) {
dns_zt_setviewcommit(view->zonetable);
}
UNLOCK(&view->lock);
}
void
dns_view_setviewrevert(dns_view_t *view) {
dns_zt_t *zonetable;
REQUIRE(DNS_VIEW_VALID(view));
/*
* dns_zt_setviewrevert() attempts to lock this view, so we must
* release the lock.
*/
LOCK(&view->lock);
if (view->redirect != NULL) {
dns_zone_setviewrevert(view->redirect);
}
if (view->managed_keys != NULL) {
dns_zone_setviewrevert(view->managed_keys);
}
zonetable = view->zonetable;
UNLOCK(&view->lock);
if (zonetable != NULL) {
dns_zt_setviewrevert(zonetable);
}
}