Compare commits

...
Author SHA1 Message Date
W.C.A. Wijngaards 75b6dba593 - Fix CVE-2026-44608, Use after free and crash in RPZ code. Thanks
to Qifan Zhang, Palo Alto Networks, for the report.
2026-05-20 10:22:52 +02:00
W.C.A. Wijngaards 138fb48eac Changelog entry.
- Fix CVE-2026-44390, Unbounded name compression in certain cases
  causes degradation of service. Thanks to Qifan Zhang, Palo Alto
  Networks, for the report.
2026-05-20 10:22:10 +02:00
W.C.A. Wijngaards dae7a37974 - Fix CVE-2026-44390, Unbounded name compression in certain cases
causes degradation of service. Thanks to Qifan Zhang, Palo Alto
  Networks, for the report.
2026-05-20 10:21:26 +02:00
W.C.A. Wijngaards 8ae4b4545d - Fix CVE-2026-42960, Possible cache poisoning attack while following
delegation. Thanks to TaoFei Guo from Peking University, Yang Luo
  and JianJun Chen, Tsinghua University, for the report.
2026-05-20 10:20:45 +02:00
W.C.A. Wijngaards c343fff3a4 - Fix CVE-2026-42923, Degradation of service with unbounded NSEC3
hash calculations. Thanks to Qifan Zhang, Palo Alto Networks, for
  the report.
2026-05-20 10:20:02 +02:00
W.C.A. Wijngaards a794c87578 - Fix CVE-2026-42534, Jostle logic bypass degrades resolution
performance. Thanks to Qifan Zhang, Palo Alto Networks, for the
  report.
2026-05-20 10:19:08 +02:00
W.C.A. Wijngaards ef5ca84360 - Fix CVE-2026-41292, Parsing a long list of incoming EDNS options
degrades performance. Thanks to GitHub user 'N0zoM1z0', also Qifan
  Zhang from Palo Alto Networks, for the report.
2026-05-20 10:18:23 +02:00
W.C.A. Wijngaards 8d8fa42266 - Fix CVE-2026-40622, "Ghost domain name" variant. Thanks to Qifan
Zhang, Palo Alto Networks, for the report.
2026-05-20 10:16:18 +02:00
W.C.A. Wijngaards a587535c5d - Fix CVE-2026-32792, Packet of death with DNSCrypt. Thanks to Andrew
Griffiths from 'calif.io' for the report.
2026-05-20 10:15:30 +02:00
W.C.A. Wijngaards 94d5babaee - Fix CVE-2026-42959, Crash during DNSSEC validation of malicious
content. Thanks to Qifan Zhang, Palo Alto Networks, for the report.
2026-05-20 10:14:32 +02:00
W.C.A. Wijngaards fe946ba4e9 - Fix CVE-2026-42944, Heap overflow and crash with multiple nsid,
cookie, padding EDNS options. Thanks to Qifan Zhang, Palo Alto
  Networks, for the report.
2026-05-20 10:13:55 +02:00
W.C.A. Wijngaards 6a31e470f8 - Fix CVE-2026-33278, Possible remote code execution during DNSSEC
validation. Thanks to Qifan Zhang, Palo Alto Networks, for the report.
2026-05-20 10:13:08 +02:00
W.C.A. Wijngaards e577695aeb Set version to 1.25.1 for release. 2026-05-20 10:11:15 +02:00
W.C.A. Wijngaards 25fe602024 - For #1441: Fix type of ipv6 addr struct. 2026-04-23 09:37:30 +02:00
W.C.A. Wijngaards df0e86de49 Changelog entry for #1441.
- Merge #1441: Fix buffer overrun in
  doq_repinfo_retrieve_localaddr().
2026-04-23 09:35:44 +02:00
FothsidandGitHub e49b550cf3 Fix buffer overrun in doq_repinfo_retrieve_localaddr() (#1441) 2026-04-23 09:35:23 +02:00
W.C.A. Wijngaards 07c96792f2 - Fix doxygen comment syntax. 2026-04-21 13:44:55 +02:00
W.C.A. Wijngaards 84ab430e11 - Set version number to 1.25.0 of code repository. 2026-04-21 13:27:55 +02:00
W.C.A. Wijngaards 53499e4a88 - Fix handling of wildcard CNAMEs in the chain of trust.
An improper wildcard in the chain of trust would send
  the retries to the wrong upstream. Also it could label
  the step in the chain of trust as secure, when it was not.
  Thanks to Qifan Zhang, Palo Alto Networks for the report.
2026-04-21 13:24:40 +02:00
W.C.A. Wijngaards 8a25a97687 - Fix that a DNAME with an unsigned CNAME is checked for
the correct match. This stops that for certain zone
  configurations an unchecked unsigned CNAME could get
  secure status. Thanks to Qifan Zhang, Palo Alto Networks
  for the report.
2026-04-21 13:19:13 +02:00
W.C.A. Wijngaards c112bcf2fd - Fix that signatures are not allowed with revoked dnskeys.
Thanks to Qifan Zhang, Palo Alto Networks for the report.
2026-04-21 13:07:34 +02:00
W.C.A. Wijngaards 9de549c498 - Fix that upstream TLS connections are not reused as TLS
connections for a different name, at the same IP. This
  checks that the tls name is correct when reusing the
  upstream connections. Thanks to TaoFei Guo from Peking
  University and JianJun Chen from Tsinghua University for
  the report.
2026-04-21 11:59:05 +02:00
W.C.A. Wijngaards 84c645e7b3 - Fix for missing bounds check for decompressing dnames
for downloaded authority zones. This fixes that the server
  could end up with malformed zone content after receiving
  truncated packet contents from an AXFR. In addition, the
  domain names in the SOA rdata are checked before the
  authority code picks up the zone serial.
  Thanks to Halil Oktay for the report.
2026-04-21 10:32:37 +02:00
W.C.A. Wijngaards 197a425c7d - Fix for iterator RCODE handling of YXDOMAIN. This fixes
that the server only accepts YXDOMAIN answers that contain
  a DNAME record. This stops bad answers, and checks that
  the authoritative server gives correct replies.
  Thanks to Qifan Zhang, Palo Alto Networks for the report.
2026-04-21 10:09:02 +02:00
W.C.A. Wijngaards 311054728d - Fix EDNS extended RCODE reflection. This fixes that
the server does not echo extended rcode values after class
  chaos queries. Thanks to Qifan Zhang, Palo Alto Networks
  for the report.
2026-04-21 09:58:19 +02:00
W.C.A. Wijngaards 6d74856212 - Fix for the Jiggle Attack. The server is fixed to answer
with errors for error cases, and does not stay silent.
  In addition, the error replies do not contain parts of the
  incoming query. This is more conformant, stops reflection
  and stops it as a covert channel. Thanks to Yuqi Qiu and
  Xiang Li, Nankai University (AOSP Lab) for the report.
  In addition, thanks to Qifan Zhang, Palo Alto Networks, for
  noting the fingerprinting possibility, that is also fixed
  with this.
2026-04-21 09:54:17 +02:00
W.C.A. Wijngaards d489e6027e - Add test case for malformed SVCB records. Thanks to
Qifan Zhang, Palo Alto Networks for the additional test.
2026-04-21 09:41:53 +02:00
W.C.A. Wijngaards e1d146d6b0 - Fix test with https zone for libressl. 2026-04-20 16:10:33 +02:00
W.C.A. Wijngaards eb2fe8df8d - Fix unused variable warning when compiled without ssl. 2026-04-20 12:24:55 +02:00
W.C.A. Wijngaards 86a8be75f0 - Fix compile warnings for thread setname routine, and test compile. 2026-04-20 12:24:28 +02:00
W.C.A. Wijngaards 52fc5ee374 - Fix pthread_setname detection to fail on warnings. 2026-04-17 17:13:14 +02:00
W.C.A. Wijngaards 82359c8fb1 - Update generated configure, with autoconf. 2026-04-17 17:00:09 +02:00
W.C.A. Wijngaards c996671a1f - Update generated man pages. 2026-04-17 16:32:02 +02:00
Yorgos Thessalonikefs e233a1ef65 Changelog entry for #1400:
- Merge #1400: Support pthread_setname_np.
2026-04-17 16:23:53 +02:00
Yorgos Thessalonikefs 06ff9f20d0 Merge branch 'features/pthread-setname' 2026-04-17 16:22:04 +02:00
W.C.A. Wijngaards af209a12ea - Fix subnet store of servfail to not leak memory. 2026-04-17 13:48:38 +02:00
W.C.A. Wijngaards 84ac7e1b58 - Fix ttl comparisons in rdata_copy for 32bit signed or unsigned. 2026-04-17 13:27:41 +02:00
W.C.A. Wijngaards 24d502763c - Fix to increase size of the buffer for the win_svc reportev log
function.
2026-04-17 11:05:31 +02:00
W.C.A. Wijngaards 99c61c19ac - Fix compat/gmtime_r old style definition syntax. 2026-04-17 11:05:15 +02:00
W.C.A. Wijngaards cb05e9d525 - Fix compat/chacha_private sigma and tau definitions to use
nonstring attribute.
2026-04-17 11:04:51 +02:00
W.C.A. Wijngaards abddd4e270 - Update github ci cross platform to use
cross-platform-actions/action@v1.0.0.
- Fix github ci to speed up with parralel build, for windows ci.
2026-04-17 10:41:24 +02:00
W.C.A. Wijngaards 656b412492 - Update github ci to use actions/checkout@v6. 2026-04-17 10:13:06 +02:00
W.C.A. Wijngaards f15a46fcd4 - Fix to compile the shm code when there is no shmget. 2026-04-17 09:42:35 +02:00
W.C.A. Wijngaards 8d434bf744 - Fix setup of ssl context copy, to check for the tls service
pem option for stat calls.
2026-04-17 09:34:06 +02:00
W.C.A. Wijngaards 13b269d398 - Fix setup of ssl context copy of the tls service pem option,
from a clang analyzer warning.
2026-04-17 09:29:10 +02:00
Yorgos Thessalonikefs 7aff88881a - Fix cleaning up DoH session. The same query can be on multiple
streams in a session.
2026-04-16 11:01:07 +02:00
W.C.A. Wijngaards b97bd3a1fc - Fix configure, autoconf for #1406. 2026-04-16 10:55:57 +02:00
Yorgos Thessalonikefs 6aa5ad85f4 Changelog entry for #1406:
- Merge #1406: Introduce new 'tls-protocols' configuration option.
2026-04-16 10:53:01 +02:00
42b19c20c1 Introduce new 'tls-protocols' configuration option (#1406)
- Introduce new 'tls-protocols' configuration option that specifies
  which of the supported TLS protocols will be used.
  This change invalidates some previous changes:
- TLSv1.2 is again enabled by default, but can be selectively turned off if
  desired (related to #1303).
- The biefly introduced (not yet released) 'tls-use-system-versions'
  configuration option, that addressed #1346, is reverted in favor of
  'tls-protocols'.
- The briefly introduced (not yet released) '--enable-system-tls'
  configure option, related to #1401, is no longer needed with the new
  option and the current default.

- Review comment for checking out of memory condition

Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>
2026-04-16 10:38:24 +02:00
W.C.A. Wijngaards db1fe8b475 - Fix to shorten RRSIG count in scrubber, this protects against
an overly large number of RRSIGs. It can be configured with
  `iter-scrub-rrsig: 8`, it has default 8. Thanks to Yuxiao Wu,
  Tsinghua University for the report.
2026-04-15 11:41:28 +02:00
W.C.A. Wijngaards f4f964f4fb - Fix RFC7766 compliance when client sends EOF over TCP. It stops
pending replies and closes. Thanks to Yuxiao Wu, Tsinghua
  University for the report.
2026-04-15 11:29:07 +02:00
W.C.A. Wijngaards a2272860de - iana portlist updated. 2026-04-14 15:36:33 +02:00
W.C.A. Wijngaards 95083d4377 - Fix clang analyzer warning for subnetmod, when return_msg is
NULL for update cache, like when it stores servfail status.
2026-04-14 15:36:00 +02:00
W.C.A. Wijngaards 5ce0bf5281 - Fix #1017: memory corruption related core dumps.
When alloc_reg_obtain has an empty list, return a new allocation.
2026-04-14 15:34:59 +02:00
Yorgos Thessalonikefs 6a0d5e2cb1 - Update the documentation of 'max-query-restarts' in the man page. 2026-04-13 18:07:01 +02:00
W.C.A. Wijngaards 330d5211c9 - Fix for EDNS client subnet so that it does not store SERVFAIL in
the global cache after a failed lookup, such as timeouts. A failure
  entry is stored in the subnet cache, for the query name, for a
  couple of seconds. Queries can continue to use the subnet cache
  during that time.
2026-04-10 15:45:28 +02:00
Yorgos Thessalonikefs 2dc28a249a - Fix unused variable warning. 2026-04-07 18:03:20 +02:00
W.C.A. Wijngaards c5f14dc880 Changelog comment for #1408
- Merge #1408: Fix shared memory stats with threads.
2026-03-30 16:15:32 +02:00
a2ace114de Fix shared memory stats with threads (#1408)
* - stats-shm-volley, with mesh_time_median the additions add up to the correct
  average that is used.

* - stats-shm-volley, the stat interval is selected with offset.

* - stats-shm-volley, stat totals in separate struct. The first thread zeroes
  it, and the last thread copies it.

* - stats-shm-volley, the array is inited for a new round if one or more

* - stats-shm-volley, the array is inited for a new round if one or more
  threads are not responsive for stat collection.

* - stats-shm-volley review, typos and slightly more detailed text for comments.

---------

Co-authored-by: Yorgos Thessalonikefs <yorgos@nlnetlabs.nl>
2026-03-30 16:13:11 +02:00
W.C.A. Wijngaards 2e9b880718 - Fix defense in depth for service callback with empty packet. 2026-03-27 15:42:45 +01:00
W.C.A. Wijngaards a0ec6cd946 - Fix test code to allow empty hex answer packets from testbound. 2026-03-27 15:39:27 +01:00
W.C.A. Wijngaards ea36979c40 - Fix to allow the control-interface config to use ip@port notation. 2026-03-27 14:29:15 +01:00
W.C.A. Wijngaards 315077b9e6 - Fix to check for invalid http content length and chunk size,
and to check the RR rdata field lengths when decompressing and
  inserting RRs from an authority zone transfer. This stops
  large memory use and heap buffer-overflow read errors. Thanks
  to Haruto Kimura (Stella) for the report.
2026-03-24 08:45:52 +01:00
W.C.A. Wijngaards 535d899bef - Fix for testcode pktview to check buffer size and log errors. 2026-03-20 15:57:46 +01:00
W.C.A. Wijngaards 8656cfd4c8 - Fix to add tls-service-key to memory printout for fast_reload. 2026-03-13 16:49:34 +01:00
W.C.A. Wijngaards 8f44ddb7de - Fix detection of http listening port in fast_reload. 2026-03-13 16:37:41 +01:00
W.C.A. Wijngaards 4484dc3954 - For #278: fast_reload can reload tls-service-key, tls-service-pem
and tls-cert-bundle changes. It checks the modification time of
  the tls-service-key and tls-service-pem files for update.
2026-03-13 16:25:42 +01:00
W.C.A. Wijngaards eb3bba0724 - iana portlist updated. 2026-03-13 12:05:33 +01:00
W.C.A. Wijngaards 2eff1d8ab5 - Fix #278: DoT: complete unbound restart required on certificate
renew. Fix so that a reload checks if the files have changed, and
  if so, reload the contexts. Also for DoH, DoQ and outgoing DoT.
2026-03-13 11:42:34 +01:00
Yorgos Thessalonikefs 4672fa5b53 - Fix to ignore out-of-zone DNAME records for CNAME synthesis. Thanks
to Yuxiao Wu, Yiyi Wang, Zhang Chao, Baojun Liu, and Haixin Duan from
  Tsinghua University.
2026-03-13 11:28:32 +01:00
W.C.A. Wijngaards 18029fc44f Changelog comment for #1418
- Merge #1418: Apply cache TTL policy to DNAME and synthesized
  CNAME on wire path.
2026-03-09 13:54:37 +01:00
Arunabha DasandGitHub 5c6f56f8f1 Apply cache TTL policy to DNAME and synthesized CNAME on wire path (#1418)
When the scrubber synthesizes a CNAME from a DNAME (authority omits CNAME),
apply cache-min-ttl/cache-max-ttl to both DNAME and synthesized CNAME in
msg_parse so they stay equal and respect config (RFC 6672).

- iterator/iter_scrub.c: In synth_cname_rrset(), clamp TTL to [MIN_TTL,
  MAX_TTL] when !SERVE_ORIGINAL_TTL and write back to both synth CNAME
  and DNAME rrset. Removes FIXME.
2026-03-09 13:53:52 +01:00
W.C.A. Wijngaards 9af29c3ed1 - Fix compile failure in unbound-checkconf for older gcc compiler. 2026-03-09 09:18:43 +01:00
Yorgos Thessalonikefs 76ef8c5803 - Constrain the explicit macros for remote.c:fr_atomic_copy_cfg(). 2026-03-06 17:27:21 +01:00
Yorgos Thessalonikefs 94ef1a8fee - Warn for unused 'nodefault' local-zone configuration in
unbound-checkconf (related to #1416).
2026-03-06 17:05:57 +01:00
Yorgos Thessalonikefs 683241a2f5 - Document the suggestion for a higher value for 'outgoing-range';
helps when the request list is full.
2026-03-06 17:01:41 +01:00
W.C.A. Wijngaards 92ab54641e Changelog entry for #1415
- Merge #1415: Add lock unlock for view in memory error handling.
2026-03-06 08:58:33 +01:00
Andy WarnerandGitHub da3812953a Add lock unlock for view in memory error handling (#1415)
view->lock would be skipped during an out of memory error bailout.
2026-03-06 08:57:54 +01:00
W.C.A. Wijngaards 1bd7c8dfee - Update generated man pages. 2026-03-05 12:15:54 +01:00
W.C.A. Wijngaards 8f96ae7acf - Fix for DNS Rebinding Bypass via SVCB/HTTPS Records in Unbound.
Thanks to Kunta Chu, School of Software, Tsinghua University,
  Taofei Guo, Peking University, and Jianjun Chen, Institute for
  Network Sciences and Cyberspace, Tsinghua University for the
  report. The private-address option is fixed to also elide
  SVCB and HTTPS records that match the filter.
2026-03-05 09:47:13 +01:00
Yorgos Thessalonikefs c4f8e60c85 - For #1411: Introduce a failing case in the rpl test so that it only
passes with the fix in place.
2026-03-04 13:22:42 +01:00
W.C.A. Wijngaards a296b248b0 - For #1411: Fix that the lookup for DNAME uses flag. Fix assertion
in expired calc debug routine.
2026-03-03 17:44:31 +01:00
W.C.A. Wijngaards 1ef131299a For #1411, fix up doc/Changelog. 2026-03-03 08:55:56 +01:00
Arunabha DasandGitHub 5b58a872ef Allow synthesized DNAME TTL=0 to be served from cache within grace period (#1411)
* Allow synthesized DNAME TTL=0 to be served from cache within grace period

Addresses doc/TODO: cache TTL=0 packets properly for synthesis.
- rrset_cache_lookup: allow TTL=0 DNAME within 1s grace for synthesis
- synth_dname_msg: support PACKED_RRSET_UPSTREAM_0TTL, return TTL=0 to client

Reduces recursion when authoritative servers return DNAME with TTL=0 (RFC 2308).
Client response still correctly returns TTL=0.

Note: Test with proper TTL=0 DNSSEC RRSIGs omitted - requires ldns-signzone
to generate valid signatures for TTL=0 RRsets.

* Add iter_dname_ttl0.rpl replay test for DNAME TTL=0
Tests signed DNAME with TTL=0 and RRSIG Original TTL=0 (RFC 4034).
Verifies end-to-end handling of TTL=0 DNAME responses.
2026-03-03 08:51:31 +01:00
W.C.A. Wijngaards 94b04d6d46 - Update generated man pages. 2026-02-27 14:33:55 +01:00
W.C.A. Wijngaards f1a65eb4e8 For #1409: Changelog entry and more text. 2026-02-27 13:55:25 +01:00
Daisuke HIGASHIandGitHub 38e1e3eec3 Documentation CNAME in redirect-type local-zone (#1409) 2026-02-27 13:37:56 +01:00
W.C.A. Wijngaards bff3d762ff - Fix validator to set unchecked when validation recursion
requests are passed. The edns subnet module checks if validation
  is needed for a cache response, and set the validator to protect
  the cache with validation for non-subnet lookups.
2026-02-25 10:59:33 +01:00
Yorgos Thessalonikefs fb322f3e87 - Fixed some typos reported in #1395 by rezky_nightky. 2026-02-23 16:17:40 +01:00
Yorgos Thessalonikefs 2feee13735 - Fix to disallow cache lookup/store in external cachedb when a
forwarder/stub forbids it with the no-cache option.
2026-02-23 14:35:50 +01:00
W.C.A. Wijngaards 1d36696462 - Fix to make the cachedb_val_expired.crpl succeed. 2026-02-23 12:52:10 +01:00
W.C.A. Wijngaards aa4e2a9e69 - Fix to have cachedb not return expired bogus data as non-bogus. 2026-02-23 12:45:14 +01:00
W.C.A. Wijngaards 8e04d04949 - For #1405: local-zone always_refuse also blocks queries of type DS. 2026-02-17 15:36:08 +01:00
W.C.A. Wijngaards c5627dbd52 - Fix to remove unused conditional from cookie timestamp at
worker env.
2026-02-17 11:15:15 +01:00
W.C.A. Wijngaards 014ed9c5ff - Fix that cachedb aggressive negative responses have the RA flag set. 2026-02-16 16:35:37 +01:00
Yorgos Thessalonikefs 16e1e6d375 - Fix #1404: Priming the root key fails after loading ipfire.org RPZ
zones. Fixed by including the ZONEMD RRtype in the list of types to
  ignore for RPZ zones. Analysis and patch provided by ummeegge.
2026-02-16 13:37:19 +01:00
W.C.A. Wijngaards 1a9a4e4ca1 - Fix #1403: Inconsistency between do-nat64 and do-not-query-address
during retries.
2026-02-11 16:01:30 +01:00
W.C.A. Wijngaards f7f638e18f - Update generated man pages. 2026-02-09 16:11:17 +01:00
W.C.A. Wijngaards c956aea93d Changelog note and documentation for #1401.
- Merge #1401: Add a new build-time option for system TLS.
  The --enable-system-tls flag enables the
  tls-use-system-policy-versions setting by default.
2026-02-09 16:05:28 +01:00
Petr MenšíkandGitHub 4556a4f490 Add a new build-time option for system TLS (#1401)
We want to use crypto-policy provided configuration always in our
builds. Allow changing the default of tls-use-system-policy-versions at
build time by a simple configure parameter.
2026-02-09 15:57:16 +01:00
Yorgos Thessalonikefs 1cdddf0fe9 - Fix #1389: [FR] replacement with ECC-GOST12 according to RFC9558.
Patch contributed by Igor V. Ruzanov, available in
  contrib/gost12.patch.
2026-02-06 14:39:23 +01:00
Yorgos Thessalonikefs 18fec256b7 - Support pthread_setname_np, and variants, to set the name on spawned
threads for easier debugging/monitoring.
2026-02-06 14:17:04 +01:00
W.C.A. Wijngaards 567c70dada Fix attribution of fix. 2026-02-04 14:17:56 +01:00
W.C.A. Wijngaards 8b4b2a88f7 - Fix local privilege escalation on Windows. Thanks to Hao Huang
for the report. The OpenSSL init calls are set to not load
  the openssl.cnf file when compiled for Windows.
2026-02-04 11:54:11 +01:00
Yorgos Thessalonikefs faf40c97fc - Eagerly remove .skip mark files in between mini_tdir.sh runs in case
there has been a change on the environment.
2026-02-03 15:08:59 +01:00
W.C.A. Wijngaards daa016e3e4 - Add test for allow-notify with a host name. 2026-01-27 13:49:33 +01:00
W.C.A. Wijngaards 039f69e735 - Fix to not skip allow-notify hostname lookups when there are only
urls.
2026-01-26 16:16:38 +01:00
W.C.A. Wijngaards b39009e487 Merge branch 'master' of github.com:NLnetLabs/unbound 2026-01-26 15:17:26 +01:00
W.C.A. Wijngaards 933769ee73 - Fix that allow-notify entries with hostnames are copied after IPv4
and IPv6 lookup.
2026-01-26 15:16:43 +01:00
Yorgos Thessalonikefs 57bff79627 - Update generated man pages. 2026-01-23 18:04:25 +01:00
Yorgos Thessalonikefs 1b5559d534 Changelog entry for #1396:
- Merge #1396: Log Linux thread ID.
- On Linux systems log the system-wide unique thread ID instead of
  Unbound's internal thread counter.
- Introduce the 'log-thread-id' configuration option to manage logging
  the system-wide Linux thread ID for easier debugging with system
  tools.
2026-01-23 17:46:14 +01:00
Yorgos ThessalonikefsandGitHub 9d271c5343 Merge pull request #1396 from NLnetLabs/features/thread-id 2026-01-23 17:42:30 +01:00
Yorgos Thessalonikefs 74cc49e6c4 - Introduce the 'log-thread-id' configuration option to manage logging
the system-wide Linux thread ID for easier debugging with system
  tools.
2026-01-23 17:15:14 +01:00
Yorgos Thessalonikefs d414ebf0c7 - On Linux systems log the system-wide unique thread ID instead of
Unbound's internal thread counter.
2026-01-23 17:08:55 +01:00
W.C.A. Wijngaards 9b123d1b78 - Fix http test tool petal to not print errors when there is no
error.
2026-01-22 14:19:35 +01:00
W.C.A. Wijngaards 37b71261a2 - Fix that fast reload copies the iter_scrub_ns, iter_scrub_cname
and max_global_quota options.
2026-01-22 09:42:56 +01:00
W.C.A. Wijngaards 4426db4d3d - Merge #1388: QNX Porting support for unbound. 2026-01-21 13:13:01 +01:00
nnarayanamurthyandGitHub fe10bc7682 QNX Porting support for unbound branch-1.24.1 (#1388)
* qnx Porting support for version release-1.24.1

* updating __QNXNTO__ with __QNX__
2026-01-21 13:12:13 +01:00
W.C.A. Wijngaards 67d2eae28c - Merge #1392: Include "V" (version) option in synopsis. 2026-01-19 09:09:47 +01:00
David H. GutteridgeandGitHub 9010a7075e Include "V" (version) option in synopsis (#1392) 2026-01-19 09:09:12 +01:00
W.C.A. Wijngaards cc6dbc9f38 - Fix documentation for requestlist.overwritten and
requestlist.exceeded, it explains which query was dropped.
2026-01-15 09:35:04 +01:00
W.C.A. Wijngaards 4198343dbe Compile fixup for #1381. 2026-01-08 14:19:06 +01:00
W.C.A. Wijngaards 08600d68e8 Changelog note for #1381, and man page explanation.
- Merge #1381: Do not initialize quic_table unless it is enabled.
2026-01-08 14:16:54 +01:00
Petr MenšíkandGitHub 18e098285e Do not initialize quic_table unless it is enabled (#1381)
* Do not initialize quic_table unless it is enabled

Fedora in FIPS mode might fail to initialize ngtcp2 library, because
some ciphers desired are not available.

Make it possible to skip initialization by setting explicitly quic_port
to 0. Unless we have some listeners for port 853 configured, skip its
initialization as well.

Related: https://pagure.io/freeipa/issue/9877

* Fix typo in logged function name
2026-01-08 14:12:32 +01:00
Yorgos Thessalonikefs f1b35bab4b Changelog entry for #1391:
- Merge #1391 from Götz Görisch: Fix documentation to adhere to
  RFC5952.
2026-01-06 18:21:34 +01:00
Yorgos ThessalonikefsandGitHub 84ed77238d Merge pull request #1391 from GoetzGoerisch/docs
Fix documentation to adhere to RFC 5952
2026-01-06 18:19:47 +01:00
Goetz Goerisch adb0374a4d Fix documentation to adhere to RFC 5952
Update the text representations of IPv6 addresses.
2026-01-06 16:10:37 +01:00
W.C.A. Wijngaards b0b634558b - Fix edns subnet, that scope zero queries, when there is a
subquery without subnet, and the forward-no-cache or
  stub-no-cache option is set, it is not stored in cache due to
  the forward or stub option.
This has the changelog entry and test.
2026-01-06 09:33:00 +01:00
W.C.A. Wijngaards 8546247292 - Fix edns subnet, that scope zero queries, when there is a
subquery without subnet, and the forward-no-cache or
  stub-no-cache option is set, it is not stored in cache due to
  the forward or stub option.
2026-01-06 09:32:21 +01:00
Yorgos Thessalonikefs 44659cb3bf - Use the same EDE removal logic when encoding errors as when encoding
replies.
2025-12-31 16:22:15 +01:00
Yorgos Thessalonikefs a1ac2d0252 - Update the unbound-anchor man page to note write permissions of the
generated file if it is to be used with Unbound's
  auto-trust-anchor-file option.
2025-12-31 14:05:42 +01:00
Yorgos Thessalonikefs 5c7a26b615 - Mark "THROWAWAY" and "(DNSSEC) LAME" responses clearly as Unbound's
categorization in the log output.
2025-12-30 13:15:37 +01:00
Yorgos Thessalonikefs 09d352b917 - More specific wording in the unbound.conf man page for stub-first
and forward-first options.
2025-12-24 14:57:44 +01:00
W.C.A. Wijngaards c0522043f0 - Fix http2 drop handling to clear the postpone_drop state so that
other streams on the http2 session are not affected by a drop,
  and can clean up properly if also dropped. Fix http2 send reply
  so that when there is a send failure is does not recurse into
  the mesh functions and also does not drop the connection due to
  the condition of one stream.
2025-12-03 14:41:10 +01:00
W.C.A. Wijngaards b858801feb - Fix to remove http2 stream mesh state when mesh new request is
dropping the new request.
2025-12-02 15:31:53 +01:00
W.C.A. Wijngaards 588db09928 - Fix header comment about EDE reference in validator/val_sigcrypt.h. 2025-12-01 16:04:41 +01:00
W.C.A. Wijngaards 5c66c48a1b - Fix to add EDNS CO flag to testbound and debug message log. 2025-12-01 15:29:41 +01:00
Yorgos Thessalonikefs 83336477c6 - For #1375, there is no DNSTAP environment if it wasn't configured. 2025-11-28 15:20:21 +01:00
Yorgos Thessalonikefs e3e5eb66cf - Tag for 1.24.2 release.
The repository continues with version 1.24.3.
2025-11-26 13:54:25 +01:00
Yorgos Thessalonikefs 00d3b97dbb Merge branch 'branch-1.24.2' 2025-11-26 13:50:49 +01:00
Yorgos Thessalonikefs f6269baa60 - Additional fix for CVE-2025-11411 (possible domain hijacking attack),
to include YXDOMAIN and non-referral nodata answers in the mitigation as
  well, reported by TaoFei Guo from Peking University, Yang Luo and JianJun
  Chen from Tsinghua University.
2025-11-26 11:09:40 +01:00
Yorgos Thessalonikefs 19154c6e58 - Set version to 1.24.2. 2025-11-26 10:58:06 +01:00
W.C.A. Wijngaards 0f43b0ea6c Changelog note for #1375, and lock for lockchecks and ifdef for compile fix.
- Merge #1375: Copy DNSTAP changes from daemon to workers after
  fast_reload.
2025-11-13 15:45:27 +01:00
smeddlepandGitHub e6d92f458f Copy DNSTAP changes from daemon to workers after fast_reload (#1375)
- On fast_reload, the identity and version strings are always freed and
  reallocated as part of dt_apply_cfg(). Add fr_worker_pickup_dnstap_changes()
  to copy any changes from daemon to workers.
2025-11-13 15:42:44 +01:00
W.C.A. Wijngaards a31b9d50e2 Changelog note for #1374
- Merge #1374: Mesh reply counters.
  This adds the statistics num.queries.replyaddr_limit and
  requestlist.current.replies.
2025-11-13 09:34:45 +01:00
Robert EdmondsandGitHub fceb4e8585 Mesh reply counters (#1374)
* Statistics counter for number of queries dropped by limit on reply addresses

Request list entries can be associated with multiple pending "reply
addresses". Basically each request list entry keeps its own list of
clients that should receive the response once the recursion is finished.
This requires keeping allocations around for each client, and there is
a global limit on the number of *additional* reply addresses that can
be allocated. (Each new request list entry seems to get its own initial
reply address which is not counted against the limit.)

This commit adds a statistics counter "num_queries_replyaddr_limit" that
counts the number of incoming client queries that have been dropped due
to the restriction on allocating additional reply addresses. This allows
distinguishing these drops from other kinds of drops.

* Statistics counter for number of mesh reply entries

Request list entries can be associated with multiple pending "reply
addresses". Since there is a limit on the number of additional reply
addresses that can be allocated which can cause incoming queries to be
dropped if exceeded, it would be nice to be able to track this number.

This commit basically exports the mesh_area's internal counter
`num_reply_addrs` as "threadX.requestlist.current.replies" /
"total.requestlist.current.replies".
2025-11-13 09:33:05 +01:00
W.C.A. Wijngaards 98f4257890 - iana portlist updated. 2025-11-12 11:49:21 +01:00
W.C.A. Wijngaards 0a15118aff - Fix that when discard timeout drops packet, they are accounted as
less reply addresses in use in the mesh area.
2025-11-12 11:49:04 +01:00
W.C.A. Wijngaards e887a79a92 - Fix configure test for nonstring attribute so that it does not
accept when the compiler prints a warning about an unknown
  attribute.
2025-11-06 15:03:17 +01:00
W.C.A. Wijngaards f9b9050ab8 - Fix configure test for noreturn attribute so it compiles without
warning.
2025-11-06 15:00:08 +01:00
W.C.A. Wijngaards 94735384fd - Fix add comment to worker_handle_request function that explain it. 2025-11-06 14:32:56 +01:00
W.C.A. Wijngaards 5dab0609e5 - Fix dns64 log output to log the default instead of a null string. 2025-11-04 10:19:03 +01:00
Yorgos Thessalonikefs 024c921dbf - Fix #1366: Infra cache does not work correctly for NAT64, by
moving the NAT64 synthesis from the iterator when selecting a target
  address, to the delegation point itself when adding target
  addresses.
2025-11-01 15:10:27 +01:00
Yorgos Thessalonikefs 1a808e2978 - Fix typo; spotted by T3rm1. 2025-10-28 14:42:20 +01:00
Yorgos Thessalonikefs 56ded934de - Fix #1165, document the possible circular dependency when using
host names instead of IP addresses for name servers in stub/forward
  zones and log a warning when spotted in the configuration.
2025-10-27 14:01:10 +01:00
Yorgos Thessalonikefs 98952f11d1 Changelog entry for #1331:
- Merge #1331 from Jitka Plesníková: Replace deprecated $function by
  new $action, for SWIG.
2025-10-27 09:59:35 +01:00
Yorgos ThessalonikefsandGitHub cb4b3de62f Merge pull request #1331 from jplesnik/master
Replace deprecated $function by new $action
2025-10-27 09:57:59 +01:00
Yorgos Thessalonikefs c8dcfc0853 - For #1364, use OPENSSL_VERSION_TEXT instead of OPENSSL_VERSION_NUMBER
for part of the configure script. OPENSSL_VERSION_TEXT is more
  consistent across versions.
2025-10-24 15:43:22 +02:00
Yorgos Thessalonikefs 2bb28fdf12 - Fix unused attribute warning in redis.c when threads are not
supported.
2025-10-24 14:44:58 +02:00
Yorgos Thessalonikefs 6ad26909dd - Note Havard Eidnes for his suggestions on the mailing list. 2025-10-24 14:26:08 +02:00
Yorgos Thessalonikefs 9602973c86 - unbound.conf man page updates to include a preview of the section
clauses and some reformatting around the use of "clause", "option"
  and "attributes".
2025-10-24 14:23:53 +02:00
Yorgos Thessalonikefs 713b1783d4 - Tag for 1.24.1 release.
The repository continues with version 1.24.2.
2025-10-22 12:49:29 +02:00
Yorgos Thessalonikefs e06b7eb3f1 Merge branch 'branch-1.24.1' 2025-10-22 12:44:59 +02:00
Yorgos Thessalonikefs a33f0638e1 - Fix CVE-2025-11411 (possible domain hijacking attack), reported by Yuxiao Wu,
Yunyi Zhang, Baojun Liu and Haixin Duan from Tsinghua University.
2025-10-22 10:54:57 +02:00
Yorgos Thessalonikefs bbeee42e25 - Set version to 1.24.1. 2025-10-22 10:50:18 +02:00
Yorgos Thessalonikefs 1cb9595a42 - Update the unbound.conf online man page link and some text
reformatting in README.md.
2025-10-20 14:34:40 +02:00
Wouter WijngaardsandGitHub aa21e38b3a Fix for analysis and ports workflows iOS, Windows (#1361)
* - Remove SDK_VERSION and only run failed jobs, echo windows config.log

* Use commented out to fix syntax of ci.

* - Turn off succeeded tests, only link libssp for cross compile, use
no-shared for openssl ios.

* - Remove iPhone armv7s, and iPhoneSimulator i386 from ios ci.
  The lib system does not provide symbols for it on the new macos
  runner.
- Fix to exclude libssp for windows compiles.
2025-10-15 16:12:39 +02:00
W.C.A. Wijngaards 964848b94a - Fix unbound.conf man page entry for root-hints to say it can
be used without strongly recommending it.
2025-10-15 15:40:47 +02:00
Yorgos Thessalonikefs a4dd321fd8 - Remove extra gpg instructions from makedist.sh output. 2025-10-15 14:59:48 +02:00
Yorgos Thessalonikefs d23a28a693 - ci: don't fail fast for the analysis_port workflow. 2025-10-15 14:10:20 +02:00
W.C.A. Wijngaards 5423c0a8e9 Update ios ci with older sdk version to use. 2025-10-15 13:41:36 +02:00
W.C.A. Wijngaards 6a5385f291 - Fix to update openssl version in ios ci. 2025-10-15 12:25:44 +02:00
W.C.A. Wijngaards 16f3478048 - Add extended dns error code for invalid query type to definition
list.
2025-10-15 11:39:58 +02:00
W.C.A. Wijngaards c8860a5fb6 - Fix to reply with SERVFAIL when the wait-limit is exceeded. 2025-10-15 11:36:29 +02:00
W.C.A. Wijngaards 735c96aac7 - Fix to drop UDP for discard-timeout, but not stream connections. 2025-10-15 11:04:22 +02:00
W.C.A. Wijngaards a75ea01a15 - Fix #1358 Enabling FIPS in OpenSSL causes unit test to fail. 2025-10-10 09:17:08 +02:00
Yorgos Thessalonikefs 21f02a0865 - Note clearly that 'wait-limit: 0' disables all wait limits.
- 'wait-limit-cookie: 0' can now disable cookie validated wait
  limits.
2025-10-03 16:44:44 +02:00
Yorgos Thessalonikefs e017d66fc1 - Note 'respip' and 'dns64' module order in the unbound.conf
man page.
2025-10-03 11:27:26 +02:00
W.C.A. Wijngaards adaf5dab49 - Fix that https is set up as enabled when the port is listed in
interface-automatic-ports. Also for the set up of quic it is
  enabled when listed there.
2025-10-02 10:16:06 +02:00
W.C.A. Wijngaards feeebc95f8 - Fix for #1344: Fix that respip and dns64 can be enabled at the
same time, the client info is copied for attach_sub and add_sub
  calls. That makes respip work on dns64 synthesized answers, and
  also makes RPZ work with DNS64. The order for the modules is
  module-config: "respip dns64 validator iterator".
2025-09-30 11:28:15 +02:00
W.C.A. Wijngaards 187aa52859 - Fix #1344: module conf 'respip dns64 validator cachedb iterator'
is not known to work.
2025-09-29 16:11:50 +02:00
W.C.A. Wijngaards f1fea8dc46 - Fix #1353: auth-zone can not use empty label for $ORIGIN when
http download.
2025-09-29 14:24:31 +02:00
Yorgos Thessalonikefs 0c01257d1d Changelog entry for #1351:
- Merge #1351: ac_cv_func_malloc_0_nonnull for malloc(0) check.
2025-09-29 13:14:07 +02:00
W.C.A. Wijngaards 50a11ebcc8 - Rebuild configure script from its sources. 2025-09-29 13:13:15 +02:00
Yorgos ThessalonikefsandGitHub 1e2dc657a1 ac_cv_func_malloc_0_nonnull for malloc(0) check (#1351)
- For #1339, use the standard variable ac_cv_func_malloc_0_nonnull for
  the malloc(0) check during configure; patch from Helmut Grohne.
2025-09-29 13:12:27 +02:00
Yorgos Thessalonikefs 843124852f Changelog entry for #1349:
- Merge #1349: Fix #1346: [FR] Please allow back TLS 1.2.
2025-09-29 12:10:34 +02:00
W.C.A. Wijngaards 5e2fdff8e5 - Fix fr_atomic_copy_cfg. 2025-09-29 12:08:30 +02:00
499a3a7a61 Fix #1346: [FR] Please allow back TLS 1.2. (#1349)
* 'tls-use-system-policy-versions' is introduced to allow Unbound to use
  any system available TLS version when serving TLS.

* Apply suggestions from code review

---------

Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>
2025-09-29 12:03:56 +02:00
W.C.A. Wijngaards 2024c1d050 - Neaten up the change in acx_nlnetlabs.m4 to version 49. 2025-09-29 11:40:14 +02:00
W.C.A. Wijngaards 6cd595a816 - Fix modstack_call_init to use the original string when it has
changed, to call modstack_config with. And skip the changed name
  in the string correctly. Thanks to Jan Komissar.
2025-09-29 11:31:50 +02:00
W.C.A. Wijngaards 74cf81e9a7 - Rebuild configure script from its sources. 2025-09-29 10:02:54 +02:00
Yorgos Thessalonikefs 35f6fd47fb - Test for nonstring attribute in configure and add
nonstring attribute annotations.
2025-09-26 16:23:55 +02:00
Alex BandandGitHub 270e099aab Update Mastodon shield 2025-09-25 21:39:39 +02:00
Yorgos Thessalonikefs 64645e1401 - Avoid calling mesh_detect_cycle_found() when there is no mesh state
to begin with.
2025-09-24 14:30:24 +02:00
Yorgos Thessalonikefs 421d317a64 - For #1350, same CAP_NET_ADMIN change for unbound_portable.service.in
as well.
2025-09-23 17:42:41 +02:00
Yorgos Thessalonikefs 0b8ed987de Changelog entry for #1350:
- Merge #1350 from Maryse47: unbound.service.in: allow CAP_NET_ADMIN.
2025-09-23 17:37:59 +02:00
Yorgos ThessalonikefsandGitHub 9511797487 Merge pull request #1350 from Maryse47/patch-1
unbound.service.in: allow CAP_NET_ADMIN and drop CAP_NET_RAW (redundant now).
2025-09-23 17:37:09 +02:00
Yorgos Thessalonikefs 0b7bb75152 - For #1352, align with the current Python<3 code. 2025-09-23 17:31:55 +02:00
Yorgos Thessalonikefs 88c688ec10 Changelog entry for #1352:
- Merge #1352 from Petr Vaganov: pythonmod: fix HANDLE_LEAK on
  pythonmod_init.
2025-09-23 17:15:16 +02:00
Maryse47andGitHub 81fd1dc71c unbound.service.in: drop CAP_NET_RAW
CAP_NET_RAW is unnecessary after CAP_NET_ADMIN was added
2025-09-23 17:13:31 +02:00
Yorgos ThessalonikefsandGitHub 69217cf675 Merge pull request #1352 from petrvaganoff/dev-52227
pythonmod: fix HANDLE_LEAK on pythonmod_init
2025-09-23 17:13:30 +02:00
Petr Vaganov 7c28f1b99c pythonmod: fix HANDLE_LEAK on pythonmod_init
Found by the static analyzer Svace (ISP RAS).

Handle 'script_py' is created at pythonmod.c:436
by calling function 'fopen' and lost at pythonmod.c:457,465.

Signed-off-by: Petr Vaganov <petrvaganoff@gmail.com>
2025-09-23 19:51:46 +05:00
Maryse47andGitHub fa6340cfa5 unbound.service.in: allow CAP_NET_ADMIN
Allowing CAP_NET_ADMIN is necessary for SO_SNDBUFFORCE and SO_RCVBUFFORCE calls.
2025-09-23 13:00:50 +02:00
Yorgos Thessalonikefs e471e15774 - unbound.conf manpage: explicitly mention RFC6891. 2025-09-19 15:49:07 +02:00
Yorgos Thessalonikefs ec3db03121 Changelog entry for #1337:
- Merge #1337: 0 TTL cached replies and some TTL behavior changes.
2025-09-19 15:01:30 +02:00
Yorgos Thessalonikefs e2bf773089 Merge branch 'features/no-ttl-zero-cacherep' 2025-09-19 14:56:04 +02:00
Yorgos Thessalonikefs 3017a0aa52 - Update README.man with clearer text. 2025-09-19 10:03:10 +02:00
W.C.A. Wijngaards 8419e9780e - Fix to remove configure~ from release tarballs. 2025-09-19 09:46:34 +02:00
W.C.A. Wijngaards c429c4ab96 - Tag for 1.24.0 release. Includes the fixes below after rc1.
The repository continues with version 1.24.1.
2025-09-18 10:57:37 +02:00
bc61034f60 code review: use proper roundrobin index
Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>
2025-09-17 12:19:20 +02:00
Yorgos Thessalonikefs 2dd821c257 - Too many quotes for the EDE message debug printout. 2025-09-17 11:27:16 +02:00
W.C.A. Wijngaards 713b5db537 - Fix to print warning for when so-sndbuf setsockopt is not granted. 2025-09-15 16:11:27 +02:00
Yorgos Thessalonikefs c3a8d5251f - Small debug output improvement when attaching an EDE. 2025-09-15 12:06:49 +02:00
Yorgos Thessalonikefs 73e408f1d0 A few changes for TTL processing:
- Cached messages that reach 0 TTL are considered expired. This prevents
  Unbound itself from issuing replies with TTL 0 and possibly causing a
  thundering herd at the last second. Upstream replies of TTL 0 still
  get the usual pass-through but they are not considered for caching
  from Unbound or any of its caching modules.
- 'serve-expired-reply-ttl' is changed and is now capped by the original
  TTL value of the record to try and make some sense when replying
  with expired records.
- TTL decoding was updated to adhere to RFC8767 section 4 where a set
  high-order bit means the value is positive instead of 0.
2025-09-15 10:03:35 +02:00
Yorgos Thessalonikefs d521135f66 Merge branch 'master' into features/no-ttl-zero-cacherep 2025-09-12 15:24:06 +02:00
W.C.A. Wijngaards d71ead5598 - Update contrib/aaaa-filter-iterator.patch so it applies on 1.24.0. 2025-09-11 13:23:51 +02:00
W.C.A. Wijngaards cdbfadfb7b - version set to 1.24.0 for release.
- tag for 1.24.0rc1.
2025-09-11 09:03:40 +02:00
W.C.A. Wijngaards 4267de87b5 - Fix #1332: CNAME chains are sometimes not followed when RPZs add a
local CNAME rewrite.
2025-09-09 12:34:11 +02:00
Yorgos Thessalonikefs dd6200065f - Update man pages. 2025-09-08 14:50:27 +02:00
Yorgos Thessalonikefs a72177e73c - Update documentation for using "SET ... EX" in Redis.
- Document max buffer sizes for Redis commands.
2025-09-08 14:49:12 +02:00
Jitka Plesnikova 1d3d78dff5 Replace deprecated $function by new $action
The long-deprecated $function was removed from future SWIG 4.4.0.
It can be safely replaced by $action.
2025-09-08 10:11:49 +02:00
W.C.A. Wijngaards 5588f66bdb - For #1328: make depend. 2025-09-03 14:04:24 +02:00
W.C.A. Wijngaards 85e916e7e0 - Fix indentation in tcp-mss option parsing. 2025-09-02 17:12:14 +02:00
W.C.A. Wijngaards af96824642 - Fix #1324: Memory leak in 'msgparse.c' in
'parse_edns_options_from_query(...)'.
2025-09-02 17:10:42 +02:00
W.C.A. Wijngaards 8faa95354d - Fix #1235: Outdated Python2 code in
unbound/pythonmod/examples/log.py.
2025-09-02 12:54:03 +02:00
W.C.A. Wijngaards c57c39833e - Fix for #1324: Fix to free edns options scratch in ratelimit case. 2025-09-01 09:28:29 +02:00
Yorgos Thessalonikefs 44da5eee66 - Limit the number of consecutive reads on an HTTP/2 session.
Thanks to Gal Bar Nahum for exposing the possibility of infinite
  reads on the session.
2025-08-29 15:35:32 +02:00
W.C.A. Wijngaards 74bc8c9e77 - Fix setup_listen_sslctx warning for nettle compile. 2025-08-28 14:19:52 +02:00
W.C.A. Wijngaards 0c558cb805 - Fix unbound-control dump_cache for double unlock of lruhash table.
Changelog entry.
2025-08-27 16:55:55 +02:00
W.C.A. Wijngaards 533291dce9 - Fix unbound-control dump_cache for double unlock of lruhash table. 2025-08-27 16:55:38 +02:00
W.C.A. Wijngaards e613e27f35 - Fix ports workflow to install expat for macos. 2025-08-26 14:41:13 +02:00
W.C.A. Wijngaards f2f36a2733 - Fix that the zone acquired timestamp is set after the
zonefile is read.
2025-08-22 14:06:51 +02:00
W.C.A. Wijngaards 78d9bcacb6 - Fix #1319: [FR] zone status for Unbound auth-zones. 2025-08-22 12:40:00 +02:00
W.C.A. Wijngaards c170ed1b30 - Fix sha1 enable environment variable in test code on windows. 2025-08-22 10:04:57 +02:00
W.C.A. Wijngaards ebfa09e04f - For #1318: Fix compile warnings for DoH compile on windows. 2025-08-22 10:04:00 +02:00
W.C.A. Wijngaards 65be1d0ec3 - Fix for #1317: Fix contrib/unbound.service comment path for
systemd network configuration.
2025-08-21 15:49:42 +02:00
W.C.A. Wijngaards ca36e21f71 - Fix #1317: Unbound starts too early. Add
Wants=network-online.target under [Unit] in unbound.service.
2025-08-21 15:14:42 +02:00
W.C.A. Wijngaards 458c793012 - Fix to check for extraneous command arguments for unbound-control,
when the command takes no arguments but there are arguments present.
Changelog note for the fix.
2025-08-21 10:00:41 +02:00
W.C.A. Wijngaards 1341905de8 - Fix to check for extraneous command arguments for unbound-control,
when the command takes no arguments but there are arguments present.
2025-08-21 09:47:24 +02:00
W.C.A. Wijngaards 1d877400ea - Fix cache_lookup subnet print to not print messages without rrsets
and perform in-depth check on node in the addrtree.
2025-08-15 16:04:34 +02:00
W.C.A. Wijngaards 8fd4b91afc - Fix cache_lookup subnet print to not print messages without rrsets
and perform in-depth check on node in the addrtree.
2025-08-15 16:04:23 +02:00
W.C.A. Wijngaards 523710f371 - Fix cache_lookup subnet printout to wipe zero part of the prefix.
Changelog entry.
2025-08-15 14:07:05 +02:00
W.C.A. Wijngaards 13bb78a740 - Fix cache_lookup subnet printout to wipe zero part of the prefix. 2025-08-15 14:06:54 +02:00
W.C.A. Wijngaards 1e37f86ef5 - unbound-control cache_lookup +t allows tld and root names. And
subnet cache contents are printed.
Changelog, documentation and unit test.
2025-08-15 13:03:31 +02:00
W.C.A. Wijngaards 81345fe1e3 - unbound-control cache_lookup +t allows tld and root names. And
subnet cache contents are printed.
2025-08-15 13:03:00 +02:00
W.C.A. Wijngaards 40877f46e5 - Fix to decouple file descriptor activity and cache lookups in
dump_cache.
Changelog note.
2025-08-14 12:20:22 +02:00
W.C.A. Wijngaards 991108af8d - Fix to decouple file descriptor activity and cache lookups in
dump_cache.
2025-08-14 12:20:10 +02:00
W.C.A. Wijngaards 4f790bd65e - Fix to increase responsiveness of dump_cache. 2025-08-14 11:25:40 +02:00
W.C.A. Wijngaards d122ae6490 - Fix to unlock cache_lookup message for malformed records. 2025-08-13 12:02:41 +02:00
W.C.A. Wijngaards 651a71fa76 - Fix to remove debug from cache_lookup. 2025-08-13 11:59:53 +02:00
W.C.A. Wijngaards 2f7890eb6e - unbound-control cache_lookup <domains> prints the cached rrsets
and messages for those.
Changelog and information.
2025-08-13 11:36:47 +02:00
W.C.A. Wijngaards fad747308f - unbound-control cache_lookup <domains> prints the cached rrsets
and messages for those.
2025-08-13 11:31:42 +02:00
W.C.A. Wijngaards d55f20fdcc - Fix that unbound-control dump_cache releases the cache locks
every so often, so that the server stays responsive.
Changelog entry for it.
2025-08-12 12:00:01 +02:00
W.C.A. Wijngaards 19b289feec - Fix that unbound-control dump_cache releases the cache locks
every so often, so that the server stays responsive.
2025-08-12 11:59:48 +02:00
W.C.A. Wijngaards 752a3f7f52 - Fix to whitespace in dname_str. 2025-08-07 16:19:10 +02:00
W.C.A. Wijngaards 3ec5d78ac9 - Fix that edns-subnet failure to create a subquery errors as
servfail, and not formerror.
2025-08-07 16:09:47 +02:00
W.C.A. Wijngaards 08d59c9a78 - Fix dname_str for printout of long names. Thanks to Jan Komissar
for the fix.
2025-08-07 09:45:02 +02:00
W.C.A. Wijngaards cdcc0337d1 - Fix edns subnet, so that the subquery without subnet is stored in
global cache if the querier used 0.0.0.0/0 and the name and address
  do not receive subnet treatment. If the name and address are
  configured for subnet, it is stored in the subnet cache.
2025-08-06 12:08:44 +02:00
W.C.A. Wijngaards 305adf12bf - Fix edns subnet, so that the subquery without subnet is stored in
global cache if the querier used 0.0.0.0/0 and the name and address
  do not receive subnet treatment. If the name and address are
  configured for subnet, it is stored in the subnet cache.
2025-08-06 12:01:42 +02:00
W.C.A. Wijngaards 3d7e847a5e - Fix to use assertions for consistency checks in #1309 reclaimed 2025-08-05 16:20:01 +02:00
W.C.A. Wijngaards da6b735ed9 - Fix #1309: incorrectly reclaimed tcp handler can cause data
corruption and segfault.
2025-08-05 15:46:54 +02:00
W.C.A. Wijngaards 5758427d86 - Fix testbound test program to accurately output packets from hex. 2025-08-01 10:34:12 +02:00
W.C.A. Wijngaards 4f12148af4 - Fix redis cachedb module gettimeofday init failure.
Changelog note for the fix.
2025-07-28 09:33:42 +02:00
W.C.A. Wijngaards f8f4779f1f - Fix redis cachedb module gettimeofday init failure. 2025-07-28 09:32:55 +02:00
W.C.A. Wijngaards da9ab59e10 - Redis checks for server down and throttles reconnects.
And unit test for redis reconnect interval.
2025-07-24 11:06:00 +02:00
W.C.A. Wijngaards 424f86466a - Redis checks for server down and throttles reconnects. 2025-07-24 11:05:25 +02:00
W.C.A. Wijngaards 910288c0d1 - iana portlist updated. 2025-07-17 14:50:29 +02:00
W.C.A. Wijngaards b6e52c0a52 - Fix #1303: [FR] Disable TLSv1.2. 2025-07-17 14:50:13 +02:00
W.C.A. Wijngaards b58af78b63 - Fix to not set rlimits in the unit tests. 2025-07-17 11:40:31 +02:00
W.C.A. Wijngaards a1150078f2 - Add unit tests for non-ecs aggregation. 2025-07-16 11:46:04 +02:00
W.C.A. Wijngaards f49e6ccecd - Fix for RebirthDay Attack CVE-2025-5994, reported by Xiang Li
from AOSP Lab Nankai University.
- Tag for 1.23.1 with the release of 1.23.0 and the CVE fix, the
  repository continues with the previous fixes, with 1.23.2.
2025-07-16 11:40:32 +02:00
W.C.A. Wijngaards ad0e0fc290 Merge branch 'branch-1.23.1' 2025-07-16 11:34:44 +02:00
W.C.A. Wijngaards 5bf82f2464 - Fix RebirthDay Attack CVE-2025-5994, reported by Xiang Li from AOSP
Lab Nankai University.
2025-07-16 10:02:01 +02:00
W.C.A. Wijngaards 20f862de51 - Set version to 1.23.1. 2025-07-16 10:00:39 +02:00
Yorgos Thessalonikefs 46823f7bc3 - Update man page templates from rst. 2025-07-12 17:37:54 +02:00
Yorgos Thessalonikefs dd3ac53ff1 - For #1289: add num.valops in the unbound-control man page. 2025-07-12 17:35:16 +02:00
Yorgos Thessalonikefs 1a6052fcac - For #1289: test num.valops in existing stat_values.tdir. 2025-07-12 17:33:43 +02:00
Yorgos Thessalonikefs 6689f0b4da Changelog entry for #1289:
- Merge #1289 from Roland van Rijswijk-Deij: Add extra statistic to
  track the number of signature validation operations.
  Adds 'num.valops' to extended statistics.
2025-07-12 16:35:02 +02:00
44ac818f87 Add extra statistic to track the number of signature validation operations (#1289)
* Add extra statistic to track the number of signature validation operations performed by the validator module

* Move validation operation statistic to mesh as suggested

* Fix NULL pointer dereference in case the mesh is not used (and is `NULL`)

Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>

* Fix NULL pointer dereference on qstate and qstate->env in unit test situation

---------

Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>
2025-07-12 16:29:38 +02:00
W.C.A. Wijngaards b4e12030e7 - For #1301: configure cant find SSL_is_quic in OpenSSL 3.5.1. 2025-07-11 15:58:50 +02:00
W.C.A. Wijngaards 9fe92d1119 - Fix detection of SSL_CTX_set_tmp_ecdh function. 2025-07-11 15:47:59 +02:00
W.C.A. Wijngaards 6ba2d6840b - Fix to improve dnstap discovery on Fedora. 2025-07-08 09:29:27 +02:00
W.C.A. Wijngaards 1de9d6ec66 - Fix layout of comm_point_udp_ancil_callback. 2025-07-03 15:57:49 +02:00
W.C.A. Wijngaards cb919d5126 - For #1300: implement sock-queue-timeout for FreeBSD as well. 2025-07-03 15:54:33 +02:00
W.C.A. Wijngaards 444c839474 - Fix #1300: Is 'sock-queue-timeout' a linux only feature. 2025-07-03 14:10:46 +02:00
W.C.A. Wijngaards 0276bcbceb Changelog note for #1299
- Generate ltmain.sh and configure again.
2025-07-02 10:57:23 +02:00
Jose Luis DuranandGitHub 41c55ffac1 Fix typos (#1299) 2025-07-02 10:50:49 +02:00
Yorgos Thessalonikefs 4200d23882 - For #1247, replay test (added tcp_transport to
outnet_serviced_query).
2025-06-25 14:02:47 +02:00
Yorgos Thessalonikefs e2814fe165 - For #1247, turn off fetch-policy for delegation when looking into
parent side name servers that may not update the addresses and hit
  NXNS limits.
2025-06-25 13:59:17 +02:00
Yorgos Thessalonikefs ca153f4657 - Fix #1247: forward-first: ssl handshake failed on root nameservers. 2025-06-25 13:56:50 +02:00
Yorgos Thessalonikefs ee607c0f72 Changelog entry for #1293:
- Fix #1293: EDE 6 is attached to insecure cached answers when client
  sends the CD bit.
2025-06-20 14:11:22 +02:00
Yorgos Thessalonikefs 2d90d5d729 - Fix #1293: EDE 6 is attached to insecure cached answers when client sends
the CD bit.
2025-06-20 14:09:30 +02:00
W.C.A. Wijngaards ce72770f61 - Fix rrset cache create allocation failure case. 2025-06-19 16:27:13 +02:00
W.C.A. Wijngaards de93a636da Changelog note for #1297
- Merge #1297: edns-subnet: fix NULL_AFTER_DEREF on subnetmod.
2025-06-19 16:24:54 +02:00
KostyaandGitHub d3f88d008f edns-subnet: fix NULL_AFTER_DEREF on subnetmod (#1297)
Found by static analyzer svace.
Static analyzer message: Redundant comparison with a NULL value at subnetmod.c:236 for pointer 'sn_env->subnet_msg_cache',
which was dereferenced at slabhash.c:228 by passing as 1st parameter to function 'slabhash_setmarkdel' at subnetmod.c:235.

Moved usage of sn_env->subnet_msg_cache in slabhash_setmarkdel after checking.

Signed-off-by: Konstantin Kamanin <bewflast@gmail.com>
2025-06-19 16:24:21 +02:00
W.C.A. Wijngaards a1d68cdc96 - Fix #1296: DNS over QUIC depends on a very outdated version of
ngtcp2. Fixed so it works with ngtcp2 1.13.0 and OpenSSL 3.5.0.
2025-06-19 14:39:45 +02:00
Yorgos Thessalonikefs 9201c75013 - Fix for consistent use of local zone CNAME alias for configured auth
zones. Now it also applies to downstream configured auth zones.
2025-06-17 15:03:29 +02:00
W.C.A. Wijngaards f066d6d453 - Fix #1295: Windows 32-bit binaries download seems to be missing dll
dependency.
2025-06-16 14:26:54 +02:00
W.C.A. Wijngaards a04bd5da29 - Fix to check control-interface addresses in unbound-checkconf. 2025-06-16 12:43:31 +02:00
W.C.A. Wijngaards e4cf7aeccf - Fix header return value description for skip_pkt_rrs and
parse_edns_from_query_pkt.
2025-06-12 12:17:01 +02:00
W.C.A. Wijngaards a8aa1dbbe1 - Fix conditional expressions with parentheses for bitwise and. 2025-06-11 16:42:43 +02:00
W.C.A. Wijngaards 9f29292839 - Fix bitwise operators in conditional expressions with parentheses. 2025-06-11 15:46:31 +02:00
W.C.A. Wijngaards 1cc1e0b89e - iana portlist updated. 2025-06-05 11:11:56 +02:00
W.C.A. Wijngaards 565bce670c - Fix comment for the dname_remove_label_limit_len function. 2025-06-05 11:11:32 +02:00
W.C.A. Wijngaards c0563f43b0 - Fix unbound-anchor certificate file read for line ends and end of
file.
2025-06-05 11:09:53 +02:00
Yorgos Thessalonikefs 81f3de4da2 - Small man page corrections for the 'disable-dnssec-lame-check' option. 2025-06-03 14:12:27 +02:00
W.C.A. Wijngaards ff7dfd52a2 - Fix #1288: [FR] Improve fuzzing of unbound by adapting the netbound
program.
2025-05-21 12:41:54 +02:00
Yorgos Thessalonikefs 342a0f48e3 - Add more checks about respip in unbound-checkconf.
Also fixes #310: unbound-checkconf not reporting RPZ configuration
  error.
2025-05-20 16:21:02 +02:00
Yorgos Thessalonikefs 71ac59e6f4 Changelog entry for #1285:
- Merge #1285:  RST man pages.
2025-05-20 12:23:32 +02:00
Yorgos ThessalonikefsandGitHub 6662f71732 RST man pages (#1285)
Introduce restructuredText man pages to sync the online and source code man page documentation.
The templated man pages (*.in) are still part of the repo but generated with docutils from their .rst counterpart.
Documentation on how to generate those (mainly for core developers) are in README.man.
2025-05-20 12:20:20 +02:00
W.C.A. Wijngaards 32644937b0 - Fix for cname chain length with qtype ANY and qname minimisation.
Thanks to Jim Greenwood from Nominet for the report.
2025-05-19 13:17:21 +02:00
W.C.A. Wijngaards 1634beb4a0 - Fix config of slab values when there is no config file. 2025-05-15 14:34:18 +02:00
W.C.A. Wijngaards 1ef7b4a246 - Adjusted so-sndbuf default to 4m. 2025-05-13 15:31:05 +02:00
W.C.A. Wijngaards 03772d10fb - Change default for so-sndbuf to 1m, to mitigate a cross-layer
issue where the UDP socket send buffers are exhausted waiting
  for ARP/NDP resolution. Thanks to Reflyable for the report.
2025-05-13 15:04:32 +02:00
Yorgos Thessalonikefs 9152c914af - Fix #1282: log-destaddr fail on long ipv6 addresses. 2025-05-13 11:02:58 +02:00
Yorgos Thessalonikefs a35ac5d82e - Fix #1284: NULL pointer deref in az_find_nsec_cover() (latent bug)
by adding a log_assert() to safeguard future development.
2025-05-13 11:00:23 +02:00
W.C.A. Wijngaards 21e3278400 - Fix #1283: Unsafe usage of atoi() while parsing the configuration
file.
2025-05-12 14:57:42 +02:00
Yorgos Thessalonikefs 8e1deede08 Changelog entry for #1280:
- Merge #1280: Fix auth nsec3 code. Fixes NSEC3 code to not break on
  broken auth zones that include unsigned out of zone (above apex)
  data. Could lead to hang while trying to prove a wildcard answer.
2025-05-12 14:29:11 +02:00
Yorgos ThessalonikefsandGitHub 4e23523d1a Fix auth nsec3 code (#1280)
- Fix NSEC3 code to not break on broken auth zones that include unsigned
  out of zone (above apex) data. Could lead to hang while trying to
  prove a wildcard answer.
  Reported by Dmitrii Kuvaiskii from Amazon Web Services.

- Tests for NSEC3 auth zones with out of zone data.
2025-05-12 14:26:47 +02:00
W.C.A. Wijngaards 8190526250 - Fix #1281: forward-zone "name: ." conflicts with auth-zone "name: ."
in 1.23.0, but worked in 1.22.0.
2025-05-09 16:01:41 +02:00
Yorgos Thessalonikefs 5dd14e2644 - Sync unbound and unbound-checkconf log output for unknown modules. 2025-05-05 14:47:12 +02:00
Yorgos Thessalonikefs b50faccb1d Changelog entry for #1276:
- Merge #1276: Auto-configure '-slabs' values.
2025-04-29 15:23:07 +02:00
fcc21885e4 Auto-configure '-slabs' values (#1276)
- Auto-configure '-slabs' values to a power of 2 value close to num-threads
  by default for multi-threaded environments.

Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>
2025-04-29 15:21:47 +02:00
W.C.A. Wijngaards a904a3a2c2 - Fix dnstap to use protoc. 2025-04-29 12:43:56 +02:00
W.C.A. Wijngaards c253c8367a - Fix for parallel build of dnstap protoc-c output. 2025-04-29 12:38:41 +02:00
Yorgos Thessalonikefs 0f95fae445 Changelog entry for #1275:
- Merge #1275: Use macros for the fr_check_changed* functions.
2025-04-28 15:50:03 +02:00
Yorgos ThessalonikefsandGitHub e5bbc36ae0 Use macros for the fr_check_changed* functions (#1275) 2025-04-28 15:48:45 +02:00
W.C.A. Wijngaards c88fa02c18 - Fix #1272: assertion failure testcode/unitverify.c:202. 2025-04-25 11:12:28 +02:00
W.C.A. Wijngaards e794234ac8 - Tag for 1.23.0rc2. This became the release of 1.23.0 on 24 April
2025. The code repository continues with 1.23.1 in development.
2025-04-24 10:17:45 +02:00
W.C.A. Wijngaards db53ebb798 Merge branch 'branch-1.23.0' 2025-04-24 10:14:02 +02:00
W.C.A. Wijngaards fe835f9d52 - Increase default to num-queries-per-thread: 2048, when unbound is
compiled with libevent. It makes saturation of the task queue more
  resource intensive and less practical. Thanks to Shiming Liu,
  Network and Information Security Lab, Tsinghua University for the
  report.
2025-04-16 12:03:08 +02:00
Yorgos Thessalonikefs 30c13d0351 Changelog entry for #1265:
- Merge #1265: Fix WSAPoll.
2025-04-11 15:10:46 +02:00
Yorgos Thessalonikefs d6e8ac1289 Fix WSAPoll (#1265)
* Fix calling WSAPoll.

* fast_reload: explicitly set tcp_wouldblock on Windows when there is no
  command to read from the fast_reload thread.

* For poll(), also check for ENOMEM (Linux).

* Remove ifdefs for ENOMEM.
* Some systems return EAGAIN for poll.
2025-04-11 15:09:07 +02:00
Yorgos Thessalonikefs 9c99b404a1 Changelog entry for #1265:
- Merge #1265: Fix WSAPoll.
2025-04-11 15:07:25 +02:00
Yorgos ThessalonikefsandGitHub 75e8fd7539 Fix WSAPoll (#1265)
* Fix calling WSAPoll.

* fast_reload: explicitly set tcp_wouldblock on Windows when there is no
  command to read from the fast_reload thread.

* For poll(), also check for ENOMEM (Linux).

* Remove ifdefs for ENOMEM.
* Some systems return EAGAIN for poll.
2025-04-11 15:05:52 +02:00
W.C.A. Wijngaards 16ee7cf944 - Fix for print of connection type in log-replies for dot and doh. 2025-04-10 09:33:51 +02:00
W.C.A. Wijngaards 38026a21ee Merge branch 'master' into branch-1.23.0 2025-04-09 14:20:22 +02:00
W.C.A. Wijngaards 4f06e658d1 - Fix #1264: unbound 1.22.0 leaks memory when doing DoH. 2025-04-09 14:13:58 +02:00
W.C.A. Wijngaards fca3ae0535 - Fix to detect if atomic_store links in configure. 2025-04-09 11:06:25 +02:00
W.C.A. Wijngaards 66b3abc803 Merge branch 'branch-1.23.0' of github.com:NLnetLabs/unbound into branch-1.23.0 2025-04-08 15:43:05 +02:00
W.C.A. Wijngaards 922c5c3ab3 - Fix fast_reload to print chroot with config file name. 2025-04-08 15:42:56 +02:00
Yorgos Thessalonikefs f9d740dfdc - Update to the manpage for the fast_reload part. 2025-04-08 15:34:51 +02:00
W.C.A. Wijngaards 5eb1382fc0 - Tag for 1.23.0rc1. 2025-04-08 08:37:30 +02:00
Yorgos Thessalonikefs e94e140f49 - More explicit text about memory usage during fast_reload. 2025-04-07 16:56:38 +02:00
Yorgos Thessalonikefs db6505eb8b Changelog entry for #902:
- Merge #902: DNS Error Reporting (RFC 9567). Introduces new
  configuration option 'dns-error-reporting' and new statistics for
  'num.dns_error_reports'.
2025-04-07 10:28:37 +02:00
a616437338 DNS Error Reporting (RFC 9567) (#902)
* v1 EDER poc

* remove superfluous edns_list_get_option function

* create an EDER configurable

* Hackathon 114

* Fixes for version -04

* Generated configparser and configlexer are not versioned in master anymore

* Remove NOERROR DNS Error Reporting; not part of final RFC.
* Use assigned IANA EDNS0 Option Code for Report-Channel.

* Fix buffer protection and agent domain validity

* Use DNS Error Reporting instead of the eder nickname

* Update documentation.

* Fix typo.

* Bail out early if ede is not present.

* Forget previous EDNS options from upstream; this is what was
  implicitly happening but not deterministacally.

* Don't report LDNS_EDE_OTHER and bail early if there is no reporting
  agent.

* Only do DNS error reporting when a client asked for something that
  went wrong.

* Add an error reporting agent in the parent that should be ignored.

* review feedback.

* fixup for fast reload

* Add 'num.dns_error_reports' to stats and test for it.

---------

Co-authored-by: TCY16 <tom@nlnetlabs.nl>
Co-authored-by: Yorgos Thessalonikefs <yorgos@nlnetlabs.nl>
2025-04-07 10:25:10 +02:00
W.C.A. Wijngaards eb390dd038 - Fix to update common.sh for speed of kill_pid. 2025-04-04 11:55:42 +02:00
W.C.A. Wijngaards 4074a5b2ba - Fix test to speed up common.sh script kill_pid. 2025-04-04 11:37:42 +02:00
W.C.A. Wijngaards a7e618b9c2 Fix typo in Changelog entry. 2025-04-04 11:00:16 +02:00
Yorgos Thessalonikefs 349721a39d Changelog entry for #1019:
- Merge #1019: Redis read-only replica support.
  Introduces new 'redis-replica-*' options for the Redis cache backend.
2025-04-04 10:58:59 +02:00
W.C.A. Wijngaards ed71f72baa - Fix redis_replicat test for unused option defaults and log printout. 2025-04-04 10:57:53 +02:00
W.C.A. Wijngaards 0e5d26807d - Fix nettle compile for warnings and ticket keys. 2025-04-04 10:30:22 +02:00
90243a694a Redis read-only replica support (#1019)
* Set version to 1.19.1 for point release.

* Initial work for Redis read-only replica support.

* Test for Redis replica.

* Documentation for the Redis replica timeouts.

* redis replica, rewrite set_timeout()

* clean merge.

* Add new options for fast reload.

* Apply suggestions from code review

Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>

* some more typos

---------

Co-authored-by: W.C.A. Wijngaards <wouter@nlnetlabs.nl>
Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>
2025-04-04 10:20:47 +02:00
W.C.A. Wijngaards 7fb6f9d613 - Fix comment name in the rpz nsdname test. 2025-04-04 08:58:54 +02:00
W.C.A. Wijngaards 7fb05c01c2 - Fix mesh_copy_client_info to omit null contents from copy. 2025-04-04 08:57:24 +02:00
W.C.A. Wijngaards cb5a019d9f - Fix parameter unused warning in net_help.c. 2025-04-03 15:21:16 +02:00
W.C.A. Wijngaards 53ecdb25ef - Fix test for stat_values for wait limit defaults for localhost. 2025-04-03 14:50:30 +02:00
W.C.A. Wijngaards 9939d5cdb0 - Fix ub_event and include dnstap and win_svc headers. 2025-04-03 10:59:41 +02:00
W.C.A. Wijngaards 5f91d5f74c - Fix wait-limit-netblock and wait-limit-cookie-netblock config parse
to allow two arguments.
2025-04-03 09:53:27 +02:00
W.C.A. Wijngaards c2ca679f5c - Fix #1263: Exempt loopback addresses from wait-limit. 2025-04-03 09:45:36 +02:00
W.C.A. Wijngaards ba18abcd35 - Fix that ub_event has the facility to deal with callbacks for
fast reload, doq, windows-stop and dnstap.
- Fix fast reload test to check if pid exists before acting on it.
2025-04-02 16:25:58 +02:00
W.C.A. Wijngaards a7704ad49f - Fix unbound-control test so it counts the new flush_negative output,
also answers the _ta probe from testns and prints command output
  and skip a thread specific test when no threads are available.
2025-04-02 15:52:20 +02:00
Yorgos Thessalonikefs 8b38fe5ab6 - For #1262, ifdef is no longer needed. 2025-04-02 11:53:50 +02:00
Yorgos Thessalonikefs fcdb0bbf91 Changelog entry for #1262:
- Merge #1262 from markyang92, fix build with
  'gcc-15 -Wbuiltin-declaration-mismatch' error in compat/malloc.c.
2025-04-02 11:52:04 +02:00
Yorgos ThessalonikefsandGitHub b738b354bd Merge pull request #1262 from markyang92/master
fix build with gcc-15 -Wbuiltin-declaration-mismatch error in compat/malloc.c
2025-04-02 11:49:49 +02:00
mark.yang 1c58ce0791 fix build with gcc-15 -Wbuiltin-declaration-mismatch error
See more details: http://errors.yoctoproject.org/Errors/Details/850313
../git/compat/malloc.c:9:7: warning: conflicting types for built-in function 'malloc'; expected 'void *(long unsigned int)' [-Wbuiltin-declaration-mismatch]
    9 | void *malloc ();
      |       ^~~~~~
../git/compat/malloc.c:5:1: note: 'malloc' is declared in header '<stdlib.h>'
    4 | #include "config.h"
  +++ |+#include <stdlib.h>
    5 | #undef malloc
../git/compat/malloc.c: In function 'rpl_malloc_unbound':
../git/compat/malloc.c:23:10: error: too many arguments to function 'malloc'; expected 0, have 1
   23 |   return malloc (n);
      |          ^~~~~~  ~
../git/compat/malloc.c:9:7: note: declared here
    9 | void *malloc ();
      |       ^~~~~~

* Seeing that there is '#undef malloc', it appears they don't want to
  use the malloc from stdlib.h.
  Therefore, we need to correctly define the parameters for malloc.

Signed-off-by: mark.yang <mark.yang@lge.com>
2025-04-02 15:25:42 +09:00
W.C.A. Wijngaards a7106fc58d - Enable the auth_tls.tdir and auth_tls_failcert.tdir tests. 2025-04-01 14:44:25 +02:00
W.C.A. Wijngaards 17f95ffac1 - Fix escape more characters when printing an RR type with an unquoted
string.
2025-04-01 13:53:29 +02:00
W.C.A. Wijngaards 0ca76b05e0 - Skip the unit tests for auth_tls.tdir and auth_tls_failcert.tdir. 2025-03-31 16:04:07 +02:00
218f5cfc92 Fast Reload Option (#1042)
* - fast-reload, add unbound-control fast_reload

* - fast-reload, make a thread to service the unbound-control command.

* - fast-reload, communication sockets for information transfer.

* - fast-reload, fix compile for unbound-dnstap-socket.

* - fast-reload, set nonblocking communication to keep the server thread
  responding to DNS requests.

* - fast-reload, poll routine to test for readiness, timeout fails connection.

* - fast-reload, detect loop in sock_poll_timeout routine.

* - fast-reload, send done and exited notification.

* - fast-reload, defines for constants in ipc.

* - fast-reload, ipc socket recv and send resists partial reads and writes and
  can continue byte by byte. Also it can continue after an interrupt.

* - fast-reload, send exit command to thread when done.

* - fast-reload, output strings for client on string list.

* - fast-reload, add newline to terminal output.

* - fast-reload, send client string to remote client.

* - fast-reload, better debug output.

* - fast-reload, print queue structure, for output to the remote client.

* - fast-reload, move print items to print queue from fast_reload_thread struct.

* - fast-reload, keep list of pending print queue items in daemon struct.

* - fast-reload, comment explains in_list for printq to print remainder.

* - fast-reload, unit test testdata/fast_reload_thread.tdir that tests the
  thread output.

* - fast-reload, fix test link for fast_reload_printq_list_delete function.

* - fast-reload, reread config file from disk.

* - fast-reload, unshare forwards, making the structure locked, with an rwlock.

* - fast-reload, for nonthreaded, the unbound-control commands forward,
  forward_add and forward_delete should be distributed to other processes,
  but when threaded, they should not be distributed to other threads because
  the structure is not thread specific any more.

* - fast-reload, unshared stub hints, making the structure locked, with an rwlock.

* - fast-reload, helpful comments for hints lookup function return value.

* - fast-reload, fix bug in fast reload printout, the strlist appendlist routine,
  and printout time statistics after the reload is done.

* - fast-reload, keep track of reloadtime and deletestime and print them.

* - fast-reload, keep track of constructtime and print it.

* - fast-reload, construct new items.

* - fast-reload, better comment.

* - fast-reload, reload the config and swap trees for forwards and stub hints.

* - fast-reload, in forwards_swap_tree set protection of trees with locks.

* - fast-reload, in hints_swap_tree also swap the node count of the trees.

* - fast-reload, reload ipc to stop and start threads.

* - fast-reload, unused forward declarations removed.

* - fast-reload, unit test that fast reload works with forwards and stubs.

* - fast-reload, fix clang analyzer warnings.

* - fast-reload, small documentation entry in unbound-control -h output.

* - fast-reload, printout memory use by fast reload, in bytes.

* - fast-reload, compile without threads.

* - fast-reload, document fast_reload in man page.

* - fast-reload, print ok when done successfully.

* - fast-reload, option for fast-reload commandline, +v verbosity option,
  with timing and memory use output.

* - fast-reload, option for fast-reload commandline, +p does not pause threads.

* - fast-reload, option for fast-reload commandline, +d drops mesh queries.

* - fast-reload, fix to poll every thread with nopause to make certain that
  resources are not held by the threads and can be deleted.

* - fast-reload, fix to use atomic store for config variables with nopause.

* - fast-reload, reload views.

* - fast-reload, when tag defines are different, it drops the queries.

* - fast-reload, fix tag define check.

* - fast-reload, document that tag change causes drop of queries.

* - fast-reload, fix space in documentation man page.

* - fast-reload, copy respip client information to query state, put views tree
  in module env for lookup.

* - fast-reload, nicer respip view comparison.

* - fast-reload, respip global set is in module env.

* - fast-reload, document that respip_client_info acl info is copied.

* - fast-reload, reload the respip_set.

* - fast-reload, document no pause and pick up of use_response_ip boolean.

* - fast-reload, fix test compile.

* - fast-reload, reload local zones.

* Update locking management for iter_fwd and iter_hints methods. (#1054)

fast reload, move most of the locking management to iter_fwd and
iter_hints methods. The caller still has the ability to handle its
own locking, if desired, for atomic operations on sets of different
structs.

Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>

* - fast-reload, reload access-control.

* - fast-reload, reload access control interface, such as interface-action.

* - fast-reload, reload tcp-connection-limit.

* - fast-reload, improve comments on acl_list and tcl_list swap tree.

* - fast-reload, fixup references to old tcp connection limits in open tcp
  connections.

* - fast-reload, fixup to clean tcp connection also for different linked order.

* - fast-reload, if no tcp connection limits existed, no need to remove
  references for that.

* - fast-reload, document more options that work and do not work.

* - fast-reload, reload auth_zone and rpz data.

* - fast-reload, fix auth_zones_get_mem.

* - fast-reload, fix compilation of testbound for the new comm_timer_get_mem
  reference in remote control.

* - fast-reload, change use_rpz with reload.

* - fast-reload, list changes in auth zones and stop zonemd callbacks for
  deleted auth zones.

* - fast-reload, note xtree is not swapped, and why it is not swapped.

* - fast-reload, for added auth zones, pick up zone transfer and zonemd tasks.

* - fast-reload, unlock xfr when done with transfer pick up.

* - fast-reload, unlock z when picking up the xfr for it during transfer task
  pick up.

* - fast-reload, pick up task changes for added, deleted and modified auth zones.

* - fast-reload, remove xfr of auth zone deletion without tasks.

* - fast-reload, pick up zone transfer config.

* - fast-reload, the main worker thread picks up the transfer tasks and also
  performs setup of the xfer struct.

* - fast-reload, keep writelock on newzone when auth zone changes.

* - fast-reload, change cachedb_enabled setting.

* - fast-reload, pick up edns-strings config.

* - fast-reload, note that settings are not updated.

* - fast-reload, pick up dnstap config.

* - fast-reload, dnstap options that need to be loaded without +p.

* - fast-reload, fix auth zone reload

* - fast-reload, remove debug for auth zone test.

* - fast-reload, fix auth zone reload with zone transfer.

* - fast-reload, fix auth zone reload lock order.

* - fast-reload, remove debug from fast reload test.

* - fast-reload, remove unused function.

* - fast-reload, fix the worker trust anchor probe timer lock acquisition in
  the probe answer callback routine for trust anchor probes.

* - fast-reload, reload trust anchors.

* - fast-reload, fix trust anchor reload lock on autr global data and test
  for trust anchor reload.

* - fast-reload, adjust cache sizes.

* - fast-reload, reload cache sizes when changed.

* - fast-reload, reload validator env changes.

* - fast-reload, reload mesh changes.

* - fast-reload, check for incompatible changes.

* - fast-reload, improve error text for incompatible change.

* - fast-reload, fix check config option compatibility.

* - fast-reload, improve error text for nopause change.

* - fast-reload, fix spelling of incompatible options.

* - fast-reload, reload target-fetch-policy, outbound-msg-retry, max-sent-count
  and max-query-restarts.

* - fast-reload, check nopause config change for target-fetch-policy.

* - fast-reload, reload do-not-query-address, private-address and capt-exempt.

* - fast-reload, check nopause config change for do-not-query-address,
  private-address and capt-exempt.

* - fast-reload, check fast reload not possible due to interface and
  outgoing-interface changes.

* - fast-reload, reload nat64 settings.

* - fast-reload, reload settings stored in the infra structure.

* - fast-reload, fix modstack lookup and remove outgoing-range check.

* - fast-reload, more explanation for config parse failure.

* - fast-reload, reload worker outside network changes.

* - fast-reload, detect incompatible changes in network settings.

* fast-reload, commit test files.

* - fast-reload, fix warnings for call types in windows compile.

* - fast-reload, fix warnings and comm_point_internal for tcp wouldblock calls.

* - fast-reload, extend lock checks for repeat thread ids.

* - fast-reload, additional test cases, cache change and tag changes.

* - fast-reload, fix documentation for auth_zone_verify_zonemd_with_key.

* - fast-reload, fix copy_cfg type casts and memory leak on config parse failure.

* - fast-reload, fix use of WSAPoll.

* Review comments for the fast reload feature (#1259)

* - fast-reload review, respip set can be null from a view.

* - fast-reload review, typos.

* - fast-reload review, keep clang static analyzer happy.

* - fast-reload review, don't forget to copy tag_actions.

* - fast-reload review, less indentation.

* - fast-reload review, don't leak respip_actions when reloading.

* - fast-reload review, protect NULL pointer dereference in get_mem
  functions.

* - fast-reload review, add fast_reload_most_options.tdir to test most
  options with high verbosity when fast reloading.

* - fast-reload review, don't skip new line on long error printouts.

* - fast-reload review, typo.

* - fast-reload review, use new_z for consistency.

* - fast-reload review, nit for unlock ordering to make eye comparison
  with the lock counterpart easier.

* - fast-reload review, in case of error the sockets are already closed.

* - fast-reload review, identation.

* - fast-reload review, add static keywords.

* - fast-reload review, update unbound-control usage text.

* - fast-reload review, updates to the man page.

* - fast-reload, the fast-reload command is experimental.

* - fast-reload, fix compile of doqclient for fast reload functions.

* Changelog comment for #1042
- Merge #1042: Fast Reload. The unbound-control fast_reload is added.
  It reads changed config in a thread, then only briefly pauses the
  service threads, that keep running. DNS service is only interrupted
  briefly, less than a second.

---------

Co-authored-by: Yorgos Thessalonikefs <yorgos@nlnetlabs.nl>
2025-03-31 15:25:24 +02:00
W.C.A. Wijngaards 914cef75f9 - iana portlist update. 2025-03-31 14:25:16 +02:00
W.C.A. Wijngaards f76365754e - Fix for ci test, expat is installed on the osx image. 2025-03-27 10:52:00 +01:00
W.C.A. Wijngaards aa77d02336 - Fix unit test dname log printout typecast. 2025-03-27 10:47:20 +01:00
Yorgos Thessalonikefs 23273d76a5 - For #1255, for ios try the latest expat version again. 2025-03-26 16:51:46 +01:00
Yorgos Thessalonikefs 94a84d3387 - For #1255, for ios disable building tests that require C++11. 2025-03-26 16:40:10 +01:00
Yorgos Thessalonikefs d91c857e22 - For #1255, for ios use an older expat version that does not require
C++11 language features.
2025-03-26 16:15:16 +01:00
Yorgos Thessalonikefs d03e4b1884 - Fix #1255: Multiple pinnings to vulnerable copies of libexpat. 2025-03-26 14:58:54 +01:00
W.C.A. Wijngaards 376f2ade2a - Fix #1254: send failed: Socket is not connected and
`remote address is 0.0.0.0 port 53`.
2025-03-24 08:54:54 +01:00
W.C.A. Wijngaards 0eabc8d0f1 - Fix for #1253: Fix for redis cachedb backend to expect an integer
reply for the EXPIRE command.
2025-03-21 14:07:22 +01:00
W.C.A. Wijngaards a42fb99508 - Fix #1253: Cache entries fail to be removed from Redis cachedb
backend with unbound-control flush* +c.
2025-03-21 12:56:21 +01:00
W.C.A. Wijngaards eccf52e39d - Fix print of RR type NSAP-PTR, it is an unquoted string. 2025-03-20 15:51:03 +01:00
W.C.A. Wijngaards 30b9cb5f81 - Fix for windows compile create ssl contexts. 2025-03-18 14:01:53 +01:00
W.C.A. Wijngaards b0d20e2d28 - Fix #1251: WSAPoll first argument cannot be NULL. 2025-03-18 13:59:53 +01:00
W.C.A. Wijngaards 13afde2cad - Fix representation of types GPOS and RESINFO, add rdf type for 2025-03-17 16:38:17 +01:00
Yorgos Thessalonikefs 71bb60e586 - Fix 'unbound-control flush_negative' when reporting removed data;
reported by David 'eqvinox' Lamparter.
2025-03-16 09:02:20 +01:00
W.C.A. Wijngaards 5c84bb573f Changelog nore for #1238 and add --help description.
- Merge #1238: Prefer SOURCE_DATE_EPOCH over actual time.
  Add --help output description for the SOURCE_DATE_EPOCH variable.
2025-02-28 09:32:49 +01:00
Sefa EyeogluandGitHub d9f1dae540 Prefer SOURCE_DATE_EPOCH over actual time (#1238)
* Add ax_build_date_epoch from Autoconf Archive

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>

* Prefer SOURCE_DATE_EPOCH over actual time

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>

---------

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2025-02-28 09:22:19 +01:00
W.C.A. Wijngaards a3d750b7d8 Changelog note for #1243
- Merge #1243: Do not shadow tm on line 236.
2025-02-25 09:37:36 +01:00
Florian ObserandGitHub c371be3f9f Do not shadow tm on line 236. (#1243) 2025-02-25 09:36:44 +01:00
Yorgos Thessalonikefs c5c5486261 - Fix hash calculation for cachedb to ignore case. Previously, cached
records there were only relevant for same case queries (if not
  already in Unbound's internal cache).
2025-02-24 14:47:13 +01:00
Yorgos Thessalonikefs 1894c0a150 Changelog entry for #1241:
- Merge #1241: Fix infra-keep-probing for low infra-cache-max-rtt
  values.
2025-02-19 13:46:01 +01:00
Yorgos ThessalonikefsandGitHub edb20a2ad2 Merge pull request #1241 from NLnetLabs/bugfix/keep-probing-max-rtt
Fix infra-keep-probing for low infra-cache-max-rtt values
2025-02-19 13:44:40 +01:00
Yorgos Thessalonikefs bcf162abd7 - The maximum value of a probe rto was not aligned with the
(configurable) infra-cache-max-rtt value. That could result in
  infra-keep-probing not working if an infra-cache-max-rtt value was chosen
  that was below 12000 ms. This fix still uses a default value of 12000
  ms for the probe but caps it to the infra-cache-max-rtt if that is
  lower.
2025-02-19 12:14:59 +01:00
Yorgos Thessalonikefs 5e1f35b59b - Fix static analysis report about unhandled EOF on error conditions
when reading anchor key files.
2025-02-19 11:24:49 +01:00
Yorgos Thessalonikefs 72828ff81c - Consider reconfigurations when calculating the still_useful_timeout
for servers in the infrastructure cache.
2025-02-17 15:21:18 +01:00
W.C.A. Wijngaards 01cea4d5be - Fix #986: Resolving sas.com with dnssec-validation fails though
signed delegations seem to be (mostly) correct.
2025-01-30 16:26:31 +01:00
Yorgos Thessalonikefs 35dbbcb2f5 - Make the default value of module-config "validator iterator"
regardless of compilation options. --enable-subnet would implicitly
  change the value to enable the subnetcache module by default in the
  past.
2025-01-29 12:08:28 +01:00
Yorgos Thessalonikefs 911509fd59 Changelog entry for #1220:
- Merge #1220 from Petr Menšík, Add unbound members group access to
  control key.
2025-01-24 16:56:09 +01:00
Yorgos ThessalonikefsandGitHub b48958c983 Merge pull request #1220 from InfrastructureServices/unbound-control-group-key
Add unbound members group access to control key
2025-01-24 16:53:12 +01:00
Yorgos Thessalonikefs cc55beefc8 Changelog entry for #1224:
- Merge #1224 from Theo Buehler: Do not use DSA API unless USE_DSA is
  set.
2025-01-21 17:35:00 +01:00
Yorgos ThessalonikefsandGitHub a2bf32bb4e Merge pull request #1224 from botovq/improve-use-dsa
Do not use DSA API unless USE_DSA is set
2025-01-21 17:33:48 +01:00
W.C.A. Wijngaards d9b863ed76 Changelog note for #1229
- Merge #1229: check before use daemon->shm_info.
2025-01-21 15:48:46 +01:00
eaglegaiandGitHub 073c7301eb check before use daemon->shm_info (#1229)
fix core after the command `unbound-control stop unbound`

fix:https://github.com/NLnetLabs/unbound/issues/1228

Signed-off-by: eaglegai <eaglegai@163.com>
2025-01-21 15:47:51 +01:00
Yorgos Thessalonikefs f822042cd0 - Do not open unencrypted channels next to encrypted ones on the same
port.
2025-01-21 15:26:40 +01:00
W.C.A. Wijngaards 5f58ced71e - Fix to check length in ATMA string to wire. 2025-01-21 12:30:30 +01:00
W.C.A. Wijngaards 207ae97ff9 - Fix encoding of RR type ATMA. 2025-01-21 12:27:15 +01:00
W.C.A. Wijngaards 9a0de14aa1 - Fix compile of interface check code when dnscrypt or quic is
disabled.
2025-01-21 10:13:48 +01:00
Yorgos Thessalonikefs 048c193243 - Use the same interface listening port discovery code for all needed
protocols.
- Port to string only when needed before getaddrinfo().
2025-01-21 10:04:30 +01:00
Yorgos Thessalonikefs d62fff2c7c - Create the quic SSL listening context only when needed. 2025-01-20 15:49:37 +01:00
Yorgos Thessalonikefs 3f839cebc3 Changelog entry for #1222:
- Merge #1222: Unique DoT and DoH SSL contexts to allow for different
  ALPN.
2025-01-20 15:45:11 +01:00
Yorgos ThessalonikefsandGitHub e4483bbbd1 Unique DoT and DoH SSL contexts to allow for different ALPN (#1222) 2025-01-20 15:43:44 +01:00
Theo Buehler 8672b34fca Do not use DSA API unless USE_DSA is set
Even if USE_DSA is unset, unbound ends up linking against OpenSSL
DSA API because these guards are missing.
2025-01-18 10:40:43 +01:00
Yorgos Thessalonikefs 1d428f2d54 Changelog entry for #1221:
- Merge #1221: Consider auth zones when checking for forwarders.
2025-01-17 10:19:26 +01:00
Yorgos ThessalonikefsandGitHub 9882a395ab Merge pull request #1221 from NLnetLabs/bugfix/consider-auth-zones-when-forwarding
Consider auth zones when checking for forwarders
2025-01-17 10:18:32 +01:00
Yorgos Thessalonikefs 394588818f - Use correct RFC number for resolver.arpa. 2025-01-15 10:55:31 +01:00
Yorgos Thessalonikefs f52b2a6ea2 - Add resolver.arpa and service.arpa to the default locally served
zones.
2025-01-14 17:18:32 +01:00
Yorgos Thessalonikefs b2fec3be11 - Take configured auth zones into consideration when checking if a
request needs to be forwarded.
2025-01-14 16:38:53 +01:00
Petr Menšík f4881bd81a Add unbound members group access to control key
Recent openssl genrsa does not use umask for generated keys. There is no
strong reason why every member of unbound group should be able read
server key. But control key would be quite useful to be group readable
and to allow control access to whole group. Allowing access to control
by group membership, not via sudo.
2025-01-14 14:35:09 +01:00
Yorgos Thessalonikefs c3b5bff311 - Fix typo. 2025-01-13 12:32:16 +01:00
Yorgos Thessalonikefs 62a0e03801 - Fix #1213: Misleading error message on default access control causing
refuse.
2025-01-13 11:33:24 +01:00
Yorgos Thessalonikefs 716f3df385 Changelog entry for #1214:
- Merge #1214: Use TCP_NODELAY on TLS sockets to speed up the TLS
  handshake.
2025-01-10 13:54:49 +01:00
Yorgos ThessalonikefsandGitHub 7e4f7ec5be Merge pull request #1214 from NLnetLabs/bugfix/tls-handshake
Use TCP_NODELAY on TLS sockets to speed up the TLS handshake.
2025-01-10 13:53:46 +01:00
Yorgos Thessalonikefs 7559d26c93 - Use TCP_NODELAY on TLS sockets to speed up the TLS handshake. 2025-01-10 12:11:59 +01:00
Yorgos Thessalonikefs eb36c880de Changelog entry for #1174:
- Merge #1174: Serve expired cache update fixes. Fixes a regression bug
  with serve-expired that appeared in 1.22.0 and would not allow the
  iterator to update the cache with not-yet-validated entries resulting
  in increased outgoing traffic.
2024-12-31 16:30:35 +01:00
Yorgos ThessalonikefsandGitHub fff9f62a1e Serve expired cache update fixes (#1174)
- Fixes a regression bug with serve-expired that appeared in 1.22.0
  and would not allow the iterator to update the cache with
  not-yet-validated entries resulting in increased outgoing traffic.

- Treat serve_expired_norec_ttl as a backoff timer for failed updates of expired records.
- Try to use expired answers instead of SERVFAIL if serve-expired is
  enabled even without serve-expired-client-timeout.
- Add suggestion to refresh the cached norec_ttl and expired_ttl when a
  response cannot update the usable expired entry.
2024-12-31 16:28:12 +01:00
Yorgos Thessalonikefs e57e537c85 - For #1207: [FR] Support for RESINFO RRType 261 (RFC9606), add
LDNS_RR_TYPE_RESINFO similar to LDNS_RR_TYPE_TXT.
2024-12-20 15:04:34 +01:00
Yorgos Thessalonikefs 71d821fde9 Changelog entry for #1204:
- Merge #1204: ci: set persist-credentials: false for actions/checkout
  per zizmor suggestion.
2024-12-13 13:43:29 +01:00
Yorgos ThessalonikefsandGitHub df5ab5624d Merge pull request #1204 from NLnetLabs/zizmor-improvements 2024-12-13 13:42:31 +01:00
Maarten Aertsen eb08dc617a set persist-credentials: false per zizmor suggestion 2024-12-13 13:12:03 +01:00
Yorgos Thessalonikefs ded4c82ced - Fix typo in log_servfail.tdir test. 2024-12-03 16:03:05 +01:00
Yorgos Thessalonikefs e82a691efe Changelog entry for #1187:
- Merge #1187: Create the SSL_CTX for QUIC before chroot and privilege
  drop.
2024-12-03 14:21:34 +01:00
61d7250b96 Create the SSL_CTX for QUIC before chroot and privilege drop (#1187)
Fixes #1185 by creating the SSL_CTX for QUIC before chroot and
privilege drop, just like the other SSL_CTX creations.

---------

Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>
2024-12-03 14:20:33 +01:00
Yorgos Thessalonikefs b4a9c8bb05 - Safeguard alias loop while looking in the cache for expired answers. 2024-12-03 14:10:17 +01:00
Yorgos Thessalonikefs be92752368 - Merge #1198: Fix log-servfail with serve expired and no useful cache
contents.
2024-12-03 14:05:12 +01:00
Yorgos ThessalonikefsandGitHub 1512945c79 Merge pull request #1198 from NLnetLabs/bugfix/log-servfail-serve-expired
Fix log-servfail with serve expired and no useful cache contents
2024-12-03 14:02:03 +01:00
Yorgos Thessalonikefs 9de159b96b - For #1175, the default value of serve-expired-ttl is set to 86400
(1 day) as suggested by RFC8767.
2024-12-03 13:09:51 +01:00
Yorgos Thessalonikefs bd2e66de1e Changelog entry for #1189, #1197:
- Merge #1189: Fix the dname_str method to cause conversion errors
  when the domain name length is 255.
- Merge #1197: dname_str() fixes.
2024-12-03 11:58:06 +01:00
Yorgos ThessalonikefsandGitHub 9770e855d2 Merge pull request #1197 from NLnetLabs/dname_str-more-tests
dname_str() fixes
2024-12-03 11:55:41 +01:00
Yorgos Thessalonikefs c124f67f33 - For #1193, introduce log-servfail.tdir and cleanup the log-servfail
setting from other tests.
2024-12-02 12:30:11 +01:00
Yorgos Thessalonikefs c55490c1e6 - Fix #1193: log-servfail fails to log host SERVFAIL responses in
Unbound 1.19.2 on Ubuntu 24.04.1 LTS, by not considering cached
  failures when trying to reply with expired data.
2024-12-02 12:28:11 +01:00
Yorgos Thessalonikefs f46acec35f - For #1189, homogenize the input buffer size for dname_str(). 2024-12-02 11:53:56 +01:00
Yorgos Thessalonikefs 1cd2fb3b9d - For #1189, add unit tests for dname_str() and debug check the input
buffer size.
2024-12-02 10:03:35 +01:00
wenxuan70 06fb30d0a0 Fix the dname_str method to cause conversion errors when the domain name length is 255 2024-11-24 17:53:23 +08:00
Yorgos Thessalonikefs 9e3c50ec9e - For #1175, update serve-expired tests. 2024-11-22 16:14:02 +01:00
Yorgos Thessalonikefs eefdbb341f - Fix #1175: serve-expired does not adhere to secure-by-default
principle. The default value of serve-expired-client-timeout
  is set to 1800 as suggested by RFC8767.
2024-11-22 15:32:34 +01:00
Yorgos Thessalonikefs e75da7d954 - Fix comparison to help static analyzer. 2024-11-20 10:53:45 +01:00
Yorgos Thessalonikefs 9a3a1bc221 Changelog entry for #1169:
- Merge #1169 from Sergey Kacheev, fix: lock-free counters for
  auth_zone up/down queries.
2024-11-19 17:01:34 +01:00
Yorgos ThessalonikefsandGitHub c1e9d7be7f Merge pull request #1169 from sakateka/lock-free-az-counters
fix: lock-free counters for auth_zone up/down queries
2024-11-19 17:00:01 +01:00
Sergey Kacheev 2c72a4970b fix: lock-free counters for auth_zone up/down queries 2024-11-19 18:55:31 +03:00
W.C.A. Wijngaards 4cf7fae50c - Fix for #1183: release nsec3 hashes per test file. 2024-11-15 10:47:27 +01:00
W.C.A. Wijngaards a2ac980737 - Fix #1183: the data being used is released in method
nsec3_hash_test_entry.
2024-11-15 10:37:35 +01:00
W.C.A. Wijngaards c88eed83d9 - ttl-zero-cacherep, unit test for ttl zero for a cache response. 2024-11-11 17:08:38 +01:00
W.C.A. Wijngaards 50fcf71f04 - ttl-zero-cacherep, Responses in the last second of their cache TTL,
get an extra second. That makes the TTL not 0, since they are from
  cache and can be cached by the client.
2024-11-11 15:43:10 +01:00
Yorgos Thessalonikefs 733d5f7161 - Complete fix for max-global-quota to 200. 2024-11-08 17:34:28 +01:00
Yorgos Thessalonikefs fe288a9b06 - More descriptive text for 'harden-algo-downgrade'. 2024-11-08 13:56:04 +01:00
Yorgos Thessalonikefs fd1a1d5fa0 - Increase the default of max-global-quota to 200 from 128 after
operational feedback. Still keeping the possible amplification
  factor (CAMP related issues) in the hundreds.
2024-11-06 16:28:37 +01:00
Yorgos Thessalonikefs 3c4b87636a Changelog entry for:
- Fix SETEX check during Redis (re)initialization.
2024-11-05 12:20:25 +01:00
Yorgos Thessalonikefs 36d8c6e778 - Fix SETEX check during Redis (re)initialization. 2024-11-05 12:18:55 +01:00
W.C.A. Wijngaards 60fd77b8f9 - Fix to log redis timeout error string on failure. 2024-11-05 11:41:41 +01:00
W.C.A. Wijngaards d5e91d181b - Fix for the serve expired DNSSEC information fix, it would not allow
current delegation information be updated in cache. The fix allows
  current delegation and validation recursion information to be
  updated, but as a consequence no longer has certain expired
  information around for later dnssec valid expired responses.
2024-11-05 10:39:27 +01:00
W.C.A. Wijngaards 7985d17b57 Changelog note for #1167
- Merge #1167: Makefile.in: fix occasional parallel build failures
  around bison rule.
2024-11-04 13:26:27 +01:00
Sergei TrofimovichandGitHub 46cfbf313d Makefile.in: fix occasional parallel build failures around bison rule (#1167)
Without the change `make -j16 --shuffle` occasinally fails to build as:

    $ make -j16 --shuffle
    ...
    bison -y -d -o util/configparser.c ./util/configparser.y
    ...
    /libtool --tag=CC --mode=compile gcc -I.  -I...-openssl-3.3.2-dev/include -I...-libevent-2.1.12-dev/include -I...-expat-2.6.3-dev/include -DSRCDIR=. -g -O2 -flto -fPIE -pthread  -o configparser.lo -c util/configparser.c
    ...
    util/configparser.c:755:3: error: expected ',' or '}' at end of input
  755 |   YYSYMBOL_server_low_rtt = 626,           /* server_low_rtt  */
      |   ^

The build failure happens due to this `Makefile.in` rule:

    util/configparser.c util/configparser.h:  $(srcdir)/util/configparser.y
        @-if test ! -d util; then $(INSTALL) -d util; fi
        $(YACC) -d -o util/configparser.c $(srcdir)/util/configparser.y

For GNU make that means that each of the targets will attempt the rule
execution when the file is missing: one for .c file and another for .h
file:

    https://www.gnu.org/software/make/manual/html_node/Multiple-Targets.html

The workaround is to only run $(YACC) for .c target and use .c as a
pre-requisite for an .h file.

Before the change the build fails about every 10-th run.
After the change no build failures after 100 successful builds.
2024-11-04 13:26:05 +01:00
W.C.A. Wijngaards 533c3b0514 - Fix redis that during a reload it does not fail if the redis
server does not connect or does not respond. It still logs the
  errors and if the server is up checks expiration features.
2024-11-04 10:14:26 +01:00
W.C.A. Wijngaards 5f3f214da5 - Fix redis that during a reload it does not fail if the redis
server does not connect or does not respond. It still logs the
  errors and if the server is up checks expiration features.
2024-11-04 10:14:13 +01:00
Yorgos Thessalonikefs 11b8157a98 Changelog entry for #1157:
- Merge #1157 from Liang Zhu, Fix heap corruption when calling
  ub_ctx_delete in Windows.
2024-11-01 16:27:06 +01:00
Liang ZhuandGitHub 1c24cd79cc Fix heap corruption when calling ub_ctx_delete in Windows (#1157) 2024-11-01 16:26:05 +01:00
Yorgos Thessalonikefs d34fb3ed77 Changelog entry for #1170:
- Merge #1170 from Melroy van den Berg, Fix chroot manpage
  description.
2024-11-01 16:12:07 +01:00
Melroy van den BergandGitHub c37833c943 Fix chroot manpage description (#1170) 2024-11-01 16:10:57 +01:00
Yorgos Thessalonikefs 8a6a4bd7f3 - Add test case for #1159.
- Some clean up for stat_values.test.
2024-11-01 15:57:52 +01:00
Yorgos Thessalonikefs d23523e528 - Merge #1159: Stats for discard-timeout and wait-limit. 2024-11-01 15:54:24 +01:00
Wouter WijngaardsandGitHub 75967e7f5e Stats for discard-timeout and wait-limit (#1159)
* - Stats num.queries_discard_timeout and num.queries_wait_limit are used
  instead of the mesh dropped that of requests exceeded.
2024-11-01 15:52:58 +01:00
Yorgos Thessalonikefs f5580f0a63 - Fix #1163: Typos in unbound.conf documentation. 2024-10-25 21:25:16 +02:00
W.C.A. Wijngaards 0e2b2743d8 Add changelog entry for tag for 1.22.0rc1. 2024-10-17 10:57:07 +02:00
W.C.A. Wijngaards 018be1d089 - Tag for 1.22.0 release. This did not contain the 1154 fix
from 16 oct. The code repository continues with
  version 1.22.1 in development.
2024-10-17 10:48:58 +02:00
W.C.A. Wijngaards 9a63db344e - Fix #1154: Tag Incorrectly Applying for Other Interfaces
Using the Same IP. This fix is not for 1.22.0.
2024-10-16 15:56:33 +02:00
W.C.A. Wijngaards 0076736fc4 - Fix for dnstap with dnscrypt and dnstap without dnsoverquic. 2024-10-16 11:52:49 +02:00
Yorgos Thessalonikefs f8e45ed696 - Fix for dnsoverquic and dnstap to use the correct dnstap
environment.
2024-10-16 11:02:31 +02:00
W.C.A. Wijngaards 2a28c7389c - Fix dnsoverquic to extend the number of streams when one is closed. 2024-10-14 13:53:55 +02:00
W.C.A. Wijngaards 114edf2c38 - Fix to display warning if quic-port is set but dnsoverquic is not
enabled when compiled.
2024-10-14 11:34:26 +02:00
W.C.A. Wijngaards e0c93e300b - Fix contrib/aaaa-filter-iterator.patch for change in call
signature for cache_fill_missing.
2024-10-11 11:42:30 +02:00
W.C.A. Wijngaards bd1813b126 - Fix harden-unverified-glue for AAAA cache_fill_missing lookups. 2024-10-11 09:03:11 +02:00
W.C.A. Wijngaards 1b7e14dc39 - Fix to disable detection of quic configured ports when quic is
not compiled in.
2024-10-11 08:51:14 +02:00
W.C.A. Wijngaards 8b7782e8fc - Fix add reallocarray to alloc stats unit test, and disable
override of strdup in unbound-host, and the result of config
  get option is freed properly.
2024-10-10 10:43:23 +02:00
W.C.A. Wijngaards e0201435a4 - Fix cookie_file test sporadic fails for time change during
the test.
2024-10-10 09:45:48 +02:00
W.C.A. Wijngaards 66fb3ff670 - Fix for dnstap compile of doqclient with doq disabled. 2024-10-09 15:52:33 +02:00
W.C.A. Wijngaards 36461ea73d Changelog entry and unit test for fix of NSEC TTL and prefetch ttl.
- Fix to limit NSEC TTL for messages from cachedb. Fix to limit the
  prefetch ttl for messages after a CNAME with short TTL.
2024-10-09 15:29:23 +02:00
W.C.A. Wijngaards 5679c8b1df - Fix to limit NSEC TTL for messages from cachedb. Fix to limit the
prefetch ttl for messages after a CNAME with short TTL.
2024-10-09 15:28:55 +02:00
W.C.A. Wijngaards a4d8c0c43b Changelog note for #871
- Merge #871: DNS over QUIC. This adds `quic-port: 853` and
  `quic-size: 8m` that enable dnsoverquic, and the counters
  `num.query.quic` and `mem.quic` in the statistics output.
  The feature needs to be enabled by compiling with libngtcp2,
  with `--with-libngtcp2=path` and libngtcp2 needs openssl+quic,
  pass that with `--with-ssl=path` to compile unbound as well.
2024-10-09 10:35:45 +02:00
3d89c26d32 DNSoverQUIC (#871)
* - dnsoverquic, configure --with-libngtcp2 option.

* - dnsoverquic, create comm_point for doq and receive cmsg local address.

* - dnsoverquic, less obtrusive debug.

* - dnsoverquic, log and fix local port number. Neater subroutines and ifdefs.

* - dnsoverquic, add testcode/doqclient.

* - dnsoverquic, review fixes on doqclient.

* - dnsoverquic, fix unit test testbound link.

* - dnsoverquic, parse query in doqclient.

* - dnsoverquic, link with libngtcp2_crypto_openssl and code for doqclient.

* - dnsoverquic, random routine for doqclient and fix ngaddr allocation, and
  check ub_initstate return.

* - dnsoverquic, fix doqclient free of allocated ngaddr addresses.

* - dnsoverquic, enable debug output with -v for doqclient.

* - dnsoverquic, create and set TLS object and TLS context in doqclient.

* - dnsoverquic, work on quic tls context in doqclient.

* - dnsoverquic, set default dnsoverquic port to the standardized 853 port.

* - dnsoverquic, remove debug comment.

* - dnsoverquic, dns-over-quic quic-port: 853 config option.

* - dnsoverquic, log type of interface created at start of unbound.

* - dnsoverquic, log type of no tls https as https when interface is created.

* - dnsoverquic, setup client quic tls methods.

* - dnsoverquic, event work in doqclient.

* - dnsoverquic, explain in documentation that QUIC uses UDP.

* - dnsoverquic, make doqclient exit.

* - dnsoverquic, doqclient cleanup run routine.

* - dnsoverquic, doqclient code nicer.

* - dnsoverquic, doqclient read and timer.

* - dnsoverquic, doqclient write work.

* - dnsoverquic, review fixes.

* - dnsoverquic, detect openssl quic support at configure time.

* - dnsoverquic, do not allow QUIC on port 53 to stop confusion of DoQ and DNS.

* - dnsoverquic, in doqclient, when idle close is returned, drop the connection
  without calling ngtcp2_conn_write_connection_close.

* - dnsoverquic, in doqclient, log callbacks.

* - dnsoverquic, in doqclient add extend_max_local_streams_bidi callback.

* - dnsoverquic, in doqclient add client query lists.

* - dnsoverquic, in doqclient, code cleaner, log text nicer.

* - dnsoverquic, in doqclient, work on write_streams.

* - dnsoverquic, in doqclient, use signed int for stream_id, work on the
  ngtcp2_recv_stream_data callback.

* - dnsoverquic, in doqclient, print result and fixes for recv data.

* - dnsoverquic, in doqclient, add the event callbacks to fptr wlist.

* - dnsoverquic, in doqclient, when already expired, use zero timeout timer.

* - dnsoverquic, in doqclient, ignore unused return codes from
  ngtcp2_conn_writev_stream.

* - dnsoverquic, add doqclient event functions to the unbound-dnstap-socket
  test tool for linking.

* - dnsoverquic, in doqclient, fix multiple operands for the commandline.
  neater dns message output.

* - dnsoverquic, in doqclient, store packet when write blocks and try later.

* - dnsoverquic, in doqclient, limit number of packets and number of bytes sent.

* - dnsoverquic, in doqclient, better size estimate for outgoing packet.

* - dnsoverquic, in doqclient, fix that already written next packet is not
  counted for data length to send.

* - dnsoverquic, in doqclient, early data transmission and session resumption.

* - dnsoverquic, send version negotiation packet.

* - dnsoverquic, send retry and accept the connection.

* - dnsoverquic, storage structures.

* - dnsoverquic, doq connection setup.

* - dnsoverquic, neater code layout for new conn. Fix verbosity of log print.

* - dnsoverquic, doq conn callback functions.

* - dnsoverquic, doq_fill_rand routine in header file.

* - dnsoverquic, keep track of connection ids.

* - dnsoverquic, get_new_connection_id callback.

* - dnsoverquic, create doq_conid tree.

* - dnsoverquic, settings for server connection.

* - dnsoverquic, tls context.

* - dnsoverquic, sendmsg error handling.

* - dnsoverquic, neat code.

* - dnsoverquic, track doq connection last error.

* - dnsoverquic, neater packet address parameters.

* - dnsoverquic, fix uninitialized bytes in msg control in doq sendmsg, and
  fix tree cleanup of conid tree.

* - dnsoverquic, better usage text for doqclient.

* - dnsoverquic, neat code.

* - dnsoverquic, connection receive packet handling.

* - dnsoverquic, debug output.

* - dnsoverquic, debug switched meaning of scid and dcid gives
  ERR_TRANSPORT_PARAM.

* - dnsoverquic, remove debug output.

* - dnsoverquic, connection delete routine and error from connection read in
  more detail with less clutter.

* - dnsoverquic, write to stream, and receive stream data, log packet.

* - dnsoverquic, alpn set up.

* - dnsoverquic, connection close.

* - dnsoverquic, doq_table and locks.

* - dnsoverquic, fix tests.

* - dnsoverquic, better locking.

* - dnsoverquic, doq_stream.

* - dnsoverquic, remove compile warning.

* - dnsoverquic, doq_stream receive data.

* - dnsoverquic, fixes for locks and keep length bytes allocated.

* - dnsoverquic, lock connection on initial insertion.

* - dnsoverquic, reply information, and reply buffer.

* - dnsoverquic, reply info from cache, local-zone and recursion lookups.

* - dnsoverquic, spelling in comment about buffer storage.

* - dnsoverquic, stream write list and doqclient fixes to exit and printout.

* - dnsoverquic, doqclient -q option for short printout.

* - dnsoverquic, unit test with local data reply.

* - dnsoverquic, write connection and write event is set.

* - dnsoverquic, neater logging for write event connection stream writes.

* - dnsoverquic, log remote connection when the streams are written for it.

* - dnsoverquic, better threaded use, threads can write to doq connections at
  the same time.

* - dnsoverquic, unit test for the calculation of connection size with a query.

* - dnsoverquic, use less memory per connection.

* - dnsoverquic, remove unit test output.

* - dnsoverquic, add MSG_DONTWAIT so that there is no mistakenly blocking
  socket operations.

* - dnsoverquic, doqclient logs address on connection failures.

* - dnsoverquic, compat code for clock get time routine.

* - dnsoverquic, use skip_test for doq unit test.

* - dnsoverquic, fixes for proxyprotocol, use remote_addr and set proxyprotocol
  disabled on the doq connection.

* - dnsoverquic, doqclient sets log identity to its name, instead of "unbound".

* - dnsoverquic, handle blocked udp packet writes.

* - dnsoverquic, fix function documentation for verbose_print_addr from
  services/listen_dnsport.c.

* - dnsoverquic, fix doq_conn lock protection. The checklock allows to set
  the output file name, and doqclient uses that. Print place of lock_protect.

* - dnsoverquic, neater buffer clear when write of blocked packet fails, make
  sure that memory area does not overlap for blocked packet addresses when
  write of blocked packet fails, and size blocked packet buffer to the pkt buf.

* - dnsoverquic, move lock check after the test to test script in doq test.

* - dnsoverquic, the doq test uses valgrind when enabled.

* - dnsoverquic, git ignore the doqclient test.

* - dnsoverquic, limit the buffer for packets to max packet size with some more.

* - dnsoverquic, spelling fix.

* - dnsoverquic, timer work, structure and adds and deletes.

* - dnsoverquic, timer_tree uses table.lock.

* - dnsoverquic, fix timer tree remove and spelling in header file comment.

* - dnsoverquic, fix testbound for timer compare function linkage.

* - dnsoverquic, timer set add debug output.

* - dnsoverquic, doq_conn_check_timer function.

* - dnsoverquic, doq_done_setup_timer_and_write function.

* - dnsoverquic, fix that doq conn is not deleted whilst editing write and timer.

* - dnsoverquic, Fix #861 make ERROR netevent.h:1073:32: error: field 'blocked_pkt_pi' has incomplete type

* - dnsoverquic, timer element has timeout setup when socket callback complete.

* - dnsoverquic, fix unit test compile.

* - dnsoverquic, timer callback routine, handle timeout and close and delete the
  connection if necessary.

* - dnsoverquic, timer pickup stops at current time.

* - dnsoverquic, timer comparable with the event base time.

* - dnsoverquic, erase marked time when timer disabled.

* - dnsoverquic, fix timer to set correctly and lock popped write connection
  early, before it is modified.

* - dnsoverquic, fix to unlock connection lock when it is unlinked and deleted.

* - dnsoverquic, fix to unlock connection lock when it is deleted because it is
  a duplicate connection.

* - dnsoverquic, fix that doq timer is not disabled when not set.

* - dnsoverquic, quic-size: 8m maximum number of bytes for QUIC buffers.

* - dnsoverquic, flex and bison.

* - dnsoverquic, quic-size turn away new connections when full.

* - dnsoverquic, doqclient outputs stream reset information.

* - dnsoverquic, detect stream close and reset.

* - dnsoverquic, free stream buffers when data is acked and stream is closed.

* - dnsoverquic, delete stream when closed. Unlink it. Allow stream_id 4 as first.

* - dnsoverquic, stats output for mem.quic and num.query.quic.

* - dnsoverquic, review fix.

* - dnsoverquic, fix when compiled without ngtcp2.

* - dnsoverquic, fix to detect ngtcp2_crypto_quictls for openssl crypto, after
  change in libngtcp2.

* - dnsoverquic, fix for newer ngtcp2 versions. detect ngtcp2_ccerr_default,
  ngtcp2/ngtcp2_crypto_quictls.h, struct ngtcp2_pkt_hd.tokenlen,
  struct ngtcp2_settings.tokenlen and struct ngtcp2_version_cid.

* - dnsoverquic, fix for newer ngtcp2 version, detect number of arguments for
  ngtcp2_conn_shutdown_stream.

* - dnsoverquic, fix for newer ngtcp2.

* - dnsoverquic, use the functions from util/timeval_func.h.

* - dnsoverquic, fix in doqclient only write transport parameters once.

* - dnsoverquic, debug log output removed.

* - dnsoverquic, fix in doqclient to work with renamed NGTCP2_CC_ALGO_BBR_V2
  from ngtcp2.

* - dnsoverquic, fix to check in doq_server_socket_create that tls-service-key
  and tls-service-pem have a value.

* - dnsoverquic, fix to error when doq_server_socket_create fails.

* - dnsoverquic, improve linebreaks in configparser additions.

* - dnsoverquic, fix port from interface pickup after main branch change.

* Fix getting user data from SSL, fix calloc warning.

* Fix fwrite return value check in doqclient

* - timeval_substruct from timeval_func.h
- lock_protect also for HAVE_NGTCP2_CCERR_DEFAULT
- fix doq logging for inet_ntop failures

* - memset for consistency
- no value returned from msghdr_get_ecn when S_SPLINT_S is defined

* - dnsoverquic, rerun autoconf.

---------

Co-authored-by: Yorgos Thessalonikefs <yorgos@nlnetlabs.nl>
2024-10-09 10:32:03 +02:00
W.C.A. Wijngaards dcf7afd722 - Fix #1128: Cannot override tcp-upstream and tls-upstream with
forward-tcp-upstream and forward-tls-upstream.
2024-10-08 15:29:03 +02:00
W.C.A. Wijngaards e67171612b - Fix #1149: unbound-control-setup hangs sometimes depending on
the openssl version.
2024-10-08 11:54:07 +02:00
Yorgos Thessalonikefs a1b25f0296 - The fix for CVE-2024-8508 was part of 1.21.1, a security point release
on 1.21.0. The code repository continues with this fix and the version
  number 1.22.0.
2024-10-03 18:19:01 +02:00
Yorgos Thessalonikefs 490585bf29 Merge branch 'release-1.21.1' 2024-10-03 18:14:01 +02:00
Yorgos Thessalonikefs b7c61d7cc2 - Fix CVE-2024-8508, unbounded name compression could lead to denial of
service.
2024-10-03 17:41:20 +02:00
Yorgos Thessalonikefs 01883fb017 - Set version to 1.21.1 2024-10-03 14:11:57 +02:00
W.C.A. Wijngaards 5bb3b9cc83 - Fix unbound dnstap socket test program analyzer warnings about
unused variable assignments and variable initialization.
2024-09-30 16:36:01 +02:00
W.C.A. Wijngaards 3a1b79f6a1 - Fix negative cache NSEC3 parameter compares for zero length NSEC3
salt.
2024-09-30 09:25:51 +02:00
W.C.A. Wijngaards 84eeb9b97c - Fix #1144: [FR] log timestamps in ISO8601 format with timezone.
This adds the option `log-time-iso: yes` that logs in ISO8601
  format.
2024-09-25 11:16:46 +02:00
Yorgos Thessalonikefs d88eeb4c32 Changelog entry for #1143:
- Merge #1143: Fix cache update when serve expired is used. Expired
  records are favored over resolution and validation failures when
  serve-expired is used.
2024-09-24 16:49:34 +02:00
Yorgos ThessalonikefsandGitHub 2e398d51ba Fix cache update when serve expired is used (#1143)
- Fix cache update when serve expired is used in order to not evict
  still usable expired records. Modules are forbidden to update the
  cache if their answer is DNSSEC unchecked or bogus and a valid
  (expired) entry already exists. Bogus replies from the validator are
  also discarded in favor of existing (expired) valid replies.

- serve-expired-ttl-reset should try to keep expired records in the
  cache in case they are reset.
2024-09-24 16:47:04 +02:00
Yorgos Thessalonikefs 24ebca7df6 - More clear text for prefetch and minimal-responses in the
unbound.conf man page.
2024-09-24 15:10:21 +02:00
Yorgos Thessalonikefs 7f4a61e6fc - Attempt to further fix doh_downstream_buffer_size.tdir flakiness. 2024-09-24 12:21:03 +02:00
Yorgos Thessalonikefs db719d404f - Fix doxygen warnings by commenting out CLANG_ASSISTED_PARSING,
CLANG_ADD_INC_PATHS, CLANG_OPTIONS and CLANG_DATABASE_PATH; they were
  already disabled.
2024-09-23 15:31:32 +02:00
W.C.A. Wijngaards a35a0c49da - Fix dns64 with prefetch that the prefetch is stored in cache. 2024-09-23 12:19:43 +02:00
W.C.A. Wijngaards 5e9b6296b7 - Add redis-command-timeout: 20 and redis-connect-timeout: 200,
that can set the timeout separately for commands and the
  connection set up to the redis server. If they are not
  specified, the redis-timeout value is used.
2024-09-17 13:10:34 +02:00
W.C.A. Wijngaards 606e262fdd Changelog comment for #1140.
- Merge #1140: Fix spelling mistake in comments.
2024-09-16 12:15:04 +02:00
TochusandGitHub 819764663b Fix spelling mistake in comments (#1140)
I noticed a spelling mistake in the comments. The term “chain of trust” was incorrectly written as “chainoftrust”. This change corrects the spelling to “chain of trust” which is the correct term used in English.
2024-09-16 12:14:28 +02:00
Yorgos Thessalonikefs 6bf2b2ac56 - Fix and add comments in testdata/val_negcache_ttl.rpl. 2024-09-11 12:16:02 +02:00
W.C.A. Wijngaards 5767b0933f - Add unit test for ttl limit for aggressive nsec. 2024-09-10 10:17:31 +02:00
W.C.A. Wijngaards 24e0f0ab7e - Fix to limit NSEC and NSEC3 TTL when aggressive nsec is
enabled (RFC9077).
2024-09-10 10:13:48 +02:00
Yorgos Thessalonikefs d3fdbba877 - Fix comment to not trigger doxygen unknown command. 2024-09-06 16:03:20 +02:00
Yorgos Thessalonikefs c36ce2a390 - Fix alloc-size and calloc-transposed-args compiler warnings. 2024-09-06 16:01:30 +02:00
W.C.A. Wijngaards 7ecff4113c - Fix config file read for dnstap-sample-rate. 2024-09-05 09:35:54 +02:00
W.C.A. Wijngaards 99824bc0e6 Changelog note for #1135
- Merge #1135: Add new IANA trust anchor.
2024-09-02 09:25:44 +02:00
9f09c36401 Add new IANA trust anchor (#1135)
Signed-off-by: Keelan Cannoo <keelan.cannoo@cyberstorm.mu>
Co-authored-by: Keelan10 <keelan.cannoo@cyberstorm.mu>
2024-09-02 09:24:55 +02:00
W.C.A. Wijngaards a887284703 - Fix for #1132, comment about adjusted copy of reference check. 2024-08-30 08:56:00 +02:00
W.C.A. Wijngaards fb198b96f1 Changelog note for #1132 and fix for #1132.
- Merge #1132: b.root renumbering.
- Fix for #1132, adjusted unit test for change in the test file.
2024-08-30 08:51:56 +02:00
Loganaden VelvindronandGitHub 30bf996f39 b.root renumbering (#1132)
https://b.root-servers.org/news/2023/05/16/new-addresses.html

Worked together with Jaykishan Muktawoa <jay@cyberstorm.mu>
2024-08-30 08:48:31 +02:00
W.C.A. Wijngaards 52154e658a - Fix to print port number in logs for auth zone transfer activities. 2024-08-29 13:04:03 +02:00
W.C.A. Wijngaards c06d3646a9 - Unit test for auth zone transfer TLS, and TLS failure. 2024-08-29 10:40:31 +02:00
W.C.A. Wijngaards 42d421a305 - Fix that stub-zone and forward-zone clauses do not exhaust memory
for long content.
2024-08-28 13:16:29 +02:00
W.C.A. Wijngaards b5951ce1fa - Fix that when rpz is applied the message does not get picked up by
the validator. That stops validation failures for the message.
2024-08-28 10:51:22 +02:00
W.C.A. Wijngaards 6b37309705 - Fix #1130: Loads of logs: "validation failure: key for validation
<domain>. is marked as invalid because of a previous" for
  non-DNSSEC signed zone.
2024-08-27 17:00:27 +02:00
W.C.A. Wijngaards dc274fef9b - Fix documentation for cache_fill_missing function. 2024-08-23 13:19:15 +02:00
W.C.A. Wijngaards db1167c8b3 - Fix #1127: error: "memory exhausted" when defining more than 9994
local-zones.
2024-08-23 09:22:07 +02:00
W.C.A. Wijngaards 1e0cf1e86b - Merge patch to fix for glue that is outside of zone, with
`harden-unverified-glue`, from Karthik Umashankar (Microsoft).
  Enabling this option protects the Unbound resolver against bad
  glue, that is unverified out of zone glue, by resolving them.
  It uses the records as last resort if there is no other working
  glue.
2024-08-23 08:56:48 +02:00
W.C.A. Wijngaards 348df52e05 Enable ci back after debug. 2024-08-21 14:20:04 +02:00
W.C.A. Wijngaards 6b3266aaf8 - Fix for char signedness warnings on NetBSD. 2024-08-21 14:15:23 +02:00
W.C.A. Wijngaards 4f52461e81 - Add cross platform netbsd to github ci. 2024-08-21 14:03:11 +02:00
W.C.A. Wijngaards 06d5031d22 - Add cross platform openbsd to github ci. 2024-08-21 13:50:55 +02:00
W.C.A. Wijngaards 12119e2d3e ci for freebsd nicer, with libevent, faster without static compile, and
with grouped output, also the pkg install is conditional on the platform.
2024-08-21 13:37:42 +02:00
W.C.A. Wijngaards 19d53d5663 Fix for freebsd ci. 2024-08-21 13:24:54 +02:00
W.C.A. Wijngaards 04e6f9e03b - Add cross platform freebsd to github ci. 2024-08-21 13:20:00 +02:00
W.C.A. Wijngaards 3d350fa73d - Add iter-scrub-ns, iter-scrub-cname and max-global-quota
configuration options.
2024-08-20 14:08:52 +02:00
W.C.A. Wijngaards 015b2b0daf - Fix #1126: unbound-control-setup hangs while testing for openssl
presence starting from version 1.21.0.
2024-08-19 15:51:47 +02:00
W.C.A. Wijngaards 5fa84d50bf - Tag for release 1.21.0, the repository continues with 1.21.1
in development.
2024-08-15 11:01:41 +02:00
W.C.A. Wijngaards 79e4c57851 - Fix spelling for the cache-min-negative-ttl entry in the
example.conf.
2024-08-09 14:04:25 +02:00
W.C.A. Wijngaards 5abdd09095 - Fix that for windows the module startup is called and sets up
the module-config.
2024-08-08 16:14:09 +02:00
W.C.A. Wijngaards 158c1defe3 - Set version number to 1.21.0 for release. 2024-08-08 09:30:53 +02:00
W.C.A. Wijngaards b4519012dc - Fix CacheFlush issues with limit on NS RRs. Thanks to Yehuda Afek,
Anat Bremler-Barr, Shoham Danino and Yuval Shavitt (Tel-Aviv
  University and Reichman University).
2024-08-08 09:28:44 +02:00
W.C.A. Wijngaards ed883238fd - Fix CAMP issues with global quota. Thanks to Huayi Duan, Marco
Bearzi, Jodok Vieli, and Cagin Tanir from NetSec group, ETH Zurich.
2024-08-08 09:27:45 +02:00
W.C.A. Wijngaards 0f2f6025e7 - Fix that alloc stats for forwards and hints are printed, and when
alloc stats is enabled, the unit test for unbound control waits for
  reloads to complete.
2024-08-02 15:51:40 +02:00
W.C.A. Wijngaards 3cbf554e3b Changelog note for #1090
- Merge #1090: Cookie secret file. Adds
  `cookie-secret-file: "unbound_cookiesecrets.txt"` option to store
  cookie secrets for EDNS COOKIE secret rollover. The remote control
  add_cookie_secret, activate_cookie_secret and drop_cookie_secret
  commands can be used for rollover, the command print_cookie_secrets
  shows the values in use.
2024-08-02 13:36:06 +02:00
ad21dbd1c2 Cookie secret file (#1090)
* - cookie-secret-file, define struct.

* - cookie-secret-file, add config option, create, read and delete struct.

* - cookie-secret-file, check cookie secrets for cookie validation.

* - cookie-secret-file, unbound-control add_cookie_secret, drop_cookie_secret,
  activate_cookie_secret and print_cookie_secrets.

* - cookie-secret-file, test and fix locks, renew writes a fresh cookie,
  staging cookies get a fresh cookie and spelling in error message.

* - cookie-secret-file, remove unused variable from cookie file unit test.

* Remove unshare and faketime dependencies for cookie_file test; documentation nits.

---------

Co-authored-by: Yorgos Thessalonikefs <yorgos@nlnetlabs.nl>
2024-08-02 13:32:08 +02:00
W.C.A. Wijngaards 50cf55bdac Update changelog.
- Fix testbound for alloc stats strdup in util/alloc.c.
2024-08-02 08:59:47 +02:00
W.C.A. Wijngaards 6106528a50 - Fix testbound for alloc stats strdup in util/alloc.c. 2024-08-02 08:58:22 +02:00
W.C.A. Wijngaards befa7d8cd8 - Fix that alloc stats has strdup checks, it stops debuggers from
complaining about mismatch at free time.
2024-08-02 08:54:54 +02:00
W.C.A. Wijngaards 92be76fb89 - Fix that the worker mem report with alloc stats does not attempt
to print memory use of forwards and hints if they have been
  deleted already.
2024-08-01 17:15:07 +02:00
W.C.A. Wijngaards 9a6b6765cc - Fix dnstap test program, cleans up to have clean memory on exit,
for tap_data_free, does not delete NULL items. Also it does not try
  to free the tail, specifically in the free of the list since that
  picked up the next item in the list for its loop causing invalid
  free. Added internal unit test to unbound-dnstap-socket for that.
2024-08-01 16:12:04 +02:00
W.C.A. Wijngaards 03b511b1a2 - Fix for #1114: Fix that cache fill for forward-host names is
performed, so that with nonzero target-fetch-policy it fetches
  forwarder addresses and uses them from cache. Also updated that
  delegation point cache fill routines use CDflag for AAAA message
  lookups, so that its negative lookup stops a recursion since the
  cache uses the bit for disambiguation for dns64 but the recursion
  uses CDflag for the AAAA target lookups, so the check correctly
  stops a useless recursion by its cache lookup.
2024-07-31 11:42:44 +02:00
W.C.A. Wijngaards 6af28bed08 - Fix to document parameters of auth_zone_verify_zonemd_with_key. 2024-07-30 13:47:53 +02:00
W.C.A. Wijngaards f094f4ea3c - Add root key 38696 from 2024 for DNSSEC validation. It is added
to the default root keys in unbound-anchor. The content can be
  inspected with `unbound-anchor -l`.
2024-07-25 11:42:22 +02:00
Yorgos Thessalonikefs c717debace - For #935 and #1104, clarify RPZ order and semantics. 2024-07-24 01:54:02 +02:00
Yorgos Thessalonikefs 7d4d21764a - Cleanup ede.tdir test. 2024-07-23 20:22:25 +02:00
W.C.A. Wijngaards 83e6977f06 - Fix link of unbound-dnstap-socket without openssl. 2024-07-23 15:06:54 +02:00
W.C.A. Wijngaards 671e11552c - Fix link of dnstap without openssl. 2024-07-23 14:56:21 +02:00
W.C.A. Wijngaards c4541e634b - Fix uninitialized variable warning in create_tcp_accept_sock. 2024-07-23 10:42:36 +02:00
W.C.A. Wijngaards 30da725e67 - Fix to have empty definition when not supported for weak attribute. 2024-07-23 10:02:39 +02:00
W.C.A. Wijngaards 8de5ae3552 - Fix compile when the compiler does not support the noreturn
attribute.
2024-07-23 09:55:31 +02:00
W.C.A. Wijngaards 5bea29b01c - For #1110: Test for fallthrough attribute in configure and add
fallthrough attribute annotations.
2024-07-23 09:47:42 +02:00
Wouter WijngaardsandGitHub 89c9eafa44 Merge pull request #1110 from r-barnes/patch-1
Make fallthrough explicit for libworker.c
2024-07-23 09:44:28 +02:00
Yorgos Thessalonikefs 3512eaec48 - Fix #1106: ratelimit-below-domain logs the wrong FROM address. 2024-07-23 09:07:06 +02:00
Richard BarnesandGitHub f9bd35dcfa Make fallthrough explicit for libworker.c
The code currently doesn't compile with LLVM's `-Wimplicit-fallthrough` flag, but the attribute works for both GCC (>=7) and LLVM.
2024-07-22 16:37:38 -07:00
W.C.A. Wijngaards 3af4e44646 - Fix dnstap wakeup, a running wakeup timer is left to expire and not
increased, a timer is started when the dtio thread is sleeping,
  the timer set disabled when the dtio thread goes to sleep, and
  after sleep the thread checks to see if there are messages to log
  immediately.
2024-07-19 16:16:02 +02:00
W.C.A. Wijngaards c3dd6a2dbd - Add dnstap-sample-rate that logs only 1/N messages, for high volume
server environments. Thanks Dan Luther.
2024-07-19 10:04:40 +02:00
W.C.A. Wijngaards 8fca3e7c5b - For #1103: Fix to drop mesh state reference for the http2 stream
associated with the reply, not the currently active stream. And
  it does not remove it twice on a mesh_send_reply call. The reply
  h2_stream is NULL when not in use, for more initialisation.
2024-07-16 14:23:10 +02:00
W.C.A. Wijngaards 8947c2c764 - For #1103: fix to also drop mesh state reference when the discard
limit is reached, when there is an error making a new recursion
  state and when the connection is dropped with is_drop.
2024-07-15 14:51:20 +02:00
W.C.A. Wijngaards b1e3319a11 Merge branch 'master' of github.com:NLnetLabs/unbound 2024-07-12 16:41:58 +02:00
W.C.A. Wijngaards d52f501d90 - For #1103: fix to also drop mesh state reference when a h2 reply is
dropped.
2024-07-12 16:41:46 +02:00
Yorgos Thessalonikefs 7083d58c6b - For #1102: clearer text for using interface-* options for the
loopback interface.
2024-07-12 16:29:44 +02:00
W.C.A. Wijngaards 3adb9c8f92 - Fix #1103: unbound 1.20.0 segmentation fault with nghttp2. 2024-07-12 16:11:29 +02:00
Yorgos Thessalonikefs 51425b2388 - Add RPZ tag tests in acl_interface.tdir. 2024-07-12 15:38:12 +02:00
W.C.A. Wijngaards d43760a8cd - For #773: In contrib/unbound.service.in set unbound to start after
network-online.target. Also for contrib/unbound_portable.service.in.
2024-07-10 14:05:43 +02:00
Yorgos Thessalonikefs ea3e327006 - Update list of known EDE codes. 2024-07-09 15:58:30 +02:00
W.C.A. Wijngaards be09350eca - Fix shadowed error string variable in validator dnskey handling. 2024-07-08 16:50:16 +02:00
W.C.A. Wijngaards 169acfc546 - Fixup algo_needs_reason string buffer length. 2024-07-08 15:38:27 +02:00
W.C.A. Wijngaards bed7cc2a90 - Fix that validation reason failure that uses string print uses
separate buffer that is passed, from the scratch validation buffer.
2024-07-08 15:29:20 +02:00
Yorgos Thessalonikefs 02f4446833 - Don't check for message TTL changes if the RRsets remain the same. 2024-07-05 19:58:19 +02:00
W.C.A. Wijngaards c8a2289542 - Fix for #1099: Fix to check for deleted RRset when the contents
is updated and fetched after it is stored, and also check for a
  changed RRset.
2024-07-05 17:54:46 +02:00
W.C.A. Wijngaards b53d90053e - Fix #1099: Unbound core dump on SIGSEGV. 2024-07-05 17:18:01 +02:00
W.C.A. Wijngaards 978b0696d3 - Fix neater printout. 2024-07-05 14:11:26 +02:00
W.C.A. Wijngaards ec5f86b4eb - Fix for neater printout for error for missing DS response. 2024-07-05 08:49:52 +02:00
W.C.A. Wijngaards ec2f45c6fd - Fix to print details about the failure to lookup a DNSKEY record
when validation fails due to the missing DNSKEY. Also for key prime
  and DS lookups.
2024-07-04 14:51:18 +02:00
W.C.A. Wijngaards 6b319c97ee - Fix compile warnings in fptr_wlist.c. 2024-07-03 16:42:52 +02:00
W.C.A. Wijngaards 6eb3992c9e - Fix to remove unneeded linebreak in fptr_wlist.c. 2024-07-03 15:51:22 +02:00
W.C.A. Wijngaards 94a94fd8c8 - Fix to use modstack_init in zonemd unit test. 2024-07-03 15:49:13 +02:00
W.C.A. Wijngaards 36f9d1a2a9 - Add unit test skip files and bison and flex output to gitignore. 2024-07-03 14:59:39 +02:00
W.C.A. Wijngaards d3a2264272 Changelog entry for #144 and #1098
- Fix #144: Port ipset to BSD pf tables.
2024-07-03 14:53:42 +02:00
Wouter WijngaardsandGitHub 92b6c2a7b9 Merge pull request #1098 from NLnetLabs/ipset-pf-support
Ipset pf support
2024-07-03 14:49:16 +02:00
W.C.A. Wijngaards a335e601e4 ipset-pf-support, move startup and destartup to the front of the module
func block functions, modstack call deinit function names, and detect
module change when no startup functions are needed.
2024-07-03 13:53:44 +02:00
a19009df1d Apply suggestions from code review
Co-authored-by: Yorgos Thessalonikefs <yorgos@nlnetlabs.nl>
2024-07-03 13:08:51 +02:00
Yorgos Thessalonikefs 96f8a94c19 - Fix for repeated use of a DNAME record: first overallocate and then
move the exact size of the init value to avoid false positive heap
  overflow reads from address sanitizers.
2024-07-03 10:08:44 +02:00
W.C.A. Wijngaards 2fe4e2ec3e - Fix compile warning in worker pthread id printout. 2024-07-02 09:44:58 +02:00
W.C.A. Wijngaards e54928a628 - Fix unused variable warning in do_cache_remove. 2024-07-02 09:33:22 +02:00
W.C.A. Wijngaards 538434186e - Fix to remove unused include from the readzone test program. 2024-07-02 09:31:34 +02:00
W.C.A. Wijngaards 65e7253d19 ipset-pf-support, simplification of code. 2024-07-02 09:08:27 +02:00
W.C.A. Wijngaards 03ac902296 - ipset-pf-support, fix to skip unit test if no pf dev. 2024-07-01 17:11:20 +02:00
W.C.A. Wijngaards 97ad1df343 ipset-pf-support, fix to log error on failure to open pf. 2024-07-01 17:06:11 +02:00
W.C.A. Wijngaards 2279cde8f7 ipset-pf-support, fix to remove unused include, free at end, adjust
qname for comparison.
2024-07-01 17:02:49 +02:00
W.C.A. Wijngaards ff653a7ef8 Call module init init again, and new function startup and destartup.
NULL can be used if the function is not used. Open shared ports during
reload. Deinit is called during reload.
2024-07-01 16:10:07 +02:00
W.C.A. Wijngaards fd11cd9182 ipset-pf-support, fix compilation, close of pf socket. 2024-07-01 14:54:45 +02:00
W.C.A. Wijngaards 3953f827fb Merge branch 'master' of https://github.com/madroach/unbound into ipset-pf-support 2024-07-01 14:36:33 +02:00
W.C.A. Wijngaards 7fbc061846 - Fix ip-ratelimit-cookie setting, it was not applied. 2024-06-27 14:51:58 +02:00
Yorgos Thessalonikefs 70f73a33b3 - Explicitly set the RD bit for the mesh query flags when prefetching.
These queries have no waiting client but they need to be treated as
  recursive.
2024-06-26 15:51:58 +02:00
Yorgos Thessalonikefs b67fbb69e7 - Fix pkg-config availability check in dnstap/dnstap.m4 and
systemd.m4.
- autoconf.
2024-06-21 14:34:12 +02:00
Yorgos Thessalonikefs 902c79608c - Fix #1092: Ubuntu 22.04 Jammy fails to compile unbound 1.20.0; by
adding helpful text for the Python interpreter version and allowing
  the default pkg-config unavailability error message to be shown.
- autoconf.
2024-06-19 15:27:50 +02:00
W.C.A. Wijngaards 08050dc939 - Fix #1091: Build fails with OpenSSL >= 3.0 built with
OPENSSL_NO_DEPRECATED.
2024-06-17 12:28:45 +02:00
W.C.A. Wijngaards 9603924bb4 - Add unit test for validation of repeated use of a DNAME record. 2024-06-07 11:56:19 +02:00
W.C.A. Wijngaards 4c2da2b979 - Fix validation for repeated use of a DNAME record. 2024-06-06 15:28:21 +02:00
W.C.A. Wijngaards 1974732d19 - Fix typos for 'the the' in text. 2024-06-06 09:35:57 +02:00
W.C.A. Wijngaards 3cad5818a1 - Fix memory leak in setup of dsa sig. 2024-06-06 09:30:09 +02:00
Yorgos Thessalonikefs ad12109191 - Merge #1080: AddressSanitizer detection in tdir tests and memory leak
fixes.
2024-06-04 17:34:58 +02:00
Yorgos Thessalonikefs f611220eb8 - Skip unbound-dnstap-socket unit test when not compiled with
--enable-debug.
2024-06-04 16:59:58 +02:00
W.C.A. Wijngaards 86fe9cbce5 - Fix to squelch connection reset by peer errors from log. And fix
that the tcp read errors are labeled as initial for the first calls.
2024-06-03 12:14:51 +02:00
Yorgos Thessalonikefs ac609fcbfc - Fix memory leak on exit for unbound-dnstap-socket; creates false negatives
during testing.
2024-05-31 12:11:17 +02:00
Yorgos Thessalonikefs 486985fbdf - Fix memory leak when reload_keep_cache is used and num-threads changes. 2024-05-31 12:09:35 +02:00
Yorgos Thessalonikefs caab100207 - Enable AddressSanitizer error detection in tdir tests. 2024-05-31 12:08:43 +02:00
W.C.A. Wijngaards 4b30e88eec - Fix for #1079: fix RPZ taglist in iterator callback that no client
info is like no taglist intersection.
2024-05-30 12:44:26 +02:00
W.C.A. Wijngaards b6c7ea563f - Fix #1079: tags from tagged rpz zones are no longer honored after
upgrade from 1.19.3 to 1.20.0.
2024-05-30 12:11:30 +02:00
W.C.A. Wijngaards 910d7cf446 Changelog note for #1078.
- Merge #1078: Only check old pid if no username.
2024-05-29 14:45:01 +02:00
Wouter WijngaardsandGitHub cd485f2036 Merge pull request #1078 from vopatek/master
Only check old pid if no username
2024-05-29 14:44:31 +02:00
Martin Vopatek 8ff1baf585 Only check old pid if no username
Do as the comment says and only check old pid if there is no username
configured.
2024-05-29 14:16:18 +02:00
Yorgos Thessalonikefs 5fc4673901 - Update patch to remove 'command' shell builtin and update error
text.
2024-05-27 17:17:48 +02:00
Michael TokarevandYorgos Thessalonikefs faf3d358dc unbound-control-setup: check openssl
Before doing anything, check if openssl binary (which we will use)
is available, and print a useful error message if it is not found.
2024-05-27 16:35:34 +02:00
Yorgos Thessalonikefs f5a2160ba3 - Fix unused variable warning on compilation with no thread support. 2024-05-27 14:56:52 +02:00
W.C.A. Wijngaards 0c0c36f015 - Fix spelling of tcp-idle-timeout docs, from Michael Tokarev. 2024-05-27 14:36:35 +02:00
W.C.A. Wijngaards 47956de897 - Fix to enable that SERVFAIL is cached, for a short period, for more
cases. In the cases where limits are exceeded.
2024-05-27 13:53:16 +02:00
Yorgos Thessalonikefs b30c869a59 Changelog entry for #1059:
- Fix #1059: Intermittent DNS blocking failure with local-zone and
  always_nxdomain. Addition of local_zones dynamically via
  unbound-control was not finding the zone's parent correctly.
2024-05-24 15:24:52 +02:00
Yorgos ThessalonikefsandGitHub 6f030e9672 Proper parent identification for dynamically entered local zones (#1076)
- Fix #1059: Intermittent DNS blocking failure with local-zone and
  always_nxdomain. Addition of local_zones dynamically via
  unbound-control was not finding the zone's parent correctly.
2024-05-24 15:21:40 +02:00
W.C.A. Wijngaards 7107d3c9e7 - Fix #1064: Unbound 1.20 Cachedb broken?
Add unit test for validation status commit.
2024-05-24 09:06:48 +02:00
W.C.A. Wijngaards fbdc06ebc4 - Fix for #1064: Fix that cachedb expired messages are considered
insecure, and thus can be served to clients when dnssec is enabled.
2024-05-21 17:06:18 +02:00
W.C.A. Wijngaards d149e755fd - Fix for parse end of forward-zone, stub-zone and view. 2024-05-21 12:04:57 +02:00
W.C.A. Wijngaards 86ee8ccd12 - Fix to print a parse error when config is read with no name for
a forward-zone, stub-zone or view.
2024-05-21 11:54:18 +02:00
W.C.A. Wijngaards 8d6a1ba811 Changelog note for #1073.
- Merge #1073: fix null pointer dereference issue in function
  ub_ctx_set_fwd.
2024-05-21 11:52:47 +02:00
Wouter WijngaardsandGitHub 9ccb8d5f20 Merge pull request #1073 from xiaoxiaoafeifei/master
fix null pointer dereference issue in function ub_ctx_set_fwd
2024-05-21 11:51:52 +02:00
zhailiangliang 8e43e2574c fix null pointer dereference issue in function ub_ctx_set_fwd of file libunbound/libunbound.c 2024-05-21 08:40:35 +00:00
Yorgos Thessalonikefs 2e70506763 Changelog entry for #1069:
- Merge #1069: Fix unbound-control stdin commands for multi-process
  Unbounds.
2024-05-17 10:31:20 +02:00
7f184c8ca8 Fix unbound-control stdin commands for multi-process Unbounds (#1069)
- Fix unbound-control commands that read stdin in multi-process
  operation (local_zones_remove, local_zones, local_datas_remove,
  local_datas, view_local_datas_remove, view_local_datas). They will
  be properly distributed to all processes. dump_cache and load_cache
  are no longer supported in multi-process operation.

 - Remove testdata/remote-threaded.tdir. testdata/09-unbound-control.tdir
  now checks both single and multi process/thread operation.

---------

Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>
2024-05-17 10:25:24 +02:00
W.C.A. Wijngaards da2b307aa3 - Fix #1071: [FR] Clear both in-memory and cachedb module cache with
`unbound-control flush*` commands.
2024-05-16 16:56:58 +02:00
Yorgos Thessalonikefs 739a88ceed Changelog entry for #1070:
- Merge #1070: Fix rtt assignement for low values of
  infra-cache-max-rtt.
2024-05-16 13:43:24 +02:00
Yorgos ThessalonikefsandGitHub 3ff5c7a74d Fix rtt assignement for low values of infra-cache-max-rtt (#1070)
* Fix rtt assignement for still useful servers when a low value for
  infra-cache-max-rtt is configured.
2024-05-16 13:42:32 +02:00
Yorgos Thessalonikefs 1048c4a28c - Add missing common functions to tdir tests. 2024-05-15 11:20:36 +02:00
W.C.A. Wijngaards 7de009f99a - Fix when the mesh jostle is exceeded that nameserver targets are
marked as resolved, so that the lookup is not stuck on the
  requestlist.
2024-05-10 09:50:35 +02:00
W.C.A. Wijngaards 95669855fb - Fix to squelch udp connect errors in the log at low verbosity about
invalid argument for IPv6 link local addresses.
2024-05-08 16:40:41 +02:00
W.C.A. Wijngaards 56e7cade28 The code repository continues with version 1.20.1. 2024-05-08 11:10:53 +02:00
W.C.A. Wijngaards c085a53268 - Fix for #1062: declaration before statement, avoid print of null,
and redundant check for array size.
And changelog note for merge of #1062.
2024-05-07 14:05:21 +02:00
Wouter WijngaardsandGitHub 49569b81aa Merge pull request #1062 from xiaoxiaoafeifei/master
Fix potential overflow bug while parsing port in function cfg_mark_ports
2024-05-07 14:02:21 +02:00
zhailiangliang 4497e8a154 Fix potential overflow bug while parsing port in function cfg_mark_ports 2024-05-07 11:35:52 +00:00
W.C.A. Wijngaards b9525c5fd4 - Set version number to 1.20.0 for release. 2024-05-01 10:15:12 +02:00
W.C.A. Wijngaards c3206f4568 - Fix for the DNSBomb vulnerability CVE-2024-33655. Thanks to Xiang Li
from the Network and Information Security Lab of Tsinghua University
  for reporting it.
2024-05-01 10:10:58 +02:00
W.C.A. Wijngaards 9abed3fc83 - Fix doxygen comment for errinf_to_str_bogus. 2024-04-29 13:42:26 +02:00
Yorgos Thessalonikefs 63a6b7b255 - Cleanup unnecessary strdup calls for EDE strings. 2024-04-29 10:15:19 +02:00
W.C.A. Wijngaards 15dc8e8a3f - Man page entry for unbound-checkconf -q. 2024-04-26 14:54:25 +02:00
Yorgos Thessalonikefs cd4a017e96 - Fix #876: [FR] can unbound-checkconf be silenced when configuration
is valid?
2024-04-26 14:50:39 +02:00
W.C.A. Wijngaards 82c0207fa6 - Add unit tests for cachedb and subnet cache expired data. 2024-04-26 13:33:26 +02:00
W.C.A. Wijngaards 7c5e765b3b - Fix cachedb with serve-expired-client-timeout disabled. The edns
subnet module deletes global cache and cachedb cache when it
  stores a result, and serve-expired is enabled, so that the global
  reply, that is older than the ecs reply, does not return after
  the ecs reply expires.
2024-04-26 13:32:15 +02:00
W.C.A. Wijngaards f456d97a34 - Fix doc unit test for out of directory build. 2024-04-25 17:06:06 +02:00
W.C.A. Wijngaards 8b490b1540 - Fix to disable fragmentation on systems with IP_DONTFRAG,
with a nonzero value for the socket option argument.
2024-04-25 12:53:05 +02:00
W.C.A. Wijngaards b3951e5885 Changelog note for #1041 and #1038.
- Merge #1041: Stub and Forward unshare. This has one structure
  for them and fixes #1038: fatal error: Could not initialize
  thread / error: reading root hints.
2024-04-25 11:12:27 +02:00
Wouter WijngaardsandGitHub ced9762b14 Merge pull request #1041 from NLnetLabs/stubfwd-unshare
Stub and Forward unshare
2024-04-25 11:11:00 +02:00
9b9bba9f02 Update locking management for iter_fwd and iter_hints methods. (#1054)
fast reload, move most of the locking management to iter_fwd and
iter_hints methods. The caller still has the ability to handle its
own locking, if desired, for atomic operations on sets of different
structs.

Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>
2024-04-25 11:05:58 +02:00
W.C.A. Wijngaards 07859a9ef3 - Fix configure flto check error, by finding grep for it. 2024-04-25 10:53:35 +02:00
W.C.A. Wijngaards cb74467acb - Fix ci workflow for macos for moved install locations. 2024-04-24 16:31:44 +02:00
Yorgos Thessalonikefs 62dad42152 - Merge #1053: Remove child delegations from cache when grandchild
delegations are returned from parent.
2024-04-23 14:24:07 +02:00
Yorgos Thessalonikefs 3ec74d1e3a - When a granchild delegation is returned, remove any cached child delegations
up to parent to not cause delegation invalidation because of an
  expired child delegation that would never be updated. Most likely to
  happen without qname-minimisation. Reported by Roland van Rijswijk-Deij.
2024-04-22 15:46:06 +02:00
W.C.A. Wijngaards 52aff65e35 - Fix edns subnet to sort rrset references when storing messages
in the cache. This fixes a race condition in the rrset locks.
2024-04-22 13:44:42 +02:00
W.C.A. Wijngaards 5994fb3db5 - Add checklock feature verbose_locking to trace locks and unlocks. 2024-04-22 13:42:35 +02:00
Yorgos Thessalonikefs 0dbcb45d28 Changelog entry for #1049:
- Merge #1049 from Petr Menšík: Py_NoSiteFlag is not needed since
  Python 3.8
2024-04-15 14:49:14 +02:00
Yorgos ThessalonikefsandGitHub d71f257215 Merge pull request #1049 from InfrastructureServices/python3.12-Py_NoSiteFlag-warning
Py_NoSiteFlag is not needed since Python 3.8
2024-04-15 14:47:45 +02:00
Petr Mensik b11d234f77 Py_NoSiteFlag is not needed since Python 3.8
Python since 3.12 prints warning about Py_NoSiteFlag is deprecated. It
seems that variable is not needed since Python 3.8, since it sets in
such cases directly config.site_import variable few moments later.
Move using deprecated variable to versions before that flag in config
could be used only.

This should fix warning like:

pythonmod/pythonmod.c: In function 'pythonmod_init':
pythonmod/pythonmod.c:359:7: warning: 'Py_NoSiteFlag' is deprecated [-Wdeprecated-declarations]
  359 |       Py_NoSiteFlag = 1;
      |       ^~~~~~~~~~~~~
In file included from /usr/include/python3.12/Python.h:48,
                 from pythonmod/pythonmod.c:54:
/usr/include/python3.12/cpython/pydebug.h:14:37: note: declared here
   14 | Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_NoSiteFlag;
      |                                     ^~~~~~~~~~~~~

https://docs.python.org/3/c-api/init.html#c.Py_NoSiteFlag
2024-04-15 13:52:41 +02:00
W.C.A. Wijngaards 0d4c5aa421 - Fix configure, autoconf for #1048. 2024-04-15 12:17:56 +02:00
W.C.A. Wijngaards 9e60f93b84 Changelog note for #1048.
- Fix #1048: Update ax_pkg_swig.m4 and ax_pthread.m4.
2024-04-15 12:15:54 +02:00
Wouter WijngaardsandGitHub 9d63e8f093 Merge pull request #1048 from InfrastructureServices/configure-m4-refresh
Update ax_pkg_swig.m4 and ax_pthread.m4
2024-04-15 12:15:26 +02:00
Petr Mensik 4c40253df7 Update ax_pkg_swig.m4 and ax_pthread.m4
Use vanilla m4 files with known source. Prepared for possible removal at
build time if the system already has autoconf-archive source present.
Switch to AX_PKG_SWIG macro for versioned or unversioned swig detection.
2024-04-15 11:54:46 +02:00
W.C.A. Wijngaards 491b56d051 - Fixup cachedb to not refetch when serve-expired-client-timeout is
used.
2024-04-12 14:22:18 +02:00
W.C.A. Wijngaards 4d530920e0 - Fixup unit test for cachedb server expired client timeout with
a check if response if from upstream or from cachedb.
2024-04-12 11:51:00 +02:00
W.C.A. Wijngaards 08fb9a9209 - Fix cachedb for serve-expired with serve-expired-client-timeout. 2024-04-12 11:26:53 +02:00
W.C.A. Wijngaards 04ff2672b5 - Fix to not reply serve expired unless enabled for cachedb. 2024-04-10 17:06:01 +02:00
W.C.A. Wijngaards d47849a26e - Fix cachedb for serve-expired with serve-expired-reply-ttl. 2024-04-10 17:01:57 +02:00
W.C.A. Wijngaards 63ee97d0fd - Fix makefile dependencies for fake_event.c. 2024-04-10 14:04:39 +02:00
W.C.A. Wijngaards bd74a32b79 - Extended test for cachedb serve expired. 2024-04-10 13:08:23 +02:00
W.C.A. Wijngaards b990be88ef - Add test for cachedb serve expired. 2024-04-10 12:36:21 +02:00
W.C.A. Wijngaards cccf5e73c0 - Fixup compile without cachedb. 2024-04-10 11:33:52 +02:00
W.C.A. Wijngaards f3f85e5a11 - Fixup compile without cachedb. 2024-04-10 11:29:10 +02:00
W.C.A. Wijngaards d55511f1dd - Fixup compile without cachedb. 2024-04-10 11:27:08 +02:00
W.C.A. Wijngaards d98c7b9ae3 - Implement cachedb-check-when-serve-expired: yes option, default
is enabled. When serve expired is enabled with cachedb, it first
  checks cachedb before serving the expired response.
2024-04-10 11:21:28 +02:00
Yorgos Thessalonikefs a30221c5bb - Merge #1043 from xiaoxiaoafeifei: Add loongarch support; updates
config.guess(2024-01-01) and config.sub(2024-01-01), verified
  with upstream.
2024-04-09 17:00:59 +02:00
zhailiangliang 411e843fc4 Add loongarch support:
1. update config.guess(2024-01-01) and config.sub(2024-01-01)
  2. add loongarch to little endian support
2024-04-09 11:15:14 +08:00
Yorgos Thessalonikefs 8575d5b35c - Fix #595: unbound-anchor cannot deal with full disk; it will now
first write out to a temp file before replacing the original one,
  like Unbound already does for auto-trust-anchor-file.
2024-04-08 14:15:03 +02:00
W.C.A. Wijngaards ba16e41160 - Fix comment syntax for view function views_find_view. 2024-04-05 16:11:29 +02:00
Yorgos Thessalonikefs 708d5229ae - Merge #1027: Introduce 'cache-min-negative-ttl' option. 2024-04-05 11:44:37 +02:00
Yorgos Thessalonikefs fb4a7d65d7 - Fix #369: dnstap showing extra responses; for client responses
right from the cache when replying with expired data or
  prefetching.
2024-04-03 15:18:13 +02:00
W.C.A. Wijngaards d7353e6e99 - fast-reload, helpful comments for hints lookup function return value. 2024-04-03 13:55:57 +02:00
W.C.A. Wijngaards 48113cfaba - fast-reload, unshared stub hints, making the structure locked, with an rwlock. 2024-04-03 13:55:57 +02:00
W.C.A. Wijngaards c0b5754ef7 - fast-reload, for nonthreaded, the unbound-control commands forward,
forward_add and forward_delete should be distributed to other processes,
  but when threaded, they should not be distributed to other threads because
  the structure is not thread specific any more.
2024-04-03 13:55:57 +02:00
W.C.A. Wijngaards f2fb498c69 - fast-reload, unshare forwards, making the structure locked, with an rwlock. 2024-04-03 13:55:54 +02:00
Yorgos Thessalonikefs 91e8e0e511 - Fix #1035: Potential Bug while parsing port from the "stub-host"
string; also affected forward-zones and remote-control host
  directives.
2024-04-03 13:37:57 +02:00
W.C.A. Wijngaards dfff8d23cf - For #1040: adjust error text and disallow negative ports in other
parts of cfg_mark_ports.
2024-04-03 10:16:18 +02:00
W.C.A. Wijngaards 103d9a68fa Changelog note for #1040
- Fix #1040: fix heap-buffer-overflow issue in function cfg_mark_ports
  of file util/config_file.c.
2024-04-03 10:03:04 +02:00
Wouter WijngaardsandGitHub a814fe8c5f Merge pull request #1040 from xiaoxiaoafeifei/master
fix heap-buffer-overflow issue in function cfg_mark_ports of file util/config_file.c
2024-04-03 10:02:45 +02:00
zhailiangliang 193401e754 fix heap-buffer-overflow issue in function cfg_mark_ports of file util/config_file.c 2024-04-03 15:40:58 +08:00
W.C.A. Wijngaards e1aeabde44 - Fix for crypto related failures to have a better error string. 2024-03-28 09:58:57 +01:00
W.C.A. Wijngaards 6d1e61173b - Fix #1034: DoT forward-zone via unbound-control. 2024-03-28 09:58:03 +01:00
W.C.A. Wijngaards 6f82b5be4a - Fix that the server does not chown the pidfile. 2024-03-27 14:52:25 +01:00
W.C.A. Wijngaards 192f1b0e2b - Fix that when the server truncates the pidfile, it does not follow
symbolic links.
2024-03-27 14:07:54 +01:00
W.C.A. Wijngaards 238a796e38 - Fix to add unit test for lruhash space that exercises the routines. 2024-03-27 13:33:46 +01:00
W.C.A. Wijngaards fe393ac355 - Fix comment in lruhash space function. 2024-03-27 12:30:00 +01:00
W.C.A. Wijngaards 3ea078baf6 - Fix for #1032, add safeguard to make table space positive. 2024-03-27 11:49:20 +01:00
W.C.A. Wijngaards eb3e1ae24f - Fix #1032: The size of subnet_msg_cache calculation mistake cause
memory usage increased beyond expectations.
2024-03-27 11:45:34 +01:00
W.C.A. Wijngaards c2b20c585e - Fix name of unit test for subnet cache response. 2024-03-27 11:43:55 +01:00
Yorgos Thessalonikefs 07561964fc - For #831: Format text, use exclamation icon and explicit label
names.
2024-03-25 22:02:08 +01:00
Yorgos Thessalonikefs ce8c1ce5b0 Changelog entry for #831
- Merge #831 from Pierre4012: Improve Windows NSIS installer
  script (setup.nsi).
2024-03-25 16:46:25 +01:00
Pierre4012andGitHub ef60dcac31 Improve Windows NSIS installer script (setup.nsi) (#831)
* Improve Windows NSIS installer script (setup.nsi)

Two improvements of installer script :
- avoid error message when Unbound is running,
- add "DisplayVersion" in registry thus Windows package manager (Winget) can handle Unbound.

* Update setup.nsi ask user to stop unbound service + DisplayVersion in Windows registry
2024-03-25 16:43:49 +01:00
W.C.A. Wijngaards 73bd5a19aa - Fix localdata and rpz localdata to match CNAME only if no direct
type match is available.
2024-03-19 10:21:10 +01:00
W.C.A. Wijngaards fef974ca5c - Fix rpz so that rpz CNAME can apply after rpz CNAME. And fix that
clientip and nsip can give a CNAME.
2024-03-19 09:32:53 +01:00
W.C.A. Wijngaards 8dbf46913b - Fix rpz for qtype CNAME after nameserver trigger. 2024-03-18 14:36:29 +01:00
W.C.A. Wijngaards e46b188fe8 - Add rpz unit test for nsip action override. 2024-03-18 14:11:43 +01:00
W.C.A. Wijngaards e6b1f9a4c3 - Fix rpz that copies the cname override completely to the temp
region, so there are no references to the rpz region.
2024-03-18 13:52:59 +01:00
W.C.A. Wijngaards 39cfc8c1c0 - Fix rpz, it follows iterator CNAMEs for nsip and nsdname and sets
the reply query_info values, that is better for debug logging.
2024-03-18 12:45:00 +01:00
W.C.A. Wijngaards 79e25e192c - Fix that rpz CNAME content is limited to the max number of cnames. 2024-03-18 11:25:29 +01:00
Yorgos Thessalonikefs 792089f523 Merge branch 'features/makedist-persist-windir' 2024-03-15 17:22:00 +01:00
Yorgos Thessalonikefs 34636caa2d - For windows build, persist the openssl and expat directories for
repeated builds while debugging.
2024-03-15 16:59:46 +01:00
W.C.A. Wijngaards 2993437eaa - Fix that addrinfo is not kept around but copied and freed, so that
log-destaddr uses a copy of the information, much like NSD does.
2024-03-15 13:39:49 +01:00
W.C.A. Wijngaards 0bcc8c0211 - The code repository continues with version 1.19.4. 2024-03-14 10:33:13 +01:00
W.C.A. Wijngaards 4b54d8e15e - Fix rpz for cname override action after nsdname and nsip triggers. 2024-03-13 17:14:14 +01:00
W.C.A. Wijngaards afe52595a9 - Fix to unify codepath for local alias for rpz cname action override. 2024-03-13 16:12:48 +01:00
W.C.A. Wijngaards 4f417262e3 - Fix rpz that the rpz override is taken in case of clientip triggers.
Fix that the clientip passthru action is logged. Fix that the
  clientip localdata action is logged. Fix rpz override action cname
  for the clientip trigger.
2024-03-13 16:04:58 +01:00
W.C.A. Wijngaards 1db3b38104 - Fix #1029: rpz trigger clientip and action rpz-passthru not working
as expected.
2024-03-13 13:45:04 +01:00
Yorgos Thessalonikefs bc47f50926 Changelog entry for #1028:
- Merge #1028: Clearer documentation for tcp-idle-timeout and
  edns-tcp-keepalive-timeout.
2024-03-12 14:52:57 +01:00
Yorgos ThessalonikefsandGitHub e36b5a099c Clearer documentation for tcp-idle-timeout and edns-tcp-keepalive-timeout (#1028)
* - Clearer documentation for tcp-idle-timeout and
  edns-tcp-keepalive-timeout.

* - Address review comment.
2024-03-12 14:52:00 +01:00
Yorgos Thessalonikefs 025881d0e9 - Introduce 'cache-min-negative-ttl' option to bound the minimum TTL for
negative answers overriding 'cache-min-ttl'.
2024-03-12 11:24:59 +01:00
W.C.A. Wijngaards 320d0a5f1b - Fix #1021 Inconsistent Behavior with Changing rpz-cname-override
and doing a unbound-control reload.
2024-03-11 16:31:58 +01:00
W.C.A. Wijngaards d382210fce Update doc/Changelog to note the fixes included in 1.19.3rc2. 2024-03-11 12:30:24 +01:00
W.C.A. Wijngaards 7b62767e16 - Fix unbound-control-setup.cmd to have CA v3 basicConstraints,
like unbound-control-setup.sh has.
2024-03-08 17:18:05 +01:00
W.C.A. Wijngaards 6568841bb0 - Fix doc test so it ignores but outputs unsupported doxygen options. 2024-03-08 16:43:24 +01:00
W.C.A. Wijngaards e361f6b284 - Fix qname minimisation for reply with a DNAME for qtype CNAME that
answers it.
2024-03-08 16:33:17 +01:00
Yorgos Thessalonikefs 53766917ef - Update doc/unbound.doxygen with 'doxygen -u'. Fixes option
deprecation warnings and updates with newer defaults.
2024-03-08 16:13:36 +01:00
W.C.A. Wijngaards 2a255076f5 - Fix validator classification of qtype DNAME for positive and
redirection answers, and fix validator signature routine for dealing
  with the synthesized CNAME for a DNAME without previously
  encountering it and also for when the qtype is DNAME.
2024-03-08 14:10:06 +01:00
W.C.A. Wijngaards fb080e7853 - Remove unused portion from iter_dname_ttl unit test. 2024-03-08 09:51:37 +01:00
W.C.A. Wijngaards 0818841038 - Fix TTL of synthesized CNAME when a DNAME is used from cache. 2024-03-08 09:47:59 +01:00
W.C.A. Wijngaards 939baebfe7 - Fix unbound-control-setup.cmd to use 3072 bits so that certificates
are long enough for newer OpenSSL versions.
2024-03-08 09:07:36 +01:00
W.C.A. Wijngaards 326ba26522 - Version set to 1.19.3 for release. After 1.19.2 point release with
security fix for CVE-2024-1931, Denial of service when trimming
  EDE text on positive replies. The code repo includes the fix and
  is for version 1.19.3.
2024-03-07 11:06:42 +01:00
W.C.A. Wijngaards ec0b510f1c - Fix for #1022: Fix ede prohibited in access control refused answers. 2024-03-05 13:39:29 +01:00
W.C.A. Wijngaards be626f7c53 - Fix edns subnet replies for scope zero answers to not get stored
in the global cache, and in cachedb, when the upstream replies
  without an EDNS record.
2024-03-04 13:20:13 +01:00
W.C.A. Wijngaards 3096e4930e - Move github workflows to use checkoutv4. 2024-02-28 11:44:52 +01:00
Yorgos Thessalonikefs 33bdf44a04 - Document the suspend argument for process_ds_response(). 2024-02-23 14:34:33 +01:00
W.C.A. Wijngaards ccbe31c21f - Fix trim of EDE text from large udp responses from spinning cpu. 2024-02-22 16:22:31 +01:00
Yorgos Thessalonikefs c6746499c1 Changelog entry for #1010:
- Merge #1010: Mention REFUSED has the TC bit set with unmatched
  allow_cookie acl in the manpage. It also fixes the code to match the
  documentation about clients with a valid cookie that bypass the
  ratelimit regardless of the allow_cookie acl.
2024-02-20 15:33:18 +01:00
Willem TooropandGitHub e1229e375f Mention REFUSED has the TC bit set with unmatched allow_cookie acl in the manpage (#1010)
* Mention REFUSED with TC with unmatched allow_cookie acl in manpage

Also moved the part about bypassing ip-ratelimit to the ip-ratelimit
description as it will be bypassed with a valid DNS-Cookie regardless of the
allow_cookie acl.

* Apply suggestions from code review

* Update doc/unbound.conf.5.in

* DNS-Cookies should bypass ip-ratelimit setting
2024-02-20 15:29:34 +01:00
W.C.A. Wijngaards be27499d39 - These fixes are part of the 1.19.1 release, that is a security
point release on 1.19.0, the code repository continues with these
  fixes, with version number 1.19.2.
2024-02-13 14:03:30 +01:00
W.C.A. Wijngaards 56a2b564ef Merge commit '92f2a1ca690a44880f4c4fa70a4b5a4b029aaf1c' 2024-02-13 13:58:09 +01:00
W.C.A. Wijngaards 9a00877af9 Merge commit '882903f2fa800c4cb6f5e225b728e2887bb7b9ae' 2024-02-13 13:57:56 +01:00
W.C.A. Wijngaards 54d86dd73b - Fix documentation for access-control in the unbound.conf man page. 2024-02-08 14:36:18 +01:00
Yorgos Thessalonikefs b496714caa - autoconf. 2024-02-07 10:51:16 +01:00
Yorgos Thessalonikefs 3f5175584b - For #1006: fix logic error introduced by previous fix. 2024-02-07 10:49:28 +01:00
Yorgos Thessalonikefs 11fff226f3 - autoheader, autoconf. 2024-02-07 10:42:39 +01:00
Yorgos Thessalonikefs 93490a0fc1 - Fix #1006: Can't find protobuf-c package since #999. 2024-02-07 10:38:52 +01:00
W.C.A. Wijngaards 0585c3e5fd Autoconf and changelog note for #999
- Merge #999: Search for protobuf-c with pkg-config.
2024-01-30 16:24:41 +01:00
Wouter WijngaardsandGitHub 0b74f2a007 Merge pull request #999 from NickCao/master
Search for protobuf-c with pkg-config
2024-01-30 16:23:43 +01:00
Nick Cao 59d98b9ef6 Search for protobuf-c with pkg-config 2024-01-26 17:52:24 -05:00
Yorgos Thessalonikefs 3522451600 - Update message TTL when using cached RRSETs. It could result in
non-expired messages with expired RRSETs (non-usable messages by
  Unbound).
2024-01-23 10:10:37 +01:00
Yorgos Thessalonikefs fe03bacd6c - Update error printout for duplicate trust anchors to include the
trust anchor name (relates to #920).
2024-01-22 15:54:36 +01:00
W.C.A. Wijngaards 1f46d5945b - Fix for #997: Print details for SSL certificate failure. 2024-01-22 09:40:36 +01:00
W.C.A. Wijngaards 585d73bf7c For analysis workflow, clean up the script to use OpenSSL Configure
without change.
2024-01-17 16:23:18 +01:00
W.C.A. Wijngaards 9e84cebfdb - workflow for analysis, cleanup of windows compile with msys2 perl. 2024-01-17 16:20:22 +01:00
W.C.A. Wijngaards d1a2bd67da - Fix warning for windres on resource files due to redefinition. 2024-01-17 16:19:56 +01:00
W.C.A. Wijngaards 7708429d35 For workflow, set perl interpreter for build. 2024-01-17 15:08:56 +01:00
W.C.A. Wijngaards 6045911d95 - Fix for workflow 2024-01-17 14:58:44 +01:00
W.C.A. Wijngaards 1b212aa073 For workflow, look for pacman. 2024-01-17 14:56:10 +01:00
W.C.A. Wijngaards 4d48166835 For workflow, use msys2 perl. 2024-01-17 14:53:23 +01:00
W.C.A. Wijngaards 437bac370a In workflow, use strawberry perl to run configure script. 2024-01-17 14:40:57 +01:00
W.C.A. Wijngaards 546062d3a3 For workflow, change path separator. 2024-01-17 14:36:35 +01:00
W.C.A. Wijngaards 576b93c99f For windows runner, look at perl contents. 2024-01-17 14:30:48 +01:00
W.C.A. Wijngaards 180275c4e0 Fix to install with cpanmin a missing perl module for the windows workflow. 2024-01-17 14:07:57 +01:00
W.C.A. Wijngaards 379e4b68f5 Fix for workflow to install perl module. 2024-01-17 14:03:30 +01:00
W.C.A. Wijngaards 74b4d81992 - Update workflow for ports to use newer openssl on windows compile. 2024-01-17 13:45:59 +01:00
W.C.A. Wijngaards fea8f0d5fd Changelog note for #993
- Merge #993: Update b.root-servers.net also in example config file.
2024-01-16 16:44:15 +01:00
Wouter WijngaardsandGitHub 0e5dab5eaf Merge pull request #993 from InfrastructureServices/b.root-servers.net-conf
Update b.root-servers.net also in example config file
2024-01-16 16:44:02 +01:00
W.C.A. Wijngaards c550bc154f - Fix to link with libssp for libcrypto and getaddrinfo check for
only header. Also update crosscompile to remove ssp for 32bit.
2024-01-16 16:40:14 +01:00
Petr Mensik 40fcb91206 Update b.root-servers.net also in example config file
Addition to commit a8739bad76, which
updated only address specified in code. But addresses provided in
example configuration were not updated, I think they should be updated
too.
2024-01-16 16:14:13 +01:00
W.C.A. Wijngaards c8554ff48c - Fix to link with -lcrypt32 for OpenSSL 3.2.0 on Windows. 2024-01-15 16:44:27 +01:00
W.C.A. Wijngaards 3d95cef08c Changelog note for #988.
- Merge #988: Fix NLnetLabs#981: dump_cache truncates large records.
2024-01-09 08:41:52 +01:00
Wouter WijngaardsandGitHub 9cd724cf5e Merge pull request #988 from dyunwei/master
Fix NLnetLabs#981: dump_cache truncates large records.
2024-01-09 08:41:30 +01:00
dyunwei eb7eb5ce68 Fix NLnetLabs#981: dump_cache truncates large records. 2024-01-09 14:17:31 +08:00
W.C.A. Wijngaards 418eeb642c - Fix unit test for #987 change in udp1xxx retry packet send. 2024-01-05 14:11:55 +01:00
W.C.A. Wijngaards 8ac56d004d Changelog note for #987
- Merge #987: skip edns frag retry if advertised udp payload size is
  not smaller.
2024-01-05 13:47:30 +01:00
Wouter WijngaardsandGitHub 52a76583c5 Merge pull request #987 from borisVanhoof/skip_edns_frag_retry
skip edns frag retry if advertised udp payload size is not smaller
2024-01-05 13:47:15 +01:00
sahnalys12 b1d02cc94f skip edns frag retry if advertised udp payload size is not smaller
If serviced query is in UDP_EDNS_FRAG mode, and EDNS_ADVERTISED_SIZE
is 1232 (the default) or more, then the retry will have the same edns
udp payload size with the same result.
2024-01-05 12:16:23 +01:00
W.C.A. Wijngaards b9b488b6d3 - Remove unneeded newlines and improve indentation in remote control
code.
2024-01-04 17:06:15 +01:00
W.C.A. Wijngaards 9a2d0238a8 - Fix #983: Sha1 runtime insecure change was incomplete. 2024-01-03 13:33:43 +01:00
W.C.A. Wijngaards 5cc21690eb Changelog note for #985.
- Merge #985: Add DoH and DoT to dnstap message.
2024-01-03 10:37:44 +01:00
Wouter WijngaardsandGitHub f80f65d58c Merge pull request #985 from k-akashi/dnstap_dot_doh
Add DoH and DoT to dnstap message
2024-01-03 10:36:38 +01:00
W.C.A. Wijngaards df284fbe65 Changelog note for #979 and #980.
- Merge #980: DoH: reject non-h2 early. To fix #979: Improve errors
  for non-HTTP/2 DoH clients.
2024-01-03 10:04:06 +01:00
Wouter WijngaardsandGitHub b632ebf129 Merge pull request #980 from jsha/reject-non-h2
DoH: reject non-h2 early
2024-01-03 09:59:15 +01:00
k-akashi 4b9cd8e81d Add DoH and DoT to dnstap message 2023-12-27 07:26:21 +09:00
Yorgos Thessalonikefs 6c82f4ae9b - Update example.conf with cookie options. 2023-12-22 11:42:20 +01:00
Jacob Hoffman-Andrews 87644fa46b DoH: reject non-h2 early
Previously, non-h2 connections would be accepted, and then error out
with a verbose message "http2: session_recv from ____ failed,
error: Received bad client magic byte string". Instead, we can detect
absence of h2 support at connection time and reject with a clearer
verbose message.
2023-12-13 16:58:44 -08:00
W.C.A. Wijngaards 22dc376392 Fixup doc/Changelog. 2023-12-08 17:17:23 +01:00
W.C.A. Wijngaards 4ef1fb5a24 - Fix root_zonemd unit test, it checks that the root ZONEMD verifies,
now that the root has a valid ZONEMD.
2023-12-08 17:15:35 +01:00
Yorgos Thessalonikefs be6fd80a1c - Merge PR #973: Use the origin (DNAME) TTL for synthesized CNAMEs as per RFC 6672. 2023-12-08 09:23:26 +01:00
W.C.A. Wijngaards c48a467b8e Changelog note for #975
- Merge #975: Fixed some syntax errors in rpl files.
2023-12-07 12:11:03 +01:00
Wouter WijngaardsandGitHub 557edbb84a Merge pull request #975 from NLnetLabs/testdata-syntax
Fixed some syntax errors in rpl files.
2023-12-07 12:10:40 +01:00
Philip Homburg 0cfc6e6d95 Fixed some syntax errors in rpl files. 2023-12-07 11:38:01 +01:00
W.C.A. Wijngaards 2978106991 - Fix #974: doc: default number of outgoing ports without libevent. 2023-12-07 09:41:03 +01:00
Yorgos Thessalonikefs 8517f49745 - Use the origin (DNAME) TTL for syntesized CNAMEs as per RFC 6672. 2023-12-06 23:40:01 +01:00
W.C.A. Wijngaards 6c76b4e2f8 - Fix tests to use new common.sh functions, wait_logfile and
kill_from_pidfile.
2023-12-06 16:32:06 +01:00
W.C.A. Wijngaards c91bd60051 - Update test script file common.sh. 2023-12-06 16:14:24 +01:00
W.C.A. Wijngaards a8739bad76 - Updated IPv4 and IPv6 address for b.root-servers.net in root hints. 2023-12-06 13:25:58 +01:00
W.C.A. Wijngaards 2b97442f2e - iana portlist update. 2023-12-06 13:22:35 +01:00
W.C.A. Wijngaards 5997355e22 - Fix to sync the tests script file common.sh. 2023-12-06 11:58:14 +01:00
W.C.A. Wijngaards d8bd9845cc - Fix dnstap that assertion failed on logging other than UDP and TCP
traffic. It lists it as TCP traffic.
2023-12-05 13:14:08 +01:00
W.C.A. Wijngaards 3d1bc143af - Fix #969: [FR] distinguish Do53, DoT and DoH in the logs. 2023-12-05 10:05:51 +01:00
W.C.A. Wijngaards 72a25f825c Changelog note for #971
- Merge #971: fix 'WARNING: Message has 41 extra bytes at end'.
2023-12-05 09:09:42 +01:00
Wouter WijngaardsandGitHub c4e0354876 Merge pull request #971 from dukeartem/master
fix 'WARNING: Message has 41 extra bytes at end'
2023-12-05 09:09:23 +01:00
ArtemandGitHub 389e820878 fix 'WARNING: Message has 41 extra bytes at end' 2023-12-05 09:43:15 +03:00
Yorgos Thessalonikefs a2f0186427 - Merge #968: Replace the obsolescent fgrep with grep -F in tests. 2023-11-27 16:47:13 +01:00
W.C.A. Wijngaards 58d670a258 - Fix #964: config.h.in~ backup file in release tar balls. 2023-11-27 16:04:33 +01:00
Yorgos Thessalonikefs ca88669435 - Replace the obsolescent fgrep with grep -F in tests. 2023-11-24 15:51:17 +01:00
Yorgos Thessalonikefs 15a9b0f2be - Use 127.0.0.1 explicitly in tests to avoid delays and errors on newer
systems.
2023-11-24 15:34:25 +01:00
W.C.A. Wijngaards 197bf15402 - Fix unit test parse of origin syntax. 2023-11-09 15:26:46 +01:00
W.C.A. Wijngaards 0bae242cbf - The repository continues with 1.19.1. 2023-11-08 10:59:25 +01:00
Christopher Zimmermann 1d23e0c920 Merge remote-tracking branch 'upstream/master' 2021-02-03 13:19:19 +01:00
Christopher Zimmermann ad51795314 Don't try to run daemon_privileged on reload. 2020-05-10 22:30:25 +02:00
Christopher Zimmermann 7d76e84953 Port ipset to BSD pf tables 2020-05-10 22:30:25 +02:00
Christopher Zimmermann c96e4ca121 allow privileged initialisation of modules 2020-05-10 22:30:25 +02:00
695 changed files with 88574 additions and 16942 deletions
+82 -40
View File
@@ -12,6 +12,7 @@ jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- name: GCC on Linux
@@ -32,12 +33,12 @@ jobs:
- name: OS X
os: macos-latest
install_expat: "yes"
config: "--enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl --with-libexpat=/usr/local/opt/expat"
config: "--enable-debug --disable-flto --with-ssl=/opt/homebrew/opt/openssl --with-libexpat=/opt/homebrew/opt/expat"
make_test: "yes"
- name: Clang on OS X
os: macos-latest
install_expat: "yes"
config: "CC=clang --enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl --with-libexpat=/usr/local/opt/expat --disable-static"
config: "CC=clang --enable-debug --disable-flto --with-ssl=/opt/homebrew/opt/openssl --with-libexpat=/opt/homebrew/opt/expat --disable-static"
make_test: "yes"
clang_analysis: "yes"
- name: ubsan (gcc undefined behaviour sanitizer)
@@ -48,15 +49,6 @@ jobs:
os: ubuntu-latest
config: 'CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=address" --disable-flto --disable-static'
make_test: "yes"
- name: Apple iPhone on iOS, armv7
os: macos-latest
AUTOTOOLS_HOST: armv7-apple-ios
OPENSSL_HOST: ios-cross
IOS_SDK: iPhoneOS
IOS_CPU: armv7s
test_ios: "yes"
config: "no"
make: "no"
- name: Apple iPhone on iOS, arm64
os: macos-latest
AUTOTOOLS_HOST: aarch64-apple-ios
@@ -84,15 +76,6 @@ jobs:
test_ios: "yes"
config: "no"
make: "no"
- name: iPhoneSimulator on OS X, i386
os: macos-latest
AUTOTOOLS_HOST: i386-apple-ios
OPENSSL_HOST: iphoneos-cross
IOS_SDK: iPhoneSimulator
IOS_CPU: i386
test_ios: "yes"
config: "no"
make: "no"
- name: iPhoneSimulator on OS X, x86_64
os: macos-latest
AUTOTOOLS_HOST: x86_64-apple-ios
@@ -161,13 +144,44 @@ jobs:
test_windows: "yes"
config: "no"
make: "no"
- name: FreeBSD
os: ubuntu-latest
config: "no"
make: "no"
with_cross_platform_action: "yes"
cross_platform_os: "freebsd"
cross_platform_arch: "x86-64"
cross_platform_version: "14.1"
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
- name: OpenBSD
os: ubuntu-latest
config: "no"
make: "no"
with_cross_platform_action: "yes"
cross_platform_os: "openbsd"
cross_platform_arch: "x86-64"
cross_platform_version: "7.5"
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
- name: NetBSD
os: ubuntu-latest
config: "no"
make: "no"
with_cross_platform_action: "yes"
cross_platform_os: "netbsd"
cross_platform_arch: "x86-64"
cross_platform_version: "10.0"
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
with:
submodules: false
persist-credentials: false
- name: test_windows
if: ${{ matrix.test_windows == 'yes' }}
env:
LIBEXPAT_FNAME: expat-2.7.0
LIBEXPAT_VERSION_DIR: R_2_7_0
shell: bash
run: |
export unboundpath=`pwd`
@@ -175,31 +189,32 @@ jobs:
cd ..
export prepath=`pwd`
echo prepath=${prepath}
# parralel build option
export MINJ="-j4"
echo "choco install winflexbison3"
choco install winflexbison3
echo 'LEX="win_flex"'
export LEX="win_flex"
echo 'YACC="win_bison -y"'
export YACC="win_bison -y"
#echo "curl cpanm"
#curl -L -k -s -S -o cpanm https://cpanmin.us/
#echo "perl cpanm Pod::Usage"
#perl cpanm Pod::Usage
mkdir openssl
echo "curl openssl"
curl -L -k -s -S -o openssl-1.1.1j.tar.gz https://www.openssl.org/source/openssl-1.1.1j.tar.gz
tar xzf openssl-1.1.1j.tar.gz
cd openssl-1.1.1j
curl -L -k -s -S -o openssl-3.2.0.tar.gz https://www.openssl.org/source/openssl-3.2.0.tar.gz
tar xzf openssl-3.2.0.tar.gz
cd openssl-3.2.0
# remove pod::Usage because we do not need -help or -man output
# from the Configure script
echo "Fixup ./Configure by removing use Pod::Usage require"
sed -e 's/use Pod::Usage//' < Configure > Configure.fix
echo "./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix=\""$prepath/openssl\"""
./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl"
# from the Configure script, this fixes it for openssl 1.1.1
#echo "Fixup ./Configure by removing use Pod::Usage require"
#sed -e 's/use Pod::Usage//' < Configure > Configure.fix
# ./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl"
# pacman is used to install for msys2, with
# C:/msys64/usr/bin/pacman -S perl
echo "C:/msys64/usr/bin/perl ./Configure no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix=\""$prepath/openssl"\" PERL=\"C:/msys64/usr/bin/perl\""
C:/msys64/usr/bin/perl ./Configure no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl" PERL="C:/msys64/usr/bin/perl"
# make the libs only, build faster
echo "make build_libs"
#make
make build_libs
#make $MINJ
make $MINJ build_libs
mv Makefile Makefile.orig
# fixup \\ in the installtop to /.
echo "fixup INSTALLTOP"
@@ -211,9 +226,9 @@ jobs:
cd ..
mkdir expat
echo "curl expat"
curl -L -k -s -S -o expat-2.2.10.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_10/expat-2.2.10.tar.gz
tar xzf expat-2.2.10.tar.gz
cd expat-2.2.10
curl -L -k -s -S -o $LIBEXPAT_FNAME.tar.gz https://github.com/libexpat/libexpat/releases/download/$LIBEXPAT_VERSION_DIR/$LIBEXPAT_FNAME.tar.gz
tar xzf $LIBEXPAT_FNAME.tar.gz
cd $LIBEXPAT_FNAME
echo "./configure SHELL=/usr/bin/bash CONFIG_SHELL=/usr/bin/bash --prefix=\"$prepath/expat\" --exec-prefix=\"$prepath/expat\" --bindir=\"$prepath/expat/bin\" --includedir=\"$prepath/expat/include\" --mandir=\"$prepath/expat/man\" --libdir=\"$prepath/expat/lib\""
./configure SHELL=/usr/bin/bash CONFIG_SHELL=/usr/bin/bash --prefix="$prepath/expat" --exec-prefix="$prepath/expat" --bindir="$prepath/expat/bin" --includedir="$prepath/expat/include" --mandir="$prepath/expat/man" --libdir="$prepath/expat/lib"
# fixup SHELL is treated specially, but SHELZZ is not by make.
@@ -231,7 +246,7 @@ jobs:
mv xmlwf/Makefile xmlwf/Makefile.orig
sed -e 's/SHELL/SHELLZZ/g' < xmlwf/Makefile.orig > xmlwf/Makefile
echo "make"
make
make $MINJ
echo "make install"
make install
cd ..
@@ -239,7 +254,7 @@ jobs:
cd unbound
echo "./configure --enable-debug --enable-static-exe --disable-flto \"--with-ssl=$prepath/openssl\" --with-libexpat=\"$prepath/expat\" --disable-shared"
./configure --enable-debug --enable-static-exe --disable-flto "--with-ssl=$prepath/openssl" --with-libexpat="$prepath/expat" --disable-shared
make
make $MINJ
# specific test output
#make testbound.exe; ./testbound.exe -s
#make testbound; ./testbound.exe -p testdata/acl.rpl -o -vvvv
@@ -332,6 +347,33 @@ jobs:
echo "::group::make install"
make install
echo "::endgroup::"
- name: cross-platform-action on ${{ matrix.cross_platform_os }} ${{ matrix.cross_platform_version }}
if: ${{ matrix.with_cross_platform_action == 'yes' }}
uses: cross-platform-actions/action@v1.0.0
env:
CROSS_PLATFORM_OS: ${{ matrix.cross_platform_os }}
with:
environment_variables: CROSS_PLATFORM_OS
operating_system: ${{ matrix.cross_platform_os }}
architecture: ${{ matrix.cross_platform_arch }}
version: ${{ matrix.cross_platform_version }}
shell: bash
memory: 4G
cpu_count: 2
run: |
set -e -x
if test "$CROSS_PLATFORM_OS" = "freebsd"; then sudo pkg install -y openssl libevent expat; fi
if test "$CROSS_PLATFORM_OS" = "openbsd"; then sudo pkg_add libevent; fi
if test "$CROSS_PLATFORM_OS" = "netbsd"; then sudo pkgin -y install libevent; fi
echo "::group::configure"
./configure ${{ matrix.cross_platform_config }}
echo "::endgroup::"
echo "::group::make"
make
echo "::endgroup::"
echo "::group::make test"
make test
echo "::endgroup::"
- name: install libevent
if: ${{ matrix.install_libevent == 'yes' }}
run: sudo apt-get install libevent-dev
+3 -1
View File
@@ -12,7 +12,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: configure
run: ./configure --enable-debug
- name: make
+5
View File
@@ -10,6 +10,9 @@
/config.status
/dnstap/dnstap_config.h
/dnscrypt/dnscrypt_config.h
/util/configlexer.c
/util/configparser.c
/util/configparser.h
/clubsyms.def
/doc/example.conf
/doc/libunbound.3
@@ -33,6 +36,7 @@
/asynclook
/delayer
/dohclient
/doqclient
/lock-verify
/memstats
/perf
@@ -55,6 +59,7 @@
/pythonmod/unboundmodule.py
/testdata/result.*
/testdata/.done-*
/testdata/.skip-*
/testdata/.perfstats.txt
/doc/html
/doc/xml
+839 -566
View File
File diff suppressed because it is too large Load Diff
+12 -9
View File
@@ -4,7 +4,7 @@
[![Packaging status](https://repology.org/badge/tiny-repos/unbound.svg)](https://repology.org/project/unbound/versions)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/unbound.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:unbound)
[![Documentation Status](https://readthedocs.org/projects/unbound/badge/?version=latest)](https://unbound.readthedocs.io/en/latest/?badge=latest)
[![Mastodon Follow](https://img.shields.io/mastodon/follow/109262826617293067?domain=https%3A%2F%2Ffosstodon.org&style=social)](https://fosstodon.org/@nlnetlabs)
[![Mastodon Follow](https://img.shields.io/mastodon/follow/114692612288811644?domain=social.nlnetlabs.nl&style=social)](https://social.nlnetlabs.nl/@nlnetlabs)
Unbound is a validating, recursive, caching DNS resolver. It is designed to be
fast and lean and incorporates modern features based on open standards. If you
@@ -25,18 +25,21 @@ Unbound can be compiled and installed using:
./configure && make && make install
```
You can use libevent if you want. libevent is useful when using many (10000)
outgoing ports. By default max 256 ports are opened at the same time and the
builtin alternative is equally capable and a little faster.
You can use libevent if you want. libevent is useful when using many (e.g.,
10000) outgoing ports.
Use the `--with-libevent` configure option to compile Unbound with libevent
support.
If not, the default builtin alternative opens max 256 ports at the same time
and is equally capable and a little faster.
## Unbound configuration
All of Unbound's configuration options are described in the man pages, which
will be installed and are available on the Unbound
[documentation page](https://unbound.docs.nlnetlabs.nl/).
All of Unbound's configuration options are described in the `unbound.conf(5)`
man page, which will be installed and is also available on the Unbound
[documentation page](https://unbound.docs.nlnetlabs.nl/en/latest/manpages/unbound.conf.html)
for the latest version.
An example configuration file is located in
An example configuration file, with minimal documentation, is located in
[doc/example.conf](https://github.com/NLnetLabs/unbound/blob/master/doc/example.conf.in).
+152 -44
View File
@@ -2,7 +2,15 @@
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
# BSD licensed.
#
# Version 46
# Version 51
# 2025-11-06 Fix ACX_CHECK_NONSTRING_ATTRIBUTE to reject clang, that prints
# a warning for 'unknown attribute' when nonstring is used.
# 2025-09-29 add ac_cv_func_malloc_0_nonnull as a cache value for the malloc(0)
# check by ACX_FUNC_MALLOC.
# 2025-09-29 add ACX_CHECK_NONSTRING_ATTRIBUTE, AHX_CONFIG_NONSTRING_ATTRIBUTE.
# 2024-01-16 fix to add -l:libssp.a to -lcrypto link check.
# and check for getaddrinfo with only header.
# 2024-01-15 fix to add crypt32 to -lcrypto link check when checking for gdi32.
# 2023-05-04 fix to remove unused whitespace.
# 2023-01-26 fix -Wstrict-prototypes.
# 2022-09-01 fix checking if nonblocking sockets work on OpenBSD.
@@ -68,6 +76,7 @@
# ACX_DEPFLAG - find cc dependency flags.
# ACX_DETERMINE_EXT_FLAGS_UNBOUND - find out which flags enable BSD and POSIX.
# ACX_CHECK_FORMAT_ATTRIBUTE - find cc printf format syntax.
# ACX_CHECK_NONSTRING_ATTRIBUTE - find cc nonstring attribute syntax.
# ACX_CHECK_UNUSED_ATTRIBUTE - find cc variable unused syntax.
# ACX_CHECK_FLTO - see if cc supports -flto and use it if so.
# ACX_LIBTOOL_C_ONLY - create libtool for C only, improved.
@@ -89,6 +98,7 @@
# ACX_FUNC_IOCTLSOCKET - find ioctlsocket, portably.
# ACX_FUNC_MALLOC - check malloc, define replacement .
# AHX_CONFIG_FORMAT_ATTRIBUTE - config.h text for format.
# AHX_CONFIG_NONSTRING_ATTRIBUTE - config.h text for nonstring.
# AHX_CONFIG_UNUSED_ATTRIBUTE - config.h text for unused.
# AHX_CONFIG_FSEEKO - define fseeko, ftello fallback.
# AHX_CONFIG_RAND_MAX - define RAND_MAX if needed.
@@ -487,7 +497,7 @@ AC_DEFUN([AHX_CONFIG_FORMAT_ATTRIBUTE],
])
dnl Check how to mark function arguments as unused.
dnl result in HAVE_ATTR_UNUSED.
dnl result in HAVE_ATTR_UNUSED.
dnl Make sure you include AHX_CONFIG_UNUSED_ATTRIBUTE also.
AC_DEFUN([ACX_CHECK_UNUSED_ATTRIBUTE],
[AC_REQUIRE([AC_PROG_CC])
@@ -522,6 +532,49 @@ if test $ac_cv_c_unused_attribute = yes; then
fi
])dnl
dnl Check how to mark function arguments as nonstring.
dnl result in HAVE_ATTR_NONSTRING.
dnl Make sure you include AHX_CONFIG_NONSTRING_ATTRIBUTE also.
AC_DEFUN([ACX_CHECK_NONSTRING_ATTRIBUTE],
[AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([ACX_CHECK_ERROR_FLAGS])
BAKCFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $ERRFLAG"
AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "nonstring" attribute)
AC_CACHE_VAL(ac_cv_c_nonstring_attribute,
[ac_cv_c_nonstring_attribute=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>
struct test {
char __attribute__((nonstring)) s[1];
};
]], [[
struct test t = { "1" };
(void) t;
]])],[ac_cv_c_nonstring_attribute="yes"],[ac_cv_c_nonstring_attribute="no"])
CFLAGS="$BAKCFLAGS"
])
dnl Setup ATTR_NONSTRING config.h parts.
dnl make sure you call ACX_CHECK_NONSTRING_ATTRIBUTE also.
AC_DEFUN([AHX_CONFIG_NONSTRING_ATTRIBUTE],
[
#if defined(DOXYGEN)
# define ATTR_NONSTRING(x) x
#elif defined(__cplusplus)
# define ATTR_NONSTRING(x) __attribute__((nonstring)) x
#elif defined(HAVE_ATTR_NONSTRING)
# define ATTR_NONSTRING(x) __attribute__((nonstring)) x
#else /* !HAVE_ATTR_NONSTRING */
# define ATTR_NONSTRING(x) x
#endif /* !HAVE_ATTR_NONSTRING */
])
AC_MSG_RESULT($ac_cv_c_nonstring_attribute)
if test $ac_cv_c_nonstring_attribute = yes; then
AC_DEFINE(HAVE_ATTR_NONSTRING, 1, [Whether the C compiler accepts the "nonstring" attribute])
fi
])dnl
dnl Pre-fun for ACX_LIBTOOL_C_ONLY
AC_DEFUN([ACX_LIBTOOL_C_PRE], [
# skip these tests, we do not need them.
@@ -707,7 +760,7 @@ AC_DEFUN([ACX_SSL_CHECKS], [
LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir_lib"
ACX_RUNTIME_PATH_ADD([$ssldir_lib])
fi
AC_MSG_CHECKING([for EVP_sha256 in -lcrypto])
LIBS="$LIBS -lcrypto"
LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
@@ -732,40 +785,73 @@ AC_DEFUN([ACX_SSL_CHECKS], [
]])],[
AC_DEFINE([HAVE_EVP_SHA256], 1,
[If you have EVP_sha256])
AC_MSG_RESULT(yes)
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
LIBS="$BAKLIBS"
LIBSSL_LIBS="$BAKSSLLIBS"
LIBS="$LIBS -ldl"
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
AC_MSG_CHECKING([if -lcrypto needs -ldl])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
int EVP_sha256(void);
(void)EVP_sha256();
]])],[
AC_DEFINE([HAVE_EVP_SHA256], 1,
[If you have EVP_sha256])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
LIBS="$BAKLIBS"
LIBSSL_LIBS="$BAKSSLLIBS"
LIBS="$LIBS -ldl -pthread"
LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
int EVP_sha256(void);
(void)EVP_sha256();
]])],[
AC_DEFINE([HAVE_EVP_SHA256], 1,
[If you have EVP_sha256])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32"
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32 -lcrypt32"
AC_MSG_CHECKING([if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
int EVP_sha256(void);
(void)EVP_sha256();
]])],[
AC_DEFINE([HAVE_EVP_SHA256], 1,
[If you have EVP_sha256])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
LIBS="$BAKLIBS"
LIBSSL_LIBS="$BAKSSLLIBS"
LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a"
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a"
AC_MSG_CHECKING([if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
int EVP_sha256(void);
(void)EVP_sha256();
]])],[
AC_DEFINE([HAVE_EVP_SHA256], 1,
[If you have EVP_sha256])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
LIBS="$BAKLIBS"
LIBSSL_LIBS="$BAKSSLLIBS"
LIBS="$LIBS -ldl"
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
AC_MSG_CHECKING([if -lcrypto needs -ldl])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
int EVP_sha256(void);
(void)EVP_sha256();
]])],[
AC_DEFINE([HAVE_EVP_SHA256], 1,
[If you have EVP_sha256])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
LIBS="$BAKLIBS"
LIBSSL_LIBS="$BAKSSLLIBS"
LIBS="$LIBS -ldl -pthread"
LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
int EVP_sha256(void);
(void)EVP_sha256();
]])],[
AC_DEFINE([HAVE_EVP_SHA256], 1,
[If you have EVP_sha256])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
])
])
])
])
])
])
])
fi
@@ -779,7 +865,7 @@ AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT])
dnl Check for SSL, where SSL is mandatory
dnl Adds --with-ssl option, searches for openssl and defines HAVE_SSL if found
dnl Setup of CPPFLAGS, CFLAGS. Adds -lcrypto to LIBS.
dnl Setup of CPPFLAGS, CFLAGS. Adds -lcrypto to LIBS.
dnl Checks main header files of SSL.
dnl
AC_DEFUN([ACX_WITH_SSL],
@@ -872,7 +958,7 @@ dnl see if on windows
if test "$ac_cv_header_windows_h" = "yes"; then
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
USE_WINSOCK="1"
if echo $LIBS | grep 'lws2_32' >/dev/null; then
if echo "$LIBS" | grep 'lws2_32' >/dev/null; then
:
else
LIBS="$LIBS -lws2_32"
@@ -880,6 +966,24 @@ if test "$ac_cv_header_windows_h" = "yes"; then
fi
],
dnl no quick getaddrinfo, try mingw32 and winsock2 library.
dnl perhaps getaddrinfo needs only the include
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[
#ifdef HAVE_WS2TCPIP_H
#include <ws2tcpip.h>
#endif
],
[
(void)getaddrinfo(NULL, NULL, NULL, NULL);
]
)],
[
ac_cv_func_getaddrinfo="yes"
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
USE_WINSOCK="1"
],
ORIGLIBS="$LIBS"
LIBS="$LIBS -lws2_32"
AC_LINK_IFELSE(
@@ -904,6 +1008,7 @@ ac_cv_func_getaddrinfo="no"
LIBS="$ORIGLIBS"
])
)
)
AC_MSG_RESULT($ac_cv_func_getaddrinfo)
if test $ac_cv_func_getaddrinfo = yes; then
@@ -1135,8 +1240,9 @@ dnl detect malloc and provide malloc compat prototype.
dnl $1: unique name for compat code
AC_DEFUN([ACX_FUNC_MALLOC],
[
AC_MSG_CHECKING([for GNU libc compatible malloc])
AC_RUN_IFELSE([AC_LANG_PROGRAM(
AC_CACHE_CHECK([for GNU libc compatible malloc],[ac_cv_func_malloc_0_nonnull],
[
AC_RUN_IFELSE([AC_LANG_PROGRAM(
[[#if defined STDC_HEADERS || defined HAVE_STDLIB_H
#include <stdlib.h>
#else
@@ -1144,14 +1250,16 @@ char *malloc ();
#endif
]], [ if(malloc(0) != 0) return 1;])
],
[AC_MSG_RESULT([no])
AC_LIBOBJ(malloc)
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] ,
[AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_MALLOC], 1, [If have GNU libc compatible malloc])],
[AC_MSG_RESULT([no (crosscompile)])
AC_LIBOBJ(malloc)
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] )
[ac_cv_func_malloc_0_nonnull=no],
[ac_cv_func_malloc_0_nonnull=yes],
[ac_cv_func_malloc_0_nonnull="no (crosscompile)"])
])
AS_IF([test "$ac_cv_func_malloc_0_nonnull" = yes],
[AC_DEFINE([HAVE_MALLOC], 1, [If have GNU libc compatible malloc])],
[
AC_LIBOBJ(malloc)
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])
])
])
dnl Define fallback for fseeko and ftello if needed.
+1 -1
View File
@@ -9,7 +9,7 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]])
if test -z "$PYTHON"; then
AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path])
AC_MSG_ERROR([Cannot find 'python$PYTHON_VERSION' in your system path. You can use the environment variable 'PYTHON_VERSION=version_number' for an explicit version.])
PYTHON_VERSION=""
fi
+70
View File
@@ -0,0 +1,70 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_build_date_epoch.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BUILD_DATE_EPOCH(VARIABLE[, FORMAT[, ACTION-IF-FAIL]])
#
# DESCRIPTION
#
# Sets VARIABLE to a string representing the current time. It is
# formatted according to FORMAT if specified, otherwise it is formatted as
# the number of seconds (excluding leap seconds) since the UNIX epoch (01
# Jan 1970 00:00:00 UTC).
#
# If the SOURCE_DATE_EPOCH environment variable is set, it uses the value
# of that variable instead of the current time. See
# https://reproducible-builds.org/specs/source-date-epoch). If
# SOURCE_DATE_EPOCH is set but cannot be properly interpreted as a UNIX
# timestamp, then execute ACTION-IF-FAIL if specified, otherwise error.
#
# VARIABLE is AC_SUBST-ed.
#
# LICENSE
#
# Copyright (c) 2016 Eric Bavier <bavier@member.fsf.org>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <https://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 2
AC_DEFUN([AX_BUILD_DATE_EPOCH],
[dnl
AC_MSG_CHECKING([for build time])
ax_date_fmt="m4_default($2,%s)"
AS_IF([test x"$SOURCE_DATE_EPOCH" = x],
[$1=`date "+$ax_date_fmt"`],
[ax_build_date=`date -u -d "@$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null \
|| date -u -r "$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null`
AS_IF([test x"$ax_build_date" = x],
[m4_ifval([$3],
[$3],
[AC_MSG_ERROR([malformed SOURCE_DATE_EPOCH])])],
[$1=$ax_build_date])])
AC_MSG_RESULT([$$1])
])dnl AX_BUILD_DATE_EPOCH
+58 -52
View File
@@ -1,39 +1,43 @@
# ===========================================================================
# http://autoconf-archive.cryp.to/ac_pkg_swig.html
# https://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html
# ===========================================================================
#
# SYNOPSIS
#
# AC_PROG_SWIG([major.minor.micro])
# AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found])
#
# DESCRIPTION
#
# This macro searches for a SWIG installation on your system. If found you
# should call SWIG via $(SWIG). You can use the optional first argument to
# check if the version of the available SWIG is greater than or equal to
# the value of the argument. It should have the format: N[.N[.N]] (N is a
# number between 0 and 999. Only the first N is mandatory.)
# This macro searches for a SWIG installation on your system. If found,
# then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is
# found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd.
#
# If the version argument is given (e.g. 1.3.17), AC_PROG_SWIG checks that
# the swig package is this version number or higher.
# You can use the optional first argument to check if the version of the
# available SWIG is greater than or equal to the value of the argument. It
# should have the format: N[.N[.N]] (N is a number between 0 and 999. Only
# the first N is mandatory.) If the version argument is given (e.g.
# 1.3.17), AX_PKG_SWIG checks that the swig package is this version number
# or higher.
#
# As usual, action-if-found is executed if SWIG is found, otherwise
# action-if-not-found is executed.
#
# In configure.in, use as:
#
# AC_PROG_SWIG(1.3.17)
# SWIG_ENABLE_CXX
# SWIG_MULTI_MODULE_SUPPORT
# SWIG_PYTHON
# AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ])
# AX_SWIG_ENABLE_CXX
# AX_SWIG_MULTI_MODULE_SUPPORT
# AX_SWIG_PYTHON
#
# LAST MODIFICATION
#
# 2008-04-12
#
# COPYLEFT
# LICENSE
#
# Copyright (c) 2008 Sebastian Huber <sebastian-huber@web.de>
# Copyright (c) 2008 Alan W. Irwin <irwin@beluga.phys.uvic.ca>
# Copyright (c) 2008 Alan W. Irwin
# Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>
# Copyright (c) 2008 Andrew Collier <colliera@ukzn.ac.za>
# Copyright (c) 2008 Andrew Collier
# Copyright (c) 2011 Murray Cumming <murrayc@openismus.com>
# Copyright (c) 2018 Reini Urban <rurban@cpan.org>
# Copyright (c) 2021 Vincent Danjean <Vincent.Danjean@ens-lyon.org>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
@@ -46,7 +50,7 @@
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
# with this program. If not, see <https://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
@@ -57,17 +61,21 @@
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Macro Archive. When you make and
# distribute a modified version of the Autoconf Macro, you may extend this
# special exception to the GPL to apply to your modified version as well.
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
AC_DEFUN([AC_PROG_SWIG],[
AC_PATH_PROG([SWIG],[swig])
#serial 15
AC_DEFUN([AX_PKG_SWIG],[
# Find path to the "swig" executable.
AC_PATH_PROGS([SWIG],[swig swig3.0 swig2.0])
if test -z "$SWIG" ; then
AC_MSG_WARN([cannot find 'swig' program. You should look at http://www.swig.org])
SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false'
elif test -n "$1" ; then
AC_MSG_CHECKING([for SWIG version])
m4_ifval([$3],[$3],[:])
elif test -z "$1" ; then
m4_ifval([$2],[$2],[:])
else
AC_MSG_CHECKING([SWIG version])
[swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
AC_MSG_RESULT([$swig_version])
if test -n "$swig_version" ; then
@@ -77,12 +85,12 @@ AC_DEFUN([AC_PROG_SWIG],[
if test -z "$required_major" ; then
[required_major=0]
fi
[required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
[required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
[required_minor=`echo $required | sed 's/[^0-9].*//'`]
if test -z "$required_minor" ; then
[required_minor=0]
fi
[required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
[required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
[required_patch=`echo $required | sed 's/[^0-9].*//'`]
if test -z "$required_patch" ; then
[required_patch=0]
@@ -103,30 +111,28 @@ AC_DEFUN([AC_PROG_SWIG],[
if test -z "$available_patch" ; then
[available_patch=0]
fi
[badversion=0]
if test $available_major -lt $required_major ; then
[badversion=1]
fi
if test $available_major -eq $required_major \
-a $available_minor -lt $required_minor ; then
[badversion=1]
fi
if test $available_major -eq $required_major \
-a $available_minor -eq $required_minor \
-a $available_patch -lt $required_patch ; then
[badversion=1]
fi
if test $badversion -eq 1 ; then
AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version. You should look at http://www.swig.org])
SWIG='echo "Error: SWIG version >= $1 is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false'
# Convert the version tuple into a single number for easier comparison.
# Using base 100 should be safe since SWIG internally uses BCD values
# to encode its version number.
required_swig_vernum=`expr $required_major \* 10000 \
\+ $required_minor \* 100 \+ $required_patch`
available_swig_vernum=`expr $available_major \* 10000 \
\+ $available_minor \* 100 \+ $available_patch`
if test $available_swig_vernum -lt $required_swig_vernum; then
AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version.])
SWIG=''
m4_ifval([$3],[$3],[])
else
AC_MSG_NOTICE([SWIG executable is '$SWIG'])
SWIG_LIB=`$SWIG -swiglib`
AC_MSG_NOTICE([SWIG library directory is '$SWIG_LIB'])
AC_MSG_CHECKING([for SWIG library])
SWIG_LIB=`$SWIG -swiglib | tr '\r\n' ' '`
AC_MSG_RESULT([$SWIG_LIB])
m4_ifval([$2],[$2],[])
fi
else
AC_MSG_WARN([cannot determine SWIG version])
SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false'
SWIG=''
m4_ifval([$3],[$3],[])
fi
fi
AC_SUBST([SWIG_LIB])
+317 -127
View File
@@ -1,5 +1,5 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
# ===========================================================================
#
# SYNOPSIS
@@ -14,24 +14,28 @@
# flags that are needed. (The user can also force certain compiler
# flags/libs to be tested by setting these environment variables.)
#
# Also sets PTHREAD_CC to any special C compiler that is needed for
# multi-threaded programs (defaults to the value of CC otherwise). (This
# is necessary on AIX to use the special cc_r compiler alias.)
# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
# needed for multi-threaded programs (defaults to the value of CC
# respectively CXX otherwise). (This is necessary on e.g. AIX to use the
# special cc_r/CC_r compiler alias.)
#
# NOTE: You are assumed to not only compile your program with these flags,
# but also link it with them as well. e.g. you should link with
# but also to link with them as well. For example, you might link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
# If you are only building threads programs, you may wish to use these
# If you are only building threaded programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC:
#
# LIBS="$PTHREAD_LIBS $LIBS"
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
# CC="$PTHREAD_CC"
# CXX="$PTHREAD_CXX"
#
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
#
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
@@ -55,6 +59,7 @@
#
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
# Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
@@ -67,7 +72,7 @@
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
# with this program. If not, see <https://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
@@ -82,35 +87,41 @@
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 21
#serial 31
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_PROG_SED])
AC_LANG_PUSH([C])
ax_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# requires special compiler flags (e.g. on Tru64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
save_CFLAGS="$CFLAGS"
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
ax_pthread_save_CC="$CC"
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
AC_MSG_RESULT([$ax_pthread_ok])
if test x"$ax_pthread_ok" = xno; then
if test "x$ax_pthread_ok" = "xno"; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
CC="$ax_pthread_save_CC"
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
fi
# We must check for the threads library under a number of different
@@ -118,12 +129,14 @@ fi
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all, and "pthread-config"
# which is a program returning the flags for the Pth emulation library.
# Create a list of thread flags to try. Items with a "," contain both
# C compiler flags (before ",") and linker flags (after ","). Other items
# starting with a "-" are C compiler flags, and remaining items are
# library names, except for "none" which indicates that we try without
# any flags at all, and "pthread-config" which is a program returning
# the flags for the Pth emulation library.
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
@@ -132,82 +145,163 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
# (Note: HP C rejects this with "bad form for `-t' option")
# -pthreads: Solaris/gcc (Note: HP C also rejects)
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads too;
# also defines -D_REENTRANT)
# ... -mt is also the pthreads flag for HP/aCC
# doesn't hurt to check since this sometimes defines pthreads and
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
# is present but should not be used directly; and before -mthreads,
# because the compiler interprets this as "-mt" + "-hreads")
# -mthreads: Mingw32/gcc, Lynx/gcc
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case ${host_os} in
case $host_os in
freebsd*)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
;;
hpux*)
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
# multi-threading and also sets -lpthread."
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
;;
openedition*)
# IBM z/OS requires a feature-test macro to be defined in order to
# enable POSIX threads at all, so give the user a hint if this is
# not set. (We don't define these ourselves, as they can affect
# other portions of the system API in unpredictable ways.)
AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
[
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
AX_PTHREAD_ZOS_MISSING
# endif
],
[AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
;;
solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
# tests will erroneously succeed. (N.B.: The stubs are missing
# pthread_cleanup_push, or rather a function called by this macro,
# so we could check for that, but who knows whether they'll stub
# that too in a future libc.) So we'll check first for the
# standard Solaris way of linking pthreads (-mt -lpthread).
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
;;
darwin*)
ax_pthread_flags="-pthread $ax_pthread_flags"
ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
;;
esac
# Clang doesn't consider unrecognized options an error unless we specify
# -Werror. We throw in some extra Clang-specific options to ensure that
# this doesn't happen for GCC, which also accepts -Werror.
# Are we compiling with Clang?
AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
save_CFLAGS="$CFLAGS"
ax_pthread_extra_flags="-Werror"
CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
[AC_MSG_RESULT([yes])],
[ax_pthread_extra_flags=
AC_MSG_RESULT([no])])
CFLAGS="$save_CFLAGS"
AC_CACHE_CHECK([whether $CC is Clang],
[ax_cv_PTHREAD_CLANG],
[ax_cv_PTHREAD_CLANG=no
# Note that Autoconf sets GCC=yes for Clang as well as GCC
if test "x$GCC" = "xyes"; then
AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
[/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
# if defined(__clang__) && defined(__llvm__)
AX_PTHREAD_CC_IS_CLANG
# endif
],
[ax_cv_PTHREAD_CLANG=yes])
fi
])
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
if test x"$ax_pthread_ok" = xno; then
for flag in $ax_pthread_flags; do
case $flag in
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
# Note that for GCC and Clang -pthread generally implies -lpthread,
# except when -nostdlib is passed.
# This is problematic using libtool to build C++ shared libraries with pthread:
# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
# To solve this, first try -pthread together with -lpthread for GCC
AS_IF([test "x$GCC" = "xyes"],
[ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
AS_IF([test "x$ax_pthread_clang" = "xyes"],
[ax_pthread_flags="-pthread,-lpthread -pthread"])
# The presence of a feature test macro requesting re-entrant function
# definitions is, on some systems, a strong hint that pthreads support is
# correctly enabled
case $host_os in
darwin* | hpux* | linux* | osf* | solaris*)
ax_pthread_check_macro="_REENTRANT"
;;
aix*)
ax_pthread_check_macro="_THREAD_SAFE"
;;
*)
ax_pthread_check_macro="--"
;;
esac
AS_IF([test "x$ax_pthread_check_macro" = "x--"],
[ax_pthread_check_cond=0],
[ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
if test "x$ax_pthread_ok" = "xno"; then
for ax_pthread_try_flag in $ax_pthread_flags; do
case $ax_pthread_try_flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
*,*)
PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $flag])
PTHREAD_CFLAGS="$flag"
AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
PTHREAD_CFLAGS="$ax_pthread_try_flag"
;;
pthread-config)
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
if test x"$ax_pthread_config" = xno; then continue; fi
AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
PTHREAD_CFLAGS="`pthread-config --cflags`"
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$flag])
PTHREAD_LIBS="-l$flag"
AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
PTHREAD_LIBS="-l$ax_pthread_try_flag"
;;
esac
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
@@ -218,8 +312,18 @@ for flag in $ax_pthread_flags; do
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
static void routine(void *a) { *((int*)a) = 0; }
# if $ax_pthread_check_cond
# error "$ax_pthread_check_macro must be defined"
# endif
static void *some_global = NULL;
static void routine(void *a)
{
/* To avoid any unused-parameter or
unused-but-set-parameter warning. */
some_global = a;
}
static void *start_routine(void *a) { return a; }],
[pthread_t th; pthread_attr_t attr;
pthread_create(&th, 0, start_routine, 0);
@@ -227,101 +331,187 @@ for flag in $ax_pthread_flags; do
pthread_attr_init(&attr);
pthread_cleanup_push(routine, 0);
pthread_cleanup_pop(0) /* ; */])],
[ax_pthread_ok=yes],
[])
[ax_pthread_ok=yes],
[])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
AC_MSG_RESULT([$ax_pthread_ok])
if test "x$ax_pthread_ok" = xyes; then
break;
fi
AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Clang needs special handling, because older versions handle the -pthread
# option in a rather... idiosyncratic way
if test "x$ax_pthread_clang" = "xyes"; then
# Clang takes -pthread; it has never supported any other flag
# (Note 1: This will need to be revisited if a system that Clang
# supports has POSIX threads in a separate library. This tends not
# to be the way of modern systems, but it's conceivable.)
# (Note 2: On some systems, notably Darwin, -pthread is not needed
# to get POSIX threads support; the API is always present and
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
# -pthread does define _REENTRANT, and while the Darwin headers
# ignore this macro, third-party headers might not.)
# However, older versions of Clang make a point of warning the user
# that, in an invocation where only linking and no compilation is
# taking place, the -pthread option has no effect ("argument unused
# during compilation"). They expect -pthread to be passed in only
# when source code is being compiled.
#
# Problem is, this is at odds with the way Automake and most other
# C build frameworks function, which is that the same flags used in
# compilation (CFLAGS) are also used in linking. Many systems
# supported by AX_PTHREAD require exactly this for POSIX threads
# support, and in fact it is often not straightforward to specify a
# flag that is used only in the compilation phase and not in
# linking. Such a scenario is extremely rare in practice.
#
# Even though use of the -pthread flag in linking would only print
# a warning, this can be a nuisance for well-run software projects
# that build with -Werror. So if the active version of Clang has
# this misfeature, we search for an option to squash it.
AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
# Create an alternate version of $ac_link that compiles and
# links in two steps (.c -> .o, .o -> exe) instead of one
# (.c -> exe), because the warning occurs only in the second
# step
ax_pthread_save_ac_link="$ac_link"
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
ax_pthread_save_CFLAGS="$CFLAGS"
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
ac_link="$ax_pthread_save_ac_link"
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
[ac_link="$ax_pthread_2step_ac_link"
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
[break])
])
done
ac_link="$ax_pthread_save_ac_link"
CFLAGS="$ax_pthread_save_CFLAGS"
AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
])
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
no | unknown) ;;
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
esac
fi # $ax_pthread_clang = yes
# Various other checks:
if test "x$ax_pthread_ok" = xyes; then
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
save_CFLAGS="$CFLAGS"
if test "x$ax_pthread_ok" = "xyes"; then
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
AC_MSG_CHECKING([for joinable pthread attribute])
attr_name=unknown
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
[int attr = $attr; return attr /* ; */])],
[attr_name=$attr; break],
[])
done
AC_MSG_RESULT([$attr_name])
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
fi
AC_CACHE_CHECK([for joinable pthread attribute],
[ax_cv_PTHREAD_JOINABLE_ATTR],
[ax_cv_PTHREAD_JOINABLE_ATTR=unknown
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
[int attr = $ax_pthread_attr; return attr /* ; */])],
[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
[])
done
])
AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
test "x$ax_pthread_joinable_attr_defined" != "xyes"],
[AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
[$ax_cv_PTHREAD_JOINABLE_ATTR],
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
ax_pthread_joinable_attr_defined=yes
])
AC_MSG_CHECKING([if more special flags are required for pthreads])
flag=no
case ${host_os} in
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
osf* | hpux*) flag="-D_REENTRANT";;
solaris*)
if test "$GCC" = "yes"; then
flag="-D_REENTRANT"
else
# TODO: What about Clang on Solaris?
flag="-mt -D_REENTRANT"
fi
;;
esac
AC_MSG_RESULT([$flag])
if test "x$flag" != xno; then
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
fi
AC_CACHE_CHECK([whether more special flags are required for pthreads],
[ax_cv_PTHREAD_SPECIAL_FLAGS],
[ax_cv_PTHREAD_SPECIAL_FLAGS=no
case $host_os in
solaris*)
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
;;
esac
])
AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
test "x$ax_pthread_special_flags_added" != "xyes"],
[PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
ax_pthread_special_flags_added=yes])
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
[ax_cv_PTHREAD_PRIO_INHERIT], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
[[int i = PTHREAD_PRIO_INHERIT;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no])
[ax_cv_PTHREAD_PRIO_INHERIT],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
[[int i = PTHREAD_PRIO_INHERIT;
return i;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no])
])
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
test "x$ax_pthread_prio_inherit_defined" != "xyes"],
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
ax_pthread_prio_inherit_defined=yes
])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
# More AIX lossage: compile with *_r variant
if test "x$GCC" != xyes; then
if test "x$GCC" != "xyes"; then
case $host_os in
aix*)
AS_CASE(["x/$CC"],
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
[#handle absolute path differently from PATH based program lookup
AS_CASE(["x$CC"],
[x/*],
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
[#handle absolute path differently from PATH based program lookup
AS_CASE(["x$CC"],
[x/*],
[
AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
],
[
AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
]
)
])
;;
esac
fi
fi
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
AC_SUBST([PTHREAD_LIBS])
AC_SUBST([PTHREAD_CFLAGS])
AC_SUBST([PTHREAD_CC])
AC_SUBST([PTHREAD_CXX])
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$ax_pthread_ok" = xyes; then
if test "x$ax_pthread_ok" = "xyes"; then
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
:
else
+188 -62
View File
@@ -47,9 +47,12 @@
#include "util/regional.h"
#include "util/net_help.h"
#include "util/config_file.h"
#include "util/data/dname.h"
#include "util/data/msgreply.h"
#include "util/data/msgencode.h"
#include "services/cache/dns.h"
#include "services/mesh.h"
#include "services/modstack.h"
#include "validator/val_neg.h"
#include "validator/val_secalgo.h"
#include "iterator/iter_utils.h"
@@ -265,15 +268,6 @@ cachedb_init(struct module_env* env, int id)
return 0;
}
cachedb_env->enabled = 1;
if(env->cfg->serve_expired && env->cfg->serve_expired_reply_ttl)
log_warn(
"cachedb: serve-expired-reply-ttl is set but not working for data "
"originating from the external cache; 0 TTL is used for those.");
if(env->cfg->serve_expired && env->cfg->serve_expired_client_timeout)
log_warn(
"cachedb: serve-expired-client-timeout is set but not working for "
"data originating from the external cache; expired data are used "
"in the reply without first trying to refresh the data.");
return 1;
}
@@ -329,30 +323,31 @@ error_response(struct module_qstate* qstate, int id, int rcode)
/**
* Hash the query name, type, class and dbacess-secret into lookup buffer.
* @param qstate: query state with query info
* and env->cfg with secret.
* @param qinfo: query info
* @param env: with env->cfg with secret.
* @param buf: returned buffer with hash to lookup
* @param len: length of the buffer.
*/
static void
calc_hash(struct module_qstate* qstate, char* buf, size_t len)
calc_hash(struct query_info* qinfo, struct module_env* env, char* buf,
size_t len)
{
uint8_t clear[1024];
size_t clen = 0;
uint8_t hash[CACHEDB_HASHSIZE/8];
const char* hex = "0123456789ABCDEF";
const char* secret = qstate->env->cfg->cachedb_secret;
const char* secret = env->cfg->cachedb_secret;
size_t i;
/* copy the hash info into the clear buffer */
if(clen + qstate->qinfo.qname_len < sizeof(clear)) {
memmove(clear+clen, qstate->qinfo.qname,
qstate->qinfo.qname_len);
clen += qstate->qinfo.qname_len;
if(clen + qinfo->qname_len < sizeof(clear)) {
memmove(clear+clen, qinfo->qname, qinfo->qname_len);
query_dname_tolower(clear+clen);
clen += qinfo->qname_len;
}
if(clen + 4 < sizeof(clear)) {
uint16_t t = htons(qstate->qinfo.qtype);
uint16_t c = htons(qstate->qinfo.qclass);
uint16_t t = htons(qinfo->qtype);
uint16_t c = htons(qinfo->qclass);
memmove(clear+clen, &t, 2);
memmove(clear+clen+2, &c, 2);
clen += 4;
@@ -406,12 +401,9 @@ prep_data(struct module_qstate* qstate, struct sldns_buffer* buf)
FLAGS_GET_RCODE(qstate->return_msg->rep->flags) !=
LDNS_RCODE_YXDOMAIN)
return 0;
/* We don't store the reply if its TTL is 0 unless serve-expired is
* enabled. Such a reply won't be reusable and simply be a waste for
* the backend. It's also compatible with the default behavior of
* dns_cache_store_msg(). */
if(qstate->return_msg->rep->ttl == 0 &&
!qstate->env->cfg->serve_expired)
/* We don't store the reply if its TTL is 0. This is probably coming
* from upstream and it is not meant to be stored. */
if(qstate->return_msg->rep->ttl == 0)
return 0;
/* The EDE is added to the out-list so it is encoded in the cached message */
@@ -465,7 +457,7 @@ good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf)
* - serve_expired needs to be set
* - if SERVE_EXPIRED_TTL is set make sure that the record is not older
* than that. */
if((time_t)expiry < *qstate->env->now &&
if(TTL_IS_EXPIRED((time_t)expiry, *qstate->env->now) &&
(!qstate->env->cfg->serve_expired ||
(SERVE_EXPIRED_TTL &&
*qstate->env->now - (time_t)expiry > SERVE_EXPIRED_TTL)))
@@ -477,7 +469,8 @@ good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf)
/* Adjust the TTL of the given RRset by 'subtract'. If 'subtract' is
* negative, set the TTL to 0. */
static void
packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract)
packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract,
time_t timestamp)
{
size_t i;
size_t total = data->count + data->rrsig_count;
@@ -489,13 +482,13 @@ packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract)
data->rr_ttl[i] -= subtract;
else data->rr_ttl[i] = 0;
}
data->ttl_add = (subtract < data->ttl_add) ? (data->ttl_add - subtract) : 0;
data->ttl_add = timestamp;
}
/* Adjust the TTL of a DNS message and its RRs by 'adjust'. If 'adjust' is
* negative, set the TTLs to 0. */
static void
adjust_msg_ttl(struct dns_msg* msg, time_t adjust)
adjust_msg_ttl(struct dns_msg* msg, time_t adjust, time_t timestamp)
{
size_t i;
if(adjust >= 0 && msg->rep->ttl > adjust)
@@ -507,13 +500,42 @@ adjust_msg_ttl(struct dns_msg* msg, time_t adjust)
for(i=0; i<msg->rep->rrset_count; i++) {
packed_rrset_ttl_subtract((struct packed_rrset_data*)msg->
rep->rrsets[i]->entry.data, adjust);
rep->rrsets[i]->entry.data, adjust, timestamp);
}
}
/* Set the TTL of the given RRset to fixed value. */
static void
packed_rrset_ttl_set(struct packed_rrset_data* data, time_t ttl, time_t timestamp)
{
size_t i;
size_t total = data->count + data->rrsig_count;
data->ttl = ttl;
for(i=0; i<total; i++) {
data->rr_ttl[i] = ttl;
}
data->ttl_add = timestamp;
}
/* Set the TTL of a DNS message and its RRs by to a fixed value. */
static void
set_msg_ttl(struct dns_msg* msg, time_t ttl, time_t timestamp)
{
size_t i;
msg->rep->ttl = ttl;
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
for(i=0; i<msg->rep->rrset_count; i++) {
packed_rrset_ttl_set((struct packed_rrset_data*)msg->
rep->rrsets[i]->entry.data, ttl, timestamp);
}
}
/** convert dns message in buffer to return_msg */
static int
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf,
int* msg_expired, time_t* msg_timestamp, time_t* msg_expiry)
{
struct msg_parse* prs;
struct edns_data edns;
@@ -530,6 +552,9 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
&timestamp, sizeof(timestamp));
expiry = be64toh(expiry);
timestamp = be64toh(timestamp);
log_assert(timestamp <= expiry);
*msg_expiry = (time_t)expiry;
*msg_timestamp = (time_t)timestamp;
/* parse DNS packet */
regional_free_all(qstate->env->scratch);
@@ -581,10 +606,9 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
return 1; /* message from the future (clock skew?) */
}
adjust = *qstate->env->now - (time_t)timestamp;
if(qstate->return_msg->rep->ttl < adjust) {
if(TTL_IS_EXPIRED((time_t)expiry, *qstate->env->now)) {
verbose(VERB_ALGO, "cachedb msg expired");
/* If serve-expired is enabled, we still use an expired message
* setting the TTL to 0. */
*msg_expired = 1;
if(!qstate->env->cfg->serve_expired ||
(FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
!= LDNS_RCODE_NOERROR &&
@@ -593,19 +617,21 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
!= LDNS_RCODE_YXDOMAIN))
return 0; /* message expired */
else
adjust = -1;
/* If serve-expired is enabled, we still use an expired message.
* Set the TTL to 0 now and it will be handled specially later
* when we need to store it internally. */
adjust = -1;
}
adjust_msg_ttl(qstate->return_msg, adjust, timestamp);
verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust);
adjust_msg_ttl(qstate->return_msg, adjust);
if(qstate->env->cfg->aggressive_nsec) {
limit_nsec_ttl(qstate->return_msg);
}
/* Similar to the unbound worker, if serve-expired is enabled and
* the msg would be considered to be expired, mark the state so a
* refetch will be scheduled. The comparison between 'expiry' and
* 'now' should be redundant given how these values were calculated,
* but we check it just in case as does good_expiry_and_qinfo(). */
if(qstate->env->cfg->serve_expired &&
(adjust == -1 || (time_t)expiry < *qstate->env->now)) {
* refetch will be scheduled. */
if(*msg_expired && !qstate->env->cfg->serve_expired_client_timeout) {
qstate->need_refetch = 1;
}
@@ -617,10 +643,11 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
* return true if lookup was successful.
*/
static int
cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie)
cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie,
int* msg_expired, time_t* msg_timestamp, time_t* msg_expiry)
{
char key[(CACHEDB_HASHSIZE/8)*2+1];
calc_hash(qstate, key, sizeof(key));
calc_hash(&qstate->qinfo, qstate->env, key, sizeof(key));
/* call backend to fetch data for key into scratch buffer */
if( !(*ie->backend->lookup)(qstate->env, ie, key,
@@ -634,7 +661,8 @@ cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie)
}
/* parse dns message into return_msg */
if( !parse_data(qstate, qstate->env->scratch_buffer) ) {
if( !parse_data(qstate, qstate->env->scratch_buffer, msg_expired,
msg_timestamp, msg_expiry) ) {
return 0;
}
return 1;
@@ -647,7 +675,7 @@ static void
cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
{
char key[(CACHEDB_HASHSIZE/8)*2+1];
calc_hash(qstate, key, sizeof(key));
calc_hash(&qstate->qinfo, qstate->env, key, sizeof(key));
/* prepare data in scratch buffer */
if(!prep_data(qstate, qstate->env->scratch_buffer))
@@ -666,6 +694,7 @@ cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
static int
cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
{
uint8_t dpname_storage[LDNS_MAX_DOMAINLEN+1];
uint8_t* dpname=NULL;
size_t dpnamelen=0;
struct dns_msg* msg;
@@ -674,7 +703,7 @@ cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
return 0;
}
if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo,
&dpname, &dpnamelen))
&dpname, &dpnamelen, dpname_storage, sizeof(dpname_storage)))
return 0; /* no cache for these queries */
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
qstate->qinfo.qname_len, qstate->qinfo.qtype,
@@ -705,17 +734,52 @@ cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
* Store query into the internal cache of unbound.
*/
static void
cachedb_intcache_store(struct module_qstate* qstate)
cachedb_intcache_store(struct module_qstate* qstate, int msg_expired,
time_t msg_timestamp, time_t msg_expiry)
{
uint32_t store_flags = qstate->query_flags;
if(qstate->env->cfg->serve_expired)
store_flags |= DNSCACHE_STORE_ZEROTTL;
int serve_expired = qstate->env->cfg->serve_expired;
if(!qstate->return_msg)
return;
if(serve_expired && msg_expired) {
time_t original_ttl = msg_expiry - msg_timestamp;
store_flags |= DNSCACHE_STORE_EXPIRED_MSG_CACHEDB;
/* Pass the original TTL of the expired message and signal with
* the DNSCACHE_STORE_EXPIRED_MSG_CACHEDB flag that
* dns_cache_store_msg() needs to set absolute expired TTLs
* based on the original message TTL.
* Results as expired message in the cache */
set_msg_ttl(qstate->return_msg, original_ttl, 0);
verbose(VERB_ALGO, "cachedb expired msg set to be expired now "
"(original ttl: %d)", (int)original_ttl);
/* The expired entry does not get checked by the validator
* and we need a validation value for it. */
/* By setting this to unchecked, bogus data is not returned
* as non-bogus. */
if(qstate->env->cfg->cachedb_check_when_serve_expired)
qstate->return_msg->rep->security = sec_status_unchecked;
}
(void)dns_cache_store(qstate->env, &qstate->qinfo,
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
qstate->region, store_flags, qstate->qstarttime);
qstate->region, store_flags, qstate->qstarttime,
qstate->is_valrec);
if(serve_expired && msg_expired) {
if(qstate->env->cfg->serve_expired_client_timeout) {
/* No expired response from the query state, the
* query resolution needs to continue and it can
* pick up the expired result after the timer out
* of cache. */
return;
}
/* Send serve expired responses based on the cachedb
* returned message, that was just stored in the cache.
* It can then continue to work on this query. */
mesh_respond_serve_expired(qstate->mesh_info);
/* set TTLs as expired for this return_msg in case it is used
* later on */
set_msg_ttl(qstate->return_msg,
EXPIRED_REPLY_TTL_CALC(msg_expiry, msg_timestamp), 0);
}
}
/**
@@ -731,6 +795,8 @@ cachedb_handle_query(struct module_qstate* qstate,
struct cachedb_qstate* ATTR_UNUSED(iq),
struct cachedb_env* ie, int id)
{
int msg_expired = 0;
time_t msg_timestamp, msg_expiry;
qstate->is_cachedb_answer = 0;
/* check if we are enabled, and skip if so */
if(!ie->enabled) {
@@ -739,8 +805,11 @@ cachedb_handle_query(struct module_qstate* qstate,
return;
}
if(qstate->blacklist || qstate->no_cache_lookup) {
/* cache is blacklisted or we are instructed from edns to not look */
if(qstate->blacklist || qstate->no_cache_lookup
|| iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL,
NULL, 0)) {
/* cache is blacklisted or we are instructed from edns to not
* look or a forwarder/stub forbids it */
/* pass request to next module */
qstate->ext_state[id] = module_wait_module;
return;
@@ -765,32 +834,50 @@ cachedb_handle_query(struct module_qstate* qstate,
}
/* ask backend cache to see if we have data */
if(cachedb_extcache_lookup(qstate, ie)) {
if(cachedb_extcache_lookup(qstate, ie, &msg_expired, &msg_timestamp,
&msg_expiry)) {
if(verbosity >= VERB_ALGO)
log_dns_msg(ie->backend->name,
&qstate->return_msg->qinfo,
qstate->return_msg->rep);
/* store this result in internal cache */
cachedb_intcache_store(qstate);
cachedb_intcache_store(qstate,
msg_expired, msg_timestamp, msg_expiry);
/* In case we have expired data but there is a client timer for expired
* answers, pass execution to next module in order to try updating the
* data first.
* TODO: this needs revisit. The expired data stored from cachedb has
* 0 TTL which is picked up by iterator later when looking in the cache.
* Document that ext cachedb does not work properly with
* serve_stale_reply_ttl yet. */
*/
if(qstate->env->cfg->serve_expired && msg_expired) {
qstate->return_msg = NULL;
qstate->ext_state[id] = module_wait_module;
/* The expired reply is sent with
* mesh_respond_serve_expired, and so
* the need_refetch is not used. */
qstate->need_refetch = 0;
return;
}
if(qstate->need_refetch && qstate->serve_expired_data &&
qstate->serve_expired_data->timer) {
qstate->return_msg = NULL;
qstate->ext_state[id] = module_wait_module;
return;
}
/* No 0TTL answers escaping from external cache. */
log_assert(qstate->return_msg->rep->ttl > 0);
qstate->is_cachedb_answer = 1;
/* we are done with the query */
qstate->ext_state[id] = module_finished;
return;
}
if(qstate->serve_expired_data &&
qstate->env->cfg->cachedb_check_when_serve_expired &&
!qstate->env->cfg->serve_expired_client_timeout) {
/* Reply with expired data if any to client, because cachedb
* also has no useful, current data */
mesh_respond_serve_expired(qstate->mesh_info);
}
/* no cache fetches */
/* pass request to next module */
qstate->ext_state[id] = module_wait_module;
@@ -810,7 +897,9 @@ cachedb_handle_response(struct module_qstate* qstate,
{
qstate->is_cachedb_answer = 0;
/* check if we are not enabled or instructed to not cache, and skip */
if(!ie->enabled || qstate->no_cache_store) {
if(!ie->enabled || qstate->no_cache_store
|| iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL,
NULL, 0)) {
/* we are done with the query */
qstate->ext_state[id] = module_finished;
return;
@@ -914,7 +1003,7 @@ cachedb_get_mem(struct module_env* env, int id)
*/
static struct module_func_block cachedb_block = {
"cachedb",
&cachedb_init, &cachedb_deinit, &cachedb_operate,
NULL, NULL, &cachedb_init, &cachedb_deinit, &cachedb_operate,
&cachedb_inform_super, &cachedb_clear, &cachedb_get_mem
};
@@ -923,4 +1012,41 @@ cachedb_get_funcblock(void)
{
return &cachedb_block;
}
int
cachedb_is_enabled(struct module_stack* mods, struct module_env* env)
{
struct cachedb_env* ie;
int id = modstack_find(mods, "cachedb");
if(id == -1)
return 0;
ie = (struct cachedb_env*)env->modinfo[id];
if(ie && ie->enabled)
return 1;
return 0;
}
void cachedb_msg_remove(struct module_qstate* qstate)
{
cachedb_msg_remove_qinfo(qstate->env, &qstate->qinfo);
}
void cachedb_msg_remove_qinfo(struct module_env* env, struct query_info* qinfo)
{
char key[(CACHEDB_HASHSIZE/8)*2+1];
int id = modstack_find(env->modstack, "cachedb");
struct cachedb_env* ie = (struct cachedb_env*)env->modinfo[id];
log_query_info(VERB_ALGO, "cachedb msg remove", qinfo);
calc_hash(qinfo, env, key, sizeof(key));
sldns_buffer_clear(env->scratch_buffer);
sldns_buffer_write_u32(env->scratch_buffer, 0);
sldns_buffer_flip(env->scratch_buffer);
/* call backend */
(*ie->backend->store)(env, ie, key,
sldns_buffer_begin(env->scratch_buffer),
sldns_buffer_limit(env->scratch_buffer),
0);
}
#endif /* USE_CACHEDB */
+24
View File
@@ -41,6 +41,7 @@
*/
#include "util/module.h"
struct cachedb_backend;
struct module_stack;
/**
* The global variable environment contents for the cachedb
@@ -110,3 +111,26 @@ size_t cachedb_get_mem(struct module_env* env, int id);
*/
struct module_func_block* cachedb_get_funcblock(void);
/**
* See if the cachedb is enabled.
* @param mods: module stack. It finds the cachedb module environment.
* @param env: module environment.
* @return true if exists and enabled.
*/
int cachedb_is_enabled(struct module_stack* mods, struct module_env* env);
/**
* Remove a message from the global cache. Because edns subnet has a more
* specific entry, and if not removed when everything expires, the global
* entry is used, instead of a fresh lookup of the edns subnet entry.
* @param qstate: query state.
*/
void cachedb_msg_remove(struct module_qstate* qstate);
/**
* Remove message from the cachedb cache, by query info.
* @param env: module environment to look up cachedb state.
* @param qinfo: the message to remove.
*/
void cachedb_msg_remove_qinfo(struct module_env* env,
struct query_info* qinfo);
+330 -69
View File
@@ -46,24 +46,62 @@
#include "cachedb/cachedb.h"
#include "util/alloc.h"
#include "util/config_file.h"
#include "util/locks.h"
#include "util/timeval_func.h"
#include "sldns/sbuffer.h"
#ifdef USE_REDIS
#include "hiredis/hiredis.h"
struct redis_moddata {
redisContext** ctxs; /* thread-specific redis contexts */
int numctxs; /* number of ctx entries */
const char* server_host; /* server's IP address or host name */
int server_port; /* server's TCP port */
const char* server_path; /* server's unix path, or "", NULL if unused */
const char* server_password; /* server's AUTH password, or "", NULL if unused */
struct timeval timeout; /* timeout for connection setup and commands */
int logical_db; /* the redis logical database to use */
/* thread-specific redis contexts */
redisContext** ctxs;
redisContext** replica_ctxs;
/* number of ctx entries */
int numctxs;
/* server's IP address or host name */
const char* server_host;
const char* replica_server_host;
/* server's TCP port */
int server_port;
int replica_server_port;
/* server's unix path, or "", NULL if unused */
const char* server_path;
const char* replica_server_path;
/* server's AUTH password, or "", NULL if unused */
const char* server_password;
const char* replica_server_password;
/* timeout for commands */
struct timeval command_timeout;
struct timeval replica_command_timeout;
/* timeout for connection setup */
struct timeval connect_timeout;
struct timeval replica_connect_timeout;
/* the reconnect interval time. */
struct timeval reconnect_interval;
struct timeval replica_reconnect_interval;
/* reconnect attempts, 0 if connected, counts up failed reconnects. */
int reconnect_attempts;
int replica_reconnect_attempts;
/* Lock on reconnect_wait time. */
lock_basic_type wait_lock;
lock_basic_type replica_wait_lock;
/* reconnect wait time, wait until it has passed before reconnect. */
struct timeval reconnect_wait;
struct timeval replica_reconnect_wait;
/* the redis logical database to use */
int logical_db;
int replica_logical_db;
/* if the SET with EX command is supported */
int set_with_ex_available;
};
/** The limit on the number of redis connect attempts. After failure if
* the number is exceeded, the reconnects are throttled by the wait time. */
#define REDIS_RECONNECT_ATTEMPT_LIMIT 3
static redisReply* redis_command(struct module_env*, struct cachedb_env*,
const char*, const uint8_t*, size_t);
const char*, const uint8_t*, size_t, int);
static void
moddata_clean(struct redis_moddata** moddata) {
@@ -77,63 +115,145 @@ moddata_clean(struct redis_moddata** moddata) {
}
free((*moddata)->ctxs);
}
if((*moddata)->replica_ctxs) {
int i;
for(i = 0; i < (*moddata)->numctxs; i++) {
if((*moddata)->replica_ctxs[i])
redisFree((*moddata)->replica_ctxs[i]);
}
free((*moddata)->replica_ctxs);
}
lock_basic_destroy(&(*moddata)->wait_lock);
lock_basic_destroy(&(*moddata)->replica_wait_lock);
free(*moddata);
*moddata = NULL;
}
static redisContext*
redis_connect(const struct redis_moddata* moddata)
redis_connect(const char* host, int port, const char* path,
const char* password, int logical_db,
const struct timeval connect_timeout,
const struct timeval command_timeout,
const struct timeval* reconnect_interval,
int* reconnect_attempts,
struct timeval* reconnect_wait,
lock_basic_type* wait_lock,
struct timeval* now_tv,
const char* infostr)
{
struct timeval now_val;
redisContext* ctx;
#ifdef THREADS_DISABLED
/* Fix attribute unused warning.
* wait_lock is only used with lock_basic_* functions that are nop'ed
* when compiled without thread support. */
(void)wait_lock;
#endif /* THREADS_DISABLED */
if(moddata->server_path && moddata->server_path[0]!=0) {
ctx = redisConnectUnixWithTimeout(moddata->server_path,
moddata->timeout);
/* See if the redis server is down, and reconnect has to wait. */
if(*reconnect_attempts > REDIS_RECONNECT_ATTEMPT_LIMIT) {
/* Acquire lock to look at timeval, the integer has atomic
* integrity. */
struct timeval wait_tv;
if(now_tv) {
now_val = *now_tv;
} else {
if(gettimeofday(&now_val, NULL) < 0)
log_err("redis: gettimeofday: %s",
strerror(errno));
}
lock_basic_lock(wait_lock);
wait_tv = *reconnect_wait;
lock_basic_unlock(wait_lock);
if(timeval_smaller(&now_val, &wait_tv)) {
verbose(VERB_ALGO, "redis %sdown, reconnect wait",
infostr);
return NULL;
}
}
if(path && path[0]!=0) {
ctx = redisConnectUnixWithTimeout(path, connect_timeout);
} else {
ctx = redisConnectWithTimeout(moddata->server_host,
moddata->server_port, moddata->timeout);
ctx = redisConnectWithTimeout(host, port, connect_timeout);
}
if(!ctx || ctx->err) {
const char *errstr = "out of memory";
if(ctx)
errstr = ctx->errstr;
log_err("failed to connect to redis server: %s", errstr);
log_err("failed to connect to redis %sserver: %s", infostr, errstr);
goto fail;
}
if(redisSetTimeout(ctx, moddata->timeout) != REDIS_OK) {
log_err("failed to set redis timeout");
if(redisSetTimeout(ctx, command_timeout) != REDIS_OK) {
log_err("failed to set redis %stimeout, %s", infostr, ctx->errstr);
goto fail;
}
if(moddata->server_password && moddata->server_password[0]!=0) {
if(password && password[0]!=0) {
redisReply* rep;
rep = redisCommand(ctx, "AUTH %s", moddata->server_password);
rep = redisCommand(ctx, "AUTH %s", password);
if(!rep || rep->type == REDIS_REPLY_ERROR) {
log_err("failed to authenticate with password");
log_err("failed to authenticate %swith password", infostr);
freeReplyObject(rep);
goto fail;
}
freeReplyObject(rep);
}
if(moddata->logical_db > 0) {
if(logical_db > 0) {
redisReply* rep;
rep = redisCommand(ctx, "SELECT %d", moddata->logical_db);
rep = redisCommand(ctx, "SELECT %d", logical_db);
if(!rep || rep->type == REDIS_REPLY_ERROR) {
log_err("failed to set logical database (%d)",
moddata->logical_db);
log_err("failed %sto set logical database (%d)",
infostr, logical_db);
freeReplyObject(rep);
goto fail;
}
freeReplyObject(rep);
}
verbose(VERB_OPS, "Connection to Redis established");
*reconnect_attempts = 0;
if(verbosity >= VERB_OPS) {
char port_str[6+1];
port_str[0] = ' ';
(void)snprintf(port_str+1, sizeof(port_str)-1, "%d", port);
verbose(VERB_OPS, "Connection to Redis %sestablished (%s%s)",
infostr,
path&&path[0]!=0?path:host,
path&&path[0]!=0?"":port_str);
}
return ctx;
fail:
if(ctx)
redisFree(ctx);
(*reconnect_attempts)++;
if(*reconnect_attempts > REDIS_RECONNECT_ATTEMPT_LIMIT) {
/* Wait for the reconnect interval before trying again. */
struct timeval tv;
if(now_tv) {
now_val = *now_tv;
} else {
if(gettimeofday(&now_val, NULL) < 0)
log_err("redis: gettimeofday: %s",
strerror(errno));
}
tv = now_val;
timeval_add(&tv, reconnect_interval);
lock_basic_lock(wait_lock);
*reconnect_wait = tv;
lock_basic_unlock(wait_lock);
verbose(VERB_ALGO, "redis %sreconnect wait until %d.%6.6d",
infostr, (int)tv.tv_sec, (int)tv.tv_usec);
}
return NULL;
}
static void
set_timeout(struct timeval* timeout, int value, int explicit_value)
{
int v = explicit_value != 0 ? explicit_value : value;
timeout->tv_sec = v / 1000;
timeout->tv_usec = (v % 1000) * 1000;
}
static int
redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
{
@@ -147,42 +267,120 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
log_err("out of memory");
goto fail;
}
lock_basic_init(&moddata->wait_lock);
lock_protect(&moddata->wait_lock, &moddata->reconnect_wait,
sizeof(moddata->reconnect_wait));
lock_basic_init(&moddata->replica_wait_lock);
lock_protect(&moddata->replica_wait_lock,
&moddata->replica_reconnect_wait,
sizeof(moddata->replica_reconnect_wait));
moddata->numctxs = env->cfg->num_threads;
/* note: server_host and similar string configuration options are
* shallow references to configured strings; we don't have to free them
* in this module. */
moddata->server_host = env->cfg->redis_server_host;
moddata->replica_server_host = env->cfg->redis_replica_server_host;
moddata->server_port = env->cfg->redis_server_port;
moddata->replica_server_port = env->cfg->redis_replica_server_port;
moddata->server_path = env->cfg->redis_server_path;
moddata->replica_server_path = env->cfg->redis_replica_server_path;
moddata->server_password = env->cfg->redis_server_password;
moddata->replica_server_password = env->cfg->redis_replica_server_password;
set_timeout(&moddata->command_timeout,
env->cfg->redis_timeout,
env->cfg->redis_command_timeout);
set_timeout(&moddata->replica_command_timeout,
env->cfg->redis_replica_timeout,
env->cfg->redis_replica_command_timeout);
set_timeout(&moddata->connect_timeout,
env->cfg->redis_timeout,
env->cfg->redis_connect_timeout);
set_timeout(&moddata->replica_connect_timeout,
env->cfg->redis_replica_timeout,
env->cfg->redis_replica_connect_timeout);
set_timeout(&moddata->reconnect_interval, 1000, 0);
set_timeout(&moddata->replica_reconnect_interval, 1000, 0);
moddata->logical_db = env->cfg->redis_logical_db;
moddata->replica_logical_db = env->cfg->redis_replica_logical_db;
moddata->ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
if(!moddata->ctxs) {
log_err("out of memory");
goto fail;
}
/* note: server_host is a shallow reference to configured string.
* we don't have to free it in this module. */
moddata->server_host = env->cfg->redis_server_host;
moddata->server_port = env->cfg->redis_server_port;
moddata->server_path = env->cfg->redis_server_path;
moddata->server_password = env->cfg->redis_server_password;
moddata->timeout.tv_sec = env->cfg->redis_timeout / 1000;
moddata->timeout.tv_usec = (env->cfg->redis_timeout % 1000) * 1000;
moddata->logical_db = env->cfg->redis_logical_db;
for(i = 0; i < moddata->numctxs; i++) {
redisContext* ctx = redis_connect(moddata);
if(!ctx) {
log_err("redis_init: failed to init redis");
if((moddata->replica_server_host && moddata->replica_server_host[0]!=0)
|| (moddata->replica_server_path && moddata->replica_server_path[0]!=0)) {
/* There is a replica configured, allocate ctxs */
moddata->replica_ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
if(!moddata->replica_ctxs) {
log_err("out of memory");
goto fail;
}
}
for(i = 0; i < moddata->numctxs; i++) {
redisContext* ctx = redis_connect(
moddata->server_host,
moddata->server_port,
moddata->server_path,
moddata->server_password,
moddata->logical_db,
moddata->connect_timeout,
moddata->command_timeout,
&moddata->reconnect_interval,
&moddata->reconnect_attempts,
&moddata->reconnect_wait,
&moddata->wait_lock,
env->now_tv,
"");
if(!ctx) {
log_err("redis_init: failed to init redis "
"(for thread %d)", i);
/* And continue, the context can be established
* later, just like after a disconnect. */
}
moddata->ctxs[i] = ctx;
}
if(moddata->replica_ctxs) {
for(i = 0; i < moddata->numctxs; i++) {
redisContext* ctx = redis_connect(
moddata->replica_server_host,
moddata->replica_server_port,
moddata->replica_server_path,
moddata->replica_server_password,
moddata->replica_logical_db,
moddata->replica_connect_timeout,
moddata->replica_command_timeout,
&moddata->replica_reconnect_interval,
&moddata->replica_reconnect_attempts,
&moddata->replica_reconnect_wait,
&moddata->replica_wait_lock,
env->now_tv,
"replica ");
if(!ctx) {
log_err("redis_init: failed to init redis "
"replica (for thread %d)", i);
/* And continue, the context can be established
* later, just like after a disconnect. */
}
moddata->replica_ctxs[i] = ctx;
}
}
cachedb_env->backend_data = moddata;
if(env->cfg->redis_expire_records) {
if(env->cfg->redis_expire_records &&
moddata->ctxs[env->alloc->thread_num] != NULL) {
redisReply* rep = NULL;
int redis_reply_type = 0;
/** check if setex command is supported */
/** check if set with ex command is supported */
rep = redis_command(env, cachedb_env,
"SETEX __UNBOUND_REDIS_CHECK__ 1 none", NULL, 0);
"SET __UNBOUND_REDIS_CHECK__ none EX 1", NULL, 0, 1);
if(!rep) {
/** init failed, no response from redis server*/
log_err("redis_init: failed to init redis, the "
"redis-expire-records option requires the SETEX command "
"(redis >= 2.0.0)");
goto fail;
goto set_with_ex_fail;
}
redis_reply_type = rep->type;
freeReplyObject(rep);
@@ -190,15 +388,18 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
case REDIS_REPLY_STATUS:
break;
default:
/** init failed, setex command not supported */
log_err("redis_init: failed to init redis, the "
"redis-expire-records option requires the SETEX command "
"(redis >= 2.0.0)");
goto fail;
/** init failed, set_with_ex command not supported */
goto set_with_ex_fail;
}
moddata->set_with_ex_available = 1;
}
return 1;
set_with_ex_fail:
log_err("redis_init: failure during redis_init, the "
"redis-expire-records option requires the SET with EX command "
"(redis >= 2.6.12)");
return 1;
fail:
moddata_clean(&moddata);
return 0;
@@ -229,9 +430,9 @@ redis_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
*/
static redisReply*
redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
const char* command, const uint8_t* data, size_t data_len)
const char* command, const uint8_t* data, size_t data_len, int write)
{
redisContext* ctx;
redisContext* ctx, **ctx_selector;
redisReply* rep;
struct redis_moddata* d = (struct redis_moddata*)
cachedb_env->backend_data;
@@ -242,17 +443,50 @@ redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
* assumption throughout the unbound architecture, so we simply assert
* it. */
log_assert(env->alloc->thread_num < d->numctxs);
ctx = d->ctxs[env->alloc->thread_num];
ctx_selector = !write && d->replica_ctxs
?d->replica_ctxs
:d->ctxs;
ctx = ctx_selector[env->alloc->thread_num];
/* If we've not established a connection to the server or we've closed
* it on a failure, try to re-establish a new one. Failures will be
* logged in redis_connect(). */
if(!ctx) {
ctx = redis_connect(d);
d->ctxs[env->alloc->thread_num] = ctx;
if(!write && d->replica_ctxs) {
ctx = redis_connect(
d->replica_server_host,
d->replica_server_port,
d->replica_server_path,
d->replica_server_password,
d->replica_logical_db,
d->replica_connect_timeout,
d->replica_command_timeout,
&d->replica_reconnect_interval,
&d->replica_reconnect_attempts,
&d->replica_reconnect_wait,
&d->replica_wait_lock,
env->now_tv,
"replica ");
} else {
ctx = redis_connect(
d->server_host,
d->server_port,
d->server_path,
d->server_password,
d->logical_db,
d->connect_timeout,
d->command_timeout,
&d->reconnect_interval,
&d->reconnect_attempts,
&d->reconnect_wait,
&d->wait_lock,
env->now_tv,
"");
}
ctx_selector[env->alloc->thread_num] = ctx;
}
if(!ctx)
return NULL;
if(!ctx) return NULL;
/* Send the command and get a reply, synchronously. */
rep = (redisReply*)redisCommand(ctx, command, data, data_len);
@@ -262,7 +496,7 @@ redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
log_err("redis_command: failed to receive a reply, "
"closing connection: %s", ctx->errstr);
redisFree(ctx);
d->ctxs[env->alloc->thread_num] = NULL;
ctx_selector[env->alloc->thread_num] = NULL;
return NULL;
}
@@ -280,7 +514,14 @@ redis_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
char* key, struct sldns_buffer* result_buffer)
{
redisReply* rep;
char cmdbuf[4+(CACHEDB_HASHSIZE/8)*2+1]; /* "GET " + key */
/* Supported commands:
* - "GET " + key
*/
#define REDIS_LOOKUP_MAX_BUF_LEN \
4 /* "GET " */ \
+(CACHEDB_HASHSIZE/8)*2 /* key hash */ \
+ 1 /* \0 */
char cmdbuf[REDIS_LOOKUP_MAX_BUF_LEN];
int n;
int ret = 0;
@@ -292,7 +533,7 @@ redis_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
return 0;
}
rep = redis_command(env, cachedb_env, cmdbuf, NULL, 0);
rep = redis_command(env, cachedb_env, cmdbuf, NULL, 0, 0);
if(!rep)
return 0;
switch(rep->type) {
@@ -329,26 +570,45 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
{
redisReply* rep;
int n;
int set_ttl = (env->cfg->redis_expire_records &&
struct redis_moddata* moddata = (struct redis_moddata*)
cachedb_env->backend_data;
int set_ttl = (moddata->set_with_ex_available &&
env->cfg->redis_expire_records &&
(!env->cfg->serve_expired || env->cfg->serve_expired_ttl > 0));
/* Supported commands:
* - "SET " + key + " %b"
* - "SETEX " + key + " " + ttl + " %b"
* - "SET " + key + " %b EX " + ttl
* older redis 2.0.0 was "SETEX " + key + " " + ttl + " %b"
* - "EXPIRE " + key + " 0"
*/
char cmdbuf[6+(CACHEDB_HASHSIZE/8)*2+11+3+1];
#define REDIS_STORE_MAX_BUF_LEN \
7 /* "EXPIRE " */ \
+(CACHEDB_HASHSIZE/8)*2 /* key hash */ \
+ 7 /* " %b EX " */ \
+ 20 /* ttl (uint64_t) */ \
+ 1 /* \0 */
char cmdbuf[REDIS_STORE_MAX_BUF_LEN];
if (!set_ttl) {
verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len);
/* build command to set to a binary safe string */
n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key);
} else if(ttl == 0) {
/* use the EXPIRE command, SET with EX 0 is an invalid time. */
/* Replies with REDIS_REPLY_INTEGER of 1. */
verbose(VERB_ALGO, "redis_store expire %s (%d bytes)",
key, (int)data_len);
n = snprintf(cmdbuf, sizeof(cmdbuf), "EXPIRE %s 0", key);
data = NULL;
data_len = 0;
} else {
/* add expired ttl time to redis ttl to avoid premature eviction of key */
ttl += env->cfg->serve_expired_ttl;
verbose(VERB_ALGO, "redis_store %s (%d bytes) with ttl %u",
key, (int)data_len, (uint32_t)ttl);
key, (int)data_len, (unsigned)(uint32_t)ttl);
/* build command to set to a binary safe string */
n = snprintf(cmdbuf, sizeof(cmdbuf), "SETEX %s %u %%b", key,
(uint32_t)ttl);
n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b EX %u", key,
(unsigned)(uint32_t)ttl);
}
@@ -357,11 +617,12 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
return;
}
rep = redis_command(env, cachedb_env, cmdbuf, data, data_len);
rep = redis_command(env, cachedb_env, cmdbuf, data, data_len, 1);
if(rep) {
verbose(VERB_ALGO, "redis_store set completed");
if(rep->type != REDIS_REPLY_STATUS &&
rep->type != REDIS_REPLY_ERROR) {
rep->type != REDIS_REPLY_ERROR &&
rep->type != REDIS_REPLY_INTEGER) {
log_err("redis_store: unexpected type of reply (%d)",
rep->type);
}
+7
View File
@@ -38,6 +38,9 @@
#ifndef UB_ON_WINDOWS
#include <sys/mman.h>
#endif
#ifdef __QNX__
#include "util/log.h"
#endif /* __QNX__ */
#define KEYSTREAM_ONLY
#include "chacha_private.h"
@@ -187,7 +190,11 @@ _rs_stir(void)
if(errno != ENOSYS ||
fallback_getentropy_urandom(rnd, sizeof rnd) == -1) {
#ifdef SIGKILL
#ifndef __QNX__
raise(SIGKILL);
#else /* !__QNX__ */
fatal_exit("failed to getentropy");
#endif /* __QNX__ */
#else
exit(9); /* windows */
#endif
+2 -2
View File
@@ -48,8 +48,8 @@ typedef struct
a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
static const char sigma[16] = "expand 32-byte k";
static const char tau[16] = "expand 16-byte k";
static const char ATTR_NONSTRING(sigma[16]) = "expand 32-byte k";
static const char ATTR_NONSTRING(tau[16]) = "expand 16-byte k";
static void
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ATTR_UNUSED(ivbits))
+3 -3
View File
@@ -57,7 +57,7 @@ int getnameinfo(const struct sockaddr *sa, size_t ATTR_UNUSED(salen), char *host
}
if (host != NULL) {
if (flags & NI_NUMERICHOST) {
if ((flags & NI_NUMERICHOST)) {
if (strlcpy(host, inet_ntoa(sin->sin_addr),
hostlen) >= hostlen)
return (EAI_MEMORY);
@@ -168,7 +168,7 @@ getaddrinfo(const char *hostname, const char *servname,
port = 0;
}
if (hints && hints->ai_flags & AI_PASSIVE) {
if (hints && (hints->ai_flags & AI_PASSIVE)) {
addr = htonl(0x00000000);
if (hostname && inet_aton(hostname, &in) != 0)
addr = in.s_addr;
@@ -193,7 +193,7 @@ getaddrinfo(const char *hostname, const char *servname,
}
/* Don't try DNS if AI_NUMERICHOST is set */
if (hints && hints->ai_flags & AI_NUMERICHOST)
if (hints && (hints->ai_flags & AI_NUMERICHOST))
return (EAI_NONAME);
hp = gethostbyname(hostname);
+20
View File
@@ -29,7 +29,9 @@
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#ifndef __QNX__
#include <sys/syscall.h>
#endif /* !__QNX__ */
#ifdef SYS__sysctl
#include <linux/sysctl.h>
#endif
@@ -42,7 +44,9 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#ifndef __QNX__
#include <link.h>
#endif /* __QNX__ */
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
@@ -60,12 +64,14 @@
#define SHA512_Final(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r)
#endif
#ifndef __QNX__
#include <linux/types.h>
#include <linux/random.h>
#ifdef HAVE_GETAUXVAL
#include <sys/auxv.h>
#endif
#include <sys/vfs.h>
#endif /* !__QNX__ */
#ifndef MAP_ANON
#define MAP_ANON MAP_ANONYMOUS
#endif
@@ -94,8 +100,10 @@ static int getentropy_urandom(void *buf, size_t len);
#ifdef SYS__sysctl
static int getentropy_sysctl(void *buf, size_t len);
#endif
#ifndef __QNX__
static int getentropy_fallback(void *buf, size_t len);
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
#endif /* !__QNX__ */
int
getentropy(void *buf, size_t len)
@@ -178,6 +186,7 @@ getentropy(void *buf, size_t len)
* sysctl ABI, or consider providing a new failsafe API which
* works in a chroot or when file descriptors are exhausted.
*/
#ifndef __QNX__
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
@@ -185,6 +194,9 @@ getentropy(void *buf, size_t len)
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
#else /* !__QNX__ */
fatal_exit("failed to read from /dev/urandom");
#endif /* __QNX__ */
errno = EIO;
return (ret);
@@ -214,7 +226,11 @@ getentropy_urandom(void *buf, size_t len)
{
struct stat st;
size_t i;
#ifndef __QNX__
int fd, cnt, flags;
#else /* !__QNX__ */
int fd, flags;
#endif /* __QNX__ */
int save_errno = errno;
start:
@@ -241,10 +257,12 @@ start:
close(fd);
goto nodevrandom;
}
#ifndef __QNX__
if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
close(fd);
goto nodevrandom;
}
#endif /* !__QNX__ */
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
@@ -265,6 +283,7 @@ nodevrandom:
return (-1);
}
#ifndef __QNX__
#ifdef SYS__sysctl
static int
getentropy_sysctl(void *buf, size_t len)
@@ -537,3 +556,4 @@ getentropy_fallback(void *buf, size_t len)
errno = save_errno;
return (0); /* satisfied */
}
#endif /* !__QNX__ */
+1 -4
View File
@@ -42,10 +42,7 @@ static const int year_lengths[2] = {
};
static void
timesub(timep, offset, tmp)
const time_t * const timep;
const long offset;
struct tm * const tmp;
timesub(const time_t * const timep, const long offset, struct tm * const tmp)
{
long days;
long rem;
-4
View File
@@ -5,12 +5,8 @@
#undef malloc
#include <sys/types.h>
#ifndef USE_WINSOCK
void *malloc ();
#else
/* provide a prototype */
void *malloc (size_t n);
#endif
/* Allocate an N-byte block of memory from the heap.
If N is zero, allocate a 1-byte block. */
+704 -559
View File
File diff suppressed because it is too large Load Diff
+242 -23
View File
@@ -1,5 +1,8 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* apply the fallthrough attribute. */
#undef ATTR_FALLTHROUGH
/* apply the noreturn attribute to a function that exits the program */
#undef ATTR_NORETURN
@@ -57,9 +60,15 @@
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Whether the C compiler accepts the "fallthrough" attribute */
#undef HAVE_ATTR_FALLTHROUGH
/* Whether the C compiler accepts the "format" attribute */
#undef HAVE_ATTR_FORMAT
/* Whether the C compiler accepts the "nonstring" attribute */
#undef HAVE_ATTR_NONSTRING
/* Whether the C compiler accepts the "noreturn" attribute */
#undef HAVE_ATTR_NORETURN
@@ -123,6 +132,14 @@
and to 0 if you don't. */
#undef HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW
/* Define to 1 if you have the declaration of `ngtcp2_conn_server_new', and to
0 if you don't. */
#undef HAVE_DECL_NGTCP2_CONN_SERVER_NEW
/* Define to 1 if you have the declaration of `ngtcp2_crypto_encrypt_cb', and
to 0 if you don't. */
#undef HAVE_DECL_NGTCP2_CRYPTO_ENCRYPT_CB
/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you
don't. */
#undef HAVE_DECL_NID_ED25519
@@ -159,6 +176,10 @@
0 if you don't. */
#undef HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
/* Define to 1 if you have the declaration of `SSL_CTX_set_tmp_ecdh', and to 0
if you don't. */
#undef HAVE_DECL_SSL_CTX_SET_TMP_ECDH
/* Define to 1 if you have the declaration of `strlcat', and to 0 if you
don't. */
#undef HAVE_DECL_STRLCAT
@@ -364,6 +385,9 @@
/* Define if we have LibreSSL */
#undef HAVE_LIBRESSL
/* If we have atomic_store */
#undef HAVE_LINK_ATOMIC_STORE
/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
#undef HAVE_LINUX_NET_TSTAMP_H
@@ -379,8 +403,8 @@
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <minix/config.h> header file. */
#undef HAVE_MINIX_CONFIG_H
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
@@ -406,12 +430,80 @@
/* Define to 1 if you have the <net/if.h> header file. */
#undef HAVE_NET_IF_H
/* Define to 1 if you have the <net/pfvar.h> header file. */
#undef HAVE_NET_PFVAR_H
/* Define this to use nghttp2 client. */
#undef HAVE_NGHTTP2
/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
#undef HAVE_NGHTTP2_NGHTTP2_H
/* Define this to use ngtcp2. */
#undef HAVE_NGTCP2
/* Define to 1 if you have the `ngtcp2_ccerr_default' function. */
#undef HAVE_NGTCP2_CCERR_DEFAULT
/* Define to 1 if you have the `ngtcp2_conn_encode_0rtt_transport_params'
function. */
#undef HAVE_NGTCP2_CONN_ENCODE_0RTT_TRANSPORT_PARAMS
/* Define to 1 if you have the `ngtcp2_conn_get_max_local_streams_uni'
function. */
#undef HAVE_NGTCP2_CONN_GET_MAX_LOCAL_STREAMS_UNI
/* Define to 1 if you have the `ngtcp2_conn_get_num_scid' function. */
#undef HAVE_NGTCP2_CONN_GET_NUM_SCID
/* Define to 1 if you have the `ngtcp2_conn_in_closing_period' function. */
#undef HAVE_NGTCP2_CONN_IN_CLOSING_PERIOD
/* Define to 1 if you have the `ngtcp2_conn_in_draining_period' function. */
#undef HAVE_NGTCP2_CONN_IN_DRAINING_PERIOD
/* Define if ngtcp2_conn_shutdown_stream has 4 arguments. */
#undef HAVE_NGTCP2_CONN_SHUTDOWN_STREAM4
/* Define to 1 if you have the `ngtcp2_conn_tls_early_data_rejected' function.
*/
#undef HAVE_NGTCP2_CONN_TLS_EARLY_DATA_REJECTED
/* Define to 1 if you have the `ngtcp2_crypto_encrypt_cb' function. */
#undef HAVE_NGTCP2_CRYPTO_ENCRYPT_CB
/* Define to 1 if you have the
`ngtcp2_crypto_quictls_configure_client_context' function. */
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_CLIENT_CONTEXT
/* Define to 1 if you have the
`ngtcp2_crypto_quictls_configure_server_context' function. */
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT
/* Define to 1 if you have the
`ngtcp2_crypto_quictls_from_ossl_encryption_level' function. */
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_FROM_OSSL_ENCRYPTION_LEVEL
/* Define to 1 if you have the `ngtcp2_crypto_quictls_init' function. */
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_INIT
/* Define to 1 if the system has the type `ngtcp2_encryption_level'. */
#undef HAVE_NGTCP2_ENCRYPTION_LEVEL
/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_openssl.h> header file.
*/
#undef HAVE_NGTCP2_NGTCP2_CRYPTO_OPENSSL_H
/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_ossl.h> header file. */
#undef HAVE_NGTCP2_NGTCP2_CRYPTO_OSSL_H
/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_quictls.h> header file.
*/
#undef HAVE_NGTCP2_NGTCP2_CRYPTO_QUICTLS_H
/* Define to 1 if you have the <ngtcp2/ngtcp2.h> header file. */
#undef HAVE_NGTCP2_NGTCP2_H
/* Use libnss for crypto */
#undef HAVE_NSS
@@ -472,12 +564,27 @@
/* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD
/* Define to 1 if you have the <pthread_np.h> header file. */
#undef HAVE_PTHREAD_NP_H
/* Have PTHREAD_PRIO_INHERIT. */
#undef HAVE_PTHREAD_PRIO_INHERIT
/* Define to 1 if the system has the type `pthread_rwlock_t'. */
#undef HAVE_PTHREAD_RWLOCK_T
/* Define if pthread_setname_np has the common 2 arguments. */
#undef HAVE_PTHREAD_SETNAME_NP
/* Define if pthread_setname_np has only 1 argument. */
#undef HAVE_PTHREAD_SETNAME_NP1
/* Define if pthread_setname_np has 3 arguments. */
#undef HAVE_PTHREAD_SETNAME_NP3
/* Define if pthread_setname_np exists as pthread_set_name_np instead. */
#undef HAVE_PTHREAD_SET_NAME_NP
/* Define to 1 if the system has the type `pthread_spinlock_t'. */
#undef HAVE_PTHREAD_SPINLOCK_T
@@ -575,18 +682,27 @@
/* Define to 1 if you have the `SSL_get1_peer_certificate' function. */
#undef HAVE_SSL_GET1_PEER_CERTIFICATE
/* Define to 1 if you have the `SSL_is_quic' function. */
#undef HAVE_SSL_IS_QUIC
/* Define to 1 if you have the `SSL_set1_host' function. */
#undef HAVE_SSL_SET1_HOST
/* Define to 1 if you have the <stdarg.h> header file. */
#undef HAVE_STDARG_H
/* Define to 1 if you have the <stdatomic.h> header file. */
#undef HAVE_STDATOMIC_H
/* Define to 1 if you have the <stdbool.h> header file. */
#undef HAVE_STDBOOL_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdio.h> header file. */
#undef HAVE_STDIO_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
@@ -614,9 +730,32 @@
/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */
#undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
/* Define to 1 if `tokenlen' is a member of `struct ngtcp2_pkt_hd'. */
#undef HAVE_STRUCT_NGTCP2_PKT_HD_TOKENLEN
/* Define to 1 if `max_tx_udp_payload_size' is a member of `struct
ngtcp2_settings'. */
#undef HAVE_STRUCT_NGTCP2_SETTINGS_MAX_TX_UDP_PAYLOAD_SIZE
/* Define to 1 if `tokenlen' is a member of `struct ngtcp2_settings'. */
#undef HAVE_STRUCT_NGTCP2_SETTINGS_TOKENLEN
/* Define to 1 if `original_dcid_present' is a member of `struct
ngtcp2_transport_params'. */
#undef HAVE_STRUCT_NGTCP2_TRANSPORT_PARAMS_ORIGINAL_DCID_PRESENT
/* Define to 1 if the system has the type `struct ngtcp2_version_cid'. */
#undef HAVE_STRUCT_NGTCP2_VERSION_CID
/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */
#undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIMENSEC
/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
/* Define if you have Swig libraries and header files. */
#undef HAVE_SWIG
@@ -689,6 +828,9 @@
/* Define to 1 if you have the <vfork.h> header file. */
#undef HAVE_VFORK_H
/* Define to 1 if you have the <wchar.h> header file. */
#undef HAVE_WCHAR_H
/* Define to 1 if you have the <windows.h> header file. */
#undef HAVE_WINDOWS_H
@@ -830,7 +972,9 @@
/* Define to 1 if libsodium supports sodium_set_misuse_handler */
#undef SODIUM_MISUSE_HANDLER
/* Define to 1 if you have the ANSI C header files. */
/* Define to 1 if all of the C90 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#undef STDC_HEADERS
/* use default strptime. */
@@ -910,6 +1054,9 @@
/* Define this to enable client TCP Fast Open. */
#undef USE_MSG_FASTOPEN
/* Define this to use ngtcp2_crypto_ossl. */
#undef USE_NGTCP2_CRYPTO_OSSL
/* Define this to enable client TCP Fast Open. */
#undef USE_OSX_MSG_FASTOPEN
@@ -926,21 +1073,87 @@
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Enable general extensions on macOS. */
#ifndef _DARWIN_C_SOURCE
# undef _DARWIN_C_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
/* Enable X/Open compliant socket functions that do not require linking
with -lxnet on HP-UX 11.11. */
#ifndef _HPUX_ALT_XOPEN_SOCKET_API
# undef _HPUX_ALT_XOPEN_SOCKET_API
#endif
/* Identify the host operating system as Minix.
This macro does not affect the system headers' behavior.
A future release of Autoconf may stop defining this macro. */
#ifndef _MINIX
# undef _MINIX
#endif
/* Enable general extensions on NetBSD.
Enable NetBSD compatibility extensions on Minix. */
#ifndef _NETBSD_SOURCE
# undef _NETBSD_SOURCE
#endif
/* Enable OpenBSD compatibility extensions on NetBSD.
Oddly enough, this does nothing on OpenBSD. */
#ifndef _OPENBSD_SOURCE
# undef _OPENBSD_SOURCE
#endif
/* Define to 1 if needed for POSIX-compatible behavior. */
#ifndef _POSIX_SOURCE
# undef _POSIX_SOURCE
#endif
/* Define to 2 if needed for POSIX-compatible behavior. */
#ifndef _POSIX_1_SOURCE
# undef _POSIX_1_SOURCE
#endif
/* Enable POSIX-compatible threading on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
#endif
/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
# undef __STDC_WANT_IEC_60559_BFP_EXT__
#endif
/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
# undef __STDC_WANT_IEC_60559_DFP_EXT__
#endif
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
#endif
/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
# undef __STDC_WANT_IEC_60559_TYPES_EXT__
#endif
/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
#ifndef __STDC_WANT_LIB_EXT2__
# undef __STDC_WANT_LIB_EXT2__
#endif
/* Enable extensions specified by ISO/IEC 24747:2009. */
#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
# undef __STDC_WANT_MATH_SPEC_FUNCS__
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
/* Enable X/Open extensions. Define to 500 only if necessary
to make mbstate_t available. */
#ifndef _XOPEN_SOURCE
# undef _XOPEN_SOURCE
#endif
@@ -966,11 +1179,6 @@
`char[]'. */
#undef YYTEXT_POINTER
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
@@ -980,19 +1188,9 @@
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES
/* Define to 1 if on MINIX. */
#undef _MINIX
/* Enable for compile on Minix */
#undef _NETBSD_SOURCE
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#undef _POSIX_1_SOURCE
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
/* defined to use gcc ansi snprintf and sscanf that understands %lld when
compiled for windows. */
#undef __USE_MINGW_ANSI_STDIO
@@ -1033,7 +1231,7 @@
/* Define to `long int' if <sys/types.h> does not define. */
#undef off_t
/* Define to `int' if <sys/types.h> does not define. */
/* Define as a signed integer type capable of holding a process identifier. */
#undef pid_t
/* Define to 'int' if not defined */
@@ -1207,6 +1405,17 @@
#endif /* !HAVE_ATTR_UNUSED */
#if defined(DOXYGEN)
# define ATTR_NONSTRING(x) x
#elif defined(__cplusplus)
# define ATTR_NONSTRING(x) __attribute__((nonstring)) x
#elif defined(HAVE_ATTR_NONSTRING)
# define ATTR_NONSTRING(x) __attribute__((nonstring)) x
#else /* !HAVE_ATTR_NONSTRING */
# define ATTR_NONSTRING(x) x
#endif /* !HAVE_ATTR_NONSTRING */
#ifndef HAVE_FSEEKO
#define fseeko fseek
#define ftello ftell
@@ -1425,6 +1634,10 @@ struct sockaddr_storage;
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__)
# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__)
# define strdup(s) unbound_stat_strdup_log(s, __FILE__, __LINE__, __func__)
#ifdef HAVE_REALLOCARRAY
# define reallocarray(p,n,s) unbound_stat_reallocarray_log(p, n, s, __FILE__, __LINE__, __func__)
#endif
void *unbound_stat_malloc(size_t size);
void *unbound_stat_calloc(size_t nmemb, size_t size);
void unbound_stat_free(void *ptr);
@@ -1437,6 +1650,10 @@ void unbound_stat_free_log(void *ptr, const char* file, int line,
const char* func);
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
int line, const char* func);
void *unbound_stat_reallocarray_log(void *ptr, size_t nmemb, size_t size,
const char* file, int line, const char* func);
char *unbound_stat_strdup_log(const char *s, const char* file, int line,
const char* func);
#elif defined(UNBOUND_ALLOC_LITE)
# include "util/alloc.h"
#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */
@@ -1447,6 +1664,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
#define UNBOUND_DNS_OVER_TLS_PORT 853
/** default port for DNS over HTTPS traffic. */
#define UNBOUND_DNS_OVER_HTTPS_PORT 443
/** default port for DNS over QUIC traffic. */
#define UNBOUND_DNS_OVER_QUIC_PORT 853
/** default port for unbound control traffic, registered port with IANA,
ub-dns-control 8953/tcp unbound dns nameserver control */
#define UNBOUND_CONTROL_PORT 8953
Vendored
+503 -325
View File
File diff suppressed because it is too large Load Diff
Vendored
+8851 -5178
View File
File diff suppressed because it is too large Load Diff
+313 -35
View File
@@ -2,23 +2,24 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.56])
sinclude(acx_nlnetlabs.m4)
sinclude(ax_build_date_epoch.m4)
sinclude(ax_pthread.m4)
sinclude(acx_python.m4)
sinclude(ac_pkg_swig.m4)
sinclude(ax_pkg_swig.m4)
sinclude(dnstap/dnstap.m4)
sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[19])
m4_define([VERSION_MICRO],[0])
m4_define([VERSION_MINOR],[25])
m4_define([VERSION_MICRO],[1])
AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound])
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
LIBUNBOUND_CURRENT=9
LIBUNBOUND_REVISION=23
LIBUNBOUND_REVISION=37
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -109,6 +110,20 @@ LIBUNBOUND_AGE=1
# 1.17.1 had 9:21:1
# 1.18.0 had 9:22:1
# 1.19.0 had 9:23:1
# 1.19.1 had 9:24:1
# 1.19.2 had 9:25:1
# 1.19.3 had 9:26:1
# 1.20.0 had 9:27:1
# 1.21.0 had 9:28:1
# 1.21.1 had 9:29:1
# 1.22.0 had 9:30:1
# 1.23.0 had 9:31:1
# 1.23.1 had 9:32:1
# 1.24.0 had 9:33:1
# 1.24.1 had 9:34:1
# 1.24.2 had 9:35:1
# 1.25.0 had 9:36:1
# 1.25.1 had 9:37:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -270,6 +285,9 @@ AC_DEFINE(WINVER, 0x0502, [the version of the windows API enabled])
ACX_RSRC_VERSION(wnvs)
AC_DEFINE_UNQUOTED(RSRC_PACKAGE_VERSION, [$wnvs], [version number for resource files])
# Check for 'grep -e' program, here, since ACX_CHECK_FLTO needs that.
AC_PROG_GREP
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_LANG([C])
@@ -314,6 +332,7 @@ fi
AC_C_INLINE
ACX_CHECK_FORMAT_ATTRIBUTE
ACX_CHECK_UNUSED_ATTRIBUTE
ACX_CHECK_NONSTRING_ATTRIBUTE
AC_DEFUN([CHECK_WEAK_ATTRIBUTE],
[AC_REQUIRE([AC_PROG_CC])
@@ -331,6 +350,8 @@ AC_MSG_RESULT($ac_cv_c_weak_attribute)
if test $ac_cv_c_weak_attribute = yes; then
AC_DEFINE(HAVE_ATTR_WEAK, 1, [Whether the C compiler accepts the "weak" attribute])
AC_DEFINE(ATTR_WEAK, [__attribute__((weak))], [apply the weak attribute to a symbol])
else
AC_DEFINE(ATTR_WEAK,[], [apply the weak attribute to a symbol])
fi
])dnl End of CHECK_WEAK_ATTRIBUTE
@@ -342,7 +363,14 @@ AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "noreturn" attribu
AC_CACHE_VAL(ac_cv_c_noreturn_attribute,
[ac_cv_c_noreturn_attribute=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h>
__attribute__((noreturn)) void f(int x) { printf("%d", x); }
#ifdef STDC_HEADERS
# include <stdlib.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
__attribute__((noreturn)) void f(int x) { printf("%d", x); exit(1); }
]], [[
f(1);
]])],[ac_cv_c_noreturn_attribute="yes"],[ac_cv_c_noreturn_attribute="no"])
@@ -352,11 +380,54 @@ AC_MSG_RESULT($ac_cv_c_noreturn_attribute)
if test $ac_cv_c_noreturn_attribute = yes; then
AC_DEFINE(HAVE_ATTR_NORETURN, 1, [Whether the C compiler accepts the "noreturn" attribute])
AC_DEFINE(ATTR_NORETURN, [__attribute__((__noreturn__))], [apply the noreturn attribute to a function that exits the program])
else
AC_DEFINE(ATTR_NORETURN,[], [apply the noreturn attribute to a function that exits the program])
fi
])dnl End of CHECK_NORETURN_ATTRIBUTE
CHECK_NORETURN_ATTRIBUTE
AC_DEFUN([CHECK_FALLTHROUGH_ATTRIBUTE],
[AC_REQUIRE([AC_PROG_CC])
AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "fallthrough" attribute)
BAKCFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Werror"
AC_CACHE_VAL(ac_cv_c_fallthrough_attribute,
[ac_cv_c_fallthrough_attribute=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h>
void f(int x) {
int y = 0;
switch(x) {
case 1:
y = 1;
__attribute__((fallthrough));
/* fallthrough */
case 2:
y++;
break;
case 3:
y = 3;
break;
}
printf("%d", y);
}
]], [[
f(1);
]])],[ac_cv_c_fallthrough_attribute="yes"],[ac_cv_c_fallthrough_attribute="no"])
])
CFLAGS="$BAKCFLAGS"
AC_MSG_RESULT($ac_cv_c_fallthrough_attribute)
if test $ac_cv_c_fallthrough_attribute = yes; then
AC_DEFINE(HAVE_ATTR_FALLTHROUGH, 1, [Whether the C compiler accepts the "fallthrough" attribute])
AC_DEFINE(ATTR_FALLTHROUGH, [__attribute__((fallthrough));], [apply the fallthrough attribute.])
else
AC_DEFINE(ATTR_FALLTHROUGH,[], [apply the fallthrough attribute.])
fi
])dnl End of CHECK_FALLTHROUGH_ATTRIBUTE
CHECK_FALLTHROUGH_ATTRIBUTE
if test "$srcdir" != "."; then
CPPFLAGS="$CPPFLAGS -I$srcdir"
fi
@@ -406,7 +477,7 @@ AC_CHECK_TOOL(STRIP, strip)
ACX_LIBTOOL_C_ONLY
# pkg-config is only needed for these options, do not require it otherwise
if test "$enable_systemd" = "yes" -o "$with_pyunbound" = "yes" -o "$with_pythonmod" = "yes"; then
if test "$enable_systemd" = "yes" -o "$enable_dnstap" = "yes" -o "$with_pyunbound" = "yes" -o "$with_pythonmod" = "yes"; then
PKG_PROG_PKG_CONFIG
fi
@@ -467,6 +538,7 @@ AC_CHECK_HEADERS([netioapi.h],,, [AC_INCLUDES_DEFAULT
# Check for Linux timestamping headers
AC_CHECK_HEADERS([linux/net_tstamp.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([stdatomic.h],,, [AC_INCLUDES_DEFAULT])
# check for types.
# Using own tests for int64* because autoconf builtin only give 32bit.
@@ -573,19 +645,19 @@ AC_ARG_ENABLE(alloc-nonregional, AS_HELP_STRING([--enable-alloc-nonregional],[ e
if test x_$enable_alloc_nonregional = x_yes; then
AC_DEFINE(UNBOUND_ALLOC_NONREGIONAL, 1, [use malloc not regions, for debug use])
fi
if test x_$enable_alloc_checks = x_yes; then
AS_IF([test x_$enable_alloc_checks = x_yes],[
AC_DEFINE(UNBOUND_ALLOC_STATS, 1, [use statistics for allocs and frees, for debug use])
SLDNS_ALLOCCHECK_EXTRA_OBJ="alloc.lo log.lo"
AC_SUBST(SLDNS_ALLOCCHECK_EXTRA_OBJ)
ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ="alloc.lo"
AC_SUBST(ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ)
else
if test x_$enable_alloc_lite = x_yes; then
],[
AS_IF([test x_$enable_alloc_lite = x_yes],[
AC_DEFINE(UNBOUND_ALLOC_LITE, 1, [use to enable lightweight alloc assertions, for debug use])
else
],[
ACX_FUNC_MALLOC([unbound])
fi
fi
])
])
# check windows threads (we use them, not pthreads, on windows).
if test "$on_mingw" = "yes"; then
@@ -660,6 +732,76 @@ int main(void) {return 0;}
])
fi
if test x_$ub_have_pthreads != x_no; then
# Long checks to support pthread_setname_np().
# Some OSes have the extra non-portable functions in a specific
# header file.
AC_CHECK_HEADERS([pthread_np.h],,, [AC_INCLUDES_DEFAULT])
BAKCFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Werror"
# MacOS only has 1 argument, the name.
AC_MSG_CHECKING([whether pthread_setname_np has only 1 argument])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
],[
(void)pthread_setname_np("");
])],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PTHREAD_SETNAME_NP1, 1, [Define if pthread_setname_np has only 1 argument.])
],[
AC_MSG_RESULT(no)
])
# NetBSD has 3 arguments to allow for formatting of the name.
AC_MSG_CHECKING([whether pthread_setname_np has 3 arguments])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
],[
(void)pthread_setname_np(0, "", NULL);
])],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PTHREAD_SETNAME_NP3, 1, [Define if pthread_setname_np has 3 arguments.])
],[
AC_MSG_RESULT(no)
])
# Most OSes have the common 2 arguments, thread and name.
AC_MSG_CHECKING([whether pthread_setname_np has the common 2 arguments])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
],[
(void)pthread_setname_np(0, "");
])],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PTHREAD_SETNAME_NP, 1, [Define if pthread_setname_np has the common 2 arguments.])
],[
AC_MSG_RESULT(no)
])
# FreeBSD/OpenBSD use a slightly different function name.
AC_MSG_CHECKING([whether pthread_setname_np exists as pthread_set_name_np instead])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
],[
(void)pthread_set_name_np(0, "");
])],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PTHREAD_SET_NAME_NP, 1, [Define if pthread_setname_np exists as pthread_set_name_np instead.])
],[
AC_MSG_RESULT(no)
])
CFLAGS="$BAKCFLAGS"
fi
# check solaris thread library
AC_ARG_WITH(solaris-threads, AS_HELP_STRING([--with-solaris-threads],[use solaris native thread library.]), [ ],[ withval="no" ])
ub_have_sol_threads=no
@@ -792,9 +934,9 @@ if test x_$ub_test_python != x_no; then
ub_have_swig=no
AC_ARG_ENABLE(swig-version-check, AS_HELP_STRING([--disable-swig-version-check],[Disable swig version check to build python modules with older swig even though that is unreliable]))
if test "$enable_swig_version_check" = "yes"; then
AC_PROG_SWIG(2.0.1)
AX_PKG_SWIG(2.0.1)
else
AC_PROG_SWIG
AX_PKG_SWIG
fi
AC_MSG_CHECKING(SWIG)
if test ! -x "$SWIG"; then
@@ -852,7 +994,8 @@ if test "`uname`" = "Linux"; then
GCC_DOCKER_LINTFLAGS='-syntax'
AC_SUBST(GCC_DOCKER_LINTFLAGS)
fi
CONFIG_DATE=`date +%Y%m%d`
AX_BUILD_DATE_EPOCH(CONFIG_DATE, [%Y%m%d])
AC_ARG_VAR(SOURCE_DATE_EPOCH, [If it is set, it uses the value of that variable instead of the current time as the build timestamp. The format is a unix timestamp. This enables reproducible build output.])
AC_SUBST(CONFIG_DATE)
# Checks for libraries.
@@ -944,7 +1087,7 @@ LIBS="-lssl $LIBS"
AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites SSL_CTX_set_tlsext_ticket_key_evp_cb SSL_CTX_set_alpn_select_cb SSL_get0_alpn_selected SSL_CTX_set_alpn_protos SSL_get1_peer_certificate])
LIBS="$BAKLIBS"
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto,SSL_CTX_set_tmp_ecdh], [], [], [
AC_INCLUDES_DEFAULT
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
@@ -1173,15 +1316,24 @@ case "$enable_ecdsa" in
;;
*)
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])])
AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])])
AC_CHECK_FUNC(EVP_PKEY_fromdata, [
# with EVP_PKEY_fromdata, check if EC is not disabled
AC_CHECK_DECL([OPENSSL_NO_EC], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])
], [], [AC_INCLUDES_DEFAULT
#include <openssl/evp.h>
])
], [
# without EVP_PKEY_fromdata, older openssl, check for support
AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])])
AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])])
])
AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT
#include <openssl/evp.h>
])
# see if OPENSSL 1.0.0 or later (has EVP MD and Verify independency)
AC_MSG_CHECKING([if openssl supports SHA2 and ECDSA with EVP])
if grep OPENSSL_VERSION_TEXT $ssldir_include/openssl/opensslv.h | grep "OpenSSL" >/dev/null; then
if grep OPENSSL_VERSION_NUMBER $ssldir_include/openssl/opensslv.h | grep 0x0 >/dev/null; then
if grep OPENSSL_VERSION_TEXT $ssldir_include/openssl/opensslv.h | grep "OpenSSL 0\." >/dev/null; then
AC_MSG_RESULT([no])
AC_DEFINE_UNQUOTED([USE_ECDSA_EVP_WORKAROUND], [1], [Define this to enable an EVP workaround for older openssl])
else
@@ -1515,6 +1667,76 @@ if test x_$withval = x_yes -o x_$withval != x_no; then
])
fi
# ngtcp2
AC_ARG_WITH(libngtcp2, AS_HELP_STRING([--with-libngtcp2=path],[specify explicit path for libngtcp2, for QUIC.]),
[ ],[ withval="no" ])
found_libngtcp2="no"
if test x_$withval = x_yes -o x_$withval != x_no; then
AC_MSG_CHECKING(for libngtcp2)
if test x_$withval = x_ -o x_$withval = x_yes; then
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
fi
for dir in $withval ; do
if test -f "$dir/include/ngtcp2/ngtcp2.h"; then
found_libngtcp2="yes"
dnl assume /usr is in default path.
if test "$dir" != "/usr"; then
CPPFLAGS="$CPPFLAGS -I$dir/include"
LDFLAGS="$LDFLAGS -L$dir/lib"
fi
AC_MSG_RESULT(found in $dir)
AC_DEFINE([HAVE_NGTCP2], [1], [Define this to use ngtcp2.])
LIBS="$LIBS -lngtcp2"
break;
fi
done
if test x_$found_libngtcp2 != x_yes; then
AC_MSG_ERROR([Could not find libngtcp2, ngtcp2.h])
fi
AC_CHECK_HEADERS([ngtcp2/ngtcp2.h ngtcp2/ngtcp2_crypto_ossl.h ngtcp2/ngtcp2_crypto_openssl.h ngtcp2/ngtcp2_crypto_quictls.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_DECLS([ngtcp2_conn_server_new], [], [], [AC_INCLUDES_DEFAULT
#include <ngtcp2/ngtcp2.h>
])
AC_CHECK_DECLS([ngtcp2_crypto_encrypt_cb], [], [], [AC_INCLUDES_DEFAULT
#include <ngtcp2/ngtcp2_crypto.h>
])
AC_CHECK_LIB([ngtcp2_crypto_ossl], [ngtcp2_crypto_encrypt_cb], [
LIBS="$LIBS -lngtcp2_crypto_ossl"
AC_DEFINE(USE_NGTCP2_CRYPTO_OSSL, 1, [Define this to use ngtcp2_crypto_ossl.])
], [
AC_CHECK_LIB([ngtcp2_crypto_openssl], [ngtcp2_crypto_encrypt_cb], [ LIBS="$LIBS -lngtcp2_crypto_openssl" ], [
AC_CHECK_LIB([ngtcp2_crypto_quictls], [ngtcp2_crypto_encrypt_cb], [ LIBS="$LIBS -lngtcp2_crypto_quictls" ])
])
])
AC_CHECK_FUNCS([ngtcp2_crypto_encrypt_cb ngtcp2_ccerr_default ngtcp2_conn_in_closing_period ngtcp2_conn_in_draining_period ngtcp2_conn_get_max_local_streams_uni ngtcp2_crypto_quictls_from_ossl_encryption_level ngtcp2_crypto_quictls_configure_server_context ngtcp2_crypto_quictls_configure_client_context ngtcp2_crypto_quictls_init ngtcp2_conn_get_num_scid ngtcp2_conn_tls_early_data_rejected ngtcp2_conn_encode_0rtt_transport_params])
# these check_funcs need -lssl
BAKLIBS="$LIBS"
LIBS="-lssl $LIBS"
AC_CHECK_FUNCS([SSL_is_quic], [], [AC_MSG_ERROR([No QUIC support detected in OpenSSL. Need OpenSSL version with QUIC support to enable DNS over QUIC with libngtcp2.])])
LIBS="$BAKLIBS"
AC_CHECK_TYPES([struct ngtcp2_version_cid, ngtcp2_encryption_level],,,[AC_INCLUDES_DEFAULT
#include <ngtcp2/ngtcp2.h>
])
AC_CHECK_MEMBERS([struct ngtcp2_pkt_hd.tokenlen, struct ngtcp2_settings.tokenlen, struct ngtcp2_settings.max_tx_udp_payload_size, struct ngtcp2_transport_params.original_dcid_present],,,[AC_INCLUDES_DEFAULT
#include <ngtcp2/ngtcp2.h>
])
AC_MSG_CHECKING([whether ngtcp2_conn_shutdown_stream has 4 arguments])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
#include <ngtcp2/ngtcp2.h>
],[
(void)ngtcp2_conn_shutdown_stream(NULL, 0, 0, 0);
])],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_NGTCP2_CONN_SHUTDOWN_STREAM4, 1, [Define if ngtcp2_conn_shutdown_stream has 4 arguments.])
],[
AC_MSG_RESULT(no)
])
fi
# set static linking for uninstalled libraries if requested
AC_SUBST(staticexe)
staticexe=""
@@ -1525,13 +1747,19 @@ if test x_$enable_static_exe = x_yes; then
if test "$on_mingw" = yes; then
staticexe="-all-static"
# for static compile, include gdi32 and zlib here.
if echo $LIBS | grep 'lgdi32' >/dev/null; then
if echo "$LIBS" | grep 'lgdi32' >/dev/null; then
:
else
LIBS="$LIBS -lgdi32"
fi
AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ])
LIBS="$LIBS -l:libssp.a"
if echo "$host" | $GREP -i -e linux >/dev/null; then
if echo "$LIBS" | grep -e "libssp.a" -e "lssp" >/dev/null; then
:
else
LIBS="$LIBS -l:libssp.a"
fi
fi
fi
fi
@@ -1548,7 +1776,13 @@ if test x_$enable_fully_static = x_yes; then
LIBS="$LIBS -lgdi32"
fi
AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ])
LIBS="$LIBS -l:libssp.a"
if echo "$host" | $GREP -i -e linux >/dev/null; then
if echo "$LIBS" | grep -e "libssp.a" -e "lssp" >/dev/null; then
:
else
LIBS="$LIBS -l:libssp.a"
fi
fi
fi
fi
@@ -1568,7 +1802,11 @@ if test "$USE_WINSOCK" = 1; then
#include <windows.h>
])
AC_CHECK_TOOL(WINDRES, windres)
LIBS="$LIBS -liphlpapi -lcrypt32"
if echo "$LIBS" | grep crypt32 >/dev/null; then
LIBS="$LIBS -liphlpapi"
else
LIBS="$LIBS -liphlpapi -lcrypt32"
fi
WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
AC_SUBST(WINAPPS)
WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
@@ -1602,6 +1840,7 @@ if test $ac_cv_func_daemon = yes; then
])
fi
AC_CHECK_MEMBERS([struct stat.st_mtimensec, struct stat.st_mtim.tv_nsec])
AC_CHECK_MEMBERS([struct sockaddr_un.sun_len],,,[
AC_INCLUDES_DEFAULT
#ifdef HAVE_SYS_UN_H
@@ -1680,6 +1919,25 @@ AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
if echo $host_os | grep darwin8 > /dev/null; then
AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work])
fi
AC_MSG_CHECKING([for atomic_store])
AC_LINK_IFELSE([AC_LANG_PROGRAM(AC_INCLUDES_DEFAULT [[
#ifdef HAVE_STDATOMIC_H
#include <stdatomic.h>
#endif
]], [[
int newvar = 5, var = 0;
atomic_store((_Atomic int*)&var, newvar);
newvar = 0;
/* condition to use the variables. */
if(var == newvar) return 1;
]])], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_LINK_ATOMIC_STORE, 1, [If we have atomic_store])
], [
AC_MSG_RESULT([no])
])
AC_CHECK_DECLS([inet_pton,inet_ntop], [], [], [
AC_INCLUDES_DEFAULT
#ifdef HAVE_NETINET_IN_H
@@ -1818,10 +2076,12 @@ if test x_$enable_lock_checks = x_yes; then
UBSYMS="-export-symbols clubsyms.def"
cp ${srcdir}/libunbound/ubsyms.def clubsyms.def
echo lock_protect >> clubsyms.def
echo lock_protect_place >> clubsyms.def
echo lock_unprotect >> clubsyms.def
echo lock_get_mem >> clubsyms.def
echo checklock_start >> clubsyms.def
echo checklock_stop >> clubsyms.def
echo checklock_set_output_name >> clubsyms.def
echo checklock_lock >> clubsyms.def
echo checklock_unlock >> clubsyms.def
echo checklock_init >> clubsyms.def
@@ -1902,15 +2162,17 @@ case "$enable_ipset" in
IPSET_OBJ="ipset.lo"
AC_SUBST(IPSET_OBJ)
# mnl
AC_ARG_WITH(libmnl, AS_HELP_STRING([--with-libmnl=path],[specify explicit path for libmnl.]),
# BSD's pf
AC_CHECK_HEADERS([net/pfvar.h], [], [
# mnl
AC_ARG_WITH(libmnl, AS_HELP_STRING([--with-libmnl=path],[specify explicit path for libmnl.]),
[ ],[ withval="yes" ])
found_libmnl="no"
AC_MSG_CHECKING(for libmnl)
if test x_$withval = x_ -o x_$withval = x_yes; then
found_libmnl="no"
AC_MSG_CHECKING(for libmnl)
if test x_$withval = x_ -o x_$withval = x_yes; then
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
fi
for dir in $withval ; do
fi
for dir in $withval ; do
if test -f "$dir/include/libmnl/libmnl.h" -o -f "$dir/include/libmnl/libmnl/libmnl.h"; then
found_libmnl="yes"
dnl assume /usr is in default path.
@@ -1928,10 +2190,14 @@ case "$enable_ipset" in
LIBS="$LIBS -lmnl"
break;
fi
done
if test x_$found_libmnl != x_yes; then
AC_MSG_ERROR([Could not find libmnl, libmnl.h])
fi
done
if test x_$found_libmnl != x_yes; then
AC_MSG_ERROR([Could not find libmnl, libmnl.h])
fi
], [
#include <netinet/in.h>
#include <net/if.h>
])
;;
no|*)
# nothing
@@ -2112,6 +2378,7 @@ dnl includes
AHX_CONFIG_FORMAT_ATTRIBUTE
AHX_CONFIG_UNUSED_ATTRIBUTE
AHX_CONFIG_NONSTRING_ATTRIBUTE
AHX_CONFIG_FSEEKO
AHX_CONFIG_MAXHOSTNAMELEN
#if !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN)
@@ -2249,6 +2516,10 @@ struct sockaddr_storage;
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__)
# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__)
# define strdup(s) unbound_stat_strdup_log(s, __FILE__, __LINE__, __func__)
#ifdef HAVE_REALLOCARRAY
# define reallocarray(p,n,s) unbound_stat_reallocarray_log(p, n, s, __FILE__, __LINE__, __func__)
#endif
void *unbound_stat_malloc(size_t size);
void *unbound_stat_calloc(size_t nmemb, size_t size);
void unbound_stat_free(void *ptr);
@@ -2261,6 +2532,10 @@ void unbound_stat_free_log(void *ptr, const char* file, int line,
const char* func);
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
int line, const char* func);
void *unbound_stat_reallocarray_log(void *ptr, size_t nmemb, size_t size,
const char* file, int line, const char* func);
char *unbound_stat_strdup_log(const char *s, const char* file, int line,
const char* func);
#elif defined(UNBOUND_ALLOC_LITE)
# include "util/alloc.h"
#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */
@@ -2271,6 +2546,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
#define UNBOUND_DNS_OVER_TLS_PORT 853
/** default port for DNS over HTTPS traffic. */
#define UNBOUND_DNS_OVER_HTTPS_PORT 443
/** default port for DNS over QUIC traffic. */
#define UNBOUND_DNS_OVER_QUIC_PORT 853
/** default port for unbound control traffic, registered port with IANA,
ub-dns-control 8953/tcp unbound dns nameserver control */
#define UNBOUND_CONTROL_PORT 8953
@@ -2282,7 +2559,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
dnl if we build from source tree, the man pages need @date@ and @version@
dnl if this is a distro tarball, that was already done by makedist.sh
AC_SUBST(version, [VERSION_MAJOR.VERSION_MINOR.VERSION_MICRO])
AC_SUBST(date, [`date +'%b %e, %Y'`])
AX_BUILD_DATE_EPOCH(date, [[%b %e, %Y]])
AC_SUBST(date)
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service contrib/unbound_portable.service])
AC_CONFIG_HEADERS([config.h])
+2
View File
@@ -58,3 +58,5 @@ distribution but may be helpful.
* unbound.init_yocto: An init script to start and stop the server. Put it
in /etc/init.d/unbound to use it. It is for the Yocto Project, in
embedded systems, contributed by beni-sandu.
* gost12.patch: adds ECC-GOST12 support for the informational RFC9558.
Contributed by Igor V. Ruzanov.
+50 -50
View File
@@ -1,10 +1,10 @@
diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
index 5a75e319..c6c6dbe2 100644
index 172eb26c..2921c87f 100644
--- a/doc/unbound.conf.5.in
+++ b/doc/unbound.conf.5.in
@@ -970,6 +970,13 @@ potentially broken nameservers. A lot of domains will not be resolvable when
this option in enabled. Only use if you know what you are doing.
This option only has effect when qname-minimisation is enabled. Default is no.
@@ -2146,6 +2146,13 @@ Default: no
.UNINDENT
.INDENT 0.0
.TP
+.B aaaa\-filter: \fI<yes or no>
+Activate behavior similar to BIND's AAAA-filter.
@@ -13,14 +13,14 @@ index 5a75e319..c6c6dbe2 100644
+This also causes an additional A query to be sent for each AAAA query.
+This breaks DNSSEC!
+.TP
.B aggressive\-nsec: \fI<yes or no>
Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
and other denials, using information from previous NXDOMAINs answers.
.B aggressive\-nsec: \fI<yes or no>\fP
Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN and other
denials, using information from previous NXDOMAINs answers.
diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c
index f093c1bf..e55a2246 100644
index 49a5f5da..fbe434fa 100644
--- a/iterator/iter_scrub.c
+++ b/iterator/iter_scrub.c
@@ -679,6 +679,32 @@ static int sanitize_nsec_is_overreach(sldns_buffer* pkt,
@@ -849,6 +849,32 @@ scrub_sanitize_rr_length(sldns_buffer* pkt, struct msg_parse* msg,
return 0;
}
@@ -53,15 +53,15 @@ index f093c1bf..e55a2246 100644
/**
* Given a response event, remove suspect RRsets from the response.
* "Suspect" rrsets are potentially poison. Note that this routine expects
@@ -698,6 +724,7 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
@@ -869,6 +895,7 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
struct iter_env* ie)
struct iter_env* ie, struct module_qstate* qstate)
{
+ int found_a_record = 0; /* ASN: do we have a A record? */
int del_addi = 0; /* if additional-holding rrsets are deleted, we
do not trust the normalized additional-A-AAAA any more */
struct rrset_parse* rrset, *prev;
@@ -733,6 +760,13 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
uint8_t* ns_rrset_dname = NULL;
@@ -906,6 +933,13 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
rrset = rrset->rrset_all_next;
}
@@ -75,9 +75,9 @@ index f093c1bf..e55a2246 100644
/* At this point, we brutally remove ALL rrsets that aren't
* children of the originating zone. The idea here is that,
* as far as we know, the server that we contacted is ONLY
@@ -744,6 +778,24 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
rrset = msg->rrset_first;
while(rrset) {
@@ -925,6 +959,24 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
continue;
}
+ /* ASN: For AAAA records only... */
+ if((ie->aaaa_filter) && (rrset->type == LDNS_RR_TYPE_AAAA)) {
@@ -101,10 +101,10 @@ index f093c1bf..e55a2246 100644
if( (rrset->type == LDNS_RR_TYPE_A ||
rrset->type == LDNS_RR_TYPE_AAAA)) {
diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
index 2482a1f4..bd5ba243 100644
index 1da21896..6583dd0e 100644
--- a/iterator/iter_utils.c
+++ b/iterator/iter_utils.c
@@ -177,6 +177,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
@@ -250,6 +250,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
iter_env->outbound_msg_retry = cfg->outbound_msg_retry;
iter_env->max_sent_count = cfg->max_sent_count;
iter_env->max_query_restarts = cfg->max_query_restarts;
@@ -113,12 +113,12 @@ index 2482a1f4..bd5ba243 100644
}
diff --git a/iterator/iterator.c b/iterator/iterator.c
index 54006940..768fe202 100644
index 71e64655..735f4ca0 100644
--- a/iterator/iterator.c
+++ b/iterator/iterator.c
@@ -2155,6 +2155,53 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
return 0;
@@ -2412,6 +2412,53 @@ check_waiting_queries(struct iter_qstate* iq, struct module_qstate* qstate,
qstate->ext_state[id] = module_wait_reply;
}
}
+
+/**
@@ -170,8 +170,8 @@ index 54006940..768fe202 100644
/**
* This is the request event state where the request will be sent to one of
@@ -2216,6 +2263,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
@@ -2554,6 +2601,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
}
}
+ /* ASN: If we have a AAAA query, then also query for A records */
@@ -184,7 +184,7 @@ index 54006940..768fe202 100644
/* Make sure we have a delegation point, otherwise priming failed
* or another failure occurred */
if(!iq->dp) {
@@ -3648,6 +3702,61 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
@@ -4178,6 +4232,61 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
return 0;
}
@@ -236,7 +236,7 @@ index 54006940..768fe202 100644
+ /* see if the failure did get (parent-lame) info */
+ if(!cache_fill_missing(super->env,
+ super_iq->qchase.qclass, super->region,
+ super_iq->dp))
+ super_iq->dp, 0))
+ log_err("ASN-AAAA-filter: out of memory adding missing");
+ dpns->resolved = 1; /* mark as failed */
+ }
@@ -246,7 +246,7 @@ index 54006940..768fe202 100644
/*
* Return priming query results to interested super querystates.
*
@@ -3667,6 +3776,9 @@ iter_inform_super(struct module_qstate* qstate, int id,
@@ -4197,6 +4306,9 @@ iter_inform_super(struct module_qstate* qstate, int id,
else if(super->qinfo.qtype == LDNS_RR_TYPE_DS && ((struct iter_qstate*)
super->minfo[id])->state == DSNS_FIND_STATE)
processDSNSResponse(qstate, id, super);
@@ -256,7 +256,7 @@ index 54006940..768fe202 100644
else if(qstate->return_rcode != LDNS_RCODE_NOERROR)
error_supers(qstate, id, super);
else if(qstate->is_priming)
@@ -3704,6 +3816,9 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq,
@@ -4234,6 +4346,9 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq,
case INIT_REQUEST_3_STATE:
cont = processInitRequest3(qstate, iq, id);
break;
@@ -266,7 +266,7 @@ index 54006940..768fe202 100644
case QUERYTARGETS_STATE:
cont = processQueryTargets(qstate, iq, ie, id);
break;
@@ -4040,6 +4155,8 @@ iter_state_to_string(enum iter_state state)
@@ -4578,6 +4693,8 @@ iter_state_to_string(enum iter_state state)
return "INIT REQUEST STATE (stage 2)";
case INIT_REQUEST_3_STATE:
return "INIT REQUEST STATE (stage 3)";
@@ -275,7 +275,7 @@ index 54006940..768fe202 100644
case QUERYTARGETS_STATE :
return "QUERY TARGETS STATE";
case PRIME_RESP_STATE :
@@ -4064,6 +4181,7 @@ iter_state_is_responsestate(enum iter_state s)
@@ -4602,6 +4719,7 @@ iter_state_is_responsestate(enum iter_state s)
case INIT_REQUEST_STATE :
case INIT_REQUEST_2_STATE :
case INIT_REQUEST_3_STATE :
@@ -284,10 +284,10 @@ index 54006940..768fe202 100644
case COLLECT_CLASS_STATE :
return 0;
diff --git a/iterator/iterator.h b/iterator/iterator.h
index 8b840528..a61c4195 100644
index ae4b4e45..a44f9d27 100644
--- a/iterator/iterator.h
+++ b/iterator/iterator.h
@@ -133,6 +133,9 @@ struct iter_env {
@@ -157,6 +157,9 @@ struct iter_env {
*/
int* target_fetch_policy;
@@ -297,7 +297,7 @@ index 8b840528..a61c4195 100644
/** lock on ratelimit counter */
lock_basic_type queries_ratelimit_lock;
/** number of queries that have been ratelimited */
@@ -187,6 +190,14 @@ enum iter_state {
@@ -217,6 +220,14 @@ enum iter_state {
*/
INIT_REQUEST_3_STATE,
@@ -312,9 +312,9 @@ index 8b840528..a61c4195 100644
/**
* Each time a delegation point changes for a given query or a
* query times out and/or wakes up, this state is (re)visited.
@@ -376,6 +387,13 @@ struct iter_qstate {
*/
int refetch_glue;
@@ -434,6 +445,13 @@ struct iter_qstate {
* already so that it is accepted later. */
int empty_nodata_found;
+ /**
+ * ASN: This is a flag that, if true, means that this query is
@@ -327,10 +327,10 @@ index 8b840528..a61c4195 100644
struct outbound_list outlist;
diff --git a/pythonmod/interface.i b/pythonmod/interface.i
index 1ca8686a..d91b19ec 100644
index 2040fb9e..f073c3dc 100644
--- a/pythonmod/interface.i
+++ b/pythonmod/interface.i
@@ -995,6 +995,7 @@ struct config_file {
@@ -1013,6 +1013,7 @@ struct config_file {
int harden_dnssec_stripped;
int harden_referral_path;
int use_caps_bits_for_id;
@@ -339,23 +339,23 @@ index 1ca8686a..d91b19ec 100644
struct config_strlist* private_domain;
size_t unwanted_threshold;
diff --git a/util/config_file.c b/util/config_file.c
index 969d664b..8d94b008 100644
index b1e767b3..5eb3c099 100644
--- a/util/config_file.c
+++ b/util/config_file.c
@@ -231,6 +231,7 @@ config_create(void)
cfg->harden_referral_path = 0;
@@ -247,6 +247,7 @@ config_create(void)
cfg->harden_algo_downgrade = 0;
cfg->harden_unknown_additional = 0;
cfg->use_caps_bits_for_id = 0;
+ cfg->aaaa_filter = 0; /* ASN: default is disabled */
cfg->caps_whitelist = NULL;
cfg->private_address = NULL;
cfg->private_domain = NULL;
diff --git a/util/config_file.h b/util/config_file.h
index c7c9a0a4..e3aa15b0 100644
index 44ac036b..1e59ab07 100644
--- a/util/config_file.h
+++ b/util/config_file.h
@@ -285,6 +285,8 @@ struct config_file {
int harden_algo_downgrade;
@@ -311,6 +311,8 @@ struct config_file {
int harden_unknown_additional;
/** use 0x20 bits in query as random ID bits */
int use_caps_bits_for_id;
+ /** ASN: enable AAAA filter? */
@@ -364,10 +364,10 @@ index c7c9a0a4..e3aa15b0 100644
struct config_strlist* caps_whitelist;
/** strip away these private addrs from answers, no DNS Rebinding */
diff --git a/util/configlexer.lex b/util/configlexer.lex
index 34a0e5dd..c890be2a 100644
index bc258673..76aab170 100644
--- a/util/configlexer.lex
+++ b/util/configlexer.lex
@@ -317,6 +317,7 @@ use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
@@ -327,6 +327,7 @@ use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
caps-whitelist{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
caps-exempt{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) }
@@ -376,10 +376,10 @@ index 34a0e5dd..c890be2a 100644
private-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) }
prefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) }
diff --git a/util/configparser.y b/util/configparser.y
index d4f965f9..8cc237c6 100644
index 82e1d878..dc19bed5 100644
--- a/util/configparser.y
+++ b/util/configparser.y
@@ -97,6 +97,7 @@ extern struct config_parser_state* cfg_parser;
@@ -100,6 +100,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT
%token VAR_OUTGOING_PORT_AVOID VAR_DLV_ANCHOR_FILE VAR_DLV_ANCHOR
%token VAR_NEG_CACHE_SIZE VAR_HARDEN_REFERRAL_PATH VAR_PRIVATE_ADDRESS
@@ -387,7 +387,7 @@ index d4f965f9..8cc237c6 100644
%token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE
%token VAR_CONTROL_INTERFACE VAR_CONTROL_PORT VAR_SERVER_KEY_FILE
%token VAR_SERVER_CERT_FILE VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE
@@ -247,6 +248,7 @@ content_server: server_num_threads | server_verbosity | server_port |
@@ -276,6 +277,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size |
server_harden_referral_path | server_private_address |
server_private_domain | server_extended_statistics |
@@ -395,7 +395,7 @@ index d4f965f9..8cc237c6 100644
server_local_data_ptr | server_jostle_timeout |
server_unwanted_reply_threshold | server_log_time_ascii |
server_domain_insecure | server_val_sig_skew_min |
@@ -1754,6 +1756,15 @@ server_caps_whitelist: VAR_CAPS_WHITELIST STRING_ARG
@@ -1932,6 +1934,15 @@ server_caps_whitelist: VAR_CAPS_WHITELIST STRING_ARG
yyerror("out of memory");
}
;
+7 -4
View File
@@ -1,21 +1,24 @@
#!/usr/bin/env bash
LIBEXPAT_FNAME=expat-2.7.0
LIBEXPAT_VERSION_DIR=R_2_7_0
echo "Downloading Expat"
if ! curl -L -k -s -o expat-2.2.9.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_9/expat-2.2.9.tar.gz;
if ! curl -L -k -s -o $LIBEXPAT_FNAME.tar.gz https://github.com/libexpat/libexpat/releases/download/$LIBEXPAT_VERSION_DIR/$LIBEXPAT_FNAME.tar.gz;
then
echo "Failed to download Expat"
exit 1
fi
echo "Unpacking Expat"
rm -rf ./expat-2.2.9
if ! tar -xf expat-2.2.9.tar.gz;
rm -rf ./$LIBEXPAT_FNAME
if ! tar -xf $LIBEXPAT_FNAME.tar.gz;
then
echo "Failed to unpack Expat"
exit 1
fi
cd expat-2.2.9 || exit 1
cd $LIBEXPAT_FNAME || exit 1
echo "Configuring Expat"
if ! ./configure --build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" --prefix="$ANDROID_PREFIX"; then
+325
View File
@@ -0,0 +1,325 @@
diff --git a/sldns/keyraw.c b/sldns/keyraw.c
index 42a9262a3..cc6406a56 100644
--- a/sldns/keyraw.c
+++ b/sldns/keyraw.c
@@ -85,7 +85,7 @@ sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
}
break;
#ifdef USE_GOST
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
return 512;
#endif
#ifdef USE_ECDSA
@@ -146,7 +146,7 @@ sldns_key_EVP_load_gost_id(void)
if(gost_id) return gost_id;
/* see if configuration loaded gost implementation from other engine*/
- meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
+ meth = EVP_PKEY_asn1_find_str(NULL, "gost2012_256", -1);
if(meth) {
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
return gost_id;
@@ -170,7 +170,7 @@ sldns_key_EVP_load_gost_id(void)
return 0;
}
- meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
+ meth = EVP_PKEY_asn1_find_str(&e, "gost2012_256", -1);
if(!meth) {
/* algo not found */
ENGINE_finish(e);
@@ -536,12 +536,17 @@ EVP_PKEY* sldns_key_rsa2pkey_raw(unsigned char* key, size_t len)
EVP_PKEY*
sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
{
- /* prefix header for X509 encoding */
- uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
- 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
- 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
- 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
- unsigned char encoded[37+64];
+ /* prefix header for X509 encoding
+ *
+ * note: based on draft-makarenko-gost2012-dnssec-01 (pre-RFC9558 and it DOES work!)
+ * ASN1 header described in RFC9558 is not suitable due to d2i_PUBKEY() works with
+ * non-compressed public keys (two additional bytes 0x04, 0x40 at the end of header)
+ */
+ uint8_t asn[32] = { 0x30, 0x5e, 0x30, 0x17, 0x06, 0x08, 0x2a, 0x85,
+ 0x03, 0x07, 0x01, 0x01, 0x01, 0x01, 0x30, 0x0b,
+ 0x06, 0x09, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x02,
+ 0x01, 0x01, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40 };
+ unsigned char encoded[32+64];
const unsigned char* pp;
if(keylen != 64) {
/* key wrong size */
@@ -549,8 +554,8 @@ sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
}
/* create evp_key */
- memmove(encoded, asn, 37);
- memmove(encoded+37, key, 64);
+ memmove(encoded, asn, 32);
+ memmove(encoded+32, key, 64);
pp = (unsigned char*)&encoded[0];
return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
diff --git a/sldns/rrdef.h b/sldns/rrdef.h
index bbc3d5b86..7d5f3c057 100644
--- a/sldns/rrdef.h
+++ b/sldns/rrdef.h
@@ -384,11 +384,12 @@ enum sldns_enum_algorithm
LDNS_RSASHA1_NSEC3 = 7,
LDNS_RSASHA256 = 8, /* RFC 5702 */
LDNS_RSASHA512 = 10, /* RFC 5702 */
- LDNS_ECC_GOST = 12, /* RFC 5933 */
+ LDNS_ECC_GOST = 12, /* RFC 5933, deprecated */
LDNS_ECDSAP256SHA256 = 13, /* RFC 6605 */
LDNS_ECDSAP384SHA384 = 14, /* RFC 6605 */
LDNS_ED25519 = 15, /* RFC 8080 */
LDNS_ED448 = 16, /* RFC 8080 */
+ LDNS_ECC_GOST12 = 23, /* RFC 9558 */
LDNS_INDIRECT = 252,
LDNS_PRIVATEDNS = 253,
LDNS_PRIVATEOID = 254
@@ -402,8 +403,9 @@ enum sldns_enum_hash
{
LDNS_SHA1 = 1, /* RFC 4034 */
LDNS_SHA256 = 2, /* RFC 4509 */
- LDNS_HASH_GOST = 3, /* RFC 5933 */
- LDNS_SHA384 = 4 /* RFC 6605 */
+ LDNS_HASH_GOST = 3, /* RFC 5933, deprecated */
+ LDNS_SHA384 = 4, /* RFC 6605 */
+ LDNS_HASH_GOST12 = 5 /* RFC 9558 */
};
typedef enum sldns_enum_hash sldns_hash;
diff --git a/sldns/wire2str.c b/sldns/wire2str.c
index 75b8f37b0..b4c4755e6 100644
--- a/sldns/wire2str.c
+++ b/sldns/wire2str.c
@@ -45,11 +45,12 @@ static sldns_lookup_table sldns_algorithms_data[] = {
{ LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
{ LDNS_RSASHA256, "RSASHA256"},
{ LDNS_RSASHA512, "RSASHA512"},
- { LDNS_ECC_GOST, "ECC-GOST"},
+ { LDNS_ECC_GOST, "ECC-GOST"}, /* deprecated */
{ LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
{ LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
{ LDNS_ED25519, "ED25519"},
{ LDNS_ED448, "ED448"},
+ { LDNS_ECC_GOST12, "ECC-GOST12"},
{ LDNS_INDIRECT, "INDIRECT" },
{ LDNS_PRIVATEDNS, "PRIVATEDNS" },
{ LDNS_PRIVATEOID, "PRIVATEOID" },
@@ -61,8 +62,9 @@ sldns_lookup_table* sldns_algorithms = sldns_algorithms_data;
static sldns_lookup_table sldns_hashes_data[] = {
{ LDNS_SHA1, "SHA1" },
{ LDNS_SHA256, "SHA256" },
- { LDNS_HASH_GOST, "HASH-GOST" },
+ { LDNS_HASH_GOST, "HASH-GOST" }, /* deprecated */
{ LDNS_SHA384, "SHA384" },
+ { LDNS_HASH_GOST12, "HASH-GOST12" },
{ 0, NULL }
};
sldns_lookup_table* sldns_hashes = sldns_hashes_data;
diff --git a/testcode/unitverify.c b/testcode/unitverify.c
index fcf2e2ffe..4a33e9f6a 100644
--- a/testcode/unitverify.c
+++ b/testcode/unitverify.c
@@ -696,7 +696,7 @@ verify_test(void)
#endif
#ifdef USE_GOST
if(sldns_key_EVP_load_gost_id())
- verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost", "20090807060504");
+ verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost12", "20251226060504");
else printf("Warning: skipped GOST, openssl does not provide gost.\n");
#endif
#ifdef USE_ECDSA
diff --git a/testdata/test_sigs.gost12 b/testdata/test_sigs.gost12
new file mode 100644
index 000000000..72a250cff
--- /dev/null
+++ b/testdata/test_sigs.gost12
@@ -0,0 +1,39 @@
+; Signature test file
+
+; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification.
+; later entries are verified with it.
+
+; Test GOST signatures using algo number 23.
+
+ENTRY_BEGIN
+SECTION QUESTION
+nlnetlabs.nl. IN DNSKEY
+SECTION ANSWER
+nlnetlabs.nl. 3600 IN DNSKEY 256 3 23 cdOtkEcb6NhcdOpIbPYtWyWxdlUiKgtKQbYg3lIjtG7i3fYjUID9zyOgoQEiV9wuGCfrw5cNsnvNw+8HiVFK4g== ;{id = 12301 (zsk), size = 512b}
+ENTRY_END
+
+; entry to test
+ENTRY_BEGIN
+SECTION QUESTION
+open.nlnetlabs.nl. IN A
+SECTION ANSWER
+open.nlnetlabs.nl. 600 IN A 213.154.224.1
+open.nlnetlabs.nl. 600 IN RRSIG A 23 3 600 20260122084903 20251225084903 12301 nlnetlabs.nl. I12wYNs96DxMy26CWx296/sWMJAFg4nNXBo0sw7PnuMbJW5NFAmZYtFWhUdOWn4umaiodYOAmKG8Zg/OKvEtAQ==
+ENTRY_END
+
+ENTRY_BEGIN
+SECTION QUESTION
+open.nlnetlabs.nl. IN AAAA
+SECTION ANSWER
+open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::1
+open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::53
+open.nlnetlabs.nl. 600 IN RRSIG AAAA 23 3 600 20260122084903 20251225084903 12301 nlnetlabs.nl. J0jHa+CP8HM6UDa2+uYgaze2mfpJTh2hkZ2KwMTYb5sfL6iBmxxql0c/403Itk4fMfYBMGn7zfzDQ+CxnCgSWw==
+ENTRY_END
+
+ENTRY_BEGIN
+SECTION QUESTION
+open.nlnetlabs.nl. IN NSEC
+SECTION ANSWER
+open.nlnetlabs.nl. 86400 IN NSEC nlnetlabs.nl. A AAAA RRSIG NSEC
+open.nlnetlabs.nl. 86400 IN RRSIG NSEC 23 3 86400 20260122084903 20251225084903 12301 nlnetlabs.nl. INCLYe9vAaNYaYx5Ay3Q6QdX+wPW9sMRvVlGt/jUEGgCi+88QlV80CT1oHrhRI66I14Wk6NRAGZRNx1tUPSHSg==
+ENTRY_END
diff --git a/validator/val_secalgo.c b/validator/val_secalgo.c
index be8347b1b..4f621a309 100644
--- a/validator/val_secalgo.c
+++ b/validator/val_secalgo.c
@@ -246,10 +246,10 @@ ds_digest_size_supported(int algo)
return SHA256_DIGEST_LENGTH;
#endif
#ifdef USE_GOST
- case LDNS_HASH_GOST:
+ case LDNS_HASH_GOST12:
/* we support GOST if it can be loaded */
(void)sldns_key_EVP_load_gost_id();
- if(EVP_get_digestbyname("md_gost94"))
+ if(EVP_get_digestbyname("md_gost12_256"))
return 32;
else return 0;
#endif
@@ -265,9 +265,9 @@ ds_digest_size_supported(int algo)
#ifdef USE_GOST
/** Perform GOST hash */
static int
-do_gost94(unsigned char* data, size_t len, unsigned char* dest)
+do_gost12(unsigned char* data, size_t len, unsigned char* dest)
{
- const EVP_MD* md = EVP_get_digestbyname("md_gost94");
+ const EVP_MD* md = EVP_get_digestbyname("md_gost12_256");
if(!md)
return 0;
return sldns_digest_evp(data, (unsigned int)len, dest, md);
@@ -302,8 +302,8 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
return 1;
#endif
#ifdef USE_GOST
- case LDNS_HASH_GOST:
- if(do_gost94(buf, len, res))
+ case LDNS_HASH_GOST12:
+ if(do_gost12(buf, len, res))
return 1;
break;
#endif
@@ -384,7 +384,7 @@ dnskey_algo_id_is_supported(int id)
#endif
#ifdef USE_GOST
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
/* we support GOST if it can be loaded */
return sldns_key_EVP_load_gost_id();
#endif
@@ -612,17 +612,17 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
break;
#ifdef USE_GOST
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
*evp_key = sldns_gost2pkey_raw(key, keylen);
if(!*evp_key) {
verbose(VERB_QUERY, "verify: "
"sldns_gost2pkey_raw failed");
return 0;
}
- *digest_type = EVP_get_digestbyname("md_gost94");
+ *digest_type = EVP_get_digestbyname("md_gost12_256");
if(!*digest_type) {
verbose(VERB_QUERY, "verify: "
- "EVP_getdigest md_gost94 failed");
+ "EVP_getdigest md_gost12_256 failed");
return 0;
}
break;
@@ -964,7 +964,7 @@ ds_digest_size_supported(int algo)
return SHA384_LENGTH;
#endif
/* GOST not supported in NSS */
- case LDNS_HASH_GOST:
+ case LDNS_HASH_GOST12:
default: break;
}
return 0;
@@ -991,7 +991,7 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
return HASH_HashBuf(HASH_AlgSHA384, res, buf, len)
== SECSuccess;
#endif
- case LDNS_HASH_GOST:
+ case LDNS_HASH_GOST12:
default:
verbose(VERB_QUERY, "unknown DS digest algorithm %d",
algo);
@@ -1031,7 +1031,7 @@ dnskey_algo_id_is_supported(int id)
case LDNS_ECDSAP384SHA384:
return PK11_TokenExists(CKM_ECDSA);
#endif
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
default:
return 0;
}
@@ -1352,7 +1352,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
/* no prefix for DSA verification */
break;
#endif /* USE_ECDSA */
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
default:
verbose(VERB_QUERY, "verify: unknown algorithm %d",
algo);
@@ -1675,7 +1675,7 @@ ds_digest_size_supported(int algo)
return SHA384_DIGEST_SIZE;
#endif
/* GOST not supported */
- case LDNS_HASH_GOST:
+ case LDNS_ECC_GOST12:
default:
break;
}
@@ -1700,7 +1700,7 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res);
#endif
- case LDNS_HASH_GOST:
+ case LDNS_ECC_GOST12:
default:
verbose(VERB_QUERY, "unknown DS digest algorithm %d",
algo);
@@ -1744,7 +1744,7 @@ dnskey_algo_id_is_supported(int id)
return 1;
#endif
case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
default:
return 0;
}
@@ -2103,7 +2103,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_secure;
#endif
case LDNS_RSAMD5:
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
default:
*reason = "unable to verify signature, unknown algorithm";
return sec_status_bogus;
+11 -7
View File
@@ -1,28 +1,32 @@
#!/usr/bin/env bash
LIBEXPAT_FNAME=expat-2.7.0
LIBEXPAT_VERSION_DIR=R_2_7_0
echo "Downloading Expat"
if ! curl -L -k -s -o expat-2.2.9.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_9/expat-2.2.9.tar.gz;
if ! curl -L -k -s -o $LIBEXPAT_FNAME.tar.gz https://github.com/libexpat/libexpat/releases/download/$LIBEXPAT_VERSION_DIR/$LIBEXPAT_FNAME.tar.gz;
then
echo "Failed to download Expat"
exit 1
fi
echo "Unpacking Expat"
rm -rf ./expat-2.2.9
if ! tar -xf expat-2.2.9.tar.gz;
rm -rf ./$LIBEXPAT_FNAME
if ! tar -xf $LIBEXPAT_FNAME.tar.gz;
then
echo "Failed to unpack Expat"
exit 1
fi
cd expat-2.2.9 || exit 1
cd $LIBEXPAT_FNAME || exit 1
export PKG_CONFIG_PATH="$IOS_PREFIX/lib/pkgconfig"
echo "Configuring Expat"
if ! ./configure \
--build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" \
--prefix="$IOS_PREFIX" ; then
if ! ./configure --without-tests \
--build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" \
--prefix="$IOS_PREFIX" ;
then
echo "Error: Failed to configure Expat"
cat config.log
exit 1
+7 -5
View File
@@ -1,21 +1,22 @@
#!/usr/bin/env bash
OPENSSL_VERSION=1.1.1d
echo "Downloading OpenSSL"
if ! curl -L -k -s -o openssl-1.1.1d.tar.gz https://www.openssl.org/source/openssl-1.1.1d.tar.gz;
if ! curl -L -k -s -o openssl-$OPENSSL_VERSION.tar.gz https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz;
then
echo "Failed to download OpenSSL"
exit 1
fi
echo "Unpacking OpenSSL"
rm -rf ./openssl-1.1.1d
if ! tar -xf openssl-1.1.1d.tar.gz;
rm -rf ./openssl-$OPENSSL_VERSION
if ! tar -xf openssl-$OPENSSL_VERSION.tar.gz;
then
echo "Failed to unpack OpenSSL"
exit 1
fi
cd openssl-1.1.1d || exit 1
cd openssl-$OPENSSL_VERSION || exit 1
if ! cp ../contrib/ios/15-ios.conf Configurations/; then
echo "Failed to copy OpenSSL ios config"
@@ -27,7 +28,8 @@ fi
# Also see https://github.com/openssl/openssl/issues/7607.
if ! patch -u -p0 < ../contrib/ios/openssl.patch; then
echo "Failed to patch OpenSSL"
exit 1
# the partial patch may be useful.
#exit 1
fi
echo "Configuring OpenSSL"
+5
View File
@@ -175,6 +175,7 @@ fi
# For example, remove 4.3, 6.2, and 6.1 if they are not installed. We go back to
# the 1.0 SDKs because Apple WatchOS uses low numbers, like 2.0 and 2.1.
XCODE_SDK=
if test -z "$SDK_VERSION"; then
for i in $(seq -f "%.1f" 30.0 -0.1 1.0)
do
if [ -d "$XCODE_DEVELOPER_SDK/Developer/SDKs/$IOS_SDK$i.sdk" ]; then
@@ -182,6 +183,10 @@ do
break
fi
done
else
i="$SDK_VERSION"
XCODE_SDK="$IOS_SDK$i.sdk"
fi
# Error checking
if [ -z "$XCODE_SDK" ]; then
+9
View File
@@ -22,4 +22,13 @@ pidfile=${unbound_pidfile:-"/usr/local/etc/unbound/unbound.pid"}
command_args=${unbound_flags:-"-c /usr/local/etc/unbound/unbound.conf"}
extra_commands="reload"
if test "$1" = "stop" ; then
run_rc_command "$1"
ret=$?
if test $ret -eq 0; then
rm -f "$pidfile"
fi
exit $ret
fi
run_rc_command "$1"
+1
View File
@@ -75,6 +75,7 @@ stop() {
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
[ $retval -eq 0 ] && rm -f $pidfile
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
umount ${rootdir}/dev/log >/dev/null 2>&1
fi;
+1
View File
@@ -58,6 +58,7 @@ stop() {
killproc -p $pidfile unbound
retval=$?
[ $retval -eq 0 ] && rm -f $lockfile
[ $retval -eq 0 ] && rm -f $pidfile
for mountfile in /dev/log /dev/urandom /etc/localtime /etc/resolv.conf /var/run/unbound
do
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}''${mountfile}'' /proc/mounts; then
+1
View File
@@ -75,6 +75,7 @@ stop() {
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
[ $retval -eq 0 ] && rm -f $pidfile
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
umount ${rootdir}/dev/log >/dev/null 2>&1
fi;
+9 -3
View File
@@ -38,12 +38,18 @@
; - `LockPersonality=yes` locks down the personality system call so that the
; kernel execution domain may not be changed from the default.
;
; - With /etc/systemd/network/*.network a setting to make sure the network
; is not considered online too early, can reduce network unreachable
; errors on server start:
; [Link]
; RequiredForOnline=routable
;
[Unit]
Description=Validating, recursive, and caching DNS resolver
Documentation=man:unbound(8)
After=network.target
Before=network-online.target nss-lookup.target
After=network-online.target
Wants=network-online.target
Before=nss-lookup.target
[Install]
WantedBy=multi-user.target
@@ -53,7 +59,7 @@ ExecReload=+/bin/kill -HUP $MAINPID
ExecStart=@UNBOUND_SBIN_DIR@/unbound -d -p
NotifyAccess=main
Type=notify
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_RAW
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_ADMIN
MemoryDenyWriteExecute=true
NoNewPrivileges=true
PrivateDevices=true
+3 -3
View File
@@ -14,8 +14,8 @@
[Unit]
Description=Validating, recursive, and caching DNS resolver
Documentation=man:unbound(8)
After=network.target
Before=network-online.target nss-lookup.target
After=network-online.target
Before=nss-lookup.target
Wants=nss-lookup.target
[Install]
@@ -26,7 +26,7 @@ ExecReload=+/bin/kill -HUP $MAINPID
ExecStart=@UNBOUND_SBIN_DIR@/unbound -d -p
NotifyAccess=main
Type=notify
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_RAW
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_ADMIN
MemoryDenyWriteExecute=true
NoNewPrivileges=true
PrivateDevices=true
+17 -13
View File
@@ -221,7 +221,9 @@ acl_interface_insert(struct acl_list* acl_interface,
struct sockaddr_storage* addr, socklen_t addrlen,
enum acl_access control)
{
return acl_find_or_create(acl_interface, addr, addrlen, control);
struct acl_addr* node = acl_find_or_create(acl_interface, addr, addrlen, control);
node->is_interface = 1;
return node;
}
/** apply acl_tag string */
@@ -551,17 +553,6 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
return 1;
}
int
acl_interface_compare(const void* k1, const void* k2)
{
struct addr_tree_node* n1 = (struct addr_tree_node*)k1;
struct addr_tree_node* n2 = (struct addr_tree_node*)k2;
return sockaddr_cmp(&n1->addr, n1->addrlen, &n2->addr,
n2->addrlen);
/* We don't care about comparing node->net. All addresses in the
* acl_interface tree have either 32 (ipv4) or 128 (ipv6). */
}
void
acl_interface_init(struct acl_list* acl_interface)
{
@@ -816,10 +807,23 @@ log_acl_action(const char* action, struct sockaddr_storage* addr,
addr_to_str(&acladdr->node.addr, acladdr->node.addrlen,
n, sizeof(n));
verbose(VERB_ALGO, "%s query from %s port %d because of "
"%s/%d %s", action, a, (int)port, n, acladdr->node.net,
"%s/%d %s%s", action, a, (int)port, n,
acladdr->node.net,
acladdr->is_interface?"(ACL on interface IP) ":"",
acl_access_to_str(acl));
} else {
verbose(VERB_ALGO, "%s query from %s port %d", action, a,
(int)port);
}
}
void acl_list_swap_tree(struct acl_list* acl, struct acl_list* data)
{
/* swap tree and region */
rbtree_type oldtree = acl->tree;
struct regional* oldregion = acl->region;
acl->tree = data->tree;
acl->region = data->region;
data->tree = oldtree;
data->region = oldregion;
}
+10 -3
View File
@@ -107,6 +107,8 @@ struct acl_addr {
struct config_strlist** tag_datas;
/** size of the tag_datas array */
size_t tag_datas_size;
/* If the acl node is for an interface */
int is_interface;
/* view element, NULL if none */
struct view* view;
};
@@ -147,9 +149,6 @@ acl_interface_insert(struct acl_list* acl_interface,
int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
struct views* v);
/** compare ACL interface "addr_tree" nodes (+port) */
int acl_interface_compare(const void* k1, const void* k2);
/**
* Initialise (also clean) the acl_interface struct.
* @param acl_interface: where to store.
@@ -202,4 +201,12 @@ const char* acl_access_to_str(enum acl_access acl);
void log_acl_action(const char* action, struct sockaddr_storage* addr,
socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr);
/**
* Swap internal tree with preallocated entries.
* @param acl: the acl structure.
* @param data: the data structure used to take elements from. This contains
* the old elements on return.
*/
void acl_list_swap_tree(struct acl_list* acl, struct acl_list* data);
#endif /* DAEMON_ACL_LIST_H */
+252 -114
View File
@@ -62,84 +62,231 @@
#include "sldns/wire2str.h"
#include "sldns/str2wire.h"
static void spool_txt_printf(struct config_strlist_head* txt,
const char* format, ...) ATTR_FORMAT(printf, 2, 3);
/** Append to strlist at end, and log error if out of memory. */
static void
spool_txt_string(struct config_strlist_head* txt, char* str)
{
if(!cfg_strlist_append(txt, strdup(str))) {
log_err("out of memory in spool text");
}
}
/** Spool txt to spool list. */
static void
spool_txt_vmsg(struct config_strlist_head* txt, const char* format,
va_list args)
{
char msg[65535];
vsnprintf(msg, sizeof(msg), format, args);
spool_txt_string(txt, msg);
}
/** Print item to spool list. On alloc failure the list is as before. */
static void
spool_txt_printf(struct config_strlist_head* txt, const char* format, ...)
{
va_list args;
va_start(args, format);
spool_txt_vmsg(txt, format, args);
va_end(args);
}
/** dump one rrset zonefile line */
static int
dump_rrset_line(RES* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
static void
dump_rrset_line(struct config_strlist_head* txt, struct ub_packed_rrset_key* k,
time_t now, size_t i)
{
char s[65535];
if(!packed_rr_to_string(k, i, now, s, sizeof(s))) {
return ssl_printf(ssl, "BADRR\n");
spool_txt_string(txt, "BADRR\n");
return;
}
return ssl_printf(ssl, "%s", s);
spool_txt_string(txt, s);
}
/** dump rrset key and data info */
static int
dump_rrset(RES* ssl, struct ub_packed_rrset_key* k,
static void
dump_rrset(struct config_strlist_head* txt, struct ub_packed_rrset_key* k,
struct packed_rrset_data* d, time_t now)
{
size_t i;
/* rd lock held by caller */
if(!k || !d) return 1;
if(k->id == 0) return 1; /* deleted */
if(d->ttl < now) return 1; /* expired */
if(!k || !d) return;
if(k->id == 0) return; /* deleted */
if(d->ttl < now) return; /* expired */
/* meta line */
if(!ssl_printf(ssl, ";rrset%s " ARG_LL "d %u %u %d %d\n",
spool_txt_printf(txt, ";rrset%s " ARG_LL "d %u %u %d %d\n",
(k->rk.flags & PACKED_RRSET_NSEC_AT_APEX)?" nsec_apex":"",
(long long)(d->ttl - now),
(unsigned)d->count, (unsigned)d->rrsig_count,
(int)d->trust, (int)d->security
))
return 0;
);
for(i=0; i<d->count + d->rrsig_count; i++) {
if(!dump_rrset_line(ssl, k, now, i))
dump_rrset_line(txt, k, now, i);
}
}
/** Spool strlist to the output. */
static int
spool_strlist(RES* ssl, struct config_strlist* list)
{
struct config_strlist* s;
for(s=list; s; s=s->next) {
if(!ssl_printf(ssl, "%s", s->str))
return 0;
}
return 1;
}
/** dump lruhash rrset cache */
/** dump lruhash cache and call callback for every item. */
static int
dump_rrset_lruhash(RES* ssl, struct lruhash* h, time_t now)
dump_lruhash(struct lruhash* table,
void (*func)(struct lruhash_entry*, struct config_strlist_head*, void*),
RES* ssl, void* arg)
{
struct lruhash_entry* e;
/* lruhash already locked by caller */
/* walk in order of lru; best first */
for(e=h->lru_start; e; e = e->lru_next) {
lock_rw_rdlock(&e->lock);
if(!dump_rrset(ssl, (struct ub_packed_rrset_key*)e->key,
(struct packed_rrset_data*)e->data, now)) {
lock_rw_unlock(&e->lock);
int just_started = 1;
int not_done = 1;
hashvalue_type hash;
size_t num = 0; /* number of entries processed. */
size_t max = 2; /* number of entries after which it unlocks. */
struct config_strlist_head txt; /* Text strings spooled. */
memset(&txt, 0, sizeof(txt));
while(not_done) {
size_t i; /* hash bin. */
/* Process a number of items. */
num = 0;
lock_quick_lock(&table->lock);
if(just_started) {
i = 0;
} else {
i = hash&table->size_mask;
}
while(num < max) {
/* Process bin. */
int found = 0;
size_t num_bin = 0;
struct lruhash_bin* bin = &table->array[i];
struct lruhash_entry* e;
lock_quick_lock(&bin->lock);
for(e = bin->overflow_list; e; e = e->overflow_next) {
/* Entry e is locked by the func. */
func(e, &txt, arg);
num_bin++;
}
lock_quick_unlock(&bin->lock);
/* This addition of bin number of entries may take
* it over the max. */
num += num_bin;
/* Move to next bin. */
/* Find one with an entry, with a hash value, so we
* can continue from the hash value. The hash value
* can be indexed also if the array changes size. */
i++;
while(i < table->size) {
bin = &table->array[i];
lock_quick_lock(&bin->lock);
if(bin->overflow_list) {
hash = bin->overflow_list->hash;
lock_quick_unlock(&bin->lock);
found = 1;
just_started = 0;
break;
}
lock_quick_unlock(&bin->lock);
i++;
}
if(!found) {
not_done = 0;
break;
}
}
lock_quick_unlock(&table->lock);
/* Print the spooled items, that are collected while the
* locks are locked. The print happens while they are not
* locked. */
if(txt.first) {
if(!spool_strlist(ssl, txt.first)) {
config_delstrlist(txt.first);
return 0;
}
config_delstrlist(txt.first);
memset(&txt, 0, sizeof(txt));
}
}
/* Print the final spooled items. */
if(txt.first) {
if(!spool_strlist(ssl, txt.first)) {
config_delstrlist(txt.first);
return 0;
}
lock_rw_unlock(&e->lock);
config_delstrlist(txt.first);
}
return 1;
}
/** dump slabhash cache and call callback for every item. */
static int
dump_slabhash(struct slabhash* sh,
void (*func)(struct lruhash_entry*, struct config_strlist_head*, void*),
RES* ssl, void* arg)
{
/* Process a number of items at a time, then unlock the cache,
* so that ordinary processing can continue. Keep an iteration marker
* to continue the loop. That means the cache can change, items
* could be inserted and deleted. And, for example, the hash table
* can grow. */
size_t slab;
for(slab=0; slab<sh->size; slab++) {
if(!dump_lruhash(sh->array[slab], func, ssl, arg))
return 0;
}
return 1;
}
/** Struct for dump information. */
struct dump_info {
/** The worker. */
struct worker* worker;
/** The printout connection. */
RES* ssl;
};
/** Dump the rrset cache entry */
static void
dump_rrset_entry(struct lruhash_entry* e, struct config_strlist_head* txt,
void* arg)
{
struct dump_info* dump_info = (struct dump_info*)arg;
lock_rw_rdlock(&e->lock);
dump_rrset(txt, (struct ub_packed_rrset_key*)e->key,
(struct packed_rrset_data*)e->data,
*dump_info->worker->env.now);
lock_rw_unlock(&e->lock);
}
/** dump rrset cache */
static int
dump_rrset_cache(RES* ssl, struct worker* worker)
{
struct rrset_cache* r = worker->env.rrset_cache;
size_t slab;
struct dump_info dump_info;
dump_info.worker = worker;
dump_info.ssl = ssl;
if(!ssl_printf(ssl, "START_RRSET_CACHE\n")) return 0;
for(slab=0; slab<r->table.size; slab++) {
lock_quick_lock(&r->table.array[slab]->lock);
if(!dump_rrset_lruhash(ssl, r->table.array[slab],
*worker->env.now)) {
lock_quick_unlock(&r->table.array[slab]->lock);
return 0;
}
lock_quick_unlock(&r->table.array[slab]->lock);
}
if(!dump_slabhash(&r->table, &dump_rrset_entry, ssl, &dump_info))
return 0;
return ssl_printf(ssl, "END_RRSET_CACHE\n");
}
/** dump message to rrset reference */
static int
dump_msg_ref(RES* ssl, struct ub_packed_rrset_key* k)
static void
dump_msg_ref(struct config_strlist_head* txt, struct ub_packed_rrset_key* k)
{
char* nm, *tp, *cl;
nm = sldns_wire2str_dname(k->rk.dname, k->rk.dname_len);
@@ -149,30 +296,25 @@ dump_msg_ref(RES* ssl, struct ub_packed_rrset_key* k)
free(nm);
free(tp);
free(cl);
return ssl_printf(ssl, "BADREF\n");
}
if(!ssl_printf(ssl, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags)) {
free(nm);
free(tp);
free(cl);
return 0;
spool_txt_string(txt, "BADREF\n");
return;
}
spool_txt_printf(txt, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags);
free(nm);
free(tp);
free(cl);
return 1;
}
/** dump message entry */
static int
dump_msg(RES* ssl, struct query_info* k, struct reply_info* d, time_t now)
static void
dump_msg(struct config_strlist_head* txt, struct query_info* k,
struct reply_info* d, time_t now)
{
size_t i;
char* nm, *tp, *cl;
if(!k || !d) return 1;
if(d->ttl < now) return 1; /* expired */
if(!k || !d) return;
if(d->ttl < now) return; /* expired */
nm = sldns_wire2str_dname(k->qname, k->qname_len);
tp = sldns_wire2str_type(k->qtype);
cl = sldns_wire2str_class(k->qclass);
@@ -180,45 +322,35 @@ dump_msg(RES* ssl, struct query_info* k, struct reply_info* d, time_t now)
free(nm);
free(tp);
free(cl);
return 1; /* skip this entry */
return; /* skip this entry */
}
if(!rrset_array_lock(d->ref, d->rrset_count, now)) {
/* rrsets have timed out or do not exist */
free(nm);
free(tp);
free(cl);
return 1; /* skip this entry */
return; /* skip this entry */
}
/* meta line */
if(!ssl_printf(ssl, "msg %s %s %s %d %d " ARG_LL "d %d %u %u %u %d %s\n",
nm, cl, tp,
(int)d->flags, (int)d->qdcount,
(long long)(d->ttl-now), (int)d->security,
(unsigned)d->an_numrrsets,
(unsigned)d->ns_numrrsets,
(unsigned)d->ar_numrrsets,
(int)d->reason_bogus,
d->reason_bogus_str?d->reason_bogus_str:"")) {
free(nm);
free(tp);
free(cl);
rrset_array_unlock(d->ref, d->rrset_count);
return 0;
}
spool_txt_printf(txt,
"msg %s %s %s %d %d " ARG_LL "d %d %u %u %u %d %s\n",
nm, cl, tp,
(int)d->flags, (int)d->qdcount,
(long long)(d->ttl-now), (int)d->security,
(unsigned)d->an_numrrsets,
(unsigned)d->ns_numrrsets,
(unsigned)d->ar_numrrsets,
(int)d->reason_bogus,
d->reason_bogus_str?d->reason_bogus_str:"");
free(nm);
free(tp);
free(cl);
for(i=0; i<d->rrset_count; i++) {
if(!dump_msg_ref(ssl, d->rrsets[i])) {
rrset_array_unlock(d->ref, d->rrset_count);
return 0;
}
dump_msg_ref(txt, d->rrsets[i]);
}
rrset_array_unlock(d->ref, d->rrset_count);
return 1;
}
/** copy msg to worker pad */
@@ -247,49 +379,40 @@ copy_msg(struct regional* region, struct lruhash_entry* e,
return (*k)->qname != NULL;
}
/** dump lruhash msg cache */
static int
dump_msg_lruhash(RES* ssl, struct worker* worker, struct lruhash* h)
/** Dump the msg entry. */
static void
dump_msg_entry(struct lruhash_entry* e, struct config_strlist_head* txt,
void* arg)
{
struct lruhash_entry* e;
struct dump_info* dump_info = (struct dump_info*)arg;
struct query_info* k;
struct reply_info* d;
/* lruhash already locked by caller */
/* walk in order of lru; best first */
for(e=h->lru_start; e; e = e->lru_next) {
regional_free_all(worker->scratchpad);
lock_rw_rdlock(&e->lock);
/* make copy of rrset in worker buffer */
if(!copy_msg(worker->scratchpad, e, &k, &d)) {
lock_rw_unlock(&e->lock);
return 0;
}
regional_free_all(dump_info->worker->scratchpad);
/* Make copy of rrset in worker buffer. */
lock_rw_rdlock(&e->lock);
if(!copy_msg(dump_info->worker->scratchpad, e, &k, &d)) {
lock_rw_unlock(&e->lock);
/* release lock so we can lookup the rrset references
* in the rrset cache */
if(!dump_msg(ssl, k, d, *worker->env.now)) {
return 0;
}
log_err("out of memory in dump_msg_entry");
return;
}
return 1;
lock_rw_unlock(&e->lock);
/* Release lock so we can lookup the rrset references
* in the rrset cache. */
dump_msg(txt, k, d, *dump_info->worker->env.now);
}
/** dump msg cache */
static int
dump_msg_cache(RES* ssl, struct worker* worker)
{
struct slabhash* sh = worker->env.msg_cache;
size_t slab;
struct dump_info dump_info;
dump_info.worker = worker;
dump_info.ssl = ssl;
if(!ssl_printf(ssl, "START_MSG_CACHE\n")) return 0;
for(slab=0; slab<sh->size; slab++) {
lock_quick_lock(&sh->array[slab]->lock);
if(!dump_msg_lruhash(ssl, worker, sh->array[slab])) {
lock_quick_unlock(&sh->array[slab]->lock);
return 0;
}
lock_quick_unlock(&sh->array[slab]->lock);
}
if(!dump_slabhash(worker->env.msg_cache, &dump_msg_entry, ssl,
&dump_info))
return 0;
return ssl_printf(ssl, "END_MSG_CACHE\n");
}
@@ -692,7 +815,7 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
return 1; /* skip this one, not all references satisfied */
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags,
*worker->env.now)) {
*worker->env.now, 1)) {
log_warn("error out of memory");
return 0;
}
@@ -811,12 +934,18 @@ print_dp_main(RES* ssl, struct delegpt* dp, struct dns_msg* msg)
struct ub_packed_rrset_key* k = msg->rep->rrsets[i];
struct packed_rrset_data* d =
(struct packed_rrset_data*)k->entry.data;
struct config_strlist_head txt;
memset(&txt, 0, sizeof(txt));
if(d->security == sec_status_bogus) {
if(!ssl_printf(ssl, "Address is BOGUS:\n"))
return;
}
if(!dump_rrset(ssl, k, d, 0))
dump_rrset(&txt, k, d, 0);
if(!spool_strlist(ssl, txt.first)) {
config_delstrlist(txt.first);
return;
}
config_delstrlist(txt.first);
}
delegpt_count_ns(dp, &n_ns, &n_miss);
delegpt_count_addr(dp, &n_addr, &n_res, &n_avail);
@@ -836,9 +965,10 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
struct delegpt* dp;
struct dns_msg* msg;
struct regional* region = worker->scratchpad;
char b[260];
char b[LDNS_MAX_DOMAINLEN];
struct query_info qinfo;
struct iter_hints_stub* stub;
int nolock = 0;
regional_free_all(region);
qinfo.qname = nm;
qinfo.qname_len = nmlen;
@@ -850,13 +980,16 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
if(!ssl_printf(ssl, "The following name servers are used for lookup "
"of %s\n", b))
return 0;
dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass);
dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass, nolock);
if(dp) {
if(!ssl_printf(ssl, "forwarding request:\n"))
if(!ssl_printf(ssl, "forwarding request:\n")) {
lock_rw_unlock(&worker->env.fwds->lock);
return 0;
}
print_dp_main(ssl, dp, NULL);
print_dp_details(ssl, worker, dp);
lock_rw_unlock(&worker->env.fwds->lock);
return 1;
}
@@ -892,21 +1025,26 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
return 0;
continue;
}
}
}
stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass,
dp);
dp, nolock);
if(stub) {
if(stub->noprime) {
if(!ssl_printf(ssl, "The noprime stub servers "
"are used:\n"))
"are used:\n")) {
lock_rw_unlock(&worker->env.hints->lock);
return 0;
}
} else {
if(!ssl_printf(ssl, "The stub is primed "
"with servers:\n"))
"with servers:\n")) {
lock_rw_unlock(&worker->env.hints->lock);
return 0;
}
}
print_dp_main(ssl, stub->dp, NULL);
print_dp_details(ssl, worker, stub->dp);
lock_rw_unlock(&worker->env.hints->lock);
} else {
print_dp_main(ssl, dp, msg);
print_dp_details(ssl, worker, dp);
+393 -36
View File
@@ -91,6 +91,8 @@
#include "util/net_help.h"
#include "sldns/keyraw.h"
#include "respip/respip.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_hints.h"
#include <signal.h>
#ifdef HAVE_SYSTEMD
@@ -99,6 +101,9 @@
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef USE_CACHEDB
#include "cachedb/cachedb.h"
#endif
/** How many quit requests happened. */
static int sig_record_quit = 0;
@@ -194,6 +199,255 @@ signal_handling_playback(struct worker* wrk)
sig_record_reload = 0;
}
#ifdef HAVE_SSL
/* setup a listening ssl context, fatal_exit() on any failure */
static void
setup_listen_sslctx(void** ctx, int is_dot, int is_doh,
struct config_file* cfg, char* chroot)
{
char* key = cfg->ssl_service_key;
char* pem = cfg->ssl_service_pem;
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
key += strlen(chroot);
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
pem += strlen(chroot);
if(!(*ctx = listen_sslctx_create(key, pem, NULL,
cfg->tls_ciphers, cfg->tls_ciphersuites,
(cfg->tls_session_ticket_keys.first &&
cfg->tls_session_ticket_keys.first->str[0] != 0),
is_dot, is_doh, cfg->tls_protocols))) {
fatal_exit("could not set up listen SSL_CTX");
}
}
#endif /* HAVE_SSL */
#ifdef HAVE_SSL
void* daemon_setup_listen_dot_sslctx(struct daemon* daemon,
struct config_file* cfg)
{
void* ctx;
(void)setup_listen_sslctx(&ctx, 1, 0, cfg, daemon->chroot);
return ctx;
}
#endif /* HAVE_SSL */
#ifdef HAVE_SSL
#ifdef HAVE_NGHTTP2_NGHTTP2_H
void* daemon_setup_listen_doh_sslctx(struct daemon* daemon,
struct config_file* cfg)
{
void* ctx;
(void)setup_listen_sslctx(&ctx, 0, 1, cfg, daemon->chroot);
return ctx;
}
#endif /* HAVE_NGHTTP2_NGHTTP2_H */
#endif /* HAVE_SSL */
#ifdef HAVE_SSL
#ifdef HAVE_NGTCP2
void* daemon_setup_listen_quic_sslctx(struct daemon* daemon,
struct config_file* cfg)
{
void* ctx;
char* chroot = daemon->chroot;
char* key = cfg->ssl_service_key;
char* pem = cfg->ssl_service_pem;
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
key += strlen(chroot);
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
pem += strlen(chroot);
if(!(ctx = quic_sslctx_create(key, pem, NULL))) {
fatal_exit("could not set up quic SSL_CTX");
}
return ctx;
}
#endif /* HAVE_NGTCP2 */
#endif /* HAVE_SSL */
#ifdef HAVE_SSL
void* daemon_setup_connect_dot_sslctx(struct daemon* daemon,
struct config_file* cfg)
{
void* ctx;
char* bundle, *chroot = daemon->chroot;
bundle = cfg->tls_cert_bundle;
if(chroot && bundle && strncmp(bundle, chroot, strlen(chroot)) == 0)
bundle += strlen(chroot);
if(!(ctx = connect_sslctx_create(NULL, NULL, bundle,
cfg->tls_win_cert)))
fatal_exit("could not set up connect SSL_CTX");
return ctx;
}
#endif /* HAVE_SSL */
/* setups the needed ssl contexts, fatal_exit() on any failure */
void
daemon_setup_sslctxs(struct daemon* daemon, struct config_file* cfg)
{
#ifdef HAVE_SSL
char* chroot = daemon->chroot;
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
char* key = cfg->ssl_service_key;
char* pem = cfg->ssl_service_pem;
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
key += strlen(chroot);
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
pem += strlen(chroot);
/* setup the session keys; the callback to use them will be
* attached to each sslctx separately */
if(cfg->tls_session_ticket_keys.first &&
cfg->tls_session_ticket_keys.first->str[0] != 0) {
if(!listen_sslctx_setup_ticket_keys(
cfg->tls_session_ticket_keys.first, chroot)) {
fatal_exit("could not set session ticket SSL_CTX");
}
}
daemon->listen_dot_sslctx = daemon_setup_listen_dot_sslctx(
daemon, cfg);
#ifdef HAVE_NGHTTP2_NGHTTP2_H
if(cfg_has_https(cfg)) {
daemon->listen_doh_sslctx =
daemon_setup_listen_doh_sslctx(daemon, cfg);
}
#endif
#ifdef HAVE_NGTCP2
if(cfg_has_quic(cfg)) {
daemon->listen_quic_sslctx =
daemon_setup_listen_quic_sslctx(daemon, cfg);
}
#endif /* HAVE_NGTCP2 */
/* Store the file name and mtime to detect changes later. */
daemon->ssl_service_key = strdup(cfg->ssl_service_key);
if(!daemon->ssl_service_key)
fatal_exit("could not setup ssl ctx: out of memory");
if(cfg->ssl_service_pem) {
daemon->ssl_service_pem = strdup(cfg->ssl_service_pem);
if(!daemon->ssl_service_pem)
fatal_exit("could not setup ssl ctx: out of memory");
} else {
daemon->ssl_service_pem = NULL;
}
if(!file_get_mtime(key,
&daemon->mtime_ssl_service_key,
&daemon->mtime_ns_ssl_service_key, NULL))
log_err("Could not stat(%s): %s",
key, strerror(errno));
if(pem) {
if(!file_get_mtime(pem,
&daemon->mtime_ssl_service_pem,
&daemon->mtime_ns_ssl_service_pem, NULL))
log_err("Could not stat(%s): %s",
pem, strerror(errno));
} else {
daemon->mtime_ssl_service_pem = 0;
daemon->mtime_ns_ssl_service_pem = 0;
}
}
daemon->connect_dot_sslctx = daemon_setup_connect_dot_sslctx(
daemon, cfg);
#else /* HAVE_SSL */
(void)daemon;(void)cfg;
#endif /* HAVE_SSL */
}
/** Delete the ssl ctxs */
static void
daemon_delete_sslctxs(struct daemon* daemon)
{
#ifdef HAVE_SSL
listen_sslctx_delete_ticket_keys();
SSL_CTX_free((SSL_CTX*)daemon->listen_dot_sslctx);
daemon->listen_dot_sslctx = NULL;
SSL_CTX_free((SSL_CTX*)daemon->listen_doh_sslctx);
daemon->listen_doh_sslctx = NULL;
SSL_CTX_free((SSL_CTX*)daemon->connect_dot_sslctx);
daemon->connect_dot_sslctx = NULL;
free(daemon->ssl_service_key);
daemon->ssl_service_key = NULL;
free(daemon->ssl_service_pem);
daemon->ssl_service_pem = NULL;
#else
(void)daemon;
#endif
#ifdef HAVE_NGTCP2
SSL_CTX_free((SSL_CTX*)daemon->listen_quic_sslctx);
daemon->listen_quic_sslctx = NULL;
#endif
}
int
ssl_cert_changed(struct daemon* daemon, struct config_file* cfg)
{
time_t mtime = 0;
long ns = 0;
char* chroot = daemon->chroot;
char* key = cfg->ssl_service_key;
char* pem = cfg->ssl_service_pem;
log_assert(daemon->ssl_service_key && cfg->ssl_service_key);
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
key += strlen(chroot);
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
pem += strlen(chroot);
if(strcmp(daemon->ssl_service_key, cfg->ssl_service_key) != 0)
return 1;
if(daemon->ssl_service_pem && cfg->ssl_service_pem &&
strcmp(daemon->ssl_service_pem, cfg->ssl_service_pem) != 0)
return 1;
if(!file_get_mtime(key, &mtime, &ns, NULL)) {
log_err("Could not stat(%s): %s",
key, strerror(errno));
/* It has probably changed, but file read is likely going to
* fail. */
return 0;
}
if(mtime != daemon->mtime_ssl_service_key ||
ns != daemon->mtime_ns_ssl_service_key)
return 1;
if(pem) {
if(!file_get_mtime(pem, &mtime, &ns, NULL)) {
log_err("Could not stat(%s): %s",
pem, strerror(errno));
/* It has probably changed, but file read is likely going to
* fail. */
return 0;
}
if(mtime != daemon->mtime_ssl_service_pem ||
ns != daemon->mtime_ns_ssl_service_pem)
return 1;
}
return 0;
}
/** Reload the sslctxs if they have changed */
static void
daemon_reload_sslctxs(struct daemon* daemon)
{
#ifdef HAVE_SSL
if(daemon->cfg->ssl_service_key && daemon->cfg->ssl_service_key[0]) {
/* See if changed */
if(!daemon->ssl_service_key ||
ssl_cert_changed(daemon,daemon->cfg)) {
verbose(VERB_ALGO, "Reloading certificates");
daemon_delete_sslctxs(daemon);
daemon_setup_sslctxs(daemon, daemon->cfg);
}
} else {
/* See if sslctxs are removed from config. */
if(daemon->ssl_service_key) {
verbose(VERB_ALGO, "Removing certificates");
daemon_delete_sslctxs(daemon);
}
}
#else
(void)daemon;
#endif
}
struct daemon*
daemon_init(void)
{
@@ -230,7 +484,11 @@ daemon_init(void)
# else
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
| OPENSSL_INIT_ADD_ALL_DIGESTS
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
| OPENSSL_INIT_NO_LOAD_CONFIG
# endif
, NULL);
# endif
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
/* grab the COMP method ptr because openssl leaks it */
@@ -239,7 +497,11 @@ daemon_init(void)
# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
(void)SSL_library_init();
# else
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
| OPENSSL_INIT_NO_LOAD_CONFIG
# endif
, NULL);
# endif
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
if(!ub_openssl_lock_init())
@@ -260,6 +522,7 @@ daemon_init(void)
free(daemon);
return NULL;
}
daemon->env->modstack = &daemon->mods;
/* init edns_known_options */
if(!edns_known_options_init(daemon->env)) {
free(daemon->env);
@@ -317,21 +580,18 @@ daemon_init(void)
return daemon;
}
static int setup_acl_for_ports(struct acl_list* list,
struct listen_port* port_list)
int setup_acl_for_ports(struct acl_list* list, struct listen_port* port_list)
{
struct acl_addr* acl_node;
struct addrinfo* addr;
for(; port_list; port_list=port_list->next) {
if(!port_list->socket) {
/* This is mainly for testbound where port_list is
* empty. */
continue;
}
addr = port_list->socket->addr;
if(!(acl_node = acl_interface_insert(list,
(struct sockaddr_storage*)addr->ai_addr,
(socklen_t)addr->ai_addrlen,
(struct sockaddr_storage*)port_list->socket->addr,
port_list->socket->addrlen,
acl_refuse))) {
return 0;
}
@@ -340,7 +600,7 @@ static int setup_acl_for_ports(struct acl_list* list,
return 1;
}
int
int
daemon_open_shared_ports(struct daemon* daemon)
{
log_assert(daemon);
@@ -440,6 +700,19 @@ daemon_open_shared_ports(struct daemon* daemon)
return 1;
}
int
daemon_privileged(struct daemon* daemon)
{
daemon->env->cfg = daemon->cfg;
daemon->env->alloc = &daemon->superalloc;
daemon->env->worker = NULL;
if(!modstack_call_startup(&daemon->mods, daemon->cfg->module_conf,
daemon->env)) {
fatal_exit("failed to startup modules");
}
return 1;
}
/**
* Setup modules. setup module stack.
* @param daemon: the daemon
@@ -449,11 +722,15 @@ static void daemon_setup_modules(struct daemon* daemon)
daemon->env->cfg = daemon->cfg;
daemon->env->alloc = &daemon->superalloc;
daemon->env->worker = NULL;
daemon->env->need_to_validate = 0; /* set by module init below */
if(!modstack_setup(&daemon->mods, daemon->cfg->module_conf,
daemon->env)) {
fatal_exit("failed to setup modules");
if(daemon->mods_inited) {
modstack_call_deinit(&daemon->mods, daemon->env);
}
daemon->env->need_to_validate = 0; /* set by module init below */
if(!modstack_call_init(&daemon->mods, daemon->cfg->module_conf,
daemon->env)) {
fatal_exit("failed to init modules");
}
daemon->mods_inited = 1;
log_edns_known_options(VERB_ALGO, daemon->env);
}
@@ -499,7 +776,10 @@ daemon_clear_allocs(struct daemon* daemon)
{
int i;
for(i=0; i<daemon->num; i++) {
/* daemon->num may be different during reloads (after configuration
* read). Use old_num which has the correct value used to setup the
* worker_allocs */
for(i=0; i<daemon->old_num; i++) {
alloc_clear(daemon->worker_allocs[i]);
free(daemon->worker_allocs[i]);
}
@@ -533,6 +813,14 @@ daemon_create_workers(struct daemon* daemon)
fatal_exit("out of memory during daemon init");
numport = daemon_get_shufport(daemon, shufport);
verbose(VERB_ALGO, "total of %d outgoing ports available", numport);
#ifdef HAVE_NGTCP2
if (cfg_has_quic(daemon->cfg)) {
daemon->doq_table = doq_table_create(daemon->cfg, daemon->rand);
if(!daemon->doq_table)
fatal_exit("could not create doq_table: out of memory");
}
#endif
daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1);
if(daemon->reuseport && (int)daemon->num < (int)daemon->num_ports) {
@@ -602,6 +890,25 @@ static void close_other_pipes(struct daemon* daemon, int thr)
}
#endif /* THREADS_DISABLED */
/**
* Function to set the thread local log ID.
* Either the internal thread number, or the LWP ID on Linux based on
* configuration.
*/
static void
set_log_thread_id(struct worker* worker, struct config_file* cfg)
{
(void)cfg;
log_assert(worker);
#if defined(HAVE_GETTID) && !defined(THREADS_DISABLED)
worker->thread_tid = gettid();
if(cfg->log_thread_id)
log_thread_set(&worker->thread_tid);
else
#endif
log_thread_set(&worker->thread_num);
}
/**
* Function to start one thread.
* @param arg: user argument.
@@ -612,7 +919,14 @@ thread_start(void* arg)
{
struct worker* worker = (struct worker*)arg;
int port_num = 0;
log_thread_set(&worker->thread_num);
log_assert(worker->thr_id);
set_log_thread_id(worker, worker->daemon->cfg);
{
char name[16]; /* seems to be the safest size between
different OSes */
snprintf(name, sizeof(name), "unbound/%u", worker->thread_num);
ub_thread_setname(worker->thr_id, name);
}
ub_thread_blocksigs();
#ifdef THREADS_DISABLED
/* close pipe ends used by main */
@@ -687,16 +1001,17 @@ daemon_fork(struct daemon* daemon)
#endif
log_assert(daemon);
if(!(daemon->views = views_create()))
daemon_reload_sslctxs(daemon);
if(!(daemon->env->views = views_create()))
fatal_exit("Could not create views: out of memory");
/* create individual views and their localzone/data trees */
if(!views_apply_cfg(daemon->views, daemon->cfg))
if(!views_apply_cfg(daemon->env->views, daemon->cfg))
fatal_exit("Could not set up views");
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views))
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->env->views))
fatal_exit("Could not setup access control list");
if(!acl_interface_apply_cfg(daemon->acl_interface, daemon->cfg,
daemon->views))
daemon->env->views))
fatal_exit("Could not setup interface control list");
if(!tcl_list_apply_cfg(daemon->tcl, daemon->cfg))
fatal_exit("Could not setup TCP connection limits");
@@ -711,22 +1026,36 @@ daemon_fork(struct daemon* daemon)
"dnscrypt support");
#endif
}
if(daemon->cfg->cookie_secret_file &&
daemon->cfg->cookie_secret_file[0]) {
if(!(daemon->cookie_secrets = cookie_secrets_create()))
fatal_exit("Could not create cookie_secrets: out of memory");
if(!cookie_secrets_apply_cfg(daemon->cookie_secrets,
daemon->cfg->cookie_secret_file))
fatal_exit("Could not setup cookie_secrets");
}
/* create global local_zones */
if(!(daemon->local_zones = local_zones_create()))
fatal_exit("Could not create local zones: out of memory");
if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg))
fatal_exit("Could not set up local zones");
if(!(daemon->env->fwds = forwards_create()) ||
!forwards_apply_cfg(daemon->env->fwds, daemon->cfg))
fatal_exit("Could not set forward zones");
if(!(daemon->env->hints = hints_create()) ||
!hints_apply_cfg(daemon->env->hints, daemon->cfg))
fatal_exit("Could not set root or stub hints");
/* process raw response-ip configuration data */
if(!(daemon->respip_set = respip_set_create()))
if(!(daemon->env->respip_set = respip_set_create()))
fatal_exit("Could not create response IP set");
if(!respip_global_apply_cfg(daemon->respip_set, daemon->cfg))
if(!respip_global_apply_cfg(daemon->env->respip_set, daemon->cfg))
fatal_exit("Could not set up response IP set");
if(!respip_views_apply_cfg(daemon->views, daemon->cfg,
if(!respip_views_apply_cfg(daemon->env->views, daemon->cfg,
&have_view_respip_cfg))
fatal_exit("Could not set up per-view response IP sets");
daemon->use_response_ip = !respip_set_is_empty(daemon->respip_set) ||
have_view_respip_cfg;
daemon->use_response_ip = !respip_set_is_empty(
daemon->env->respip_set) || have_view_respip_cfg;
/* setup modules */
daemon_setup_modules(daemon);
@@ -740,6 +1069,10 @@ daemon_fork(struct daemon* daemon)
if(!edns_strings_apply_cfg(daemon->env->edns_strings, daemon->cfg))
fatal_exit("Could not set up EDNS strings");
#ifdef USE_CACHEDB
daemon->env->cachedb_enabled = cachedb_is_enabled(&daemon->mods,
daemon->env);
#endif
/* response-ip-xxx options don't work as expected without the respip
* module. To avoid run-time operational surprise we reject such
* configuration. */
@@ -754,9 +1087,19 @@ daemon_fork(struct daemon* daemon)
fatal_exit("RPZ requires the respip module");
/* first create all the worker structures, so we can pass
* them to the newly created threads.
* them to the newly created threads.
*/
daemon_create_workers(daemon);
/* Set it for the first (main) worker since it does not take part in
* the thread_start() procedure.
*/
set_log_thread_id(daemon->workers[0], daemon->cfg);
/* If shm stats need an offset, calculate it */
if(daemon->cfg->shm_enable && daemon->cfg->stat_interval > 0) {
daemon->stat_time_specific = 1;
daemon->stat_time_offset =
((int)time(NULL))%daemon->cfg->stat_interval;
}
#if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
/* in libev the first inited base gets signals */
@@ -832,16 +1175,24 @@ daemon_cleanup(struct daemon* daemon)
slabhash_clear(daemon->env->msg_cache);
}
daemon->old_num = daemon->num; /* save the current num */
forwards_delete(daemon->env->fwds);
daemon->env->fwds = NULL;
hints_delete(daemon->env->hints);
daemon->env->hints = NULL;
local_zones_delete(daemon->local_zones);
daemon->local_zones = NULL;
respip_set_delete(daemon->respip_set);
daemon->respip_set = NULL;
views_delete(daemon->views);
daemon->views = NULL;
respip_set_delete(daemon->env->respip_set);
daemon->env->respip_set = NULL;
views_delete(daemon->env->views);
daemon->env->views = NULL;
if(daemon->env->auth_zones)
auth_zones_cleanup(daemon->env->auth_zones);
/* key cache is cleared by module desetup during next daemon_fork() */
/* key cache is cleared by module deinit during next daemon_fork() */
daemon_remote_clear(daemon->rc);
if(daemon->fast_reload_thread)
fast_reload_thread_stop(daemon->fast_reload_thread);
if(daemon->fast_reload_printq_list)
fast_reload_printq_list_delete(daemon->fast_reload_printq_list);
for(i=0; i<daemon->num; i++)
worker_delete(daemon->workers[i]);
free(daemon->workers);
@@ -860,6 +1211,12 @@ daemon_cleanup(struct daemon* daemon)
#ifdef USE_DNSCRYPT
dnsc_delete(daemon->dnscenv);
daemon->dnscenv = NULL;
#endif
#ifdef HAVE_NGTCP2
if (daemon->doq_table) {
doq_table_delete(daemon->doq_table);
daemon->doq_table = NULL;
}
#endif
daemon->cfg = NULL;
}
@@ -870,7 +1227,9 @@ daemon_delete(struct daemon* daemon)
size_t i;
if(!daemon)
return;
modstack_desetup(&daemon->mods, daemon->env);
modstack_call_deinit(&daemon->mods, daemon->env);
modstack_call_destartup(&daemon->mods, daemon->env);
modstack_free(&daemon->mods);
daemon_remote_delete(daemon->rc);
for(i = 0; i < daemon->num_ports; i++)
listening_ports_free(daemon->ports[i]);
@@ -889,15 +1248,13 @@ daemon_delete(struct daemon* daemon)
acl_list_delete(daemon->acl);
acl_list_delete(daemon->acl_interface);
tcl_list_delete(daemon->tcl);
cookie_secrets_delete(daemon->cookie_secrets);
listen_desetup_locks();
free(daemon->chroot);
free(daemon->pidfile);
free(daemon->cfgfile);
free(daemon->env);
#ifdef HAVE_SSL
listen_sslctx_delete_ticket_keys();
SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx);
SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx);
#endif
daemon_delete_sslctxs(daemon);
free(daemon);
/* lex cleanup */
ub_c_lex_destroy();
+87 -6
View File
@@ -58,6 +58,10 @@ struct ub_randstate;
struct daemon_remote;
struct respip_set;
struct shm_main_info;
struct doq_table;
struct cookie_secrets;
struct fast_reload_thread;
struct fast_reload_printq;
#include "dnstap/dnstap_config.h"
#ifdef USE_DNSTAP
@@ -95,8 +99,26 @@ struct daemon {
struct listen_port* rc_ports;
/** remote control connections management (for first worker) */
struct daemon_remote* rc;
/** ssl context for listening to dnstcp over ssl, and connecting ssl */
void* listen_sslctx, *connect_sslctx;
/** ssl context for listening to dnstcp over ssl */
void* listen_dot_sslctx;
/** ssl context for connecting to dnstcp over ssl */
void* connect_dot_sslctx;
/** ssl context for listening to DoH */
void* listen_doh_sslctx;
/** ssl context for listening to quic */
void* listen_quic_sslctx;
/** the file name that the ssl context is made with, private key. */
char* ssl_service_key;
/** the file name that the ssl context is made with, certificate. */
char* ssl_service_pem;
/** modification time for ssl_service_key, in sec and ns. Like
* in a struct timespec, but without that for portability. */
time_t mtime_ssl_service_key;
long mtime_ns_ssl_service_key;
/** modification time for ssl_service_pem, in sec and ns. Like
* in a struct timespec, but without that for portability. */
time_t mtime_ssl_service_pem;
long mtime_ns_ssl_service_pem;
/** num threads allocated */
int num;
/** num threads allocated in the previous config or 0 at first */
@@ -115,6 +137,8 @@ struct daemon {
struct module_env* env;
/** stack of module callbacks */
struct module_stack mods;
/** The module stack has been inited */
int mods_inited;
/** access control, which client IPs are allowed to connect */
struct acl_list* acl;
/** access control, which interfaces are allowed to connect */
@@ -127,15 +151,18 @@ struct daemon {
struct timeval time_last_stat;
/** time when daemon started */
struct timeval time_boot;
/** views structure containing view tree */
struct views* views;
#ifdef USE_DNSTAP
/** the dnstap environment master value, copied and changed by threads*/
struct dt_env* dtenv;
#endif
/** The SHM info for shared memory stats. */
struct shm_main_info* shm_info;
/** response-ip set with associated actions and tags. */
struct respip_set* respip_set;
/** if the timeout for statistics is attempted at specific offset.
* If it is true, the stat timeout is the interval+offset, and that
* picks (roughly) the same time offset every time period. */
int stat_time_specific;
/** if the timeout is specific, what offset in the period. */
int stat_time_offset;
/** some response-ip tags or actions are configured if true */
int use_response_ip;
/** some RPZ policies are configured */
@@ -144,8 +171,23 @@ struct daemon {
/** the dnscrypt environment */
struct dnsc_env* dnscenv;
#endif
/** the doq connection table */
struct doq_table* doq_table;
/** reuse existing cache on reload if other conditions allow it. */
int reuse_cache;
/** the EDNS cookie secrets from the cookie-secret-file */
struct cookie_secrets* cookie_secrets;
/** the fast reload thread, or NULL */
struct fast_reload_thread* fast_reload_thread;
/** the fast reload printq list */
struct fast_reload_printq* fast_reload_printq_list;
/** the fast reload option to drop mesh queries, true if so. */
int fast_reload_drop_mesh;
/** for fast reload, if the tcl, tcp connection limits, has
* changes for workers */
int fast_reload_tcl_has_changes;
/** config file name */
char* cfgfile;
};
/**
@@ -162,6 +204,15 @@ struct daemon* daemon_init(void);
*/
int daemon_open_shared_ports(struct daemon* daemon);
/**
* Do daemon setup that needs privileges
* like opening privileged ports or opening device files.
* The cfg member pointer must have been set for the daemon.
* @param daemon: the daemon.
* @return: false on error.
*/
int daemon_privileged(struct daemon* daemon);
/**
* Fork workers and start service.
* When the routine exits, it is no longer forked.
@@ -189,4 +240,34 @@ void daemon_delete(struct daemon* daemon);
*/
void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg);
/**
* Setup acl list to have entries for the port list.
* @param list: the acl interface
* @param port_list: list of open ports, or none.
* @return false on failure
*/
int setup_acl_for_ports(struct acl_list* list, struct listen_port* port_list);
/* setups the needed ssl contexts, fatal_exit() on any failure */
void daemon_setup_sslctxs(struct daemon* daemon, struct config_file* cfg);
/** See if the SSL cert files have changed */
int ssl_cert_changed(struct daemon* daemon, struct config_file* cfg);
/** Setup the listening DoT SSL_CTX, returns the ssl ctx. */
void* daemon_setup_listen_dot_sslctx(struct daemon* daemon,
struct config_file* cfg);
/** Setup the listening DoH SSL_CTX, returns the ssl ctx. */
void* daemon_setup_listen_doh_sslctx(struct daemon* daemon,
struct config_file* cfg);
/** Setup the listening Quic SSL_CTX, returns the ssl ctx */
void* daemon_setup_listen_quic_sslctx(struct daemon* daemon,
struct config_file* cfg);
/** Setup the connect DoT SSL_CTX, returns the ssl ctx */
void* daemon_setup_connect_dot_sslctx(struct daemon* daemon,
struct config_file* cfg);
#endif /* DAEMON_H */
+5364 -169
View File
File diff suppressed because it is too large Load Diff
+175
View File
@@ -48,6 +48,7 @@
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
#endif
#include "util/locks.h"
struct config_file;
struct listen_list;
struct listen_port;
@@ -55,6 +56,7 @@ struct worker;
struct comm_reply;
struct comm_point;
struct daemon_remote;
struct config_strlist_head;
/** number of milliseconds timeout on incoming remote control handshake */
#define REMOTE_CONTROL_TCP_TIMEOUT 120000
@@ -118,6 +120,145 @@ struct remote_stream {
};
typedef struct remote_stream RES;
/**
* Notification status. This is exchanged between the fast reload thread
* and the server thread, over the commpair sockets.
*/
enum fast_reload_notification {
/** nothing, not used */
fast_reload_notification_none = 0,
/** the fast reload thread is done */
fast_reload_notification_done = 1,
/** the fast reload thread is done but with an error, it failed */
fast_reload_notification_done_error = 2,
/** the fast reload thread is told to exit by the server thread.
* Sent on server quit while the reload is running. */
fast_reload_notification_exit = 3,
/** the fast reload thread has exited, after being told to exit */
fast_reload_notification_exited = 4,
/** the fast reload thread has information to print out */
fast_reload_notification_printout = 5,
/** stop as part of the reload the thread and other threads */
fast_reload_notification_reload_stop = 6,
/** ack the stop as part of the reload, and also ack start */
fast_reload_notification_reload_ack = 7,
/** resume from stop as part of the reload */
fast_reload_notification_reload_start = 8,
/** the fast reload thread wants the mainthread to poll workers,
* after the reload, sent when nopause is used */
fast_reload_notification_reload_nopause_poll = 9
};
/**
* Fast reload printout queue. Contains a list of strings, that need to be
* printed over the file descriptor.
*/
struct fast_reload_printq {
/** if this item is in a list, the previous and next */
struct fast_reload_printq *prev, *next;
/** if this item is in a list, it is true. */
int in_list;
/** list of strings to printout */
struct config_strlist_head* to_print;
/** the current item to print. It is malloced. NULL if none. */
char* client_item;
/** The length, strlen, of the client_item, that has to be sent. */
int client_len;
/** The number of bytes sent of client_item. */
int client_byte_count;
/** the comm point for the client connection, the remote control
* client. */
struct comm_point* client_cp;
/** the remote control connection to print output to. */
struct remote_stream remote;
/** the worker that the event is added in */
struct worker* worker;
};
/**
* Fast reload auth zone change. Keeps track if an auth zone was removed,
* added or changed. This is needed because workers can have events for
* dealing with auth zones, like transfers, and those have to be removed
* too, not just the auth zone structure from the tree. */
struct fast_reload_auth_change {
/** next in the list of auth zone changes. */
struct fast_reload_auth_change* next;
/** the zone in the old config */
struct auth_zone* old_z;
/** the zone in the new config */
struct auth_zone* new_z;
/** if the zone was deleted */
int is_deleted;
/** if the zone was added */
int is_added;
/** if the zone has been changed */
int is_changed;
};
/**
* Fast reload thread structure
*/
struct fast_reload_thread {
/** the thread number for the dtio thread,
* must be first to cast thread arg to int* in checklock code. */
int threadnum;
/** communication socket pair, that sends commands */
int commpair[2];
/** thread id, of the io thread */
ub_thread_type tid;
#ifdef HAVE_GETTID
/** thread tid, the LWP id */
pid_t thread_tid;
/** if logging should include the LWP id */
int thread_tid_log;
#endif
/** if the io processing has started */
int started;
/** if the thread has to quit */
int need_to_quit;
/** verbosity of the fast_reload command, the number of +v options */
int fr_verb;
/** option to not pause threads during reload */
int fr_nopause;
/** option to drop mesh queries */
int fr_drop_mesh;
/** the event that listens on the remote service worker to the
* commpair, it receives content from the fast reload thread. */
void* service_event;
/** if the event that listens on the remote service worker has
* been added to the comm base. */
int service_event_is_added;
/** the service event can read a cmd, nonblocking, so it can
* save the partial read cmd here */
uint32_t service_read_cmd;
/** the number of bytes in service_read_cmd */
int service_read_cmd_count;
/** the worker that the service_event is added in */
struct worker* worker;
/** the printout of output to the remote client. */
struct fast_reload_printq *printq;
/** lock on fr_output, to stop race when both remote control thread
* and fast reload thread use fr_output list. */
lock_basic_type fr_output_lock;
/** list of strings, that the fast reload thread produces that have
* to be printed. The remote control thread can pick them up with
* the lock. */
struct config_strlist_head* fr_output;
/** communication socket pair, to respond to the reload request */
int commreload[2];
/** the list of auth zone changes. */
struct fast_reload_auth_change* auth_zone_change_list;
/** the old tree of auth zones, to lookup. */
struct auth_zones* old_auth_zones;
/** If the ssl ctxs have changed. */
int sslctxs_changed;
};
/**
* Create new remote control state for the daemon.
* @param cfg: config file with key file settings.
@@ -203,4 +344,38 @@ int ssl_printf(RES* ssl, const char* format, ...)
int ssl_read_line(RES* ssl, char* buf, size_t max);
#endif /* HAVE_SSL */
/**
* Start fast reload thread
* @param ssl: the RES connection to print to.
* @param worker: the remote servicing worker.
* @param s: the rc_state that is servicing the remote control connection to
* the remote control client. It needs to be moved away to stay connected
* while the fast reload is running.
* @param fr_verb: verbosity to print output at. 0 is nothing, 1 is some
* and 2 is more detail.
* @param fr_nopause: option to not pause threads during reload.
* @param fr_drop_mesh: option to drop mesh queries.
*/
void fast_reload_thread_start(RES* ssl, struct worker* worker,
struct rc_state* s, int fr_verb, int fr_nopause, int fr_drop_mesh);
/**
* Stop fast reload thread
* @param fast_reload_thread: the thread struct.
*/
void fast_reload_thread_stop(struct fast_reload_thread* fast_reload_thread);
/** fast reload thread commands to remote service thread event callback */
void fast_reload_service_cb(int fd, short bits, void* arg);
/** fast reload callback for the remote control client connection */
int fast_reload_client_callback(struct comm_point* c, void* arg, int err,
struct comm_reply* rep);
/** fast reload printq delete list */
void fast_reload_printq_list_delete(struct fast_reload_printq* list);
/** Pick up per worker changes after a fast reload. */
void fast_reload_worker_pickup_changes(struct worker* worker);
#endif /* DAEMON_REMOTE_H */
+45 -18
View File
@@ -262,6 +262,7 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
s->svr = worker->stats;
s->mesh_num_states = (long long)worker->env.mesh->all.count;
s->mesh_num_reply_states = (long long)worker->env.mesh->num_reply_states;
s->mesh_num_reply_addrs = (long long)worker->env.mesh->num_reply_addrs;
s->mesh_jostled = (long long)worker->env.mesh->stats_jostled;
s->mesh_dropped = (long long)worker->env.mesh->stats_dropped;
s->mesh_replies_sent = (long long)worker->env.mesh->replies_sent;
@@ -273,6 +274,7 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
/* add in the values from the mesh */
s->svr.ans_secure += (long long)worker->env.mesh->ans_secure;
s->svr.ans_bogus += (long long)worker->env.mesh->ans_bogus;
s->svr.val_ops += (long long)worker->env.mesh->val_ops;
s->svr.ans_rcode_nodata += (long long)worker->env.mesh->ans_nodata;
s->svr.ans_expired += (long long)worker->env.mesh->ans_expired;
for(i=0; i<UB_STATS_RCODE_NUM; i++)
@@ -281,6 +283,14 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
s->svr.rpz_action[i] += (long long)worker->env.mesh->rpz_action[i];
timehist_export(worker->env.mesh->histogram, s->svr.hist,
NUM_BUCKETS_HIST);
s->svr.num_queries_discard_timeout +=
(long long)worker->env.mesh->num_queries_discard_timeout;
s->svr.num_queries_replyaddr_limit +=
(long long)worker->env.mesh->num_queries_replyaddr_limit;
s->svr.num_queries_wait_limit +=
(long long)worker->env.mesh->num_queries_wait_limit;
s->svr.num_dns_error_reports +=
(long long)worker->env.mesh->num_dns_error_reports;
/* values from outside network */
s->svr.unwanted_replies = (long long)worker->back->unwanted_replies;
s->svr.qtcp_outgoing = (long long)worker->back->num_tcp_outgoing;
@@ -325,20 +335,8 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
s->svr.num_query_dnscrypt_replay = 0;
#endif /* USE_DNSCRYPT */
if(worker->env.auth_zones) {
if(reset && !worker->env.cfg->stat_cumulative) {
lock_rw_wrlock(&worker->env.auth_zones->lock);
} else {
lock_rw_rdlock(&worker->env.auth_zones->lock);
}
s->svr.num_query_authzone_up = (long long)worker->env.
auth_zones->num_query_up;
s->svr.num_query_authzone_down = (long long)worker->env.
auth_zones->num_query_down;
if(reset && !worker->env.cfg->stat_cumulative) {
worker->env.auth_zones->num_query_up = 0;
worker->env.auth_zones->num_query_down = 0;
}
lock_rw_unlock(&worker->env.auth_zones->lock);
s->svr.num_query_authzone_up += (long long)worker->env.mesh->num_query_authzone_up;
s->svr.num_query_authzone_down += (long long)worker->env.mesh->num_query_authzone_down;
}
s->svr.mem_stream_wait =
(long long)tcp_req_info_get_stream_buffer_size();
@@ -346,6 +344,12 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
(long long)http2_get_query_buffer_size();
s->svr.mem_http2_response_buffer =
(long long)http2_get_response_buffer_size();
#ifdef HAVE_NGTCP2
s->svr.mem_quic = (long long)doq_table_quic_size_get(
worker->daemon->doq_table);
#else
s->svr.mem_quic = 0;
#endif /* HAVE_NGTCP2 */
/* Set neg cache usage numbers */
set_neg_cache_stats(worker, &s->svr, reset);
@@ -391,6 +395,13 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
else worker_send_cmd(who, worker_cmd_stats_noreset);
verbose(VERB_ALGO, "wait for stats reply");
if(tube_wait_timeout(worker->cmd, STATS_THREAD_WAIT) == 0) {
#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG)
# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG
unsigned long pthid = 0;
if(verbosity >= VERB_OPS)
memcpy(&pthid, &who->thr_id, sizeof(unsigned long));
# endif
#endif
verbose(VERB_OPS, "no response from thread %d"
#ifdef HAVE_GETTID
" LWP %u"
@@ -407,7 +418,7 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
#endif
#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG)
# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG
, (unsigned long)*((unsigned long*)&who->thr_id)
, pthid
# endif
#endif
);
@@ -438,9 +449,17 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
total->svr.num_queries_cookie_valid += a->svr.num_queries_cookie_valid;
total->svr.num_queries_cookie_client += a->svr.num_queries_cookie_client;
total->svr.num_queries_cookie_invalid += a->svr.num_queries_cookie_invalid;
total->svr.num_queries_discard_timeout +=
a->svr.num_queries_discard_timeout;
total->svr.num_queries_replyaddr_limit +=
a->svr.num_queries_replyaddr_limit;
total->svr.num_queries_wait_limit += a->svr.num_queries_wait_limit;
total->svr.num_dns_error_reports += a->svr.num_dns_error_reports;
total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
total->svr.num_queries_timed_out += a->svr.num_queries_timed_out;
total->svr.num_query_authzone_up += a->svr.num_query_authzone_up;
total->svr.num_query_authzone_down += a->svr.num_query_authzone_down;
if (total->svr.max_query_time_us < a->svr.max_query_time_us)
total->svr.max_query_time_us = a->svr.max_query_time_us;
total->svr.sum_query_list_size += a->svr.sum_query_list_size;
@@ -448,9 +467,9 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
#ifdef USE_DNSCRYPT
total->svr.num_query_dnscrypt_crypted += a->svr.num_query_dnscrypt_crypted;
total->svr.num_query_dnscrypt_cert += a->svr.num_query_dnscrypt_cert;
total->svr.num_query_dnscrypt_cleartext += \
total->svr.num_query_dnscrypt_cleartext +=
a->svr.num_query_dnscrypt_cleartext;
total->svr.num_query_dnscrypt_crypted_malformed += \
total->svr.num_query_dnscrypt_crypted_malformed +=
a->svr.num_query_dnscrypt_crypted_malformed;
#endif /* USE_DNSCRYPT */
/* the max size reached is upped to higher of both */
@@ -467,6 +486,7 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
total->svr.qtls += a->svr.qtls;
total->svr.qtls_resume += a->svr.qtls_resume;
total->svr.qhttps += a->svr.qhttps;
total->svr.qquic += a->svr.qquic;
total->svr.qipv6 += a->svr.qipv6;
total->svr.qbit_QR += a->svr.qbit_QR;
total->svr.qbit_AA += a->svr.qbit_AA;
@@ -481,6 +501,7 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
total->svr.ans_rcode_nodata += a->svr.ans_rcode_nodata;
total->svr.ans_secure += a->svr.ans_secure;
total->svr.ans_bogus += a->svr.ans_bogus;
total->svr.val_ops += a->svr.val_ops;
total->svr.unwanted_replies += a->svr.unwanted_replies;
total->svr.unwanted_queries += a->svr.unwanted_queries;
total->svr.tcp_accept_usage += a->svr.tcp_accept_usage;
@@ -503,6 +524,7 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
total->mesh_num_states += a->mesh_num_states;
total->mesh_num_reply_states += a->mesh_num_reply_states;
total->mesh_num_reply_addrs += a->mesh_num_reply_addrs;
total->mesh_jostled += a->mesh_jostled;
total->mesh_dropped += a->mesh_dropped;
total->mesh_replies_sent += a->mesh_replies_sent;
@@ -526,7 +548,8 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
else stats->qclass_big++;
stats->qopcode[ LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ]++;
if(c->type != comm_udp) {
stats->qtcp++;
if(c->type != comm_doq)
stats->qtcp++;
if(c->ssl != NULL) {
stats->qtls++;
#ifdef HAVE_SSL
@@ -535,6 +558,10 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
#endif
if(c->type == comm_http)
stats->qhttps++;
#ifdef HAVE_NGTCP2
else if(c->type == comm_doq)
stats->qquic++;
#endif
}
}
if(repinfo && addr_is_ip6(&repinfo->remote_addr, repinfo->remote_addrlen))
+42 -51
View File
@@ -174,7 +174,7 @@ static void
checkrlimits(struct config_file* cfg)
{
#ifndef S_SPLINT_S
#ifdef HAVE_GETRLIMIT
#if defined(HAVE_GETRLIMIT) && !defined(unbound_testbound)
/* list has number of ports to listen to, ifs number addresses */
int list = ((cfg->do_udp?1:0) + (cfg->do_tcp?1 +
(int)cfg->incoming_num_tcp:0));
@@ -366,9 +366,8 @@ readpid (const char* file)
/** write pid to file.
* @param pidfile: file name of pid file.
* @param pid: pid to write to file.
* @return false on failure
*/
static int
static void
writepid (const char* pidfile, pid_t pid)
{
int fd;
@@ -383,7 +382,7 @@ writepid (const char* pidfile, pid_t pid)
, 0644)) == -1) {
log_err("cannot open pidfile %s: %s",
pidfile, strerror(errno));
return 0;
return;
}
while(count < strlen(pidbuf)) {
ssize_t r = write(fd, pidbuf+count, strlen(pidbuf)-count);
@@ -393,17 +392,16 @@ writepid (const char* pidfile, pid_t pid)
log_err("cannot write to pidfile %s: %s",
pidfile, strerror(errno));
close(fd);
return 0;
return;
} else if(r == 0) {
log_err("cannot write any bytes to pidfile %s: "
"write returns 0 bytes written", pidfile);
close(fd);
return 0;
return;
}
count += r;
}
close(fd);
return 1;
}
/**
@@ -465,6 +463,18 @@ detach(void)
#endif /* HAVE_DAEMON */
}
/** setup the remote and ticket keys */
static void
setup_sslctx_remote(struct daemon* daemon, struct config_file* cfg)
{
#ifdef HAVE_SSL
if(!(daemon->rc = daemon_remote_create(cfg)))
fatal_exit("could not set up remote-control");
#else /* HAVE_SSL */
(void)daemon;(void)cfg;
#endif /* HAVE_SSL */
}
/** daemonize, drop user privileges and chroot if needed */
static void
perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
@@ -475,7 +485,11 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
#endif
#ifdef HAVE_GETPWNAM
struct passwd *pwd = NULL;
#endif
if(!daemon_privileged(daemon))
fatal_exit("could not do privileged setup");
#ifdef HAVE_GETPWNAM
if(cfg->username && cfg->username[0]) {
if((pwd = getpwnam(cfg->username)) == NULL)
fatal_exit("user '%s' does not exist.", cfg->username);
@@ -487,36 +501,8 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
#endif
/* read ssl keys while superuser and outside chroot */
#ifdef HAVE_SSL
if(!(daemon->rc = daemon_remote_create(cfg)))
fatal_exit("could not set up remote-control");
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
if(!(daemon->listen_sslctx = listen_sslctx_create(
cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
fatal_exit("could not set up listen SSL_CTX");
if(cfg->tls_ciphers && cfg->tls_ciphers[0]) {
if (!SSL_CTX_set_cipher_list(daemon->listen_sslctx, cfg->tls_ciphers)) {
fatal_exit("failed to set tls-cipher %s", cfg->tls_ciphers);
}
}
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
if(cfg->tls_ciphersuites && cfg->tls_ciphersuites[0]) {
if (!SSL_CTX_set_ciphersuites(daemon->listen_sslctx, cfg->tls_ciphersuites)) {
fatal_exit("failed to set tls-ciphersuites %s", cfg->tls_ciphersuites);
}
}
#endif
if(cfg->tls_session_ticket_keys.first &&
cfg->tls_session_ticket_keys.first->str[0] != 0) {
if(!listen_sslctx_setup_ticket_keys(daemon->listen_sslctx, cfg->tls_session_ticket_keys.first)) {
fatal_exit("could not set session ticket SSL_CTX");
}
}
}
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
cfg->tls_cert_bundle, cfg->tls_win_cert)))
fatal_exit("could not set up connect SSL_CTX");
#endif
setup_sslctx_remote(daemon, cfg);
daemon_setup_sslctxs(daemon, cfg);
/* init syslog (as root) if needed, before daemonize, otherwise
* a fork error could not be printed since daemonize closed stderr.*/
@@ -545,7 +531,15 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
cfg, 1);
if(!daemon->pidfile)
fatal_exit("pidfile alloc: out of memory");
checkoldpid(daemon->pidfile, pidinchroot);
/* Check old pid if there is no username configured.
* With a username, the assumption is that the privilege
* drop makes a pidfile not removed when the server stopped
* last time. The server does not chown the pidfile for it,
* because that creates privilege escape problems, with the
* pidfile writable by unprivileged users, but used by
* privileged users. */
if(!(cfg->username && cfg->username[0]))
checkoldpid(daemon->pidfile, pidinchroot);
}
#endif
@@ -557,18 +551,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
/* write new pidfile (while still root, so can be outside chroot) */
#ifdef HAVE_KILL
if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) {
if(writepid(daemon->pidfile, getpid())) {
if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 &&
pidinchroot) {
# ifdef HAVE_CHOWN
if(chown(daemon->pidfile, cfg_uid, cfg_gid) == -1) {
verbose(VERB_QUERY, "cannot chown %u.%u %s: %s",
(unsigned)cfg_uid, (unsigned)cfg_gid,
daemon->pidfile, strerror(errno));
}
# endif /* HAVE_CHOWN */
}
}
writepid(daemon->pidfile, getpid());
}
#else
(void)daemon;
@@ -682,6 +665,9 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
* it would succeed on SIGHUP as well */
if(!cfg->use_syslog)
log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
daemon->cfgfile = strdup(*cfgfile);
if(!daemon->cfgfile)
fatal_exit("out of memory in daemon cfgfile strdup");
}
/**
@@ -716,6 +702,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi
"the commandline to see more errors, "
"or unbound-checkconf", cfgfile);
log_warn("Continuing with default config settings");
config_auto_slab_values(cfg);
}
apply_settings(daemon, cfg, cmdline_verbose, debug_mode);
if(!done_setup)
@@ -746,7 +733,11 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi
if(daemon->pidfile) {
int fd;
/* truncate pidfile */
fd = open(daemon->pidfile, O_WRONLY | O_TRUNC, 0644);
fd = open(daemon->pidfile, O_WRONLY | O_TRUNC
#ifdef O_NOFOLLOW
| O_NOFOLLOW
#endif
, 0644);
if(fd != -1)
close(fd);
/* delete pidfile */
+325 -158
View File
@@ -160,9 +160,11 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
+ sizeof(worker->rndstate)
+ regional_get_mem(worker->scratchpad)
+ sizeof(*worker->env.scratch_buffer)
+ sldns_buffer_capacity(worker->env.scratch_buffer)
+ forwards_get_mem(worker->env.fwds)
+ hints_get_mem(worker->env.hints);
+ sldns_buffer_capacity(worker->env.scratch_buffer);
if(worker->daemon->env->fwds)
log_info("forwards=%u", (unsigned)forwards_get_mem(worker->env.fwds));
if(worker->daemon->env->hints)
log_info("hints=%u", (unsigned)hints_get_mem(worker->env.hints));
if(worker->thread_num == 0)
me += acl_list_get_mem(worker->daemon->acl);
if(cur_serv) {
@@ -253,7 +255,8 @@ worker_handle_service_reply(struct comm_point* c, void* arg, int error,
return 0;
}
/* sanity check. */
if(!LDNS_QR_WIRE(sldns_buffer_begin(c->buffer))
if(sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE
|| !LDNS_QR_WIRE(sldns_buffer_begin(c->buffer))
|| LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) !=
LDNS_PACKET_QUERY
|| LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) > 1) {
@@ -290,6 +293,44 @@ worker_err_ratelimit(struct worker* worker, int err)
return err;
}
/**
* Reply with an error.
* This reply includes the qname if it has been parsed.
* For error ratelimiting, the err ratelimit routine should be checked
* beforehand. The reply is without EDNS, and copies RD and sets QR flag.
* @param pkt: the packet buffer from the comm point.
* @param err: the error code that would be wanted.
* @param qname_len: 0 if not parsed, and the qname length in packet.
*/
static void
query_error(sldns_buffer* pkt, int err, size_t qname_len)
{
/* Preserve the RD flag.
* The CD flag must be cleared in authoritative answers,
* also the AD flag need not be copied into answers.
* The other flags need not be copied into the answer. */
sldns_buffer_write_u16_at(pkt, 2,
sldns_buffer_read_u16_at(pkt, 2)&0x0100U);
LDNS_QR_SET(sldns_buffer_begin(pkt)); /* Set QR flag. */
LDNS_RCODE_SET(sldns_buffer_begin(pkt), err); /* Set rcode */
if(qname_len && LDNS_QDCOUNT(sldns_buffer_begin(pkt))>=1 &&
qname_len <= LDNS_MAX_DOMAINLEN) {
/* Copy query into the answer. */
LDNS_QDCOUNT_SET(sldns_buffer_begin(pkt), 1);
sldns_buffer_set_position(pkt, LDNS_HEADER_SIZE +
qname_len + 2 /* type */ + 2 /* class */ );
} else {
/* No query section in answer. */
LDNS_QDCOUNT_SET(sldns_buffer_begin(pkt), 0);
sldns_buffer_set_position(pkt, LDNS_HEADER_SIZE);
}
LDNS_ANCOUNT_SET(sldns_buffer_begin(pkt), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(pkt), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(pkt), 0);
sldns_buffer_flip(pkt);
}
/**
* Structure holding the result of the worker_check_request function.
* Based on configuration it could be called up to four times; ideally should
@@ -327,7 +368,6 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker,
return;
}
if(LDNS_TC_WIRE(sldns_buffer_begin(pkt))) {
LDNS_TC_CLR(sldns_buffer_begin(pkt));
verbose(VERB_QUERY, "request bad, has TC bit on");
out->value = worker_err_ratelimit(worker, LDNS_RCODE_FORMERR);
return;
@@ -369,6 +409,84 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker,
return;
}
/**
* Send fast-reload acknowledgement to the mainthread in one byte.
* This signals that this worker has received the previous command.
* The worker is waiting if that is after a reload_stop command.
* Or the worker has briefly processed the event itself, and in doing so
* released data pointers to old config, after a reload_poll command.
*/
static void
worker_send_reload_ack(struct worker* worker)
{
/* If this is clipped to 8 bits because thread_num>255, then that
* is not a problem, the receiver counts the number of bytes received.
* The number is informative only. */
uint8_t c = (uint8_t)worker->thread_num;
ssize_t ret;
while(1) {
ret = send(worker->daemon->fast_reload_thread->commreload[1],
(void*)&c, 1, 0);
if(ret == -1) {
if(
#ifndef USE_WINSOCK
errno == EINTR || errno == EAGAIN
# ifdef EWOULDBLOCK
|| errno == EWOULDBLOCK
# endif
#else
WSAGetLastError() == WSAEINTR ||
WSAGetLastError() == WSAEINPROGRESS ||
WSAGetLastError() == WSAEWOULDBLOCK
#endif
)
continue; /* Try again. */
log_err("worker reload ack reply: send failed: %s",
sock_strerror(errno));
break;
}
break;
}
}
/** stop and wait to resume the worker */
static void
worker_stop_and_wait(struct worker* worker)
{
uint8_t* buf = NULL;
uint32_t len = 0, cmd;
worker_send_reload_ack(worker);
/* wait for reload */
if(!tube_read_msg(worker->cmd, &buf, &len, 0)) {
log_err("worker reload read reply failed");
return;
}
if(len != sizeof(uint32_t)) {
log_err("worker reload reply, bad control msg length %d",
(int)len);
free(buf);
return;
}
cmd = sldns_read_uint32(buf);
free(buf);
if(cmd == worker_cmd_quit) {
/* quit anyway */
verbose(VERB_ALGO, "reload reply, control cmd quit");
comm_base_exit(worker->base);
return;
}
if(cmd != worker_cmd_reload_start) {
log_err("worker reload reply, wrong reply command");
}
if(worker->daemon->fast_reload_drop_mesh) {
verbose(VERB_ALGO, "worker: drop mesh queries after reload");
mesh_delete_all(worker->env.mesh);
}
fast_reload_worker_pickup_changes(worker);
worker_send_reload_ack(worker);
verbose(VERB_ALGO, "worker resume after reload");
}
void
worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), uint8_t* msg,
size_t len, int error, void* arg)
@@ -404,6 +522,15 @@ worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), uint8_t* msg,
verbose(VERB_ALGO, "got control cmd remote");
daemon_remote_exec(worker);
break;
case worker_cmd_reload_stop:
verbose(VERB_ALGO, "got control cmd reload_stop");
worker_stop_and_wait(worker);
break;
case worker_cmd_reload_poll:
verbose(VERB_ALGO, "got control cmd reload_poll");
fast_reload_worker_pickup_changes(worker);
worker_send_reload_ack(worker);
break;
default:
log_err("bad command %d", (int)cmd);
break;
@@ -598,7 +725,8 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
return 1;
if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, &actinfo,
alias_rrset, 0, worker->scratchpad, az, NULL))
alias_rrset, 0, worker->scratchpad, az, NULL,
worker->env.views, worker->env.respip_set))
return 0;
/* xxx_deny actions mean dropping the reply, unless the original reply
@@ -656,20 +784,21 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
*partial_repp = NULL; /* avoid accidental further pass */
/* Check TTL */
if(rep->ttl < timenow) {
if(TTL_IS_EXPIRED(rep->ttl, timenow)) {
/* Check if we need to serve expired now */
if(worker->env.cfg->serve_expired &&
!worker->env.cfg->serve_expired_client_timeout) {
if(worker->env.cfg->serve_expired_ttl &&
rep->serve_expired_ttl < timenow)
return 0;
/* Ignore expired failure answers */
if(FLAGS_GET_RCODE(rep->flags) !=
LDNS_RCODE_NOERROR &&
FLAGS_GET_RCODE(rep->flags) !=
LDNS_RCODE_NXDOMAIN &&
FLAGS_GET_RCODE(rep->flags) !=
LDNS_RCODE_YXDOMAIN)
/* if serve-expired-client-timeout is set, serve
* an expired record without attempting recursion
* if the serve_expired_norec_ttl is set for the record
* as we know that recursion is currently failing. */
(!worker->env.cfg->serve_expired_client_timeout ||
timenow < rep->serve_expired_norec_ttl)
#ifdef USE_CACHEDB
&& !(worker->env.cachedb_enabled &&
worker->env.cfg->cachedb_check_when_serve_expired)
#endif
) {
if(!reply_info_can_answer_expired(rep, timenow))
return 0;
if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
return 0;
@@ -758,7 +887,8 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
} else if(partial_rep &&
!respip_merge_cname(partial_rep, qinfo, rep, cinfo,
must_validate, &encode_rep, worker->scratchpad,
worker->env.auth_zones)) {
worker->env.auth_zones, worker->env.views,
worker->env.respip_set)) {
goto bail_out;
}
if(encode_rep != rep) {
@@ -879,6 +1009,7 @@ chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns,
size_t udpsize = edns->udp_size;
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
if(!inplace_cb_reply_local_call(&worker->env, NULL, NULL, NULL,
LDNS_RCODE_NOERROR, edns, repinfo, worker->scratchpad,
@@ -1079,7 +1210,7 @@ answer_notify(struct worker* w, struct query_info* qinfo,
if(verbosity >= VERB_DETAIL) {
char buf[380];
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
char sr[25];
dname_str(qinfo->qname, zname);
sr[0]=0;
@@ -1137,9 +1268,7 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
worker_check_request(c->buffer, worker, check_result);
if(check_result->value != 0) {
if(check_result->value != -1) {
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
check_result->value);
query_error(c->buffer, check_result->value, 0);
return 1;
}
comm_point_drop_reply(repinfo);
@@ -1151,45 +1280,22 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
log_assert(sldns_buffer_limit(c->buffer) >= LDNS_HEADER_SIZE
&& LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) == 1);
sldns_buffer_skip(c->buffer, LDNS_HEADER_SIZE); /* skip header */
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE); /* skip header */
/* check additional section is present and that we respond with EDEs */
if(LDNS_ARCOUNT(sldns_buffer_begin(c->buffer)) != 1
|| !ede) {
LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_REFUSED);
sldns_buffer_flip(c->buffer);
query_error(c->buffer, LDNS_RCODE_REFUSED, 0);
return 1;
}
if (!query_dname_len(c->buffer)) {
LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
sldns_buffer_flip(c->buffer);
query_error(c->buffer, LDNS_RCODE_FORMERR, 0);
return 1;
}
/* space available for query type and class? */
if (sldns_buffer_remaining(c->buffer) < 2 * sizeof(uint16_t)) {
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
sldns_buffer_flip(c->buffer);
query_error(c->buffer, LDNS_RCODE_FORMERR, 0);
return 1;
}
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
@@ -1211,35 +1317,27 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
if(!skip_pkt_rrs(c->buffer,
((int)LDNS_ANCOUNT(sldns_buffer_begin(c->buffer)))+
((int)LDNS_NSCOUNT(sldns_buffer_begin(c->buffer))))) {
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_set_position(c->buffer, opt_rr_mark);
sldns_buffer_flip(c->buffer);
query_error(c->buffer, LDNS_RCODE_FORMERR,
opt_rr_mark - LDNS_HEADER_SIZE
- 2 /* qtype */ - 2 /* qclass */);
return 1;
}
}
/* Do we have a valid OPT RR here? If not return REFUSED (could be a valid TSIG or something so no FORMERR) */
/* domain name must be the root of length 1. */
if(sldns_buffer_remaining(c->buffer) < 1 || *sldns_buffer_current(c->buffer) != 0) {
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_set_position(c->buffer, opt_rr_mark);
sldns_buffer_flip(c->buffer);
query_error(c->buffer, LDNS_RCODE_REFUSED,
opt_rr_mark - LDNS_HEADER_SIZE
- 2 /* qtype */ - 2 /* qclass */);
return 1;
} else {
sldns_buffer_skip(c->buffer, 1); /* skip root label */
}
if(sldns_buffer_remaining(c->buffer) < 2 ||
sldns_buffer_read_u16(c->buffer) != LDNS_RR_TYPE_OPT) {
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_set_position(c->buffer, opt_rr_mark);
sldns_buffer_flip(c->buffer);
query_error(c->buffer, LDNS_RCODE_REFUSED,
opt_rr_mark - LDNS_HEADER_SIZE
- 2 /* qtype */ - 2 /* qclass */);
return 1;
}
/* Write OPT RR directly after the query,
@@ -1326,15 +1424,6 @@ deny_refuse_non_local(struct comm_point* c, enum acl_access acl,
worker, repinfo, acladdr, ede, check_result);
}
/* Returns 1 if the ip rate limit check can happen before EDNS parsing,
* else 0 */
static int
pre_edns_ip_ratelimit_check(enum acl_access acl)
{
if(acl == acl_allow_cookie) return 0;
return 1;
}
/* Check if the query is blocked by source IP rate limiting.
* Returns 1 if it passes the check, 0 otherwise. */
static int
@@ -1360,6 +1449,24 @@ check_ip_ratelimit(struct worker* worker, struct sockaddr_storage* addr,
return 1;
}
/*
* This is the callback function when a request arrives. It is passed
* the packet and user argument. Return true to send a reply.
* This is of type comm_point_callback_type. The struct comm_point contains
* more comments on the comm_point.callback member about the function.
* @param c: the comm_point where the request arrives on.
* @param arg: the user argument for the callback, the worker.
* @param error: This can be NETEVENT_NOERROR, NETEVENT_TIMEOUT,
* NETEVENT_CLOSED or other comm point callback error values.
* @param repinfo: The reply info, use it to send a reply. If the reply
* is immediate, return 1. If the reply is later on return 0 and save
* the repinfo, to call comm_point_send_reply on.
* @return 1 to sent a reply straight away, for like cache response so that
* no allocation needs to be done. And only internal preallocated buffers
* are used. Return 0 and save the repinfo to reply later, for responses
* that need to be looked up. Return 0 and call comm_point_drop_reply on
* the repinfo to drop the response.
*/
int
worker_handle_request(struct comm_point* c, void* arg, int error,
struct comm_reply* repinfo)
@@ -1418,7 +1525,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
return 0;
}
if(c->dnscrypt && !repinfo->is_dnscrypted) {
char buf[LDNS_MAX_DOMAINLEN+1];
char buf[LDNS_MAX_DOMAINLEN];
/* Check if this is unencrypted and asking for certs */
worker_check_request(c->buffer, worker, &check_result);
if(check_result.value != 0) {
@@ -1426,6 +1533,10 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
"dnscrypt: worker check request: bad query.");
log_addr(VERB_CLIENT,"from",&repinfo->client_addr,
repinfo->client_addrlen);
if(check_result.value != -1) {
query_error(c->buffer, check_result.value, 0);
return 1;
}
comm_point_drop_reply(repinfo);
return 0;
}
@@ -1434,8 +1545,12 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
"dnscrypt: worker parse request: formerror.");
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
comm_point_drop_reply(repinfo);
return 0;
if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) {
comm_point_drop_reply(repinfo);
return 0;
}
query_error(c->buffer, LDNS_RCODE_FORMERR, 0);
return 1;
}
dname_str(qinfo.qname, buf);
if(!(qinfo.qtype == LDNS_RR_TYPE_TXT &&
@@ -1446,9 +1561,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
worker->daemon->dnscenv->provider_name,
sldns_rr_descript(qinfo.qtype)->_name,
buf);
comm_point_drop_reply(repinfo);
if(worker_err_ratelimit(worker, LDNS_RCODE_SERVFAIL) == -1) {
comm_point_drop_reply(repinfo);
return 0;
}
query_error(c->buffer, LDNS_RCODE_SERVFAIL,
qinfo.qname_len);
worker->stats.num_query_dnscrypt_cleartext++;
return 0;
return 1;
}
worker->stats.num_query_dnscrypt_cert++;
sldns_buffer_rewind(c->buffer);
@@ -1462,8 +1582,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
*/
if(worker->dtenv.log_client_query_messages) {
log_addr(VERB_ALGO, "request from client", &repinfo->client_addr, repinfo->client_addrlen);
log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer,
log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr, repinfo->c->socket->addrlen);
dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr, c->type, c->ssl, c->buffer,
((worker->env.cfg->sock_queue_timeout && timeval_isset(&c->recv_tv))?&c->recv_tv:NULL));
}
#endif
@@ -1488,9 +1608,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
verbose(VERB_ALGO, "worker check request: bad query.");
log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen);
if(check_result.value != -1) {
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
check_result.value);
query_error(c->buffer, check_result.value, 0);
return 1;
}
comm_point_drop_reply(repinfo);
@@ -1498,7 +1616,9 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
worker->stats.num_queries++;
pre_edns_ip_ratelimit = pre_edns_ip_ratelimit_check(acl);
pre_edns_ip_ratelimit = !worker->env.cfg->do_answer_cookie
|| sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE
|| LDNS_ARCOUNT(sldns_buffer_begin(c->buffer)) == 0;
/* If the IP rate limiting check needs extra EDNS information (e.g.,
* DNS Cookies) postpone the check until after EDNS is parsed. */
@@ -1522,10 +1642,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
comm_point_drop_reply(repinfo);
return 0;
}
sldns_buffer_rewind(c->buffer);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
query_error(c->buffer, LDNS_RCODE_FORMERR, 0);
goto send_reply;
}
if(worker->env.cfg->log_queries) {
@@ -1538,10 +1655,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
verbose(VERB_ALGO, "worker request: refused zone transfer.");
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
sldns_buffer_rewind(c->buffer);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_REFUSED);
if(worker_err_ratelimit(worker, LDNS_RCODE_REFUSED) == -1) {
comm_point_drop_reply(repinfo);
return 0;
}
query_error(c->buffer, LDNS_RCODE_REFUSED, qinfo.qname_len);
if(worker->stats.extended) {
worker->stats.qtype[qinfo.qtype]++;
}
@@ -1560,10 +1678,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
comm_point_drop_reply(repinfo);
return 0;
}
sldns_buffer_rewind(c->buffer);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
query_error(c->buffer, LDNS_RCODE_FORMERR, qinfo.qname_len);
if(worker->stats.extended) {
worker->stats.qtype[qinfo.qtype]++;
}
@@ -1571,12 +1686,17 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
if((ret=parse_edns_from_query_pkt(
c->buffer, &edns, worker->env.cfg, c, repinfo,
(worker->env.now ? *worker->env.now : time(NULL)),
worker->scratchpad)) != 0) {
*worker->env.now, worker->scratchpad,
worker->daemon->cookie_secrets)) != 0) {
struct edns_data reply_edns;
verbose(VERB_ALGO, "worker parse edns: formerror.");
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
if(worker_err_ratelimit(worker, ret) == -1) {
comm_point_drop_reply(repinfo);
regional_free_all(worker->scratchpad);
return 0;
}
memset(&reply_edns, 0, sizeof(reply_edns));
reply_edns.edns_present = 1;
error_encode(c->buffer, ret, &qinfo,
@@ -1593,6 +1713,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
verbose(VERB_ALGO, "query with bad edns version.");
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
if(worker_err_ratelimit(worker, EDNS_RCODE_BADVERS) == -1) {
comm_point_drop_reply(repinfo);
regional_free_all(worker->scratchpad);
return 0;
}
extended_error_encode(c->buffer, EDNS_RCODE_BADVERS, &qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), 0, &edns);
@@ -1620,6 +1745,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
repinfo->client_addrlen, edns.cookie_valid,
c->buffer)) {
worker->stats.num_queries_ip_ratelimited++;
regional_free_all(worker->scratchpad);
comm_point_drop_reply(repinfo);
return 0;
}
@@ -1637,6 +1763,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
else if(edns.cookie_present) {
/* Cookie present, but not valid: Cookie was bad! */
if(worker_err_ratelimit(worker, LDNS_EXT_RCODE_BADCOOKIE) == -1) {
comm_point_drop_reply(repinfo);
regional_free_all(worker->scratchpad);
return 0;
}
extended_error_encode(c->buffer,
LDNS_EXT_RCODE_BADCOOKIE, &qinfo,
*(uint16_t*)(void *)
@@ -1651,6 +1782,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
"need cookie or stateful transport");
log_addr(VERB_ALGO, "from",&repinfo->remote_addr
, repinfo->remote_addrlen);
if(worker_err_ratelimit(worker, LDNS_RCODE_REFUSED) == -1) {
comm_point_drop_reply(repinfo);
regional_free_all(worker->scratchpad);
return 0;
}
EDNS_OPT_LIST_APPEND_EDE(&edns.opt_list_out,
worker->scratchpad, LDNS_EDE_OTHER,
"DNS Cookie needed for UDP replies");
@@ -1677,14 +1813,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
verbose(VERB_ALGO, "worker request: edns is too small.");
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
if(worker_err_ratelimit(worker, LDNS_RCODE_SERVFAIL) == -1) {
comm_point_drop_reply(repinfo);
regional_free_all(worker->scratchpad);
return 0;
}
/* A small error without qname, and TC flag on. */
query_error(c->buffer, LDNS_RCODE_SERVFAIL, 0);
LDNS_TC_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_SERVFAIL);
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
sldns_buffer_write_at(c->buffer, 4,
(uint8_t*)"\0\0\0\0\0\0\0\0", 8);
sldns_buffer_flip(c->buffer);
regional_free_all(worker->scratchpad);
goto send_reply;
}
@@ -1731,8 +1867,9 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
goto send_reply;
}
if(worker->env.auth_zones &&
auth_zones_answer(worker->env.auth_zones, &worker->env,
&qinfo, &edns, repinfo, c->buffer, worker->scratchpad)) {
auth_zones_downstream_answer(worker->env.auth_zones,
&worker->env, &qinfo, &edns, repinfo, c->buffer,
worker->scratchpad)) {
regional_free_all(worker->scratchpad);
if(sldns_buffer_limit(c->buffer) == 0) {
comm_point_drop_reply(repinfo);
@@ -1768,6 +1905,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
* ACLs allow the snooping. */
if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) &&
acl != acl_allow_snoop ) {
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
&repinfo->client_addr, repinfo->client_addrlen);
/* This ratelimited error query is accounted in the stats,
* as an incoming query. */
if(worker_err_ratelimit(worker, LDNS_RCODE_REFUSED) == -1) {
comm_point_drop_reply(repinfo);
regional_free_all(worker->scratchpad);
return 0;
}
if(worker->env.cfg->ede) {
EDNS_OPT_LIST_APPEND_EDE(&edns.opt_list_out,
worker->scratchpad, LDNS_EDE_NOT_AUTHORITATIVE, "");
@@ -1776,29 +1922,17 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), &edns);
regional_free_all(worker->scratchpad);
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
&repinfo->client_addr, repinfo->client_addrlen);
goto send_reply;
}
/* If we've found a local alias, replace the qname with the alias
* target before resolving it. */
if(qinfo.local_alias) {
struct ub_packed_rrset_key* rrset = qinfo.local_alias->rrset;
struct packed_rrset_data* d = rrset->entry.data;
/* Sanity check: our current implementation only supports
* a single CNAME RRset as a local alias. */
if(qinfo.local_alias->next ||
rrset->rk.type != htons(LDNS_RR_TYPE_CNAME) ||
d->count != 1) {
log_err("assumption failure: unexpected local alias");
if(!local_alias_shallow_copy_qname(qinfo.local_alias, &qinfo.qname,
&qinfo.qname_len)) {
regional_free_all(worker->scratchpad);
return 0; /* drop it */
}
qinfo.qname = d->rr_data[0] + 2;
qinfo.qname_len = d->rr_len[0] - 2;
}
/* If we may apply IP-based actions to the answer, build the client
@@ -1815,7 +1949,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
cinfo_tmp.tag_datas = acladdr->tag_datas;
cinfo_tmp.tag_datas_size = acladdr->tag_datas_size;
cinfo_tmp.view = acladdr->view;
cinfo_tmp.respip_set = worker->daemon->respip_set;
cinfo_tmp.view_name = NULL;
cinfo = &cinfo_tmp;
}
@@ -1847,13 +1981,13 @@ lookup_cache:
* its qname must be that used for cache
* lookup. */
if((worker->env.cfg->prefetch &&
*worker->env.now >= rep->prefetch_ttl) ||
rep->prefetch_ttl <= *worker->env.now) ||
(worker->env.cfg->serve_expired &&
*worker->env.now > rep->ttl)) {
time_t leeway = rep->ttl - *worker->env.now;
if(rep->ttl < *worker->env.now)
leeway = 0;
TTL_IS_EXPIRED(rep->ttl, *worker->env.now) &&
!(*worker->env.now < rep->serve_expired_norec_ttl))) {
time_t leeway =
TTL_IS_EXPIRED(rep->ttl, *worker->env.now)
? 0 : rep->ttl - *worker->env.now;
lock_rw_unlock(&e->lock);
reply_and_prefetch(worker, lookup_qinfo,
@@ -1949,10 +2083,10 @@ send_reply_rc:
/*
* sending src (client)/dst (local service) addresses over DNSTAP from send_reply code label (when we serviced local zone for ex.)
*/
if(worker->dtenv.log_client_response_messages) {
log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
if(worker->dtenv.log_client_response_messages && rc !=0) {
log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr, repinfo->c->socket->addrlen);
log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen);
dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr, c->type, c->ssl, c->buffer);
}
#endif
if(worker->env.cfg->log_replies)
@@ -1966,11 +2100,15 @@ send_reply_rc:
qinfo.qname = qinfo.local_alias->rrset->rk.dname;
log_reply_info(NO_VERBOSE, &qinfo,
&repinfo->client_addr, repinfo->client_addrlen,
tv, 1, c->buffer);
tv, 1, c->buffer,
(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr:NULL),
c->type, c->ssl);
} else {
log_reply_info(NO_VERBOSE, &qinfo,
&repinfo->client_addr, repinfo->client_addrlen,
tv, 1, c->buffer);
tv, 1, c->buffer,
(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr:NULL),
c->type, c->ssl);
}
}
#ifdef USE_DNSCRYPT
@@ -2022,10 +2160,37 @@ worker_restart_timer(struct worker* worker)
{
if(worker->env.cfg->stat_interval > 0) {
struct timeval tv;
if(worker->daemon->stat_time_specific) {
struct timeval dest, now;
int interval = worker->env.cfg->stat_interval;
int offset = worker->daemon->stat_time_offset;
int nows, spec;
if(gettimeofday(&now, NULL) < 0)
log_err("gettimeofday: %s", strerror(errno));
#ifndef S_SPLINT_S
tv.tv_sec = worker->env.cfg->stat_interval;
tv.tv_usec = 0;
nows = (int)now.tv_sec;
/* The next time is on the timer interval, at the
* specific offset, time value % interval = offset. */
/* It relies on the integer division below to drop the
* remainder in order to calculate the expected
* result. */
spec = ((nows-offset)/interval+1)*interval+offset;
/* This is instead of an assertion, and should not
* be needed. So assert(spec > nows), tv is going to
* be positive. */
if(spec<=nows) spec += interval;
dest.tv_sec = spec;
dest.tv_usec = 0;
#endif
/* Subtract in timeval, so the fractions of a second
* are rounded to the whole specific time. */
timeval_subtract(&tv, &dest, &now);
} else {
#ifndef S_SPLINT_S
tv.tv_sec = worker->env.cfg->stat_interval;
tv.tv_usec = 0;
#endif
}
comm_timer_set(worker->stat_timer, &tv);
}
}
@@ -2100,9 +2265,6 @@ worker_init(struct worker* worker, struct config_file *cfg,
struct dt_env* dtenv = &worker->dtenv;
#else
void* dtenv = NULL;
#endif
#ifdef HAVE_GETTID
worker->thread_tid = gettid();
#endif
worker->need_to_exit = 0;
worker->base = comm_base_create(do_sigs);
@@ -2171,8 +2333,11 @@ worker_init(struct worker* worker, struct config_file *cfg,
: cfg->tcp_idle_timeout,
cfg->harden_large_queries, cfg->http_max_streams,
cfg->http_endpoint, cfg->http_notls_downstream,
worker->daemon->tcl, worker->daemon->listen_sslctx,
dtenv, worker_handle_request, worker);
worker->daemon->tcl, worker->daemon->listen_dot_sslctx,
worker->daemon->listen_doh_sslctx,
worker->daemon->listen_quic_sslctx,
dtenv, worker->daemon->doq_table, worker->env.rnd,
cfg, worker_handle_request, worker);
if(!worker->front) {
log_err("could not create listening sockets");
worker_delete(worker);
@@ -2187,7 +2352,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
cfg->unwanted_threshold, cfg->outgoing_tcp_mss,
&worker_alloc_cleanup, worker,
cfg->do_udp || cfg->udp_upstream_without_downstream,
worker->daemon->connect_sslctx, cfg->delay_close,
worker->daemon->connect_dot_sslctx, cfg->delay_close,
cfg->tls_use_sni, dtenv, cfg->udp_connect,
cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout,
cfg->tcp_auth_query_timeout);
@@ -2263,18 +2428,6 @@ worker_init(struct worker* worker, struct config_file *cfg,
worker_delete(worker);
return 0;
}
if(!(worker->env.fwds = forwards_create()) ||
!forwards_apply_cfg(worker->env.fwds, cfg)) {
log_err("Could not set forward zones");
worker_delete(worker);
return 0;
}
if(!(worker->env.hints = hints_create()) ||
!hints_apply_cfg(worker->env.hints, cfg)) {
log_err("Could not set root or stub hints");
worker_delete(worker);
return 0;
}
/* one probe timer per process -- if we have 5011 anchors */
if(autr_get_num_anchors(worker->env.anchors) > 0
#ifndef THREADS_DISABLED
@@ -2347,8 +2500,6 @@ worker_delete(struct worker* worker)
outside_network_quit_prepare(worker->back);
mesh_delete(worker->env.mesh);
sldns_buffer_free(worker->env.scratch_buffer);
forwards_delete(worker->env.fwds);
hints_delete(worker->env.hints);
listen_delete(worker->front);
outside_network_delete(worker->back);
comm_signal_delete(worker->comsig);
@@ -2520,3 +2671,19 @@ void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
log_assert(0);
}
#endif
#ifdef HAVE_NGTCP2
void doq_client_event_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
void* ATTR_UNUSED(arg))
{
log_assert(0);
}
#endif
#ifdef HAVE_NGTCP2
void doq_client_timer_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
void* ATTR_UNUSED(arg))
{
log_assert(0);
}
#endif
+7 -1
View File
@@ -72,7 +72,13 @@ enum worker_commands {
/** obtain statistics without statsclear */
worker_cmd_stats_noreset,
/** execute remote control command */
worker_cmd_remote
worker_cmd_remote,
/** for fast-reload, perform stop */
worker_cmd_reload_stop,
/** for fast-reload, start again */
worker_cmd_reload_start,
/** for fast-reload, poll to make sure worker has released data */
worker_cmd_reload_poll
};
/**
+22 -17
View File
@@ -366,22 +366,23 @@ static int
dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg)
{
struct config_strlist* s;
verbose(VERB_ALGO, "dns64-prefix: %s", cfg->dns64_prefix);
if (!netblockstrtoaddr(cfg->dns64_prefix ? cfg->dns64_prefix :
DEFAULT_DNS64_PREFIX, 0, &dns64_env->prefix_addr,
const char* dns64_prefix = cfg->dns64_prefix ?
cfg->dns64_prefix : DEFAULT_DNS64_PREFIX;
verbose(VERB_ALGO, "dns64-prefix: %s", dns64_prefix);
if (!netblockstrtoaddr(dns64_prefix, 0, &dns64_env->prefix_addr,
&dns64_env->prefix_addrlen, &dns64_env->prefix_net)) {
log_err("cannot parse dns64-prefix netblock: %s", cfg->dns64_prefix);
log_err("cannot parse dns64-prefix netblock: %s", dns64_prefix);
return 0;
}
if (!addr_is_ip6(&dns64_env->prefix_addr, dns64_env->prefix_addrlen)) {
log_err("dns64_prefix is not IPv6: %s", cfg->dns64_prefix);
log_err("dns64_prefix is not IPv6: %s", dns64_prefix);
return 0;
}
if (dns64_env->prefix_net != 32 && dns64_env->prefix_net != 40 &&
dns64_env->prefix_net != 48 && dns64_env->prefix_net != 56 &&
dns64_env->prefix_net != 64 && dns64_env->prefix_net != 96 ) {
log_err("dns64-prefix length it not 32, 40, 48, 56, 64 or 96: %s",
cfg->dns64_prefix);
log_err("dns64-prefix length is not 32, 40, 48, 56, 64 or 96: %s",
dns64_prefix);
return 0;
}
for(s = cfg->dns64_ignore_aaaa; s; s = s->next) {
@@ -496,8 +497,8 @@ handle_ipv6_ptr(struct module_qstate* qstate, int id)
/* Create the new sub-query. */
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0, 0,
&subq))
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->client_info,
qstate->query_flags, 0, 0, &subq))
return module_error;
if (subq) {
subq->curmod = id;
@@ -522,8 +523,8 @@ generate_type_A_query(struct module_qstate* qstate, int id)
/* Start the sub-query. */
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0,
0, &subq))
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->client_info,
qstate->query_flags, 0, 0, &subq))
{
verbose(VERB_ALGO, "dns64: sub-query creation failed");
return module_error;
@@ -631,7 +632,7 @@ handle_event_moddone(struct module_qstate* qstate, int id)
/* When an AAAA query completes check if we want to perform DNS64
* synthesis. We skip queries with DNSSEC enabled (!CD) and
* ones generated by us to retrive the A/PTR record to use for
* ones generated by us to retrieve the A/PTR record to use for
* synth. */
int could_synth =
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA &&
@@ -657,8 +658,9 @@ handle_event_moddone(struct module_qstate* qstate, int id)
qstate->return_msg->rep &&
!dns_cache_store(
qstate->env, &qstate->qinfo, qstate->return_msg->rep,
0, 0, 0, NULL,
qstate->query_flags, qstate->qstarttime))
0, qstate->prefetch_leeway, 0, NULL,
qstate->query_flags, qstate->qstarttime,
qstate->is_valrec))
log_err("out of memory");
/* do nothing */
@@ -701,6 +703,7 @@ dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
iq->state = DNS64_NEW_QUERY;
iq->started_no_cache_store = qstate->no_cache_store;
qstate->no_cache_store = 1;
ATTR_FALLTHROUGH
/* fallthrough */
case module_event_pass:
qstate->ext_state[id] = handle_event_pass(qstate, id);
@@ -846,6 +849,7 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
*/
cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount,
rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
rep->serve_expired_norec_ttl,
rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
rep->rrset_count, rep->security, LDNS_EDE_NONE);
if(!cp)
@@ -1006,7 +1010,8 @@ dns64_inform_super(struct module_qstate* qstate, int id,
/* Store the generated response in cache. */
if ( (!super_dq || !super_dq->started_no_cache_store) &&
!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep,
0, 0, 0, NULL, super->query_flags, qstate->qstarttime))
0, super->prefetch_leeway, 0, NULL, super->query_flags,
qstate->qstarttime, qstate->is_valrec))
log_err("out of memory");
}
@@ -1044,8 +1049,8 @@ dns64_get_mem(struct module_env* env, int id)
*/
static struct module_func_block dns64_block = {
"dns64",
&dns64_init, &dns64_deinit, &dns64_operate, &dns64_inform_super,
&dns64_clear, &dns64_get_mem
NULL, NULL, &dns64_init, &dns64_deinit, &dns64_operate,
&dns64_inform_super, &dns64_clear, &dns64_get_mem
};
/**
+1 -1
View File
@@ -361,7 +361,7 @@ dnscrypt_server_uncurve(struct dnsc_env* env,
len -= DNSCRYPT_QUERY_HEADER_SIZE;
while (*sldns_buffer_at(buffer, --len) == 0)
while (len>0 && *sldns_buffer_at(buffer, --len) == 0)
;
if (*sldns_buffer_at(buffer, len) != 0x80) {
+90 -19
View File
@@ -86,6 +86,31 @@ dt_pack(const Dnstap__Dnstap *d, void **buf, size_t *sz)
return 1;
}
/** See if the message is sent due to dnstap sample rate */
static int
dt_sample_rate_limited(struct dt_env* env)
{
lock_basic_lock(&env->sample_lock);
/* Sampling is every [n] packets. Where n==1, every packet is sent */
if(env->sample_rate > 1) {
int submit = 0;
/* if sampling is engaged... */
if (env->sample_rate_count > env->sample_rate) {
/* once the count passes the limit */
/* submit the message */
submit = 1;
/* and reset the count */
env->sample_rate_count = 0;
}
/* increment count regardless */
env->sample_rate_count++;
lock_basic_unlock(&env->sample_lock);
return !submit;
}
lock_basic_unlock(&env->sample_lock);
return 0;
}
static void
dt_send(const struct dt_env *env, void *buf, size_t len_buf)
{
@@ -146,6 +171,7 @@ dt_create(struct config_file* cfg)
env = (struct dt_env *) calloc(1, sizeof(struct dt_env));
if (!env)
return NULL;
lock_basic_init(&env->sample_lock);
env->dtio = dt_io_thread_create();
if(!env->dtio) {
@@ -166,8 +192,11 @@ static void
dt_apply_identity(struct dt_env *env, struct config_file *cfg)
{
char buf[MAXHOSTNAMELEN+1];
if (!cfg->dnstap_send_identity)
if (!cfg->dnstap_send_identity) {
free(env->identity);
env->identity = NULL;
return;
}
free(env->identity);
if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) {
if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
@@ -189,8 +218,11 @@ dt_apply_identity(struct dt_env *env, struct config_file *cfg)
static void
dt_apply_version(struct dt_env *env, struct config_file *cfg)
{
if (!cfg->dnstap_send_version)
if (!cfg->dnstap_send_version) {
free(env->version);
env->version = NULL;
return;
}
free(env->version);
if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0)
env->version = strdup(PACKAGE_STRING);
@@ -204,13 +236,8 @@ dt_apply_version(struct dt_env *env, struct config_file *cfg)
}
void
dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
dt_apply_logcfg(struct dt_env *env, struct config_file *cfg)
{
if (!cfg->dnstap)
return;
dt_apply_identity(env, cfg);
dt_apply_version(env, cfg);
if ((env->log_resolver_query_messages = (unsigned int)
cfg->dnstap_log_resolver_query_messages))
{
@@ -241,6 +268,23 @@ dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
{
verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled");
}
lock_basic_lock(&env->sample_lock);
if((env->sample_rate = (unsigned int)cfg->dnstap_sample_rate))
{
verbose(VERB_OPS, "dnstap SAMPLE_RATE enabled and set to \"%d\"", (int)env->sample_rate);
}
lock_basic_unlock(&env->sample_lock);
}
void
dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
{
if (!cfg->dnstap)
return;
dt_apply_identity(env, cfg);
dt_apply_version(env, cfg);
dt_apply_logcfg(env, cfg);
}
int
@@ -273,6 +317,7 @@ dt_delete(struct dt_env *env)
if (!env)
return;
dt_io_thread_delete(env->dtio);
lock_basic_destroy(&env->sample_lock);
free(env->identity);
free(env->version);
free(env);
@@ -305,6 +350,7 @@ dt_msg_fill_net(struct dt_msg *dm,
struct sockaddr_storage *qs,
struct sockaddr_storage *rs,
enum comm_point_type cptype,
void *cpssl,
ProtobufCBinaryData *qaddr, protobuf_c_boolean *has_qaddr,
uint32_t *qport, protobuf_c_boolean *has_qport,
ProtobufCBinaryData *raddr, protobuf_c_boolean *has_raddr,
@@ -371,13 +417,26 @@ dt_msg_fill_net(struct dt_msg *dm,
*has_rport = 1;
}
log_assert(cptype == comm_udp || cptype == comm_tcp);
if (cptype == comm_udp) {
/* socket_protocol */
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP;
dm->m.has_socket_protocol = 1;
} else if (cptype == comm_tcp) {
if (cpssl == NULL) {
/* socket_protocol */
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
dm->m.has_socket_protocol = 1;
} else {
/* socket_protocol */
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOT;
dm->m.has_socket_protocol = 1;
}
} else if (cptype == comm_http) {
/* socket_protocol */
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOH;
dm->m.has_socket_protocol = 1;
} else {
/* other socket protocol */
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
dm->m.has_socket_protocol = 1;
}
@@ -388,12 +447,16 @@ dt_msg_send_client_query(struct dt_env *env,
struct sockaddr_storage *qsock,
struct sockaddr_storage *rsock,
enum comm_point_type cptype,
void *cpssl,
sldns_buffer *qmsg,
struct timeval* tstamp)
{
struct dt_msg dm;
struct timeval qtime;
if(dt_sample_rate_limited(env))
return;
if(tstamp)
memcpy(&qtime, tstamp, sizeof(qtime));
else gettimeofday(&qtime, NULL);
@@ -410,8 +473,7 @@ dt_msg_send_client_query(struct dt_env *env,
dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
log_assert(cptype == comm_udp || cptype == comm_tcp);
dt_msg_fill_net(&dm, qsock, rsock, cptype,
dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
&dm.m.query_address, &dm.m.has_query_address,
&dm.m.query_port, &dm.m.has_query_port,
&dm.m.response_address, &dm.m.has_response_address,
@@ -427,11 +489,15 @@ dt_msg_send_client_response(struct dt_env *env,
struct sockaddr_storage *qsock,
struct sockaddr_storage *rsock,
enum comm_point_type cptype,
void *cpssl,
sldns_buffer *rmsg)
{
struct dt_msg dm;
struct timeval rtime;
if(dt_sample_rate_limited(env))
return;
gettimeofday(&rtime, NULL);
/* type */
@@ -446,8 +512,7 @@ dt_msg_send_client_response(struct dt_env *env,
dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
log_assert(cptype == comm_udp || cptype == comm_tcp);
dt_msg_fill_net(&dm, qsock, rsock, cptype,
dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
&dm.m.query_address, &dm.m.has_query_address,
&dm.m.query_port, &dm.m.has_query_port,
&dm.m.response_address, &dm.m.has_response_address,
@@ -462,6 +527,7 @@ dt_msg_send_outside_query(struct dt_env *env,
struct sockaddr_storage *rsock,
struct sockaddr_storage *qsock,
enum comm_point_type cptype,
void *cpssl,
uint8_t *zone, size_t zone_len,
sldns_buffer *qmsg)
{
@@ -469,11 +535,14 @@ dt_msg_send_outside_query(struct dt_env *env,
struct timeval qtime;
uint16_t qflags;
if(dt_sample_rate_limited(env))
return;
gettimeofday(&qtime, NULL);
qflags = sldns_buffer_read_u16_at(qmsg, 2);
/* type */
if (qflags & BIT_RD) {
if ((qflags & BIT_RD)) {
if (!env->log_forwarder_query_messages)
return;
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY);
@@ -497,8 +566,7 @@ dt_msg_send_outside_query(struct dt_env *env,
dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
log_assert(cptype == comm_udp || cptype == comm_tcp);
dt_msg_fill_net(&dm, rsock, qsock, cptype,
dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
&dm.m.response_address, &dm.m.has_response_address,
&dm.m.response_port, &dm.m.has_response_port,
&dm.m.query_address, &dm.m.has_query_address,
@@ -513,6 +581,7 @@ dt_msg_send_outside_response(struct dt_env *env,
struct sockaddr_storage *rsock,
struct sockaddr_storage *qsock,
enum comm_point_type cptype,
void *cpssl,
uint8_t *zone, size_t zone_len,
uint8_t *qbuf, size_t qbuf_len,
const struct timeval *qtime,
@@ -522,12 +591,15 @@ dt_msg_send_outside_response(struct dt_env *env,
struct dt_msg dm;
uint16_t qflags;
if(dt_sample_rate_limited(env))
return;
(void)qbuf_len; log_assert(qbuf_len >= sizeof(qflags));
memcpy(&qflags, qbuf, sizeof(qflags));
qflags = ntohs(qflags);
/* type */
if (qflags & BIT_RD) {
if ((qflags & BIT_RD)) {
if (!env->log_forwarder_response_messages)
return;
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE);
@@ -556,8 +628,7 @@ dt_msg_send_outside_response(struct dt_env *env,
dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
log_assert(cptype == comm_udp || cptype == comm_tcp);
dt_msg_fill_net(&dm, rsock, qsock, cptype,
dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
&dm.m.response_address, &dm.m.has_response_address,
&dm.m.response_port, &dm.m.has_response_port,
&dm.m.query_address, &dm.m.has_query_address,
+19
View File
@@ -39,6 +39,7 @@
#ifdef USE_DNSTAP
#include "util/locks.h"
struct config_file;
struct sldns_buffer;
struct dt_msg_queue;
@@ -75,6 +76,13 @@ struct dt_env {
unsigned log_forwarder_query_messages : 1;
/** whether to log Message/FORWARDER_RESPONSE */
unsigned log_forwarder_response_messages : 1;
/** lock on sample count */
lock_basic_type sample_lock;
/** rate limit value from config, samples 1/N messages */
unsigned int sample_rate;
/** rate limit counter */
unsigned int sample_rate_count;
};
/**
@@ -98,6 +106,13 @@ dt_create(struct config_file* cfg);
void
dt_apply_cfg(struct dt_env *env, struct config_file *cfg);
/**
* Apply config settings for log enable for message types.
* @param env: dnstap environment object.
* @param cfg: new config settings.
*/
void dt_apply_logcfg(struct dt_env *env, struct config_file *cfg);
/**
* Initialize per-worker state in dnstap environment object.
* @param env: dnstap environment object to initialize, created with dt_create().
@@ -133,6 +148,7 @@ dt_msg_send_client_query(struct dt_env *env,
struct sockaddr_storage *qsock,
struct sockaddr_storage *rsock,
enum comm_point_type cptype,
void *cpssl,
struct sldns_buffer *qmsg,
struct timeval* tstamp);
@@ -149,6 +165,7 @@ dt_msg_send_client_response(struct dt_env *env,
struct sockaddr_storage *qsock,
struct sockaddr_storage *rsock,
enum comm_point_type cptype,
void *cpssl,
struct sldns_buffer *rmsg);
/**
@@ -168,6 +185,7 @@ dt_msg_send_outside_query(struct dt_env *env,
struct sockaddr_storage *rsock,
struct sockaddr_storage *qsock,
enum comm_point_type cptype,
void *cpssl,
uint8_t *zone, size_t zone_len,
struct sldns_buffer *qmsg);
@@ -192,6 +210,7 @@ dt_msg_send_outside_response(struct dt_env *env,
struct sockaddr_storage *rsock,
struct sockaddr_storage *qsock,
enum comm_point_type cptype,
void *cpssl,
uint8_t *zone, size_t zone_len,
uint8_t *qbuf, size_t qbuf_len,
const struct timeval *qtime,
+97 -38
View File
@@ -5,45 +5,104 @@
# Check for required dnstap libraries and add dnstap configure args.
AC_DEFUN([dt_DNSTAP],
[
AC_ARG_ENABLE([dnstap],
AS_HELP_STRING([--enable-dnstap],
[Enable dnstap support (requires protobuf-c)]),
[opt_dnstap=$enableval], [opt_dnstap=no])
AC_ARG_ENABLE([dnstap],
AS_HELP_STRING([--enable-dnstap],
[Enable dnstap support (requires protobuf-c)]),
[opt_dnstap=$enableval],
[opt_dnstap=no])
AC_ARG_WITH([dnstap-socket-path],
AS_HELP_STRING([--with-dnstap-socket-path=pathname],
[set default dnstap socket path]),
[opt_dnstap_socket_path=$withval], [opt_dnstap_socket_path="$1"])
AC_ARG_WITH([dnstap-socket-path],
AS_HELP_STRING([--with-dnstap-socket-path=pathname],
[set default dnstap socket path]),
[opt_dnstap_socket_path=$withval],
[opt_dnstap_socket_path="$1"])
if test "x$opt_dnstap" != "xno"; then
AC_PATH_PROG([PROTOC_C], [protoc-c])
if test -z "$PROTOC_C"; then
AC_MSG_ERROR([The protoc-c program was not found. Please install protobuf-c!])
if test "x$opt_dnstap" != "xno"; then
AC_PATH_PROG([PROTOC], [protoc])
# 'protoc-c' is deprecated. We use 'protoc' instead. If it can not be
# found, try 'protoc-c'.
if test -z "$PROTOC"; then
AC_PATH_PROG([PROTOC_C], [protoc-c])
else
PROTOC_C="$PROTOC"
fi
if test -z "$PROTOC_C"; then
AC_MSG_ERROR([[The protoc or protoc-c program was not found. It is needed for dnstap, use --disable-dnstap, or install protobuf-c to provide protoc or protoc-c]])
fi
# Check for protoc-gen-c plugin
AC_PATH_PROG([PROTOC_GEN_C], [protoc-gen-c])
if test -z "$PROTOC_GEN_C"; then
AC_MSG_ERROR([[The protoc-gen-c plugin was not found. It is needed for dnstap, use --disable-dnstap, or install protobuf-c-compiler to provide protoc-gen-c]])
fi
# Test that protoc-gen-c actually works
AC_MSG_CHECKING([if protoc-gen-c plugin works])
cat > conftest.proto << EOF
syntax = "proto2";
message TestMessage {
optional string test_field = 1;
}
EOF
if $PROTOC_C --c_out=. conftest.proto >/dev/null 2>&1; then
AC_MSG_RESULT([yes])
rm -f conftest.proto conftest.pb-c.c conftest.pb-c.h
else
AC_MSG_RESULT([no])
rm -f conftest.proto conftest.pb-c.c conftest.pb-c.h
AC_MSG_ERROR([[The protoc-gen-c plugin is not working properly. Please ensure protobuf-c-compiler is properly installed]])
fi
AC_ARG_WITH([protobuf-c],
AS_HELP_STRING([--with-protobuf-c=path], [Path where protobuf-c is installed, for dnstap]),
[
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
if test -f $withval/include/google/protobuf-c/protobuf-c.h; then
CFLAGS="$CFLAGS -I$withval/include/google"
else
CFLAGS="$CFLAGS -I$withval/include"
fi
LDFLAGS="$LDFLAGS -L$withval/lib"
],
[
if test -n "$PKG_CONFIG"; then
PKG_CHECK_MODULES([PROTOBUFC], [libprotobuf-c],
[
CFLAGS="$CFLAGS $PROTOBUFC_CFLAGS"
LIBS="$LIBS $PROTOBUFC_LIBS"
],
[
# pkg-config failed; try falling back to known values
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
CFLAGS="$CFLAGS -I/usr/include/google"
else
if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
CFLAGS="$CFLAGS -I/usr/local/include/google"
LDFLAGS="$LDFLAGS -L/usr/local/lib"
else
AC_MSG_ERROR([The protobuf-c package was not found with pkg-config. Please install protobuf-c!])
fi
fi
]
)
else
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
CFLAGS="$CFLAGS -I/usr/include/google"
else
if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
CFLAGS="$CFLAGS -I/usr/local/include/google"
LDFLAGS="$LDFLAGS -L/usr/local/lib"
fi
fi
fi
]
)
AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
AC_MSG_ERROR([The protobuf-c library was not found. Please install the development libraries for protobuf-c!]))
$2
else
$3
fi
AC_ARG_WITH([protobuf-c], AS_HELP_STRING([--with-protobuf-c=path],
[Path where protobuf-c is installed, for dnstap]), [
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
if test -f $withval/include/google/protobuf-c/protobuf-c.h; then
CFLAGS="$CFLAGS -I$withval/include/google"
else
CFLAGS="$CFLAGS -I$withval/include"
fi
LDFLAGS="$LDFLAGS -L$withval/lib"
], [
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
CFLAGS="$CFLAGS -I/usr/include/google"
else
if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
CFLAGS="$CFLAGS -I/usr/local/include/google"
LDFLAGS="$LDFLAGS -L/usr/local/lib"
fi
fi
])
AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
AC_MSG_ERROR([The protobuf-c library was not found. Please install the development libraries for protobuf-c!]))
$2
else
$3
fi
])
+75 -7
View File
@@ -13,8 +13,8 @@
// with this file. If not, see:
//
// <http://creativecommons.org/publicdomain/zero/1.0/>.
syntax = "proto2";
syntax = "proto2";
package dnstap;
// "Dnstap": this is the top-level dnstap type, which is a "union" type that
@@ -56,11 +56,60 @@ enum SocketFamily {
INET6 = 2; // IPv6 (RFC 2460)
}
// SocketProtocol: the transport protocol of a socket. This specifies how to
// interpret "transport port" fields.
// SocketProtocol: the protocol used to transport a DNS message.
enum SocketProtocol {
UDP = 1; // User Datagram Protocol (RFC 768)
TCP = 2; // Transmission Control Protocol (RFC 793)
UDP = 1; // DNS over UDP transport (RFC 1035 section 4.2.1)
TCP = 2; // DNS over TCP transport (RFC 1035 section 4.2.2)
DOT = 3; // DNS over TLS (RFC 7858)
DOH = 4; // DNS over HTTPS (RFC 8484)
DNSCryptUDP = 5; // DNSCrypt over UDP (https://dnscrypt.info/protocol)
DNSCryptTCP = 6; // DNSCrypt over TCP (https://dnscrypt.info/protocol)
DOQ = 7; // DNS over QUIC (RFC 9250)
}
// Policy: information about any name server operator policy
// applied to the processing of a DNS message.
message Policy {
// Match: what aspect of the message or message exchange
// triggered the application of the Policy.
enum Match {
QNAME = 1; // Name in question section of query
CLIENT_IP = 2; // Client IP address
RESPONSE_IP = 3; // Address in A/AAAA RRSet
NS_NAME = 4; // Authoritative name server, by name
NS_IP = 5; // Authoritative name server, by IP address
}
// The Action taken to implement the Policy.
enum Action {
NXDOMAIN = 1; // Respond with NXDOMAIN
NODATA = 2; // Respond with empty answer section
PASS = 3; // Do not alter the response (passthrough)
DROP = 4; // Do not respond.
TRUNCATE = 5; // Truncate UDP response, forcing TCP retry
LOCAL_DATA = 6; // Respond with local data from policy
}
// type: the type of policy applied, e.g. "RPZ" for a
// policy from a Response Policy Zone.
optional string type = 1;
// rule: the rule matched by the message.
//
// In a RPZ context, this is the owner name of the rule in
// the Response Policy Zone in wire format.
optional bytes rule = 2;
// action: the policy action taken in response to the
// rule match.
optional Action action = 3;
// match: the feature of the message exchange which matched the rule.
optional Match match = 4;
// The matched value. Format depends on the matched feature .
optional bytes value = 5;
}
// Message: a wire-format (RFC 1035 section 4) DNS message and associated
@@ -158,6 +207,24 @@ message Message {
// STUB_RESPONSE is a DNS response message sent from a DNS server to a
// stub resolver, from the perspective of the stub resolver.
STUB_RESPONSE = 10;
// TOOL_QUERY is a DNS query message sent from a DNS software tool to a
// DNS server, from the perspective of the tool.
TOOL_QUERY = 11;
// TOOL_RESPONSE is a DNS response message received by a DNS software
// tool from a DNS server, from the perspective of the tool.
TOOL_RESPONSE = 12;
// UPDATE_QUERY is a Dynamic DNS Update request (RFC 2136) received
// by an authoritative name server, from the perspective of the
// authoritative name server.
UPDATE_QUERY = 13;
// UPDATE_RESPONSE is a Dynamic DNS Update response (RFC 2136) sent
// from an authoritative name server, from the perspective of the
// authoritative name server.
UPDATE_RESPONSE = 14;
}
// One of the Type values described above.
@@ -215,6 +282,9 @@ message Message {
// The responder's original wire-format DNS response message, verbatim.
optional bytes response_message = 14;
// Operator policy applied to the processing of this message, if any.
optional Policy policy = 15;
}
// All fields except for 'type' in the Message schema are optional.
@@ -236,7 +306,6 @@ message Message {
// RESOLVER_QUERY:
// socket_family, socket_protocol
// query_name, query_type, query_class
// query_message
// query_time_sec, query_time_nsec
// query_zone
@@ -244,7 +313,6 @@ message Message {
// RESOLVER_RESPONSE:
// socket_family, socket_protocol
// query_name, query_type, query_class
// query_time_sec, query_time_nsec
// query_zone
// response_address, response_port
+61 -10
View File
@@ -176,10 +176,7 @@ void
mq_wakeup_cb(void* arg)
{
struct dt_msg_queue* mq = (struct dt_msg_queue*)arg;
/* even if the dtio is already active, because perhaps much
* traffic suddenly, we leave the timer running to save on
* managing it, the once a second timer is less work then
* starting and stopping the timer frequently */
lock_basic_lock(&mq->dtio->wakeup_timer_lock);
mq->dtio->wakeup_timer_enabled = 0;
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
@@ -210,6 +207,8 @@ dt_msg_queue_start_timer(struct dt_msg_queue* mq, int wakeupnow)
lock_basic_lock(&mq->dtio->wakeup_timer_lock);
if(mq->dtio->wakeup_timer_enabled) {
if(wakeupnow) {
tv.tv_sec = 0;
tv.tv_usec = 0;
comm_timer_set(mq->wakeup_timer, &tv);
}
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
@@ -221,8 +220,14 @@ dt_msg_queue_start_timer(struct dt_msg_queue* mq, int wakeupnow)
if(!wakeupnow) {
tv.tv_sec = 1;
tv.tv_usec = 0;
/* If it is already set, keep it running. */
if(!comm_timer_is_set(mq->wakeup_timer))
comm_timer_set(mq->wakeup_timer, &tv);
} else {
tv.tv_sec = 0;
tv.tv_usec = 0;
comm_timer_set(mq->wakeup_timer, &tv);
}
comm_timer_set(mq->wakeup_timer, &tv);
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
}
@@ -260,8 +265,9 @@ dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len)
/* acquire lock */
lock_basic_lock(&mq->lock);
/* if list was empty, start timer for (eventual) wakeup */
if(mq->first == NULL)
/* if list was empty, start timer for (eventual) wakeup,
* or if dtio is not writing now an eventual wakeup is needed. */
if(mq->first == NULL || !mq->dtio->event_added_is_write)
wakeupstarttimer = 1;
/* if list contains more than wakeupnum elements, wakeup now,
* or if list is (going to be) almost full */
@@ -442,6 +448,9 @@ int dt_io_thread_apply_cfg(struct dt_io_thread* dtio, struct config_file *cfg)
dtio->tls_use_sni = cfg->tls_use_sni;
#endif /* HAVE_SSL */
}
#ifdef HAVE_GETTID
dtio->thread_tid_log = cfg->log_thread_id;
#endif
return 1;
}
@@ -1259,6 +1268,13 @@ static void dtio_sleep(struct dt_io_thread* dtio)
/* unregister the event polling for write, because there is
* nothing to be written */
(void)dtio_add_output_event_read(dtio);
/* Set wakeuptimer enabled off; so that the next worker thread that
* wants to log starts a timer if needed, since the writer thread
* has gone to sleep. */
lock_basic_lock(&dtio->wakeup_timer_lock);
dtio->wakeup_timer_enabled = 0;
lock_basic_unlock(&dtio->wakeup_timer_lock);
}
#ifdef HAVE_SSL
@@ -1322,7 +1338,11 @@ static int dtio_ssl_check_peer(struct dt_io_thread* dtio)
if((SSL_get_verify_mode(dtio->ssl)&SSL_VERIFY_PEER)) {
/* verification */
if(SSL_get_verify_result(dtio->ssl) == X509_V_OK) {
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
X509* x = SSL_get1_peer_certificate(dtio->ssl);
#else
X509* x = SSL_get_peer_certificate(dtio->ssl);
#endif
if(!x) {
verbose(VERB_ALGO, "dnstap io, %s, SSL "
"connection failed no certificate",
@@ -1347,7 +1367,11 @@ static int dtio_ssl_check_peer(struct dt_io_thread* dtio)
#endif
X509_free(x);
} else {
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
X509* x = SSL_get1_peer_certificate(dtio->ssl);
#else
X509* x = SSL_get_peer_certificate(dtio->ssl);
#endif
if(x) {
log_cert(VERB_ALGO, "dnstap io, peer "
"certificate", x);
@@ -1488,9 +1512,11 @@ void dtio_output_cb(int ATTR_UNUSED(fd), short bits, void* arg)
}
#endif
if((bits&UB_EV_READ || dtio->ssl_brief_write)) {
if((bits&UB_EV_READ) || dtio->ssl_brief_write) {
#ifdef HAVE_SSL
if(dtio->ssl_brief_write)
(void)dtio_disable_brief_write(dtio);
#endif
if(dtio->ready_frame_sent && !dtio->accept_frame_received) {
if(dtio_read_accept_frame(dtio) <= 0)
return;
@@ -1513,8 +1539,22 @@ void dtio_output_cb(int ATTR_UNUSED(fd), short bits, void* arg)
/* no messages on the first iteration,
* the queues are all empty */
dtio_sleep(dtio);
/* After putting to sleep, see if
* a message is in a message queue,
* if so, resume service. Stops a
* race condition where a thread could
* have one message but the dtio
* also just went to sleep. With the
* message queued between the
* dtio_find_msg and dtio_sleep
* calls. */
if(dtio_find_msg(dtio)) {
if(!dtio_add_output_event_write(dtio))
return;
}
}
return; /* nothing to do */
if(!dtio->cur_msg)
return; /* nothing to do */
}
}
@@ -2093,7 +2133,18 @@ static void* dnstap_io(void* arg)
struct dt_io_thread* dtio = (struct dt_io_thread*)arg;
time_t secs = 0;
struct timeval now;
log_thread_set(&dtio->threadnum);
const char name[16] = "unbound/dnstap"; /* seems to be the safest size
between different OSes */
#if defined(HAVE_GETTID) && !defined(THREADS_DISABLED)
dtio->thread_tid = gettid();
if(dtio->thread_tid_log)
log_thread_set(&dtio->thread_tid);
else
#endif
log_thread_set(&dtio->threadnum);
ub_thread_setname(dtio->tid, name);
/* setup */
verbose(VERB_ALGO, "start dnstap io thread");
+6
View File
@@ -131,6 +131,12 @@ struct dt_io_thread {
struct dt_io_list_item* io_list_iter;
/** thread id, of the io thread */
ub_thread_type tid;
#ifdef HAVE_GETTID
/** thread tid, the LWP id */
pid_t thread_tid;
/** if logging should include the LWP id */
int thread_tid_log;
#endif
/** if the io processing has started */
int started;
/** ssl context for the io thread, for tls connections. type SSL_CTX* */
+303 -49
View File
@@ -75,17 +75,18 @@
static void usage(char* argv[])
{
printf("usage: %s [options]\n", argv[0]);
printf(" Listen to dnstap messages\n");
printf(" Listen to dnstap messages\n");
printf("stdout has dnstap log, stderr has verbose server log\n");
printf("-u <socketpath> listen to unix socket with this file name\n");
printf("-s <serverip[@port]> listen for TCP on the IP and port\n");
printf("-t <serverip[@port]> listen for TLS on IP and port\n");
printf("-x <server.key> server key file for TLS service\n");
printf("-y <server.pem> server cert file for TLS service\n");
printf("-z <verify.pem> cert file to verify client connections\n");
printf("-l long format for DNS printout\n");
printf("-v more verbose log output\n");
printf("-h this help text\n");
printf("-u <socketpath> listen to unix socket with this file name\n");
printf("-s <serverip[@port]> listen for TCP on the IP and port\n");
printf("-t <serverip[@port]> listen for TLS on IP and port\n");
printf("-x <server.key> server key file for TLS service\n");
printf("-y <server.pem> server cert file for TLS service\n");
printf("-z <verify.pem> cert file to verify client connections\n");
printf("-l long format for DNS printout\n");
printf("-v more verbose log output\n");
printf("-c internal unit test and exit\n");
printf("-h this help text\n");
exit(1);
}
@@ -102,6 +103,14 @@ struct main_tap_data {
struct tap_socket_list* acceptlist;
};
/* list of data */
struct tap_data_list {
/** next in list */
struct tap_data_list* next;
/** the data */
struct tap_data* d;
};
/** tap callback variables */
struct tap_data {
/** the fd */
@@ -128,6 +137,10 @@ struct tap_data {
uint8_t* frame;
/** length of this frame */
size_t len;
/** back pointer to the tap_data_list entry;
* used to NULL the forward pointer to this data
* when this data is freed. */
struct tap_data_list* data_list;
};
/** list of sockets */
@@ -156,8 +169,89 @@ struct tap_socket {
char* ip;
/** for a TLS socket, the tls context */
SSL_CTX* sslctx;
/** dumb way to deal with memory leaks:
* tap_data was only freed on errors and not during exit leading to
* false positives when testing for memory leaks. */
struct tap_data_list* data_list;
};
/** try to delete tail entries from the list if all of them have no data */
static void tap_data_list_try_to_free_tail(struct tap_data_list* list)
{
struct tap_data_list* current = list;
log_assert(!list->d);
if(!list->next) /* we are the last, we can't remove ourselves */
return;
list = list->next;
while(list) {
if(list->d) /* a tail entry still has data; return */
return;
list = list->next;
}
/* keep the next */
list = current->next;
/* the tail will be removed; but not ourselves */
current->next = NULL;
while(list) {
current = list;
list = list->next;
free(current);
}
}
/** delete the tap structure */
static void tap_data_free(struct tap_data* data, int free_tail)
{
if(!data)
return;
if(data->ev) {
ub_event_del(data->ev);
ub_event_free(data->ev);
}
#ifdef HAVE_SSL
SSL_free(data->ssl);
#endif
sock_close(data->fd);
free(data->id);
free(data->frame);
if(data->data_list) {
data->data_list->d = NULL;
if(free_tail)
tap_data_list_try_to_free_tail(data->data_list);
}
free(data);
}
/** insert tap_data in the tap_data_list */
static int tap_data_list_insert(struct tap_data_list** liststart,
struct tap_data* d)
{
struct tap_data_list* entry = (struct tap_data_list*)
malloc(sizeof(*entry));
if(!entry)
return 0;
entry->next = *liststart;
entry->d = d;
d->data_list = entry;
*liststart = entry;
return 1;
}
/** delete the tap_data_list and free any remaining tap_data */
static void tap_data_list_delete(struct tap_data_list* list)
{
struct tap_data_list* e = list, *next;
while(e) {
next = e->next;
if(e->d) {
tap_data_free(e->d, 0);
e->d = NULL;
}
free(e);
e = next;
}
}
/** del the tap event */
static void tap_socket_delev(struct tap_socket* s)
{
@@ -173,7 +267,7 @@ static void tap_socket_close(struct tap_socket* s)
{
if(!s) return;
if(s->fd == -1) return;
close(s->fd);
sock_close(s->fd);
s->fd = -1;
}
@@ -184,6 +278,7 @@ static void tap_socket_delete(struct tap_socket* s)
#ifdef HAVE_SSL
SSL_CTX_free(s->sslctx);
#endif
tap_data_list_delete(s->data_list);
ub_event_free(s->ev);
free(s->socketpath);
free(s->ip);
@@ -235,7 +330,7 @@ static struct tap_socket* tap_socket_new_tcpaccept(char* ip,
/** create new socket (unconnected, not base-added), or NULL malloc fail */
static struct tap_socket* tap_socket_new_tlsaccept(char* ip,
void (*ev_cb)(int, short, void*), void* data, char* server_key,
char* server_cert, char* verifypem)
char* server_cert, char* verifypem, char* tls_protocols)
{
struct tap_socket* s = calloc(1, sizeof(*s));
if(!s) {
@@ -251,7 +346,8 @@ static struct tap_socket* tap_socket_new_tlsaccept(char* ip,
s->fd = -1;
s->ev_cb = ev_cb;
s->data = data;
s->sslctx = listen_sslctx_create(server_key, server_cert, verifypem);
s->sslctx = listen_sslctx_create(server_key, server_cert, verifypem,
NULL, NULL, 0, 0, 0, tls_protocols);
if(!s->sslctx) {
log_err("could not create ssl context");
free(s->ip);
@@ -728,27 +824,12 @@ static ssize_t tap_receive(struct tap_data* data, void* buf, size_t len)
return receive_bytes(data, data->fd, buf, len);
}
/** delete the tap structure */
static void tap_data_free(struct tap_data* data)
{
ub_event_del(data->ev);
ub_event_free(data->ev);
#ifdef HAVE_SSL
SSL_free(data->ssl);
#endif
close(data->fd);
free(data->id);
free(data->frame);
free(data);
}
/** reply with ACCEPT control frame to bidirectional client,
* returns 0 on error */
static int reply_with_accept(struct tap_data* data)
{
#ifdef USE_DNSTAP
/* len includes the escape and framelength */
int r;
size_t len = 0;
void* acceptframe = fstrm_create_control_frame_accept(
DNSTAP_CONTENT_TYPE, &len);
@@ -759,6 +840,8 @@ static int reply_with_accept(struct tap_data* data)
fd_set_block(data->fd);
if(data->ssl) {
#ifdef HAVE_SSL
int r;
if((r=SSL_write(data->ssl, acceptframe, len)) <= 0) {
int r2;
if((r2=SSL_get_error(data->ssl, r)) == SSL_ERROR_ZERO_RETURN)
@@ -769,6 +852,7 @@ static int reply_with_accept(struct tap_data* data)
free(acceptframe);
return 0;
}
#endif
} else {
if(send(data->fd, acceptframe, len, 0) == -1) {
log_err("send failed: %s", sock_strerror(errno));
@@ -804,6 +888,7 @@ static int reply_with_finish(struct tap_data* data)
fd_set_block(data->fd);
if(data->ssl) {
#ifdef HAVE_SSL
int r;
if((r=SSL_write(data->ssl, finishframe, len)) <= 0) {
int r2;
@@ -815,6 +900,7 @@ static int reply_with_finish(struct tap_data* data)
free(finishframe);
return 0;
}
#endif
} else {
if(send(data->fd, finishframe, len, 0) == -1) {
log_err("send failed: %s", sock_strerror(errno));
@@ -842,7 +928,11 @@ static int tap_check_peer(struct tap_data* data)
if((SSL_get_verify_mode(data->ssl)&SSL_VERIFY_PEER)) {
/* verification */
if(SSL_get_verify_result(data->ssl) == X509_V_OK) {
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
X509* x = SSL_get1_peer_certificate(data->ssl);
#else
X509* x = SSL_get_peer_certificate(data->ssl);
#endif
if(!x) {
if(verbosity) log_info("SSL connection %s"
" failed no certificate", data->id);
@@ -864,7 +954,11 @@ static int tap_check_peer(struct tap_data* data)
#endif
X509_free(x);
} else {
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
X509* x = SSL_get1_peer_certificate(data->ssl);
#else
X509* x = SSL_get_peer_certificate(data->ssl);
#endif
if(x) {
if(verbosity)
log_cert(VERB_ALGO, "peer certificate", x);
@@ -906,7 +1000,7 @@ static int tap_handshake(struct tap_data* data)
return 0;
} else if(r == 0) {
/* closed */
tap_data_free(data);
tap_data_free(data, 1);
return 0;
} else if(want == SSL_ERROR_SYSCALL) {
/* SYSCALL and errno==0 means closed uncleanly */
@@ -924,7 +1018,7 @@ static int tap_handshake(struct tap_data* data)
if(!silent)
log_err("SSL_handshake syscall: %s",
strerror(errno));
tap_data_free(data);
tap_data_free(data, 1);
return 0;
} else {
unsigned long err = ERR_get_error();
@@ -934,7 +1028,7 @@ static int tap_handshake(struct tap_data* data)
verbose(VERB_OPS, "ssl handshake failed "
"from %s", data->id);
}
tap_data_free(data);
tap_data_free(data, 1);
return 0;
}
}
@@ -942,7 +1036,7 @@ static int tap_handshake(struct tap_data* data)
data->ssl_handshake_done = 1;
if(!tap_check_peer(data)) {
/* closed */
tap_data_free(data);
tap_data_free(data, 1);
return 0;
}
return 1;
@@ -968,7 +1062,7 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
if(verbosity>=4) log_info("s recv %d", (int)ret);
if(ret == 0) {
/* closed or error */
tap_data_free(data);
tap_data_free(data, 1);
return;
} else if(ret == -1) {
/* continue later */
@@ -990,7 +1084,7 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
data->frame = calloc(1, data->len);
if(!data->frame) {
log_err("out of memory");
tap_data_free(data);
tap_data_free(data, 1);
return;
}
}
@@ -1003,7 +1097,7 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
if(verbosity>=4) log_info("f recv %d", (int)r);
if(r == 0) {
/* closed or error */
tap_data_free(data);
tap_data_free(data, 1);
return;
} else if(r == -1) {
/* continue later */
@@ -1028,13 +1122,13 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
data->is_bidirectional = 1;
if(verbosity) log_info("bidirectional stream");
if(!reply_with_accept(data)) {
tap_data_free(data);
tap_data_free(data, 1);
return;
}
} else if(data->len >= 4 && sldns_read_uint32(data->frame) ==
FSTRM_CONTROL_FRAME_STOP && data->is_bidirectional) {
if(!reply_with_finish(data)) {
tap_data_free(data);
tap_data_free(data, 1);
return;
}
}
@@ -1046,7 +1140,6 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
data->len = 0;
data->len_done = 0;
data->data_done = 0;
}
/** callback for main listening file descriptor */
@@ -1059,7 +1152,9 @@ void dtio_mainfdcallback(int fd, short ATTR_UNUSED(bits), void* arg)
char* id = NULL;
struct sockaddr_storage addr;
socklen_t addrlen = (socklen_t)sizeof(addr);
int s = accept(fd, (struct sockaddr*)&addr, &addrlen);
int s;
memset(&addr, 0, sizeof(addr));
s = accept(fd, (struct sockaddr*)&addr, &addrlen);
if(s == -1) {
#ifndef USE_WINSOCK
/* EINTR is signal interrupt. others are closed connection. */
@@ -1129,6 +1224,8 @@ void dtio_mainfdcallback(int fd, short ATTR_UNUSED(bits), void* arg)
&dtio_tap_callback, data);
if(!data->ev) fatal_exit("could not ub_event_new");
if(ub_event_add(data->ev, NULL) != 0) fatal_exit("could not ub_event_add");
if(!tap_data_list_insert(&tap_sock->data_list, data))
fatal_exit("could not tap_data_list_insert");
}
/** setup local accept sockets */
@@ -1164,13 +1261,13 @@ static void setup_tcp_list(struct main_tap_data* maindata,
/** setup tls accept sockets */
static void setup_tls_list(struct main_tap_data* maindata,
struct config_strlist_head* tls_list, char* server_key,
char* server_cert, char* verifypem)
char* server_cert, char* verifypem, char* tls_protocols)
{
struct config_strlist* item;
for(item = tls_list->first; item; item = item->next) {
struct tap_socket* s;
s = tap_socket_new_tlsaccept(item->str, &dtio_mainfdcallback,
maindata, server_key, server_cert, verifypem);
maindata, server_key, server_cert, verifypem, tls_protocols);
if(!s) fatal_exit("out of memory");
if(!tap_socket_list_insert(&maindata->acceptlist, s))
fatal_exit("out of memory");
@@ -1203,7 +1300,7 @@ static void
setup_and_run(struct config_strlist_head* local_list,
struct config_strlist_head* tcp_list,
struct config_strlist_head* tls_list, char* server_key,
char* server_cert, char* verifypem)
char* server_cert, char* verifypem, char* tls_protocols)
{
time_t secs = 0;
struct timeval now;
@@ -1229,7 +1326,7 @@ setup_and_run(struct config_strlist_head* local_list,
setup_local_list(maindata, local_list);
setup_tcp_list(maindata, tcp_list);
setup_tls_list(maindata, tls_list, server_key, server_cert,
verifypem);
verifypem, tls_protocols);
if(!tap_socket_list_addevs(maindata->acceptlist, base))
fatal_exit("could not setup accept events");
if(verbosity) log_info("start of service");
@@ -1243,6 +1340,114 @@ setup_and_run(struct config_strlist_head* local_list,
free(maindata);
}
/* internal unit tests */
static int internal_unittest()
{
/* unit test tap_data_list_try_to_free_tail() */
#define unit_tap_datas_max 5
struct tap_data* datas[unit_tap_datas_max];
struct tap_data_list* list;
struct tap_socket* socket = calloc(1, sizeof(*socket));
size_t i = 0;
log_assert(socket);
log_assert(unit_tap_datas_max>2); /* needed for the test */
for(i=0; i<unit_tap_datas_max; i++) {
datas[i] = calloc(1, sizeof(struct tap_data));
log_assert(datas[i]);
log_assert(tap_data_list_insert(&socket->data_list, datas[i]));
}
/* sanity base check */
list = socket->data_list;
for(i=0; list; i++) list = list->next;
log_assert(i==unit_tap_datas_max);
/* Free the last data, tail cannot be erased */
list = socket->data_list;
while(list->next) list = list->next;
free(list->d);
list->d = NULL;
tap_data_list_try_to_free_tail(list);
list = socket->data_list;
for(i=0; list; i++) list = list->next;
log_assert(i==unit_tap_datas_max);
/* Free the third to last data, tail cannot be erased */
list = socket->data_list;
for(i=0; i<unit_tap_datas_max-3; i++) list = list->next;
free(list->d);
list->d = NULL;
tap_data_list_try_to_free_tail(list);
list = socket->data_list;
for(i=0; list; i++) list = list->next;
log_assert(i==unit_tap_datas_max);
/* Free the second to last data, try to remove tail from the third
* again, tail (last 2) should be removed */
list = socket->data_list;
for(i=0; i<unit_tap_datas_max-2; i++) list = list->next;
free(list->d);
list->d = NULL;
list = socket->data_list;
while(list->d) list = list->next;
tap_data_list_try_to_free_tail(list);
list = socket->data_list;
for(i=0; list; i++) list = list->next;
log_assert(i==unit_tap_datas_max-2);
/* Free all the remaining data, try to remove tail from the start,
* only the start should remain */
list = socket->data_list;
while(list) {
free(list->d);
list->d = NULL;
list = list->next;
}
tap_data_list_try_to_free_tail(socket->data_list);
list = socket->data_list;
for(i=0; list; i++) list = list->next;
log_assert(i==1);
/* clean up */
tap_data_list_delete(socket->data_list);
free(socket);
/* Start again. Add two elements */
socket = calloc(1, sizeof(*socket));
log_assert(socket);
for(i=0; i<2; i++) {
datas[i] = calloc(1, sizeof(struct tap_data));
log_assert(datas[i]);
log_assert(tap_data_list_insert(&socket->data_list, datas[i]));
}
/* sanity base check */
list = socket->data_list;
for(i=0; list; i++) list = list->next;
log_assert(i==2);
/* Free the last data, tail cannot be erased */
list = socket->data_list;
while(list->next) list = list->next;
free(list->d);
list->d = NULL;
tap_data_list_try_to_free_tail(list);
list = socket->data_list;
for(i=0; list; i++) list = list->next;
log_assert(i==2);
/* clean up */
tap_data_list_delete(socket->data_list);
free(socket);
if(log_get_lock()) {
lock_basic_destroy((lock_basic_type*)log_get_lock());
}
checklock_stop();
#ifdef USE_WINSOCK
WSACleanup();
#endif
return 0;
}
/** getopt global, in case header files fail to declare it. */
extern int optind;
/** getopt global, in case header files fail to declare it. */
@@ -1257,6 +1462,8 @@ int main(int argc, char** argv)
struct config_strlist_head tcp_list;
struct config_strlist_head tls_list;
char* server_key = NULL, *server_cert = NULL, *verifypem = NULL;
char* tls_protocols = "TLSv1.2 TLSv1.3";
#ifdef USE_WINSOCK
WSADATA wsa_data;
if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) {
@@ -1293,7 +1500,7 @@ int main(int argc, char** argv)
#endif
/* command line options */
while( (c=getopt(argc, argv, "hls:t:u:vx:y:z:")) != -1) {
while( (c=getopt(argc, argv, "hcls:t:u:vx:y:z:")) != -1) {
switch(c) {
case 'u':
if(!cfg_strlist_append(&local_list,
@@ -1329,14 +1536,20 @@ int main(int argc, char** argv)
case 'v':
verbosity++;
break;
case 'c':
#ifndef UNBOUND_DEBUG
fatal_exit("-c option needs compilation with "
"--enable-debug");
#endif
return internal_unittest();
case 'h':
case '?':
default:
usage(argv);
}
}
argc -= optind;
argv += optind;
/* argc -= optind; not using further arguments */
/* argv += optind; not using further arguments */
if(usessl) {
#ifdef HAVE_SSL
@@ -1350,21 +1563,32 @@ int main(int argc, char** argv)
#else
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
| OPENSSL_INIT_ADD_ALL_DIGESTS
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
| OPENSSL_INIT_NO_LOAD_CONFIG
# endif
, NULL);
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
(void)SSL_library_init();
#else
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
| OPENSSL_INIT_NO_LOAD_CONFIG
# endif
, NULL);
#endif
#endif /* HAVE_SSL */
}
setup_and_run(&local_list, &tcp_list, &tls_list, server_key,
server_cert, verifypem);
server_cert, verifypem, tls_protocols);
config_delstrlist(local_list.first);
config_delstrlist(tcp_list.first);
config_delstrlist(tls_list.first);
if(log_get_lock()) {
lock_basic_destroy((lock_basic_type*)log_get_lock());
}
checklock_stop();
#ifdef USE_WINSOCK
WSACleanup();
@@ -1572,3 +1796,33 @@ void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg))
{
log_assert(0);
}
void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
void* ATTR_UNUSED(arg))
{
log_assert(0);
}
int fast_reload_client_callback(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply* ATTR_UNUSED(repinfo))
{
log_assert(0);
return 0;
}
#ifdef HAVE_NGTCP2
void doq_client_event_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
void* ATTR_UNUSED(arg))
{
log_assert(0);
}
#endif
#ifdef HAVE_NGTCP2
void doq_client_timer_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
void* ATTR_UNUSED(arg))
{
log_assert(0);
}
#endif
+1799 -22
View File
File diff suppressed because it is too large Load Diff
+4 -5
View File
@@ -19,11 +19,10 @@ The DNSTAP code has BSD license in dnstap/dnstap.c.
* Make and install: ./configure; make; make install
* --with-libevent=/path/to/libevent
Can be set to either the system install or the build directory.
--with-libevent=no (default) gives a builtin alternative
implementation. libevent is useful when having many (thousands)
of outgoing ports. This improves randomization and spoof
resistance. For the default of 16 ports the builtin alternative
works well and is a little faster.
--with-libevent=no gives a builtin alternative implementation.
Libevent is enabled by default, it is useful when having many
(thousands) of outgoing ports. This improves randomization and spoof
resistance. It also allows a higher number of outgoing queries.
* --with-libexpat=/path/to/libexpat
Can be set to the install directory of libexpat.
* --without-pthreads
+3 -3
View File
@@ -13,7 +13,7 @@ If you're not using DNSSEC then you may remove "validator".
2. The "dns64-prefix" directive indicates your DNS64 prefix. For example:
dns64-prefix: 64:FF9B::/96
dns64-prefix: 64:ff9b::/96
The prefix must be a /96 or shorter.
@@ -42,9 +42,9 @@ To enable NAT64 in Unbound, add to unbound.conf's "server" section:
do-nat64: yes
The NAT64 prefix defaults to the DNS64 prefix, which in turn defaults to the
standard 64:FF9B::/96 prefix. You can reconfigure it with:
standard 64:ff9b::/96 prefix. You can reconfigure it with:
nat64-prefix: 64:FF9B::/96
nat64-prefix: 64:ff9b::/96
To test NAT64 operation, pick a domain that only has IPv4 reachability for its
nameservers and try resolving any names in that domain.
+21
View File
@@ -0,0 +1,21 @@
After Unbound 1.23.0, the source of the man pages is in reStructuredText format.
This helps with the online documentation at https://unbound.docs.nlnetlabs.nl
and makes it easier to maintain and contribute to the documentation.
The templated man pages (*.in) are still part of the code repository as to not
alter current procedures that could be in place by users/packagers.
These man pages (*.in) are still the ones being used when
configuring/installing Unbound.
Packagers/users do not have to generate any man pages themselves, this is done
by the core developers during development and upon releasing new versions.
The templated man pages (*.in) are generated by Sphinx (used for the online
documentation).
The online documentation has its own repository at
https://github.com/NLnetLabs/unbound-manual.
In that README.md (https://github.com/NLnetLabs/unbound-manual/README.md)
there are further simple instructions on how to generate the templated man
pages there and update them in this repository.
+179 -39
View File
@@ -54,7 +54,7 @@ server:
# interface: 192.0.2.153
# interface: 192.0.2.154
# interface: 192.0.2.154@5003
# interface: 2001:DB8::5
# interface: 2001:db8::5
# interface: eth0@5003
# enable this feature to copy the source address of queries to reply.
@@ -72,12 +72,12 @@ server:
# server from by ip-address. If none, the default (all) interface
# is used. Specify every interface on a 'outgoing-interface:' line.
# outgoing-interface: 192.0.2.153
# outgoing-interface: 2001:DB8::5
# outgoing-interface: 2001:DB8::6
# outgoing-interface: 2001:db8::5
# outgoing-interface: 2001:db8::6
# Specify a netblock to use remainder 64 bits as random bits for
# upstream queries. Uses freebind option (Linux).
# outgoing-interface: 2001:DB8::/64
# outgoing-interface: 2001:db8::/64
# Also (Linux:) ip -6 addr add 2001:db8::/64 dev lo
# And: ip -6 route add local 2001:db8::/64 dev lo
# And set prefer-ip6: yes to use the ip6 randomness from a netblock.
@@ -116,8 +116,8 @@ server:
# so-rcvbuf: 0
# buffer size for UDP port 53 outgoing (SO_SNDBUF socket option).
# 0 is system default. Use 4m to handle spikes on very busy servers.
# so-sndbuf: 0
# 0 is system default. Set larger to handle spikes on very busy servers.
# so-sndbuf: 4m
# use SO_REUSEPORT to distribute queries over threads.
# at extreme load it could be better to turn it off to distribute even.
@@ -163,7 +163,7 @@ server:
# msg-cache-slabs: 4
# the number of queries that a thread gets to service.
# num-queries-per-thread: 1024
# num-queries-per-thread: 2048
# if very busy, 50% queries run to completion, 50% get timeout in msec
# jostle-timeout: 200
@@ -187,10 +187,47 @@ server:
# query upon encountering a CNAME record.
# max-query-restarts: 11
# Limit on number of NS records in NS RRset for incoming packets.
# iter-scrub-ns: 20
# Limit on number of CNAME, DNAME records for incoming packets.
# iter-scrub-cname: 11
# Limit on number of RRSIGs for an RRset for incoming packets.
# iter-scrub-rrsig: 8
# Limit on upstream queries for an incoming query and its recursion.
# max-global-quota: 200
# Should the scrubber remove promiscuous NS from positive answers,
# protects against poison attempts.
# iter-scrub-promiscuous: yes
# msec for waiting for an unknown server to reply. Increase if you
# are behind a slow satellite link, to eg. 1128.
# unknown-server-time-limit: 376
# msec before recursion replies are dropped. The work item continues.
# discard-timeout: 1900
# Max number of replies waiting for recursion per IP address.
# wait-limit: 1000
# Max replies waiting for recursion for IP address with cookie.
# wait-limit-cookie: 10000
# Apart from the default, the wait limit can be set for a netblock.
# wait-limit-netblock: 192.0.2.0/24 50000
# Apart from the default, the wait limit with cookie can be adjusted.
# wait-limit-cookie-netblock: 192.0.2.0/24 50000
# Defaults for loopback, it has no wait limit.
# wait-limit-netblock: 127.0.0.0/8 -1
# wait-limit-netblock: ::1/128 -1
# wait-limit-cookie-netblock: 127.0.0.0/8 -1
# wait-limit-cookie-netblock: ::1/128 -1
# the amount of memory to use for the RRset cache.
# plain value in bytes or you can append k, m or G. default is "4Mb".
# rrset-cache-size: 4m
@@ -211,6 +248,11 @@ server:
# the time to live (TTL) value cap for negative responses in the cache
# cache-max-negative-ttl: 3600
# the time to live (TTL) value lower bound, in seconds. Default 0.
# For negative responses in the cache. If disabled, default,
# cache-min-ttl applies if configured.
# cache-min-negative-ttl: 0
# the time to live (TTL) value for cached roundtrip times, lameness and
# EDNS version information for hosts. In seconds.
# infra-host-ttl: 900
@@ -244,7 +286,7 @@ server:
# do-ip6: yes
# If running unbound on an IPv6-only host, domains that only have
# IPv4 servers would become unresolveable. If NAT64 is available in
# IPv4 servers would become unresolvable. If NAT64 is available in
# the network, unbound can use NAT64 to reach these servers with
# the following option. This is NOT needed for enabling DNS64 on a
# system that has IPv4 connectivity.
@@ -283,7 +325,8 @@ server:
# Enable EDNS TCP keepalive option.
# edns-tcp-keepalive: no
# Timeout for EDNS TCP keepalive, in msec.
# Timeout for EDNS TCP keepalive, in msec. Overrides tcp-idle-timeout
# if edns-tcp-keepalive is set.
# edns-tcp-keepalive-timeout: 120000
# UDP queries that have waited in the socket buffer for a long time
@@ -303,6 +346,7 @@ server:
# Choose deny (drop message), refuse (polite error reply),
# allow (recursive ok), allow_setrd (recursive ok, rd bit is forced on),
# allow_snoop (recursive and nonrecursive ok)
# allow_cookie (allow UDP with valid cookie or stateful transport)
# deny_non_local (drop queries unless can be answered from local-data)
# refuse_non_local (like deny_non_local but polite error reply).
# access-control: 127.0.0.0/8 allow
@@ -338,7 +382,7 @@ server:
# interface-action: 192.0.2.153 allow
# interface-action: 192.0.2.154 allow
# interface-action: 192.0.2.154@5003 allow
# interface-action: 2001:DB8::5 allow
# interface-action: 2001:db8::5 allow
# interface-action: eth0@5003 allow
# Similar to 'access-control-tag:' but for interfaces.
@@ -430,6 +474,10 @@ server:
# print UTC timestamp in ascii to logfile, default is epoch in seconds.
# log-time-ascii: no
# log timestamp in ISO8601 format if also log-time-ascii is enabled.
# (y-m-dTh:m:s.msec[+-]tzhours:tzminutes)
# log-time-iso: no
# print one line with time, IP, name, type, class for every query.
# log-queries: no
@@ -441,6 +489,9 @@ server:
# filtering log-queries and log-replies from the log.
# log-tag-queryreply: no
# log with destination address, port and type for log-replies.
# log-destaddr: no
# log the local-zone actions, like local-zone type inform is enabled
# also for the other local zone types.
# log-local-actions: no
@@ -448,6 +499,10 @@ server:
# print log lines that say why queries return SERVFAIL to clients.
# log-servfail: no
# log system-wide Linux thread ID, insted of Unbound's internal thread
# counter. Only on Linux and only when threads are available.
# log-thread-id: no
# the pid file. Can be an absolute path outside of chroot/work dir.
# pidfile: "@UNBOUND_PIDFILE@"
@@ -499,6 +554,9 @@ server:
# Harden against out of zone rrsets, to avoid spoofing attempts.
# harden-glue: yes
# Harden against unverified (outside-zone, including sibling zone) glue rrsets
# harden-unverified-glue: no
# Harden against receiving dnssec-stripped data. If you turn it
# off, failing to validate dnskey data for a trustanchor will
# trigger insecure mode for that zone (like without a trustanchor).
@@ -515,8 +573,9 @@ server:
# harden-referral-path: no
# Harden against algorithm downgrade when multiple algorithms are
# advertised in the DS record. If no, allows the weakest algorithm
# to validate the zone.
# advertised in the DS record. If no, allows any algorithm
# to validate the zone which is the standard behavior for validators.
# Check the manpage for detailed information.
# harden-algo-downgrade: no
# Harden against unknown records in the authority section and the
@@ -606,7 +665,7 @@ server:
# or, just before the iterator).
# module-config: "validator iterator"
# File with trusted keys, kept uptodate using RFC5011 probes,
# File with trusted keys, kept up-to-date using RFC5011 probes,
# initial file like trust-anchor-file, then it stores metadata.
# Use several entries, one per domain name, to track multiple zones.
#
@@ -666,7 +725,7 @@ server:
# val-max-restart: 5
# Should additional section of secure message also be kept clean of
# unsecure data. Useful to shield the users of this validator from
# non-secure data. Useful to shield the users of this validator from
# potential bogus data in the additional section. All unsigned data
# in the additional section is removed from secure messages.
# val-clean-additional: yes
@@ -689,12 +748,13 @@ server:
# disable-edns-do: no
# Serve expired responses from cache, with serve-expired-reply-ttl in
# the response, and then attempt to fetch the data afresh.
# the response. By default it first tries to refresh an expired answer.
# Can be configured with serve-expired-client-timeout.
# serve-expired: no
#
# Limit serving of expired responses to configured seconds after
# expiration. 0 disables the limit.
# serve-expired-ttl: 0
# serve-expired-ttl: 86400
#
# Set the TTL of expired records to the serve-expired-ttl value after a
# failed attempt to retrieve the record from upstream. This makes sure
@@ -703,14 +763,14 @@ server:
# serve-expired-ttl-reset: no
#
# TTL value to use when replying with expired data.
# Capped by the original TTL of the record.
# serve-expired-reply-ttl: 30
#
# Time in milliseconds before replying to the client with expired data.
# This essentially enables the serve-stale behavior as specified in
# RFC 8767 that first tries to resolve before
# immediately responding with expired data. 0 disables this behavior.
# A recommended value is 1800.
# serve-expired-client-timeout: 0
# RFC 8767 that first tries to resolve before immediately responding
# with expired data. 0 disables this behavior.
# serve-expired-client-timeout: 1800
# Return the original TTL as received from the upstream name server rather
# than the decrementing TTL as stored in the cache. Enabling this feature
@@ -769,6 +829,8 @@ server:
# local-zone: "127.in-addr.arpa." nodefault
# local-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." nodefault
# local-zone: "home.arpa." nodefault
# local-zone: "resolver.arpa." nodefault
# local-zone: "service.arpa." nodefault
# local-zone: "onion." nodefault
# local-zone: "test." nodefault
# local-zone: "invalid." nodefault
@@ -871,6 +933,22 @@ server:
# add a netblock specific override to a localzone, with zone type
# local-zone-override: "example.com" 192.0.2.0/24 refuse
# Action to apply when the IP address in an AAAA or A RR in the answer
# section of a response matches the specified IP netblock.
# Requires use of the respip module.
# response-ip: 192.0.2.0/24 redirect
# Redirect as specified by the "resource record string" when the IP
# address in an AAAA or A RR in the answer section of a response
# matches the specified IP netblock.
# Requires use of the respip module.
# response-ip-data: 192.0.2.0/24 "example. A 192.0.2.1"
# Apply tag(s) when the IP address in an AAAA or A RR in the answer
# section of a response matches the specified IP netblock.
# Requires use of the respip module.
# response-ip-tag: 192.0.2.0/24 "tag1 tag2"
# service clients over TLS (on the TCP sockets) with plain DNS inside
# the TLS stream, and over HTTPS using HTTP/2 as specified in RFC8484.
# Give the certificate to use and private key.
@@ -879,22 +957,24 @@ server:
# tls-service-pem: "path/to/publiccertfile.pem"
# tls-port: 853
# https-port: 443
# quic-port: 853
# Also serve tls on these port numbers (eg. 443, ...), by listing
# tls-additional-port: portno for each of the port numbers.
# cipher setting for TLSv1.2
# tls-ciphers: "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256"
# cipher setting for TLSv1.3
# tls-ciphersuites: "TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256"
# Pad responses to padded queries received over TLS
# pad-responses: yes
# Padded responses will be padded to the closest multiple of this size.
# pad-responses-block-size: 468
# Use the SNI extension for TLS connections. Default is yes.
# Changing the value requires a reload.
# Changing the value requires a restart.
# tls-use-sni: yes
# TLS protocols.
# Changing the value requires a restart.
# tls-protocols: "TLSv1.2 TLSv1.3"
# Add the secret file for TLS Session Ticket.
# Secret file must be 80 bytes of random data.
# First key use to encrypt and decrypt TLS session tickets.
@@ -915,15 +995,18 @@ server:
# and on other systems, the default openssl certificates
# tls-system-cert: no
# Pad responses to padded queries received over TLS
# pad-responses: yes
# Padded responses will be padded to the closest multiple of this size.
# pad-responses-block-size: 468
# Pad queries over TLS upstreams
# pad-queries: yes
# Padded queries will be padded to the closest multiple of this size.
# pad-queries-block-size: 128
# Also serve tls on these port numbers (eg. 443, ...), by listing
# tls-additional-port: portno for each of the port numbers.
# HTTP endpoint to provide DNS-over-HTTPS service on.
# http-endpoint: "/dns-query"
@@ -943,6 +1026,9 @@ server:
# Disable TLS for DNS-over-HTTP downstream service.
# http-notls-downstream: no
# Maximum number of bytes used for QUIC buffers.
# quic-size: 8m
# The interfaces that use these listed port numbers will support and
# expect PROXYv2. For UDP and TCP/TLS interfaces.
# proxy-protocol-port: portno for each of the port numbers.
@@ -983,6 +1069,13 @@ server:
# if 0(default) it is disabled, otherwise states qps allowed per ip address
# ip-ratelimit: 0
# global query ratelimit for all ip addresses with a valid DNS Cookie.
# feature is experimental.
# if 0(default) it is disabled, otherwise states qps allowed per ip address
# useful in combination with 'allow_cookie'.
# If used, suggested to be higher than ip-ratelimit, tenfold.
# ip-ratelimit-cookie: 0
# ip ratelimits are tracked in a cache, size in bytes of cache (or k,m).
# ip-ratelimit-size: 4m
# ip ratelimit cache slabs, reduces lock contention if equal to cpucount.
@@ -1004,6 +1097,19 @@ server:
# the number of servers that will be used in the fast server selection.
# fast-server-num: 3
# reply to requests containing DNS Cookies as specified in RFC 7873 and RFC 9018.
# answer-cookie: no
# secret for DNS Cookie generation.
# useful for anycast deployments.
# example value "000102030405060708090a0b0c0d0e0f".
# cookie-secret: <128 bit random hex string>
# File with cookie secrets, the 'cookie-secret:' option is ignored
# and the file can be managed to have staging and active secrets
# with remote control commands. Disabled with "". Default is "".
# cookie-secret-file: "/usr/local/etc/unbound_cookiesecrets.txt"
# Enable to attach Extended DNS Error codes (RFC8914) to responses.
# ede: no
@@ -1012,6 +1118,11 @@ server:
# Note that the ede option above needs to be enabled for this to work.
# ede-serve-expired: no
# Enable DNS Error Reporting (RFC9567).
# qname-minimisation is advised to be turned on as well to increase
# privacy on the outgoing reports.
# dns-error-reporting: no
# Specific options for ipsecmod. Unbound needs to be configured with
# --enable-ipsecmod for these to take effect.
#
@@ -1150,7 +1261,7 @@ remote-control:
# sources of notifies.
# auth-zone:
# name: "."
# primary: 199.9.14.201 # b.root-servers.net
# primary: 170.247.170.2 # b.root-servers.net
# primary: 192.33.4.12 # c.root-servers.net
# primary: 199.7.91.13 # d.root-servers.net
# primary: 192.5.5.241 # f.root-servers.net
@@ -1158,7 +1269,7 @@ remote-control:
# primary: 193.0.14.129 # k.root-servers.net
# primary: 192.0.47.132 # xfr.cjr.dns.icann.org
# primary: 192.0.32.132 # xfr.lax.dns.icann.org
# primary: 2001:500:200::b # b.root-servers.net
# primary: 2801:1b8:10::b # b.root-servers.net
# primary: 2001:500:2::c # c.root-servers.net
# primary: 2001:500:2d::d # d.root-servers.net
# primary: 2001:500:2f::f # f.root-servers.net
@@ -1178,10 +1289,11 @@ remote-control:
# zonefile: "example.org.zone"
# Views
# Create named views. Name must be unique. Map views to requests using
# the access-control-view option. Views can contain zero or more local-zone
# and local-data options. Options from matching views will override global
# options. Global options will be used if no matching view is found.
# Create named views. Name must be unique.
# Map views to requests using the access-control-view/interface-view options.
# Views can contain zero or more local-zone and local-data options.
# Options from matching views will override global options.
# Global options will be used if no matching view is found.
# With view-first yes, it will try to answer using the global local-zone and
# local-data elements if there is no view specific match.
# view:
@@ -1189,6 +1301,8 @@ remote-control:
# local-zone: "example.com" redirect
# local-data: "example.com A 192.0.2.3"
# local-data-ptr: "192.0.2.3 www.example.com"
# response-ip: 192.0.2.0/24 redirect
# response-ip-data: 192.0.2.0/24 "example. A 192.0.2.1"
# view-first: no
# view:
# name: "anotherview"
@@ -1228,6 +1342,9 @@ remote-control:
# secret-seed: "default"
# # if the backend should be read from, but not written to.
# cachedb-no-store: no
# # if the cachedb should be checked before a serve-expired response is
# # given, when serve-expired is enabled.
# cachedb-check-when-serve-expired: yes
#
# # For "redis" backend:
# # (to enable, use --with-libhiredis to configure before compiling)
@@ -1236,15 +1353,35 @@ remote-control:
# # redis server's TCP port
# redis-server-port: 6379
# # if the server uses a unix socket, set its path, or "" when not used.
# # redis-server-path: "/var/lib/redis/redis-server.sock"
# redis-server-path: "/var/lib/redis/redis-server.sock"
# # if the server uses an AUTH password, specify here, or "" when not used.
# # redis-server-password: ""
# redis-server-password: ""
# # timeout (in ms) for communication with the redis server
# redis-timeout: 100
# # timeout (in ms) for commands, if 0, uses redis-timeout.
# redis-command-timeout: 0
# # timeout (in ms) for connection set up, if 0, uses redis-timeout.
# redis-connect-timeout: 0
# # set timeout on redis records based on DNS response TTL
# redis-expire-records: no
# # redis logical database to use, 0 is the default database.
# redis-logical-db: 0
# # redis replica server's IP address or host name
# redis-replica-server-host: 127.0.0.1
# # redis replica server's TCP port
# redis-replica-server-port: 6379
# # if the replica server uses a unix socket, set its path, or "" when not used.
# redis-replica-server-path: "/var/lib/redis/redis-server.sock"
# # if the replica server uses an AUTH password, specify here, or "" when not used.
# redis-replica-server-password: ""
# # timeout (in ms) for communication with the redis replica server
# redis-replica-timeout: 100
# # timeout (in ms) for redis replica commands, if 0, uses redis-replica-timeout.
# redis-replica-command-timeout: 0
# # timeout (in ms) for redis replica connection set up, if 0, uses redis-replica-timeout.
# redis-replica-connect-timeout: 0
# # redis logical database to use for the replica server, 0 is the default database.
# redis-replica-logical-db: 0
# IPSet
# Add specify domain into set via ipset.
@@ -1286,6 +1423,8 @@ remote-control:
# dnstap-identity: ""
# # if "" it uses the package version.
# dnstap-version: ""
# # log only 1/N messages, if 0 it is disabled. default 0.
# dnstap-sample-rate: 0
# dnstap-log-resolver-query-messages: no
# dnstap-log-resolver-response-messages: no
# dnstap-log-client-query-messages: no
@@ -1294,7 +1433,8 @@ remote-control:
# dnstap-log-forwarder-response-messages: no
# Response Policy Zones
# RPZ policies. Applied in order of configuration. QNAME, Response IP
# RPZ policies. Applied in order of configuration. Any match from an earlier
# RPZ zone will terminate the RPZ lookup. QNAME, Response IP
# Address, nsdname, nsip and clientip triggers are supported. Supported
# actions are: NXDOMAIN, NODATA, PASSTHRU, DROP, Local Data, tcp-only
# and drop. Policies can be loaded from a file, or using zone
+330 -343
View File
@@ -1,335 +1,306 @@
.TH "libunbound" "3" "@date@" "NLnet Labs" "unbound @version@"
.\"
.\" libunbound.3 -- unbound library functions manual
.\"
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.SH "NAME"
.B libunbound,
.B unbound.h,
.B ub_ctx,
.B ub_result,
.B ub_callback_type,
.B ub_ctx_create,
.B ub_ctx_delete,
.B ub_ctx_set_option,
.B ub_ctx_get_option,
.B ub_ctx_config,
.B ub_ctx_set_fwd,
.B ub_ctx_set_stub,
.B ub_ctx_set_tls,
.B ub_ctx_resolvconf,
.B ub_ctx_hosts,
.B ub_ctx_add_ta,
.B ub_ctx_add_ta_autr,
.B ub_ctx_add_ta_file,
.B ub_ctx_trustedkeys,
.B ub_ctx_debugout,
.B ub_ctx_debuglevel,
.B ub_ctx_async,
.B ub_poll,
.B ub_wait,
.B ub_fd,
.B ub_process,
.B ub_resolve,
.B ub_resolve_async,
.B ub_cancel,
.B ub_resolve_free,
.B ub_strerror,
.B ub_ctx_print_local_zones,
.B ub_ctx_zone_add,
.B ub_ctx_zone_remove,
.B ub_ctx_data_add,
.B ub_ctx_data_remove
\- Unbound DNS validating resolver @version@ functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP
\fIstruct ub_ctx *\fR
\fBub_ctx_create\fR(\fIvoid\fR);
.LP
\fIvoid\fR
\fBub_ctx_delete\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_ctx_set_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar*\fR val);
.LP
\fIint\fR
\fBub_ctx_get_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar**\fR val);
.LP
\fIint\fR
\fBub_ctx_config\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_ctx_set_fwd\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR addr);
.LP
\fIint\fR
\fBub_ctx_set_stub\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR zone,
\fIchar*\fR addr,
.br
\fIint\fR isprime);
.LP
\fIint\fR
\fBub_ctx_set_tls\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR tls);
.LP
\fIint\fR
\fBub_ctx_resolvconf\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_ctx_hosts\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_ctx_add_ta\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR ta);
.LP
\fIint\fR
\fBub_ctx_add_ta_autr\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_ctx_add_ta_file\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_ctx_trustedkeys\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_ctx_debugout\fR(\fIstruct ub_ctx*\fR ctx, \fIFILE*\fR out);
.LP
\fIint\fR
\fBub_ctx_debuglevel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR d);
.LP
\fIint\fR
\fBub_ctx_async\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR dothread);
.LP
\fIint\fR
\fBub_poll\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_wait\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_fd\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_process\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_resolve\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name,
.br
\fIint\fR rrtype, \fIint\fR rrclass, \fIstruct ub_result**\fR result);
.LP
\fIint\fR
\fBub_resolve_async\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name,
.br
\fIint\fR rrtype, \fIint\fR rrclass, \fIvoid*\fR mydata,
.br
\fIub_callback_type\fR callback, \fIint*\fR async_id);
.LP
\fIint\fR
\fBub_cancel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR async_id);
.LP
\fIvoid\fR
\fBub_resolve_free\fR(\fIstruct ub_result*\fR result);
.LP
\fIconst char *\fR
\fBub_strerror\fR(\fIint\fR err);
.LP
\fIint\fR
\fBub_ctx_print_local_zones\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_ctx_zone_add\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR zone_name, \fIchar*\fR zone_type);
.LP
\fIint\fR
\fBub_ctx_zone_remove\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR zone_name);
.LP
\fIint\fR
\fBub_ctx_data_add\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR data);
.LP
\fIint\fR
\fBub_ctx_data_remove\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR data);
.SH "DESCRIPTION"
.B Unbound
is an implementation of a DNS resolver, that does caching and
DNSSEC validation. This is the library API, for using the \-lunbound library.
The server daemon is described in \fIunbound\fR(8).
The library works independent from a running unbound server, and
can be used to convert hostnames to ip addresses, and back,
and obtain other information from the DNS. The library performs public\-key
validation of results with DNSSEC.
.P
The library uses a variable of type \fIstruct ub_ctx\fR to keep context
between calls. The user must maintain it, creating it with
.B ub_ctx_create
and deleting it with
.B ub_ctx_delete\fR.
It can be created and deleted at any time. Creating it anew removes any
previous configuration (such as trusted keys) and clears any cached results.
.P
The functions are thread\-safe, and a context can be used in a threaded (as
well as in a non\-threaded) environment. Also resolution (and validation)
can be performed blocking and non\-blocking (also called asynchronous).
The async method returns from the call immediately, so that processing
can go on, while the results become available later.
.P
.\" Man page generated from reStructuredText.
.
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "LIBUNBOUND" "3" "@date@" "@version@" "Unbound"
.SH NAME
libunbound \- Unbound DNS validating resolver @version@ functions.
.SH SYNOPSIS
.sp
\fB#include <unbound.h>\fP
.sp
struct ub_ctx * \fBub_ctx_create\fP(void);
.sp
void \fBub_ctx_delete\fP(struct ub_ctx* ctx);
.sp
int \fBub_ctx_set_option\fP(struct ub_ctx* ctx, char* opt, char* val);
.sp
int \fBub_ctx_get_option\fP(struct ub_ctx* ctx, char* opt, char** val);
.sp
int \fBub_ctx_config\fP(struct ub_ctx* ctx, char* fname);
.sp
int \fBub_ctx_set_fwd\fP(struct ub_ctx* ctx, char* addr);
.INDENT 0.0
.TP
int \fBub_ctx_set_stub\fP(struct ub_ctx* ctx, char* zone, char* addr,
int isprime);
.UNINDENT
.sp
int \fBub_ctx_set_tls\fP(struct ub_ctx* ctx, int tls);
.sp
int \fBub_ctx_resolvconf\fP(struct ub_ctx* ctx, char* fname);
.sp
int \fBub_ctx_hosts\fP(struct ub_ctx* ctx, char* fname);
.sp
int \fBub_ctx_add_ta\fP(struct ub_ctx* ctx, char* ta);
.sp
int \fBub_ctx_add_ta_autr\fP(struct ub_ctx* ctx, char* fname);
.sp
int \fBub_ctx_add_ta_file\fP(struct ub_ctx* ctx, char* fname);
.sp
int \fBub_ctx_trustedkeys\fP(struct ub_ctx* ctx, char* fname);
.sp
int \fBub_ctx_debugout\fP(struct ub_ctx* ctx, FILE* out);
.sp
int \fBub_ctx_debuglevel\fP(struct ub_ctx* ctx, int d);
.sp
int \fBub_ctx_async\fP(struct ub_ctx* ctx, int dothread);
.sp
int \fBub_poll\fP(struct ub_ctx* ctx);
.sp
int \fBub_wait\fP(struct ub_ctx* ctx);
.sp
int \fBub_fd\fP(struct ub_ctx* ctx);
.sp
int \fBub_process\fP(struct ub_ctx* ctx);
.INDENT 0.0
.TP
int \fBub_resolve\fP(struct ub_ctx* ctx, char* name,
int rrtype, int rrclass, struct ub_result** result);
.TP
int \fBub_resolve_async\fP(struct ub_ctx* ctx, char* name,
int rrtype, int rrclass, void* mydata,
ub_callback_type* callback, int* async_id);
.UNINDENT
.sp
int \fBub_cancel\fP(struct ub_ctx* ctx, int async_id);
.sp
void \fBub_resolve_free\fP(struct ub_result* result);
.sp
const char * \fBub_strerror\fP(int err);
.sp
int \fBub_ctx_print_local_zones\fP(struct ub_ctx* ctx);
.sp
int \fBub_ctx_zone_add\fP(struct ub_ctx* ctx, char* zone_name, char* zone_type);
.sp
int \fBub_ctx_zone_remove\fP(struct ub_ctx* ctx, char* zone_name);
.sp
int \fBub_ctx_data_add\fP(struct ub_ctx* ctx, char* data);
.sp
int \fBub_ctx_data_remove\fP(struct ub_ctx* ctx, char* data);
.SH DESCRIPTION
.sp
Unbound is an implementation of a DNS resolver, that does caching and DNSSEC
validation.
This is the library API, for using the \fB\-lunbound\fP library.
The server daemon is described in \fI\%unbound(8)\fP\&.
The library works independent from a running unbound server, and can be used to
convert hostnames to ip addresses, and back, and obtain other information from
the DNS.
The library performs public\-key validation of results with DNSSEC.
.sp
The library uses a variable of type \fIstruct ub_ctx\fP to keep context between
calls.
The user must maintain it, creating it with \fBub_ctx_create\fP and deleting it
with \fBub_ctx_delete\fP\&.
It can be created and deleted at any time.
Creating it anew removes any previous configuration (such as trusted keys) and
clears any cached results.
.sp
The functions are thread\-safe, and a context can be used in a threaded (as well
as in a non\-threaded) environment.
Also resolution (and validation) can be performed blocking and non\-blocking
(also called asynchronous).
The async method returns from the call immediately, so that processing can go
on, while the results become available later.
.sp
The functions are discussed in turn below.
.SH "FUNCTIONS"
.TP
.SH FUNCTIONS
.INDENT 0.0
.TP
.B ub_ctx_create
Create a new context, initialised with defaults.
The information from /etc/resolv.conf and /etc/hosts is not utilised
by default. Use
.B ub_ctx_resolvconf
and
.B ub_ctx_hosts
to read them.
Before you call this, use the openssl functions CRYPTO_set_id_callback and
CRYPTO_set_locking_callback to set up asynchronous operation if you use
lib openssl (the application calls these functions once for initialisation).
Openssl 1.0.0 or later uses the CRYPTO_THREADID_set_callback function.
The information from \fB/etc/resolv.conf\fP and \fB/etc/hosts\fP is
not utilised by default.
Use \fBub_ctx_resolvconf\fP and \fBub_ctx_hosts\fP to read them.
Before you call this, use the openssl functions
\fBCRYPTO_set_id_callback\fP and \fBCRYPTO_set_locking_callback\fP to set
up asynchronous operation if you use lib openssl (the application calls
these functions once for initialisation).
Openssl 1.0.0 or later uses the \fBCRYPTO_THREADID_set_callback\fP
function.
.TP
.B ub_ctx_delete
Delete validation context and free associated resources.
Outstanding async queries are killed and callbacks are not called for them.
Outstanding async queries are killed and callbacks are not called for
them.
.TP
.B ub_ctx_set_option
A power\-user interface that lets you specify one of the options from the
config file format, see \fIunbound.conf\fR(5). Not all options are
relevant. For some specific options, such as adding trust anchors, special
routines exist. Pass the option name with the trailing ':'.
A power\-user interface that lets you specify one of the options from
the config file format, see \fI\%unbound.conf(5)\fP\&.
Not all options are relevant.
For some specific options, such as adding trust anchors, special
routines exist.
Pass the option name with the trailing \fB\(aq:\(aq\fP\&.
.TP
.B ub_ctx_get_option
A power\-user interface that gets an option value. Some options cannot be
gotten, and others return a newline separated list. Pass the option name
without trailing ':'. The returned value must be free(2)d by the caller.
A power\-user interface that gets an option value.
Some options cannot be gotten, and others return a newline separated
list.
Pass the option name without trailing \fB\(aq:\(aq\fP\&.
The returned value must be free(2)d by the caller.
.TP
.B ub_ctx_config
A power\-user interface that lets you specify an unbound config file, see
\fIunbound.conf\fR(5), which is read for configuration. Not all options are
relevant. For some specific options, such as adding trust anchors, special
routines exist. This function is thread\-safe only if a single instance of
ub_ctx* exists in the application. If several instances exist the
application has to ensure that ub_ctx_config is not called in parallel by
the different instances.
A power\-user interface that lets you specify an unbound config file,
see \fI\%unbound.conf(5)\fP, which is read for
configuration.
Not all options are relevant.
For some specific options, such as adding trust anchors, special
routines exist.
This function is thread\-safe only if a single instance of \fBub_ctx\fP*
exists in the application.
If several instances exist the application has to ensure that
\fBub_ctx_config\fP is not called in parallel by the different instances.
.TP
.B ub_ctx_set_fwd
Set machine to forward DNS queries to, the caching resolver to use.
IP4 or IP6 address. Forwards all DNS requests to that machine, which
is expected to run a recursive resolver. If the proxy is not
DNSSEC capable, validation may fail. Can be called several times, in
that case the addresses are used as backup servers.
At this time it is only possible to set configuration before the
first resolve is done.
Set machine to forward DNS queries to, the caching resolver to use.
IP4 or IP6 address.
Forwards all DNS requests to that machine, which is expected to run a
recursive resolver.
If the proxy is not DNSSEC capable, validation may fail.
Can be called several times, in that case the addresses are used as
backup servers.
At this time it is only possible to set configuration before the first
resolve is done.
.TP
.B ub_ctx_set_stub
Set a stub zone, authoritative dns servers to use for a particular zone.
IP4 or IP6 address. If the address is NULL the stub entry is removed.
Set isprime true if you configure root hints with it. Otherwise similar to
the stub zone item from unbound's config file. Can be called several times,
for different zones, or to add multiple addresses for a particular zone.
At this time it is only possible to set configuration before the
first resolve is done.
Set a stub zone, authoritative dns servers to use for a particular
zone.
IP4 or IP6 address.
If the address is NULL the stub entry is removed.
Set isprime true if you configure root hints with it.
Otherwise similar to the stub zone item from unbound\(aqs config file.
Can be called several times, for different zones, or to add multiple
addresses for a particular zone.
At this time it is only possible to set configuration before the first
resolve is done.
.TP
.B ub_ctx_set_tls
Enable DNS over TLS (DoT) for machines set with
.B ub_ctx_set_fwd.
At this time it is only possible to set configuration before the
first resolve is done.
Enable DNS over TLS (DoT) for machines set with \fBub_ctx_set_fwd\fP\&.
At this time it is only possible to set configuration before the first
resolve is done.
.TP
.B ub_ctx_resolvconf
By default the root servers are queried and full resolver mode is used, but
you can use this call to read the list of nameservers to use from the
filename given.
Usually "/etc/resolv.conf". Uses those nameservers as caching proxies.
By default the root servers are queried and full resolver mode is used,
but you can use this call to read the list of nameservers to use from
the filename given.
Usually \fB\(dq/etc/resolv.conf\(dq\fP\&.
Uses those nameservers as caching proxies.
If they do not support DNSSEC, validation may fail.
Only nameservers are picked up, the searchdomain, ndots and other
settings from \fIresolv.conf\fR(5) are ignored.
If fname NULL is passed, "/etc/resolv.conf" is used (if on Windows,
the system\-wide configured nameserver is picked instead).
At this time it is only possible to set configuration before the
first resolve is done.
settings from \fIresolv.conf(5)\fP are ignored.
If fname NULL is passed, \fB\(dq/etc/resolv.conf\(dq\fP is used (if on
Windows, the system\-wide configured nameserver is picked instead).
At this time it is only possible to set configuration before the first
resolve is done.
.TP
.B ub_ctx_hosts
Read list of hosts from the filename given.
Usually "/etc/hosts". When queried for, these addresses are not marked
DNSSEC secure. If fname NULL is passed, "/etc/hosts" is used
(if on Windows, etc/hosts from WINDIR is picked instead).
At this time it is only possible to set configuration before the
first resolve is done.
Usually \fB\(dq/etc/hosts\(dq\fP\&.
When queried for, these addresses are not marked DNSSEC secure.
If fname NULL is passed, \fB\(dq/etc/hosts\(dq\fP is used (if on Windows,
\fBetc/hosts\fP from WINDIR is picked instead).
At this time it is only possible to set configuration before the first
resolve is done.
.TP
.B
ub_ctx_add_ta
.B ub_ctx_add_ta
Add a trust anchor to the given context.
At this time it is only possible to add trusted keys before the
first resolve is done.
At this time it is only possible to add trusted keys before the first
resolve is done.
The format is a string, similar to the zone\-file format,
[domainname] [type] [rdata contents]. Both DS and DNSKEY records are accepted.
\fB[domainname]\fP \fB[type]\fP \fB[rdata contents]\fP\&.
Both DS and DNSKEY records are accepted.
.TP
.B ub_ctx_add_ta_autr
Add filename with automatically tracked trust anchor to the given context.
Pass name of a file with the managed trust anchor. You can create this
file with \fIunbound\-anchor\fR(8) for the root anchor. You can also
create it with an initial file with one line with a DNSKEY or DS record.
Add filename with automatically tracked trust anchor to the given
context.
Pass name of a file with the managed trust anchor.
You can create this file with
\fI\%unbound\-anchor(8)\fP for the root anchor.
You can also create it with an initial file with one line with a DNSKEY
or DS record.
If the file is writable, it is updated when the trust anchor changes.
At this time it is only possible to add trusted keys before the
first resolve is done.
At this time it is only possible to add trusted keys before the first
resolve is done.
.TP
.B ub_ctx_add_ta_file
Add trust anchors to the given context.
Pass name of a file with DS and DNSKEY records in zone file format.
At this time it is only possible to add trusted keys before the
first resolve is done.
At this time it is only possible to add trusted keys before the first
resolve is done.
.TP
.B ub_ctx_trustedkeys
Add trust anchors to the given context.
Pass the name of a bind\-style config file with trusted\-keys{}.
At this time it is only possible to add trusted keys before the
first resolve is done.
Pass the name of a bind\-style config file with \fBtrusted\-keys{}\fP\&.
At this time it is only possible to add trusted keys before the first
resolve is done.
.TP
.B ub_ctx_debugout
Set debug and error log output to the given stream. Pass NULL to disable
output. Default is stderr. File\-names or using syslog can be enabled
using config options, this routine is for using your own stream.
Set debug and error log output to the given stream.
Pass NULL to disable output.
Default is stderr.
File\-names or using syslog can be enabled using config options, this
routine is for using your own stream.
.TP
.B ub_ctx_debuglevel
Set debug verbosity for the context. Output is directed to stderr.
Set debug verbosity for the context.
Output is directed to stderr.
Higher debug level gives more output.
.TP
.B ub_ctx_async
Set a context behaviour for asynchronous action.
if set to true, enables threading and a call to
.B ub_resolve_async
if set to true, enables threading and a call to \fBub_resolve_async\fP
creates a thread to handle work in the background.
If false, a process is forked to handle work in the background.
Changes to this setting after
.B ub_resolve_async
calls have been made have no effect (delete and re\-create the context
to change).
Changes to this setting after \fBub_resolve_async\fP calls have been made
have no effect (delete and re\-create the context to change).
.TP
.B ub_poll
Poll a context to see if it has any new results.
Do not poll in a loop, instead extract the fd below to poll for readiness,
and then check, or wait using the wait routine.
Do not poll in a loop, instead extract the \fBfd\fP below to poll for
readiness, and then check, or wait using the wait routine.
Returns 0 if nothing to read, or nonzero if a result is available.
If nonzero, call
.B ub_process
to do callbacks.
If nonzero, call \fBub_process\fP to do callbacks.
.TP
.B ub_wait
Wait for a context to finish with results. Calls
.B ub_process
after the wait for you. After the wait, there are no more outstanding
asynchronous queries.
Wait for a context to finish with results.
Calls \fBub_process\fP after the wait for you.
After the wait, there are no more outstanding asynchronous queries.
.TP
.B ub_fd
Get file descriptor. Wait for it to become readable, at this point
answers are returned from the asynchronous validating resolver.
Then call the \fBub_process\fR to continue processing.
Get file descriptor.
Wait for it to become readable, at this point answers are returned from
the asynchronous validating resolver.
Then call the \fBub_process\fP to continue processing.
.TP
.B ub_process
Call this routine to continue processing results from the validating
resolver (when the fd becomes readable).
resolver (when the \fBfd\fP becomes readable).
Will perform necessary callbacks.
.TP
.B ub_resolve
@@ -340,95 +311,111 @@ The result structure is newly allocated with the resulting data.
.TP
.B ub_resolve_async
Perform asynchronous resolution and validation of the target name.
Arguments mean the same as for \fBub_resolve\fR except no
data is returned immediately, instead a callback is called later.
The callback receives a copy of the mydata pointer, that you can use to pass
information to the callback. The callback type is a function pointer to
a function declared as
.IP
void my_callback_function(void* my_arg, int err,
.br
struct ub_result* result);
.IP
The async_id is returned so you can (at your option) decide to track it
and cancel the request if needed. If you pass a NULL pointer the async_id
is not returned.
Arguments mean the same as for \fBub_resolve\fP except no data is
returned immediately, instead a callback is called later.
The callback receives a copy of the mydata pointer, that you can use to
pass information to the callback.
The callback type is a function pointer to a function declared as:
.INDENT 7.0
.INDENT 3.5
.sp
.nf
.ft C
void my_callback_function(void* my_arg, int err,
struct ub_result* result);
.ft P
.fi
.UNINDENT
.UNINDENT
.sp
The \fBasync_id\fP is returned so you can (at your option) decide to
track it and cancel the request if needed.
If you pass a NULL pointer the \fBasync_id\fP is not returned.
.TP
.B ub_cancel
Cancel an async query in progress. This may return an error if the query
does not exist, or the query is already being delivered, in that case you
may still get a callback for the query.
Cancel an async query in progress.
This may return an error if the query does not exist, or the query is
already being delivered, in that case you may still get a callback for
the query.
.TP
.B ub_resolve_free
Free struct ub_result contents after use.
Free struct \fBub_result\fP contents after use.
.TP
.B ub_strerror
Convert error value from one of the unbound library functions
to a human readable string.
Convert error value from one of the unbound library functions to a
human readable string.
.TP
.B ub_ctx_print_local_zones
Debug printout the local authority information to debug output.
.TP
.B ub_ctx_zone_add
Add new zone to local authority info, like local\-zone \fIunbound.conf\fR(5)
statement.
Add new zone to local authority info, like local\-zone
\fI\%unbound.conf(5)\fP statement.
.TP
.B ub_ctx_zone_remove
Delete zone from local authority info.
.TP
.B ub_ctx_data_add
Add resource record data to local authority info, like local\-data
\fIunbound.conf\fR(5) statement.
\fI\%unbound.conf(5)\fP statement.
.TP
.B ub_ctx_data_remove
Delete local authority data from the name given.
.SH "RESULT DATA STRUCTURE"
The result of the DNS resolution and validation is returned as
\fIstruct ub_result\fR. The result structure contains the following entries.
.P
.UNINDENT
.SH RESULT DATA STRUCTURE
.sp
The result of the DNS resolution and validation is returned as \fIstruct
ub_result\fP\&.
The result structure contains the following entries:
.INDENT 0.0
.INDENT 3.5
.sp
.nf
struct ub_result {
char* qname; /* text string, original question */
int qtype; /* type code asked for */
int qclass; /* class code asked for */
char** data; /* array of rdata items, NULL terminated*/
int* len; /* array with lengths of rdata items */
char* canonname; /* canonical name of result */
int rcode; /* additional error code in case of no data */
void* answer_packet; /* full network format answer packet */
int answer_len; /* length of packet in octets */
int havedata; /* true if there is data */
int nxdomain; /* true if nodata because name does not exist */
int secure; /* true if result is secure */
int bogus; /* true if a security failure happened */
char* why_bogus; /* string with error if bogus */
int was_ratelimited; /* true if the query was ratelimited (SERVFAIL) by unbound */
int ttl; /* number of seconds the result is valid */
};
.ft C
struct ub_result {
char* qname; /* text string, original question */
int qtype; /* type code asked for */
int qclass; /* class code asked for */
char** data; /* array of rdata items, NULL terminated*/
int* len; /* array with lengths of rdata items */
char* canonname; /* canonical name of result */
int rcode; /* additional error code in case of no data */
void* answer_packet; /* full network format answer packet */
int answer_len; /* length of packet in octets */
int havedata; /* true if there is data */
int nxdomain; /* true if nodata because name does not exist */
int secure; /* true if result is secure */
int bogus; /* true if a security failure happened */
char* why_bogus; /* string with error if bogus */
int was_ratelimited; /* true if the query was ratelimited (SERVFAIL) by unbound */
int ttl; /* number of seconds the result is valid */
};
.ft P
.fi
.P
If both secure and bogus are false, security was not enabled for the
domain of the query. Else, they are not both true, one of them is true.
.SH "RETURN VALUES"
Many routines return an error code. The value 0 (zero) denotes no error
happened. Other values can be passed to
.B ub_strerror
to obtain a readable error string.
.B ub_strerror
returns a zero terminated string.
.B ub_ctx_create
returns NULL on an error (a malloc failure).
.B ub_poll
returns true if some information may be available, false otherwise.
.B ub_fd
returns a file descriptor or \-1 on error.
.B ub_ctx_config
and
.B ub_ctx_resolvconf
attempt to leave errno informative on a function return with file read failure.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
\fIunbound\fR(8).
.SH "AUTHORS"
.B Unbound
developers are mentioned in the CREDITS file in the distribution.
.UNINDENT
.UNINDENT
.sp
If both secure and bogus are false, security was not enabled for the domain of
the query.
Else, they are not both true, one of them is true.
.SH RETURN VALUES
.sp
Many routines return an error code.
The value 0 (zero) denotes no error happened.
Other values can be passed to \fBub_strerror\fP to obtain a readable error
string.
\fBub_strerror\fP returns a zero terminated string.
\fBub_ctx_create\fP returns NULL on an error (a malloc failure).
\fBub_poll\fP returns true if some information may be available, false otherwise.
\fBub_fd\fP returns a file descriptor or \-1 on error.
\fBub_ctx_config\fP and \fBub_ctx_resolvconf\fP attempt to leave errno informative
on a function return with file read failure.
.SH SEE ALSO
.sp
\fI\%unbound.conf(5)\fP, \fI\%unbound(8)\fP\&.
.SH AUTHOR
Unbound developers are mentioned in the CREDITS file in the distribution.
.SH COPYRIGHT
1999-2026, NLnet Labs
.\" Generated by docutils manpage writer.
.
+491
View File
@@ -0,0 +1,491 @@
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
libunbound(3)
=============
Synopsis
--------
.. only:: html
.. code-block:: c
#include <unbound.h>
struct ub_ctx * ub_ctx_create(void);
void ub_ctx_delete(struct ub_ctx* ctx);
int ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val);
int ub_ctx_get_option(struct ub_ctx* ctx, char* opt, char** val);
int ub_ctx_config(struct ub_ctx* ctx, char* fname);
int ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr);
int ub_ctx_set_stub(struct ub_ctx* ctx, char* zone, char* addr,
int isprime);
int ub_ctx_set_tls(struct ub_ctx* ctx, int tls);
int ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname);
int ub_ctx_hosts(struct ub_ctx* ctx, char* fname);
int ub_ctx_add_ta(struct ub_ctx* ctx, char* ta);
int ub_ctx_add_ta_autr(struct ub_ctx* ctx, char* fname);
int ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname);
int ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname);
int ub_ctx_debugout(struct ub_ctx* ctx, FILE* out);
int ub_ctx_debuglevel(struct ub_ctx* ctx, int d);
int ub_ctx_async(struct ub_ctx* ctx, int dothread);
int ub_poll(struct ub_ctx* ctx);
int ub_wait(struct ub_ctx* ctx);
int ub_fd(struct ub_ctx* ctx);
int ub_process(struct ub_ctx* ctx);
int ub_resolve(struct ub_ctx* ctx, char* name, int rrtype,
int rrclass, struct ub_result** result);
int ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype,
int rrclass, void* mydata, ub_callback_type callback,
int* async_id);
int ub_cancel(struct ub_ctx* ctx, int async_id);
void ub_resolve_free(struct ub_result* result);
const char * ub_strerror(int err);
int ub_ctx_print_local_zones(struct ub_ctx* ctx);
int ub_ctx_zone_add(struct ub_ctx* ctx, char* zone_name, char* zone_type);
int ub_ctx_zone_remove(struct ub_ctx* ctx, char* zone_name);
int ub_ctx_data_add(struct ub_ctx* ctx, char* data);
int ub_ctx_data_remove(struct ub_ctx* ctx, char* data);
.. only:: man
**#include <unbound.h>**
struct ub_ctx \* **ub_ctx_create**\ (void);
void **ub_ctx_delete**\ (struct ub_ctx\* ctx);
int **ub_ctx_set_option**\ (struct ub_ctx\* ctx, char\* opt, char\* val);
int **ub_ctx_get_option**\ (struct ub_ctx\* ctx, char\* opt, char\*\* val);
int **ub_ctx_config**\ (struct ub_ctx\* ctx, char* fname);
int **ub_ctx_set_fwd**\ (struct ub_ctx\* ctx, char\* addr);
int **ub_ctx_set_stub**\ (struct ub_ctx\* ctx, char\* zone, char\* addr,
int isprime);
int **ub_ctx_set_tls**\ (struct ub_ctx\* ctx, int tls);
int **ub_ctx_resolvconf**\ (struct ub_ctx\* ctx, char\* fname);
int **ub_ctx_hosts**\ (struct ub_ctx\* ctx, char\* fname);
int **ub_ctx_add_ta**\ (struct ub_ctx\* ctx, char\* ta);
int **ub_ctx_add_ta_autr**\ (struct ub_ctx\* ctx, char\* fname);
int **ub_ctx_add_ta_file**\ (struct ub_ctx\* ctx, char\* fname);
int **ub_ctx_trustedkeys**\ (struct ub_ctx\* ctx, char\* fname);
int **ub_ctx_debugout**\ (struct ub_ctx\* ctx, FILE\* out);
int **ub_ctx_debuglevel**\ (struct ub_ctx\* ctx, int d);
int **ub_ctx_async**\ (struct ub_ctx\* ctx, int dothread);
int **ub_poll**\ (struct ub_ctx\* ctx);
int **ub_wait**\ (struct ub_ctx\* ctx);
int **ub_fd**\ (struct ub_ctx\* ctx);
int **ub_process**\ (struct ub_ctx\* ctx);
int **ub_resolve**\ (struct ub_ctx\* ctx, char\* name,
int rrtype, int rrclass, struct ub_result\*\* result);
int **ub_resolve_async**\ (struct ub_ctx\* ctx, char\* name,
int rrtype, int rrclass, void\* mydata,
ub_callback_type\* callback, int\* async_id);
int **ub_cancel**\ (struct ub_ctx\* ctx, int async_id);
void **ub_resolve_free**\ (struct ub_result\* result);
const char \* **ub_strerror**\ (int err);
int **ub_ctx_print_local_zones**\ (struct ub_ctx\* ctx);
int **ub_ctx_zone_add**\ (struct ub_ctx\* ctx, char\* zone_name, char\* zone_type);
int **ub_ctx_zone_remove**\ (struct ub_ctx\* ctx, char\* zone_name);
int **ub_ctx_data_add**\ (struct ub_ctx\* ctx, char\* data);
int **ub_ctx_data_remove**\ (struct ub_ctx\* ctx, char\* data);
Description
-----------
Unbound is an implementation of a DNS resolver, that does caching and DNSSEC
validation.
This is the library API, for using the ``-lunbound`` library.
The server daemon is described in :doc:`unbound(8)</manpages/unbound>`.
The library works independent from a running unbound server, and can be used to
convert hostnames to ip addresses, and back, and obtain other information from
the DNS.
The library performs public-key validation of results with DNSSEC.
The library uses a variable of type *struct ub_ctx* to keep context between
calls.
The user must maintain it, creating it with **ub_ctx_create** and deleting it
with **ub_ctx_delete**.
It can be created and deleted at any time.
Creating it anew removes any previous configuration (such as trusted keys) and
clears any cached results.
The functions are thread-safe, and a context can be used in a threaded (as well
as in a non-threaded) environment.
Also resolution (and validation) can be performed blocking and non-blocking
(also called asynchronous).
The async method returns from the call immediately, so that processing can go
on, while the results become available later.
The functions are discussed in turn below.
Functions
---------
.. glossary::
ub_ctx_create
Create a new context, initialised with defaults.
The information from :file:`/etc/resolv.conf` and :file:`/etc/hosts` is
not utilised by default.
Use **ub_ctx_resolvconf** and **ub_ctx_hosts** to read them.
Before you call this, use the openssl functions
**CRYPTO_set_id_callback** and **CRYPTO_set_locking_callback** to set
up asynchronous operation if you use lib openssl (the application calls
these functions once for initialisation).
Openssl 1.0.0 or later uses the **CRYPTO_THREADID_set_callback**
function.
ub_ctx_delete
Delete validation context and free associated resources.
Outstanding async queries are killed and callbacks are not called for
them.
ub_ctx_set_option
A power-user interface that lets you specify one of the options from
the config file format, see :doc:`unbound.conf(5)</manpages/unbound.conf>`.
Not all options are relevant.
For some specific options, such as adding trust anchors, special
routines exist.
Pass the option name with the trailing ``':'``.
ub_ctx_get_option
A power-user interface that gets an option value.
Some options cannot be gotten, and others return a newline separated
list.
Pass the option name without trailing ``':'``.
The returned value must be free(2)d by the caller.
ub_ctx_config
A power-user interface that lets you specify an unbound config file,
see :doc:`unbound.conf(5)</manpages/unbound.conf>`, which is read for
configuration.
Not all options are relevant.
For some specific options, such as adding trust anchors, special
routines exist.
This function is thread-safe only if a single instance of **ub_ctx**\*
exists in the application.
If several instances exist the application has to ensure that
**ub_ctx_config** is not called in parallel by the different instances.
ub_ctx_set_fwd
Set machine to forward DNS queries to, the caching resolver to use.
IP4 or IP6 address.
Forwards all DNS requests to that machine, which is expected to run a
recursive resolver.
If the proxy is not DNSSEC capable, validation may fail.
Can be called several times, in that case the addresses are used as
backup servers.
At this time it is only possible to set configuration before the first
resolve is done.
ub_ctx_set_stub
Set a stub zone, authoritative dns servers to use for a particular
zone.
IP4 or IP6 address.
If the address is NULL the stub entry is removed.
Set isprime true if you configure root hints with it.
Otherwise similar to the stub zone item from unbound's config file.
Can be called several times, for different zones, or to add multiple
addresses for a particular zone.
At this time it is only possible to set configuration before the first
resolve is done.
ub_ctx_set_tls
Enable DNS over TLS (DoT) for machines set with **ub_ctx_set_fwd**.
At this time it is only possible to set configuration before the first
resolve is done.
ub_ctx_resolvconf
By default the root servers are queried and full resolver mode is used,
but you can use this call to read the list of nameservers to use from
the filename given.
Usually :file:`"/etc/resolv.conf"`.
Uses those nameservers as caching proxies.
If they do not support DNSSEC, validation may fail.
Only nameservers are picked up, the searchdomain, ndots and other
settings from *resolv.conf(5)* are ignored.
If fname NULL is passed, :file:`"/etc/resolv.conf"` is used (if on
Windows, the system-wide configured nameserver is picked instead).
At this time it is only possible to set configuration before the first
resolve is done.
ub_ctx_hosts
Read list of hosts from the filename given.
Usually :file:`"/etc/hosts"`.
When queried for, these addresses are not marked DNSSEC secure.
If fname NULL is passed, :file:`"/etc/hosts"` is used (if on Windows,
:file:`etc/hosts` from WINDIR is picked instead).
At this time it is only possible to set configuration before the first
resolve is done.
ub_ctx_add_ta
Add a trust anchor to the given context.
At this time it is only possible to add trusted keys before the first
resolve is done.
The format is a string, similar to the zone-file format,
**[domainname]** **[type]** **[rdata contents]**.
Both DS and DNSKEY records are accepted.
ub_ctx_add_ta_autr
Add filename with automatically tracked trust anchor to the given
context.
Pass name of a file with the managed trust anchor.
You can create this file with
:doc:`unbound-anchor(8)</manpages/unbound-anchor>` for the root anchor.
You can also create it with an initial file with one line with a DNSKEY
or DS record.
If the file is writable, it is updated when the trust anchor changes.
At this time it is only possible to add trusted keys before the first
resolve is done.
ub_ctx_add_ta_file
Add trust anchors to the given context.
Pass name of a file with DS and DNSKEY records in zone file format.
At this time it is only possible to add trusted keys before the first
resolve is done.
ub_ctx_trustedkeys
Add trust anchors to the given context.
Pass the name of a bind-style config file with ``trusted-keys{}``.
At this time it is only possible to add trusted keys before the first
resolve is done.
ub_ctx_debugout
Set debug and error log output to the given stream.
Pass NULL to disable output.
Default is stderr.
File-names or using syslog can be enabled using config options, this
routine is for using your own stream.
ub_ctx_debuglevel
Set debug verbosity for the context.
Output is directed to stderr.
Higher debug level gives more output.
ub_ctx_async
Set a context behaviour for asynchronous action.
if set to true, enables threading and a call to **ub_resolve_async**
creates a thread to handle work in the background.
If false, a process is forked to handle work in the background.
Changes to this setting after **ub_resolve_async** calls have been made
have no effect (delete and re-create the context to change).
ub_poll
Poll a context to see if it has any new results.
Do not poll in a loop, instead extract the **fd** below to poll for
readiness, and then check, or wait using the wait routine.
Returns 0 if nothing to read, or nonzero if a result is available.
If nonzero, call **ub_process** to do callbacks.
ub_wait
Wait for a context to finish with results.
Calls **ub_process** after the wait for you.
After the wait, there are no more outstanding asynchronous queries.
ub_fd
Get file descriptor.
Wait for it to become readable, at this point answers are returned from
the asynchronous validating resolver.
Then call the **ub_process** to continue processing.
ub_process
Call this routine to continue processing results from the validating
resolver (when the **fd** becomes readable).
Will perform necessary callbacks.
ub_resolve
Perform resolution and validation of the target name.
The name is a domain name in a zero terminated text string.
The rrtype and rrclass are DNS type and class codes.
The result structure is newly allocated with the resulting data.
ub_resolve_async
Perform asynchronous resolution and validation of the target name.
Arguments mean the same as for **ub_resolve** except no data is
returned immediately, instead a callback is called later.
The callback receives a copy of the mydata pointer, that you can use to
pass information to the callback.
The callback type is a function pointer to a function declared as:
.. code-block:: c
void my_callback_function(void* my_arg, int err,
struct ub_result* result);
The **async_id** is returned so you can (at your option) decide to
track it and cancel the request if needed.
If you pass a NULL pointer the **async_id** is not returned.
ub_cancel
Cancel an async query in progress.
This may return an error if the query does not exist, or the query is
already being delivered, in that case you may still get a callback for
the query.
ub_resolve_free
Free struct **ub_result** contents after use.
ub_strerror
Convert error value from one of the unbound library functions to a
human readable string.
ub_ctx_print_local_zones
Debug printout the local authority information to debug output.
ub_ctx_zone_add
Add new zone to local authority info, like local-zone
:doc:`unbound.conf(5)</manpages/unbound.conf>` statement.
ub_ctx_zone_remove
Delete zone from local authority info.
ub_ctx_data_add
Add resource record data to local authority info, like local-data
:doc:`unbound.conf(5)</manpages/unbound.conf>` statement.
ub_ctx_data_remove
Delete local authority data from the name given.
Result Data structure
---------------------
The result of the DNS resolution and validation is returned as *struct
ub_result*.
The result structure contains the following entries:
.. code-block:: c
struct ub_result {
char* qname; /* text string, original question */
int qtype; /* type code asked for */
int qclass; /* class code asked for */
char** data; /* array of rdata items, NULL terminated*/
int* len; /* array with lengths of rdata items */
char* canonname; /* canonical name of result */
int rcode; /* additional error code in case of no data */
void* answer_packet; /* full network format answer packet */
int answer_len; /* length of packet in octets */
int havedata; /* true if there is data */
int nxdomain; /* true if nodata because name does not exist */
int secure; /* true if result is secure */
int bogus; /* true if a security failure happened */
char* why_bogus; /* string with error if bogus */
int was_ratelimited; /* true if the query was ratelimited (SERVFAIL) by unbound */
int ttl; /* number of seconds the result is valid */
};
If both secure and bogus are false, security was not enabled for the domain of
the query.
Else, they are not both true, one of them is true.
Return Values
-------------
Many routines return an error code.
The value 0 (zero) denotes no error happened.
Other values can be passed to **ub_strerror** to obtain a readable error
string.
**ub_strerror** returns a zero terminated string.
**ub_ctx_create** returns NULL on an error (a malloc failure).
**ub_poll** returns true if some information may be available, false otherwise.
**ub_fd** returns a file descriptor or -1 on error.
**ub_ctx_config** and **ub_ctx_resolvconf** attempt to leave errno informative
on a function return with file read failure.
See Also
--------
:doc:`unbound.conf(5)</manpages/unbound.conf>`, :doc:`unbound(8)</manpages/unbound>`.
+255 -135
View File
@@ -1,189 +1,309 @@
.TH "unbound-anchor" "8" "@date@" "NLnet Labs" "unbound @version@"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"
.\" Copyright (c) 2008, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.SH "NAME"
.B unbound\-anchor
\- Unbound anchor utility.
.SH "SYNOPSIS"
.B unbound\-anchor
.RB [ opts ]
.SH "DESCRIPTION"
.B Unbound\-anchor
performs setup or update of the root trust anchor for DNSSEC validation.
The program fetches the trust anchor with the method from RFC7958 when
regular RFC5011 update fails to bring it up to date.
It can be run (as root) from the commandline, or run as part of startup
scripts. Before you start the \fIunbound\fR(8) DNS server.
.P
.\" Man page generated from reStructuredText.
.
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "UNBOUND-ANCHOR" "8" "@date@" "@version@" "Unbound"
.SH NAME
unbound-anchor \- Unbound @version@ anchor utility.
.SH SYNOPSIS
.sp
\fBunbound\-anchor\fP [\fBopts\fP]
.SH DESCRIPTION
.sp
\fBunbound\-anchor\fP performs setup or update of the root trust anchor for DNSSEC
validation.
The program fetches the trust anchor with the method from \fI\%RFC 7958\fP when
regular \fI\%RFC 5011\fP update fails to bring it up to date.
It can be run from the commandline, or run as part of startup scripts before
you start the \fI\%unbound(8)\fP DNS server.
.sp
Note that if you want to use \fI\%RFC 5011\fP with Unbound (i.e., the
\fI\%auto\-trust\-anchor\-file\fP option) so
that trust anchor information is automatically tracked by Unbound during
operation, the user that Unbound runs under (by default \(aqunbound\(aq) must have
write permissions to the file and the directory the file lives in (for creating
temporary files).
In this case you would probably want to run this program as the designated
Unbound user.
.sp
Suggested usage:
.P
.INDENT 0.0
.INDENT 3.5
.sp
.nf
# in the init scripts.
# provide or update the root anchor (if necessary)
unbound-anchor \-a "@UNBOUND_ROOTKEY_FILE@"
# Please note usage of this root anchor is at your own risk
# and under the terms of our LICENSE (see source).
#
# start validating resolver
# the unbound.conf contains:
# auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@"
unbound \-c unbound.conf
.ft C
# in the init scripts.
# provide or update the root anchor (if necessary)
unbound\-anchor \-a \(dq@UNBOUND_ROOTKEY_FILE@\(dq
# Please note usage of this root anchor is at your own risk
# and under the terms of our LICENSE (see source).
#
# start validating resolver
# the unbound.conf contains:
# auto\-trust\-anchor\-file: \(dq@UNBOUND_ROOTKEY_FILE@\(dq
unbound \-c unbound.conf
.ft P
.fi
.P
This tool provides builtin default contents for the root anchor and root
update certificate files.
.P
.UNINDENT
.UNINDENT
.sp
This tool provides builtin default contents for the root anchor and root update
certificate files.
.sp
It tests if the root anchor file works, and if not, and an update is possible,
attempts to update the root anchor using the root update certificate.
It performs a https fetch of root-anchors.xml and checks the results (RFC7958),
if all checks are successful, it updates the root anchor file. Otherwise
the root anchor file is unchanged. It performs RFC5011 tracking if the
DNSSEC information available via the DNS makes that possible.
.P
It does not perform an update if the certificate is expired, if the network
is down or other errors occur.
.P
It performs a https fetch of
\fI\%root\-anchors.xml\fP
and checks the results (\fI\%RFC 7958\fP); if all checks are successful, it updates
the root anchor file.
Otherwise the root anchor file is unchanged.
It performs \fI\%RFC 5011\fP tracking if the DNSSEC information available via the
DNS makes that possible.
.sp
It does not perform an update if the certificate is expired, if the network is
down or other errors occur.
.sp
The available options are:
.INDENT 0.0
.TP
.B \-a \fIfile
.B \-a <file>
The root anchor key file, that is read in and written out.
Default is @UNBOUND_ROOTKEY_FILE@.
If the file does not exist, or is empty, a builtin root key is written to it.
Default is \fB@UNBOUND_ROOTKEY_FILE@\fP\&.
If the file does not exist, or is empty, a builtin root key is written
to it.
.UNINDENT
.INDENT 0.0
.TP
.B \-c \fIfile
.B \-c <file>
The root update certificate file, that is read in.
Default is @UNBOUND_ROOTCERT_FILE@.
Default is \fB@UNBOUND_ROOTCERT_FILE@\fP\&.
If the file does not exist, or is empty, a builtin certificate is used.
.UNINDENT
.INDENT 0.0
.TP
.B \-l
List the builtin root key and builtin root update certificate on stdout.
.UNINDENT
.INDENT 0.0
.TP
.B \-u \fIname
The server name, it connects to https://name. Specify without https:// prefix.
The default is "data.iana.org". It connects to the port specified with \-P.
.B \-u <name>
The server name, it connects to \fBhttps://name\fP\&.
Specify without \fBhttps://\fP prefix.
The default is \fB\(dqdata.iana.org\(dq\fP\&.
It connects to the port specified with \fI\%\-P\fP\&.
You can pass an IPv4 address or IPv6 address (no brackets) if you want.
.UNINDENT
.INDENT 0.0
.TP
.B \-S
Do not use SNI for the HTTPS connection. Default is to use SNI.
Do not use SNI for the HTTPS connection.
Default is to use SNI.
.UNINDENT
.INDENT 0.0
.TP
.B \-b \fIaddress
The source address to bind to for domain resolution and contacting the server
on https. May be either an IPv4 address or IPv6 address (no brackets).
.B \-b <address>
The source address to bind to for domain resolution and contacting the
server on https.
May be either an IPv4 address or IPv6 address (no brackets).
.UNINDENT
.INDENT 0.0
.TP
.B \-x \fIpath
The pathname to the root\-anchors.xml file on the server. (forms URL with \-u).
The default is /root\-anchors/root\-anchors.xml.
.B \-x <path>
The pathname to the root\-anchors.xml file on the server.
(forms URL with \fI\%\-u\fP).
The default is \fB/root\-anchors/root\-anchors.xml\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B \-s \fIpath
The pathname to the root\-anchors.p7s file on the server. (forms URL with \-u).
The default is /root\-anchors/root\-anchors.p7s. This file has to be a PKCS7
signature over the xml file, using the pem file (\-c) as trust anchor.
.B \-s <path>
The pathname to the root\-anchors.p7s file on the server.
(forms URL with \fI\%\-u\fP).
The default is \fB/root\-anchors/root\-anchors.p7s\fP\&.
This file has to be a PKCS7 signature over the xml file, using the pem
file (\fI\%\-c\fP) as trust anchor.
.UNINDENT
.INDENT 0.0
.TP
.B \-n \fIname
The emailAddress for the Subject of the signer's certificate from the p7s
signature file. Only signatures from this name are allowed. default is
dnssec@iana.org. If you pass "" then the emailAddress is not checked.
.B \-n <name>
The emailAddress for the Subject of the signer\(aqs certificate from the
p7s signature file.
Only signatures from this name are allowed.
The default is \fBdnssec@iana.org\fP\&.
If you pass \fB\(dq\(dq\fP then the emailAddress is not checked.
.UNINDENT
.INDENT 0.0
.TP
.B \-4
Use IPv4 for domain resolution and contacting the server on https. Default is
to use IPv4 and IPv6 where appropriate.
Use IPv4 for domain resolution and contacting the server on
https.
Default is to use IPv4 and IPv6 where appropriate.
.UNINDENT
.INDENT 0.0
.TP
.B \-6
Use IPv6 for domain resolution and contacting the server on https. Default is
to use IPv4 and IPv6 where appropriate.
Use IPv6 for domain resolution and contacting the server on https.
Default is to use IPv4 and IPv6 where appropriate.
.UNINDENT
.INDENT 0.0
.TP
.B \-f \fIresolv.conf
Use the given resolv.conf file. Not enabled by default, but you could try to
pass /etc/resolv.conf on some systems. It contains the IP addresses of the
recursive nameservers to use. However, since this tool could be used to
bootstrap that very recursive nameserver, it would not be useful (since
that server is not up yet, since we are bootstrapping it). It could be
useful in a situation where you know an upstream cache is deployed (and
running) and in captive portal situations.
.B \-f <resolv.conf>
Use the given resolv.conf file.
Not enabled by default, but you could try to pass
\fB/etc/resolv.conf\fP on some systems.
It contains the IP addresses of the recursive nameservers to use.
However, since this tool could be used to bootstrap that very recursive
nameserver, it would not be useful (since that server is not up yet,
since we are bootstrapping it).
It could be useful in a situation where you know an upstream cache is
deployed (and running) and in captive portal situations.
.UNINDENT
.INDENT 0.0
.TP
.B \-r \fIroot.hints
Use the given root.hints file (same syntax as the BIND and Unbound root hints
file) to bootstrap domain resolution. By default a list of builtin root
hints is used. Unbound\-anchor goes to the network itself for these roots,
to resolve the server (\-u option) and to check the root DNSKEY records.
.B \-r <root.hints>
Use the given root.hints file (same syntax as the BIND and Unbound root
hints file) to bootstrap domain resolution.
By default a list of builtin root hints is used.
unbound\-anchor goes to the network itself for these roots, to resolve
the server (\fI\%\-u\fP option) and to check the root DNSKEY records.
It does so, because the tool when used for bootstrapping the recursive
resolver, cannot use that recursive resolver itself because it is bootstrapping
that server.
resolver, cannot use that recursive resolver itself because it is
bootstrapping that server.
.UNINDENT
.INDENT 0.0
.TP
.B \-R
Allow fallback from \-f resolv.conf file to direct root servers query.
It allows you to prefer local resolvers, but fallback automatically
to direct root query if they do not respond or do not support DNSSEC.
Allow fallback from \fI\%\-f\fP \fB<resolv.conf>\fP file to direct root
servers query.
It allows you to prefer local resolvers, but fallback automatically to
direct root query if they do not respond or do not support DNSSEC.
.UNINDENT
.INDENT 0.0
.TP
.B \-v
More verbose. Once prints informational messages, multiple times may enable
large debug amounts (such as full certificates or byte\-dumps of downloaded
files). By default it prints almost nothing. It also prints nothing on
errors by default; in that case the original root anchor file is simply
left undisturbed, so that a recursive server can start right after it.
More verbose.
Once prints informational messages, multiple times may enable large
debug amounts (such as full certificates or byte\-dumps of downloaded
files).
By default it prints almost nothing.
It also prints nothing on errors by default; in that case the original
root anchor file is simply left undisturbed, so that a recursive server
can start right after it.
.UNINDENT
.INDENT 0.0
.TP
.B \-C \fIunbound.conf
Debug option to read unbound.conf into the resolver process used.
.B \-C <unbound.conf>
Debug option to read \fB<unbound.conf>\fP into the resolver process
used.
.UNINDENT
.INDENT 0.0
.TP
.B \-P \fIport
Set the port number to use for the https connection. The default is 443.
.B \-P <port>
Set the port number to use for the https connection.
The default is 443.
.UNINDENT
.INDENT 0.0
.TP
.B \-F
Debug option to force update of the root anchor through downloading the xml
file and verifying it with the certificate. By default it first tries to
update by contacting the DNS, which uses much less bandwidth, is much
faster (200 msec not 2 sec), and is nicer to the deployed infrastructure.
With this option, it still attempts to do so (and may verbosely tell you),
but then ignores the result and goes on to use the xml fallback method.
Debug option to force update of the root anchor through downloading the
xml file and verifying it with the certificate.
By default it first tries to update by contacting the DNS, which uses
much less bandwidth, is much faster (200 msec not 2 sec), and is nicer
to the deployed infrastructure.
With this option, it still attempts to do so (and may verbosely tell
you), but then ignores the result and goes on to use the xml fallback
method.
.UNINDENT
.INDENT 0.0
.TP
.B \-h
Show the version and commandline option help.
.SH "EXIT CODE"
.UNINDENT
.SH EXIT CODE
.sp
This tool exits with value 1 if the root anchor was updated using the
certificate or if the builtin root-anchor was used. It exits with code
0 if no update was necessary, if the update was possible with RFC5011
tracking, or if an error occurred.
.P
certificate or if the builtin root\-anchor was used.
It exits with code 0 if no update was necessary, if the update was possible
with \fI\%RFC 5011\fP tracking, or if an error occurred.
.sp
You can check the exit value in this manner:
.INDENT 0.0
.INDENT 3.5
.sp
.nf
unbound-anchor \-a "root.key" || logger "Please check root.key"
.ft C
unbound\-anchor \-a \(dqroot.key\(dq || logger \(dqPlease check root.key\(dq
.ft P
.fi
.UNINDENT
.UNINDENT
.sp
Or something more suitable for your operational environment.
.SH "TRUST"
The root keys and update certificate included in this tool
are provided for convenience and under the terms of our
license (see the LICENSE file in the source distribution or
https://github.com/NLnetLabs/unbound/blob/master/LICENSE) and might be stale or
not suitable to your purpose.
.P
By running "unbound\-anchor \-l" the keys and certificate that are
.SH TRUST
.sp
The root keys and update certificate included in this tool are provided for
convenience and under the terms of our license (see the LICENSE file in the
source distribution or \fI\%https://github.com/NLnetLabs/unbound/blob/master/LICENSE\fP
and might be stale or not suitable to your purpose.
.sp
By running \fI\%unbound\-anchor \-l\fP the keys and certificate that are
configured in the code are printed for your convenience.
.P
The build\-in configuration can be overridden by providing a root\-cert
file and a rootkey file.
.SH "FILES"
.sp
The built\-in configuration can be overridden by providing a root\-cert file and
a rootkey file.
.SH FILES
.INDENT 0.0
.TP
.I @UNBOUND_ROOTKEY_FILE@
The root anchor file, updated with 5011 tracking, and read and written to.
.B @UNBOUND_ROOTKEY_FILE@
The root anchor file, updated with 5011 tracking, and read and written
to.
The file is created if it does not exist.
.TP
.I @UNBOUND_ROOTCERT_FILE@
The trusted self\-signed certificate that is used to verify the downloaded
DNSSEC root trust anchor. You can update it by fetching it from
https://data.iana.org/root\-anchors/icannbundle.pem (and validate it).
.B @UNBOUND_ROOTCERT_FILE@
The trusted self\-signed certificate that is used to verify the
downloaded DNSSEC root trust anchor.
You can update it by fetching it from
\fI\%https://data.iana.org/root\-anchors/icannbundle.pem\fP (and validate it).
If the file does not exist or is empty, a builtin version is used.
.TP
.I https://data.iana.org/root\-anchors/root\-anchors.xml
.B \fI\%https://data.iana.org/root\-anchors/root\-anchors.xml\fP
Source for the root key information.
.TP
.I https://data.iana.org/root\-anchors/root\-anchors.p7s
.B \fI\%https://data.iana.org/root\-anchors/root\-anchors.p7s\fP
Signature on the root key information.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
\fIunbound\fR(8).
.UNINDENT
.SH SEE ALSO
.sp
\fI\%unbound.conf(5)\fP,
\fI\%unbound(8)\fP\&.
.SH AUTHOR
Unbound developers are mentioned in the CREDITS file in the distribution.
.SH COPYRIGHT
1999-2026, NLnet Labs
.\" Generated by docutils manpage writer.
.
+290
View File
@@ -0,0 +1,290 @@
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
.. program:: unbound-anchor
unbound-anchor(8)
=================
Synopsis
--------
**unbound-anchor** [``opts``]
Description
-----------
``unbound-anchor`` performs setup or update of the root trust anchor for DNSSEC
validation.
The program fetches the trust anchor with the method from :rfc:`7958` when
regular :rfc:`5011` update fails to bring it up to date.
It can be run from the commandline, or run as part of startup scripts before
you start the :doc:`unbound(8)</manpages/unbound>` DNS server.
Note that if you want to use :rfc:`5011` with Unbound (i.e., the
:ref:`auto-trust-anchor-file<unbound.conf.auto-trust-anchor-file>` option) so
that trust anchor information is automatically tracked by Unbound during
operation, the user that Unbound runs under (by default 'unbound') must have
write permissions to the file and the directory the file lives in (for creating
temporary files).
In this case you would probably want to run this program as the designated
Unbound user.
Suggested usage:
.. code-block:: text
# in the init scripts.
# provide or update the root anchor (if necessary)
unbound-anchor -a "@UNBOUND_ROOTKEY_FILE@"
# Please note usage of this root anchor is at your own risk
# and under the terms of our LICENSE (see source).
#
# start validating resolver
# the unbound.conf contains:
# auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@"
unbound -c unbound.conf
This tool provides builtin default contents for the root anchor and root update
certificate files.
It tests if the root anchor file works, and if not, and an update is possible,
attempts to update the root anchor using the root update certificate.
It performs a https fetch of
`root-anchors.xml <http://data.iana.org/root-anchors/root-anchors.xml>`__
and checks the results (:rfc:`7958`); if all checks are successful, it updates
the root anchor file.
Otherwise the root anchor file is unchanged.
It performs :rfc:`5011` tracking if the DNSSEC information available via the
DNS makes that possible.
It does not perform an update if the certificate is expired, if the network is
down or other errors occur.
The available options are:
.. option:: -a <file>
The root anchor key file, that is read in and written out.
Default is :file:`@UNBOUND_ROOTKEY_FILE@`.
If the file does not exist, or is empty, a builtin root key is written
to it.
.. option:: -c <file>
The root update certificate file, that is read in.
Default is :file:`@UNBOUND_ROOTCERT_FILE@`.
If the file does not exist, or is empty, a builtin certificate is used.
.. option:: -l
List the builtin root key and builtin root update certificate on stdout.
.. option:: -u <name>
The server name, it connects to ``https://name``.
Specify without ``https://`` prefix.
The default is ``"data.iana.org"``.
It connects to the port specified with :option:`-P`.
You can pass an IPv4 address or IPv6 address (no brackets) if you want.
.. option:: -S
Do not use SNI for the HTTPS connection.
Default is to use SNI.
.. option:: -b <address>
The source address to bind to for domain resolution and contacting the
server on https.
May be either an IPv4 address or IPv6 address (no brackets).
.. option:: -x <path>
The pathname to the root-anchors.xml file on the server.
(forms URL with :option:`-u`).
The default is :file:`/root-anchors/root-anchors.xml`.
.. option:: -s <path>
The pathname to the root-anchors.p7s file on the server.
(forms URL with :option:`-u`).
The default is :file:`/root-anchors/root-anchors.p7s`.
This file has to be a PKCS7 signature over the xml file, using the pem
file (:option:`-c`) as trust anchor.
.. option:: -n <name>
The emailAddress for the Subject of the signer's certificate from the
p7s signature file.
Only signatures from this name are allowed.
The default is ``dnssec@iana.org``.
If you pass ``""`` then the emailAddress is not checked.
.. option:: -4
Use IPv4 for domain resolution and contacting the server on
https.
Default is to use IPv4 and IPv6 where appropriate.
.. option:: -6
Use IPv6 for domain resolution and contacting the server on https.
Default is to use IPv4 and IPv6 where appropriate.
.. option:: -f <resolv.conf>
Use the given resolv.conf file.
Not enabled by default, but you could try to pass
:file:`/etc/resolv.conf` on some systems.
It contains the IP addresses of the recursive nameservers to use.
However, since this tool could be used to bootstrap that very recursive
nameserver, it would not be useful (since that server is not up yet,
since we are bootstrapping it).
It could be useful in a situation where you know an upstream cache is
deployed (and running) and in captive portal situations.
.. option:: -r <root.hints>
Use the given root.hints file (same syntax as the BIND and Unbound root
hints file) to bootstrap domain resolution.
By default a list of builtin root hints is used.
unbound-anchor goes to the network itself for these roots, to resolve
the server (:option:`-u` option) and to check the root DNSKEY records.
It does so, because the tool when used for bootstrapping the recursive
resolver, cannot use that recursive resolver itself because it is
bootstrapping that server.
.. option:: -R
Allow fallback from :option:`-f` ``<resolv.conf>`` file to direct root
servers query.
It allows you to prefer local resolvers, but fallback automatically to
direct root query if they do not respond or do not support DNSSEC.
.. option:: -v
More verbose.
Once prints informational messages, multiple times may enable large
debug amounts (such as full certificates or byte-dumps of downloaded
files).
By default it prints almost nothing.
It also prints nothing on errors by default; in that case the original
root anchor file is simply left undisturbed, so that a recursive server
can start right after it.
.. option:: -C <unbound.conf>
Debug option to read :file:`<unbound.conf>` into the resolver process
used.
.. option:: -P <port>
Set the port number to use for the https connection.
The default is 443.
.. option:: -F
Debug option to force update of the root anchor through downloading the
xml file and verifying it with the certificate.
By default it first tries to update by contacting the DNS, which uses
much less bandwidth, is much faster (200 msec not 2 sec), and is nicer
to the deployed infrastructure.
With this option, it still attempts to do so (and may verbosely tell
you), but then ignores the result and goes on to use the xml fallback
method.
.. option:: -h
Show the version and commandline option help.
Exit Code
---------
This tool exits with value 1 if the root anchor was updated using the
certificate or if the builtin root-anchor was used.
It exits with code 0 if no update was necessary, if the update was possible
with :rfc:`5011` tracking, or if an error occurred.
You can check the exit value in this manner:
.. code-block:: text
unbound-anchor -a "root.key" || logger "Please check root.key"
Or something more suitable for your operational environment.
Trust
-----
The root keys and update certificate included in this tool are provided for
convenience and under the terms of our license (see the LICENSE file in the
source distribution or https://github.com/NLnetLabs/unbound/blob/master/LICENSE
and might be stale or not suitable to your purpose.
By running :option:`unbound-anchor -l` the keys and certificate that are
configured in the code are printed for your convenience.
The built-in configuration can be overridden by providing a root-cert file and
a rootkey file.
Files
-----
@UNBOUND_ROOTKEY_FILE@
The root anchor file, updated with 5011 tracking, and read and written
to.
The file is created if it does not exist.
@UNBOUND_ROOTCERT_FILE@
The trusted self-signed certificate that is used to verify the
downloaded DNSSEC root trust anchor.
You can update it by fetching it from
https://data.iana.org/root-anchors/icannbundle.pem (and validate it).
If the file does not exist or is empty, a builtin version is used.
https://data.iana.org/root-anchors/root-anchors.xml
Source for the root key information.
https://data.iana.org/root-anchors/root-anchors.p7s
Signature on the root key information.
See Also
--------
:doc:`unbound.conf(5)</manpages/unbound.conf>`,
:doc:`unbound(8)</manpages/unbound>`.
+80 -39
View File
@@ -1,52 +1,93 @@
.TH "unbound-checkconf" "8" "@date@" "NLnet Labs" "unbound @version@"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.SH "NAME"
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.
.\" Man page generated from reStructuredText.
.
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "UNBOUND-CHECKCONF" "8" "@date@" "@version@" "Unbound"
.SH NAME
unbound-checkconf \- Check Unbound @version@ configuration file for errors.
.SH SYNOPSIS
.sp
\fBunbound\-checkconf\fP [\fB\-hf\fP] [\fB\-o option\fP] [cfgfile]
.SH DESCRIPTION
.sp
\fBunbound\-checkconf\fP checks the configuration file for the
\fI\%unbound(8)\fP DNS resolver for syntax and other errors.
The config file syntax is described in
\fIunbound.conf\fR(5).
.P
\fI\%unbound.conf(5)\fP\&.
.sp
The available options are:
.INDENT 0.0
.TP
.B \-h
Show the version and commandline option help.
.UNINDENT
.INDENT 0.0
.TP
.B \-f
Print full pathname, with chroot applied to it. Use with the \-o option.
Print full pathname, with chroot applied to it.
Use with the \fI\%\-o\fP option.
.UNINDENT
.INDENT 0.0
.TP
.B \-o\fI option
.B \-q
Make the operation quiet, suppress output on success.
.UNINDENT
.INDENT 0.0
.TP
.B \-o <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.
printed to stdout.
For \fB\(dq\(dq\fP (disabled) options an empty line is printed.
.UNINDENT
.INDENT 0.0
.TP
.I cfgfile
The config file to read with settings for Unbound. It is checked.
.B 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"
.UNINDENT
.SH EXIT CODE
.sp
The \fBunbound\-checkconf\fP program exits with status code 1 on error, 0 for a
correct config file.
.SH FILES
.INDENT 0.0
.TP
.I @ub_conf_file@
.B @ub_conf_file@
Unbound configuration file.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
\fIunbound\fR(8).
.UNINDENT
.SH SEE ALSO
.sp
\fI\%unbound.conf(5)\fP,
\fI\%unbound(8)\fP\&.
.SH AUTHOR
Unbound developers are mentioned in the CREDITS file in the distribution.
.SH COPYRIGHT
1999-2026, NLnet Labs
.\" Generated by docutils manpage writer.
.
+98
View File
@@ -0,0 +1,98 @@
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
.. program:: unbound-checkconf
unbound-checkconf(8)
====================
Synopsis
--------
**unbound-checkconf** [``-hf``] [``-o option``] [cfgfile]
Description
-----------
``unbound-checkconf`` checks the configuration file for the
:doc:`unbound(8)</manpages/unbound>` DNS resolver for syntax and other errors.
The config file syntax is described in
:doc:`unbound.conf(5)</manpages/unbound.conf>`.
The available options are:
.. option:: -h
Show the version and commandline option help.
.. option:: -f
Print full pathname, with chroot applied to it.
Use with the :option:`-o` option.
.. option:: -q
Make the operation quiet, suppress output on success.
.. option:: -o <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.
.. option:: cfgfile
The config file to read with settings for Unbound.
It is checked.
If omitted, the config file at the default location is checked.
Exit Code
---------
The ``unbound-checkconf`` program exits with status code 1 on error, 0 for a
correct config file.
Files
-----
@ub_conf_file@
Unbound configuration file.
See Also
--------
:doc:`unbound.conf(5)</manpages/unbound.conf>`,
:doc:`unbound(8)</manpages/unbound>`.
+1293 -469
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+157 -85
View File
@@ -1,118 +1,190 @@
.TH "unbound\-host" "1" "@date@" "NLnet Labs" "unbound @version@"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.SH "NAME"
.B unbound\-host
\- unbound DNS lookup utility
.SH "SYNOPSIS"
.B unbound\-host
.RB [ \-C
.IR configfile ]
.RB [ \-vdhr46D ]
.RB [ \-c
.IR class ]
.RB [ \-t
.IR type ]
.RB [ \-y
.IR key ]
.RB [ \-f
.IR keyfile ]
.RB [ \-F
.IR namedkeyfile ]
.I hostname
.SH "DESCRIPTION"
.B Unbound\-host
uses the Unbound validating resolver to query for the hostname and display
results. With the \fB\-v\fR option it displays validation
status: secure, insecure, bogus (security failure).
.P
By default it reads no configuration file whatsoever. It attempts to reach
the internet root servers. With \fB\-C\fR an Unbound config file and with
\fB\-r\fR resolv.conf can be read.
.P
.\" Man page generated from reStructuredText.
.
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "UNBOUND-HOST" "1" "@date@" "@version@" "Unbound"
.SH NAME
unbound-host \- Unbound @version@ DNS lookup utility.
.SH SYNOPSIS
.sp
\fBunbound\-host\fP [\fB\-C configfile\fP] [\fB\-vdhr46D\fP] [\fB\-c class\fP]
[\fB\-t type\fP] [\fB\-y key\fP] [\fB\-f keyfile\fP] [\fB\-F namedkeyfile\fP] hostname
.SH DESCRIPTION
.sp
\fBunbound\-host\fP uses the Unbound validating resolver to query for the hostname
and display results.
With the \fI\%\-v\fP option it displays validation status: secure, insecure,
bogus (security failure).
.sp
By default it reads no configuration file whatsoever.
It attempts to reach the internet root servers.
With \fI\%\-C\fP an unbound config file and with \fI\%\-r\fP \fBresolv.conf\fP
can be read.
.sp
The available options are:
.INDENT 0.0
.TP
.I hostname
.B hostname
This name is resolved (looked up in the DNS).
If a IPv4 or IPv6 address is given, a reverse lookup is performed.
.UNINDENT
.INDENT 0.0
.TP
.B \-h
Show the version and commandline option help.
.UNINDENT
.INDENT 0.0
.TP
.B \-v
Enable verbose output and it shows validation results, on every line.
Secure means that the NXDOMAIN (no such domain name), nodata (no such data)
or positive data response validated correctly with one of the keys.
Secure means that the NXDOMAIN (no such domain name), nodata (no such
data) or positive data response validated correctly with one of the
keys.
Insecure means that that domain name has no security set up for it.
Bogus (security failure) means that the response failed one or more checks,
it is likely wrong, outdated, tampered with, or broken.
Bogus (security failure) means that the response failed one or more
checks, it is likely wrong, outdated, tampered with, or broken.
.UNINDENT
.INDENT 0.0
.TP
.B \-d
Enable debug output to stderr. One \-d shows what the resolver and validator
are doing and may tell you what is going on. More times, \-d \-d, gives a
lot of output, with every packet sent and received.
Enable debug output to stderr.
One \fI\%\-d\fP shows what the resolver and validator are doing and may
tell you what is going on.
More times, \fI\%\-d\fP \fI\%\-d\fP, gives a lot of output, with every
packet sent and received.
.UNINDENT
.INDENT 0.0
.TP
.B \-c \fIclass
Specify the class to lookup for, the default is IN the internet class.
.B \-c <class>
Specify the class to lookup for, the default is IN the internet
class.
.UNINDENT
.INDENT 0.0
.TP
.B \-t \fItype
Specify the type of data to lookup. The default looks for IPv4, IPv6 and
mail handler data, or domain name pointers for reverse queries.
.B \-t <type>
Specify the type of data to lookup.
The default looks for IPv4, IPv6 and mail handler data, or domain name
pointers for reverse queries.
.UNINDENT
.INDENT 0.0
.TP
.B \-y \fIkey
Specify a public key to use as trust anchor. This is the base for a chain
of trust that is built up from the trust anchor to the response, in order
to validate the response message. Can be given as a DS or DNSKEY record.
For example \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD".
.B \-y <key>
Specify a public key to use as trust anchor.
This is the base for a chain of trust that is built up from the trust
anchor to the response, in order to validate the response message.
Can be given as a DS or DNSKEY record.
For example:
.INDENT 7.0
.INDENT 3.5
.sp
.nf
.ft C
\-y \(dqexample.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD\(dq
.ft P
.fi
.UNINDENT
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
.B \-D
Enables DNSSEC validation. Reads the root anchor from the default configured
root anchor at the default location, \fI@UNBOUND_ROOTKEY_FILE@\fR.
Enables DNSSEC validation.
Reads the root anchor from the default configured root anchor at the
default location, \fB@UNBOUND_ROOTKEY_FILE@\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B \-f \fIkeyfile
Reads keys from a file. Every line has a DS or DNSKEY record, in the format
as for \-y. The zone file format, the same as dig and drill produce.
.B \-f <keyfile>
Reads keys from a file.
Every line has a DS or DNSKEY record, in the format as for \fI\%\-y\fP\&.
The zone file format, the same as \fBdig\fP and \fBdrill\fP produce.
.UNINDENT
.INDENT 0.0
.TP
.B \-F \fInamedkeyfile
Reads keys from a BIND\-style named.conf file. Only the trusted\-key {}; entries
are read.
.B \-F <namedkeyfile>
Reads keys from a BIND\-style \fBnamed.conf\fP file.
Only the \fBtrusted\-key {};\fP entries are read.
.UNINDENT
.INDENT 0.0
.TP
.B \-C \fIconfigfile
Uses the specified unbound.conf to prime
.IR libunbound (3).
.B \-C <configfile>
Uses the specified unbound.conf to prime \fI\%libunbound(3)\fP\&.
Pass it as first argument if you want to override some options from the
config file with further arguments on the commandline.
.UNINDENT
.INDENT 0.0
.TP
.B \-r
Read /etc/resolv.conf, and use the forward DNS servers from there (those could
have been set by DHCP). More info in
.IR resolv.conf (5).
Read \fB/etc/resolv.conf\fP, and use the forward DNS servers from
there (those could have been set by DHCP).
More info in \fIresolv.conf(5)\fP\&.
Breaks validation if those servers do not support DNSSEC.
.UNINDENT
.INDENT 0.0
.TP
.B \-4
Use solely the IPv4 network for sending packets.
.UNINDENT
.INDENT 0.0
.TP
.B \-6
Use solely the IPv6 network for sending packets.
.SH "EXAMPLES"
Some examples of use. The keys shown below are fakes, thus a security failure
is encountered.
.P
.UNINDENT
.SH EXAMPLES
.sp
Some examples of use.
The keys shown below are fakes, thus a security failure is encountered.
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
$ unbound\-host www.example.com
.P
$ unbound\-host \-v \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" www.example.com
.P
$ unbound\-host \-v \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" 192.0.2.153
.SH "EXIT CODE"
The unbound\-host program exits with status code 1 on error,
0 on no error. The data may not be available on exit code 0, exit code 1
means the lookup encountered a fatal error.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
\fIunbound\fR(8).
$ unbound\-host \-v \-y \(dqexample.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD\(dq www.example.com
$ unbound\-host \-v \-y \(dqexample.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD\(dq 192.0.2.153
.ft P
.fi
.UNINDENT
.UNINDENT
.SH EXIT CODE
.sp
The \fBunbound\-host\fP program exits with status code 1 on error, 0 on no error.
The data may not be available on exit code 0, exit code 1 means the lookup
encountered a fatal error.
.SH SEE ALSO
.sp
\fI\%unbound.conf(5)\fP,
\fI\%unbound(8)\fP\&.
.SH AUTHOR
Unbound developers are mentioned in the CREDITS file in the distribution.
.SH COPYRIGHT
1999-2026, NLnet Labs
.\" Generated by docutils manpage writer.
.
+176
View File
@@ -0,0 +1,176 @@
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
.. program:: unbound-host
unbound-host(1)
===============
Synopsis
--------
**unbound-host** [``-C configfile``] [``-vdhr46D``] [``-c class``]
[``-t type``] [``-y key``] [``-f keyfile``] [``-F namedkeyfile``] hostname
Description
-----------
``unbound-host`` uses the Unbound validating resolver to query for the hostname
and display results.
With the :option:`-v` option it displays validation status: secure, insecure,
bogus (security failure).
By default it reads no configuration file whatsoever.
It attempts to reach the internet root servers.
With :option:`-C` an unbound config file and with :option:`-r` ``resolv.conf``
can be read.
The available options are:
.. option:: hostname
This name is resolved (looked up in the DNS).
If a IPv4 or IPv6 address is given, a reverse lookup is performed.
.. option:: -h
Show the version and commandline option help.
.. option:: -v
Enable verbose output and it shows validation results, on every line.
Secure means that the NXDOMAIN (no such domain name), nodata (no such
data) or positive data response validated correctly with one of the
keys.
Insecure means that that domain name has no security set up for it.
Bogus (security failure) means that the response failed one or more
checks, it is likely wrong, outdated, tampered with, or broken.
.. option:: -d
Enable debug output to stderr.
One :option:`-d` shows what the resolver and validator are doing and may
tell you what is going on.
More times, :option:`-d` :option:`-d`, gives a lot of output, with every
packet sent and received.
.. option:: -c <class>
Specify the class to lookup for, the default is IN the internet
class.
.. option:: -t <type>
Specify the type of data to lookup.
The default looks for IPv4, IPv6 and mail handler data, or domain name
pointers for reverse queries.
.. option:: -y <key>
Specify a public key to use as trust anchor.
This is the base for a chain of trust that is built up from the trust
anchor to the response, in order to validate the response message.
Can be given as a DS or DNSKEY record.
For example:
.. code-block:: text
-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD"
.. option:: -D
Enables DNSSEC validation.
Reads the root anchor from the default configured root anchor at the
default location, :file:`@UNBOUND_ROOTKEY_FILE@`.
.. option:: -f <keyfile>
Reads keys from a file.
Every line has a DS or DNSKEY record, in the format as for :option:`-y`.
The zone file format, the same as ``dig`` and ``drill`` produce.
.. option:: -F <namedkeyfile>
Reads keys from a BIND-style :file:`named.conf` file.
Only the ``trusted-key {};`` entries are read.
.. option:: -C <configfile>
Uses the specified unbound.conf to prime :doc:`libunbound(3)</manpages/libunbound>`.
Pass it as first argument if you want to override some options from the
config file with further arguments on the commandline.
.. option:: -r
Read :file:`/etc/resolv.conf`, and use the forward DNS servers from
there (those could have been set by DHCP).
More info in *resolv.conf(5)*.
Breaks validation if those servers do not support DNSSEC.
.. option:: -4
Use solely the IPv4 network for sending packets.
.. option:: -6
Use solely the IPv6 network for sending packets.
Examples
--------
Some examples of use.
The keys shown below are fakes, thus a security failure is encountered.
.. code-block:: text
$ unbound-host www.example.com
$ unbound-host -v -y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" www.example.com
$ unbound-host -v -y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" 192.0.2.153
Exit Code
---------
The ``unbound-host`` program exits with status code 1 on error, 0 on no error.
The data may not be available on exit code 0, exit code 1 means the lookup
encountered a fatal error.
See Also
--------
:doc:`unbound.conf(5)</manpages/unbound.conf>`,
:doc:`unbound(8)</manpages/unbound>`.
+102 -67
View File
@@ -1,88 +1,123 @@
.TH "unbound" "8" "@date@" "NLnet Labs" "unbound @version@"
.\"
.\" unbound.8 -- unbound manual
.\"
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.SH "NAME"
.B unbound
\- Unbound DNS validating resolver @version@.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]
.RB [ \-d ]
.RB [ \-p ]
.RB [ \-v ]
.RB [ \-c
.IR cfgfile ]
.SH "DESCRIPTION"
.B Unbound
is a caching DNS resolver.
.P
It uses a built in list of authoritative nameservers for the root zone (.),
.\" Man page generated from reStructuredText.
.
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "UNBOUND" "8" "@date@" "@version@" "Unbound"
.SH NAME
unbound \- Unbound DNS validating resolver @version@.
.SH SYNOPSIS
.sp
\fBunbound\fP [\fB\-hdpVv\fP] [\fB\-c <cfgfile>\fP]
.SH DESCRIPTION
.sp
\fBunbound\fP is a caching DNS resolver.
.sp
It uses a built in list of authoritative nameservers for the root zone (\fB\&.\fP),
the so called root hints.
On receiving a DNS query it will ask the root nameservers for
an answer and will in almost all cases receive a delegation to a top level
domain (TLD) authoritative nameserver.
On receiving a DNS query it will ask the root nameservers for an answer and
will in almost all cases receive a delegation to a top level domain (TLD)
authoritative nameserver.
It will then ask that nameserver for an answer.
It will recursively continue until an answer is found or no answer is
available (NXDOMAIN).
For performance and efficiency reasons that answer is cached for a
certain time (the answer's time\-to\-live or TTL).
It will recursively continue until an answer is found or no answer is available
(NXDOMAIN).
For performance and efficiency reasons that answer is cached for a certain time
(the answer\(aqs time\-to\-live or TTL).
A second query for the same name will then be answered from the cache.
Unbound can also do DNSSEC validation.
.P
To use a locally running
.B Unbound
for resolving put
.sp
.RS 6n
To use a locally running Unbound for resolving put:
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
nameserver 127.0.0.1
.RE
.ft P
.fi
.UNINDENT
.UNINDENT
.sp
into \fIresolv.conf(5)\fP\&.
.sp
If authoritative DNS is needed as well using \fI\%nsd(8)\fP,
careful setup is required because authoritative nameservers and resolvers are
using the same port number (53).
.sp
into
.IR resolv.conf (5).
.P
If authoritative DNS is needed as well using
.IR nsd (8),
careful setup is required because authoritative nameservers and
resolvers are using the same port number (53).
.P
The available options are:
.INDENT 0.0
.TP
.B \-h
Show the version number and commandline option help, and exit.
.UNINDENT
.INDENT 0.0
.TP
.B \-c\fI cfgfile
Set the config file with settings for Unbound to read instead of reading the
file at the default location, @ub_conf_file@. The syntax is
described in \fIunbound.conf\fR(5).
.B \-c <cfgfile>
Set the config file with settings for unbound to read instead of reading the
file at the default location, \fB@ub_conf_file@\fP\&.
The syntax is described in \fI\%unbound.conf(5)\fP\&.
.UNINDENT
.INDENT 0.0
.TP
.B \-d
Debug flag: do not fork into the background, but stay attached to
the console. This flag will also delay writing to the log file until
the thread\-spawn time, so that most config and setup errors appear on
stderr. If given twice or more, logging does not switch to the log file
or to syslog, but the log messages are printed to stderr all the time.
Debug flag: do not fork into the background, but stay attached to the
console.
This flag will also delay writing to the log file until the thread\-spawn
time, so that most config and setup errors appear on stderr.
If given twice or more, logging does not switch to the log file or to
syslog, but the log messages are printed to stderr all the time.
.UNINDENT
.INDENT 0.0
.TP
.B \-p
Don't use a pidfile. This argument should only be used by supervision
systems which can ensure that only one instance of Unbound will run
concurrently.
Don\(aqt use a pidfile.
This argument should only be used by supervision systems which can ensure
that only one instance of Unbound will run concurrently.
.UNINDENT
.INDENT 0.0
.TP
.B \-v
Increase verbosity. If given multiple times, more information is logged.
This is added to the verbosity (if any) from the config file.
Increase verbosity.
If given multiple times, more information is logged.
This is in addition to the verbosity (if any) from the config file.
.UNINDENT
.INDENT 0.0
.TP
.B \-V
Show the version number and build options, and exit.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
\fIunbound\-checkconf\fR(8),
\fInsd\fR(8).
.SH "AUTHORS"
.B Unbound
developers are mentioned in the CREDITS file in the distribution.
.UNINDENT
.SH SEE ALSO
.sp
\fI\%unbound.conf(5)\fP,
\fI\%unbound\-checkconf(8)\fP,
\fI\%nsd(8)\fP\&.
.SH AUTHOR
Unbound developers are mentioned in the CREDITS file in the distribution.
.SH COPYRIGHT
1999-2026, NLnet Labs
.\" Generated by docutils manpage writer.
.
+5399 -2403
View File
File diff suppressed because it is too large Load Diff
+5253
View File
File diff suppressed because it is too large Load Diff
+2007 -886
View File
File diff suppressed because it is too large Load Diff
+119
View File
@@ -0,0 +1,119 @@
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
..
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
..
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
..
IT HELPS PEOPLE DIFFING THE CHANGES
.. program:: unbound
unbound(8)
==========
Synopsis
--------
**unbound** [``-hdpVv``] [``-c <cfgfile>``]
Description
-----------
``unbound`` is a caching DNS resolver.
It uses a built in list of authoritative nameservers for the root zone (``.``),
the so called root hints.
On receiving a DNS query it will ask the root nameservers for an answer and
will in almost all cases receive a delegation to a top level domain (TLD)
authoritative nameserver.
It will then ask that nameserver for an answer.
It will recursively continue until an answer is found or no answer is available
(NXDOMAIN).
For performance and efficiency reasons that answer is cached for a certain time
(the answer's time-to-live or TTL).
A second query for the same name will then be answered from the cache.
Unbound can also do DNSSEC validation.
To use a locally running Unbound for resolving put:
.. code-block:: text
nameserver 127.0.0.1
into *resolv.conf(5)*.
If authoritative DNS is needed as well using :external+nsd:doc:`manpages/nsd`,
careful setup is required because authoritative nameservers and resolvers are
using the same port number (53).
The available options are:
.. option:: -h
Show the version number and commandline option help, and exit.
.. option:: -c <cfgfile>
Set the config file with settings for unbound to read instead of reading the
file at the default location, :file:`@ub_conf_file@`.
The syntax is described in :doc:`unbound.conf(5)</manpages/unbound.conf>`.
.. option:: -d
Debug flag: do not fork into the background, but stay attached to the
console.
This flag will also delay writing to the log file until the thread-spawn
time, so that most config and setup errors appear on stderr.
If given twice or more, logging does not switch to the log file or to
syslog, but the log messages are printed to stderr all the time.
.. option:: -p
Don't use a pidfile.
This argument should only be used by supervision systems which can ensure
that only one instance of Unbound will run concurrently.
.. option:: -v
Increase verbosity.
If given multiple times, more information is logged.
This is in addition to the verbosity (if any) from the config file.
.. option:: -V
Show the version number and build options, and exit.
See Also
--------
:doc:`unbound.conf(5)</manpages/unbound.conf>`,
:doc:`unbound-checkconf(8)</manpages/unbound-checkconf>`,
:external+nsd:doc:`manpages/nsd`.
+2 -2
View File
@@ -297,8 +297,8 @@ inplace_cb_delete_wrapped(struct module_env* env, enum inplace_cb_list_type type
*/
static struct module_func_block dynlibmod_block = {
"dynlib",
&dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate, &dynlibmod_inform_super,
&dynlibmod_clear, &dynlibmod_get_mem
NULL, NULL, &dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate,
&dynlibmod_inform_super, &dynlibmod_clear, &dynlibmod_get_mem
};
struct module_func_block* dynlibmod_get_funcblock(void)
+1 -1
View File
@@ -116,7 +116,7 @@ struct addredge {
addrlen_t len;
/** child node this edge is connected to */
struct addrnode *node;
/** Parent node this ege is connected to */
/** Parent node this edge is connected to */
struct addrnode *parent_node;
/** Index of this edge in parent_node */
int parent_index;
+301 -21
View File
@@ -51,12 +51,16 @@
#include "services/cache/dns.h"
#include "util/module.h"
#include "util/regional.h"
#include "util/fptr_wlist.h"
#include "util/storage/slabhash.h"
#include "util/config_file.h"
#include "util/data/msgreply.h"
#include "sldns/sbuffer.h"
#include "sldns/wire2str.h"
#include "iterator/iter_utils.h"
#ifdef USE_CACHEDB
#include "cachedb/cachedb.h"
#endif
/** externally called */
void
@@ -66,6 +70,7 @@ subnet_data_delete(void *d, void *ATTR_UNUSED(arg))
r = (struct subnet_msg_cache_data*)d;
addrtree_delete(r->tree4);
addrtree_delete(r->tree6);
free(r->reason_fail);
free(r);
}
@@ -80,6 +85,8 @@ msg_cache_sizefunc(void *k, void *d)
+ q->key.qname_len + lock_get_mem(&q->entry.lock);
s += addrtree_size(r->tree4);
s += addrtree_size(r->tree6);
if(r->reason_fail)
s += strlen(r->reason_fail)+1;
return s;
}
@@ -150,9 +157,32 @@ int ecs_whitelist_check(struct query_info* qinfo,
return 1;
sn_env = (struct subnet_env*)qstate->env->modinfo[id];
if(sq->is_subquery_nonsubnet) {
if(sq->is_subquery_scopezero) {
/* Check if the result can be stored in the global cache,
* this is okay if the address and name are not configured
* as subnet address and subnet zone. */
if(!ecs_is_whitelisted(sn_env->whitelist,
addr, addrlen, qinfo->qname, qinfo->qname_len,
qinfo->qclass)) {
/* The stub or forward can have no_cache set.*/
if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)) {
verbose(VERB_ALGO, "subnet subquery is not stored globally, stuborfwd is no_cache");
} else {
verbose(VERB_ALGO, "subnet store subquery global, name and addr have no subnet treatment.%s",
(sq->started_no_cache_store?
" But the subnet module was started with no_cache_store for the super query, and that is still applied to this query":""));
qstate->no_cache_store = sq->started_no_cache_store;
}
}
}
return 1;
}
/* Cache by default, might be disabled after parsing EDNS option
* received from nameserver. */
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL)) {
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)
&& sq->ecs_client_in.subnet_validdata) {
qstate->no_cache_store = 0;
}
@@ -173,12 +203,18 @@ int ecs_whitelist_check(struct query_info* qinfo,
if(sq->ecs_server_out.subnet_source_mask == 0) {
sq->subnet_sent_no_subnet = 1;
sq->subnet_sent = 0;
/* The result should end up in subnet cache,
* not in global cache. */
qstate->no_cache_store = 1;
return 1;
}
subnet_ecs_opt_list_append(&sq->ecs_server_out,
&qstate->edns_opts_back_out, qstate, region);
}
sq->subnet_sent = 1;
/* Do not store servfails in global cache, since the subnet
* option is sent out. */
qstate->no_cache_store = 1;
}
else {
/* Outgoing ECS option is set, but we don't want to sent it to
@@ -229,13 +265,13 @@ subnetmod_init(struct module_env *env, int id)
HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size,
msg_cache_sizefunc, query_info_compare, query_entry_delete,
subnet_data_delete, NULL);
slabhash_setmarkdel(sn_env->subnet_msg_cache, &subnet_markdel);
if(!sn_env->subnet_msg_cache) {
log_err("subnetcache: could not create cache");
free(sn_env);
env->modinfo[id] = NULL;
return 0;
}
slabhash_setmarkdel(sn_env->subnet_msg_cache, &subnet_markdel);
/* whitelist for edns subnet capable servers */
sn_env->whitelist = ecs_whitelist_create();
if(!sn_env->whitelist ||
@@ -310,9 +346,18 @@ delfunc(void *envptr, void *elemptr) {
static size_t
sizefunc(void *elemptr) {
struct reply_info *elem = (struct reply_info *)elemptr;
return sizeof (struct reply_info) - sizeof (struct rrset_ref)
size_t s = sizeof (struct reply_info) - sizeof (struct rrset_ref)
+ elem->rrset_count * sizeof (struct rrset_ref)
+ elem->rrset_count * sizeof (struct ub_packed_rrset_key *);
size_t i;
for (i = 0; i < elem->rrset_count; i++) {
struct ub_packed_rrset_key *key = elem->rrsets[i];
struct packed_rrset_data *data = key->entry.data;
s += ub_rrset_sizefunc(key, data);
}
if(elem->reason_bogus_str)
s += strlen(elem->reason_bogus_str)+1;
return s;
}
/**
@@ -352,7 +397,7 @@ update_cache(struct module_qstate *qstate, int id)
struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
struct ecs_data *edns = &sq->ecs_client_in;
size_t i;
int only_match_scope_zero;
int only_match_scope_zero, diff_size;
/* We already calculated hash upon lookup (lookup_and_reply) if we were
* allowed to look in the ECS cache */
@@ -391,6 +436,35 @@ update_cache(struct module_qstate *qstate, int id)
}
/* lru_entry->lock is locked regardless of how we got here,
* either from the slabhash_lookup, or above in the new allocated */
if(!qstate->return_msg && qstate->error_response_cache) {
struct subnet_msg_cache_data *data =
(struct subnet_msg_cache_data*)lru_entry->data;
data->ttl_servfail = *qstate->env->now + NORR_TTL;
data->ede_fail = errinf_to_reason_bogus(qstate);
diff_size = (data->reason_fail?strlen(data->reason_fail)+1:0);
if(qstate->errinf) {
char* str = errinf_to_str_misc(qstate);
free(data->reason_fail);
data->reason_fail = NULL;
if(str)
data->reason_fail = strdup(str);
}
diff_size = (data->reason_fail?strlen(data->reason_fail)+1:0)
- diff_size;
lock_rw_unlock(&lru_entry->lock);
if (need_to_insert) {
slabhash_insert(subnet_msg_cache, h, lru_entry,
lru_entry->data, NULL);
} else {
slabhash_update_space_used(subnet_msg_cache, h, NULL,
diff_size);
}
return;
}
if(!qstate->return_msg) {
lock_rw_unlock(&lru_entry->lock);
return;
}
/* Step 2, find the correct tree */
if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
lock_rw_unlock(&lru_entry->lock);
@@ -412,22 +486,43 @@ update_cache(struct module_qstate *qstate, int id)
rep->ref[i].id = rep->rrsets[i]->id;
}
reply_info_set_ttls(rep, *qstate->env->now);
reply_info_sortref(rep);
rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0)
only_match_scope_zero = 1;
else only_match_scope_zero = 0;
diff_size = (int)tree->size_bytes;
addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
edns->subnet_source_mask, sq->max_scope, rep,
rep->ttl, *qstate->env->now, only_match_scope_zero);
diff_size = (int)tree->size_bytes - diff_size;
lock_rw_unlock(&lru_entry->lock);
if (need_to_insert) {
slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
NULL);
} else {
slabhash_update_space_used(subnet_msg_cache, h, NULL,
diff_size);
}
}
/** See if there is a stored servfail, returns true if so, and sets reply. */
static int
lookup_check_servfail(struct module_qstate *qstate,
struct subnet_msg_cache_data *data)
{
struct module_env *env = qstate->env;
if(!data)
return 0;
if(!data->ttl_servfail || TTL_IS_EXPIRED(data->ttl_servfail, *env->now))
return 0;
qstate->return_rcode = LDNS_RCODE_SERVFAIL;
errinf_ede(qstate, data->reason_fail, data->ede_fail);
return 1;
}
/** Lookup in cache and reply true iff reply is sent. */
static int
lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq, int prefetch)
@@ -441,6 +536,8 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq,
struct addrtree *tree;
struct addrnode *node;
uint8_t scope;
int must_validate = (!(qstate->query_flags&BIT_CD)
|| qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out));
@@ -454,12 +551,20 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq,
tree = (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4)?
data->tree4 : data->tree6;
if (!tree) { /* qinfo in cache but not for this family */
if(lookup_check_servfail(qstate, data)) {
lock_rw_unlock(&e->lock);
return 1;
}
lock_rw_unlock(&e->lock);
return 0;
}
node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr,
ecs->subnet_source_mask, *env->now);
if (!node) { /* plain old cache miss */
if(lookup_check_servfail(qstate, data)) {
lock_rw_unlock(&e->lock);
return 1;
}
lock_rw_unlock(&e->lock);
return 0;
}
@@ -468,12 +573,24 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq,
(struct reply_info *)node->elem, qstate->region, *env->now, 0,
env->scratch);
scope = (uint8_t)node->scope;
lock_rw_unlock(&e->lock);
if (!qstate->return_msg) { /* Failed allocation or expired TTL */
if(lookup_check_servfail(qstate, data)) {
lock_rw_unlock(&e->lock);
return 1;
}
lock_rw_unlock(&e->lock);
return 0;
}
lock_rw_unlock(&e->lock);
if(qstate->return_msg->rep->security == sec_status_unchecked
&& must_validate) {
/* The message has to be validated first. */
verbose(VERB_ALGO, "subnet: unchecked cache entry needs "
"validation");
return 0;
}
if (sq->subnet_downstream) { /* relay to interested client */
sq->ecs_client_out.subnet_scope_mask = scope;
sq->ecs_client_out.subnet_addr_fam = ecs->subnet_addr_fam;
@@ -504,6 +621,87 @@ common_prefix(uint8_t *a, uint8_t *b, uint8_t net)
return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]);
}
/**
* Create sub request that looks up the query.
* @param qstate: query state
* @param id: module id.
* @param sq: subnet qstate
* @return false on failure.
*/
static int
generate_sub_request(struct module_qstate *qstate, int id, struct subnet_qstate* sq)
{
struct module_qstate* subq = NULL;
uint16_t qflags = 0; /* OPCODE QUERY, no flags */
int prime = 0;
int valrec = 0;
struct query_info qinf;
qinf.qname = qstate->qinfo.qname;
qinf.qname_len = qstate->qinfo.qname_len;
qinf.qtype = qstate->qinfo.qtype;
qinf.qclass = qstate->qinfo.qclass;
qinf.local_alias = NULL;
qflags |= BIT_RD;
if((qstate->query_flags & BIT_CD)!=0) {
qflags |= BIT_CD;
/* The valrec is left off. Leave out: valrec = 1;
* So that the cache is protected with DNSSEC validation.
* Just like the global cache. DNSSEC validation is performed
* regardless of the setting of the querier's CD flag. */
}
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
if(!(*qstate->env->attach_sub)(qstate, &qinf, qstate->client_info,
qflags, prime, valrec, &subq)) {
return 0;
}
if(subq) {
/* It is possible to access the subquery module state. */
struct subnet_qstate* subsq;
if(!subnet_new_qstate(subq, id)) {
verbose(VERB_ALGO, "Could not allocate new subnet qstate");
return 0;
}
subsq = (struct subnet_qstate*)subq->minfo[id];
subsq->is_subquery_nonsubnet = 1;
subsq->started_no_cache_store = sq->started_no_cache_store;
/* When the client asks 0.0.0.0/0 and the name is not treated
* as subnet, it is to be stored in the global cache.
* Store that the client asked for that, if so. */
if(sq->ecs_client_in.subnet_source_mask == 0 &&
edns_opt_list_find(qstate->edns_opts_front_in,
qstate->env->cfg->client_subnet_opcode)) {
subq->no_cache_store = 1;
subsq->is_subquery_scopezero = 1;
}
}
return 1;
}
/**
* Perform the query without subnet
* @param qstate: query state
* @param id: module id.
* @param sq: subnet qstate
* @return module state
*/
static enum module_ext_state
generate_lookup_without_subnet(struct module_qstate *qstate, int id,
struct subnet_qstate* sq)
{
verbose(VERB_ALGO, "subnetcache: make subquery to look up without subnet");
if(!generate_sub_request(qstate, id, sq)) {
verbose(VERB_ALGO, "Could not generate sub query");
qstate->return_rcode = LDNS_RCODE_SERVFAIL;
qstate->return_msg = NULL;
return module_finished;
}
sq->wait_subquery = 1;
return module_wait_subquery;
}
static enum module_ext_state
eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
{
@@ -520,6 +718,12 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
/* already an answer and its not a message, but retain
* the actual rcode, instead of module_error, so send
* module_finished */
if(qstate->error_response_cache) {
verbose(VERB_ALGO, "subnet: store error response");
lock_rw_wrlock(&sne->biglock);
update_cache(qstate, id);
lock_rw_unlock(&sne->biglock);
}
return module_finished;
}
@@ -539,14 +743,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
* is still useful to put it in the edns subnet cache for
* when a client explicitly asks for subnet specific answer. */
verbose(VERB_QUERY, "subnetcache: Authority indicates no support");
if(!sq->started_no_cache_store) {
lock_rw_wrlock(&sne->biglock);
update_cache(qstate, id);
lock_rw_unlock(&sne->biglock);
}
if (sq->subnet_downstream)
cp_edns_bad_response(c_out, c_in);
return module_finished;
return generate_lookup_without_subnet(qstate, id, sq);
}
/* Purposefully there was no sent subnet, and there is consequently
@@ -571,14 +768,14 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
!common_prefix(s_out->subnet_addr, s_in->subnet_addr,
s_out->subnet_source_mask))
{
/* we can not accept, restart query without option */
/* we can not accept, perform query without option */
verbose(VERB_QUERY, "subnetcache: forged data");
s_out->subnet_validdata = 0;
(void)edns_opt_list_remove(&qstate->edns_opts_back_out,
qstate->env->cfg->client_subnet_opcode);
sq->subnet_sent = 0;
sq->subnet_sent_no_subnet = 0;
return module_restart_next;
return generate_lookup_without_subnet(qstate, id, sq);
}
lock_rw_wrlock(&sne->biglock);
@@ -587,7 +784,21 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
}
sne->num_msg_nocache++;
lock_rw_unlock(&sne->biglock);
/* If there is an expired answer in the global cache, remove that,
* because expired answers would otherwise resurface once the ecs data
* expires, giving once in a while global data responses for ecs
* domains, with serve expired enabled. */
if(qstate->env->cfg->serve_expired) {
msg_cache_remove(qstate->env, qstate->qinfo.qname,
qstate->qinfo.qname_len, qstate->qinfo.qtype,
qstate->qinfo.qclass, 0);
#ifdef USE_CACHEDB
if(qstate->env->cachedb_enabled)
cachedb_msg_remove(qstate);
#endif
}
if (sq->subnet_downstream) {
/* Client wants to see the answer, echo option back
* and adjust the scope. */
@@ -762,6 +973,11 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
sq->max_scope = sq->ecs_server_in.subnet_scope_mask;
} else if(sq->subnet_sent_no_subnet) {
/* The answer can be stored as scope 0, not in global cache. */
/* This was already set in ecs_whitelist_check */
qstate->no_cache_store = 1;
} else if(sq->subnet_sent) {
/* Need another query to be able to store in global cache. */
/* This was already set in ecs_whitelist_check */
qstate->no_cache_store = 1;
}
@@ -780,6 +996,32 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
strmodulevent(event));
log_query_info(VERB_QUERY, "subnetcache operate: query", &qstate->qinfo);
if(sq && sq->wait_subquery_done) {
/* The subquery lookup returned. */
if(sq->ecs_client_in.subnet_source_mask == 0 &&
edns_opt_list_find(qstate->edns_opts_front_in,
qstate->env->cfg->client_subnet_opcode)) {
if(!sq->started_no_cache_store &&
qstate->return_msg) {
lock_rw_wrlock(&sne->biglock);
update_cache(qstate, id);
lock_rw_unlock(&sne->biglock);
}
if (sq->subnet_downstream)
cp_edns_bad_response(&sq->ecs_client_out,
&sq->ecs_client_in);
/* It is a scope zero lookup, append edns subnet
* option to the querier. */
subnet_ecs_opt_list_append(&sq->ecs_client_out,
&qstate->edns_opts_front_out, qstate,
qstate->region);
}
sq->wait_subquery_done = 0;
qstate->ext_state[id] = module_finished;
qstate->no_cache_store = sq->started_no_cache_store;
qstate->no_cache_lookup = sq->started_no_cache_lookup;
return;
}
if((event == module_event_new || event == module_event_pass) &&
sq == NULL) {
struct edns_option* ecs_opt;
@@ -790,6 +1032,8 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
}
sq = (struct subnet_qstate*)qstate->minfo[id];
if(sq->wait_subquery)
return; /* Wait for that subquery to return */
if((ecs_opt = edns_opt_list_find(
qstate->edns_opts_front_in,
@@ -819,6 +1063,14 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
/* No clients are interested in result or we could not
* parse it, we don't do client subnet */
sq->ecs_server_out.subnet_validdata = 0;
if(edns_opt_list_find(qstate->edns_opts_front_in,
qstate->env->cfg->client_subnet_opcode)) {
/* aggregated this deaggregated state */
qstate->ext_state[id] =
generate_lookup_without_subnet(
qstate, id, sq);
return;
}
verbose(VERB_ALGO, "subnetcache: pass to next module");
qstate->ext_state[id] = module_wait_module;
return;
@@ -859,6 +1111,14 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
}
lock_rw_unlock(&sne->biglock);
}
if(sq->ecs_client_in.subnet_source_mask == 0 &&
edns_opt_list_find(qstate->edns_opts_front_in,
qstate->env->cfg->client_subnet_opcode)) {
/* client asked for resolution without edns subnet */
qstate->ext_state[id] = generate_lookup_without_subnet(
qstate, id, sq);
return;
}
sq->ecs_server_out.subnet_addr_fam =
sq->ecs_client_in.subnet_addr_fam;
@@ -895,6 +1155,8 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
qstate->ext_state[id] = module_wait_module;
return;
}
if(sq && sq->wait_subquery)
return; /* Wait for that subquery to return */
/* Query handed back by next module, we have a 'final' answer */
if(sq && event == module_event_moddone) {
qstate->ext_state[id] = eval_response(qstate, id, sq);
@@ -943,10 +1205,27 @@ subnetmod_clear(struct module_qstate *ATTR_UNUSED(qstate),
}
void
subnetmod_inform_super(struct module_qstate *ATTR_UNUSED(qstate),
int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super))
subnetmod_inform_super(struct module_qstate *qstate, int id,
struct module_qstate *super)
{
/* Not used */
struct subnet_qstate* super_sq =
(struct subnet_qstate*)super->minfo[id];
log_query_info(VERB_ALGO, "subnetcache inform_super: query",
&super->qinfo);
super_sq->wait_subquery = 0;
super_sq->wait_subquery_done = 1;
if(qstate->return_rcode != LDNS_RCODE_NOERROR ||
!qstate->return_msg) {
super->return_msg = NULL;
super->return_rcode = LDNS_RCODE_SERVFAIL;
return;
}
super->return_rcode = LDNS_RCODE_NOERROR;
super->return_msg = dns_copy_msg(qstate->return_msg, super->region);
if(!super->return_msg) {
log_err("subnetcache: copy response, out of memory");
super->return_rcode = LDNS_RCODE_SERVFAIL;
}
}
size_t
@@ -963,7 +1242,8 @@ subnetmod_get_mem(struct module_env *env, int id)
* The module function block
*/
static struct module_func_block subnetmod_block = {
"subnetcache", &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
"subnetcache",
NULL, NULL, &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
&subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem
};
+18
View File
@@ -69,8 +69,18 @@ struct subnet_env {
};
struct subnet_msg_cache_data {
/** Tree for nodes with IPv4 subnets. */
struct addrtree* tree4;
/** Tree for nodes with IPv6 subnets. */
struct addrtree* tree6;
/** If servfail is stored, for how long. Abs time in seconds.
* This protects against too much recusion on the item when
* resolution fails, for a couple of seconds. */
time_t ttl_servfail;
/** servfail ede */
sldns_ede_code ede_fail;
/** servfail reason */
char* reason_fail;
};
struct subnet_qstate {
@@ -102,6 +112,14 @@ struct subnet_qstate {
int started_no_cache_store;
/** has the subnet module been started with no_cache_lookup? */
int started_no_cache_lookup;
/** Wait for subquery that has been started for nonsubnet lookup. */
int wait_subquery;
/** The subquery waited for is done. */
int wait_subquery_done;
/** The subnet state is a subquery state for nonsubnet lookup. */
int is_subquery_nonsubnet;
/** This is a subquery, and it is made due to a scope zero request. */
int is_subquery_scopezero;
};
void subnet_data_delete(void* d, void* ATTR_UNUSED(arg));
+4 -3
View File
@@ -163,7 +163,7 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name,
}
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
if(!(*qstate->env->attach_sub)(qstate, &ask,
if(!(*qstate->env->attach_sub)(qstate, &ask, NULL,
(uint16_t)(BIT_RD|flags), 0, 0, &newq)){
log_err("Could not generate request: out of memory");
return 0;
@@ -456,7 +456,8 @@ ipsecmod_handle_query(struct module_qstate* qstate,
/* Store A/AAAA in cache. */
if(!dns_cache_store(qstate->env, &qstate->qinfo,
qstate->return_msg->rep, 0, qstate->prefetch_leeway,
0, qstate->region, qstate->query_flags, qstate->qstarttime)) {
0, qstate->region, qstate->query_flags, qstate->qstarttime,
qstate->is_valrec)) {
log_err("ipsecmod: out of memory caching record");
}
qstate->ext_state[id] = module_finished;
@@ -615,7 +616,7 @@ ipsecmod_get_mem(struct module_env* env, int id)
*/
static struct module_func_block ipsecmod_block = {
"ipsecmod",
&ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate,
NULL, NULL, &ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate,
&ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem
};
+162 -47
View File
@@ -17,9 +17,19 @@
#include "sldns/wire2str.h"
#include "sldns/parseutil.h"
#ifdef HAVE_NET_PFVAR_H
#include <fcntl.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/pfvar.h>
typedef intptr_t filter_dev;
#else
#include <libmnl/libmnl.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/ipset/ip_set.h>
typedef struct mnl_socket * filter_dev;
#endif
#define BUFF_LEN 256
@@ -41,24 +51,95 @@ static int error_response(struct module_qstate* qstate, int id, int rcode) {
return 0;
}
static struct mnl_socket * open_mnl_socket() {
struct mnl_socket *mnl;
#ifdef HAVE_NET_PFVAR_H
static void * open_filter() {
filter_dev dev;
mnl = mnl_socket_open(NETLINK_NETFILTER);
if (!mnl) {
dev = open("/dev/pf", O_RDWR);
if (dev == -1) {
log_err("open(\"/dev/pf\") failed: %s", strerror(errno));
return NULL;
}
else
return (void *)dev;
}
#else
static void * open_filter() {
filter_dev dev;
dev = mnl_socket_open(NETLINK_NETFILTER);
if (!dev) {
log_err("ipset: could not open netfilter.");
return NULL;
}
if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) {
mnl_socket_close(mnl);
if (mnl_socket_bind(dev, 0, MNL_SOCKET_AUTOPID) < 0) {
mnl_socket_close(dev);
log_err("ipset: could not bind netfilter.");
return NULL;
}
return mnl;
return (void *)dev;
}
#endif
static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void *ipaddr, int af) {
#ifdef HAVE_NET_PFVAR_H
static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr, int af) {
struct pfioc_table io;
struct pfr_addr addr;
const char *p;
int i;
bzero(&io, sizeof(io));
bzero(&addr, sizeof(addr));
p = strrchr(setname, '/');
if (p) {
i = p - setname;
if (i >= PATH_MAX) {
errno = ENAMETOOLONG;
return -1;
}
memcpy(io.pfrio_table.pfrt_anchor, setname, i);
if (i < PATH_MAX)
io.pfrio_table.pfrt_anchor[i] = '\0';
p++;
}
else
p = setname;
if (strlen(p) >= PF_TABLE_NAME_SIZE) {
errno = ENAMETOOLONG;
return -1;
}
strlcpy(io.pfrio_table.pfrt_name, p, PF_TABLE_NAME_SIZE);
io.pfrio_buffer = &addr;
io.pfrio_size = 1;
io.pfrio_esize = sizeof(addr);
switch (af) {
case AF_INET:
addr.pfra_ip4addr = *(struct in_addr *)ipaddr;
addr.pfra_net = 32;
break;
case AF_INET6:
addr.pfra_ip6addr = *(struct in6_addr *)ipaddr;
addr.pfra_net = 128;
break;
default:
errno = EAFNOSUPPORT;
return -1;
}
addr.pfra_af = af;
if (ioctl(dev, DIOCRADDADDRS, &io) == -1) {
log_err("ioctl failed: %s", strerror(errno));
return -1;
}
return 0;
}
#else
static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr, int af) {
struct nlmsghdr *nlh;
struct nfgenmsg *nfg;
struct nlattr *nested[2];
@@ -91,14 +172,15 @@ static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void
mnl_attr_nest_end(nlh, nested[1]);
mnl_attr_nest_end(nlh, nested[0]);
if (mnl_socket_sendto(mnl, nlh, nlh->nlmsg_len) < 0) {
if (mnl_socket_sendto(dev, nlh, nlh->nlmsg_len) < 0) {
return -1;
}
return 0;
}
#endif
static void
ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
ipset_add_rrset_data(struct ipset_env *ie,
struct packed_rrset_data *d, const char* setname, int af,
const char* dname)
{
@@ -123,12 +205,16 @@ ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
snprintf(ip, sizeof(ip), "(inet_ntop_error)");
verbose(VERB_QUERY, "ipset: add %s to %s for %s", ip, setname, dname);
}
ret = add_to_ipset(mnl, setname, rr_data + 2, af);
ret = add_to_ipset((filter_dev)ie->dev, setname, rr_data + 2, af);
if (ret < 0) {
log_err("ipset: could not add %s into %s", dname, setname);
mnl_socket_close(mnl);
ie->mnl = NULL;
#if HAVE_NET_PFVAR_H
/* don't close as we might not be able to open again due to dropped privs */
#else
mnl_socket_close((filter_dev)ie->dev);
ie->dev = NULL;
#endif
break;
}
}
@@ -137,8 +223,8 @@ ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
static int
ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
struct mnl_socket *mnl, struct ub_packed_rrset_key *rrset,
const char *qname, const int qlen, const char *setname, int af)
struct ub_packed_rrset_key *rrset, const char *qname, int qlen,
const char *setname, int af)
{
static char dname[BUFF_LEN];
const char *ds, *qs;
@@ -152,11 +238,20 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
log_err("bad domain name");
return -1;
}
if (dname[dlen - 1] == '.') {
dlen--;
}
if (qname[qlen - 1] == '.') {
qlen--;
}
for (p = env->cfg->local_zones_ipset; p; p = p->next) {
ds = NULL;
qs = NULL;
plen = strlen(p->str);
if (p->str[plen - 1] == '.') {
plen--;
}
if (dlen == plen || (dlen > plen && dname[dlen - plen - 1] == '.' )) {
ds = dname + (dlen - plen);
@@ -167,8 +262,7 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
if ((ds && strncasecmp(p->str, ds, plen) == 0)
|| (qs && strncasecmp(p->str, qs, plen) == 0)) {
d = (struct packed_rrset_data*)rrset->entry.data;
ipset_add_rrset_data(ie, mnl, d, setname,
af, dname);
ipset_add_rrset_data(ie, d, setname, af, dname);
break;
}
}
@@ -178,7 +272,6 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
struct query_info qinfo, struct ipset_env *ie)
{
struct mnl_socket *mnl;
size_t i;
const char *setname;
struct ub_packed_rrset_key *rrset;
@@ -186,15 +279,17 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
static char qname[BUFF_LEN];
int qlen;
mnl = (struct mnl_socket *)ie->mnl;
if (!mnl) {
#ifdef HAVE_NET_PFVAR_H
#else
if (!ie->dev) {
/* retry to create mnl socket */
mnl = open_mnl_socket();
if (!mnl) {
ie->dev = open_filter();
if (!ie->dev) {
log_warn("ipset open_filter failed");
return -1;
}
ie->mnl = mnl;
}
#endif
qlen = sldns_wire2str_dname_buf(qinfo.qname, qinfo.qname_len,
qname, BUFF_LEN);
@@ -217,8 +312,8 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
}
if (setname) {
if(ipset_check_zones_for_rrset(env, ie, mnl, rrset,
qname, qlen, setname, af) == -1)
if(ipset_check_zones_for_rrset(env, ie, rrset, qname,
qlen, setname, af) == -1)
return -1;
}
}
@@ -226,7 +321,7 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
return 0;
}
int ipset_init(struct module_env* env, int id) {
int ipset_startup(struct module_env* env, int id) {
struct ipset_env *ipset_env;
ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env));
@@ -237,7 +332,43 @@ int ipset_init(struct module_env* env, int id) {
env->modinfo[id] = (void *)ipset_env;
ipset_env->mnl = NULL;
#ifdef HAVE_NET_PFVAR_H
ipset_env->dev = open_filter();
if (!ipset_env->dev) {
log_err("ipset open_filter failed");
return 0;
}
#else
ipset_env->dev = NULL;
#endif
return 1;
}
void ipset_destartup(struct module_env* env, int id) {
filter_dev dev;
struct ipset_env *ipset_env;
if (!env || !env->modinfo[id]) {
return;
}
ipset_env = (struct ipset_env*)env->modinfo[id];
dev = (filter_dev)ipset_env->dev;
if (dev) {
#if HAVE_NET_PFVAR_H
close(dev);
#else
mnl_socket_close(dev);
#endif
ipset_env->dev = NULL;
}
free(ipset_env);
env->modinfo[id] = NULL;
}
int ipset_init(struct module_env* env, int id) {
struct ipset_env *ipset_env = env->modinfo[id];
ipset_env->name_v4 = env->cfg->ipset_name_v4;
ipset_env->name_v6 = env->cfg->ipset_name_v6;
@@ -253,24 +384,8 @@ int ipset_init(struct module_env* env, int id) {
return 1;
}
void ipset_deinit(struct module_env *env, int id) {
struct mnl_socket *mnl;
struct ipset_env *ipset_env;
if (!env || !env->modinfo[id]) {
return;
}
ipset_env = (struct ipset_env *)env->modinfo[id];
mnl = (struct mnl_socket *)ipset_env->mnl;
if (mnl) {
mnl_socket_close(mnl);
ipset_env->mnl = NULL;
}
free(ipset_env);
env->modinfo[id] = NULL;
void ipset_deinit(struct module_env *ATTR_UNUSED(env), int ATTR_UNUSED(id)) {
/* nothing */
}
static int ipset_new(struct module_qstate* qstate, int id) {
@@ -376,8 +491,8 @@ size_t ipset_get_mem(struct module_env *env, int id) {
*/
static struct module_func_block ipset_block = {
"ipset",
&ipset_init, &ipset_deinit, &ipset_operate,
&ipset_inform_super, &ipset_clear, &ipset_get_mem
&ipset_startup, &ipset_destartup, &ipset_init, &ipset_deinit,
&ipset_operate, &ipset_inform_super, &ipset_clear, &ipset_get_mem
};
struct module_func_block * ipset_get_funcblock(void) {
+5 -1
View File
@@ -37,7 +37,7 @@ extern "C" {
#endif
struct ipset_env {
void* mnl;
void* dev;
int v4_enabled;
int v6_enabled;
@@ -50,6 +50,10 @@ struct ipset_qstate {
int dummy;
};
/** Startup the ipset module */
int ipset_startup(struct module_env* env, int id);
/** Destartup the ipset module */
void ipset_destartup(struct module_env* env, int id);
/** Init the ipset module */
int ipset_init(struct module_env* env, int id);
/** Deinit the ipset module */
+1 -1
View File
@@ -278,7 +278,7 @@ delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres,
void delegpt_log(enum verbosity_value v, struct delegpt* dp)
{
char buf[LDNS_MAX_DOMAINLEN+1];
char buf[LDNS_MAX_DOMAINLEN];
struct delegpt_ns* ns;
struct delegpt_addr* a;
size_t missing=0, numns=0, numaddr=0, numres=0, numavail=0;
+10
View File
@@ -79,6 +79,16 @@ struct delegpt {
* Also true if the delegationpoint was created from a delegation
* message and thus contains the parent-side-info already. */
uint8_t has_parent_side_NS;
/** if true, the delegation point has reached last resort processing
* and the parent side information has been possibly added to the
* delegation point.
* For now this signals that further target lookups will ignore
* the configured target-fetch-policy and only resolve on
* demand to try and avoid triggering limits at this stage (.i.e, it
* is very likely that the A/AAAA queries for the newly added name
* servers will not yield new IP addresses and trigger NXNS
* countermeasures. */
uint8_t fallback_to_parent_side_NS;
/** for assertions on type of delegpt */
uint8_t dp_type_mlc;
/** use SSL for upstream query */
+169 -38
View File
@@ -71,6 +71,7 @@ forwards_create(void)
sizeof(struct iter_forwards));
if(!fwd)
return NULL;
lock_rw_init(&fwd->lock);
return fwd;
}
@@ -100,6 +101,7 @@ forwards_delete(struct iter_forwards* fwd)
{
if(!fwd)
return;
lock_rw_destroy(&fwd->lock);
fwd_del_tree(fwd);
free(fwd);
}
@@ -127,7 +129,7 @@ forwards_insert_data(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
node->namelabs = nmlabs;
node->dp = dp;
if(!rbtree_insert(fwd->tree, &node->node)) {
char buf[257];
char buf[LDNS_MAX_DOMAINLEN];
dname_str(nm, buf);
log_err("duplicate forward zone %s ignored.", buf);
delegpt_free_mlc(dp);
@@ -137,6 +139,17 @@ forwards_insert_data(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
return 1;
}
static struct iter_forward_zone*
fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
{
struct iter_forward_zone key;
key.node.key = &key;
key.dclass = c;
key.name = nm;
key.namelabs = dname_count_size_labels(nm, &key.namelen);
return (struct iter_forward_zone*)rbtree_search(fwd->tree, &key);
}
/** insert new info into forward structure given dp */
static int
forwards_insert(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
@@ -215,6 +228,11 @@ read_fwds_host(struct config_stub* s, struct delegpt* dp)
s->name, p->str);
return 0;
}
if(dname_subdomain_c(dname, dp->name)) {
log_warn("forward-host '%s' may have a circular "
"dependency on forward-zone '%s'",
p->str, s->name);
}
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
if(tls_auth_name)
log_err("no name verification functionality in "
@@ -319,6 +337,40 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
log_err("cannot parse stub name '%s'", s->name);
return 0;
}
if(fwd_zone_find(fwd, LDNS_RR_CLASS_IN, dname) != NULL) {
/* Already a forward zone there. */
free(dname);
continue;
}
if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN, dname)) {
free(dname);
log_err("out of memory");
return 0;
}
free(dname);
}
return 1;
}
/** make NULL entries for auths */
static int
make_auth_holes(struct iter_forwards* fwd, struct config_file* cfg)
{
struct config_auth* a;
uint8_t* dname;
size_t dname_len;
for(a = cfg->auths; a; a = a->next) {
if(!a->name) continue;
dname = sldns_str2wire_dname(a->name, &dname_len);
if(!dname) {
log_err("cannot parse auth name '%s'", a->name);
return 0;
}
if(fwd_zone_find(fwd, LDNS_RR_CLASS_IN, dname) != NULL) {
/* Already a forward zone there. */
free(dname);
continue;
}
if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN, dname)) {
free(dname);
log_err("out of memory");
@@ -332,45 +384,74 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
int
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
{
if(fwd->tree) {
lock_unprotect(&fwd->lock, fwd->tree);
}
fwd_del_tree(fwd);
fwd->tree = rbtree_create(fwd_cmp);
if(!fwd->tree)
return 0;
lock_protect(&fwd->lock, fwd->tree, sizeof(*fwd->tree));
lock_rw_wrlock(&fwd->lock);
/* read forward zones */
if(!read_forwards(fwd, cfg))
if(!read_forwards(fwd, cfg)) {
lock_rw_unlock(&fwd->lock);
return 0;
if(!make_stub_holes(fwd, cfg))
}
if(!make_stub_holes(fwd, cfg)) {
lock_rw_unlock(&fwd->lock);
return 0;
}
/* TODO: Now we punch holes for auth zones as well so that in
* iterator:forward_request() we see the configured
* delegation point, but code flow/naming is hard to follow.
* Consider having a single tree with configured
* delegation points for all categories
* (stubs, forwards, auths). */
if(!make_auth_holes(fwd, cfg)) {
lock_rw_unlock(&fwd->lock);
return 0;
}
fwd_init_parents(fwd);
lock_rw_unlock(&fwd->lock);
return 1;
}
struct delegpt*
forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass,
int nolock)
{
rbnode_type* res = NULL;
struct iter_forward_zone* res;
struct iter_forward_zone key;
int has_dp;
key.node.key = &key;
key.dclass = qclass;
key.name = qname;
key.namelabs = dname_count_size_labels(qname, &key.namelen);
res = rbtree_search(fwd->tree, &key);
if(res) return ((struct iter_forward_zone*)res)->dp;
return NULL;
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
res = (struct iter_forward_zone*)rbtree_search(fwd->tree, &key);
has_dp = res && res->dp;
if(!has_dp && !nolock) { lock_rw_unlock(&fwd->lock); }
return has_dp?res->dp:NULL;
}
struct delegpt*
forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass,
int nolock)
{
/* lookup the forward zone in the tree */
rbnode_type* res = NULL;
struct iter_forward_zone *result;
struct iter_forward_zone key;
int has_dp;
key.node.key = &key;
key.dclass = qclass;
key.name = qname;
key.namelabs = dname_count_size_labels(qname, &key.namelen);
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
if(rbtree_find_less_equal(fwd->tree, &key, &res)) {
/* exact */
result = (struct iter_forward_zone*)res;
@@ -378,8 +459,10 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
/* smaller element (or no element) */
int m;
result = (struct iter_forward_zone*)res;
if(!result || result->dclass != qclass)
if(!result || result->dclass != qclass) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return NULL;
}
/* count number of labels matched */
(void)dname_lab_cmp(result->name, result->namelabs, key.name,
key.namelabs, &m);
@@ -389,20 +472,22 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
result = result->parent;
}
}
if(result)
return result->dp;
return NULL;
has_dp = result && result->dp;
if(!has_dp && !nolock) { lock_rw_unlock(&fwd->lock); }
return has_dp?result->dp:NULL;
}
struct delegpt*
forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass)
forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass, int nolock)
{
uint8_t root = 0;
return forwards_lookup(fwd, &root, qclass);
return forwards_lookup(fwd, &root, qclass, nolock);
}
int
forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
/* Finds next root item in forwards lookup tree.
* Caller needs to handle locking of the forwards structure. */
static int
next_root_locked(struct iter_forwards* fwd, uint16_t* dclass)
{
struct iter_forward_zone key;
rbnode_type* n;
@@ -419,7 +504,7 @@ forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
}
/* root not first item? search for higher items */
*dclass = p->dclass + 1;
return forwards_next_root(fwd, dclass);
return next_root_locked(fwd, dclass);
}
/* find class n in tree, we may get a direct hit, or if we don't
* this is the last item of the previous class so rbtree_next() takes
@@ -447,10 +532,21 @@ forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
}
/* not a root node, return next higher item */
*dclass = p->dclass+1;
return forwards_next_root(fwd, dclass);
return next_root_locked(fwd, dclass);
}
}
int
forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass, int nolock)
{
int ret;
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
ret = next_root_locked(fwd, dclass);
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return ret;
}
size_t
forwards_get_mem(struct iter_forwards* fwd)
{
@@ -458,69 +554,104 @@ forwards_get_mem(struct iter_forwards* fwd)
size_t s;
if(!fwd)
return 0;
lock_rw_rdlock(&fwd->lock);
s = sizeof(*fwd) + sizeof(*fwd->tree);
RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) {
s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp);
}
lock_rw_unlock(&fwd->lock);
return s;
}
static struct iter_forward_zone*
fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
{
struct iter_forward_zone key;
key.node.key = &key;
key.dclass = c;
key.name = nm;
key.namelabs = dname_count_size_labels(nm, &key.namelen);
return (struct iter_forward_zone*)rbtree_search(fwd->tree, &key);
}
int
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp,
int nolock)
{
struct iter_forward_zone *z;
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
if((z=fwd_zone_find(fwd, c, dp->name)) != NULL) {
(void)rbtree_delete(fwd->tree, &z->node);
fwd_zone_free(z);
}
if(!forwards_insert(fwd, c, dp))
if(!forwards_insert(fwd, c, dp)) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return 0;
}
fwd_init_parents(fwd);
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return 1;
}
void
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
int nolock)
{
struct iter_forward_zone *z;
if(!(z=fwd_zone_find(fwd, c, nm)))
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
if(!(z=fwd_zone_find(fwd, c, nm))) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return; /* nothing to do */
}
(void)rbtree_delete(fwd->tree, &z->node);
fwd_zone_free(z);
fwd_init_parents(fwd);
if(!nolock) { lock_rw_unlock(&fwd->lock); }
}
int
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
int nolock)
{
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
if(fwd_zone_find(fwd, c, nm) != NULL) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return 1; /* already a stub zone there */
}
if(!fwd_add_stub_hole(fwd, c, nm)) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return 0;
}
fwd_init_parents(fwd);
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return 1;
}
void
forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
uint8_t* nm, int nolock)
{
struct iter_forward_zone *z;
if(!(z=fwd_zone_find(fwd, c, nm)))
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
if(!(z=fwd_zone_find(fwd, c, nm))) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return; /* nothing to do */
if(z->dp != NULL)
}
if(z->dp != NULL) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return; /* not a stub hole */
}
(void)rbtree_delete(fwd->tree, &z->node);
fwd_zone_free(z);
fwd_init_parents(fwd);
if(!nolock) { lock_rw_unlock(&fwd->lock); }
}
void
forwards_swap_tree(struct iter_forwards* fwd, struct iter_forwards* data)
{
rbtree_type* oldtree = fwd->tree;
if(oldtree) {
lock_unprotect(&fwd->lock, oldtree);
}
if(data->tree) {
lock_unprotect(&data->lock, data->tree);
}
fwd->tree = data->tree;
data->tree = oldtree;
lock_protect(&fwd->lock, fwd->tree, sizeof(*fwd->tree));
lock_protect(&data->lock, data->tree, sizeof(*data->tree));
}
+58 -11
View File
@@ -43,6 +43,7 @@
#ifndef ITERATOR_ITER_FWD_H
#define ITERATOR_ITER_FWD_H
#include "util/rbtree.h"
#include "util/locks.h"
struct config_file;
struct delegpt;
@@ -50,6 +51,11 @@ struct delegpt;
* Iterator forward zones structure
*/
struct iter_forwards {
/** lock on the forwards tree.
* When grabbing both this lock and the anchors.lock, this lock
* is grabbed first. When grabbing both this lock and the hints.lock
* this lock is grabbed first. */
lock_rw_type lock;
/**
* Zones are stored in this tree. Sort order is specially chosen.
* first sorted on qclass. Then on dname in nsec-like order, so that
@@ -106,47 +112,65 @@ int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg);
/**
* Find forward zone exactly by name
* The return value is contents of the forwards structure.
* Caller should lock and unlock a readlock on the forwards structure if nolock
* is set.
* Otherwise caller should unlock the readlock on the forwards structure if a
* value was returned.
* @param fwd: forward storage.
* @param qname: The qname of the query.
* @param qclass: The qclass of the query.
* @param nolock: Skip locking, locking is handled by the caller.
* @return: A delegation point or null.
*/
struct delegpt* forwards_find(struct iter_forwards* fwd, uint8_t* qname,
uint16_t qclass);
uint16_t qclass, int nolock);
/**
* Find forward zone information
* For this qname/qclass find forward zone information, returns delegation
* point with server names and addresses, or NULL if no forwarding is needed.
* The return value is contents of the forwards structure.
* Caller should lock and unlock a readlock on the forwards structure if nolock
* is set.
* Otherwise caller should unlock the readlock on the forwards structure if a
* value was returned.
*
* @param fwd: forward storage.
* @param qname: The qname of the query.
* @param qclass: The qclass of the query.
* @param nolock: Skip locking, locking is handled by the caller.
* @return: A delegation point if the query has to be forwarded to that list,
* otherwise null.
*/
struct delegpt* forwards_lookup(struct iter_forwards* fwd,
uint8_t* qname, uint16_t qclass);
struct delegpt* forwards_lookup(struct iter_forwards* fwd,
uint8_t* qname, uint16_t qclass, int nolock);
/**
* Same as forwards_lookup, but for the root only
* @param fwd: forward storage.
* @param qclass: The qclass of the query.
* @param nolock: Skip locking, locking is handled by the caller.
* @return: A delegation point if root forward exists, otherwise null.
*/
struct delegpt* forwards_lookup_root(struct iter_forwards* fwd,
uint16_t qclass);
struct delegpt* forwards_lookup_root(struct iter_forwards* fwd,
uint16_t qclass, int nolock);
/**
* Find next root item in forwards lookup tree.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a readlock on the forwards structure.
* @param fwd: the forward storage
* @param qclass: class to look at next, or higher.
* @param nolock: Skip locking, locking is handled by the caller.
* @return false if none found, or if true stored in qclass.
*/
int forwards_next_root(struct iter_forwards* fwd, uint16_t* qclass);
int forwards_next_root(struct iter_forwards* fwd, uint16_t* qclass,
int nolock);
/**
* Get memory in use by forward storage
* Locks and unlocks the structure.
* @param fwd: forward storage.
* @return bytes in use
*/
@@ -158,42 +182,65 @@ int fwd_cmp(const void* k1, const void* k2);
/**
* Add zone to forward structure. For external use since it recalcs
* the tree parents.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a writelock on the forwards structure.
* @param fwd: the forward data structure
* @param c: class of zone
* @param dp: delegation point with name and target nameservers for new
* forward zone. malloced.
* @param nolock: Skip locking, locking is handled by the caller.
* @return false on failure (out of memory);
*/
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
struct delegpt* dp);
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
struct delegpt* dp, int nolock);
/**
* Remove zone from forward structure. For external use since it
* recalcs the tree parents.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a writelock on the forwards structure.
* @param fwd: the forward data structure
* @param c: class of zone
* @param nm: name of zone (in uncompressed wireformat).
* @param nolock: Skip locking, locking is handled by the caller.
*/
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c,
uint8_t* nm, int nolock);
/**
* Add stub hole (empty entry in forward table, that makes resolution skip
* a forward-zone because the stub zone should override the forward zone).
* Does not add one if not necessary.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a writelock on the forwards structure.
* @param fwd: the forward data structure
* @param c: class of zone
* @param nm: name of zone (in uncompressed wireformat).
* @param nolock: Skip locking, locking is handled by the caller.
* @return false on failure (out of memory);
*/
int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c,
uint8_t* nm, int nolock);
/**
* Remove stub hole, if one exists.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a writelock on the forwards structure.
* @param fwd: the forward data structure
* @param c: class of zone
* @param nm: name of zone (in uncompressed wireformat).
* @param nolock: Skip locking, locking is handled by the caller.
*/
void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
uint8_t* nm);
uint8_t* nm, int nolock);
/**
* Swap internal tree with preallocated entries. Caller should manage
* the locks.
* @param fwd: the forward data structure.
* @param data: the data structure used to take elements from. This contains
* the old elements on return.
*/
void forwards_swap_tree(struct iter_forwards* fwd, struct iter_forwards* data);
#endif /* ITERATOR_ITER_FWD_H */
+92 -26
View File
@@ -57,6 +57,8 @@ hints_create(void)
sizeof(struct iter_hints));
if(!hints)
return NULL;
lock_rw_init(&hints->lock);
lock_protect(&hints->lock, &hints->tree, sizeof(hints->tree));
return hints;
}
@@ -83,6 +85,7 @@ hints_delete(struct iter_hints* hints)
{
if(!hints)
return;
lock_rw_destroy(&hints->lock);
hints_del_tree(hints);
free(hints);
}
@@ -129,7 +132,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)
dp->has_parent_side_NS = 1;
if(do_ip4) {
if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) goto failed;
if(!ah(dp, "B.ROOT-SERVERS.NET.", "199.9.14.201")) goto failed;
if(!ah(dp, "B.ROOT-SERVERS.NET.", "170.247.170.2")) goto failed;
if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) goto failed;
if(!ah(dp, "D.ROOT-SERVERS.NET.", "199.7.91.13")) goto failed;
if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed;
@@ -144,7 +147,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)
}
if(do_ip6) {
if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed;
if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:200::b")) goto failed;
if(!ah(dp, "B.ROOT-SERVERS.NET.", "2801:1b8:10::b")) goto failed;
if(!ah(dp, "C.ROOT-SERVERS.NET.", "2001:500:2::c")) goto failed;
if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
if(!ah(dp, "E.ROOT-SERVERS.NET.", "2001:500:a8::e")) goto failed;
@@ -178,7 +181,7 @@ hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
node->noprime = (uint8_t)noprime;
if(!name_tree_insert(&hints->tree, &node->node, dp->name, dp->namelen,
dp->namelabs, c)) {
char buf[257];
char buf[LDNS_MAX_DOMAINLEN];
dname_str(dp->name, buf);
log_err("second hints for zone %s ignored.", buf);
delegpt_free_mlc(dp);
@@ -228,6 +231,11 @@ read_stubs_host(struct config_stub* s, struct delegpt* dp)
s->name, p->str);
return 0;
}
if(dname_subdomain_c(dname, dp->name)) {
log_warn("stub-host '%s' may have a circular "
"dependency on stub-zone '%s'",
p->str, s->name);
}
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
if(tls_auth_name)
log_err("no name verification functionality in "
@@ -438,47 +446,70 @@ read_root_hints_list(struct iter_hints* hints, struct config_file* cfg)
int
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
{
int nolock = 1;
lock_rw_wrlock(&hints->lock);
hints_del_tree(hints);
name_tree_init(&hints->tree);
/* read root hints */
if(!read_root_hints_list(hints, cfg))
if(!read_root_hints_list(hints, cfg)) {
lock_rw_unlock(&hints->lock);
return 0;
}
/* read stub hints */
if(!read_stubs(hints, cfg))
if(!read_stubs(hints, cfg)) {
lock_rw_unlock(&hints->lock);
return 0;
}
/* use fallback compiletime root hints */
if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
if(!hints_find_root(hints, LDNS_RR_CLASS_IN, nolock)) {
struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
cfg->do_ip6);
verbose(VERB_ALGO, "no config, using builtin root hints.");
if(!dp)
if(!dp) {
lock_rw_unlock(&hints->lock);
return 0;
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0))
}
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0)) {
lock_rw_unlock(&hints->lock);
return 0;
}
}
name_tree_init_parents(&hints->tree);
lock_rw_unlock(&hints->lock);
return 1;
}
struct delegpt*
hints_lookup_root(struct iter_hints* hints, uint16_t qclass)
struct delegpt*
hints_find(struct iter_hints* hints, uint8_t* qname, uint16_t qclass,
int nolock)
{
struct iter_hints_stub *stub;
size_t len;
int has_dp;
int labs = dname_count_size_labels(qname, &len);
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_rdlock(&hints->lock); }
stub = (struct iter_hints_stub*)name_tree_find(&hints->tree,
qname, len, labs, qclass);
has_dp = stub && stub->dp;
if(!has_dp && !nolock) { lock_rw_unlock(&hints->lock); }
return has_dp?stub->dp:NULL;
}
struct delegpt*
hints_find_root(struct iter_hints* hints, uint16_t qclass, int nolock)
{
uint8_t rootlab = 0;
struct iter_hints_stub *stub;
stub = (struct iter_hints_stub*)name_tree_find(&hints->tree,
&rootlab, 1, 1, qclass);
if(!stub)
return NULL;
return stub->dp;
return hints_find(hints, &rootlab, qclass, nolock);
}
struct iter_hints_stub*
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
uint16_t qclass, struct delegpt* cache_dp)
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
uint16_t qclass, struct delegpt* cache_dp, int nolock)
{
size_t len;
int labs;
@@ -486,14 +517,20 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
/* first lookup the stub */
labs = dname_count_size_labels(qname, &len);
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_rdlock(&hints->lock); }
r = (struct iter_hints_stub*)name_tree_lookup(&hints->tree, qname,
len, labs, qclass);
if(!r) return NULL;
if(!r) {
if(!nolock) { lock_rw_unlock(&hints->lock); }
return NULL;
}
/* If there is no cache (root prime situation) */
if(cache_dp == NULL) {
if(r->dp->namelabs != 1)
return r; /* no cache dp, use any non-root stub */
if(!nolock) { lock_rw_unlock(&hints->lock); }
return NULL;
}
@@ -510,12 +547,18 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
if(dname_strict_subdomain(r->dp->name, r->dp->namelabs,
cache_dp->name, cache_dp->namelabs))
return r; /* need to prime this stub */
if(!nolock) { lock_rw_unlock(&hints->lock); }
return NULL;
}
int hints_next_root(struct iter_hints* hints, uint16_t* qclass)
int hints_next_root(struct iter_hints* hints, uint16_t* qclass, int nolock)
{
return name_tree_next_root(&hints->tree, qclass);
int ret;
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_rdlock(&hints->lock); }
ret = name_tree_next_root(&hints->tree, qclass);
if(!nolock) { lock_rw_unlock(&hints->lock); }
return ret;
}
size_t
@@ -524,40 +567,63 @@ hints_get_mem(struct iter_hints* hints)
size_t s;
struct iter_hints_stub* p;
if(!hints) return 0;
lock_rw_rdlock(&hints->lock);
s = sizeof(*hints);
RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) {
s += sizeof(*p) + delegpt_get_mem(p->dp);
}
lock_rw_unlock(&hints->lock);
return s;
}
int
hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
int noprime)
int noprime, int nolock)
{
struct iter_hints_stub *z;
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_wrlock(&hints->lock); }
if((z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
dp->name, dp->namelen, dp->namelabs, c)) != NULL) {
(void)rbtree_delete(&hints->tree, &z->node);
hints_stub_free(z);
}
if(!hints_insert(hints, c, dp, noprime))
if(!hints_insert(hints, c, dp, noprime)) {
if(!nolock) { lock_rw_unlock(&hints->lock); }
return 0;
}
name_tree_init_parents(&hints->tree);
if(!nolock) { lock_rw_unlock(&hints->lock); }
return 1;
}
void
hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm)
hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm,
int nolock)
{
struct iter_hints_stub *z;
size_t len;
int labs = dname_count_size_labels(nm, &len);
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_wrlock(&hints->lock); }
if(!(z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
nm, len, labs, c)))
nm, len, labs, c))) {
if(!nolock) { lock_rw_unlock(&hints->lock); }
return; /* nothing to do */
}
(void)rbtree_delete(&hints->tree, &z->node);
hints_stub_free(z);
name_tree_init_parents(&hints->tree);
if(!nolock) { lock_rw_unlock(&hints->lock); }
}
void
hints_swap_tree(struct iter_hints* hints, struct iter_hints* data)
{
rbnode_type* oldroot = hints->tree.root;
size_t oldcount = hints->tree.count;
hints->tree.root = data->tree.root;
hints->tree.count = data->tree.count;
data->tree.root = oldroot;
data->tree.count = oldcount;
}
+56 -7
View File
@@ -43,6 +43,7 @@
#ifndef ITERATOR_ITER_HINTS_H
#define ITERATOR_ITER_HINTS_H
#include "util/storage/dnstree.h"
#include "util/locks.h"
struct iter_env;
struct config_file;
struct delegpt;
@@ -51,6 +52,10 @@ struct delegpt;
* Iterator hints structure
*/
struct iter_hints {
/** lock on the forwards tree.
* When grabbing both this lock and the anchors.lock, this lock
* is grabbed first. */
lock_rw_type lock;
/**
* Hints are stored in this tree. Sort order is specially chosen.
* first sorted on qclass. Then on dname in nsec-like order, so that
@@ -95,42 +100,70 @@ void hints_delete(struct iter_hints* hints);
int hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg);
/**
* Find root hints for the given class.
* Find hints for the given class.
* The return value is contents of the hints structure.
* Caller should lock and unlock a readlock on the hints structure if nolock
* is set.
* Otherwise caller should unlock the readlock on the hints structure if a
* value was returned.
* @param hints: hint storage.
* @param qname: the qname that generated the delegation point.
* @param qclass: class for which root hints are requested. host order.
* @param nolock: Skip locking, locking is handled by the caller.
* @return: NULL if no hints, or a ptr to stored hints.
*/
struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass);
struct delegpt* hints_find(struct iter_hints* hints, uint8_t* qname,
uint16_t qclass, int nolock);
/**
* Same as hints_lookup, but for the root only.
* @param hints: hint storage.
* @param qclass: class for which root hints are requested. host order.
* @param nolock: Skip locking, locking is handled by the caller.
* @return: NULL if no hints, or a ptr to stored hints.
*/
struct delegpt* hints_find_root(struct iter_hints* hints,
uint16_t qclass, int nolock);
/**
* Find next root hints (to cycle through all root hints).
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a readlock on the hints structure.
* @param hints: hint storage
* @param qclass: class for which root hints are sought.
* 0 means give the first available root hints class.
* x means, give class x or a higher class if any.
* returns the found class in this variable.
* @param nolock: Skip locking, locking is handled by the caller.
* @return true if a root hint class is found.
* false if not root hint class is found (qclass may have been changed).
*/
int hints_next_root(struct iter_hints* hints, uint16_t* qclass);
int hints_next_root(struct iter_hints* hints, uint16_t* qclass, int nolock);
/**
* Given a qname/qclass combination, and the delegation point from the cache
* for this qname/qclass, determine if this combination indicates that a
* stub hint exists and must be primed.
* The return value is contents of the hints structure.
* Caller should lock and unlock a readlock on the hints structure if nolock
* is set.
* Otherwise caller should unlock the readlock on the hints structure if a
* value was returned.
*
* @param hints: hint storage.
* @param qname: The qname that generated the delegation point.
* @param qclass: The qclass that generated the delegation point.
* @param dp: The cache generated delegation point.
* @param nolock: Skip locking, locking is handled by the caller.
* @return: A priming delegation point if there is a stub hint that must
* be primed, otherwise null.
*/
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
uint8_t* qname, uint16_t qclass, struct delegpt* dp);
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
uint8_t* qname, uint16_t qclass, struct delegpt* dp, int nolock);
/**
* Get memory in use by hints
* Locks and unlocks the structure.
* @param hints: hint storage.
* @return bytes in use
*/
@@ -139,23 +172,39 @@ size_t hints_get_mem(struct iter_hints* hints);
/**
* Add stub to hints structure. For external use since it recalcs
* the tree parents.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a writelock on the hints structure.
* @param hints: the hints data structure
* @param c: class of zone
* @param dp: delegation point with name and target nameservers for new
* hints stub. malloced.
* @param noprime: set noprime option to true or false on new hint stub.
* @param nolock: Skip locking, locking is handled by the caller.
* @return false on failure (out of memory);
*/
int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
int noprime);
int noprime, int nolock);
/**
* Remove stub from hints structure. For external use since it
* recalcs the tree parents.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a writelock on the hints structure.
* @param hints: the hints data structure
* @param c: class of stub zone
* @param nm: name of stub zone (in uncompressed wireformat).
* @param nolock: Skip locking, locking is handled by the caller.
*/
void hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm);
void hints_delete_stub(struct iter_hints* hints, uint16_t c,
uint8_t* nm, int nolock);
/**
* Swap internal tree with preallocated entries. Caller should manage
* the locks.
* @param hints: the hints data structure.
* @param data: the data structure used to take elements from. This contains
* the old elements on return.
*/
void hints_swap_tree(struct iter_hints* hints, struct iter_hints* data);
#endif /* ITERATOR_ITER_HINTS_H */
+167 -1
View File
@@ -207,6 +207,168 @@ size_t priv_get_mem(struct iter_priv* priv)
return sizeof(*priv) + regional_get_mem(priv->region);
}
/**
* Check if svcparam ipv4hint contains a private address.
* @param priv: private address lookup struct.
* @param d: the data bytes.
* @param data_len: number of data bytes in the svcparam.
* @param addr: address to return the private address to log in to.
* It has space for IPv4 and IPv6 addresses.
* @param addrlen: length of the addr. Returns the correct size for the addr.
* @return true if the rdata contains a private address.
*/
static int svcb_ipv4hint_contains_priv_addr(struct iter_priv* priv,
uint8_t* d, uint16_t data_len, struct sockaddr_storage* addr,
socklen_t* addrlen)
{
struct sockaddr_in sa;
*addrlen = (socklen_t)sizeof(struct sockaddr_in);
memset(&sa, 0, sizeof(struct sockaddr_in));
sa.sin_family = AF_INET;
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
while(data_len >= LDNS_IP4ADDRLEN) {
memmove(&sa.sin_addr, d, LDNS_IP4ADDRLEN);
memmove(addr, &sa, *addrlen);
if(priv_lookup_addr(priv, addr, *addrlen))
return 1;
d += LDNS_IP4ADDRLEN;
data_len -= LDNS_IP4ADDRLEN;
}
/* if data_len != 0 here, then the svcparam is malformed. */
return 0;
}
/**
* Check if svcparam ipv6hint contains a private address.
* @param priv: private address lookup struct.
* @param d: the data bytes.
* @param data_len: number of data bytes in the svcparam.
* @param addr: address to return the private address to log in to.
* It has space for IPv4 and IPv6 addresses.
* @param addrlen: length of the addr. Returns the correct size for the addr.
* @return true if the rdata contains a private address.
*/
static int svcb_ipv6hint_contains_priv_addr(struct iter_priv* priv,
uint8_t* d, uint16_t data_len, struct sockaddr_storage* addr,
socklen_t* addrlen)
{
struct sockaddr_in6 sa;
*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
memset(&sa, 0, sizeof(struct sockaddr_in6));
sa.sin6_family = AF_INET6;
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
while(data_len >= LDNS_IP6ADDRLEN) {
memmove(&sa.sin6_addr, d, LDNS_IP6ADDRLEN);
memmove(addr, &sa, *addrlen);
if(priv_lookup_addr(priv, addr, *addrlen))
return 1;
d += LDNS_IP6ADDRLEN;
data_len -= LDNS_IP6ADDRLEN;
}
/* if data_len != 0 here, then the svcparam is malformed. */
return 0;
}
/**
* Check if type SVCB and HTTPS rdata contains a private address.
* @param priv: private address lookup struct.
* @param pkt: the packet.
* @param rr: the rr with rdata to check.
* @param addr: address to return the private address to log in to.
* @param addrlen: length of the addr. Initially the total size, on
* return the correct size for the addr.
* @return true if the rdata contains a private address.
*/
static int svcb_rr_contains_priv_addr(struct iter_priv* priv,
sldns_buffer* pkt, struct rr_parse* rr, struct sockaddr_storage* addr,
socklen_t* addrlen)
{
uint8_t* d = rr->ttl_data;
uint16_t svcparamkey, data_len, rdatalen;
size_t oldpos, dname_len, dname_start, dname_compr_len;
d += 4; /* skip TTL */
rdatalen = sldns_read_uint16(d); /* read rdata length */
d += 2;
if(rdatalen < 2 /* priority */ + 1 /* 1 length target */)
return 0; /* malformed, too short */
d += 2; /* skip priority */
rdatalen -= 2;
oldpos = sldns_buffer_position(pkt);
sldns_buffer_set_position(pkt, (size_t)(d - sldns_buffer_begin(pkt)));
dname_start = sldns_buffer_position(pkt);
dname_len = pkt_dname_len(pkt);
dname_compr_len = sldns_buffer_position(pkt) - dname_start;
sldns_buffer_set_position(pkt, oldpos);
if(dname_len == 0)
return 0; /* dname malformed */
if(dname_compr_len > rdatalen)
return 0; /* malformed */
d += dname_compr_len; /* skip target */
rdatalen -= dname_compr_len;
while(rdatalen >= 4) {
svcparamkey = sldns_read_uint16(d);
data_len = sldns_read_uint16(d+2);
d += 4;
rdatalen -= 4;
/* verify that we have data_len data */
if(data_len > rdatalen) {
/* It is malformed, but if there are addresses
* in there it can be rejected. */
data_len = rdatalen;
}
if(!data_len)
continue; /* no data for the svcparamkey */
if(svcparamkey == SVCB_KEY_IPV4HINT) {
if(svcb_ipv4hint_contains_priv_addr(priv, d, data_len,
addr, addrlen))
return 1;
} else if(svcparamkey == SVCB_KEY_IPV6HINT) {
if(svcb_ipv6hint_contains_priv_addr(priv, d, data_len,
addr, addrlen))
return 1;
}
d += data_len;
rdatalen -= data_len;
}
/* If rdatalen != 0 here, then the svcb rdata is malformed. */
return 0;
}
/**
* Check if the SVCB and HTTPS rrset is bad.
* @param priv: private address lookup struct.
* @param pkt: the packet.
* @param rrset: the rrset to check.
* @return 1 if the entire rrset has to be removed. 0 if not.
* It removes RRs if they have private addresses, and log that.
*/
static int priv_svcb_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
struct rrset_parse* rrset)
{
struct rr_parse* rr, *prev = NULL;
struct sockaddr_storage addr;
socklen_t addrlen = (socklen_t)sizeof(addr);
for(rr = rrset->rr_first; rr; rr = rr->next) {
if(svcb_rr_contains_priv_addr(priv, pkt, rr, &addr,
&addrlen)) {
if(msgparse_rrset_remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, rr, &addr, addrlen))
return 1;
continue;
}
prev = rr;
}
return 0;
}
int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
struct rrset_parse* rrset)
{
@@ -268,7 +430,11 @@ int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
}
prev = rr;
}
}
} else if(rrset->type == LDNS_RR_TYPE_SVCB ||
rrset->type == LDNS_RR_TYPE_HTTPS) {
if(priv_svcb_rrset_bad(priv, pkt, rrset))
return 1;
}
}
return 0;
}
+236 -13
View File
@@ -283,7 +283,19 @@ synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias,
sizeof(uint32_t)+sizeof(uint16_t)+aliaslen);
if(!cn->rr_first->ttl_data)
return NULL;
sldns_write_uint32(cn->rr_first->ttl_data, 0); /* TTL = 0 */
memmove(cn->rr_first->ttl_data, rrset->rr_first->ttl_data,
sizeof(uint32_t)); /* RFC6672: synth CNAME TTL == DNAME TTL */
/* Apply cache TTL policy so DNAME and synthesized CNAME stay equal
* and respect cache-min-ttl/cache-max-ttl (same as rdata_copy path). */
if(!SERVE_ORIGINAL_TTL) {
uint32_t ttl = sldns_read_uint32(cn->rr_first->ttl_data);
time_t ttl_t = (time_t)ttl;
if(ttl_t < MIN_TTL) ttl_t = MIN_TTL;
if(ttl_t > MAX_TTL) ttl_t = MAX_TTL;
ttl = (uint32_t)ttl_t;
sldns_write_uint32(cn->rr_first->ttl_data, ttl);
sldns_write_uint32(rrset->rr_first->ttl_data, ttl);
}
sldns_write_uint16(cn->rr_first->ttl_data+4, aliaslen);
memmove(cn->rr_first->ttl_data+6, alias, aliaslen);
cn->rr_first->size = sizeof(uint16_t)+aliaslen;
@@ -366,6 +378,84 @@ type_allowed_in_additional_section(uint16_t tp)
return 0;
}
/** Shorten RRset */
static void
shorten_rrset(sldns_buffer* pkt, struct rrset_parse* rrset, int count)
{
/* The too large NS RRset is shortened. This is so that too large
* content does not overwhelm the cache. It may make the rrset
* bogus if it was signed, and then the domain is not resolved any
* more, that is okay, the NS RRset was too large. During a referral
* it can be shortened and then the first part of the list could
* be used to resolve. The scrub continues to disallow glue for the
* removed nameserver RRs and removes that too. Because the glue
* is not marked as okay, since the RRs have been removed here. */
int i;
struct rr_parse* rr = rrset->rr_first, *prev = NULL;
if(!rr)
return;
for(i=0; i<count; i++) {
prev = rr;
rr = rr->next;
if(!rr)
return; /* The RRset is already short. */
}
if(verbosity >= VERB_QUERY
&& rrset->dname_len <= LDNS_MAX_DOMAINLEN) {
uint8_t buf[LDNS_MAX_DOMAINLEN+1];
dname_pkt_copy(pkt, buf, rrset->dname);
log_nametypeclass(VERB_QUERY, "normalize: shorten RRset:", buf,
rrset->type, ntohs(rrset->rrset_class));
}
/* remove further rrs */
rrset->rr_last = prev;
rrset->rr_count = count;
while(rr) {
rrset->size -= rr->size;
rr = rr->next;
}
if(rrset->rr_last)
rrset->rr_last->next = NULL;
else rrset->rr_first = NULL;
}
/** Shorten RRSIGs list */
static void
shorten_rrsig(sldns_buffer* pkt, struct rrset_parse* rrset, int count)
{
/* The too large list of RRSIGs on the RRset is shortened.
* This is so that too large content does not overwhelm the cache.
* The validator does not validate more than a max number of
* RRSIGs as well. */
int i;
struct rr_parse* rr = rrset->rrsig_first, *prev = NULL;
if(!rr)
return;
for(i=0; i<count; i++) {
prev = rr;
rr = rr->next;
if(!rr)
return; /* The RRSIG list is already short. */
}
if(verbosity >= VERB_QUERY
&& rrset->dname_len <= LDNS_MAX_DOMAINLEN) {
uint8_t buf[LDNS_MAX_DOMAINLEN+1];
dname_pkt_copy(pkt, buf, rrset->dname);
log_nametypeclass(VERB_QUERY, "normalize: shorten RRSIGs:",
buf, rrset->type, ntohs(rrset->rrset_class));
}
/* remove further rrsigs */
rrset->rrsig_last = prev;
rrset->rrsig_count = count;
while(rr) {
rrset->size -= rr->size;
rr = rr->next;
}
if(rrset->rrsig_last)
rrset->rrsig_last->next = NULL;
else rrset->rrsig_first = NULL;
}
/**
* This routine normalizes a response. This includes removing "irrelevant"
* records from the answer and additional sections and (re)synthesizing
@@ -376,19 +466,22 @@ type_allowed_in_additional_section(uint16_t tp)
* @param qinfo: original query.
* @param region: where to allocate synthesized CNAMEs.
* @param env: module env with config options.
* @param zonename: name of server zone.
* @return 0 on error.
*/
static int
scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
struct query_info* qinfo, struct regional* region,
struct module_env* env)
struct module_env* env, uint8_t* zonename)
{
uint8_t* sname = qinfo->qname;
size_t snamelen = qinfo->qname_len;
struct rrset_parse* rrset, *prev, *nsset=NULL;
int cname_length = 0; /* number of CNAMEs, or DNAMEs */
if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR &&
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN)
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN &&
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_YXDOMAIN)
return 1;
/* For the ANSWER section, remove all "irrelevant" records and add
@@ -400,8 +493,21 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
prev = NULL;
rrset = msg->rrset_first;
while(rrset && rrset->section == LDNS_SECTION_ANSWER) {
if(rrset->type == LDNS_RR_TYPE_DNAME &&
pkt_strict_sub(pkt, sname, rrset->dname)) {
if((int)rrset->rrsig_count > env->cfg->iter_scrub_rrsig)
shorten_rrsig(pkt, rrset, env->cfg->iter_scrub_rrsig);
if(cname_length > env->cfg->iter_scrub_cname) {
/* Too many CNAMEs, or DNAMEs, from the authority
* server, scrub down the length to something
* shorter. This deletes everything after the limit
* is reached. The iterator is going to look up
* the content one by one anyway. */
remove_rrset("normalize: removing because too many cnames:",
pkt, msg, prev, &rrset);
continue;
}
if(rrset->type == LDNS_RR_TYPE_DNAME &&
pkt_strict_sub(pkt, sname, rrset->dname) &&
pkt_sub(pkt, rrset->dname, zonename)) {
/* check if next rrset is correct CNAME. else,
* synthesize a CNAME */
struct rrset_parse* nx = rrset->rrset_all_next;
@@ -417,8 +523,14 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
&aliaslen, pkt)) {
verbose(VERB_ALGO, "synthesized CNAME "
"too long");
if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_YXDOMAIN) {
prev = rrset;
rrset = rrset->rrset_all_next;
continue;
}
return 0;
}
cname_length++;
if(nx && nx->type == LDNS_RR_TYPE_CNAME &&
dname_pkt_compare(pkt, sname, nx->dname) == 0) {
/* check next cname */
@@ -441,8 +553,6 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
log_err("out of memory synthesizing CNAME");
return 0;
}
/* FIXME: resolve the conflict between synthesized
* CNAME ttls and the cache. */
rrset = nx;
continue;
@@ -459,11 +569,13 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
if(rrset->type == LDNS_RR_TYPE_CNAME) {
struct rrset_parse* nx = rrset->rrset_all_next;
uint8_t* oldsname = sname;
cname_length++;
/* see if the next one is a DNAME, if so, swap them */
if(nx && nx->section == LDNS_SECTION_ANSWER &&
nx->type == LDNS_RR_TYPE_DNAME &&
nx->rr_count == 1 &&
pkt_strict_sub(pkt, sname, nx->dname)) {
pkt_strict_sub(pkt, sname, nx->dname) &&
pkt_sub(pkt, nx->dname, zonename)) {
/* there is a DNAME after this CNAME, it
* is in the ANSWER section, and the DNAME
* applies to the name we cover */
@@ -506,6 +618,10 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
LDNS_SECTION_ANSWER &&
dname_pkt_compare(pkt, oldsname,
rrset->dname) == 0) {
if(rrset->type == LDNS_RR_TYPE_NS &&
rrset->rr_count > env->cfg->iter_scrub_ns) {
shorten_rrset(pkt, rrset, env->cfg->iter_scrub_ns);
}
prev = rrset;
rrset = rrset->rrset_all_next;
}
@@ -521,6 +637,11 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
continue;
}
if(rrset->type == LDNS_RR_TYPE_NS &&
rrset->rr_count > env->cfg->iter_scrub_ns) {
shorten_rrset(pkt, rrset, env->cfg->iter_scrub_ns);
}
/* Mark the additional names from relevant rrset as OK. */
/* only for RRsets that match the query name, other ones
* will be removed by sanitize, so no additional for them */
@@ -549,6 +670,8 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
"RRset:", pkt, msg, prev, &rrset);
continue;
}
if((int)rrset->rrsig_count > env->cfg->iter_scrub_rrsig)
shorten_rrsig(pkt, rrset, env->cfg->iter_scrub_rrsig);
/* only one NS set allowed in authority section */
if(rrset->type==LDNS_RR_TYPE_NS) {
/* NS set must be pertinent to the query */
@@ -570,6 +693,45 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
"RRset:", pkt, msg, prev, &rrset);
continue;
}
/* If the NS set is a promiscuous NS set, scrub that
* to remove potential for poisonous contents that
* affects other names in the same zone. Remove
* promiscuous NS sets in positive answers, that
* thus have records in the answer section. Nodata
* and nxdomain promiscuous NS sets have been removed
* already. Since the NS rrset is scrubbed, its
* address records are also not marked to be allowed
* and are removed later. */
if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR &&
msg->an_rrsets != 0 &&
env->cfg->iter_scrub_promiscuous) {
remove_rrset("normalize: removing promiscuous "
"RRset:", pkt, msg, prev, &rrset);
continue;
}
/* Also delete promiscuous NS for other RCODEs */
if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR
&& env->cfg->iter_scrub_promiscuous) {
remove_rrset("normalize: removing promiscuous "
"RRset:", pkt, msg, prev, &rrset);
continue;
}
/* Also delete promiscuous NS for NOERROR with nodata
* for authoritative answers, not for delegations.
* NOERROR with an_rrsets!=0 already handled.
* Also NOERROR and soa_in_auth already handled.
* NOERROR with an_rrsets==0, and not a referral.
* referral is (NS not the zonename, noSOA).
*/
if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR
&& msg->an_rrsets == 0
&& !(dname_pkt_compare(pkt, rrset->dname,
zonename) != 0 && !soa_in_auth(msg))
&& env->cfg->iter_scrub_promiscuous) {
remove_rrset("normalize: removing promiscuous "
"RRset:", pkt, msg, prev, &rrset);
continue;
}
if(nsset == NULL) {
nsset = rrset;
} else {
@@ -577,6 +739,25 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
"RRset:", pkt, msg, prev, &rrset);
continue;
}
if(rrset->rr_count > env->cfg->iter_scrub_ns) {
/* If this is not a referral, and the NS RRset
* is signed, then remove it entirely, so
* that when it becomes bogus it does not
* make the message that is otherwise fine
* into a bogus message. */
if(!(msg->an_rrsets == 0 &&
FLAGS_GET_RCODE(msg->flags) ==
LDNS_RCODE_NOERROR &&
!soa_in_auth(msg) &&
!(msg->flags & BIT_AA)) &&
rrset->rrsig_count != 0) {
remove_rrset("normalize: removing too large NS "
"RRset:", pkt, msg, prev, &rrset);
continue;
} else {
shorten_rrset(pkt, rrset, env->cfg->iter_scrub_ns);
}
}
}
/* if this is type DS and we query for type DS we just got
* a referral answer for our type DS query, fix packet */
@@ -596,7 +777,13 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
rrset->rrset_all_next = NULL;
return 1;
}
mark_additional_rrset(pkt, msg, rrset);
/* Only mark glue as allowed for type NS in the authority
* section. Other RR types do not get glue for them, it
* is allowed from the answer section, but not authority
* so that a message can not have address records cached
* as a side effect to the query. */
if(rrset->type==LDNS_RR_TYPE_NS)
mark_additional_rrset(pkt, msg, rrset);
prev = rrset;
rrset = rrset->rrset_all_next;
}
@@ -633,6 +820,8 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
"RRset:", pkt, msg, prev, &rrset);
continue;
}
if((int)rrset->rrsig_count > env->cfg->iter_scrub_rrsig)
shorten_rrsig(pkt, rrset, env->cfg->iter_scrub_rrsig);
prev = rrset;
rrset = rrset->rrset_all_next;
}
@@ -788,6 +977,7 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
{
int del_addi = 0; /* if additional-holding rrsets are deleted, we
do not trust the normalized additional-A-AAAA any more */
uint8_t* ns_rrset_dname = NULL;
int added_rrlen_ede = 0;
struct rrset_parse* rrset, *prev;
prev = NULL;
@@ -842,8 +1032,10 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
}
/* remove private addresses */
if( (rrset->type == LDNS_RR_TYPE_A ||
rrset->type == LDNS_RR_TYPE_AAAA)) {
if(rrset->type == LDNS_RR_TYPE_A ||
rrset->type == LDNS_RR_TYPE_AAAA ||
rrset->type == LDNS_RR_TYPE_SVCB ||
rrset->type == LDNS_RR_TYPE_HTTPS) {
/* do not set servfail since this leads to too
* many drops of other people using rfc1918 space */
@@ -893,6 +1085,16 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
continue;
}
}
if(rrset->type == LDNS_RR_TYPE_NS &&
(rrset->section == LDNS_SECTION_AUTHORITY ||
rrset->section == LDNS_SECTION_ANSWER)) {
/* If the type is NS, and we're in the
* answer or authority section, then
* store the dname so we can check
* against the glue records
* further down */
ns_rrset_dname = rrset->dname;
}
if(del_addi && rrset->section == LDNS_SECTION_ADDITIONAL) {
remove_rrset("sanitize: removing potential "
"poison reference RRset:", pkt, msg, prev, &rrset);
@@ -905,6 +1107,26 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
"RRset:", pkt, msg, prev, &rrset);
continue;
}
if(env->cfg->harden_unverified_glue && ns_rrset_dname &&
rrset->section == LDNS_SECTION_ADDITIONAL &&
(rrset->type == LDNS_RR_TYPE_A || rrset->type == LDNS_RR_TYPE_AAAA) &&
!pkt_strict_sub(pkt, rrset->dname, ns_rrset_dname)) {
/* We're in the additional section, looking
* at an A/AAAA rrset, have a previous
* delegation point and we notice that
* the glue records are NOT for strict
* subdomains of the delegation. So set a
* flag, recompute the hash for the rrset
* and write the A/AAAA record to cache.
* It'll be retrieved if we can't separately
* resolve the glue */
rrset->flags = PACKED_RRSET_UNVERIFIED_GLUE;
rrset->hash = pkt_hash_rrset(pkt, rrset->dname, rrset->type, rrset->rrset_class, rrset->flags);
store_rrset(pkt, msg, env, rrset);
remove_rrset("sanitize: storing potential "
"unverified glue reference RRset:", pkt, msg, prev, &rrset);
continue;
}
prev = rrset;
rrset = rrset->rrset_all_next;
}
@@ -930,7 +1152,8 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
/* this is not required for basic operation but is a forgery
* resistance (security) feature */
if((FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR ||
FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN) &&
FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN ||
FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_YXDOMAIN) &&
msg->qdcount == 0)
return 0;
@@ -944,7 +1167,7 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
}
/* normalize the response, this cleans up the additional. */
if(!scrub_normalize(pkt, msg, qinfo, region, env))
if(!scrub_normalize(pkt, msg, qinfo, region, env, zonename))
return 0;
/* delete all out-of-zone information */
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate))
+243 -63
View File
@@ -77,41 +77,73 @@
static const char DEFAULT_NAT64_PREFIX[] = "64:ff9b::/96";
/** fillup fetch policy array */
static void
fetch_fill(struct iter_env* ie, const char* str)
static int
fetch_fill(int* target_fetch_policy, int max_dependency_depth, const char* str)
{
char* s = (char*)str, *e;
int i;
for(i=0; i<ie->max_dependency_depth+1; i++) {
ie->target_fetch_policy[i] = strtol(s, &e, 10);
if(s == e)
fatal_exit("cannot parse fetch policy number %s", s);
for(i=0; i<max_dependency_depth+1; i++) {
target_fetch_policy[i] = strtol(s, &e, 10);
if(s == e) {
log_err("cannot parse fetch policy number %s", s);
return 0;
}
s = e;
}
return 1;
}
/** Read config string that represents the target fetch policy */
static int
read_fetch_policy(struct iter_env* ie, const char* str)
int
read_fetch_policy(int** target_fetch_policy, int* max_dependency_depth,
const char* str)
{
int count = cfg_count_numbers(str);
if(count < 1) {
log_err("Cannot parse target fetch policy: \"%s\"", str);
return 0;
}
ie->max_dependency_depth = count - 1;
ie->target_fetch_policy = (int*)calloc(
(size_t)ie->max_dependency_depth+1, sizeof(int));
if(!ie->target_fetch_policy) {
*max_dependency_depth = count - 1;
*target_fetch_policy = (int*)calloc(
(size_t)(*max_dependency_depth)+1, sizeof(int));
if(!*target_fetch_policy) {
log_err("alloc fetch policy: out of memory");
return 0;
}
fetch_fill(ie, str);
if(!fetch_fill(*target_fetch_policy, *max_dependency_depth, str))
return 0;
return 1;
}
/** apply config caps whitelist items to name tree */
static int
struct rbtree_type*
caps_white_create(void)
{
struct rbtree_type* caps_white = rbtree_create(name_tree_compare);
if(!caps_white)
log_err("out of memory");
return caps_white;
}
/** delete caps_whitelist element */
static void
caps_free(struct rbnode_type* n, void* ATTR_UNUSED(d))
{
if(n) {
free(((struct name_tree_node*)n)->name);
free(n);
}
}
void
caps_white_delete(struct rbtree_type* caps_white)
{
if(!caps_white)
return;
traverse_postorder(caps_white, caps_free, NULL);
free(caps_white);
}
int
caps_white_apply_cfg(rbtree_type* ntree, struct config_file* cfg)
{
struct config_strlist* p;
@@ -145,12 +177,41 @@ caps_white_apply_cfg(rbtree_type* ntree, struct config_file* cfg)
}
int
iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
nat64_apply_cfg(struct iter_nat64* nat64, struct config_file* cfg)
{
const char *nat64_prefix;
nat64_prefix = cfg->nat64_prefix;
if(!nat64_prefix)
nat64_prefix = cfg->dns64_prefix;
if(!nat64_prefix)
nat64_prefix = DEFAULT_NAT64_PREFIX;
if(!netblockstrtoaddr(nat64_prefix, 0, &nat64->nat64_prefix_addr,
&nat64->nat64_prefix_addrlen, &nat64->nat64_prefix_net)) {
log_err("cannot parse nat64-prefix netblock: %s", nat64_prefix);
return 0;
}
if(!addr_is_ip6(&nat64->nat64_prefix_addr,
nat64->nat64_prefix_addrlen)) {
log_err("nat64-prefix is not IPv6: %s", cfg->nat64_prefix);
return 0;
}
if(!prefixnet_is_nat64(nat64->nat64_prefix_net)) {
log_err("nat64-prefix length it not 32, 40, 48, 56, 64 or 96: %s",
nat64_prefix);
return 0;
}
nat64->use_nat64 = cfg->do_nat64;
return 1;
}
int
iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
{
int i;
/* target fetch policy */
if(!read_fetch_policy(iter_env, cfg->target_fetch_policy))
if(!read_fetch_policy(&iter_env->target_fetch_policy,
&iter_env->max_dependency_depth, cfg->target_fetch_policy))
return 0;
for(i=0; i<iter_env->max_dependency_depth+1; i++)
verbose(VERB_QUERY, "target fetch policy for level %d is %d",
@@ -170,7 +231,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
}
if(cfg->caps_whitelist) {
if(!iter_env->caps_white)
iter_env->caps_white = rbtree_create(name_tree_compare);
iter_env->caps_white = caps_white_create();
if(!iter_env->caps_white || !caps_white_apply_cfg(
iter_env->caps_white, cfg)) {
log_err("Could not set capsforid whitelist");
@@ -179,38 +240,22 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
}
nat64_prefix = cfg->nat64_prefix;
if(!nat64_prefix)
nat64_prefix = cfg->dns64_prefix;
if(!nat64_prefix)
nat64_prefix = DEFAULT_NAT64_PREFIX;
if(!netblockstrtoaddr(nat64_prefix, 0, &iter_env->nat64_prefix_addr,
&iter_env->nat64_prefix_addrlen,
&iter_env->nat64_prefix_net)) {
log_err("cannot parse nat64-prefix netblock: %s", nat64_prefix);
return 0;
}
if(!addr_is_ip6(&iter_env->nat64_prefix_addr,
iter_env->nat64_prefix_addrlen)) {
log_err("nat64-prefix is not IPv6: %s", cfg->nat64_prefix);
return 0;
}
if(!prefixnet_is_nat64(iter_env->nat64_prefix_net)) {
log_err("nat64-prefix length it not 32, 40, 48, 56, 64 or 96: %s",
nat64_prefix);
if(!nat64_apply_cfg(&iter_env->nat64, cfg)) {
log_err("Could not setup nat64");
return 0;
}
iter_env->supports_ipv6 = cfg->do_ip6;
iter_env->supports_ipv4 = cfg->do_ip4;
iter_env->use_nat64 = cfg->do_nat64;
iter_env->outbound_msg_retry = cfg->outbound_msg_retry;
iter_env->max_sent_count = cfg->max_sent_count;
iter_env->max_query_restarts = cfg->max_query_restarts;
return 1;
}
/** filter out unsuitable targets
/** filter out unsuitable targets.
* Applies NAT64 if needed as well by replacing the IPv4 with the synthesized
* IPv6 address.
* @param iter_env: iterator environment with ipv6-support flag.
* @param env: module environment with infra cache.
* @param name: zone name
@@ -263,25 +308,61 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
if(a->bogus)
return -1; /* address of server is bogus */
if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) {
log_addr(VERB_ALGO, "skip addr on the donotquery list",
&a->addr, a->addrlen);
return -1; /* server is on the donotquery list */
if(iter_env->nat64.use_nat64 &&
addr_is_ip6(&a->addr, a->addrlen) &&
a->addrlen == iter_env->nat64.nat64_prefix_addrlen &&
addr_in_common(&a->addr, 128,
&iter_env->nat64.nat64_prefix_addr,
iter_env->nat64.nat64_prefix_net,
iter_env->nat64.nat64_prefix_addrlen) ==
iter_env->nat64.nat64_prefix_net) {
/* The NAT64 is enabled, and address is IPv6, it is
* in the NAT64 prefix. It is allowed.
* So that in an IPv6-only cluster without internet
* access, that makes the NAT64 translation continue
* to work. The NAT64 prefix is allowed. */
/* Otherwise, after a timeout, the already NAT64
* translated address would be treated differently,
* and that causes confusion. */
log_addr(VERB_ALGO, "the addr is on the donotquery "
"list, but allowed because it is NAT64",
&a->addr, a->addrlen);
} else {
log_addr(VERB_ALGO, "skip addr on the donotquery list",
&a->addr, a->addrlen);
return -1; /* server is on the donotquery list */
}
}
if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) {
return -1; /* there is no ip6 available */
}
if(!iter_env->supports_ipv4 && !iter_env->use_nat64 &&
if(!iter_env->supports_ipv4 && !iter_env->nat64.use_nat64 &&
!addr_is_ip6(&a->addr, a->addrlen)) {
return -1; /* there is no ip4 available */
}
if(iter_env->nat64.use_nat64 && !addr_is_ip6(&a->addr, a->addrlen)) {
struct sockaddr_storage real_addr;
socklen_t real_addrlen;
addr_to_nat64(&a->addr, &iter_env->nat64.nat64_prefix_addr,
iter_env->nat64.nat64_prefix_addrlen,
iter_env->nat64.nat64_prefix_net,
&real_addr, &real_addrlen);
log_name_addr(VERB_QUERY, "NAT64 apply: from: ",
name, &a->addr, a->addrlen);
log_name_addr(VERB_QUERY, "NAT64 apply: to: ",
name, &real_addr, real_addrlen);
a->addr = real_addr;
a->addrlen = real_addrlen;
}
/* check lameness - need zone , class info */
if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen,
name, namelen, qtype, &lame, &dnsseclame, &reclame,
&rtt, now)) {
log_addr(VERB_ALGO, "servselect", &a->addr, a->addrlen);
verbose(VERB_ALGO, " rtt=%d%s%s%s%s", rtt,
verbose(VERB_ALGO, " rtt=%d%s%s%s%s%s", rtt,
lame?" LAME":"",
dnsseclame?" DNSSEC_LAME":"",
a->dnsseclame?" ADDR_DNSSEC_LAME":"",
reclame?" REC_LAME":"",
a->lame?" ADDR_LAME":"");
if(lame)
@@ -692,10 +773,11 @@ dns_copy_msg(struct dns_msg* from, struct regional* region)
void
iter_dns_store(struct module_env* env, struct query_info* msgqinf,
struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
struct regional* region, uint16_t flags, time_t qstarttime)
struct regional* region, uint16_t flags, time_t qstarttime,
int is_valrec)
{
if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
pside, region, flags, qstarttime))
pside, region, flags, qstarttime, is_valrec))
log_err("out of memory: cannot store data in cache");
}
@@ -1284,8 +1366,17 @@ iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd,
uint16_t* c)
{
uint16_t c1 = *c, c2 = *c;
int r1 = hints_next_root(hints, &c1);
int r2 = forwards_next_root(fwd, &c2);
int r1, r2;
int nolock = 1;
/* prelock both forwards and hints for atomic read. */
lock_rw_rdlock(&fwd->lock);
lock_rw_rdlock(&hints->lock);
r1 = hints_next_root(hints, &c1, nolock);
r2 = forwards_next_root(fwd, &c2, nolock);
lock_rw_unlock(&fwd->lock);
lock_rw_unlock(&hints->lock);
if(!r1 && !r2) /* got none, end of list */
return 0;
else if(!r1) /* got one, return that */
@@ -1450,15 +1541,26 @@ int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp)
int
iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
uint8_t** retdpname, size_t* retdpnamelen)
uint8_t** retdpname, size_t* retdpnamelen, uint8_t* dpname_storage,
size_t dpname_storage_len)
{
struct iter_hints_stub *stub;
struct delegpt *dp;
int nolock = 1;
log_assert((retdpname && retdpnamelen
&& dpname_storage && dpname_storage_len > 0) ||
(retdpname == NULL && retdpnamelen == NULL
&& dpname_storage == NULL && dpname_storage_len == 0));
/* Check for stub. */
/* Lock both forwards and hints for atomic read. */
lock_rw_rdlock(&qstate->env->fwds->lock);
lock_rw_rdlock(&qstate->env->hints->lock);
stub = hints_lookup_stub(qstate->env->hints, qinf->qname,
qinf->qclass, NULL);
dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass);
qinf->qclass, NULL, nolock);
dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass,
nolock);
/* see if forward or stub is more pertinent */
if(stub && stub->dp && dp) {
@@ -1472,35 +1574,62 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
/* check stub */
if (stub != NULL && stub->dp != NULL) {
if(stub->dp->no_cache) {
char qname[255+1];
char dpname[255+1];
enum verbosity_value level = VERB_ALGO;
int stub_no_cache = stub->dp->no_cache;
lock_rw_unlock(&qstate->env->fwds->lock);
if(verbosity >= level && stub_no_cache) {
char qname[LDNS_MAX_DOMAINLEN];
char dpname[LDNS_MAX_DOMAINLEN];
dname_str(qinf->qname, qname);
dname_str(stub->dp->name, dpname);
verbose(VERB_ALGO, "stub for %s %s has no_cache", qname, dpname);
verbose(level, "stub for %s %s has no_cache", qname, dpname);
}
if(retdpname) {
*retdpname = stub->dp->name;
if(stub->dp->namelen > dpname_storage_len) {
verbose(VERB_ALGO, "no cache stub dpname too long");
lock_rw_unlock(&qstate->env->hints->lock);
*retdpname = NULL;
*retdpnamelen = 0;
return stub_no_cache;
}
memmove(dpname_storage, stub->dp->name,
stub->dp->namelen);
*retdpname = dpname_storage;
*retdpnamelen = stub->dp->namelen;
}
return (stub->dp->no_cache);
lock_rw_unlock(&qstate->env->hints->lock);
return stub_no_cache;
}
/* Check for forward. */
if (dp) {
if(dp->no_cache) {
char qname[255+1];
char dpname[255+1];
enum verbosity_value level = VERB_ALGO;
int dp_no_cache = dp->no_cache;
lock_rw_unlock(&qstate->env->hints->lock);
if(verbosity >= level && dp_no_cache) {
char qname[LDNS_MAX_DOMAINLEN];
char dpname[LDNS_MAX_DOMAINLEN];
dname_str(qinf->qname, qname);
dname_str(dp->name, dpname);
verbose(VERB_ALGO, "forward for %s %s has no_cache", qname, dpname);
verbose(level, "forward for %s %s has no_cache", qname, dpname);
}
if(retdpname) {
*retdpname = dp->name;
if(dp->namelen > dpname_storage_len) {
verbose(VERB_ALGO, "no cache dpname too long");
lock_rw_unlock(&qstate->env->fwds->lock);
*retdpname = NULL;
*retdpnamelen = 0;
return dp_no_cache;
}
memmove(dpname_storage, dp->name, dp->namelen);
*retdpname = dpname_storage;
*retdpnamelen = dp->namelen;
}
return (dp->no_cache);
lock_rw_unlock(&qstate->env->fwds->lock);
return dp_no_cache;
}
lock_rw_unlock(&qstate->env->fwds->lock);
lock_rw_unlock(&qstate->env->hints->lock);
if(retdpname) {
*retdpname = NULL;
*retdpnamelen = 0;
@@ -1523,3 +1652,54 @@ void iterator_set_ip46_support(struct module_stack* mods,
if(outnet->num_ip6 == 0)
ie->supports_ipv6 = 0;
}
void
limit_nsec_ttl(struct dns_msg* msg)
{
/* Limit NSEC and NSEC3 TTL in response, RFC9077 */
size_t i;
int found = 0;
time_t soa_ttl = 0;
/* Limit the NSEC and NSEC3 TTL values to the SOA TTL and SOA minimum
* TTL. That has already been applied to the SOA record ttl. */
for(i=0; i<msg->rep->rrset_count; i++) {
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA) {
struct packed_rrset_data* soadata = (struct packed_rrset_data*)s->entry.data;
found = 1;
soa_ttl = soadata->ttl;
break;
}
}
if(!found)
return;
for(i=0; i<msg->rep->rrset_count; i++) {
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC ||
ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) {
struct packed_rrset_data* data = (struct packed_rrset_data*)s->entry.data;
/* Limit the negative TTL. */
if(data->ttl > soa_ttl) {
if(verbosity >= VERB_ALGO) {
char buf[256];
snprintf(buf, sizeof(buf),
"limiting TTL %d of %s record to the SOA TTL of %d for",
(int)data->ttl, ((ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC)?"NSEC":"NSEC3"), (int)soa_ttl);
log_nametypeclass(VERB_ALGO, buf,
s->rk.dname, ntohs(s->rk.type),
ntohs(s->rk.rrset_class));
}
data->ttl = soa_ttl;
}
}
}
}
void
iter_make_minimal(struct reply_info* rep)
{
size_t rem = rep->ns_numrrsets + rep->ar_numrrsets;
rep->ns_numrrsets = 0;
rep->ar_numrrsets = 0;
rep->rrset_count -= rem;
}
+61 -2
View File
@@ -61,6 +61,7 @@ struct sock_list;
struct ub_packed_rrset_key;
struct module_stack;
struct outside_network;
struct iter_nat64;
/* max number of lookups in the cache for target nameserver names.
* This stops, for large delegations, N*N lookups in the cache. */
@@ -83,6 +84,7 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
/**
* Select a valid, nice target to send query to.
* Sorting and removing unsuitable targets is combined.
* Adds records to the infra cache if not already there.
*
* @param iter_env: iterator module global state, with ip6 enabled and
* do-not-query-addresses.
@@ -142,6 +144,7 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
* @param region: to copy modified (cache is better) rrs back to.
* @param flags: with BIT_CD for dns64 AAAA translated queries.
* @param qstarttime: time of query start.
* @param is_valrec: if the query is validation recursion and does not get
* return void, because we are not interested in alloc errors,
* the iterator and validator can operate on the results in their
* scratch space (the qstate.region) and are not dependent on the cache.
@@ -150,7 +153,8 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
*/
void iter_dns_store(struct module_env* env, struct query_info* qinf,
struct reply_info* rep, int is_referral, time_t leeway, int pside,
struct regional* region, uint16_t flags, time_t qstarttime);
struct regional* region, uint16_t flags, time_t qstarttime,
int is_valrec);
/**
* Select randomly with n/m probability.
@@ -407,10 +411,14 @@ int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp);
* Used for NXDOMAIN checks, above that it is an nxdomain from a
* different server and zone. You can pass NULL to not get it.
* @param retdpnamelen: returns the length of the dpname.
* @param dpname_storage: this is where the dpname buf is stored, if any.
* So that caller can manage the buffer.
* @param dpname_storage_len: size of dpname_storage buffer.
* @return true if no_cache is set in stub or fwd.
*/
int iter_stub_fwd_no_cache(struct module_qstate *qstate,
struct query_info *qinf, uint8_t** retdpname, size_t* retdpnamelen);
struct query_info *qinf, uint8_t** retdpname, size_t* retdpnamelen,
uint8_t* dpname_storage, size_t dpname_storage_len);
/**
* Set support for IP4 and IP6 depending on outgoing interfaces
@@ -424,4 +432,55 @@ int iter_stub_fwd_no_cache(struct module_qstate *qstate,
void iterator_set_ip46_support(struct module_stack* mods,
struct module_env* env, struct outside_network* outnet);
/**
* Read config string that represents the target fetch policy.
* @param target_fetch_policy: alloced on return.
* @param max_dependency_depth: set on return.
* @param str: the config string
* @return false on failure.
*/
int read_fetch_policy(int** target_fetch_policy, int* max_dependency_depth,
const char* str);
/**
* Create caps exempt data structure.
* @return NULL on failure.
*/
struct rbtree_type* caps_white_create(void);
/**
* Delete caps exempt data structure.
* @param caps_white: caps exempt tree.
*/
void caps_white_delete(struct rbtree_type* caps_white);
/**
* Apply config caps whitelist items to name tree
* @param ntree: caps exempt tree.
* @param cfg: config with options.
*/
int caps_white_apply_cfg(struct rbtree_type* ntree, struct config_file* cfg);
/**
* Apply config for nat64
* @param nat64: the nat64 state.
* @param cfg: config with options.
* @return false on failure.
*/
int nat64_apply_cfg(struct iter_nat64* nat64, struct config_file* cfg);
/**
* Limit NSEC and NSEC3 TTL in response, RFC9077
* @param msg: dns message, the SOA record ttl is used to restrict ttls
* of NSEC and NSEC3 RRsets. If no SOA record, nothing happens.
*/
void limit_nsec_ttl(struct dns_msg* msg);
/**
* Make the response minimal. Removed authority and additional section,
* that works when there is an answer in the answer section.
* @param rep: reply to modify.
*/
void iter_make_minimal(struct reply_info* rep);
#endif /* ITERATOR_ITER_UTILS_H */
+418 -208
View File
File diff suppressed because it is too large Load Diff
+22 -10
View File
@@ -46,8 +46,6 @@
#include "util/data/msgreply.h"
#include "util/module.h"
struct delegpt;
struct iter_hints;
struct iter_forwards;
struct iter_donotq;
struct iter_prep_list;
struct iter_priv;
@@ -55,6 +53,9 @@ struct rbtree_type;
/** max number of targets spawned for a query and its subqueries */
#define MAX_TARGET_COUNT 64
/** max number of upstream queries for a query and its subqueries, it is
* never reset. */
extern int MAX_GLOBAL_QUOTA;
/** max number of target lookups per qstate, per delegation point */
#define MAX_DP_TARGET_COUNT 16
/** max number of nxdomains allowed for target lookups for a query and
@@ -105,15 +106,9 @@ extern int BLACKLIST_PENALTY;
#define EMPTY_NODATA_RETRY_COUNT 2
/**
* Global state for the iterator.
* Iterator global state for nat64.
*/
struct iter_env {
/** A flag to indicate whether or not we have an IPv6 route */
int supports_ipv6;
/** A flag to indicate whether or not we have an IPv4 route */
int supports_ipv4;
struct iter_nat64 {
/** A flag to locally apply NAT64 to make IPv4 addrs into IPv6 */
int use_nat64;
@@ -125,6 +120,20 @@ struct iter_env {
/** CIDR mask length of NAT64 prefix */
int nat64_prefix_net;
};
/**
* Global state for the iterator.
*/
struct iter_env {
/** A flag to indicate whether or not we have an IPv6 route */
int supports_ipv6;
/** A flag to indicate whether or not we have an IPv4 route */
int supports_ipv4;
/** State for nat64 */
struct iter_nat64 nat64;
/** A set of inetaddrs that should never be queried. */
struct iter_donotq* donotq;
@@ -248,6 +257,9 @@ enum target_count_variables {
TARGET_COUNT_QUERIES,
/** Number of nxdomain responses encountered. */
TARGET_COUNT_NX,
/** Global quota on number of queries to upstream servers per
* client request, that is never reset. */
TARGET_COUNT_GLOBAL_QUOTA,
/** This should stay last here, it is used for the allocation */
TARGET_COUNT_MAX,
+12 -2
View File
@@ -53,6 +53,8 @@
#include "util/storage/slabhash.h"
#include "util/edns.h"
#include "sldns/sbuffer.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_hints.h"
int
context_finalize(struct ub_ctx* ctx)
@@ -73,7 +75,9 @@ context_finalize(struct ub_ctx* ctx)
ctx->pipe_pid = getpid();
cfg_apply_local_port_policy(cfg, 65536);
config_apply(cfg);
if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env))
if(!modstack_call_startup(&ctx->mods, cfg->module_conf, ctx->env))
return UB_INITFAIL;
if(!modstack_call_init(&ctx->mods, cfg->module_conf, ctx->env))
return UB_INITFAIL;
listen_setup_locks();
log_edns_known_options(VERB_ALGO, ctx->env);
@@ -85,6 +89,12 @@ context_finalize(struct ub_ctx* ctx)
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz,
ctx->env, &ctx->mods))
return UB_INITFAIL;
if(!(ctx->env->fwds = forwards_create()) ||
!forwards_apply_cfg(ctx->env->fwds, cfg))
return UB_INITFAIL;
if(!(ctx->env->hints = hints_create()) ||
!hints_apply_cfg(ctx->env->hints, cfg))
return UB_INITFAIL;
if(!edns_strings_apply_cfg(ctx->env->edns_strings, cfg))
return UB_INITFAIL;
if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,
@@ -385,7 +395,7 @@ context_serialize_cancel(struct ctx_query* q, uint32_t* len)
/* format of cancel:
* o uint32 cmd
* o uint32 async-id */
uint8_t* p = (uint8_t*)reallocarray(NULL, sizeof(uint32_t), 2);
uint8_t* p = (uint8_t*)reallocarray(NULL, 2, sizeof(uint32_t));
if(!p) return NULL;
*len = 2*sizeof(uint32_t);
sldns_write_uint32(p, UB_LIBCMD_CANCEL);
+19 -5
View File
@@ -66,6 +66,8 @@
#include "services/authzone.h"
#include "services/listen_dnsport.h"
#include "sldns/sbuffer.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_hints.h"
#ifdef HAVE_PTHREAD
#include <signal.h>
#endif
@@ -171,6 +173,7 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
ctx->env->worker = NULL;
ctx->env->need_to_validate = 0;
modstack_init(&ctx->mods);
ctx->env->modstack = &ctx->mods;
rbtree_init(&ctx->queries, &context_query_cmp);
return ctx;
}
@@ -185,7 +188,9 @@ ub_ctx_create(void)
int e = errno;
ub_randfree(ctx->seed_rnd);
config_delete(ctx->env->cfg);
modstack_desetup(&ctx->mods, ctx->env);
modstack_call_deinit(&ctx->mods, ctx->env);
modstack_call_destartup(&ctx->mods, ctx->env);
modstack_free(&ctx->mods);
listen_desetup_locks();
edns_known_options_delete(ctx->env);
edns_strings_delete(ctx->env->edns_strings);
@@ -199,7 +204,9 @@ ub_ctx_create(void)
tube_delete(ctx->qq_pipe);
ub_randfree(ctx->seed_rnd);
config_delete(ctx->env->cfg);
modstack_desetup(&ctx->mods, ctx->env);
modstack_call_deinit(&ctx->mods, ctx->env);
modstack_call_destartup(&ctx->mods, ctx->env);
modstack_free(&ctx->mods);
listen_desetup_locks();
edns_known_options_delete(ctx->env);
edns_strings_delete(ctx->env->edns_strings);
@@ -357,7 +364,9 @@ ub_ctx_delete(struct ub_ctx* ctx)
}
libworker_delete_event(ctx->event_worker);
modstack_desetup(&ctx->mods, ctx->env);
modstack_call_deinit(&ctx->mods, ctx->env);
modstack_call_destartup(&ctx->mods, ctx->env);
modstack_free(&ctx->mods);
a = ctx->alloc_list;
while(a) {
na = a->super;
@@ -379,6 +388,8 @@ ub_ctx_delete(struct ub_ctx* ctx)
config_delete(ctx->env->cfg);
edns_known_options_delete(ctx->env);
edns_strings_delete(ctx->env->edns_strings);
forwards_delete(ctx->env->fwds);
hints_delete(ctx->env->hints);
auth_zones_delete(ctx->env->auth_zones);
free(ctx->env);
}
@@ -976,7 +987,8 @@ ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
if(!addr) {
/* disable fwd mode - the root stub should be first. */
if(ctx->env->cfg->forwards &&
strcmp(ctx->env->cfg->forwards->name, ".") == 0) {
(ctx->env->cfg->forwards->name &&
strcmp(ctx->env->cfg->forwards->name, ".") == 0)) {
s = ctx->env->cfg->forwards;
ctx->env->cfg->forwards = s->next;
s->next = NULL;
@@ -996,7 +1008,8 @@ ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
/* it parses, add root stub in front of list */
lock_basic_lock(&ctx->cfglock);
if(!ctx->env->cfg->forwards ||
strcmp(ctx->env->cfg->forwards->name, ".") != 0) {
(ctx->env->cfg->forwards->name &&
strcmp(ctx->env->cfg->forwards->name, ".") != 0)) {
s = calloc(1, sizeof(*s));
if(!s) {
lock_basic_unlock(&ctx->cfglock);
@@ -1014,6 +1027,7 @@ ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
ctx->env->cfg->forwards = s;
} else {
log_assert(ctx->env->cfg->forwards);
log_assert(ctx->env->cfg->forwards->name);
s = ctx->env->cfg->forwards;
}
dupl = strdup(addr);
+44 -25
View File
@@ -70,8 +70,6 @@
#include "util/data/msgreply.h"
#include "util/data/msgencode.h"
#include "util/tube.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_hints.h"
#include "sldns/sbuffer.h"
#include "sldns/str2wire.h"
#ifdef USE_DNSTAP
@@ -100,8 +98,6 @@ libworker_delete_env(struct libworker* w)
!w->is_bg || w->is_bg_thread);
sldns_buffer_free(w->env->scratch_buffer);
regional_destroy(w->env->scratch);
forwards_delete(w->env->fwds);
hints_delete(w->env->hints);
ub_randfree(w->env->rnd);
free(w->env);
}
@@ -159,30 +155,19 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
}
w->env->scratch = regional_create_custom(cfg->msg_buffer_size);
w->env->scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size);
w->env->fwds = forwards_create();
if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) {
forwards_delete(w->env->fwds);
w->env->fwds = NULL;
}
w->env->hints = hints_create();
if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) {
hints_delete(w->env->hints);
w->env->hints = NULL;
}
#ifdef HAVE_SSL
w->sslctx = connect_sslctx_create(NULL, NULL,
cfg->tls_cert_bundle, cfg->tls_win_cert);
if(!w->sslctx) {
/* to make the setup fail after unlock */
hints_delete(w->env->hints);
w->env->hints = NULL;
sldns_buffer_free(w->env->scratch_buffer);
w->env->scratch_buffer = NULL;
}
#endif
if(!w->is_bg || w->is_bg_thread) {
lock_basic_unlock(&ctx->cfglock);
}
if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds ||
!w->env->hints) {
if(!w->env->scratch || !w->env->scratch_buffer) {
libworker_delete(w);
return NULL;
}
@@ -307,6 +292,7 @@ libworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len)
log_err("unknown command for bg worker %d",
(int)context_serial_getcmd(msg, len));
/* and fall through to quit */
ATTR_FALLTHROUGH
/* fallthrough */
case UB_LIBCMD_QUIT:
free(msg);
@@ -437,7 +423,7 @@ int libworker_bg(struct ub_ctx* ctx)
static int
fill_canon(struct ub_result* res, uint8_t* s)
{
char buf[255+2];
char buf[LDNS_MAX_DOMAINLEN];
dname_str(s, buf);
res->canonname = strdup(buf);
return res->canonname != 0;
@@ -644,8 +630,9 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
free(qinfo.qname);
return UB_NOERROR;
}
if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones,
w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) {
if(ctx->env->auth_zones && auth_zones_downstream_answer(
ctx->env->auth_zones, w->env, &qinfo, &edns, NULL,
w->back->udp_buff, w->env->scratch)) {
regional_free_all(w->env->scratch);
libworker_fillup_fg(q, LDNS_RCODE_NOERROR,
w->back->udp_buff, sec_status_insecure, NULL, 0);
@@ -723,8 +710,9 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
w->back->udp_buff, sec_status_insecure, NULL, 0);
return UB_NOERROR;
}
if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones,
w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) {
if(ctx->env->auth_zones && auth_zones_downstream_answer(
ctx->env->auth_zones, w->env, &qinfo, &edns, NULL,
w->back->udp_buff, w->env->scratch)) {
regional_free_all(w->env->scratch);
free(qinfo.qname);
libworker_event_done_cb(q, LDNS_RCODE_NOERROR,
@@ -861,8 +849,9 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
free(qinfo.qname);
return;
}
if(w->ctx->env->auth_zones && auth_zones_answer(w->ctx->env->auth_zones,
w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) {
if(w->ctx->env->auth_zones && auth_zones_downstream_answer(
w->ctx->env->auth_zones, w->env, &qinfo, &edns, NULL,
w->back->udp_buff, w->env->scratch)) {
regional_free_all(w->env->scratch);
q->msg_security = sec_status_insecure;
add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL, 0);
@@ -1072,3 +1061,33 @@ void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
log_assert(0);
}
#endif
void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
void* ATTR_UNUSED(arg))
{
log_assert(0);
}
int fast_reload_client_callback(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply* ATTR_UNUSED(repinfo))
{
log_assert(0);
return 0;
}
#ifdef HAVE_NGTCP2
void doq_client_event_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
void* ATTR_UNUSED(arg))
{
log_assert(0);
}
#endif
#ifdef HAVE_NGTCP2
void doq_client_timer_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
void* ATTR_UNUSED(arg))
{
log_assert(0);
}
#endif
@@ -30,6 +30,7 @@ def dnssecParse(domain, rrType=RR_TYPE_A):
resolver = ub_ctx()
resolver.add_ta(". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5")
resolver.add_ta(". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D")
resolver.add_ta(". IN DS 38696 8 2 683D2D0ACB8C9B712A1948B27F741219298D0A450D612C483AF444A4C0FB2B16")
dnssecParse("nic.cz")
dnssecParse("nonexistent-domain-blablabla.cz")

Some files were not shown because too many files have changed in this diff Show More