Compare commits

...
Author SHA1 Message Date
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 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
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
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
217 changed files with 12554 additions and 1411 deletions
+9 -5
View File
@@ -31,12 +31,12 @@ jobs:
clang_analysis: "yes"
- name: OS X
os: macos-latest
install_expat: "yes"
install_expat: "no"
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"
install_expat: "no"
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"
@@ -193,8 +193,12 @@ jobs:
- uses: actions/checkout@v4
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`
@@ -237,9 +241,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.
+2
View File
@@ -13,6 +13,8 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: configure
run: ./configure --enable-debug
- name: make
+16 -7
View File
@@ -179,11 +179,11 @@ testcode/unitlruhash.c testcode/unitmain.c testcode/unitmsgparse.c \
testcode/unitneg.c testcode/unitregional.c testcode/unitslabhash.c \
testcode/unitverify.c testcode/readhex.c testcode/testpkts.c testcode/unitldns.c \
testcode/unitecs.c testcode/unitauth.c testcode/unitzonemd.c \
testcode/unittcpreuse.c testcode/unitdoq.c
testcode/unittcpreuse.c testcode/unitdoq.c testcode/unitinfra.c
UNITTEST_OBJ=unitanchor.lo unitdname.lo unitlruhash.lo unitmain.lo \
unitmsgparse.lo unitneg.lo unitregional.lo unitslabhash.lo unitverify.lo \
readhex.lo testpkts.lo unitldns.lo unitecs.lo unitauth.lo unitzonemd.lo \
unittcpreuse.lo unitdoq.lo
unittcpreuse.lo unitdoq.lo unitinfra.lo
UNITTEST_OBJ_LINK=$(UNITTEST_OBJ) worker_cb.lo $(COMMON_OBJ) $(SLDNS_OBJ) \
$(COMPAT_OBJ)
DAEMON_SRC=daemon/acl_list.c daemon/cachedump.c daemon/daemon.c \
@@ -509,10 +509,15 @@ util/configlexer.c: $(srcdir)/util/configlexer.lex util/configparser.h
fi
@if test ! -f $@; then echo "No $@ : need flex and bison to compile from source repository"; exit 1; fi
util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y
# Builds both util/configparser.c and util/configparser.h.
# To avoid double-building we split one target out.
util/configparser.c: $(srcdir)/util/configparser.y
@-if test ! -d util; then $(INSTALL) -d util; fi
$(YACC) -d -o util/configparser.c $(srcdir)/util/configparser.y
util/configparser.h: util/configparser.c
touch $@
clean:
rm -f *.o *.d *.lo *~ tags
rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup libunbound.la unbound.h
@@ -876,7 +881,7 @@ view.lo view.o: $(srcdir)/services/view.c config.h $(srcdir)/services/view.h $(s
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/respip/respip.h
rpz.lo rpz.o: $(srcdir)/services/rpz.c config.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
@@ -972,7 +977,7 @@ fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/
$(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h \
$(srcdir)/validator/val_neg.h $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h \
$(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound-event.h \
$(srcdir)/libunbound/worker.h
$(srcdir)/libunbound/worker.h $(srcdir)/daemon/remote.h
locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/sldns/sbuffer.h
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
@@ -1059,7 +1064,7 @@ tube.lo tube.o: $(srcdir)/util/tube.c config.h $(srcdir)/util/tube.h $(srcdir)/u
$(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/ub_event.h
ub_event.lo ub_event.o: $(srcdir)/util/ub_event.c config.h $(srcdir)/util/ub_event.h $(srcdir)/util/log.h \
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/util/tube.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
$(srcdir)/util/tube.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/daemon/remote.h
ub_event_pluggable.lo ub_event_pluggable.o: $(srcdir)/util/ub_event_pluggable.c config.h $(srcdir)/util/ub_event.h \
$(srcdir)/libunbound/unbound-event.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h \
@@ -1256,6 +1261,7 @@ unitzonemd.lo unitzonemd.o: $(srcdir)/testcode/unitzonemd.c config.h $(srcdir)/u
$(srcdir)/validator/val_anchor.h
unittcpreuse.lo unittcpreuse.o: $(srcdir)/testcode/unittcpreuse.c config.h $(srcdir)/services/outside_network.h \
$(srcdir)/util/random.h
unitinfra.lo unitinfra.o: $(srcdir)/testcode/unitinfra.c config.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/iterator/iterator.h
acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/locks.h \
$(srcdir)/util/log.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
@@ -1307,7 +1313,10 @@ remote.lo remote.o: $(srcdir)/daemon/remote.c config.h $(srcdir)/daemon/remote.h
$(srcdir)/validator/val_anchor.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/iterator/iter_delegpt.h \
$(srcdir)/services/outside_network.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/parseutil.h \
$(srcdir)/sldns/wire2str.h $(srcdir)/util/edns.h
$(srcdir)/sldns/wire2str.h $(srcdir)/util/edns.h \
$(srcdir)/util/locks.h $(srcdir)/util/ub_event.h \
$(srcdir)/util/tcp_conn_limit.h $(srcdir)/util/edns.h $(srcdir)/validator/val_neg.h \
$(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_donotq.h $(srcdir)/iterator/iter_priv.h
stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
$(srcdir)/libunbound/unbound.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+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
+4 -1
View File
@@ -47,6 +47,7 @@
#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"
@@ -341,6 +342,7 @@ calc_hash(struct query_info* qinfo, struct module_env* env, char* buf,
/* copy the hash info into the clear buffer */
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)) {
@@ -755,7 +757,8 @@ cachedb_intcache_store(struct module_qstate* qstate, int msg_expired)
}
(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
+203 -81
View File
@@ -52,19 +52,38 @@
#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 command_timeout; /* timeout for commands */
struct timeval connect_timeout; /* timeout for connect */
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 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;
};
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) {
@@ -78,21 +97,30 @@ 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);
}
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)
{
redisContext* ctx;
if(moddata->server_path && moddata->server_path[0]!=0) {
ctx = redisConnectUnixWithTimeout(moddata->server_path,
moddata->connect_timeout);
if(path && path[0]!=0) {
ctx = redisConnectUnixWithTimeout(path, connect_timeout);
} else {
ctx = redisConnectWithTimeout(moddata->server_host,
moddata->server_port, moddata->connect_timeout);
ctx = redisConnectWithTimeout(host, port, connect_timeout);
}
if(!ctx || ctx->err) {
const char *errstr = "out of memory";
@@ -101,13 +129,13 @@ redis_connect(const struct redis_moddata* moddata)
log_err("failed to connect to redis server: %s", errstr);
goto fail;
}
if(redisSetTimeout(ctx, moddata->command_timeout) != REDIS_OK) {
log_err("failed to set redis timeout");
if(redisSetTimeout(ctx, command_timeout) != REDIS_OK) {
log_err("failed to set redis timeout, %s", 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");
freeReplyObject(rep);
@@ -115,18 +143,25 @@ redis_connect(const struct redis_moddata* moddata)
}
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);
logical_db);
freeReplyObject(rep);
goto fail;
}
freeReplyObject(rep);
}
verbose(VERB_OPS, "Connection to Redis established");
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 established (%s%s)",
path&&path[0]!=0?path:host,
path&&path[0]!=0?"":port_str);
}
return ctx;
fail:
@@ -135,6 +170,14 @@ fail:
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)
{
@@ -149,57 +192,98 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
goto fail;
}
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);
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->command_timeout.tv_sec = env->cfg->redis_timeout / 1000;
moddata->command_timeout.tv_usec =
(env->cfg->redis_timeout % 1000) * 1000;
moddata->connect_timeout.tv_sec = env->cfg->redis_timeout / 1000;
moddata->connect_timeout.tv_usec =
(env->cfg->redis_timeout % 1000) * 1000;
if(env->cfg->redis_command_timeout != 0) {
moddata->command_timeout.tv_sec =
env->cfg->redis_command_timeout / 1000;
moddata->command_timeout.tv_usec =
(env->cfg->redis_command_timeout % 1000) * 1000;
}
if(env->cfg->redis_connect_timeout != 0) {
moddata->connect_timeout.tv_sec =
env->cfg->redis_connect_timeout / 1000;
moddata->connect_timeout.tv_usec =
(env->cfg->redis_connect_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);
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);
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);
@@ -207,15 +291,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.2)");
return 1;
fail:
moddata_clean(&moddata);
return 0;
@@ -246,9 +333,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;
@@ -259,17 +346,38 @@ 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);
} 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);
}
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);
@@ -279,7 +387,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;
}
@@ -309,7 +417,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) {
@@ -346,11 +454,16 @@ 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];
@@ -358,14 +471,22 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
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);
}
@@ -374,11 +495,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);
}
-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. */
+6
View File
@@ -378,6 +378,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
@@ -663,6 +666,9 @@
/* 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
Vendored
+110 -15
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.71 for unbound 1.22.0.
# Generated by GNU Autoconf 2.71 for unbound 1.23.1.
#
# Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>.
#
@@ -622,8 +622,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='unbound'
PACKAGE_TARNAME='unbound'
PACKAGE_VERSION='1.22.0'
PACKAGE_STRING='unbound 1.22.0'
PACKAGE_VERSION='1.23.1'
PACKAGE_STRING='unbound 1.23.1'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
PACKAGE_URL=''
@@ -712,6 +712,7 @@ SSLLIB
HAVE_SSL
PC_CRYPTO_DEPENDENCY
CONFIG_DATE
SOURCE_DATE_EPOCH
GCC_DOCKER_LINTFLAGS
NETBSD_LINTFLAGS
PYUNBOUND_UNINSTALL
@@ -959,6 +960,7 @@ SYSTEMD_LIBS
SYSTEMD_DAEMON_CFLAGS
SYSTEMD_DAEMON_LIBS
PYTHON_VERSION
SOURCE_DATE_EPOCH
PROTOBUFC_CFLAGS
PROTOBUFC_LIBS'
@@ -1509,7 +1511,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures unbound 1.22.0 to adapt to many kinds of systems.
\`configure' configures unbound 1.23.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1575,7 +1577,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of unbound 1.22.0:";;
short | recursive ) echo "Configuration of unbound 1.23.1:";;
esac
cat <<\_ACEOF
@@ -1752,6 +1754,10 @@ Some influential environment variables:
The installed Python version to use, for example '2.3'. This
string will be appended to the Python interpreter canonical
name.
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.
PROTOBUFC_CFLAGS
C compiler flags for PROTOBUFC, overriding pkg-config
PROTOBUFC_LIBS
@@ -1824,7 +1830,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
unbound configure 1.22.0
unbound configure 1.23.1
generated by GNU Autoconf 2.71
Copyright (C) 2021 Free Software Foundation, Inc.
@@ -2481,7 +2487,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by unbound $as_me 1.22.0, which was
It was created by unbound $as_me 1.23.1, which was
generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw
@@ -3243,13 +3249,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
UNBOUND_VERSION_MAJOR=1
UNBOUND_VERSION_MINOR=22
UNBOUND_VERSION_MINOR=23
UNBOUND_VERSION_MICRO=0
UNBOUND_VERSION_MICRO=1
LIBUNBOUND_CURRENT=9
LIBUNBOUND_REVISION=30
LIBUNBOUND_REVISION=32
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -3347,6 +3353,8 @@ LIBUNBOUND_AGE=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
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -16093,6 +16101,14 @@ then :
fi
ac_fn_c_check_header_compile "$LINENO" "stdatomic.h" "ac_cv_header_stdatomic_h" "$ac_includes_default
"
if test "x$ac_cv_header_stdatomic_h" = xyes
then :
printf "%s\n" "#define HAVE_STDATOMIC_H 1" >>confdefs.h
fi
# check for types.
# Using own tests for int64* because autoconf builtin only give 32bit.
@@ -19893,7 +19909,26 @@ if test "`uname`" = "Linux"; then
GCC_DOCKER_LINTFLAGS='-syntax'
fi
CONFIG_DATE=`date +%Y%m%d`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build time" >&5
printf %s "checking for build time... " >&6; }
ax_date_fmt="%Y%m%d"
if test x"$SOURCE_DATE_EPOCH" = x
then :
CONFIG_DATE=`date "+$ax_date_fmt"`
else $as_nop
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`
if test x"$ax_build_date" = x
then :
as_fn_error $? "malformed SOURCE_DATE_EPOCH" "$LINENO" 5
else $as_nop
CONFIG_DATE=$ax_build_date
fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CONFIG_DATE" >&5
printf "%s\n" "$CONFIG_DATE" >&6; }
# Checks for libraries.
@@ -23496,6 +23531,48 @@ if echo $host_os | grep darwin8 > /dev/null; then
printf "%s\n" "#define DARWIN_BROKEN_SETREUID 1" >>confdefs.h
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for atomic_store" >&5
printf %s "checking for atomic_store... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_includes_default
#ifdef HAVE_STDATOMIC_H
#include <stdatomic.h>
#endif
int
main (void)
{
int newvar = 5, var = 0;
atomic_store((_Atomic int*)&var, newvar);
newvar = 0;
/* condition to use the variables. */
if(var == newvar) return 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
printf "%s\n" "#define HAVE_LINK_ATOMIC_STORE 1" >>confdefs.h
else $as_nop
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
ac_fn_check_decl "$LINENO" "inet_pton" "ac_cv_have_decl_inet_pton" "
$ac_includes_default
#ifdef HAVE_NETINET_IN_H
@@ -24997,9 +25074,27 @@ printf "%s\n" "#define MAXSYSLOGMSGLEN 10240" >>confdefs.h
version=1.22.0
version=1.23.1
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build time" >&5
printf %s "checking for build time... " >&6; }
ax_date_fmt="%b %e, %Y"
if test x"$SOURCE_DATE_EPOCH" = x
then :
date=`date "+$ax_date_fmt"`
else $as_nop
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`
if test x"$ax_build_date" = x
then :
as_fn_error $? "malformed SOURCE_DATE_EPOCH" "$LINENO" 5
else $as_nop
date=$ax_build_date
fi
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $date" >&5
printf "%s\n" "$date" >&6; }
date=`date +'%b %e, %Y'`
ac_config_files="$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"
@@ -25509,7 +25604,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by unbound $as_me 1.22.0, which was
This file was extended by unbound $as_me 1.23.1, which was
generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -25577,7 +25672,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
unbound config.status 1.22.0
unbound config.status 1.23.1
configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
+30 -5
View File
@@ -2,6 +2,7 @@
# 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(ax_pkg_swig.m4)
@@ -10,15 +11,15 @@ sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[22])
m4_define([VERSION_MICRO],[0])
m4_define([VERSION_MINOR],[23])
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=30
LIBUNBOUND_REVISION=32
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -116,6 +117,8 @@ LIBUNBOUND_AGE=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
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -522,6 +525,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.
@@ -907,7 +911,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.
@@ -1814,6 +1819,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
@@ -2434,7 +2458,8 @@ char *unbound_stat_strdup_log(const char *s, const char* file, int line,
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])
+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
+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
+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 */
+2 -2
View File
@@ -692,7 +692,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;
}
@@ -836,7 +836,7 @@ 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;
+25 -17
View File
@@ -323,8 +323,7 @@ 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;
for(; port_list; port_list=port_list->next) {
@@ -717,16 +716,16 @@ daemon_fork(struct daemon* daemon)
#endif
log_assert(daemon);
if(!(daemon->views = views_create()))
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");
@@ -762,15 +761,15 @@ daemon_fork(struct daemon* daemon)
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);
@@ -886,14 +885,18 @@ daemon_cleanup(struct daemon* daemon)
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 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);
@@ -951,11 +954,16 @@ daemon_delete(struct daemon* daemon)
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);
SSL_CTX_free((SSL_CTX*)daemon->listen_dot_sslctx);
SSL_CTX_free((SSL_CTX*)daemon->listen_doh_sslctx);
SSL_CTX_free((SSL_CTX*)daemon->connect_dot_sslctx);
#endif
#ifdef HAVE_NGTCP2
SSL_CTX_free((SSL_CTX*)daemon->listen_quic_sslctx);
#endif
free(daemon);
/* lex cleanup */
+29 -6
View File
@@ -60,6 +60,8 @@ 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
@@ -97,8 +99,14 @@ 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;
/** num threads allocated */
int num;
/** num threads allocated in the previous config or 0 at first */
@@ -131,15 +139,11 @@ 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
struct shm_main_info* shm_info;
/** response-ip set with associated actions and tags. */
struct respip_set* respip_set;
/** some response-ip tags or actions are configured if true */
int use_response_ip;
/** some RPZ policies are configured */
@@ -154,6 +158,17 @@ struct daemon {
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;
};
/**
@@ -206,4 +221,12 @@ 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);
#endif /* DAEMON_H */
+4131 -31
View File
File diff suppressed because it is too large Load Diff
+167
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,137 @@ 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;
/** 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;
};
/**
* Create new remote control state for the daemon.
* @param cfg: config file with key file settings.
@@ -203,4 +336,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 */
+16 -16
View File
@@ -281,6 +281,12 @@ 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_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 +331,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();
@@ -451,9 +445,15 @@ 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_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;
@@ -461,9 +461,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 */
+62 -30
View File
@@ -463,6 +463,64 @@ detach(void)
#endif /* HAVE_DAEMON */
}
/* 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)
{
#ifdef HAVE_SSL
if(!(*ctx = listen_sslctx_create(
cfg->ssl_service_key, cfg->ssl_service_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))) {
fatal_exit("could not set up listen SSL_CTX");
}
#else /* HAVE_SSL */
(void)ctx;(void)is_dot;(void)is_doh;(void)cfg;
#endif /* HAVE_SSL */
}
/* setups the needed ssl contexts, fatal_exit() on any failure */
static void
setup_sslctxs(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");
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
/* 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)) {
fatal_exit("could not set session ticket SSL_CTX");
}
}
(void)setup_listen_sslctx(&daemon->listen_dot_sslctx, 1, 0, cfg);
#ifdef HAVE_NGHTTP2_NGHTTP2_H
if(cfg_has_https(cfg)) {
(void)setup_listen_sslctx(&daemon->listen_doh_sslctx, 0, 1, cfg);
}
#endif
#ifdef HAVE_NGTCP2
if(cfg_has_quic(cfg)) {
if(!(daemon->listen_quic_sslctx = quic_sslctx_create(
cfg->ssl_service_key, cfg->ssl_service_pem, NULL))) {
fatal_exit("could not set up quic SSL_CTX");
}
}
#endif /* HAVE_NGTCP2 */
}
if(!(daemon->connect_dot_sslctx = connect_sslctx_create(NULL, NULL,
cfg->tls_cert_bundle, cfg->tls_win_cert)))
fatal_exit("could not set up connect SSL_CTX");
#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,
@@ -489,36 +547,7 @@ 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
(void)setup_sslctxs(daemon, cfg);
/* init syslog (as root) if needed, before daemonize, otherwise
* a fork error could not be printed since daemonize closed stderr.*/
@@ -681,6 +710,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");
}
/**
+104 -14
View File
@@ -371,6 +371,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)
@@ -406,6 +484,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;
@@ -600,7 +687,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
@@ -761,7 +849,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) {
@@ -1082,7 +1171,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;
@@ -1413,7 +1502,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) {
@@ -1813,7 +1902,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;
}
@@ -1845,10 +1934,10 @@ 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)) {
rep->ttl < *worker->env.now &&
!(*worker->env.now < rep->serve_expired_norec_ttl))) {
time_t leeway = rep->ttl - *worker->env.now;
if(rep->ttl < *worker->env.now)
leeway = 0;
@@ -1966,13 +2055,13 @@ send_reply_rc:
&repinfo->client_addr, repinfo->client_addrlen,
tv, 1, c->buffer,
(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr:NULL),
c->type);
c->type, c->ssl);
} else {
log_reply_info(NO_VERBOSE, &qinfo,
&repinfo->client_addr, repinfo->client_addrlen,
tv, 1, c->buffer,
(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr:NULL),
c->type);
c->type, c->ssl);
}
}
#ifdef USE_DNSCRYPT
@@ -2173,10 +2262,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,
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->ssl_service_key, cfg->ssl_service_pem, cfg,
worker_handle_request, worker);
cfg, worker_handle_request, worker);
if(!worker->front) {
log_err("could not create listening sockets");
worker_delete(worker);
@@ -2191,7 +2281,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);
+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
};
/**
+4 -2
View File
@@ -658,7 +658,8 @@ handle_event_moddone(struct module_qstate* qstate, int id)
!dns_cache_store(
qstate->env, &qstate->qinfo, qstate->return_msg->rep,
0, qstate->prefetch_leeway, 0, NULL,
qstate->query_flags, qstate->qstarttime))
qstate->query_flags, qstate->qstarttime,
qstate->is_valrec))
log_err("out of memory");
/* do nothing */
@@ -1008,7 +1009,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, super->prefetch_leeway, 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");
}
+20 -8
View File
@@ -192,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) {
@@ -215,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);
@@ -230,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))
{
@@ -275,6 +276,17 @@ dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
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
dt_init(struct dt_env *env, struct comm_base* base)
{
+7
View File
@@ -106,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().
+16 -1
View File
@@ -346,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);
if(!s->sslctx) {
log_err("could not create ssl context");
free(s->ip);
@@ -1786,6 +1787,20 @@ 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))
+265
View File
@@ -1,9 +1,273 @@
11 April 2025: Yorgos
- Merge #1265: Fix WSAPoll.
10 April 2025: Wouter
- Fix for print of connection type in log-replies for dot and doh.
9 April 2025: Wouter
- Fix to detect if atomic_store links in configure.
- Fix #1264: unbound 1.22.0 leaks memory when doing DoH.
8 April 2025: Wouter
- Tag for 1.23.0rc1.
- Fix fast_reload to print chroot with config file name.
7 April 2025: Yorgos
- Merge #902: DNS Error Reporting (RFC 9567). Introduces new
configuration option 'dns-error-reporting' and new statistics for
'num.dns_error_reports'.
4 April 2025: Wouter
- Fix mesh_copy_client_info to omit null contents from copy.
- Fix comment name in the rpz nsdname test.
- Fix nettle compile for warnings and ticket keys.
- Fix redis_replica test for unused option defaults and log printout.
- Fix test to speed up common.sh script kill_pid.
- Fix to update common.sh for speed of kill_pid.
4 April 2025: Yorgos
- Merge #1019: Redis read-only replica support.
Introduces new 'redis-replica-*' options for the Redis cache backend.
3 April 2025: Wouter
- Fix #1263: Exempt loopback addresses from wait-limit.
- Fix wait-limit-netblock and wait-limit-cookie-netblock config parse
to allow two arguments.
- Fix ub_event and include dnstap and win_svc headers.
- Fix test for stat_values for wait limit defaults for localhost.
- Fix parameter unused warning in net_help.c.
2 April 2025: Yorgos
- Merge #1262 from markyang92, fix build with
'gcc-15 -Wbuiltin-declaration-mismatch' error in compat/malloc.c.
- For #1262, ifdef is no longer needed.
2 April 2025: Wouter
- 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.
- 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.
1 April 2025: Wouter
- Fix escape more characters when printing an RR type with an unquoted
string.
- Enable the auth_tls.tdir and auth_tls_failcert.tdir tests.
31 March 2025: Wouter
- iana portlist update.
- 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.
- Skip the unit tests for auth_tls.tdir and auth_tls_failcert.tdir.
27 March 2025: Wouter
- Fix unit test dname log printout typecast.
- Fix for ci test, expat is installed on the osx image.
26 March 2025: Yorgos
- Fix #1255: Multiple pinnings to vulnerable copies of libexpat.
- For #1255, for ios use an older expat version that does not require
C++11 language features.
- For #1255, for ios disable building tests that require C++11.
- For #1255, for ios try the latest expat version again.
24 March 2025: Wouter
- Fix #1254: `send failed: Socket is not connected` and
`remote address is 0.0.0.0 port 53`.
21 March 2025: Wouter
- Fix #1253: Cache entries fail to be removed from Redis cachedb
backend with unbound-control flush* +c.
- Fix for #1253: Fix for redis cachedb backend to expect an integer
reply for the EXPIRE command.
20 March 2025: Wouter
- Fix print of RR type NSAP-PTR, it is an unquoted string.
18 March 2025: Wouter
- Fix #1251: WSAPoll first argument cannot be NULL.
- Fix for windows compile create ssl contexts.
17 March 2025: Wouter
- Fix representation of types GPOS and RESINFO, add rdf type for
unquoted str.
16 March 2025: Yorgos
- Fix 'unbound-control flush_negative' when reporting removed data;
reported by David 'eqvinox' Lamparter.
28 February 2025: Wouter
- Merge #1238: Prefer SOURCE_DATE_EPOCH over actual time.
Add --help output description for the SOURCE_DATE_EPOCH variable.
25 February 2025: Wouter
- Merge #1243: Do not shadow tm on line 236.
24 February 2025: Yorgos
- 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).
19 February 2025: Yorgos
- Fix static analysis report about unhandled EOF on error conditions
when reading anchor key files.
- Merge #1241: Fix infra-keep-probing for low infra-cache-max-rtt
values.
17 February 2025: Yorgos
- Consider reconfigurations when calculating the still_useful_timeout
for servers in the infrastructure cache.
30 January 2025: Wouter
- Fix #986: Resolving sas.com with dnssec-validation fails though
signed delegations seem to be (mostly) correct.
29 January 2025: Yorgos
- 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.
24 January 2025: Yorgos
- Merge #1220 from Petr Menšík, Add unbound members group access to
control key.
21 January 2025: Yorgos
- Use the same interface listening port discovery code for all needed
protocols.
- Port to string only when needed before getaddrinfo().
- Do not open unencrypted channels next to encrypted ones on the same
port.
- Merge #1224 from Theo Buehler: Do not use DSA API unless USE_DSA is
set.
21 January 2025: Wouter
- Fix compile of interface check code when dnscrypt or quic is
disabled.
- Fix encoding of RR type ATMA.
- Fix to check length in ATMA string to wire.
- Merge #1229: check before use daemon->shm_info.
20 January 2025: Yorgos
- Merge #1222: Unique DoT and DoH SSL contexts to allow for different
ALPN.
- Create the quic SSL listening context only when needed.
15 January 2025: Yorgos
- Merge #1221: Consider auth zones when checking for forwarders.
14 January 2025: Yorgos
- Add resolver.arpa and service.arpa to the default locally served
zones.
13 January 2025: Yorgos
- Fix #1213: Misleading error message on default access control causing
refuse.
10 January 2025: Yorgos
- Merge #1214: Use TCP_NODELAY on TLS sockets to speed up the TLS
handshake.
31 December 2024: Yorgos
- 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.
20 December 2024: Yorgos
- For #1207: [FR] Support for RESINFO RRType 261 (RFC9606), add
LDNS_RR_TYPE_RESINFO similar to LDNS_RR_TYPE_TXT.
13 December 2024: Yorgos
- Merge #1204: ci: set persist-credentials: false for actions/checkout
per zizmor suggestion.
3 December 2024: Yorgos
- Merge #1189: Fix the dname_str method to cause conversion errors
when the domain name length is 255.
- Merge #1197: dname_str() fixes.
- For #1175, the default value of serve-expired-ttl is set to 86400
(1 day) as suggested by RFC8767.
- Merge #1198: Fix log-servfail with serve expired and no useful cache
contents.
- Safeguard alias loop while looking in the cache for expired answers.
- Merge #1187: Create the SSL_CTX for QUIC before chroot and privilege
drop.
- Fix typo in log_servfail.tdir test.
22 November 2024: Yorgos
- 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.
- For #1175, update serve-expired tests.
20 November 2024: Yorgos
- Fix comparison to help static analyzer.
19 November 2024: Yorgos
- Merge #1169 from Sergey Kacheev, fix: lock-free counters for
auth_zone up/down queries.
15 November 2024: Wouter
- Fix #1183: the data being used is released in method
nsec3_hash_test_entry.
- Fix for #1183: release nsec3 hashes per test file.
8 November 2024: Yorgos
- More descriptive text for 'harden-algo-downgrade'.
- Complete fix for max-global-quota to 200.
6 November 2024: Yorgos
- 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.
5 November 2024: Wouter
- 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.
- Fix to log redis timeout error string on failure.
5 November 2024: Yorgos
- Fix SETEX check during Redis (re)initialization.
4 November 2024: Wouter
- 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.
- Merge #1167: Makefile.in: fix occasional parallel build failures
around bison rule.
1 November 2024: Yorgos
- Merge #1159: Stats for discard-timeout and wait-limit.
- Add test case for #1159.
- Some clean up for stat_values.test.
- Merge #1170 from Melroy van den Berg, Fix chroot manpage
description.
- Merge #1157 from Liang Zhu, Fix heap corruption when calling
ub_ctx_delete in Windows.
25 October 2024: Yorgos
- Fix #1163: Typos in unbound.conf documentation.
17 October 2024: Wouter
- 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.
16 October 2024: Yorgos
- Fix for dnsoverquic and dnstap to use the correct dnstap
environment.
16 October 2024: Wouter
- Fix for dnstap with dnscrypt and dnstap without dnsoverquic.
- Fix #1154: Tag Incorrectly Applying for Other Interfaces
Using the Same IP. This fix is not for 1.22.0.
14 October 2024: Wouter
- Fix to display warning if quic-port is set but dnsoverquic is not
@@ -23,6 +287,7 @@
- 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.
- Tag for 1.22.0rc1.
9 October 2024: Wouter
- Merge #871: DNS over QUIC. This adds `quic-port: 853` and
+41 -11
View File
@@ -194,7 +194,7 @@ server:
# iter-scrub-cname: 11
# Limit on upstream queries for an incoming query and its recursion.
# max-global-quota: 128
# max-global-quota: 200
# msec for waiting for an unknown server to reply. Increase if you
# are behind a slow satellite link, to eg. 1128.
@@ -215,6 +215,12 @@ server:
# 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
@@ -556,8 +562,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
@@ -730,12 +737,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
@@ -748,10 +756,9 @@ server:
#
# 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
@@ -810,6 +817,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
@@ -1077,6 +1086,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.
#
@@ -1304,9 +1318,9 @@ 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.
@@ -1317,6 +1331,22 @@ remote-control:
# 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.
+167
View File
@@ -60,6 +60,155 @@ Reload the server but try to keep the RRset and message cache if
That means the caches sizes and the number of threads must not change between
reloads.
.TP
.B fast_reload \fR[\fI+dpv\fR]
Reload the server, but keep downtime to a minimum, so that user queries
keep seeing service. This needs the code compiled with threads. The config
is loaded in a thread, and prepared, then it briefly pauses the existing
server and updates config options. The intent is that the pause does not
impact the service of user queries. The cache is kept. Also user queries
worked on are kept and continue, but with the new config options.
.IP
This command is experimental at this time.
.IP
The amount of temporal memory needed during a fast_reload is twice the
amount needed for configuration.
This is because Unbound temporarily needs to store both current configuration
values and new ones while trying to fast_reload.
Zones loaded from disk (authority zones and RPZ zones) are included in such
memory needs.
.IP
Options that can be changed are for
forwards,
stubs,
views,
authority zones,
RPZ zones and
local zones.
.IP
Also
access-control and similar options,
interface-action and similar options and
tcp-connection-limit.
It can reload some
define-tag
changes, more on that below.
Further options include
insecure-lan-zones,
domain-insecure,
trust-anchor-file,
trust-anchor,
trusted-keys-file,
auto-trust-anchor-file,
edns-client-string,
ipset,
log-identity,
infra-cache-numhosts,
msg-cache-size,
rrset-cache-size,
key-cache-size,
ratelimit-size,
neg-cache-size,
num-queries-per-thread,
jostle-timeout,
use-caps-for-id,
unwanted-reply-threshold,
tls-use-sni,
outgoing-tcp-mss,
ip-dscp,
max-reuse-tcp-queries,
tcp-reuse-timeout,
tcp-auth-query-timeout,
delay-close.
.IP
It does not work with
interface and
outgoing-interface changes,
also not with
remote control,
outgoing-port-permit,
outgoing-port-avoid,
msg-buffer-size,
any **\*-slabs** options and
statistics-interval changes.
.IP
For dnstap these options can be changed:
dnstap-log-resolver-query-messages,
dnstap-log-resolver-response-messages,
dnstap-log-client-query-messages,
dnstap-log-client-response-messages,
dnstap-log-forwarder-query-messages and
dnstap-log-forwarder-response-messages.
.IP
It does not work with these options:
dnstap-enable,
dnstap-bidirectional,
dnstap-socket-path,
dnstap-ip,
dnstap-tls,
dnstap-tls-server-name,
dnstap-tls-cert-bundle,
dnstap-tls-client-key-file and
dnstap-tls-client-cert-file.
.IP
The options
dnstap-send-identity,
dnstap-send-version,
dnstap-identity, and
dnstap-version can be loaded
when ``+p`` is not used.
.IP
The '+v' option makes the output verbose which includes the time it took to do
the reload.
With '+vv' it is more verbose which includes the amount of memory that was
allocated temporarily to perform the reload; this amount of memory can be big
if the config has large contents.
In the timing output the 'reload' time is the time during which the server was
paused.
.IP
The '+p' option makes the reload not pause threads, they keep running.
Locks are acquired, but items are updated in sequence, so it is possible
for threads to see an inconsistent state with some options from the old
and some options from the new config, such as cache TTL parameters from the
old config and forwards from the new config. The stubs and forwards are
updated at the same time, so that they are viewed consistently, either old
or new values together. The option makes the reload time take eg. 3
microseconds instead of 0.3 milliseconds during which the worker threads are
interrupted. So, the interruption is much shorter, at the expense of some
inconsistency. After the reload itself, every worker thread is briefly
contacted to make them release resources, this makes the delete timing
a little longer, and takes up time from the remote control servicing
worker thread.
.IP
With the nopause option, the reload does not work to reload some options,
that fast reload works on without the nopause option: val-bogus-ttl,
val-override-date, val-sig-skew-min, val-sig-skew-max, val-max-restart,
val-nsec3-keysize-iterations, target-fetch-policy, outbound-msg-retry,
max-sent-count, max-query-restarts, do-not-query-address,
do-not-query-localhost, private-address, private-domain, caps-exempt,
nat64-prefix, do-nat64, infra-host-ttl, infra-keep-probing, ratelimit,
ip-ratelimit, ip-ratelimit-cookie, wait-limit-netblock,
wait-limit-cookie-netblock, ratelimit-below-domain, ratelimit-for-domain.
.IP
The '+d' option makes the reload drop queries that the worker threads are
working on. This is like flush_requestlist. Without it the queries are kept
so that users keep getting answers for those queries that are currently
processed. The drop makes it so that queries during the life time of the
query processing see only old, or only new config options.
.IP
When there are changes to the config tags, from the \fBdefine\-tag\fR option,
then the '+d' option is implicitly turned on with a warning printout, and
queries are dropped.
This is to stop references to the old tag information, by the old
queries. If the number of tags is increased in the newly loaded config, by
adding tags at the end, then the implicit '+d' option is not needed.
.IP
For response ip, that is actions associated with IP addresses, and perhaps
intersected with access control tag and action information, those settings
are stored with a query when it comes in based on its source IP address.
The old information is kept with the query until the queries are done.
This is gone when those queries are resolved and finished, or it is possible
to flush the requestlist with '+d'.
.TP
.B verbosity \fInumber
Change verbosity value for logging. Same values as \fBverbosity\fR keyword in
\fIunbound.conf\fR(5). This new setting lasts until the server is issued
@@ -422,6 +571,12 @@ number of queries with a client part only DNS Cookie by thread
.I threadX.num.queries_cookie_invalid
number of queries with an invalid DNS Cookie by thread
.TP
.I threadX.num.queries_discard_timeout
number of queries removed due to discard-timeout by thread
.TP
.I threadX.num.queries_wait_limit
number of queries removed due to wait-limit by thread
.TP
.I threadX.num.cachehits
number of queries that were successfully answered using a cache lookup
.TP
@@ -441,6 +596,9 @@ request for certificates.
.I threadX.num.dnscrypt.malformed
number of request that were neither cleartext, not valid dnscrypt messages.
.TP
.I threadX.num.dns_error_reports
number of DNS Error Reports generated by thread
.TP
.I threadX.num.prefetch
number of cache prefetches performed. This number is included in
cachehits, as the original query had the unprefetched answer from cache,
@@ -511,6 +669,12 @@ summed over threads.
.I total.num.queries_cookie_invalid
summed over threads.
.TP
.I total.num.queries_discard_timeout
summed over threads.
.TP
.I total.num.queries_wait_limit
summed over threads.
.TP
.I total.num.cachehits
summed over threads.
.TP
@@ -529,6 +693,9 @@ summed over threads.
.I total.num.dnscrypt.malformed
summed over threads.
.TP
.I total.num.dns_error_reports
summed over threads.
.TP
.I total.num.prefetch
summed over threads.
.TP
+154 -48
View File
@@ -326,11 +326,15 @@ The wait limit for the netblock. If not given the wait\-limit value is
used. The most specific netblock is used to determine the limit. Useful for
overriding the default for a specific, group or individual, server.
The value -1 disables wait limits for the netblock.
By default the loopback has a wait limit netblock of -1, it is not limited,
because it is separated from the rest of network for spoofed packets.
The loopback addresses 127.0.0.0/8 and ::1/128 are default at -1.
.TP
.B wait\-limit\-cookie\-netblock: \fI<netblock> <number>
The wait limit for the netblock, when the query has a DNS cookie.
If not given, the wait\-limit\-cookie value is used.
The value -1 disables wait limits for the netblock.
The loopback addresses 127.0.0.0/8 and ::1/128 are default at -1.
.TP
.B so\-rcvbuf: \fI<number>
If not 0, then set the SO_RCVBUF socket option to get more buffer
@@ -716,7 +720,7 @@ and initial ACL (check if the proxy itself is denied/refused by configuration).
The proxied address (if any) will then be used as the true client address and
will be used where applicable for logging, ACL, DNSTAP, RPZ and IP ratelimiting.
PROXYv2 is supported for UDP and TCP/TLS listening interfaces.
There is no support for PROXYv2 on a DoH or DNSCrypt listening interface.
There is no support for PROXYv2 on a DoH, DoQ or DNSCrypt listening interface.
Can list multiple, each on a new statement.
.TP
.B quic\-port: \fI<number>
@@ -902,9 +906,8 @@ outside of the chroot directory.
Additionally, Unbound may need to access /dev/urandom (for entropy)
from inside the chroot.
.IP
If given a chroot is done to the given directory. By default chroot is
enabled and the default is "@UNBOUND_CHROOT_DIR@". If you give "" no
chroot is performed.
If given a chroot is done to the given directory. The chroot is by default
set to "@UNBOUND_CHROOT_DIR@". If you give "" no chroot is performed.
.TP
.B username: \fI<name>
If given, after binding the port the user privileges are dropped. Default is
@@ -1056,11 +1059,11 @@ closer to that of BIND 9, while setting "\-1 \-1 \-1 \-1 \-1" gives behaviour
rumoured to be closer to that of BIND 8.
.TP
.B harden\-short\-bufsize: \fI<yes or no>
Very small EDNS buffer sizes from queries are ignored. Default is on, as
Very small EDNS buffer sizes from queries are ignored. Default is yes, as
described in the standard.
.TP
.B harden\-large\-queries: \fI<yes or no>
Very large queries are ignored. Default is off, since it is legal protocol
Very large queries are ignored. Default is no, since it is legal protocol
wise to send these, and could be necessary for operation if TSIG or EDNS
payload is very large.
.TP
@@ -1107,10 +1110,23 @@ to increase the max depth that is checked to.
.TP
.B harden\-algo\-downgrade: \fI<yes or no>
Harden against algorithm downgrade when multiple algorithms are
advertised in the DS record. If no, allows the weakest algorithm to
validate the zone. Default is no. Zone signers must produce zones
that allow this feature to work, but sometimes they do not, and turning
this option off avoids that validation failure.
advertised in the DS record.
This works by first choosing only the strongest DS digest type as per RFC 4509
(Unbound treats the highest algorithm as the strongest) and then
expecting signatures from all the advertised signing algorithms from the chosen
DS(es) to be present.
If no, allows any one supported algorithm to validate the zone, even if other advertised algorithms are broken.
Default is no.
RFC 6840 mandates that zone signers must produce zones signed with all
advertised algorithms, but sometimes they do not.
RFC 6840 also clarifies that this requirement is not for validators and
validators should accept any single valid path.
It should thus be explicitly noted that this option violates RFC 6840 for
DNSSEC validation and should only be used to perform a signature
completeness test to support troubleshooting.
Using this option may break DNSSEC resolution with non-RFC6840-conforming
signers and/or in multi-signer configurations that don't send all the
advertised signatures.
.TP
.B harden\-unknown\-additional: \fI<yes or no>
Harden against unknown records in the authority section and additional
@@ -1131,7 +1147,7 @@ queries. For domains that do not support 0x20 and also fail with fallback
because they keep sending different answers, like some load balancers.
Can be given multiple times, for different domains.
.TP
.B caps\-whitelist: \fI<yes or no>
.B caps\-whitelist: \fI<domain>
Alternate syntax for \fBcaps\-exempt\fR.
.TP
.B qname\-minimisation: \fI<yes or no>
@@ -1248,9 +1264,6 @@ Adding \fIrespip\fR to the front will cause RPZ processing to be done on
all queries.
The default is "\fIvalidator iterator\fR".
.IP
When the server is built with
EDNS client subnet support the default is "\fIsubnetcache validator
iterator\fR".
Most modules that need to be listed here have to be listed at the beginning
of the line. The subnetcachedb module has to be listed just before
the iterator.
@@ -1390,15 +1403,17 @@ Default is no.
.TP
.B serve\-expired: \fI<yes or no>
If enabled, Unbound attempts to serve old responses from cache with a
TTL of \fBserve\-expired\-reply\-ttl\fR in the response without waiting for the
actual resolution to finish. The actual resolution answer ends up in the cache
later on. Default is "no".
TTL of \fBserve\-expired\-reply\-ttl\fR in the response.
By default the expired answer will be used after a resolution attempt errored
out or is taking more than serve\-expired\-client\-timeout to resolve.
Default is "no".
.TP
.B serve\-expired\-ttl: \fI<seconds>
Limit serving of expired responses to configured seconds after expiration. 0
disables the limit. This option only applies when \fBserve\-expired\fR is
enabled. A suggested value per RFC 8767 is between
86400 (1 day) and 259200 (3 days). The default is 0.
Limit serving of expired responses to configured seconds after expiration.
0 disables the limit.
This option only applies when \fBserve\-expired\fR is enabled.
A suggested value per RFC 8767 is between 86400 (1 day) and 259200 (3 days).
The default is 86400.
.TP
.B serve\-expired\-ttl\-reset: \fI<yes or no>
Set the TTL of expired records to the \fBserve\-expired\-ttl\fR value after a
@@ -1412,12 +1427,14 @@ TTL value to use when replying with expired data. If
use 30 as the value (RFC 8767). The default is 30.
.TP
.B serve\-expired\-client\-timeout: \fI<msec>
Time in milliseconds before replying to the client with expired data. This
essentially enables the serve-stale behavior as specified in
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. A recommended value per
RFC 8767 is 1800. Setting this to 0 will disable this
behavior. Default is 0.
responding with expired data.
Setting this to 0 will disable this behavior and instead serve the expired
record immediately from the cache before attempting to refresh it via
resolution.
Default is 1800.
.TP
.B serve\-original\-ttl: \fI<yes or no>
If enabled, Unbound will always return the original TTL as received from
@@ -1622,6 +1639,7 @@ given zone. Use \fInodefault\fR if you use exactly that zone, if you want to
use a subzone, use \fItransparent\fR.
.P
The default zones are localhost, reverse 127.0.0.1 and ::1, the home.arpa,
the resolver.arpa, the service.arpa,
the onion, test, invalid and the AS112 zones. The AS112 zones are reverse
DNS zones for private use and reserved IP addresses for which the servers
on the internet cannot provide correct answers. They are configured by
@@ -1677,6 +1695,24 @@ local\-data: "home.arpa. 10800 IN
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
.fi
.TP 10
\h'5'\fIresolver.arpa (RFC 9462)\fR
Default content:
.nf
local\-zone: "resolver.arpa." static
local\-data: "resolver.arpa. 10800 IN NS localhost."
local\-data: "resolver.arpa. 10800 IN
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
.fi
.TP 10
\h'5'\fIservice.arpa (draft-ietf-dnssd-srp-25)\fR
Default content:
.nf
local\-zone: "service.arpa." static
local\-data: "service.arpa. 10800 IN NS localhost."
local\-data: "service.arpa. 10800 IN
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
.fi
.TP 10
\h'5'\fIonion (RFC 7686)\fR
Default content:
.nf
@@ -1998,7 +2034,7 @@ Default is 11.
Limit on the number of upstream queries sent out for an incoming query and
its subqueries from recursion. It is not reset during the resolution. When
it is exceeded the query is failed and the lookup process stops.
Default is 128.
Default is 200.
.TP 5
.B fast\-server\-permil: \fI<number>
Specify how many times out of 1000 to pick from the set of fastest servers.
@@ -2053,17 +2089,30 @@ be used. Default is 65001.
.TP 5
.B ede: \fI<yes or no>
If enabled, Unbound will respond with Extended DNS Error codes (RFC8914).
These EDEs attach informative error messages to a response for various
errors. Default is "no".
These EDEs provide additional information with a response mainly for, but not
limited to, DNS and DNSSEC errors.
When the \fBval-log-level\fR option is also set to \fB2\fR, responses with
Extended DNS Errors concerning DNSSEC failures that are not served from cache,
will also contain a descriptive text message about the reason for the failure.
Extended DNS Errors concerning DNSSEC failures will also contain a descriptive
text message about the reason for the failure.
Default is "no".
.TP 5
.B ede\-serve\-expired: \fI<yes or no>
If enabled, Unbound will attach an Extended DNS Error (RFC8914) Code 3 - Stale
Answer as EDNS0 option to the expired response. Note that this will not attach
the EDE code without setting the global \fBede\fR option to "yes" as well.
Answer as EDNS0 option to the expired response.
The \fBede\fR option needs to be enabled as well for this to work.
Default is "no".
.TP 5
.B dns\-error\-reporting: \fI<yes or no>
If enabled, Unbound will send DNS Error Reports (RFC9567).
The name servers need to express support by attaching the Report-Channel EDNS0
option on their replies specifying the reporting agent for the zone.
Any errors encountered during resolution that would result in Unbound
generating an Extended DNS Error (RFC8914) will be reported to the zone's
reporting agent.
The \fBede\fR option does not need to be enabled for this to work.
It is advised that the \fBqname\-minimisation\fR option is also enabled to
increase privacy on the outgoing reports.
Default is "no".
.SS "Remote Control Options"
In the
@@ -2476,8 +2525,8 @@ The dynamic library file to load. Repeat this option for every dynlib module
instance added to the \fBmodule\-config:\fR option.
.SS "DNS64 Module Options"
.LP
The dns64 module must be configured in the \fBmodule\-config:\fR "dns64
validator iterator" directive and be compiled into the daemon to be
The dns64 module must be configured in the \fBmodule\-config:\fR directive
e.g., "dns64 validator iterator" and be compiled into the daemon to be
enabled. These settings go in the \fBserver:\fR section.
.TP
.B dns64\-prefix: \fI<IPv6 prefix>\fR
@@ -2577,8 +2626,8 @@ in the dnscrypt nonce cache. Close to the number of cpus is
a fairly good setting.
.SS "EDNS Client Subnet Module Options"
.LP
The ECS module must be configured in the \fBmodule\-config:\fR "subnetcache
validator iterator" directive and be compiled into the daemon to be
The ECS module must be configured in the \fBmodule\-config:\fR directive e.g.,
"subnetcache validator iterator" and be compiled into the daemon to be
enabled. These settings go in the \fBserver:\fR section.
.LP
If the destination address is allowed in the configuration Unbound will add the
@@ -2599,6 +2648,15 @@ configuration file. On top of that, for each query only 100 different subnets
are allowed to be stored for each address family. Exceeding that number, older
entries will be purged from cache.
.LP
Note that due to the nature of how EDNS Client Subnet works, by segregating the
client IP space in order to try and have tailored responses for prefixes of
unknown sizes, resolution and cache response performance are impacted as a
result.
Usage of the subnetcache module should only be enabled in installations that
require such functionality where the resolver and the clients belong to
different networks.
An example of that is an open resolver installation.
.LP
This module does not interact with the \fBserve\-expired*\fR and
\fBprefetch:\fR options.
.TP
@@ -2649,8 +2707,8 @@ Specifies the maximum number of subnets ECS answers kept in the ECS radix tree.
This number applies for each qname/qclass/qtype tuple. Defaults to 100.
.SS "Opportunistic IPsec Support Module Options"
.LP
The IPsec module must be configured in the \fBmodule\-config:\fR "ipsecmod
validator iterator" directive and be compiled into Unbound by using
The IPsec module must be configured in the \fBmodule\-config:\fR directive
e.g., "ipsecmod validator iterator" and be compiled into Unbound by using
\fB\-\-enable\-ipsecmod\fR to be enabled.
These settings go in the \fBserver:\fR section.
.LP
@@ -2715,12 +2773,12 @@ Allow the ipsecmod functionality for the domain so that the module logic will be
executed. Can be given multiple times, for different domains. If the option is
not specified, all domains are treated as being allowed (default).
.TP
.B ipsecmod\-whitelist: \fI<yes or no>
.B ipsecmod\-whitelist: \fI<domain>
Alternate syntax for \fBipsecmod\-allow\fR.
.SS "Cache DB Module Options"
.LP
The Cache DB module must be configured in the \fBmodule\-config:\fR
"validator cachedb iterator" directive and be compiled into the daemon
The Cache DB module must be configured in the \fBmodule\-config:\fR directive
e.g., "validator cachedb iterator" and be compiled into the daemon
with \fB\-\-enable\-cachedb\fR.
If this module is enabled and configured, the specified backend database
works as a second level cache:
@@ -2815,12 +2873,12 @@ The TCP port number of the Redis server.
This option defaults to 6379.
.TP
.B redis-server-path: \fI<unix socket path>\fR
The unix socket path to connect to the redis server. Off by default, and it
The unix socket path to connect to the Redis server. Off by default, and it
can be set to "" to turn this off. Unix sockets may have better throughput
than the IP address option.
.TP
.B redis-server-password: \fI"<password>"\fR
The Redis AUTH password to use for the redis server.
The Redis AUTH password to use for the Redis server.
Only relevant if Redis is configured for client password authorisation.
Off by default, and it can be set to "" to turn this off.
.TP
@@ -2832,12 +2890,14 @@ re-establish a new connection later.
This option defaults to 100 milliseconds.
.TP
.B redis-command-timeout: \fI<msec>\fR
The timeout to use for redis commands, in milliseconds. If 0, it uses the
redis\-timeout value. The default is 0.
The timeout to use for Redis commands, in milliseconds.
If 0, it uses the \fBredis\-timeout\fR value.
The default is 0.
.TP
.B redis-connect-timeout: \fI<msec>\fR
The timeout to use for redis connection set up, in milliseconds. If 0, it
uses the redis\-timeout value. The default is 0.
The timeout to use for Redis connection set up, in milliseconds.
If 0, it uses the \fBredis\-timeout\fR value.
The default is 0.
.TP
.B redis-expire-records: \fI<yes or no>
If Redis record expiration is enabled. If yes, Unbound sets timeout for Redis
@@ -2857,6 +2917,52 @@ for multiple unrelated applications.
The default database in Redis is 0 while other logical databases need to be
explicitly SELECT'ed upon connecting.
This option defaults to 0.
.TP
.B redis-replica-server-host: \fI<server address or name>\fR
The IP (either v6 or v4) address or domain name of the Redis replica server.
In general an IP address should be specified as otherwise Unbound will have to
resolve the name of the server every time it establishes a connection
to the server.
This server is treated as a read-only replica server
(https://redis.io/docs/management/replication/#read-only-replica).
If specified, all Redis read commands will go to this replica server, while
the write commands will go to the \fBredis-server-host\fR.
This option defaults to "" (disabled).
.TP
.B redis-replica-server-port: \fI<port number>\fR
The TCP port number of the Redis replica server.
This option defaults to 6379.
.TP
.B redis-replica-server-path: \fI<unix socket path>\fR
The unix socket path to connect to the Redis server. Off by default, and it
can be set to "" to turn this off. Unix sockets may have better throughput
than the IP address option.
.TP
.B redis-replica-server-password: \fI"<password>"\fR
The Redis AUTH password to use for the Redis replica server.
Only relevant if Redis is configured for client password authorisation.
Off by default, and it can be set to "" to turn this off.
.TP
.B redis-replica-timeout: \fI<msec>\fR
The period until when Unbound waits for a response from the Redis replica sever.
If this timeout expires Unbound closes the connection, treats it as
if the Redis replica server does not have the requested data, and will try to
re-establish a new connection later.
This option defaults to 100 milliseconds.
.TP
.B redis-replica-command-timeout: \fI<msec>\fR
The timeout to use for Redis replica commands, in milliseconds.
If 0, it uses the \fBredis\-replica\-timeout\fR value.
The default is 0.
.TP
.B redis-replica-connect-timeout: \fI<msec>\fR
The timeout to use for Redis replica connection set up, in milliseconds.
If 0, it uses the \fBredis\-replica\-timeout\fR value.
The default is 0.
.TP
.B redis-replica-logical-db: \fI<logical database index>
Same as \fBredis-logical-db\fR but for the Redis replica server.
This option defaults to 0.
.SS DNSTAP Logging Options
DNSTAP support, when compiled in by using \fB\-\-enable\-dnstap\fR, is enabled
in the \fBdnstap:\fR section.
+138 -14
View File
@@ -51,6 +51,7 @@
#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"
@@ -155,7 +156,8 @@ int ecs_whitelist_check(struct query_info* qinfo,
/* Cache by default, might be disabled after parsing EDNS option
* received from nameserver. */
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)) {
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)
&& sq->ecs_client_in.subnet_validdata) {
qstate->no_cache_store = 0;
}
@@ -522,6 +524,69 @@ 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 sq: subnet qstate
* @return false on failure.
*/
static int
generate_sub_request(struct module_qstate *qstate, 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;
valrec = 1;
}
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, valrec,
&subq)) {
return 0;
}
if(subq) {
/* It is possible to access the subquery module state. */
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;
}
}
return 1;
}
/**
* Perform the query without subnet
* @param qstate: query state
* @param sq: subnet qstate
* @return module state
*/
static enum module_ext_state
generate_lookup_without_subnet(struct module_qstate *qstate,
struct subnet_qstate* sq)
{
verbose(VERB_ALGO, "subnetcache: make subquery to look up without subnet");
if(!generate_sub_request(qstate, sq)) {
verbose(VERB_ALGO, "Could not generate sub query");
qstate->return_rcode = LDNS_RCODE_FORMERR;
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)
{
@@ -557,14 +622,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, sq);
}
/* Purposefully there was no sent subnet, and there is consequently
@@ -589,14 +647,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, sq);
}
lock_rw_wrlock(&sne->biglock);
@@ -795,6 +853,9 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
} else if(sq->subnet_sent_no_subnet) {
/* The answer can be stored as scope 0, not in global cache. */
qstate->no_cache_store = 1;
} else if(sq->subnet_sent) {
/* Need another query to be able to store in global cache. */
qstate->no_cache_store = 1;
}
return 1;
@@ -812,6 +873,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;
@@ -822,6 +909,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,
@@ -851,6 +940,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, sq);
return;
}
verbose(VERB_ALGO, "subnetcache: pass to next module");
qstate->ext_state[id] = module_wait_module;
return;
@@ -891,6 +988,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, sq);
return;
}
sq->ecs_server_out.subnet_addr_fam =
sq->ecs_client_in.subnet_addr_fam;
@@ -927,6 +1032,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);
@@ -975,10 +1082,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
+4
View File
@@ -102,6 +102,10 @@ 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;
};
void subnet_data_delete(void* d, void* ATTR_UNUSED(arg));
+2 -1
View File
@@ -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;
+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;
+51 -1
View File
@@ -129,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);
@@ -331,6 +331,30 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
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_add_stub_hole(fwd, LDNS_RR_CLASS_IN, dname)) {
free(dname);
log_err("out of memory");
return 0;
}
free(dname);
}
return 1;
}
int
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
{
@@ -353,6 +377,16 @@ forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* 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;
@@ -590,3 +624,19 @@ forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
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));
}
+9
View File
@@ -234,4 +234,13 @@ int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c,
void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
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 */
+12 -1
View File
@@ -181,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);
@@ -611,3 +611,14 @@ hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm,
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;
}
+9
View File
@@ -198,4 +198,13 @@ int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
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 */
+104 -49
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,31 +240,13 @@ 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;
@@ -270,7 +313,7 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
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 */
}
@@ -693,10 +736,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");
}
@@ -1488,14 +1532,15 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
/* check stub */
if (stub != NULL && stub->dp != NULL) {
enum verbosity_value level = VERB_ALGO;
int stub_no_cache = stub->dp->no_cache;
lock_rw_unlock(&qstate->env->fwds->lock);
if(stub_no_cache) {
char qname[255+1];
char dpname[255+1];
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) {
if(stub->dp->namelen > dpname_storage_len) {
@@ -1516,14 +1561,15 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
/* Check for forward. */
if (dp) {
enum verbosity_value level = VERB_ALGO;
int dp_no_cache = dp->no_cache;
lock_rw_unlock(&qstate->env->hints->lock);
if(dp_no_cache) {
char qname[255+1];
char dpname[255+1];
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) {
if(dp->namelen > dpname_storage_len) {
@@ -1606,3 +1652,12 @@ limit_nsec_ttl(struct dns_msg* msg)
}
}
}
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;
}
+48 -1
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. */
@@ -142,6 +143,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 +152,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.
@@ -428,6 +431,43 @@ 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
@@ -435,4 +475,11 @@ void iterator_set_ip46_support(struct module_stack* mods,
*/
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 */
+40 -41
View File
@@ -71,13 +71,15 @@
#include "sldns/sbuffer.h"
/* number of packets */
int MAX_GLOBAL_QUOTA = 128;
int MAX_GLOBAL_QUOTA = 200;
/* in msec */
int UNKNOWN_SERVER_NICENESS = 376;
/* in msec */
int USEFUL_SERVER_TOP_TIMEOUT = 120000;
/* Equals USEFUL_SERVER_TOP_TIMEOUT*4 */
int BLACKLIST_PENALTY = (120000*4);
/** Timeout when only a single probe query per IP is allowed. */
int PROBE_MAXRTO = PROBE_MAXRTO_DEFAULT; /* in msec */
static void target_count_increase_nx(struct iter_qstate* iq, int num);
@@ -105,16 +107,6 @@ iter_init(struct module_env* env, int id)
return 1;
}
/** 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
iter_deinit(struct module_env* env, int id)
{
@@ -126,10 +118,7 @@ iter_deinit(struct module_env* env, int id)
free(iter_env->target_fetch_policy);
priv_delete(iter_env->priv);
donotq_delete(iter_env->donotq);
if(iter_env->caps_white) {
traverse_postorder(iter_env->caps_white, caps_free, NULL);
free(iter_env->caps_white);
}
caps_white_delete(iter_env->caps_white);
free(iter_env);
env->modinfo[id] = NULL;
}
@@ -258,7 +247,7 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
log_err("out of memory adding missing");
}
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->use_nat64)) &&
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->nat64.use_nat64)) &&
(dpns->got6 == 2 || !ie->supports_ipv6)) {
dpns->resolved = 1; /* mark as failed */
target_count_increase_nx(super_iq, 1);
@@ -368,7 +357,7 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
err.security = sec_status_indeterminate;
verbose(VERB_ALGO, "store error response in message cache");
iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL,
qstate->query_flags, qstate->qstarttime);
qstate->query_flags, qstate->qstarttime, qstate->is_valrec);
return error_response(qstate, id, rcode);
}
@@ -1092,7 +1081,7 @@ auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq,
/* cache is blacklisted and fallback, and we
* already have an auth_zone dp */
if(verbosity>=VERB_ALGO) {
char buf[255+1];
char buf[LDNS_MAX_DOMAINLEN];
dname_str(z->name, buf);
verbose(VERB_ALGO, "auth_zone %s "
"fallback because cache blacklisted",
@@ -1109,7 +1098,7 @@ auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq,
* validation failure, and the zone allows
* fallback to the internet, query there. */
if(verbosity>=VERB_ALGO) {
char buf[255+1];
char buf[LDNS_MAX_DOMAINLEN];
dname_str(z->name, buf);
verbose(VERB_ALGO, "auth_zone %s "
"fallback because cache blacklisted",
@@ -1723,7 +1712,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
*/
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
iq->dp, ie->supports_ipv4, ie->supports_ipv6,
ie->use_nat64)) {
ie->nat64.use_nat64)) {
int have_dp = 0;
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &have_dp, &iq->dp, qstate->region)) {
if(have_dp) {
@@ -2033,7 +2022,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
return 1;
if(iq->depth > 0 && iq->target_count &&
iq->target_count[TARGET_COUNT_QUERIES] > MAX_TARGET_COUNT) {
char s[LDNS_MAX_DOMAINLEN+1];
char s[LDNS_MAX_DOMAINLEN];
dname_str(qstate->qinfo.qname, s);
verbose(VERB_QUERY, "request %s has exceeded the maximum "
"number of glue fetches %d", s,
@@ -2041,7 +2030,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
return 2;
}
if(iq->dp_target_count > MAX_DP_TARGET_COUNT) {
char s[LDNS_MAX_DOMAINLEN+1];
char s[LDNS_MAX_DOMAINLEN];
dname_str(qstate->qinfo.qname, s);
verbose(VERB_QUERY, "request %s has exceeded the maximum "
"number of glue fetches %d to a single delegation point",
@@ -2087,7 +2076,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
if(mesh_jostle_exceeded(qstate->env->mesh)) {
/* If no ip4 query is possible, that makes
* this ns resolved. */
if(!((ie->supports_ipv4 || ie->use_nat64) &&
if(!((ie->supports_ipv4 || ie->nat64.use_nat64) &&
((ns->lame && !ns->done_pside4) ||
(!ns->lame && !ns->got4)))) {
ns->resolved = 1;
@@ -2096,7 +2085,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
}
}
/* Send the A request. */
if((ie->supports_ipv4 || ie->use_nat64) &&
if((ie->supports_ipv4 || ie->nat64.use_nat64) &&
((ns->lame && !ns->done_pside4) ||
(!ns->lame && !ns->got4))) {
if(!generate_target_query(qstate, iq, id,
@@ -2252,7 +2241,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
}
if(iq->depth > 0 && iq->target_count &&
iq->target_count[TARGET_COUNT_QUERIES] > MAX_TARGET_COUNT) {
char s[LDNS_MAX_DOMAINLEN+1];
char s[LDNS_MAX_DOMAINLEN];
dname_str(qstate->qinfo.qname, s);
verbose(VERB_QUERY, "request %s has exceeded the maximum "
"number of glue fetches %d", s,
@@ -2268,14 +2257,14 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
/* if this nameserver is at a delegation point, but that
* delegation point is a stub and we cannot go higher, skip*/
if( ((ie->supports_ipv6 && !ns->done_pside6) ||
((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4)) &&
((ie->supports_ipv4 || ie->nat64.use_nat64) && !ns->done_pside4)) &&
!can_have_last_resort(qstate->env, ns->name, ns->namelen,
iq->qchase.qclass, NULL, NULL, NULL)) {
log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
"because it is also a stub/forward,",
ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
if(ie->supports_ipv6) ns->done_pside6 = 1;
if(ie->supports_ipv4 || ie->use_nat64) ns->done_pside4 = 1;
if(ie->supports_ipv4 || ie->nat64.use_nat64) ns->done_pside4 = 1;
continue;
}
/* query for parent-side A and AAAA for nameservers */
@@ -2300,7 +2289,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
return 0;
}
}
if((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4) {
if((ie->supports_ipv4 || ie->nat64.use_nat64) && !ns->done_pside4) {
/* Send the A request. */
if(!generate_parentside_target_query(qstate, iq, id,
ns->name, ns->namelen,
@@ -2569,7 +2558,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
}
if(!ie->supports_ipv6)
delegpt_no_ipv6(iq->dp);
if(!ie->supports_ipv4 && !ie->use_nat64)
if(!ie->supports_ipv4 && !ie->nat64.use_nat64)
delegpt_no_ipv4(iq->dp);
delegpt_log(VERB_ALGO, iq->dp);
@@ -2741,9 +2730,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
if((iq->chase_flags&BIT_RD) && !(iq->response->rep->flags&BIT_AA)) {
verbose(VERB_ALGO, "forwarder, ignoring referral from auth zone");
} else {
lock_rw_wrlock(&qstate->env->auth_zones->lock);
qstate->env->auth_zones->num_query_up++;
lock_rw_unlock(&qstate->env->auth_zones->lock);
qstate->env->mesh->num_query_authzone_up++;
iq->num_current_queries++;
iq->chase_to_rd = 0;
iq->dnssec_lame_query = 0;
@@ -3046,7 +3033,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
target_count_increase_global_quota(iq, 1);
if(iq->target_count && iq->target_count[TARGET_COUNT_GLOBAL_QUOTA]
> MAX_GLOBAL_QUOTA) {
char s[LDNS_MAX_DOMAINLEN+1];
char s[LDNS_MAX_DOMAINLEN];
dname_str(qstate->qinfo.qname, s);
verbose(VERB_QUERY, "request %s has exceeded the maximum "
"global quota on number of upstream queries %d", s,
@@ -3070,9 +3057,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
real_addr = target->addr;
real_addrlen = target->addrlen;
if(ie->use_nat64 && target->addr.ss_family == AF_INET) {
addr_to_nat64(&target->addr, &ie->nat64_prefix_addr,
ie->nat64_prefix_addrlen, ie->nat64_prefix_net,
if(ie->nat64.use_nat64 && target->addr.ss_family == AF_INET) {
addr_to_nat64(&target->addr, &ie->nat64.nat64_prefix_addr,
ie->nat64.nat64_prefix_addrlen, ie->nat64.nat64_prefix_net,
&real_addr, &real_addrlen);
log_name_addr(VERB_QUERY, "applied NAT64:",
iq->dp->name, &real_addr, real_addrlen);
@@ -3296,6 +3283,16 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
iq->num_target_queries = 0;
return processDSNSFind(qstate, iq, id);
}
if(iq->qchase.qtype == LDNS_RR_TYPE_DNSKEY && SERVE_EXPIRED
&& qstate->is_valrec &&
reply_find_answer_rrset(&iq->qchase, iq->response->rep) != NULL) {
/* clean out the authority section, if any, so it
* does not overwrite dnssec valid data in the
* validation recursion lookup. */
verbose(VERB_ALGO, "make DNSKEY minimal for serve "
"expired");
iter_make_minimal(iq->response->rep);
}
if(!qstate->no_cache_store)
iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep,
@@ -3303,7 +3300,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS,
qstate->region, qstate->query_flags,
qstate->qstarttime);
qstate->qstarttime, qstate->is_valrec);
/* close down outstanding requests to be discarded */
outbound_list_clear(&iq->outlist);
iq->num_current_queries = 0;
@@ -3397,7 +3394,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
/* no prefetch-leeway, since its not the answer */
iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep, 1, 0, 0, NULL, 0,
qstate->qstarttime);
qstate->qstarttime, qstate->is_valrec);
if(iq->store_parent_NS)
iter_store_parentside_NS(qstate->env,
iq->response->rep);
@@ -3527,7 +3524,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep, 1, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS, NULL,
qstate->query_flags, qstate->qstarttime);
qstate->query_flags, qstate->qstarttime,
qstate->is_valrec);
/* set the current request's qname to the new value. */
iq->qchase.qname = sname;
iq->qchase.qname_len = snamelen;
@@ -3871,7 +3869,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
} else {
verbose(VERB_ALGO, "iterator TargetResponse failed");
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->use_nat64)) &&
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->nat64.use_nat64)) &&
(dpns->got6 == 2 || !ie->supports_ipv6)) {
dpns->resolved = 1; /* fail the target */
/* do not count cached answers */
@@ -4154,7 +4152,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
iq->response->rep, 0, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS,
qstate->region, qstate->query_flags,
qstate->qstarttime);
qstate->qstarttime, qstate->is_valrec);
}
}
qstate->return_rcode = LDNS_RCODE_NOERROR;
@@ -4334,6 +4332,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
}
/* Copy the edns options we may got from the back end */
qstate->edns_opts_back_in = NULL;
if(edns.opt_list_in) {
qstate->edns_opts_back_in = edns_opt_copy_region(edns.opt_list_in,
qstate->region);
+16 -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;
@@ -108,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;
@@ -128,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;
+15 -1
View File
@@ -423,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;
@@ -1059,6 +1059,20 @@ void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
}
#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))
+6
View File
@@ -849,6 +849,12 @@ struct ub_server_stats {
long long mem_quic;
/** number of queries over (DNS over) QUIC */
long long qquic;
/** number of queries removed due to discard-timeout */
long long num_queries_discard_timeout;
/** number of queries removed due to wait-limit */
long long num_queries_wait_limit;
/** number of dns error reports generated */
long long num_dns_error_reports;
};
/**
+1 -1
View File
@@ -204,7 +204,7 @@ struct query_info {
%inline %{
PyObject* dnameAsStr(PyObject* dname) {
char buf[LDNS_MAX_DOMAINLEN+1];
char buf[LDNS_MAX_DOMAINLEN];
buf[0] = '\0';
dname_str((uint8_t*)PyBytes_AsString(dname), buf);
return PyString_FromString(buf);
+1 -1
View File
@@ -73,7 +73,7 @@ int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo,
return dns_cache_store(qstate->env, qinfo, msgrep, is_referral,
qstate->prefetch_leeway, 0, NULL, qstate->query_flags,
qstate->qstarttime);
qstate->qstarttime, qstate->is_valrec);
}
/* Invalidate the message associated with query_info stored in message cache */
+64 -10
View File
@@ -105,6 +105,7 @@ respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage*
socklen_t addrlen, int net, int create, const char* ipstr)
{
struct resp_addr* node;
log_assert(set);
node = (struct resp_addr*)addr_tree_find(&set->ip_tree, addr, addrlen, net);
if(!node && create) {
node = regional_alloc_zero(set->region, sizeof(*node));
@@ -128,6 +129,7 @@ void
respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node)
{
struct resp_addr* prev;
log_assert(set);
prev = (struct resp_addr*)rbtree_previous((struct rbnode_type*)node);
lock_rw_destroy(&node->lock);
(void)rbtree_delete(&set->ip_tree, node);
@@ -146,6 +148,7 @@ respip_find_or_create(struct respip_set* set, const char* ipstr, int create)
struct sockaddr_storage addr;
int net;
socklen_t addrlen;
log_assert(set);
if(!netblockstrtoaddr(ipstr, 0, &addr, &addrlen, &net)) {
log_err("cannot parse netblock: '%s'", ipstr);
@@ -160,6 +163,7 @@ respip_tag_cfg(struct respip_set* set, const char* ipstr,
const uint8_t* taglist, size_t taglen)
{
struct resp_addr* node;
log_assert(set);
if(!(node=respip_find_or_create(set, ipstr, 1)))
return 0;
@@ -183,6 +187,7 @@ respip_action_cfg(struct respip_set* set, const char* ipstr,
{
struct resp_addr* node;
enum respip_action action;
log_assert(set);
if(!(node=respip_find_or_create(set, ipstr, 1)))
return 0;
@@ -325,6 +330,7 @@ static int
respip_data_cfg(struct respip_set* set, const char* ipstr, const char* rrstr)
{
struct resp_addr* node;
log_assert(set);
node=respip_find_or_create(set, ipstr, 0);
if(!node || node->action == respip_none) {
@@ -344,6 +350,7 @@ respip_set_apply_cfg(struct respip_set* set, char* const* tagname, int num_tags,
struct config_strbytelist* p;
struct config_str2list* pa;
struct config_str2list* pd;
log_assert(set);
set->tagname = tagname;
set->num_tags = num_tags;
@@ -609,6 +616,7 @@ respip_addr_lookup(const struct reply_info *rep, struct respip_set* rs,
struct resp_addr* ra;
struct sockaddr_storage ss;
socklen_t addrlen;
log_assert(rs);
lock_rw_rdlock(&rs->lock);
for(i=0; i<rep->an_numrrsets; i++) {
@@ -867,7 +875,8 @@ respip_rewrite_reply(const struct query_info* qinfo,
const struct respip_client_info* cinfo, const struct reply_info* rep,
struct reply_info** new_repp, struct respip_action_info* actinfo,
struct ub_packed_rrset_key** alias_rrset, int search_only,
struct regional* region, struct auth_zones* az, int* rpz_passthru)
struct regional* region, struct auth_zones* az, int* rpz_passthru,
struct views* views, struct respip_set* ipset)
{
const uint8_t* ctaglist;
size_t ctaglen;
@@ -876,7 +885,6 @@ respip_rewrite_reply(const struct query_info* qinfo,
struct config_strlist** tag_datas;
size_t tag_datas_size;
struct view* view = NULL;
struct respip_set* ipset = NULL;
size_t rrset_id = 0, rr_id = 0;
enum respip_action action = respip_none;
int tag = -1;
@@ -899,8 +907,20 @@ respip_rewrite_reply(const struct query_info* qinfo,
tag_actions_size = cinfo->tag_actions_size;
tag_datas = cinfo->tag_datas;
tag_datas_size = cinfo->tag_datas_size;
view = cinfo->view;
ipset = cinfo->respip_set;
if(cinfo->view) {
view = cinfo->view;
lock_rw_rdlock(&view->lock);
} else if(cinfo->view_name) {
view = views_find_view(views, cinfo->view_name, 0);
if(!view) {
/* If the view no longer exists, the rewrite can not
* be processed further. */
verbose(VERB_ALGO, "respip: failed because view %s no "
"longer exists", cinfo->view_name);
return 0;
}
/* The view is rdlocked by views_find_view. */
}
log_assert(ipset);
@@ -915,7 +935,6 @@ respip_rewrite_reply(const struct query_info* qinfo,
* Note also that we assume 'view' is valid in this function, which
* should be safe (see unbound bug #1191) */
if(view) {
lock_rw_rdlock(&view->lock);
if(view->respip_set) {
if((raddr = respip_addr_lookup(rep,
view->respip_set, &rrset_id, &rr_id))) {
@@ -961,7 +980,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
struct sockaddr_storage ss;
socklen_t ss_len = 0;
char nm[256], ip[256];
char qn[255+1];
char qn[LDNS_MAX_DOMAINLEN];
if(!rdata2sockaddr(rep->rrsets[rrset_id]->entry.data, ntohs(rep->rrsets[rrset_id]->rk.type), rr_id, &ss, &ss_len))
snprintf(ip, sizeof(ip), "invalidRRdata");
else
@@ -1101,7 +1120,8 @@ respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
qstate->client_info, qstate->return_msg->rep,
&new_rep, &actinfo, &alias_rrset, 0,
qstate->region, qstate->env->auth_zones,
&qstate->rpz_passthru)) {
&qstate->rpz_passthru, qstate->env->views,
qstate->env->respip_set)) {
goto servfail;
}
if(actinfo.action != respip_none) {
@@ -1149,7 +1169,8 @@ respip_merge_cname(struct reply_info* base_rep,
const struct query_info* qinfo, const struct reply_info* tgt_rep,
const struct respip_client_info* cinfo, int must_validate,
struct reply_info** new_repp, struct regional* region,
struct auth_zones* az)
struct auth_zones* az, struct views* views,
struct respip_set* respip_set)
{
struct reply_info* new_rep;
struct reply_info* tmp_rep = NULL; /* just a placeholder */
@@ -1176,7 +1197,7 @@ respip_merge_cname(struct reply_info* base_rep,
/* see if the target reply would be subject to a response-ip action. */
if(!respip_rewrite_reply(qinfo, cinfo, tgt_rep, &tmp_rep, &actinfo,
&alias_rrset, 1, region, az, NULL))
&alias_rrset, 1, region, az, NULL, views, respip_set))
return 0;
if(actinfo.action != respip_none) {
log_info("CNAME target of redirect response-ip action would "
@@ -1229,7 +1250,8 @@ respip_inform_super(struct module_qstate* qstate, int id,
if(!respip_merge_cname(super->return_msg->rep, &qstate->qinfo,
qstate->return_msg->rep, super->client_info,
super->env->need_to_validate, &new_rep, super->region,
qstate->env->auth_zones))
qstate->env->auth_zones, qstate->env->views,
qstate->env->respip_set))
goto fail;
super->return_msg->rep = new_rep;
return;
@@ -1326,3 +1348,35 @@ respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname,
(actionstr) ? actionstr : "inform", srcip, port);
log_nametypeclass(NO_VERBOSE, txt, qname, qtype, qclass);
}
size_t respip_set_get_mem(struct respip_set* set)
{
size_t m;
if(!set) return 0;
m = sizeof(*set);
lock_rw_rdlock(&set->lock);
m += regional_get_mem(set->region);
lock_rw_unlock(&set->lock);
return m;
}
void
respip_set_swap_tree(struct respip_set* respip_set,
struct respip_set* data)
{
rbnode_type* oldroot = respip_set->ip_tree.root;
size_t oldcount = respip_set->ip_tree.count;
struct regional* oldregion = respip_set->region;
char* const* oldtagname = respip_set->tagname;
int oldnum_tags = respip_set->num_tags;
respip_set->ip_tree.root = data->ip_tree.root;
respip_set->ip_tree.count = data->ip_tree.count;
respip_set->region = data->region;
respip_set->tagname = data->tagname;
respip_set->num_tags = data->num_tags;
data->ip_tree.root = oldroot;
data->ip_tree.count = oldcount;
data->region = oldregion;
data->tagname = oldtagname;
data->num_tags = oldnum_tags;
}
+28 -5
View File
@@ -23,7 +23,8 @@
struct respip_set {
struct regional* region;
struct rbtree_type ip_tree;
lock_rw_type lock; /* lock on the respip tree */
lock_rw_type lock; /* lock on the respip tree. It is ordered
after views and before hints, stubs and local zones. */
char* const* tagname; /* shallow copy of tag names, for logging */
int num_tags; /* number of tagname entries */
};
@@ -59,7 +60,6 @@ struct respip_addr_info;
* This is essentially a subset of acl_addr (except for respip_set) but
* defined as a separate structure to avoid dependency on the daemon-specific
* structure.
* respip_set is supposed to refer to the response-ip set for the global view.
*/
struct respip_client_info {
uint8_t* taglist;
@@ -68,8 +68,12 @@ struct respip_client_info {
size_t tag_actions_size;
struct config_strlist** tag_datas;
size_t tag_datas_size;
/** The view for the action, during cache callback that is by
* pointer. */
struct view* view;
struct respip_set* respip_set;
/** If from module query state, the view pointer is NULL, but the
* name is stored in reference to the view. */
char* view_name;
};
/**
@@ -149,13 +153,16 @@ int respip_views_apply_cfg(struct views* vs, struct config_file* cfg,
* on error.
* @param region: allocator to build *new_repp.
* @param az: auth zones containing RPZ information.
* @param views: views tree to lookup view used.
* @param respip_set: the respip set for the global view.
* @return 1 on success, 0 on error.
*/
int respip_merge_cname(struct reply_info* base_rep,
const struct query_info* qinfo, const struct reply_info* tgt_rep,
const struct respip_client_info* cinfo, int must_validate,
struct reply_info** new_repp, struct regional* region,
struct auth_zones* az);
struct auth_zones* az, struct views* views,
struct respip_set* respip_set);
/**
* See if any IP-based action should apply to any IP address of AAAA/A answer
@@ -178,6 +185,8 @@ int respip_merge_cname(struct reply_info* base_rep,
* @param region: allocator to build *new_repp.
* @param rpz_passthru: keeps track of query state can have passthru that
* stops further rpz processing. Or NULL for cached answer processing.
* @param views: views tree to lookup view used.
* @param ipset: the respip set for the global view.
* @return 1 on success, 0 on error.
*/
int respip_rewrite_reply(const struct query_info* qinfo,
@@ -186,7 +195,7 @@ int respip_rewrite_reply(const struct query_info* qinfo,
struct respip_action_info* actinfo,
struct ub_packed_rrset_key** alias_rrset,
int search_only, struct regional* region, struct auth_zones* az,
int* rpz_passthru);
int* rpz_passthru, struct views* views, struct respip_set* ipset);
/**
* Get the response-ip function block.
@@ -302,4 +311,18 @@ respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node);
struct ub_packed_rrset_key*
respip_copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region);
/** Get memory usage of respip set tree. The routine locks and unlocks the
* set for reading. */
size_t respip_set_get_mem(struct respip_set* set);
/**
* Swap internal tree with preallocated entries. Caller should manage
* the locks.
* @param respip_set: response ip tree
* @param data: preallocated information.
*/
void respip_set_swap_tree(struct respip_set* respip_set,
struct respip_set* data);
#endif /* RESPIP_RESPIP_H */
+215 -59
View File
@@ -1578,7 +1578,7 @@ auth_zone_read_zonefile(struct auth_zone* z, struct config_file* cfg)
cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
zfilename += strlen(cfg->chrootdir);
if(verbosity >= VERB_ALGO) {
char nm[255+1];
char nm[LDNS_MAX_DOMAINLEN];
dname_str(z->name, nm);
verbose(VERB_ALGO, "read zonefile %s for %s", zfilename, nm);
}
@@ -1942,7 +1942,7 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
unsupported_reason = *reason;
/* continue to check for valid ZONEMD */
if(verbosity >= VERB_ALGO) {
char zstr[255+1];
char zstr[LDNS_MAX_DOMAINLEN];
dname_str(z->name, zstr);
verbose(VERB_ALGO, "auth-zone %s ZONEMD %d %d is unsupported: %s", zstr, (int)scheme, (int)hashalgo, *reason);
}
@@ -1950,7 +1950,7 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
continue;
}
if(verbosity >= VERB_ALGO) {
char zstr[255+1];
char zstr[LDNS_MAX_DOMAINLEN];
dname_str(z->name, zstr);
if(!*reason)
verbose(VERB_ALGO, "auth-zone %s ZONEMD hash is correct", zstr);
@@ -1973,7 +1973,7 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
if(!*reason)
*reason = "no ZONEMD records found";
if(verbosity >= VERB_ALGO) {
char zstr[255+1];
char zstr[LDNS_MAX_DOMAINLEN];
dname_str(z->name, zstr);
verbose(VERB_ALGO, "auth-zone %s ZONEMD failed: %s", zstr, *reason);
}
@@ -2317,9 +2317,6 @@ auth_free_masters(struct auth_master* list)
}
}
/** delete auth xfer structure
* @param xfr: delete this xfer and its tasks.
*/
void
auth_xfer_delete(struct auth_xfer* xfr)
{
@@ -3610,9 +3607,7 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
return 0;
}
lock_rw_unlock(&z->lock);
lock_rw_wrlock(&az->lock);
az->num_query_down++;
lock_rw_unlock(&az->lock);
env->mesh->num_query_authzone_down++;
auth_error_encode(qinfo, env, edns, repinfo, buf, temp,
LDNS_RCODE_SERVFAIL);
return 1;
@@ -3625,9 +3620,7 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
/* fallback to regular answering (recursive) */
return 0;
}
lock_rw_wrlock(&az->lock);
az->num_query_down++;
lock_rw_unlock(&az->lock);
env->mesh->num_query_authzone_down++;
/* encode answer */
if(!r)
@@ -4803,8 +4796,8 @@ log_rrlist_position(const char* label, struct auth_chunk* rr_chunk,
{
sldns_buffer pkt;
size_t dlen;
uint8_t buf[256];
char str[256];
uint8_t buf[LDNS_MAX_DOMAINLEN];
char str[LDNS_MAX_DOMAINLEN];
char typestr[32];
sldns_buffer_init_frm_data(&pkt, rr_chunk->data, rr_chunk->len);
sldns_buffer_set_position(&pkt, (size_t)(rr_dname -
@@ -5231,7 +5224,7 @@ xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env)
cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
zfilename += strlen(cfg->chrootdir);
if(verbosity >= VERB_ALGO) {
char nm[255+1];
char nm[LDNS_MAX_DOMAINLEN];
dname_str(z->name, nm);
verbose(VERB_ALGO, "write zonefile %s for %s", zfilename, nm);
}
@@ -5348,7 +5341,7 @@ xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env,
/* holding z lock */
auth_zone_verify_zonemd(z, env, &env->mesh->mods, NULL, 0, 0);
if(z->zone_expired) {
char zname[256];
char zname[LDNS_MAX_DOMAINLEN];
/* ZONEMD must have failed */
/* reacquire locks, so we hold xfr lock on exit of routine,
* and both xfr and z again after releasing xfr for potential
@@ -5380,7 +5373,7 @@ xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env,
lock_rw_unlock(&z->lock);
if(verbosity >= VERB_QUERY && xfr->have_zone) {
char zname[256];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_QUERY, "auth zone %s updated to serial %u", zname,
(unsigned)xfr->serial);
@@ -5442,7 +5435,7 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env)
qinfo.local_alias = NULL;
if(verbosity >= VERB_ALGO) {
char buf1[512];
char buf2[LDNS_MAX_DOMAINLEN+1];
char buf2[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, buf2);
snprintf(buf1, sizeof(buf1), "auth zone %s: master lookup"
" for task_transfer", buf2);
@@ -5498,7 +5491,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
/* the ones that are not in addr format are supposed
* to be looked up. The lookup has failed however,
* so skip them */
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
log_err("%s: failed lookup, cannot transfer from master %s",
zname, master->host);
@@ -5537,7 +5530,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
&addr, addrlen, -1, master->ssl, master->host,
master->file, env->cfg);
if(!xfr->task_transfer->cp) {
char zname[255+1], as[256];
char zname[LDNS_MAX_DOMAINLEN], as[256];
dname_str(xfr->name, zname);
addr_port_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "cannot create http cp "
@@ -5546,7 +5539,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
}
comm_timer_set(xfr->task_transfer->timer, &t);
if(verbosity >= VERB_ALGO) {
char zname[255+1], as[256];
char zname[LDNS_MAX_DOMAINLEN], as[256];
dname_str(xfr->name, zname);
addr_port_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "auth zone %s transfer next HTTP fetch from %s started", zname, as);
@@ -5569,7 +5562,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
env->scratch_buffer, -1,
auth_name != NULL, auth_name);
if(!xfr->task_transfer->cp) {
char zname[255+1], as[256];
char zname[LDNS_MAX_DOMAINLEN], as[256];
dname_str(xfr->name, zname);
addr_port_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "cannot create tcp cp connection for "
@@ -5578,7 +5571,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
}
comm_timer_set(xfr->task_transfer->timer, &t);
if(verbosity >= VERB_ALGO) {
char zname[255+1], as[256];
char zname[LDNS_MAX_DOMAINLEN], as[256];
dname_str(xfr->name, zname);
addr_port_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "auth zone %s transfer next %s fetch from %s started", zname,
@@ -5602,7 +5595,7 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
* and that calls the callback just like a full
* lookup and lookup failures also call callback */
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s transfer next target lookup", zname);
}
@@ -5625,7 +5618,7 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
xfr_transfer_nextmaster(xfr);
}
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s transfer failed, wait", zname);
}
@@ -5728,14 +5721,14 @@ void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
lookup_target, answer, wanted_qtype);
} else {
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup has nodata", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A"));
}
}
} else {
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup has no answer", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A"));
}
@@ -5743,7 +5736,7 @@ void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
regional_free_all(temp);
} else {
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup failed", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A"));
}
@@ -6385,7 +6378,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
/* the ones that are not in addr format are supposed
* to be looked up. The lookup has failed however,
* so skip them */
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
log_err("%s: failed lookup, cannot probe to master %s",
zname, master->host);
@@ -6427,7 +6420,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
xfr->task_probe->cp = outnet_comm_point_for_udp(env->outnet,
auth_xfer_probe_udp_callback, xfr, &addr, addrlen);
if(!xfr->task_probe->cp) {
char zname[255+1], as[256];
char zname[LDNS_MAX_DOMAINLEN], as[256];
dname_str(xfr->name, zname);
addr_port_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "cannot create udp cp for "
@@ -6447,7 +6440,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
/* send udp packet */
if(!comm_point_send_udp_msg(xfr->task_probe->cp, env->scratch_buffer,
(struct sockaddr*)&addr, addrlen, 0)) {
char zname[255+1], as[256];
char zname[LDNS_MAX_DOMAINLEN], as[256];
dname_str(xfr->name, zname);
addr_port_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "failed to send soa probe for %s to %s",
@@ -6455,7 +6448,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
return 0;
}
if(verbosity >= VERB_ALGO) {
char zname[255+1], as[256];
char zname[LDNS_MAX_DOMAINLEN], as[256];
dname_str(xfr->name, zname);
addr_port_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "auth zone %s soa probe sent to %s", zname,
@@ -6486,7 +6479,7 @@ auth_xfer_probe_timer_callback(void* arg)
}
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s soa probe timeout", zname);
}
@@ -6534,7 +6527,7 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
&serial)) {
/* successful lookup */
if(verbosity >= VERB_ALGO) {
char buf[256];
char buf[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, buf);
verbose(VERB_ALGO, "auth zone %s: soa probe "
"serial is %u", buf, (unsigned)serial);
@@ -6573,14 +6566,14 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
}
} else {
if(verbosity >= VERB_ALGO) {
char buf[256];
char buf[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, buf);
verbose(VERB_ALGO, "auth zone %s: bad reply to soa probe", buf);
}
}
} else {
if(verbosity >= VERB_ALGO) {
char buf[256];
char buf[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, buf);
verbose(VERB_ALGO, "auth zone %s: soa probe failed", buf);
}
@@ -6637,7 +6630,7 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
qinfo.local_alias = NULL;
if(verbosity >= VERB_ALGO) {
char buf1[512];
char buf2[LDNS_MAX_DOMAINLEN+1];
char buf2[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, buf2);
snprintf(buf1, sizeof(buf1), "auth zone %s: master lookup"
" for task_probe", buf2);
@@ -6683,7 +6676,7 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
* and that calls the callback just like a full
* lookup and lookup failures also call callback */
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s probe next target lookup", zname);
}
@@ -6696,7 +6689,7 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
* allow_notify addrs */
probe_copy_masters_for_allow_notify(xfr);
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s probe: notify addrs updated", zname);
}
@@ -6704,7 +6697,7 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
/* only wanted lookups for copy, stop probe and start wait */
xfr->task_probe->only_lookup = 0;
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s probe: finished only_lookup", zname);
}
@@ -6730,7 +6723,7 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
if(xfr->task_probe->have_new_lease) {
/* if zone not updated, start the wait timer again */
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth_zone %s unchanged, new lease, wait", zname);
}
@@ -6741,7 +6734,7 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
xfr_set_timeout(xfr, env, 0, 0);
} else {
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s soa probe failed, wait to retry", zname);
}
@@ -6791,14 +6784,14 @@ void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
lookup_target, answer, wanted_qtype);
} else {
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup has nodata", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A"));
}
}
} else {
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup has no address", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A"));
}
@@ -6806,7 +6799,7 @@ void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
regional_free_all(temp);
} else {
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup failed", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A"));
}
@@ -6980,7 +6973,7 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
if(!xfr->task_nextprobe->timer) {
/* failed to malloc memory. likely zone transfer
* also fails for that. skip the timeout */
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
log_err("cannot allocate timer, no refresh for %s",
zname);
@@ -7001,7 +6994,7 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
xfr->task_probe->only_lookup = 1;
}
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "auth zone %s timeout in %d seconds",
zname, (int)tv.tv_sec);
@@ -7010,6 +7003,18 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
comm_timer_set(xfr->task_nextprobe->timer, &tv);
}
void auth_xfer_pickup_initial_zone(struct auth_xfer* x, struct module_env* env)
{
/* set lease_time, because we now have timestamp in env,
* (not earlier during startup and apply_cfg), and this
* notes the start time when the data was acquired */
if(x->have_zone)
x->lease_time = *env->now;
if(x->task_nextprobe && x->task_nextprobe->worker == NULL) {
xfr_set_timeout(x, env, 0, 1);
}
}
/** initial pick up of worker timeouts, ties events to worker event loop */
void
auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env)
@@ -7018,14 +7023,7 @@ auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env)
lock_rw_wrlock(&az->lock);
RBTREE_FOR(x, struct auth_xfer*, &az->xtree) {
lock_basic_lock(&x->lock);
/* set lease_time, because we now have timestamp in env,
* (not earlier during startup and apply_cfg), and this
* notes the start time when the data was acquired */
if(x->have_zone)
x->lease_time = *env->now;
if(x->task_nextprobe && x->task_nextprobe->worker == NULL) {
xfr_set_timeout(x, env, 0, 1);
}
auth_xfer_pickup_initial_zone(x, env);
lock_basic_unlock(&x->lock);
}
lock_rw_unlock(&az->lock);
@@ -7788,7 +7786,7 @@ static void auth_zone_log(uint8_t* name, enum verbosity_value level,
va_list args;
va_start(args, format);
if(verbosity >= level) {
char str[255+1];
char str[LDNS_MAX_DOMAINLEN];
char msg[MAXSYSLOGMSGLEN];
dname_str(name, str);
vsnprintf(msg, sizeof(msg), format, args);
@@ -7990,7 +7988,7 @@ static int zonemd_check_dnssec_soazonemd(struct auth_zone* z,
static void auth_zone_zonemd_fail(struct auth_zone* z, struct module_env* env,
char* reason, char* why_bogus, char** result)
{
char zstr[255+1];
char zstr[LDNS_MAX_DOMAINLEN];
/* if fail: log reason, and depending on config also take action
* and drop the zone, eg. it is gone from memory, set zone_expired */
dname_str(z->name, zstr);
@@ -8436,7 +8434,7 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env)
qinfo.local_alias = NULL;
if(verbosity >= VERB_ALGO) {
char buf1[512];
char buf2[LDNS_MAX_DOMAINLEN+1];
char buf2[LDNS_MAX_DOMAINLEN];
dname_str(z->name, buf2);
snprintf(buf1, sizeof(buf1), "auth zone %s: lookup %s "
"for zonemd verification", buf2,
@@ -8584,3 +8582,161 @@ void auth_zones_pickup_zonemd_verify(struct auth_zones* az,
}
lock_rw_unlock(&az->lock);
}
/** Get memory usage of auth rrset */
static size_t
auth_rrset_get_mem(struct auth_rrset* rrset)
{
size_t m = sizeof(*rrset) + packed_rrset_sizeof(rrset->data);
return m;
}
/** Get memory usage of auth data */
static size_t
auth_data_get_mem(struct auth_data* node)
{
size_t m = sizeof(*node) + node->namelen;
struct auth_rrset* rrset;
for(rrset = node->rrsets; rrset; rrset = rrset->next) {
m += auth_rrset_get_mem(rrset);
}
return m;
}
/** Get memory usage of auth zone */
static size_t
auth_zone_get_mem(struct auth_zone* z)
{
size_t m = sizeof(*z) + z->namelen;
struct auth_data* node;
if(z->zonefile)
m += strlen(z->zonefile)+1;
RBTREE_FOR(node, struct auth_data*, &z->data) {
m += auth_data_get_mem(node);
}
if(z->rpz)
m += rpz_get_mem(z->rpz);
return m;
}
/** Get memory usage of list of auth addr */
static size_t
auth_addrs_get_mem(struct auth_addr* list)
{
size_t m = 0;
struct auth_addr* a;
for(a = list; a; a = a->next) {
m += sizeof(*a);
}
return m;
}
/** Get memory usage of list of primaries for auth xfer */
static size_t
auth_primaries_get_mem(struct auth_master* list)
{
size_t m = 0;
struct auth_master* n;
for(n = list; n; n = n->next) {
m += sizeof(*n);
m += auth_addrs_get_mem(n->list);
if(n->host)
m += strlen(n->host)+1;
if(n->file)
m += strlen(n->file)+1;
}
return m;
}
/** Get memory usage or list of auth chunks */
static size_t
auth_chunks_get_mem(struct auth_chunk* list)
{
size_t m = 0;
struct auth_chunk* chunk;
for(chunk = list; chunk; chunk = chunk->next) {
m += sizeof(*chunk) + chunk->len;
}
return m;
}
/** Get memory usage of auth xfer */
static size_t
auth_xfer_get_mem(struct auth_xfer* xfr)
{
size_t m = sizeof(*xfr) + xfr->namelen;
/* auth_nextprobe */
m += comm_timer_get_mem(xfr->task_nextprobe->timer);
/* auth_probe */
m += auth_primaries_get_mem(xfr->task_probe->masters);
m += comm_point_get_mem(xfr->task_probe->cp);
m += comm_timer_get_mem(xfr->task_probe->timer);
/* auth_transfer */
m += auth_chunks_get_mem(xfr->task_transfer->chunks_first);
m += auth_primaries_get_mem(xfr->task_transfer->masters);
m += comm_point_get_mem(xfr->task_transfer->cp);
m += comm_timer_get_mem(xfr->task_transfer->timer);
/* allow_notify_list */
m += auth_primaries_get_mem(xfr->allow_notify_list);
return m;
}
/** Get memory usage of auth zones ztree */
static size_t
az_ztree_get_mem(struct auth_zones* az)
{
size_t m = 0;
struct auth_zone* z;
RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
lock_rw_rdlock(&z->lock);
m += auth_zone_get_mem(z);
lock_rw_unlock(&z->lock);
}
return m;
}
/** Get memory usage of auth zones xtree */
static size_t
az_xtree_get_mem(struct auth_zones* az)
{
size_t m = 0;
struct auth_xfer* xfr;
RBTREE_FOR(xfr, struct auth_xfer*, &az->xtree) {
lock_basic_lock(&xfr->lock);
m += auth_xfer_get_mem(xfr);
lock_basic_unlock(&xfr->lock);
}
return m;
}
size_t auth_zones_get_mem(struct auth_zones* zones)
{
size_t m;
if(!zones) return 0;
m = sizeof(*zones);
lock_rw_rdlock(&zones->rpz_lock);
lock_rw_rdlock(&zones->lock);
m += az_ztree_get_mem(zones);
m += az_xtree_get_mem(zones);
lock_rw_unlock(&zones->lock);
lock_rw_unlock(&zones->rpz_lock);
return m;
}
void xfr_disown_tasks(struct auth_xfer* xfr, struct worker* worker)
{
if(xfr->task_nextprobe->worker == worker) {
xfr_nextprobe_disown(xfr);
}
if(xfr->task_probe->worker == worker) {
xfr_probe_disown(xfr);
}
if(xfr->task_transfer->worker == worker) {
xfr_transfer_disown(xfr);
}
}
+34 -6
View File
@@ -70,7 +70,8 @@ struct auth_chunk;
* Authoritative zones, shared.
*/
struct auth_zones {
/** lock on the authzone trees */
/** lock on the authzone trees. It is locked after views, respip,
* local_zones and before fwds and stubs. */
lock_rw_type lock;
/** rbtree of struct auth_zone */
rbtree_type ztree;
@@ -78,10 +79,6 @@ struct auth_zones {
rbtree_type xtree;
/** do we have downstream enabled */
int have_downstream;
/** number of queries upstream */
size_t num_query_up;
/** number of queries downstream */
size_t num_query_down;
/** first auth zone containing rpz item in linked list */
struct auth_zone* rpz_first;
/** rw lock for rpz linked list, needed when iterating or editing linked
@@ -211,7 +208,9 @@ struct auth_xfer {
* one of the tasks.
* Once it has the task assigned to it, the worker can access the
* other elements of the task structure without a lock, because that
* is necessary for the eventloop and callbacks from that. */
* is necessary for the eventloop and callbacks from that.
* The auth_zone->lock is locked before this lock.
*/
lock_basic_type lock;
/** zone name, in uncompressed wireformat */
@@ -787,4 +786,33 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode,
void auth_zones_pickup_zonemd_verify(struct auth_zones* az,
struct module_env* env);
/** Get memory usage for auth zones. The routine locks and unlocks
* for reading. */
size_t auth_zones_get_mem(struct auth_zones* zones);
/**
* Initial pick up of the auth zone nextprobe timeout and that turns
* into further zone transfer work, if any. Also sets the lease time.
* @param x: xfer structure, locked by caller.
* @param env: environment of the worker that picks up the task.
*/
void auth_xfer_pickup_initial_zone(struct auth_xfer* x,
struct module_env* env);
/**
* Delete auth xfer structure
* @param xfr: delete this xfer and its tasks.
*/
void auth_xfer_delete(struct auth_xfer* xfr);
/**
* Disown tasks from the xfr that belong to this worker.
* Only tasks for the worker in question, the comm point and timer
* delete functions need to run in the thread of that worker to be
* able to delete the callback from the event base.
* @param xfr: xfr structure
* @param worker: the worker for which to stop tasks.
*/
void xfr_disown_tasks(struct auth_xfer* xfr, struct worker* worker);
#endif /* SERVICES_AUTHZONE_H */
+41 -4
View File
@@ -1056,8 +1056,9 @@ dns_cache_lookup(struct module_env* env,
int
dns_cache_store(struct module_env* env, struct query_info* msgqinf,
struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
struct regional* region, uint32_t flags, time_t qstarttime)
struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
struct regional* region, uint32_t flags, time_t qstarttime,
int is_valrec)
{
struct reply_info* rep = NULL;
if(SERVE_EXPIRED) {
@@ -1065,7 +1066,7 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
* useful expired record exists. */
struct msgreply_entry* e = msg_cache_lookup(env,
msgqinf->qname, msgqinf->qname_len, msgqinf->qtype,
msgqinf->qclass, flags, 0, 0);
msgqinf->qclass, flags, 0, 1);
if(e) {
struct reply_info* cached = e->entry.data;
if(cached->ttl < *env->now
@@ -1079,7 +1080,43 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
* one and let the validator manage caching. */
&& cached->security != sec_status_bogus
&& (env->need_to_validate &&
msgrep->security == sec_status_unchecked)) {
msgrep->security == sec_status_unchecked)
/* Exceptions to that rule are:
* o recursions that don't need validation but
* need to update the cache for coherence
* (delegation information while iterating,
* DNSKEY and DS lookups from validator)
* o explicit RRSIG queries that are not
* validated. */
&& !is_valrec
&& msgqinf->qtype != LDNS_RR_TYPE_RRSIG) {
if((int)FLAGS_GET_RCODE(msgrep->flags) !=
LDNS_RCODE_NOERROR &&
(int)FLAGS_GET_RCODE(msgrep->flags) !=
LDNS_RCODE_NXDOMAIN) {
/* The current response has an
* erroneous rcode. Adjust norec time
* so that additional lookups are not
* performed for some time. */
verbose(VERB_ALGO, "set "
"serve-expired-norec-ttl for "
"response in cache");
cached->serve_expired_norec_ttl =
NORR_TTL + *env->now;
if(env->cfg->serve_expired_ttl_reset &&
cached->serve_expired_ttl
< *env->now +
env->cfg->serve_expired_ttl) {
/* Reset serve-expired-ttl for
* valid response in cache. */
verbose(VERB_ALGO, "reset "
"serve-expired-ttl "
"for response in cache");
cached->serve_expired_ttl =
*env->now +
env->cfg->serve_expired_ttl;
}
}
verbose(VERB_ALGO, "a validated expired entry "
"could be overwritten, skip caching "
"the new message at this stage");
+4 -1
View File
@@ -90,11 +90,14 @@ struct dns_msg {
* (See DNSCACHE_STORE_xxx flags).
* @param qstarttime: time when the query was started, and thus when the
* delegations were looked up.
* @param is_valrec: if the query is validation recursion and does not get
* dnssec validation itself.
* @return 0 on alloc error (out of memory).
*/
int dns_cache_store(struct module_env* env, struct query_info* qinf,
struct reply_info* rep, int is_referral, time_t leeway, int pside,
struct regional* region, uint32_t flags, time_t qstarttime);
struct regional* region, uint32_t flags, time_t qstarttime,
int is_valrec);
/**
* Store message in the cache. Stores in message cache and rrset cache.
+105 -65
View File
@@ -52,24 +52,6 @@
#include "util/config_file.h"
#include "iterator/iterator.h"
/** Timeout when only a single probe query per IP is allowed. */
#define PROBE_MAXRTO 12000 /* in msec */
/** number of timeouts for a type when the domain can be blocked ;
* even if another type has completely rtt maxed it, the different type
* can do this number of packets (until those all timeout too) */
#define TIMEOUT_COUNT_MAX 3
/** Minus 1000 because that is outside of the RTTBAND, so
* blacklisted servers stay blacklisted if this is chosen.
* If USEFUL_SERVER_TOP_TIMEOUT is below 1000 (configured via RTT_MAX_TIMEOUT,
* infra-cache-max-rtt) change it to just above the RTT_BAND. */
#define STILL_USEFUL_TIMEOUT ( \
USEFUL_SERVER_TOP_TIMEOUT < 1000 || \
USEFUL_SERVER_TOP_TIMEOUT - 1000 <= RTT_BAND \
?RTT_BAND + 1 \
:USEFUL_SERVER_TOP_TIMEOUT - 1000)
/** ratelimit value for delegation point */
int infra_dp_ratelimit = 0;
@@ -82,6 +64,20 @@ int infra_ip_ratelimit = 0;
* For clients with a valid DNS Cookie. */
int infra_ip_ratelimit_cookie = 0;
/** Minus 1000 because that is outside of the RTTBAND, so
* blacklisted servers stay blacklisted if this is chosen.
* If USEFUL_SERVER_TOP_TIMEOUT is below 1000 (configured via RTT_MAX_TIMEOUT,
* infra-cache-max-rtt) change it to just above the RTT_BAND. */
int
still_useful_timeout()
{
return
USEFUL_SERVER_TOP_TIMEOUT < 1000 ||
USEFUL_SERVER_TOP_TIMEOUT - 1000 <= RTT_BAND
?RTT_BAND + 1
:USEFUL_SERVER_TOP_TIMEOUT - 1000;
}
size_t
infra_sizefunc(void* k, void* ATTR_UNUSED(d))
{
@@ -165,7 +161,7 @@ rate_deldatafunc(void* d, void* ATTR_UNUSED(arg))
/** find or create element in domainlimit tree */
static struct domain_limit_data* domain_limit_findcreate(
struct infra_cache* infra, char* name)
struct rbtree_type* domain_limits, char* name)
{
uint8_t* nm;
int labs;
@@ -181,8 +177,8 @@ static struct domain_limit_data* domain_limit_findcreate(
labs = dname_count_labels(nm);
/* can we find it? */
d = (struct domain_limit_data*)name_tree_find(&infra->domain_limits,
nm, nmlen, labs, LDNS_RR_CLASS_IN);
d = (struct domain_limit_data*)name_tree_find(domain_limits, nm,
nmlen, labs, LDNS_RR_CLASS_IN);
if(d) {
free(nm);
return d;
@@ -201,8 +197,8 @@ static struct domain_limit_data* domain_limit_findcreate(
d->node.dclass = LDNS_RR_CLASS_IN;
d->lim = -1;
d->below = -1;
if(!name_tree_insert(&infra->domain_limits, &d->node, nm, nmlen,
labs, LDNS_RR_CLASS_IN)) {
if(!name_tree_insert(domain_limits, &d->node, nm, nmlen, labs,
LDNS_RR_CLASS_IN)) {
log_err("duplicate element in domainlimit tree");
free(nm);
free(d);
@@ -212,19 +208,19 @@ static struct domain_limit_data* domain_limit_findcreate(
}
/** insert rate limit configuration into lookup tree */
static int infra_ratelimit_cfg_insert(struct infra_cache* infra,
static int infra_ratelimit_cfg_insert(struct rbtree_type* domain_limits,
struct config_file* cfg)
{
struct config_str2list* p;
struct domain_limit_data* d;
for(p = cfg->ratelimit_for_domain; p; p = p->next) {
d = domain_limit_findcreate(infra, p->str);
d = domain_limit_findcreate(domain_limits, p->str);
if(!d)
return 0;
d->lim = atoi(p->str2);
}
for(p = cfg->ratelimit_below_domain; p; p = p->next) {
d = domain_limit_findcreate(infra, p->str);
d = domain_limit_findcreate(domain_limits, p->str);
if(!d)
return 0;
d->below = atoi(p->str2);
@@ -232,24 +228,21 @@ static int infra_ratelimit_cfg_insert(struct infra_cache* infra,
return 1;
}
/** setup domain limits tree (0 on failure) */
static int
setup_domain_limits(struct infra_cache* infra, struct config_file* cfg)
int
setup_domain_limits(struct rbtree_type* domain_limits, struct config_file* cfg)
{
name_tree_init(&infra->domain_limits);
if(!infra_ratelimit_cfg_insert(infra, cfg)) {
name_tree_init(domain_limits);
if(!infra_ratelimit_cfg_insert(domain_limits, cfg)) {
return 0;
}
name_tree_init_parents(&infra->domain_limits);
name_tree_init_parents(domain_limits);
return 1;
}
/** find or create element in wait limit netblock tree */
static struct wait_limit_netblock_info*
wait_limit_netblock_findcreate(struct infra_cache* infra, char* str,
int cookie)
wait_limit_netblock_findcreate(struct rbtree_type* tree, char* str)
{
rbtree_type* tree;
struct sockaddr_storage addr;
int net;
socklen_t addrlen;
@@ -261,10 +254,6 @@ wait_limit_netblock_findcreate(struct infra_cache* infra, char* str,
}
/* can we find it? */
if(cookie)
tree = &infra->wait_limits_cookie_netblock;
else
tree = &infra->wait_limits_netblock;
d = (struct wait_limit_netblock_info*)addr_tree_find(tree, &addr,
addrlen, net);
if(d)
@@ -286,19 +275,21 @@ wait_limit_netblock_findcreate(struct infra_cache* infra, char* str,
/** insert wait limit information into lookup tree */
static int
infra_wait_limit_netblock_insert(struct infra_cache* infra,
struct config_file* cfg)
infra_wait_limit_netblock_insert(rbtree_type* wait_limits_netblock,
rbtree_type* wait_limits_cookie_netblock, struct config_file* cfg)
{
struct config_str2list* p;
struct wait_limit_netblock_info* d;
for(p = cfg->wait_limit_netblock; p; p = p->next) {
d = wait_limit_netblock_findcreate(infra, p->str, 0);
d = wait_limit_netblock_findcreate(wait_limits_netblock,
p->str);
if(!d)
return 0;
d->limit = atoi(p->str2);
}
for(p = cfg->wait_limit_cookie_netblock; p; p = p->next) {
d = wait_limit_netblock_findcreate(infra, p->str, 1);
d = wait_limit_netblock_findcreate(wait_limits_cookie_netblock,
p->str);
if(!d)
return 0;
d->limit = atoi(p->str2);
@@ -306,16 +297,48 @@ infra_wait_limit_netblock_insert(struct infra_cache* infra,
return 1;
}
/** setup wait limits tree (0 on failure) */
/** Add a default wait limit netblock */
static int
setup_wait_limits(struct infra_cache* infra, struct config_file* cfg)
wait_limit_netblock_default(struct rbtree_type* tree, char* str, int limit)
{
addr_tree_init(&infra->wait_limits_netblock);
addr_tree_init(&infra->wait_limits_cookie_netblock);
if(!infra_wait_limit_netblock_insert(infra, cfg))
struct wait_limit_netblock_info* d;
d = wait_limit_netblock_findcreate(tree, str);
if(!d)
return 0;
addr_tree_init_parents(&infra->wait_limits_netblock);
addr_tree_init_parents(&infra->wait_limits_cookie_netblock);
d->limit = limit;
return 1;
}
int
setup_wait_limits(rbtree_type* wait_limits_netblock,
rbtree_type* wait_limits_cookie_netblock, struct config_file* cfg)
{
addr_tree_init(wait_limits_netblock);
addr_tree_init(wait_limits_cookie_netblock);
/* Insert defaults */
/* The loopback address is separated from the rest of the network. */
/* wait-limit-netblock: 127.0.0.0/8 -1 */
if(!wait_limit_netblock_default(wait_limits_netblock, "127.0.0.0/8",
-1))
return 0;
/* wait-limit-netblock: ::1/128 -1 */
if(!wait_limit_netblock_default(wait_limits_netblock, "::1/128", -1))
return 0;
/* wait-limit-cookie-netblock: 127.0.0.0/8 -1 */
if(!wait_limit_netblock_default(wait_limits_cookie_netblock,
"127.0.0.0/8", -1))
return 0;
/* wait-limit-cookie-netblock: ::1/128 -1 */
if(!wait_limit_netblock_default(wait_limits_cookie_netblock,
"::1/128", -1))
return 0;
if(!infra_wait_limit_netblock_insert(wait_limits_netblock,
wait_limits_cookie_netblock, cfg))
return 0;
addr_tree_init_parents(wait_limits_netblock);
addr_tree_init_parents(wait_limits_cookie_netblock);
return 1;
}
@@ -348,11 +371,12 @@ infra_create(struct config_file* cfg)
return NULL;
}
/* insert config data into ratelimits */
if(!setup_domain_limits(infra, cfg)) {
if(!setup_domain_limits(&infra->domain_limits, cfg)) {
infra_delete(infra);
return NULL;
}
if(!setup_wait_limits(infra, cfg)) {
if(!setup_wait_limits(&infra->wait_limits_netblock,
&infra->wait_limits_cookie_netblock, cfg)) {
infra_delete(infra);
return NULL;
}
@@ -377,12 +401,29 @@ static void domain_limit_free(rbnode_type* n, void* ATTR_UNUSED(arg))
}
}
void
domain_limits_free(struct rbtree_type* domain_limits)
{
if(!domain_limits)
return;
traverse_postorder(domain_limits, domain_limit_free, NULL);
}
/** delete wait_limit_netblock_info entries */
static void wait_limit_netblock_del(rbnode_type* n, void* ATTR_UNUSED(arg))
{
free(n);
}
void
wait_limits_free(struct rbtree_type* wait_limits_tree)
{
if(!wait_limits_tree)
return;
traverse_postorder(wait_limits_tree, wait_limit_netblock_del,
NULL);
}
void
infra_delete(struct infra_cache* infra)
{
@@ -390,12 +431,10 @@ infra_delete(struct infra_cache* infra)
return;
slabhash_delete(infra->hosts);
slabhash_delete(infra->domain_rates);
traverse_postorder(&infra->domain_limits, domain_limit_free, NULL);
domain_limits_free(&infra->domain_limits);
slabhash_delete(infra->client_ip_rates);
traverse_postorder(&infra->wait_limits_netblock,
wait_limit_netblock_del, NULL);
traverse_postorder(&infra->wait_limits_cookie_netblock,
wait_limit_netblock_del, NULL);
wait_limits_free(&infra->wait_limits_netblock);
wait_limits_free(&infra->wait_limits_cookie_netblock);
free(infra);
}
@@ -426,7 +465,7 @@ infra_adjust(struct infra_cache* infra, struct config_file* cfg)
/* reapply domain limits */
traverse_postorder(&infra->domain_limits, domain_limit_free,
NULL);
if(!setup_domain_limits(infra, cfg)) {
if(!setup_domain_limits(&infra->domain_limits, cfg)) {
infra_delete(infra);
return NULL;
}
@@ -668,7 +707,7 @@ infra_update_tcp_works(struct infra_cache* infra,
if(data->rtt.rto >= RTT_MAX_TIMEOUT)
/* do not disqualify this server altogether, it is better
* than nothing */
data->rtt.rto = STILL_USEFUL_TIMEOUT;
data->rtt.rto = still_useful_timeout();
lock_rw_unlock(&e->lock);
}
@@ -808,7 +847,7 @@ infra_get_lame_rtt(struct infra_cache* infra,
&& infra->infra_keep_probing) {
/* single probe, keep probing */
if(*rtt >= USEFUL_SERVER_TOP_TIMEOUT)
*rtt = STILL_USEFUL_TIMEOUT;
*rtt = still_useful_timeout();
} else if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay
&& rtt_notimeout(&host->rtt)*4 <= host->rtt.rto) {
/* single probe for this domain, and we are not probing */
@@ -816,15 +855,15 @@ infra_get_lame_rtt(struct infra_cache* infra,
if(qtype == LDNS_RR_TYPE_A) {
if(host->timeout_A >= TIMEOUT_COUNT_MAX)
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
else *rtt = STILL_USEFUL_TIMEOUT;
else *rtt = still_useful_timeout();
} else if(qtype == LDNS_RR_TYPE_AAAA) {
if(host->timeout_AAAA >= TIMEOUT_COUNT_MAX)
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
else *rtt = STILL_USEFUL_TIMEOUT;
else *rtt = still_useful_timeout();
} else {
if(host->timeout_other >= TIMEOUT_COUNT_MAX)
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
else *rtt = STILL_USEFUL_TIMEOUT;
else *rtt = still_useful_timeout();
}
}
/* expired entry */
@@ -832,7 +871,7 @@ infra_get_lame_rtt(struct infra_cache* infra,
/* see if this can be a re-probe of an unresponsive server */
if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
lock_rw_unlock(&e->lock);
*rtt = STILL_USEFUL_TIMEOUT;
*rtt = still_useful_timeout();
*lame = 0;
*dnsseclame = 0;
*reclame = 0;
@@ -1081,7 +1120,8 @@ int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
lock_rw_unlock(&entry->lock);
if(premax <= lim && max > lim) {
char buf[257], qnm[257], ts[12], cs[12], ip[128];
char buf[LDNS_MAX_DOMAINLEN], qnm[LDNS_MAX_DOMAINLEN];
char ts[12], cs[12], ip[128];
dname_str(name, buf);
dname_str(qinfo->qname, qnm);
sldns_wire2str_type_buf(qinfo->qtype, ts, sizeof(ts));
+31
View File
@@ -52,6 +52,19 @@
struct slabhash;
struct config_file;
/** number of timeouts for a type when the domain can be blocked ;
* even if another type has completely rtt maxed it, the different type
* can do this number of packets (until those all timeout too) */
#define TIMEOUT_COUNT_MAX 3
/** Timeout when only a single probe query per IP is allowed.
* Any RTO above this number is considered a probe.
* It is synchronized (caped) with USEFUL_SERVER_TOP_TIMEOUT so that probing
* keeps working even if that configurable number drops below the default
* 12000 ms of probing. */
extern int PROBE_MAXRTO;
/**
* Host information kept for every server, per zone.
*/
@@ -502,4 +515,22 @@ void infra_wait_limit_inc(struct infra_cache* infra, struct comm_reply* rep,
void infra_wait_limit_dec(struct infra_cache* infra, struct comm_reply* rep,
struct config_file* cfg);
/** setup wait limits tree (0 on failure) */
int setup_wait_limits(struct rbtree_type* wait_limits_netblock,
struct rbtree_type* wait_limits_cookie_netblock,
struct config_file* cfg);
/** Free the wait limits and wait cookie limits tree. */
void wait_limits_free(struct rbtree_type* wait_limits_tree);
/** setup domain limits tree (0 on failure) */
int setup_domain_limits(struct rbtree_type* domain_limits,
struct config_file* cfg);
/** Free the domain limits tree. */
void domain_limits_free(struct rbtree_type* domain_limits);
/** exported for unit test */
int still_useful_timeout();
#endif /* SERVICES_CACHE_INFRA_H */
+82 -91
View File
@@ -703,7 +703,10 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
{
int s = -1;
char* err;
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined(SO_BINDANY)
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) \
|| defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) \
|| defined(IP_BINDANY) || defined(IP_FREEBIND) \
|| defined(SO_BINDANY) || defined(TCP_NODELAY)
int on = 1;
#endif
#ifdef HAVE_SYSTEMD
@@ -1031,7 +1034,7 @@ err:
* Create socket from getaddrinfo results
*/
static int
make_sock(int stype, const char* ifname, const char* port,
make_sock(int stype, const char* ifname, int port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
int* reuseport, int transparent, int tcp_mss, int nodelay, int freebind,
int use_systemd, int dscp, struct unbound_socket* ub_sock,
@@ -1039,9 +1042,11 @@ make_sock(int stype, const char* ifname, const char* port,
{
struct addrinfo *res = NULL;
int r, s, inuse, noproto;
char portbuf[32];
snprintf(portbuf, sizeof(portbuf), "%d", port);
hints->ai_socktype = stype;
*noip6 = 0;
if((r=getaddrinfo(ifname, port, hints, &res)) != 0 || !res) {
if((r=getaddrinfo(ifname, portbuf, hints, &res)) != 0 || !res) {
#ifdef USE_WINSOCK
if(r == EAI_NONAME && hints->ai_family == AF_INET6){
*noip6 = 1; /* 'Host not found' for IP6 on winXP */
@@ -1049,7 +1054,7 @@ make_sock(int stype, const char* ifname, const char* port,
}
#endif
log_err("node %s:%s getaddrinfo: %s %s",
ifname?ifname:"default", port, gai_strerror(r),
ifname?ifname:"default", portbuf, gai_strerror(r),
#ifdef EAI_SYSTEM
(r==EAI_SYSTEM?(char*)strerror(errno):"")
#else
@@ -1103,7 +1108,7 @@ make_sock(int stype, const char* ifname, const char* port,
/** make socket and first see if ifname contains port override info */
static int
make_sock_port(int stype, const char* ifname, const char* port,
make_sock_port(int stype, const char* ifname, int port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
int* reuseport, int transparent, int tcp_mss, int nodelay, int freebind,
int use_systemd, int dscp, struct unbound_socket* ub_sock,
@@ -1112,23 +1117,22 @@ make_sock_port(int stype, const char* ifname, const char* port,
char* s = strchr(ifname, '@');
if(s) {
/* override port with ifspec@port */
char p[16];
int port;
char newif[128];
if((size_t)(s-ifname) >= sizeof(newif)) {
log_err("ifname too long: %s", ifname);
*noip6 = 0;
return -1;
}
if(strlen(s+1) >= sizeof(p)) {
log_err("portnumber too long: %s", ifname);
port = atoi(s+1);
if(port < 0 || 0 == port || port > 65535) {
log_err("invalid portnumber in interface: %s", ifname);
*noip6 = 0;
return -1;
}
(void)strlcpy(newif, ifname, sizeof(newif));
newif[s-ifname] = 0;
(void)strlcpy(p, s+1, sizeof(p));
p[strlen(s+1)]=0;
return make_sock(stype, newif, p, hints, v6only, noip6, rcv,
return make_sock(stype, newif, port, hints, v6only, noip6, rcv,
snd, reuseport, transparent, tcp_mss, nodelay, freebind,
use_systemd, dscp, ub_sock, additional);
}
@@ -1237,26 +1241,6 @@ set_recvpktinfo(int s, int family)
return 1;
}
/** see if interface is ssl, its port number == the ssl port number */
static int
if_is_ssl(const char* ifname, const char* port, int ssl_port,
struct config_strlist* tls_additional_port)
{
struct config_strlist* s;
char* p = strchr(ifname, '@');
if(!p && atoi(port) == ssl_port)
return 1;
if(p && atoi(p+1) == ssl_port)
return 1;
for(s = tls_additional_port; s; s = s->next) {
if(p && atoi(p+1) == atoi(s->str))
return 1;
if(!p && atoi(port) == atoi(s->str))
return 1;
}
return 0;
}
/**
* Helper for ports_open. Creates one interface (or NULL for default).
* @param ifname: The interface ip address.
@@ -1265,7 +1249,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
* @param do_udp: if udp should be used.
* @param do_tcp: if tcp should be used.
* @param hints: for getaddrinfo. family and flags have to be set by caller.
* @param port: Port number to use (as string).
* @param port: Port number to use.
* @param list: list of open ports, appended to, changed to point to list head.
* @param rcv: receive buffer size for UDP
* @param snd: send buffer size for UDP
@@ -1291,7 +1275,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
*/
static int
ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
struct addrinfo *hints, const char* port, struct listen_port** list,
struct addrinfo *hints, int port, struct listen_port** list,
size_t rcv, size_t snd, int ssl_port,
struct config_strlist* tls_additional_port, int https_port,
struct config_strlist* proxy_protocol_port,
@@ -1300,12 +1284,18 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
int quic_port, int http_notls_downstream, int sock_queue_timeout)
{
int s, noip6=0;
int is_ssl = if_is_ssl(ifname, port, ssl_port, tls_additional_port);
int is_https = if_is_https(ifname, port, https_port);
int is_dnscrypt = if_is_dnscrypt(ifname, port, dnscrypt_port);
int is_pp2 = if_is_pp2(ifname, port, proxy_protocol_port);
int nodelay = is_https && http2_nodelay;
struct unbound_socket* ub_sock;
int is_doq = if_is_quic(ifname, port, quic_port);
/* Always set TCP_NODELAY on TLS connection as it speeds up the TLS
* handshake. DoH had already such option so we respect it.
* Otherwise the server waits before sending more handshake data for
* the client ACK (Nagle's algorithm), which is delayed because the
* client waits for more data before ACKing (delayed ACK). */
int nodelay = is_https?http2_nodelay:is_ssl;
struct unbound_socket* ub_sock;
const char* add = NULL;
if(!do_udp && !do_tcp)
@@ -1324,6 +1314,12 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
}
/* Check if both UDP and TCP ports should be open.
* In the case of encrypted channels, probably an unencrypted channel
* at the same port is not desired. */
if((is_ssl || is_https) && !is_doq) do_udp = do_auto = 0;
if((is_doq) && !(is_https || is_ssl)) do_tcp = 0;
if(do_auto) {
ub_sock = calloc(1, sizeof(struct unbound_socket));
if(!ub_sock)
@@ -1369,13 +1365,11 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
} else if(is_doq) {
udp_port_type = listen_type_doq;
add = "doq";
if(((strchr(ifname, '@') &&
atoi(strchr(ifname, '@')+1) == 53) ||
(!strchr(ifname, '@') && atoi(port) == 53))) {
log_err("DNS over QUIC is not allowed on "
"port 53. Port 53 is for DNS "
"datagrams. Error for "
"interface '%s'.", ifname);
if(if_listens_on(ifname, port, 53, NULL)) {
log_err("DNS over QUIC is strictly not "
"allowed on port 53 as per RFC 9250. "
"Port 53 is for DNS datagrams. Error "
"for interface '%s'.", ifname);
free(ub_sock->addr);
free(ub_sock);
return 0;
@@ -1423,8 +1417,6 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
}
if(do_tcp) {
int is_ssl = if_is_ssl(ifname, port, ssl_port,
tls_additional_port);
enum listen_type port_type;
ub_sock = calloc(1, sizeof(struct unbound_socket));
if(!ub_sock)
@@ -1523,9 +1515,10 @@ listen_create(struct comm_base* base, struct listen_port* ports,
size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
int harden_large_queries, uint32_t http_max_streams,
char* http_endpoint, int http_notls, struct tcl_list* tcp_conn_limit,
void* sslctx, struct dt_env* dtenv, struct doq_table* doq_table,
struct ub_randstate* rnd, const char* ssl_service_key,
const char* ssl_service_pem, struct config_file* cfg,
void* dot_sslctx, void* doh_sslctx, void* quic_sslctx,
struct dt_env* dtenv,
struct doq_table* doq_table,
struct ub_randstate* rnd,struct config_file* cfg,
comm_point_callback_type* cb, void *cb_arg)
{
struct listen_dnsport* front = (struct listen_dnsport*)
@@ -1558,8 +1551,7 @@ listen_create(struct comm_base* base, struct listen_port* ports,
#endif
cp = comm_point_create_doq(base, ports->fd,
front->udp_buff, cb, cb_arg, ports->socket,
doq_table, rnd, ssl_service_key,
ssl_service_pem, cfg);
doq_table, rnd, quic_sslctx, cfg);
} else if(ports->ftype == listen_type_tcp ||
ports->ftype == listen_type_tcp_dnscrypt) {
cp = comm_point_create_tcp(base, ports->fd,
@@ -1578,7 +1570,7 @@ listen_create(struct comm_base* base, struct listen_port* ports,
ports->ftype, ports->pp2_enabled, cb, cb_arg,
ports->socket);
if(ports->ftype == listen_type_http) {
if(!sslctx && !http_notls) {
if(!doh_sslctx && !http_notls) {
log_warn("HTTPS port configured, but "
"no TLS tls-service-key or "
"tls-service-pem set");
@@ -1620,10 +1612,15 @@ listen_create(struct comm_base* base, struct listen_port* ports,
(ports->ftype == listen_type_udpancil) ||
(ports->ftype == listen_type_tcp_dnscrypt) ||
(ports->ftype == listen_type_udp_dnscrypt) ||
(ports->ftype == listen_type_udpancil_dnscrypt))
(ports->ftype == listen_type_udpancil_dnscrypt)) {
cp->ssl = NULL;
else
cp->ssl = sslctx;
} else if(ports->ftype == listen_type_doq) {
cp->ssl = quic_sslctx;
} else if(ports->ftype == listen_type_http) {
cp->ssl = doh_sslctx;
} else {
cp->ssl = dot_sslctx;
}
cp->dtenv = dtenv;
cp->do_not_close = 1;
#ifdef USE_DNSCRYPT
@@ -1887,8 +1884,6 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
struct addrinfo hints;
int i, do_ip4, do_ip6;
int do_tcp, do_auto;
char portbuf[32];
snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
do_ip4 = cfg->do_ip4;
do_ip6 = cfg->do_ip6;
do_tcp = cfg->do_tcp;
@@ -1934,12 +1929,11 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
return NULL;
}
now = after;
snprintf(portbuf, sizeof(portbuf), "%d", extraport);
if(do_ip6) {
hints.ai_family = AF_INET6;
if(!ports_create_if("::0",
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list,
&hints, extraport, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port,
@@ -1958,7 +1952,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
hints.ai_family = AF_INET;
if(!ports_create_if("0.0.0.0",
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list,
&hints, extraport, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port,
@@ -1980,7 +1974,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
hints.ai_family = AF_INET6;
if(!ports_create_if(do_auto?"::0":"::1",
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list,
&hints, cfg->port, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, cfg->proxy_protocol_port,
@@ -1998,7 +1992,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
hints.ai_family = AF_INET;
if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list,
&hints, cfg->port, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, cfg->proxy_protocol_port,
@@ -2018,7 +2012,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
continue;
hints.ai_family = AF_INET6;
if(!ports_create_if(ifs[i], 0, cfg->do_udp,
do_tcp, &hints, portbuf, &list,
do_tcp, &hints, cfg->port, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, cfg->proxy_protocol_port,
@@ -2036,7 +2030,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
continue;
hints.ai_family = AF_INET;
if(!ports_create_if(ifs[i], 0, cfg->do_udp,
do_tcp, &hints, portbuf, &list,
do_tcp, &hints, cfg->port, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, cfg->proxy_protocol_port,
@@ -4598,10 +4592,9 @@ doq_alpn_select_cb(SSL* ATTR_UNUSED(ssl), const unsigned char** out,
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
/** create new tls session for server doq connection */
static SSL_CTX*
doq_ctx_server_setup(struct doq_server_socket* doq_socket)
void* quic_sslctx_create(char* key, char* pem, char* verifypem)
{
#ifdef HAVE_NGTCP2
char* sid_ctx = "unbound server";
#ifndef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT
SSL_QUIC_METHOD* quic_method;
@@ -4611,6 +4604,16 @@ doq_ctx_server_setup(struct doq_server_socket* doq_socket)
log_crypto_err("Could not SSL_CTX_new");
return NULL;
}
if(!key || key[0] == 0) {
log_err("doq: error, no tls-service-key file specified");
SSL_CTX_free(ctx);
return NULL;
}
if(!pem || pem[0] == 0) {
log_err("doq: error, no tls-service-pem file specified");
SSL_CTX_free(ctx);
return NULL;
}
SSL_CTX_set_options(ctx,
(SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
SSL_OP_SINGLE_ECDH_USE |
@@ -4623,43 +4626,37 @@ doq_ctx_server_setup(struct doq_server_socket* doq_socket)
SSL_CTX_set_alpn_select_cb(ctx, doq_alpn_select_cb, NULL);
#endif
SSL_CTX_set_default_verify_paths(ctx);
if(!SSL_CTX_use_certificate_chain_file(ctx,
doq_socket->ssl_service_pem)) {
log_err("doq: error for cert file: %s",
doq_socket->ssl_service_pem);
if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {
log_err("doq: error for cert file: %s", pem);
log_crypto_err("doq: error in "
"SSL_CTX_use_certificate_chain_file");
SSL_CTX_free(ctx);
return NULL;
}
if(!SSL_CTX_use_PrivateKey_file(ctx, doq_socket->ssl_service_key,
SSL_FILETYPE_PEM)) {
log_err("doq: error for private key file: %s",
doq_socket->ssl_service_key);
if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
log_err("doq: error for private key file: %s", key);
log_crypto_err("doq: error in SSL_CTX_use_PrivateKey_file");
SSL_CTX_free(ctx);
return NULL;
}
if(!SSL_CTX_check_private_key(ctx)) {
log_err("doq: error for key file: %s",
doq_socket->ssl_service_key);
log_err("doq: error for key file: %s", key);
log_crypto_err("doq: error in SSL_CTX_check_private_key");
SSL_CTX_free(ctx);
return NULL;
}
SSL_CTX_set_session_id_context(ctx, (void*)sid_ctx, strlen(sid_ctx));
if(doq_socket->ssl_verify_pem && doq_socket->ssl_verify_pem[0]) {
if(!SSL_CTX_load_verify_locations(ctx,
doq_socket->ssl_verify_pem, NULL)) {
if(verifypem && verifypem[0]) {
if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
log_err("doq: error for verify pem file: %s",
doq_socket->ssl_verify_pem);
verifypem);
log_crypto_err("doq: error in "
"SSL_CTX_load_verify_locations");
SSL_CTX_free(ctx);
return NULL;
}
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(
doq_socket->ssl_verify_pem));
verifypem));
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|
SSL_VERIFY_CLIENT_ONCE|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
@@ -4672,7 +4669,7 @@ doq_ctx_server_setup(struct doq_server_socket* doq_socket)
SSL_CTX_free(ctx);
return NULL;
}
#else
#else /* HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT */
/* The quic_method needs to remain valid during the SSL_CTX
* lifetime, so we allocate it. It is freed with the
* doq_server_socket. */
@@ -4690,6 +4687,10 @@ doq_ctx_server_setup(struct doq_server_socket* doq_socket)
SSL_CTX_set_quic_method(ctx, doq_socket->quic_method);
#endif
return ctx;
#else /* HAVE_NGTCP2 */
(void)key; (void)pem; (void)verifypem;
return NULL;
#endif /* HAVE_NGTCP2 */
}
/** Get the ngtcp2_conn from ssl userdata of type ngtcp2_conn_ref */
@@ -4720,16 +4721,6 @@ doq_ssl_server_setup(SSL_CTX* ctx, struct doq_conn* conn)
return ssl;
}
/** setup the doq_socket server tls context */
int
doq_socket_setup_ctx(struct doq_server_socket* doq_socket)
{
doq_socket->ctx = doq_ctx_server_setup(doq_socket);
if(!doq_socket->ctx)
return 0;
return 1;
}
int
doq_conn_setup(struct doq_conn* conn, uint8_t* scid, size_t scidlen,
uint8_t* ocid, size_t ocidlen, const uint8_t* token, size_t tokenlen)
+16 -9
View File
@@ -194,12 +194,12 @@ int resolve_interface_names(char** ifs, int num_ifs,
* @param http_endpoint: HTTP endpoint to service queries on
* @param http_notls: no TLS for http downstream
* @param tcp_conn_limit: TCP connection limit info.
* @param sslctx: nonNULL if ssl context.
* @param dot_sslctx: nonNULL if dot ssl context.
* @param doh_sslctx: nonNULL if doh ssl context.
* @param quic_sslctx: nonNULL if quic ssl context.
* @param dtenv: nonNULL if dnstap enabled.
* @param doq_table: the doq connection table, with shared information.
* @param rnd: random state.
* @param ssl_service_key: the SSL service key file.
* @param ssl_service_pem: the SSL service pem file.
* @param cfg: config file struct.
* @param cb: callback function when a request arrives. It is passed
* the packet and user argument. Return true to send a reply.
@@ -211,9 +211,10 @@ listen_create(struct comm_base* base, struct listen_port* ports,
size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
int harden_large_queries, uint32_t http_max_streams,
char* http_endpoint, int http_notls, struct tcl_list* tcp_conn_limit,
void* sslctx, struct dt_env* dtenv, struct doq_table* doq_table,
struct ub_randstate* rnd, const char* ssl_service_key,
const char* ssl_service_pem, struct config_file* cfg,
void* dot_sslctx, void* doh_sslctx, void* quic_sslctx,
struct dt_env* dtenv,
struct doq_table* doq_table,
struct ub_randstate* rnd,struct config_file* cfg,
comm_point_callback_type* cb, void *cb_arg);
/**
@@ -512,6 +513,15 @@ struct doq_table {
size_t current_size;
};
/**
* create SSL context for QUIC
* @param key: private key file.
* @param pem: public key cert.
* @param verifypem: if nonNULL, verifylocation file.
* return SSL_CTX* or NULL on failure (logged).
*/
void* quic_sslctx_create(char* key, char* pem, char* verifypem);
/** create doq table */
struct doq_table* doq_table_create(struct config_file* cfg,
struct ub_randstate* rnd);
@@ -712,9 +722,6 @@ int doq_timer_cmp(const void* key1, const void* key2);
/** compare function of doq_stream */
int doq_stream_cmp(const void* key1, const void* key2);
/** setup the doq_socket server tls context */
int doq_socket_setup_ctx(struct doq_server_socket* doq_socket);
/** setup the doq connection callbacks, and settings. */
int doq_conn_setup(struct doq_conn* conn, uint8_t* scid, size_t scidlen,
uint8_t* ocid, size_t ocidlen, const uint8_t* token, size_t tokenlen);
+46 -4
View File
@@ -223,7 +223,7 @@ lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len,
lock_rw_wrlock(&z->lock);
if(!rbtree_insert(&zones->ztree, &z->node)) {
struct local_zone* oldz;
char str[256];
char str[LDNS_MAX_DOMAINLEN];
dname_str(nm, str);
log_warn("duplicate local-zone %s", str);
lock_rw_unlock(&z->lock);
@@ -943,6 +943,16 @@ int local_zone_enter_defaults(struct local_zones* zones, struct config_file* cfg
log_err("out of memory adding default zone");
return 0;
}
/* resolver.arpa. zone (RFC 9462) */
if(!add_empty_default(zones, cfg, "resolver.arpa.")) {
log_err("out of memory adding default zone");
return 0;
}
/* service.arpa. zone (draft-ietf-dnssd-srp-25) */
if(!add_empty_default(zones, cfg, "service.arpa.")) {
log_err("out of memory adding default zone");
return 0;
}
/* onion. zone (RFC 7686) */
if(!add_empty_default(zones, cfg, "onion.")) {
log_err("out of memory adding default zone");
@@ -1765,7 +1775,7 @@ lz_inform_print(struct local_zone* z, struct query_info* qinfo,
struct sockaddr_storage* addr, socklen_t addrlen)
{
char ip[128], txt[512];
char zname[LDNS_MAX_DOMAINLEN+1];
char zname[LDNS_MAX_DOMAINLEN];
uint16_t port = ntohs(((struct sockaddr_in*)addr)->sin_port);
dname_str(z->name, zname);
addr_to_str(addr, addrlen, ip, sizeof(ip));
@@ -1875,7 +1885,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
return 0;
}
if(z && verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(z->name, zname);
verbose(VERB_ALGO, "using localzone %s %s from view %s",
zname, local_zone_type2str(lzt), view->name);
@@ -1897,7 +1907,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
z->override_tree, &tag, tagname, num_tags);
lock_rw_unlock(&zones->lock);
if(z && verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(z->name, zname);
verbose(VERB_ALGO, "using localzone %s %s", zname,
local_zone_type2str(lzt));
@@ -2210,3 +2220,35 @@ void local_zones_del_data(struct local_zones* zones,
lock_rw_unlock(&z->lock);
}
/** Get memory usage for local_zone */
static size_t
local_zone_get_mem(struct local_zone* z)
{
size_t m = sizeof(*z);
lock_rw_rdlock(&z->lock);
m += z->namelen + z->taglen + regional_get_mem(z->region);
lock_rw_unlock(&z->lock);
return m;
}
size_t local_zones_get_mem(struct local_zones* zones)
{
struct local_zone* z;
size_t m;
if(!zones) return 0;
m = sizeof(*zones);
lock_rw_rdlock(&zones->lock);
RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
m += local_zone_get_mem(z);
}
lock_rw_unlock(&zones->lock);
return m;
}
void local_zones_swap_tree(struct local_zones* zones, struct local_zones* data)
{
rbtree_type oldtree = zones->ztree;
zones->ztree = data->ztree;
data->ztree = oldtree;
}
+14
View File
@@ -642,6 +642,20 @@ local_zone_enter_rr(struct local_zone* z, uint8_t* nm, size_t nmlen,
struct local_data*
local_zone_find_data(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs);
/** Get memory usage for local_zones tree. The routine locks and unlocks
* the tree for reading. */
size_t local_zones_get_mem(struct local_zones* zones);
/**
* Swap internal tree with preallocated entries. Caller should manage
* the locks.
* @param zones: the local zones structure.
* @param data: the data structure used to take elements from. This contains
* the old elements on return.
*/
void local_zones_swap_tree(struct local_zones* zones,
struct local_zones* data);
/** Enter a new zone; returns with WRlock
* Made public for unit testing
* @param zones: the local zones tree
+282 -21
View File
@@ -77,6 +77,20 @@
#include <netdb.h>
#endif
/** Compare two views by name */
static int
view_name_compare(const char* v_a, const char* v_b)
{
if(v_a == NULL && v_b == NULL)
return 0;
/* The NULL name is smaller than if the name is set. */
if(v_a == NULL)
return -1;
if(v_b == NULL)
return 1;
return strcmp(v_a, v_b);
}
/**
* Compare two response-ip client info entries for the purpose of mesh state
* compare. It returns 0 if ci_a and ci_b are considered equal; otherwise
@@ -132,12 +146,14 @@ client_info_compare(const struct respip_client_info* ci_a,
}
if(ci_a->tag_datas != ci_b->tag_datas)
return ci_a->tag_datas < ci_b->tag_datas ? -1 : 1;
if(ci_a->view != ci_b->view)
return ci_a->view < ci_b->view ? -1 : 1;
/* For the unbound daemon these should be non-NULL and identical,
* but we check that just in case. */
if(ci_a->respip_set != ci_b->respip_set)
return ci_a->respip_set < ci_b->respip_set ? -1 : 1;
if(ci_a->view || ci_a->view_name || ci_b->view || ci_b->view_name) {
/* Compare the views by name. */
cmp = view_name_compare(
(ci_a->view?ci_a->view->name:ci_a->view_name),
(ci_b->view?ci_b->view->name:ci_b->view_name));
if(cmp != 0)
return cmp;
}
return 0;
}
@@ -214,6 +230,9 @@ mesh_create(struct module_stack* stack, struct module_env* env)
mesh->stats_dropped = 0;
mesh->ans_expired = 0;
mesh->ans_cachedb = 0;
mesh->num_queries_discard_timeout = 0;
mesh->num_queries_wait_limit = 0;
mesh->num_dns_error_reports = 0;
mesh->max_reply_states = env->cfg->num_queries_per_thread;
mesh->max_forever_states = (mesh->max_reply_states+1)/2;
#ifndef S_SPLINT_S
@@ -424,7 +443,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
verbose(VERB_ALGO, "Too many queries waiting from the IP. "
"dropping incoming query.");
comm_point_drop_reply(rep);
mesh->stats_dropped++;
mesh->num_queries_wait_limit++;
return;
}
if(!unique)
@@ -868,6 +887,78 @@ void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
mesh_run(mesh, e->qstate->mesh_info, event, e);
}
/** copy strlist to region */
static struct config_strlist*
cfg_region_strlist_copy(struct regional* region, struct config_strlist* list)
{
struct config_strlist* result = NULL, *last = NULL, *s = list;
while(s) {
struct config_strlist* n = regional_alloc_zero(region,
sizeof(*n));
if(!n)
return NULL;
n->str = regional_strdup(region, s->str);
if(!n->str)
return NULL;
if(last)
last->next = n;
else result = n;
last = n;
s = s->next;
}
return result;
}
/** Copy the client info to the query region. */
static struct respip_client_info*
mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo)
{
size_t i;
struct respip_client_info* client_info;
client_info = regional_alloc_init(region, cinfo, sizeof(*cinfo));
if(!client_info)
return NULL;
/* Copy the client_info so that if the configuration changes,
* then the data stays valid. */
if(cinfo->taglist) {
client_info->taglist = regional_alloc_init(region, cinfo->taglist,
cinfo->taglen);
if(!client_info->taglist)
return NULL;
}
if(cinfo->tag_actions) {
client_info->tag_actions = regional_alloc_init(region, cinfo->tag_actions,
cinfo->tag_actions_size);
if(!client_info->tag_actions)
return NULL;
}
if(cinfo->tag_datas) {
client_info->tag_datas = regional_alloc_zero(region,
sizeof(struct config_strlist*)*cinfo->tag_datas_size);
if(!client_info->tag_datas)
return NULL;
for(i=0; i<cinfo->tag_datas_size; i++) {
if(cinfo->tag_datas[i]) {
client_info->tag_datas[i] = cfg_region_strlist_copy(
region, cinfo->tag_datas[i]);
if(!client_info->tag_datas[i])
return NULL;
}
}
}
if(cinfo->view) {
/* Do not copy the view pointer but store a name instead.
* The name is looked up later when done, this means that
* the view tree can be changed, by reloads. */
client_info->view = NULL;
client_info->view_name = regional_strdup(region,
cinfo->view->name);
if(!client_info->view_name)
return NULL;
}
return client_info;
}
struct mesh_state*
mesh_state_create(struct module_env* env, struct query_info* qinfo,
struct respip_client_info* cinfo, uint16_t qflags, int prime,
@@ -908,8 +999,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
return NULL;
}
if(cinfo) {
mstate->s.client_info = regional_alloc_init(region, cinfo,
sizeof(*cinfo));
mstate->s.client_info = mesh_copy_client_info(region, cinfo);
if(!mstate->s.client_info) {
alloc_reg_release(env->alloc, region);
return NULL;
@@ -1489,10 +1579,121 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
&r->query_reply.client_addr,
r->query_reply.client_addrlen, duration, 0, r_buffer,
(m->s.env->cfg->log_destaddr?(void*)r->query_reply.c->socket->addr:NULL),
r->query_reply.c->type);
r->query_reply.c->type, r->query_reply.c->ssl);
}
}
/**
* Generate the DNS Error Report (RFC9567).
* If there is an EDE attached for this reply and there was a Report-Channel
* EDNS0 option from the upstream, fire up a report query.
* @param qstate: module qstate.
* @param rep: prepared reply to be sent.
*/
static void dns_error_reporting(struct module_qstate* qstate,
struct reply_info* rep)
{
struct query_info qinfo;
struct mesh_state* sub;
struct module_qstate* newq;
uint8_t buf[LDNS_MAX_DOMAINLEN];
size_t count = 0;
int written;
size_t expected_length;
struct edns_option* opt;
sldns_ede_code reason_bogus = LDNS_EDE_NONE;
sldns_rr_type qtype = qstate->qinfo.qtype;
uint8_t* qname = qstate->qinfo.qname;
size_t qname_len = qstate->qinfo.qname_len-1; /* skip the trailing \0 */
uint8_t* agent_domain;
size_t agent_domain_len;
/* We need a valid reporting agent;
* this is based on qstate->edns_opts_back_in that will probably have
* the latest reporting agent we found while iterating */
opt = edns_opt_list_find(qstate->edns_opts_back_in,
LDNS_EDNS_REPORT_CHANNEL);
if(!opt) return;
agent_domain_len = opt->opt_len;
agent_domain = opt->opt_data;
if(dname_valid(agent_domain, agent_domain_len) < 3) {
/* The agent domain needs to be a valid dname that is not the
* root; from RFC9567. */
return;
}
/* Get the EDE generated from the mesh state, these are mostly
* validator errors. If other errors are produced in the future (e.g.,
* RPZ) we would not want them to result in error reports. */
reason_bogus = errinf_to_reason_bogus(qstate);
if(rep && ((reason_bogus == LDNS_EDE_DNSSEC_BOGUS &&
rep->reason_bogus != LDNS_EDE_NONE) ||
reason_bogus == LDNS_EDE_NONE)) {
reason_bogus = rep->reason_bogus;
}
if(reason_bogus == LDNS_EDE_NONE ||
/* other, does not make sense without the text that comes
* with it */
reason_bogus == LDNS_EDE_OTHER) return;
/* Synthesize the error report query in the format:
* "_er.$qtype.$qname.$ede._er.$reporting-agent-domain" */
/* First check if the static length parts fit in the buffer.
* That is everything except for qtype and ede that need to be
* converted to decimal and checked further on. */
expected_length = 4/*_er*/+qname_len+4/*_er*/+agent_domain_len;
if(expected_length > LDNS_MAX_DOMAINLEN) goto skip;
memmove(buf+count, "\3_er", 4);
count += 4;
written = snprintf((char*)buf+count, LDNS_MAX_DOMAINLEN-count,
"X%d", qtype);
expected_length += written;
/* Skip on error, truncation or long expected length */
if(written < 0 || (size_t)written >= LDNS_MAX_DOMAINLEN-count ||
expected_length > LDNS_MAX_DOMAINLEN ) goto skip;
/* Put in the label length */
*(buf+count) = (char)(written - 1);
count += written;
memmove(buf+count, qname, qname_len);
count += qname_len;
written = snprintf((char*)buf+count, LDNS_MAX_DOMAINLEN-count,
"X%d", reason_bogus);
expected_length += written;
/* Skip on error, truncation or long expected length */
if(written < 0 || (size_t)written >= LDNS_MAX_DOMAINLEN-count ||
expected_length > LDNS_MAX_DOMAINLEN ) goto skip;
*(buf+count) = (char)(written - 1);
count += written;
memmove(buf+count, "\3_er", 4);
count += 4;
/* Copy the agent domain */
memmove(buf+count, agent_domain, agent_domain_len);
count += agent_domain_len;
qinfo.qname = buf;
qinfo.qname_len = count;
qinfo.qtype = LDNS_RR_TYPE_TXT;
qinfo.qclass = qstate->qinfo.qclass;
qinfo.local_alias = NULL;
log_query_info(VERB_ALGO, "DNS Error Reporting: generating report "
"query for", &qinfo);
if(mesh_add_sub(qstate, &qinfo, BIT_RD, 0, 0, &newq, &sub)) {
qstate->env->mesh->num_dns_error_reports++;
}
return;
skip:
verbose(VERB_ALGO, "DNS Error Reporting: report query qname too long; "
"skip");
return;
}
void mesh_query_done(struct mesh_state* mstate)
{
struct mesh_reply* r;
@@ -1510,8 +1711,10 @@ void mesh_query_done(struct mesh_state* mstate)
}
if(mstate->s.return_rcode == LDNS_RCODE_SERVFAIL ||
(rep && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_SERVFAIL)) {
/* we are SERVFAILing; check for expired answer here */
mesh_serve_expired_callback(mstate);
if(mstate->s.env->cfg->serve_expired) {
/* we are SERVFAILing; check for expired answer here */
mesh_respond_serve_expired(mstate);
}
if((mstate->reply_list || mstate->cb_list)
&& mstate->s.env->cfg->log_servfail
&& !mstate->s.env->cfg->val_log_squelch) {
@@ -1519,6 +1722,10 @@ void mesh_query_done(struct mesh_state* mstate)
if(err) { log_err("%s", err); }
}
}
if(mstate->reply_list && mstate->s.env->cfg->dns_error_reporting)
dns_error_reporting(&mstate->s, rep);
for(r = mstate->reply_list; r; r = r->next) {
struct timeval old;
timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
@@ -1540,7 +1747,7 @@ void mesh_query_done(struct mesh_state* mstate)
http2_stream_remove_mesh_state(r->h2_stream);
comm_point_drop_reply(&r->query_reply);
mstate->reply_list = reply_list;
mstate->s.env->mesh->stats_dropped++;
mstate->s.env->mesh->num_queries_discard_timeout++;
continue;
}
@@ -1682,6 +1889,25 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
return result;
}
/** remove mesh state callback */
int mesh_state_del_cb(struct mesh_state* s, mesh_cb_func_type cb, void* cb_arg)
{
struct mesh_cb* r, *prev = NULL;
r = s->cb_list;
while(r) {
if(r->cb == cb && r->cb_arg == cb_arg) {
/* Delete this entry. */
/* It was allocated in the s.region, so no free. */
if(prev) prev->next = r->next;
else s->cb_list = r->next;
return 1;
}
prev = r;
r = r->next;
}
return 0;
}
int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
sldns_buffer* buf, mesh_cb_func_type cb, void* cb_arg,
uint16_t qid, uint16_t qflags)
@@ -2029,6 +2255,8 @@ mesh_stats_clear(struct mesh_area* mesh)
{
if(!mesh)
return;
mesh->num_query_authzone_up = 0;
mesh->num_query_authzone_down = 0;
mesh->replies_sent = 0;
mesh->replies_sum_wait.tv_sec = 0;
mesh->replies_sum_wait.tv_usec = 0;
@@ -2042,6 +2270,9 @@ mesh_stats_clear(struct mesh_area* mesh)
memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*UB_STATS_RCODE_NUM);
memset(&mesh->rpz_action[0], 0, sizeof(size_t)*UB_STATS_RPZ_ACTION_NUM);
mesh->ans_nodata = 0;
mesh->num_queries_discard_timeout = 0;
mesh->num_queries_wait_limit = 0;
mesh->num_dns_error_reports = 0;
}
size_t
@@ -2143,7 +2374,8 @@ apply_respip_action(struct module_qstate* qstate,
return 1;
if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, actinfo,
alias_rrset, 0, qstate->region, az, NULL))
alias_rrset, 0, qstate->region, az, NULL, qstate->env->views,
qstate->env->respip_set))
return 0;
/* xxx_deny actions mean dropping the reply, unless the original reply
@@ -2177,7 +2409,7 @@ mesh_serve_expired_callback(void* arg)
struct timeval tv = {0, 0};
int must_validate = (!(qstate->query_flags&BIT_CD)
|| qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
int i = 0;
int i = 0, for_count;
int is_expired;
if(!qstate->serve_expired_data) return;
verbose(VERB_ALGO, "Serve expired: Trying to reply with expired data");
@@ -2190,15 +2422,21 @@ mesh_serve_expired_callback(void* arg)
"Serve expired: Not allowed to look into cache for stale");
return;
}
/* The following while is used instead of the `goto lookup_cache`
* like in the worker. */
while(1) {
/* The following for is used instead of the `goto lookup_cache`
* like in the worker. This loop should get max 2 passes if we need to
* do any aliasing. */
for(for_count = 0; for_count < 2; for_count++) {
fptr_ok(fptr_whitelist_serve_expired_lookup(
qstate->serve_expired_data->get_cached_answer));
msg = (*qstate->serve_expired_data->get_cached_answer)(qstate,
lookup_qinfo, &is_expired);
if(!msg)
if(!msg || (FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NOERROR
&& FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NXDOMAIN
&& FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_YXDOMAIN)) {
/* We don't care for cached failure answers at this
* stage. */
return;
}
/* Reset these in case we pass a second time from here. */
encode_rep = msg->rep;
memset(&actinfo, 0, sizeof(actinfo));
@@ -2212,7 +2450,8 @@ mesh_serve_expired_callback(void* arg)
} else if(partial_rep &&
!respip_merge_cname(partial_rep, &qstate->qinfo, msg->rep,
qstate->client_info, must_validate, &encode_rep, qstate->region,
qstate->env->auth_zones)) {
qstate->env->auth_zones, qstate->env->views,
qstate->env->respip_set)) {
return;
}
if(!encode_rep || alias_rrset) {
@@ -2270,7 +2509,7 @@ mesh_serve_expired_callback(void* arg)
http2_stream_remove_mesh_state(r->h2_stream);
comm_point_drop_reply(&r->query_reply);
mstate->reply_list = reply_list;
mstate->s.env->mesh->stats_dropped++;
mstate->s.env->mesh->num_queries_discard_timeout++;
continue;
}
@@ -2366,3 +2605,25 @@ int mesh_jostle_exceeded(struct mesh_area* mesh)
return 0;
return 1;
}
void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg)
{
struct mesh_state* s = NULL;
s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
if(!s) return;
if(!mesh_state_del_cb(s, cb, cb_arg)) return;
/* It was in the list and removed. */
log_assert(mesh->num_reply_addrs > 0);
mesh->num_reply_addrs--;
if(!s->reply_list && !s->cb_list) {
/* was a reply state, not anymore */
log_assert(mesh->num_reply_states > 0);
mesh->num_reply_states--;
}
if(!s->reply_list && !s->cb_list &&
s->super_set.count == 0) {
mesh->num_detached_states++;
}
}
+24
View File
@@ -90,6 +90,11 @@ struct mesh_area {
/** rbtree of all current queries (mesh_state.node)*/
rbtree_type all;
/** number of queries for unbound's auth_zones, upstream query */
size_t num_query_authzone_up;
/** number of queries for unbound's auth_zones, downstream answers */
size_t num_query_authzone_down;
/** count of the total number of mesh_reply entries */
size_t num_reply_addrs;
/** count of the number of mesh_states that have mesh_replies
@@ -132,6 +137,12 @@ struct mesh_area {
size_t ans_nodata;
/** (extended stats) type of applied RPZ action */
size_t rpz_action[UB_STATS_RPZ_ACTION_NUM];
/** stats, number of queries removed due to discard-timeout */
size_t num_queries_discard_timeout;
/** stats, number of queries removed due to wait-limit */
size_t num_queries_wait_limit;
/** stats, number of dns error reports generated */
size_t num_dns_error_reports;
/** backup of query if other operations recurse and need the
* network buffers */
@@ -697,4 +708,17 @@ int mesh_jostle_exceeded(struct mesh_area* mesh);
*/
void mesh_respond_serve_expired(struct mesh_state* mstate);
/**
* Remove callback from mesh. Removes the callback from the state.
* The state itself is left to run. Searches for the pointer values.
*
* @param mesh: the mesh.
* @param qinfo: query from client.
* @param qflags: flags from client query.
* @param cb: callback function.
* @param cb_arg: callback user arg.
*/
void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg);
#endif /* SERVICES_MESH_H */
+25 -8
View File
@@ -262,12 +262,14 @@ pick_outgoing_tcp(struct pending_tcp* pend, struct waiting_tcp* w, int s)
/** get TCP file descriptor for address, returns -1 on failure,
* tcp_mss is 0 or maxseg size to set for TCP packets. */
int
outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, int dscp)
outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen,
int tcp_mss, int dscp, int nodelay)
{
int s;
int af;
char* err;
#if defined(SO_REUSEADDR) || defined(IP_BIND_ADDRESS_NO_PORT)
#if defined(SO_REUSEADDR) || defined(IP_BIND_ADDRESS_NO_PORT) \
|| defined(TCP_NODELAY)
int on = 1;
#endif
#ifdef INET6
@@ -320,6 +322,18 @@ outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss,
" setsockopt(.. IP_BIND_ADDRESS_NO_PORT ..) failed");
}
#endif /* IP_BIND_ADDRESS_NO_PORT */
if(nodelay) {
#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
if(setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void*)&on,
(socklen_t)sizeof(on)) < 0) {
verbose(VERB_ALGO, "outgoing tcp:"
" setsockopt(.. TCP_NODELAY ..) failed");
}
#else
verbose(VERB_ALGO, "outgoing tcp:"
" setsockopt(.. TCP_NODELAY ..) unsupported");
#endif /* defined(IPPROTO_TCP) && defined(TCP_NODELAY) */
}
return s;
}
@@ -649,7 +663,8 @@ outnet_tcp_take_into_use(struct waiting_tcp* w)
}
/* open socket */
s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss, w->outnet->ip_dscp);
s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss,
w->outnet->ip_dscp, w->ssl_upstream);
if(s == -1)
return 0;
@@ -1054,7 +1069,7 @@ reuse_move_writewait_away(struct outside_network* outnet,
if(verbosity >= VERB_CLIENT && pend->query->pkt_len > 12+2+2 &&
LDNS_QDCOUNT(pend->query->pkt) > 0 &&
dname_valid(pend->query->pkt+12, pend->query->pkt_len-12)) {
char buf[LDNS_MAX_DOMAINLEN+1];
char buf[LDNS_MAX_DOMAINLEN];
dname_str(pend->query->pkt+12, buf);
verbose(VERB_CLIENT, "reuse_move_writewait_away current %s %d bytes were written",
buf, (int)pend->c->tcp_write_byte_count);
@@ -1079,7 +1094,7 @@ reuse_move_writewait_away(struct outside_network* outnet,
if(verbosity >= VERB_CLIENT && w->pkt_len > 12+2+2 &&
LDNS_QDCOUNT(w->pkt) > 0 &&
dname_valid(w->pkt+12, w->pkt_len-12)) {
char buf[LDNS_MAX_DOMAINLEN+1];
char buf[LDNS_MAX_DOMAINLEN];
dname_str(w->pkt+12, buf);
verbose(VERB_CLIENT, "reuse_move_writewait_away item %s", buf);
}
@@ -2825,7 +2840,7 @@ serviced_perturb_qname(struct ub_randstate* rnd, uint8_t* qbuf, size_t len)
lablen = *d++;
}
if(verbosity >= VERB_ALGO) {
char buf[LDNS_MAX_DOMAINLEN+1];
char buf[LDNS_MAX_DOMAINLEN];
dname_str(qbuf+10, buf);
verbose(VERB_ALGO, "qname perturbed to %s", buf);
}
@@ -3718,7 +3733,8 @@ outnet_comm_point_for_tcp(struct outside_network* outnet,
sldns_buffer* query, int timeout, int ssl, char* host)
{
struct comm_point* cp;
int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp);
int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss,
outnet->ip_dscp, ssl);
if(fd == -1) {
return 0;
}
@@ -3793,7 +3809,8 @@ outnet_comm_point_for_http(struct outside_network* outnet,
{
/* cp calls cb with err=NETEVENT_DONE when transfer is done */
struct comm_point* cp;
int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp);
int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss,
outnet->ip_dscp, ssl);
if(fd == -1) {
return 0;
}
+4 -2
View File
@@ -743,9 +743,11 @@ void reuse_write_wait_remove(struct reuse_tcp* reuse, struct waiting_tcp* w);
void reuse_write_wait_push_back(struct reuse_tcp* reuse, struct waiting_tcp* w);
/** get TCP file descriptor for address, returns -1 on failure,
* tcp_mss is 0 or maxseg size to set for TCP packets. */
* tcp_mss is 0 or maxseg size to set for TCP packets,
* nodelay (TCP_NODELAY) should be set for TLS connections to speed up the TLS
* handshake.*/
int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen,
int tcp_mss, int dscp);
int tcp_mss, int dscp, int nodelay);
/**
* Create udp commpoint suitable for sending packets to the destination.
+36 -7
View File
@@ -666,7 +666,7 @@ rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname,
int newzone = 0;
if(a == RPZ_INVALID_ACTION) {
char str[255+1];
char str[LDNS_MAX_DOMAINLEN];
if(rrtype == LDNS_RR_TYPE_SOA || rrtype == LDNS_RR_TYPE_NS ||
rrtype == LDNS_RR_TYPE_DNAME ||
rrtype == LDNS_RR_TYPE_DNSKEY ||
@@ -739,7 +739,7 @@ rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname,
static void
rpz_log_dname(char const* msg, uint8_t* dname, size_t dname_len)
{
char buf[LDNS_MAX_DOMAINLEN+1];
char buf[LDNS_MAX_DOMAINLEN];
(void)dname_len;
dname_str(dname, buf);
verbose(VERB_ALGO, "rpz: %s: <%s>", msg, buf);
@@ -1062,7 +1062,7 @@ rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
if(a == RPZ_INVALID_ACTION ||
rpz_action_to_respip_action(a) == respip_invalid) {
char str[255+1];
char str[LDNS_MAX_DOMAINLEN];
dname_str(dname, str);
verbose(VERB_ALGO, "rpz: respip trigger, %s skipping unsupported action: %s",
str, rpz_action_to_string(a));
@@ -1633,7 +1633,7 @@ log_rpz_apply(char* trigger, uint8_t* dname, struct addr_tree_node* addrnode,
struct comm_reply* repinfo, struct module_qstate* ms, char* log_name)
{
char ip[128], txt[512], portstr[32];
char dnamestr[LDNS_MAX_DOMAINLEN+1];
char dnamestr[LDNS_MAX_DOMAINLEN];
uint16_t port = 0;
if(dname) {
dname_str(dname, dnamestr);
@@ -2427,7 +2427,8 @@ rpz_delegation_point_zone_lookup(struct delegpt* dp, struct local_zones* zones,
match->dname = nameserver->name;
match->dname_len = nameserver->namelen;
if(verbosity >= VERB_ALGO) {
char nm[255+1], zn[255+1];
char nm[LDNS_MAX_DOMAINLEN];
char zn[LDNS_MAX_DOMAINLEN];
dname_str(match->dname, nm);
dname_str(z->name, zn);
if(strcmp(nm, zn) != 0)
@@ -2581,7 +2582,7 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
}
if(verbosity >= VERB_ALGO) {
char nm[255+1], zn[255+1];
char nm[LDNS_MAX_DOMAINLEN], zn[LDNS_MAX_DOMAINLEN];
dname_str(is->qchase.qname, nm);
dname_str(z->name, zn);
if(strcmp(zn, nm) != 0)
@@ -2758,7 +2759,7 @@ rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
}
if(verbosity >= VERB_ALGO) {
char nm[255+1], zn[255+1];
char nm[LDNS_MAX_DOMAINLEN], zn[LDNS_MAX_DOMAINLEN];
dname_str(qinfo->qname, nm);
dname_str(z->name, zn);
if(strcmp(zn, nm) != 0)
@@ -2791,3 +2792,31 @@ void rpz_disable(struct rpz* r)
return;
r->disabled = 1;
}
/** Get memory usage for clientip_synthesized_rrset. Ignores memory usage
* of locks. */
static size_t
rpz_clientip_synthesized_set_get_mem(struct clientip_synthesized_rrset* set)
{
size_t m = sizeof(*set);
lock_rw_rdlock(&set->lock);
m += regional_get_mem(set->region);
lock_rw_unlock(&set->lock);
return m;
}
size_t rpz_get_mem(struct rpz* r)
{
size_t m = sizeof(*r);
if(r->taglist)
m += r->taglistlen;
if(r->log_name)
m += strlen(r->log_name) + 1;
m += regional_get_mem(r->region);
m += local_zones_get_mem(r->local_zones);
m += local_zones_get_mem(r->nsdname_zones);
m += respip_set_get_mem(r->respip_set);
m += rpz_clientip_synthesized_set_get_mem(r->client_set);
m += rpz_clientip_synthesized_set_get_mem(r->ns_set);
return m;
}
+7
View File
@@ -269,4 +269,11 @@ void rpz_enable(struct rpz* r);
*/
void rpz_disable(struct rpz* r);
/**
* Get memory usage of rpz. Caller must manage locks.
* @param r: RPZ struct.
* @return memory usage.
*/
size_t rpz_get_mem(struct rpz* r);
#endif /* SERVICES_RPZ_H */
+36 -5
View File
@@ -43,6 +43,7 @@
#include "services/view.h"
#include "services/localzone.h"
#include "util/config_file.h"
#include "respip/respip.h"
int
view_cmp(const void* v1, const void* v2)
@@ -66,11 +67,6 @@ views_create(void)
return v;
}
/* \noop (ignore this comment for doxygen)
* This prototype is defined in in respip.h, but we want to avoid
* unnecessary dependencies */
void respip_set_delete(struct respip_set *set);
void
view_delete(struct view* v)
{
@@ -247,3 +243,38 @@ void views_print(struct views* v)
/* TODO implement print */
(void)v;
}
size_t views_get_mem(struct views* vs)
{
struct view* v;
size_t m;
if(!vs) return 0;
m = sizeof(struct views);
lock_rw_rdlock(&vs->lock);
RBTREE_FOR(v, struct view*, &vs->vtree) {
m += view_get_mem(v);
}
lock_rw_unlock(&vs->lock);
return m;
}
size_t view_get_mem(struct view* v)
{
size_t m = sizeof(*v);
lock_rw_rdlock(&v->lock);
m += getmem_str(v->name);
m += local_zones_get_mem(v->local_zones);
m += respip_set_get_mem(v->respip_set);
lock_rw_unlock(&v->lock);
return m;
}
void views_swap_tree(struct views* vs, struct views* data)
{
rbnode_type* oldroot = vs->vtree.root;
size_t oldcount = vs->vtree.count;
vs->vtree.root = data->vtree.root;
vs->vtree.count = data->vtree.count;
data->vtree.root = oldroot;
data->vtree.count = oldcount;
}
+25 -1
View File
@@ -54,7 +54,8 @@ struct respip_set;
* Views storage, shared.
*/
struct views {
/** lock on the view tree */
/** lock on the view tree. When locking order, the views lock
* is before the forwards,hints,anchors,localzones lock. */
lock_rw_type lock;
/** rbtree of struct view */
rbtree_type vtree;
@@ -135,4 +136,27 @@ void views_print(struct views* v);
*/
struct view* views_find_view(struct views* vs, const char* name, int write);
/**
* Calculate memory usage of views.
* @param vs: the views tree. The routine locks and unlocks the structure
* for reading.
* @return memory in bytes.
*/
size_t views_get_mem(struct views* vs);
/**
* Calculate memory usage of view.
* @param v: the view. The routine locks and unlocks the structure for reading.
* @return memory in bytes.
*/
size_t view_get_mem(struct view* v);
/**
* Swap internal tree with preallocated entries. Caller should manage
* the locks.
* @param vs: views tree
* @param data: preallocated information.
*/
void views_swap_tree(struct views* vs, struct views* data);
#endif /* SERVICES_VIEW_H */
+2
View File
@@ -195,6 +195,7 @@ void sldns_key_EVP_unload_gost(void)
}
#endif /* USE_GOST */
#ifdef USE_DSA
/* Retrieve params as BIGNUM from raw buffer */
static int
sldns_key_dsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** p,
@@ -370,6 +371,7 @@ EVP_PKEY *sldns_key_dsa2pkey_raw(unsigned char* key, size_t len)
return evp_key;
#endif
}
#endif /* USE_DSA */
/* Retrieve params as BIGNUM from raw buffer, n is modulus, e is exponent */
static int
+8 -2
View File
@@ -72,7 +72,7 @@ static const sldns_rdf_type type_nsap_wireformat[] = {
LDNS_RDF_TYPE_NSAP
};
static const sldns_rdf_type type_nsap_ptr_wireformat[] = {
LDNS_RDF_TYPE_STR
LDNS_RDF_TYPE_UNQUOTED
};
static const sldns_rdf_type type_sig_wireformat[] = {
LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32,
@@ -86,7 +86,7 @@ static const sldns_rdf_type type_px_wireformat[] = {
LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
};
static const sldns_rdf_type type_gpos_wireformat[] = {
LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR
LDNS_RDF_TYPE_UNQUOTED, LDNS_RDF_TYPE_UNQUOTED, LDNS_RDF_TYPE_UNQUOTED
};
static const sldns_rdf_type type_aaaa_wireformat[] = { LDNS_RDF_TYPE_AAAA };
static const sldns_rdf_type type_loc_wireformat[] = { LDNS_RDF_TYPE_LOC };
@@ -617,6 +617,12 @@ static sldns_rr_descriptor rdata_field_descriptors[] = {
{(enum sldns_enum_rr_type)0, "TYPE258", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
#endif
{(enum sldns_enum_rr_type)0, "TYPE259", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
{(enum sldns_enum_rr_type)0, "TYPE260", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
/* 261 */
{LDNS_RR_TYPE_RESINFO, "RESINFO", 1, 0, NULL, LDNS_RDF_TYPE_UNQUOTED, LDNS_RR_NO_COMPRESS, 0 },
/* split in array, no longer contiguous */
#ifdef DRAFT_RRTYPES
+6
View File
@@ -229,6 +229,8 @@ enum sldns_enum_rr_type
LDNS_RR_TYPE_CAA = 257, /* RFC 6844 */
LDNS_RR_TYPE_AVC = 258,
LDNS_RR_TYPE_RESINFO = 261, /* RFC 9606 */
/** DNSSEC Trust Authorities */
LDNS_RR_TYPE_TA = 32768,
/* RFC 4431, 5074, DNSSEC Lookaside Validation */
@@ -341,6 +343,9 @@ enum sldns_enum_rdf_type
/** 8 * 8 bit hex numbers separated by dashes. For EUI64. */
LDNS_RDF_TYPE_EUI64,
/** Character string without quotes. */
LDNS_RDF_TYPE_UNQUOTED,
/** A non-zero sequence of US-ASCII letters and numbers in lower case.
* For CAA.
*/
@@ -438,6 +443,7 @@ enum sldns_enum_edns_option
LDNS_EDNS_PADDING = 12, /* RFC7830 */
LDNS_EDNS_EDE = 15, /* RFC8914 */
LDNS_EDNS_CLIENT_TAG = 16, /* draft-bellis-dnsop-edns-tags-01 */
LDNS_EDNS_REPORT_CHANNEL = 18, /* RFC9567 */
LDNS_EDNS_UNBOUND_CACHEDB_TESTFRAME_TEST = 65534
};
typedef enum sldns_enum_edns_option sldns_edns_option;
+46 -8
View File
@@ -365,7 +365,8 @@ static int
sldns_rdf_type_maybe_quoted(sldns_rdf_type rdf_type)
{
return rdf_type == LDNS_RDF_TYPE_STR ||
rdf_type == LDNS_RDF_TYPE_LONG_STR;
rdf_type == LDNS_RDF_TYPE_LONG_STR ||
rdf_type == LDNS_RDF_TYPE_UNQUOTED;
}
/** see if rdata is quoted */
@@ -1719,6 +1720,8 @@ int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len,
return sldns_str2wire_eui48_buf(str, rd, len);
case LDNS_RDF_TYPE_EUI64:
return sldns_str2wire_eui64_buf(str, rd, len);
case LDNS_RDF_TYPE_UNQUOTED:
return sldns_str2wire_unquoted_buf(str, rd, len);
case LDNS_RDF_TYPE_TAG:
return sldns_str2wire_tag_buf(str, rd, len);
case LDNS_RDF_TYPE_LONG_STR:
@@ -2554,12 +2557,42 @@ int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len)
{
const char* s = str;
size_t slen = strlen(str);
size_t dlen = 0; /* number of hexdigits parsed */
size_t dlen = 0; /* number of hexdigits parsed for hex,
digits for E.164 */
/* just a hex string with optional dots? */
/* notimpl e.164 format */
if(slen > LDNS_MAX_RDFLEN*2)
return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW;
if(*len < 1)
return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
if(*s == 0) {
/* empty string */
rd[0] = 0;
*len = 1;
return LDNS_WIREPARSE_ERR_OK;
}
if(s[0] == '+') {
rd[0] = 1; /* E.164 format */
/* digits '0'..'9', with skipped dots. */
s++;
while(*s) {
if(isspace((unsigned char)*s) || *s == '.') {
s++;
continue;
}
if(*s < '0' || *s > '9')
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-str);
if(*len < dlen + 2)
return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
s-str);
rd[dlen+1] = *s++;
dlen++;
}
*len = dlen+1;
return LDNS_WIREPARSE_ERR_OK;
}
rd[0] = 0; /* AESA format */
/* hex, with skipped dots. */
while(*s) {
if(isspace((unsigned char)*s) || *s == '.') {
s++;
@@ -2567,17 +2600,17 @@ int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len)
}
if(!isxdigit((unsigned char)*s))
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str);
if(*len < dlen/2 + 1)
if(*len < dlen/2 + 2)
return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
s-str);
if((dlen&1)==0)
rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16;
else rd[dlen/2] += sldns_hexdigit_to_int(*s++);
rd[dlen/2 + 1] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16;
else rd[dlen/2 + 1] += sldns_hexdigit_to_int(*s++);
dlen++;
}
if((dlen&1)!=0)
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str);
*len = dlen/2;
*len = dlen/2 + 1;
return LDNS_WIREPARSE_ERR_OK;
}
@@ -2746,6 +2779,11 @@ int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len)
return LDNS_WIREPARSE_ERR_OK;
}
int sldns_str2wire_unquoted_buf(const char* str, uint8_t* rd, size_t* len)
{
return sldns_str2wire_str_buf(str, rd, len);
}
int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len)
{
size_t slen = strlen(str);
+9
View File
@@ -551,6 +551,15 @@ int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len);
*/
int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len);
/**
* Convert rdf of type LDNS_RDF_TYPE_UNQUOTED from string to wireformat.
* @param str: the text to convert for this rdata element.
* @param rd: rdata buffer for the wireformat.
* @param len: length of rd buffer on input, used length on output.
* @return 0 on success, error on failure.
*/
int sldns_str2wire_unquoted_buf(const char* str, uint8_t* rd, size_t* len);
/**
* Convert rdf of type LDNS_RDF_TYPE_TAG from string to wireformat.
* @param str: the text to convert for this rdata element.
+49 -1
View File
@@ -1344,6 +1344,8 @@ int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
return sldns_wire2str_eui48_scan(d, dlen, s, slen);
case LDNS_RDF_TYPE_EUI64:
return sldns_wire2str_eui64_scan(d, dlen, s, slen);
case LDNS_RDF_TYPE_UNQUOTED:
return sldns_wire2str_unquoted_scan(d, dlen, s, slen);
case LDNS_RDF_TYPE_TAG:
return sldns_wire2str_tag_scan(d, dlen, s, slen);
case LDNS_RDF_TYPE_LONG_STR:
@@ -1870,7 +1872,33 @@ int sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
int sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
{
return print_remainder_hex("", d, dl, s, sl);
uint8_t format;
int w = 0;
size_t i;
if(*dl < 1) return -1;
format = (*d)[0];
(*d)+=1;
(*dl)-=1;
if(format == 0) {
/* AESA format (ATM End System Address). */
return print_remainder_hex("", d, dl, s, sl);
} else if(format == 1) {
/* E.164 format. */
w += sldns_str_print(s, sl, "+");
for(i=0; i<*dl; i++) {
if((*d)[i] < '0' || (*d)[0] > '9')
return -1;
w += sldns_str_print(s, sl, "%c", (*d)[i]);
}
(*d) += *dl;
(*dl) = 0;
} else {
/* Unknown format. */
return -1;
}
return w;
}
/* internal scan routine that can modify arguments on failure */
@@ -2021,6 +2049,26 @@ int sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
return w;
}
int sldns_wire2str_unquoted_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
{
int w = 0;
size_t i, len;
if(*dl < 1) return -1;
len = **d;
if(*dl < 1+len) return -1;
(*d)++;
(*dl)--;
for(i=0; i<len; i++) {
if(isspace((unsigned char)(*d)[i]) || (*d)[i] == '(' ||
(*d)[i] == ')' || (*d)[i] == '\'')
w += sldns_str_print(s, sl, "\\%c", (char)(*d)[i]);
else w += str_char_print(s, sl, (*d)[i]);
}
(*d)+=len;
(*dl)-=len;
return w;
}
int sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
{
size_t i, n;
+13
View File
@@ -919,6 +919,19 @@ int sldns_wire2str_eui48_scan(uint8_t** data, size_t* data_len, char** str,
int sldns_wire2str_eui64_scan(uint8_t** data, size_t* data_len, char** str,
size_t* str_len);
/**
* Scan wireformat UNQUOTED field to string, with user buffers.
* It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
* @param data: wireformat data.
* @param data_len: length of data buffer.
* @param str: string buffer.
* @param str_len: length of string buffer.
* @return number of characters (except null) needed to print.
* Can return -1 on failure.
*/
int sldns_wire2str_unquoted_scan(uint8_t** data, size_t* data_len, char** str,
size_t* str_len);
/**
* Scan wireformat TAG field to string, with user buffers.
* It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+7 -5
View File
@@ -342,8 +342,6 @@ interfacechecks(struct config_file* cfg)
int i, j, i2, j2;
char*** resif = NULL;
int* num_resif = NULL;
char portbuf[32];
snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
if(cfg->num_ifs != 0) {
resif = (char***)calloc(cfg->num_ifs, sizeof(char**));
@@ -366,15 +364,19 @@ interfacechecks(struct config_file* cfg)
cfg->ifs[i]);
}
/* check for port combinations that are not supported */
if(if_is_pp2(resif[i][0], portbuf, cfg->proxy_protocol_port)) {
if(if_is_dnscrypt(resif[i][0], portbuf,
if(if_is_pp2(resif[i][0], cfg->port, cfg->proxy_protocol_port)) {
if(if_is_dnscrypt(resif[i][0], cfg->port,
cfg->dnscrypt_port)) {
fatal_exit("PROXYv2 and DNSCrypt combination not "
"supported!");
} else if(if_is_https(resif[i][0], portbuf,
} else if(if_is_https(resif[i][0], cfg->port,
cfg->https_port)) {
fatal_exit("PROXYv2 and DoH combination not "
"supported!");
} else if(if_is_quic(resif[i][0], cfg->port,
cfg->quic_port)) {
fatal_exit("PROXYv2 and DoQ combination not "
"supported!");
}
}
/* search for duplicates in the returned addresses */
+2 -1
View File
@@ -204,7 +204,8 @@ fi
# remove unused permissions
chmod o-rw \
"$SVR_BASE.pem" \
"$SVR_BASE.key" \
"$SVR_BASE.key"
chmod g+r,o-rw \
"$CTL_BASE.pem" \
"$CTL_BASE.key"
+19 -5
View File
@@ -109,6 +109,16 @@ usage(void)
printf(" That means the caches sizes and\n");
printf(" the number of threads must not\n");
printf(" change between reloads.\n");
printf(" fast_reload [+dpv] reloads the server but only briefly stops\n");
printf(" server processing, keeps cache, and changes\n");
printf(" most options; check unbound-control(8).\n");
printf(" +d drops running queries to keep consistency\n");
printf(" on changed options while reloading.\n");
printf(" +p does not pause threads for even faster\n");
printf(" reload but less options are supported\n");
printf(" ; check unbound-control(8).\n");
printf(" +v verbose output, it will include duration needed.\n");
printf(" +vv more verbose output, it will include memory needed.\n");
printf(" stats print statistics\n");
printf(" stats_noreset peek at statistics\n");
#ifdef HAVE_SHMGET
@@ -222,6 +232,9 @@ static void pr_stats(const char* nm, struct ub_stats_info* s)
s->svr.num_queries_cookie_client);
PR_UL_NM("num.queries_cookie_invalid",
s->svr.num_queries_cookie_invalid);
PR_UL_NM("num.queries_discard_timeout",
s->svr.num_queries_discard_timeout);
PR_UL_NM("num.queries_wait_limit", s->svr.num_queries_wait_limit);
PR_UL_NM("num.cachehits",
s->svr.num_queries - s->svr.num_queries_missed_cache);
PR_UL_NM("num.cachemiss", s->svr.num_queries_missed_cache);
@@ -231,12 +244,13 @@ static void pr_stats(const char* nm, struct ub_stats_info* s)
PR_UL_NM("num.expired", s->svr.ans_expired);
PR_UL_NM("num.recursivereplies", s->mesh_replies_sent);
#ifdef USE_DNSCRYPT
PR_UL_NM("num.dnscrypt.crypted", s->svr.num_query_dnscrypt_crypted);
PR_UL_NM("num.dnscrypt.cert", s->svr.num_query_dnscrypt_cert);
PR_UL_NM("num.dnscrypt.cleartext", s->svr.num_query_dnscrypt_cleartext);
PR_UL_NM("num.dnscrypt.malformed",
s->svr.num_query_dnscrypt_crypted_malformed);
PR_UL_NM("num.dnscrypt.crypted", s->svr.num_query_dnscrypt_crypted);
PR_UL_NM("num.dnscrypt.cert", s->svr.num_query_dnscrypt_cert);
PR_UL_NM("num.dnscrypt.cleartext", s->svr.num_query_dnscrypt_cleartext);
PR_UL_NM("num.dnscrypt.malformed",
s->svr.num_query_dnscrypt_crypted_malformed);
#endif /* USE_DNSCRYPT */
PR_UL_NM("num.dns_error_reports", s->svr.num_dns_error_reports);
printf("%s.requestlist.avg"SQ"%g\n", nm,
(s->svr.num_queries_missed_cache+s->svr.num_queries_prefetch)?
(double)s->svr.sum_query_list_size/
+14
View File
@@ -256,6 +256,20 @@ void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
}
#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))
+18 -4
View File
@@ -64,6 +64,9 @@ static int key_deleted = 0;
static ub_thread_key_type thr_debug_key;
/** the list of threads, so all threads can be examined. NULL if unused. */
static struct thr_check* thread_infos[THRDEBUG_MAX_THREADS];
/** stored maximum lock number for threads, when a thread is restarted the
* number is kept track of, because the new locks get new id numbers. */
static int thread_lockcount[THRDEBUG_MAX_THREADS];
/** do we check locking order */
int check_locking_order = 1;
/** the pid of this runset, reasonably unique. */
@@ -698,10 +701,20 @@ open_lockorder(struct thr_check* thr)
char buf[24];
time_t t;
snprintf(buf, sizeof(buf), "%s.%d", output_name, thr->num);
thr->order_info = fopen(buf, "w");
if(!thr->order_info)
fatal_exit("could not open %s: %s", buf, strerror(errno));
thr->locks_created = 0;
thr->locks_created = thread_lockcount[thr->num];
if(thr->locks_created == 0) {
thr->order_info = fopen(buf, "w");
if(!thr->order_info)
fatal_exit("could not open %s: %s", buf, strerror(errno));
} else {
/* There is already a file to append on with the previous
* thread information. */
thr->order_info = fopen(buf, "a");
if(!thr->order_info)
fatal_exit("could not open for append %s: %s", buf, strerror(errno));
return;
}
t = time(NULL);
/* write: <time_stamp> <runpid> <thread_num> */
if(fwrite(&t, sizeof(t), 1, thr->order_info) != 1 ||
@@ -728,6 +741,7 @@ static void* checklock_main(void* arg)
if(check_locking_order)
open_lockorder(thr);
ret = thr->func(thr->arg);
thread_lockcount[thr->num] = thr->locks_created;
thread_infos[thr->num] = NULL;
if(check_locking_order)
fclose(thr->order_info);
+2
View File
@@ -17,6 +17,7 @@ NEED_IPV6='fwd_ancil.tdir fwd_tcp_tc6.tdir stub_udp6.tdir edns_cache.tdir'
NEED_NOMINGW='tcp_sigpipe.tdir 07-confroot.tdir 08-host-lib.tdir fwd_ancil.tdir'
NEED_DNSCRYPT_PROXY='dnscrypt_queries.tdir dnscrypt_queries_chacha.tdir'
NEED_UNSHARE='acl_interface.tdir proxy_protocol.tdir'
NEED_REDIS_SERVER='redis_replica.tdir'
# test if dig and ldns-testns are available.
test_tool_avail "dig"
@@ -52,6 +53,7 @@ for test in `ls -d *.tdir`; do
skip_if_in_list $test "$NEED_WHOAMI" "whoami"
skip_if_in_list $test "$NEED_DNSCRYPT_PROXY" "dnscrypt-proxy"
skip_if_in_list $test "$NEED_UNSHARE" "unshare"
skip_if_in_list $test "$NEED_REDIS_SERVER" "redis-server"
if echo $NEED_IPV6 | grep $test >/dev/null; then
if test "$HAVE_IPV6" = no; then
+14
View File
@@ -2699,3 +2699,17 @@ 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;
}
+31 -5
View File
@@ -938,11 +938,11 @@ listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
char* ATTR_UNUSED(http_endpoint),
int ATTR_UNUSED(http_notls),
struct tcl_list* ATTR_UNUSED(tcp_conn_limit),
void* ATTR_UNUSED(sslctx), struct dt_env* ATTR_UNUSED(dtenv),
void* ATTR_UNUSED(dot_sslctx), void* ATTR_UNUSED(doh_sslctx),
void* ATTR_UNUSED(quic_ssl),
struct dt_env* ATTR_UNUSED(dtenv),
struct doq_table* ATTR_UNUSED(table),
struct ub_randstate* ATTR_UNUSED(rnd),
const char* ATTR_UNUSED(ssl_service_key),
const char* ATTR_UNUSED(ssl_service_pem),
struct config_file* ATTR_UNUSED(cfg),
comm_point_callback_type* cb, void *cb_arg)
{
@@ -1264,7 +1264,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
struct fake_pending* pend = (struct fake_pending*)calloc(1,
sizeof(struct fake_pending));
char z[256];
char z[LDNS_MAX_DOMAINLEN];
log_assert(pend);
log_nametypeclass(VERB_OPS, "pending serviced query",
qinfo->qname, qinfo->qtype, qinfo->qclass);
@@ -1484,6 +1484,11 @@ size_t comm_point_get_mem(struct comm_point* ATTR_UNUSED(c))
return 0;
}
size_t comm_timer_get_mem(struct comm_timer* ATTR_UNUSED(timer))
{
return 0;
}
size_t serviced_get_mem(struct serviced_query* ATTR_UNUSED(c))
{
return 0;
@@ -1939,7 +1944,8 @@ int comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
}
int outnet_get_tcp_fd(struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(tcp_mss), int ATTR_UNUSED(dscp))
socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(tcp_mss),
int ATTR_UNUSED(dscp), int ATTR_UNUSED(nodelay))
{
log_assert(0);
return -1;
@@ -1993,4 +1999,24 @@ void http2_stream_remove_mesh_state(struct http2_stream* ATTR_UNUSED(h2_stream))
{
}
void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
void* ATTR_UNUSED(arg))
{
log_assert(0);
}
void fast_reload_thread_stop(
struct fast_reload_thread* ATTR_UNUSED(fast_reload_thread))
{
/* nothing */
}
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;
}
/*********** End of Dummy routines ***********/
+17
View File
@@ -601,7 +601,24 @@ void listen_desetup_locks(void)
/* nothing */
}
void fast_reload_printq_list_delete(
struct fast_reload_printq* ATTR_UNUSED(list))
{
/* nothing */
}
void fast_reload_worker_pickup_changes(struct worker* ATTR_UNUSED(worker))
{
/* nothing */
}
#ifdef HAVE_NGTCP2
void* quic_sslctx_create(char* ATTR_UNUSED(key), char* ATTR_UNUSED(pem),
char* ATTR_UNUSED(verifypem))
{
return NULL;
}
void comm_point_doq_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
void* ATTR_UNUSED(arg))
{
+147
View File
@@ -39,6 +39,7 @@
*/
#include "config.h"
#include <ctype.h>
#include "util/log.h"
#include "testcode/unitmain.h"
#include "util/data/dname.h"
@@ -858,6 +859,151 @@ dname_setup_bufs(sldns_buffer* loopbuf, sldns_buffer* boundbuf)
sldns_buffer_flip(boundbuf);
}
static void
dname_test_str(sldns_buffer* buff)
{
char result[LDNS_MAX_DOMAINLEN], expect[LDNS_MAX_DOMAINLEN], *e;
size_t i;
unit_show_func("util/data/dname.c", "dname_str");
/* root ; expected OK */
sldns_buffer_clear(buff);
sldns_buffer_write(buff, "\000", 1);
sldns_buffer_flip(buff);
unit_assert( sldns_buffer_limit(buff) == 1 );
unit_assert( pkt_dname_len(buff) == 1 );
dname_str(sldns_buffer_begin(buff), result);
unit_assert( strcmp( ".", result) == 0 );
/* LDNS_MAX_DOMAINLEN - 1 ; expected OK */
sldns_buffer_clear(buff);
sldns_buffer_write(buff,
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 64 up to here */
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 128 up to here */
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 192 up to here */
"\074abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567" /* 253 up to here */
"\000" /* 254 up to here */
, 254);
sldns_buffer_flip(buff);
unit_assert( sldns_buffer_limit(buff) == 254 );
unit_assert( pkt_dname_len(buff) == 254 );
dname_str(sldns_buffer_begin(buff), result);
unit_assert( strcmp(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567"
".", result) == 0 );
/* LDNS_MAX_DOMAINLEN ; expected OK */
sldns_buffer_clear(buff);
sldns_buffer_write(buff,
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 64 up to here */
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 128 up to here */
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 192 up to here */
"\075abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678" /* 254 up to here */
"\000" /* 255 up to here */
, 255);
sldns_buffer_flip(buff);
unit_assert( sldns_buffer_limit(buff) == 255 );
unit_assert( pkt_dname_len(buff) == 255 );
dname_str(sldns_buffer_begin(buff), result);
unit_assert( strcmp(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678"
".", result) == 0 );
/* LDNS_MAX_DOMAINLEN + 1 ; expected to fail, output uses '&' on the latest label */
sldns_buffer_clear(buff);
sldns_buffer_write(buff,
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 64 up to here */
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 128 up to here */
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 192 up to here */
"\076abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" /* 255 up to here */
"\000" /* 256 up to here */
, 256);
sldns_buffer_flip(buff);
unit_assert( sldns_buffer_limit(buff) == 256 );
unit_assert( pkt_dname_len(buff) == 0 );
dname_str(sldns_buffer_begin(buff), result);
unit_assert( strcmp(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
"&", result) == 0 );
/* LDNS_MAX_LABELLEN + 1 ; expected to fail, output uses '#' on the offending label */
sldns_buffer_clear(buff);
sldns_buffer_write(buff,
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 64 up to here */
"\100abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890a" /* 129 up to here */
"\000" /* 130 up to here */
, 130);
sldns_buffer_flip(buff);
unit_assert( sldns_buffer_limit(buff) == 130 );
unit_assert( pkt_dname_len(buff) == 0 );
dname_str(sldns_buffer_begin(buff), result);
unit_assert( strcmp(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
"#", result) == 0 );
/* LDNS_MAX_DOMAINLEN with single labels; expected OK */
sldns_buffer_clear(buff);
for(i=0; i<=252; i+=2)
sldns_buffer_write(buff, "\001a", 2);
sldns_buffer_write_u8(buff, 0);
sldns_buffer_flip(buff);
unit_assert( sldns_buffer_limit(buff) == 255 );
unit_assert( pkt_dname_len(buff) == 255 );
dname_str(sldns_buffer_begin(buff), result);
e = expect;
for(i=0; i<=252; i+=2) {
*e++ = 'a';
*e++ = '.';
}
*e = '\0';
unit_assert( strcmp(expect, result) == 0 );
/* LDNS_MAX_DOMAINLEN + 1 with single labels; expected to fail, output uses '&' on the latest label */
sldns_buffer_clear(buff);
for(i=0; i<=250; i+=2)
sldns_buffer_write(buff, "\001a", 2);
sldns_buffer_write(buff, "\002ab", 3);
sldns_buffer_write_u8(buff, 0);
sldns_buffer_flip(buff);
unit_assert( sldns_buffer_limit(buff) == 256 );
unit_assert( pkt_dname_len(buff) == 0 );
dname_str(sldns_buffer_begin(buff), result);
e = expect;
for(i=0; i<=250; i+=2) {
*e++ = 'a';
*e++ = '.';
}
*e++ = '&';
*e = '\0';
unit_assert( strcmp(expect, result) == 0 );
/* Only alphas, numericals and '-', '_' and '*' are allowed in the output */
for(i=1; i<=255; i++) {
if(isalnum(i) || i == '-' || i == '_' || i == '*')
continue;
sldns_buffer_clear(buff);
sldns_buffer_write_u8(buff, 1);
sldns_buffer_write_u8(buff, (uint8_t)i);
sldns_buffer_write_u8(buff, 0);
sldns_buffer_flip(buff);
unit_assert( sldns_buffer_limit(buff) == 3 );
unit_assert( pkt_dname_len(buff) == 3);
dname_str(sldns_buffer_begin(buff), result);
if(strcmp( "?.", result) != 0 ) {
log_err("ASCII value '0x%lX' allowed in string output", (unsigned long)i);
unit_assert(0);
}
}
}
void dname_test(void)
{
sldns_buffer* loopbuf = sldns_buffer_new(14);
@@ -884,6 +1030,7 @@ void dname_test(void)
dname_test_topdomain();
dname_test_valid();
dname_test_has_label();
dname_test_str(buff);
sldns_buffer_free(buff);
sldns_buffer_free(loopbuf);
sldns_buffer_free(boundbuf);
+209
View File
@@ -0,0 +1,209 @@
/*
* testcode/unitinfra.c - unit test for infra cache.
*
* Copyright (c) 2025, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* \file
* Tests the infra functionality.
*/
#include "config.h"
#include "testcode/unitmain.h"
#include "iterator/iterator.h"
#include "services/cache/infra.h"
#include "util/config_file.h"
#include "util/net_help.h"
/* lookup and get key and data structs easily */
static struct infra_data* infra_lookup_host(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, int wr, time_t now, struct infra_key** k)
{
struct infra_data* d;
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
zone, zonelen, wr);
if(!e) return NULL;
d = (struct infra_data*)e->data;
if(d->ttl < now) {
lock_rw_unlock(&e->lock);
return NULL;
}
*k = (struct infra_key*)e->key;
return d;
}
static void test_keep_probing(struct infra_cache* slab,
struct config_file* cfg, struct sockaddr_storage one, socklen_t onelen,
uint8_t* zone, size_t zonelen, time_t *now, int keep_probing,
int rtt_max_timeout)
{
uint8_t edns_lame;
int vs, to, lame, dnsseclame, reclame, probedelay;
struct infra_key* k;
struct infra_data* d;
/* configure */
cfg->infra_cache_max_rtt = rtt_max_timeout;
config_apply_max_rtt(rtt_max_timeout);
slab->infra_keep_probing = keep_probing;
/* expired previous entry */
*now += cfg->host_ttl + 10;
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
*now, &vs, &edns_lame, &to) );
/* simulate timeouts until the USEFUL_SERVER_TOP_TIMEOUT is reached */
while(to < USEFUL_SERVER_TOP_TIMEOUT) {
unit_assert( infra_rtt_update(slab, &one, onelen, zone, zonelen,
LDNS_RR_TYPE_A, -1, to, *now) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
*now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to <= USEFUL_SERVER_TOP_TIMEOUT && edns_lame == 0 );
}
unit_assert( vs == 0 && to == USEFUL_SERVER_TOP_TIMEOUT && edns_lame == 0 );
/* don't let the record expire */
unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, *now, &k)) );
unit_assert( d->timeout_A >= TIMEOUT_COUNT_MAX );
unit_assert( d->probedelay > 0 );
probedelay = d->probedelay;
lock_rw_unlock(&k->entry.lock);
cfg->host_ttl = cfg->host_ttl + *now < probedelay
?cfg->host_ttl :probedelay + 10;
/* advance time and check that probing is as expected; we already had a
* lot of A timeouts (checked above). */
*now = probedelay;
unit_assert( infra_get_lame_rtt(slab, &one, onelen, zone, zonelen,
LDNS_RR_TYPE_A, &lame, &dnsseclame, &reclame, &to, *now) );
unit_assert( lame == 0 && dnsseclame == 0 && reclame == 0
&& to == keep_probing ?still_useful_timeout() :USEFUL_SERVER_TOP_TIMEOUT);
}
/** test host cache */
void infra_test(void)
{
struct sockaddr_storage one;
socklen_t onelen;
uint8_t* zone = (uint8_t*)"\007example\003com\000";
size_t zonelen = 13;
struct infra_cache* slab;
struct config_file* cfg = config_create();
time_t now = 0;
uint8_t edns_lame;
int vs, to;
struct infra_key* k;
struct infra_data* d;
int init = UNKNOWN_SERVER_NICENESS;
int default_max_rtt = USEFUL_SERVER_TOP_TIMEOUT;
unit_show_feature("infra cache");
unit_assert(ipstrtoaddr("127.0.0.1", 53, &one, &onelen));
slab = infra_create(cfg);
/* insert new record */
unit_assert( infra_host(slab, &one, onelen, zone, zonelen, now,
&vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 0 );
/* simulate no answer */
unit_assert( infra_rtt_update(slab, &one, onelen, zone, zonelen, LDNS_RR_TYPE_A, -1, init, now) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init*2 && edns_lame == 0 );
/* simulate EDNS lame */
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == -1 && to == init*2 && edns_lame == 1);
/* simulate cache expiry */
now += cfg->host_ttl + 10;
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 0 );
/* simulate no lame answer */
unit_assert( infra_set_lame(slab, &one, onelen,
zone, zonelen, now, 0, 0, LDNS_RR_TYPE_A) );
unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
unit_assert( d->ttl == now+cfg->host_ttl );
unit_assert( d->edns_version == 0 );
unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
!d->lame_other);
lock_rw_unlock(&k->entry.lock);
/* test merge of data */
unit_assert( infra_set_lame(slab, &one, onelen,
zone, zonelen, now, 0, 0, LDNS_RR_TYPE_AAAA) );
unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
d->lame_other);
lock_rw_unlock(&k->entry.lock);
/* test that noEDNS cannot overwrite known-yesEDNS */
now += cfg->host_ttl + 10;
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 0 );
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, 0, now) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 1 );
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 1 );
unit_show_feature("infra cache probing (keep-probing off, default infra-cache-max-rtt)");
test_keep_probing(slab, cfg, one, onelen, zone, zonelen, &now, 0, default_max_rtt);
unit_show_feature("infra cache probing (keep-probing on, default infra-cache-max-rtt)");
test_keep_probing(slab, cfg, one, onelen, zone, zonelen, &now, 1, default_max_rtt);
unit_show_feature("infra cache probing (keep-probing off, low infra-cache-max-rtt)");
test_keep_probing(slab, cfg, one, onelen, zone, zonelen, &now, 0, 3000);
unit_show_feature("infra cache probing (keep-probing on, low infra-cache-max-rtt)");
test_keep_probing(slab, cfg, one, onelen, zone, zonelen, &now, 1, 3000);
/* Re-apply defaults for other unit tests that follow */
config_apply_max_rtt(default_max_rtt);
infra_delete(slab);
config_delete(cfg);
}
+6 -2
View File
@@ -172,10 +172,14 @@ rr_test_file(const char* input, const char* check)
if(txt_in[0] == 0 || txt_in[0] == '\n' || txt_in[0] == ';')
continue;
/* read check lines */
if(!fgets(wire_chk, (int)bufs, chf))
if(!fgets(wire_chk, (int)bufs, chf)) {
printf("%s too short\n", check);
if(!fgets(txt_chk, (int)bufs, chf))
unit_assert(0);
}
if(!fgets(txt_chk, (int)bufs, chf)) {
printf("%s too short\n", check);
unit_assert(0);
}
chlineno += 2;
if(vbmp) printf("%s:%d %s", check, chlineno-1, wire_chk);
if(vbmp) printf("%s:%d %s", check, chlineno, txt_chk);
-97
View File
@@ -433,103 +433,6 @@ rtt_test(void)
unit_assert(UB_STATS_BUCKET_NUM == NUM_BUCKETS_HIST);
}
#include "services/cache/infra.h"
/* lookup and get key and data structs easily */
static struct infra_data* infra_lookup_host(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, int wr, time_t now, struct infra_key** k)
{
struct infra_data* d;
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
zone, zonelen, wr);
if(!e) return NULL;
d = (struct infra_data*)e->data;
if(d->ttl < now) {
lock_rw_unlock(&e->lock);
return NULL;
}
*k = (struct infra_key*)e->key;
return d;
}
/** test host cache */
static void
infra_test(void)
{
struct sockaddr_storage one;
socklen_t onelen;
uint8_t* zone = (uint8_t*)"\007example\003com\000";
size_t zonelen = 13;
struct infra_cache* slab;
struct config_file* cfg = config_create();
time_t now = 0;
uint8_t edns_lame;
int vs, to;
struct infra_key* k;
struct infra_data* d;
int init = 376;
unit_show_feature("infra cache");
unit_assert(ipstrtoaddr("127.0.0.1", 53, &one, &onelen));
slab = infra_create(cfg);
unit_assert( infra_host(slab, &one, onelen, zone, zonelen, now,
&vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 0 );
unit_assert( infra_rtt_update(slab, &one, onelen, zone, zonelen, LDNS_RR_TYPE_A, -1, init, now) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init*2 && edns_lame == 0 );
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == -1 && to == init*2 && edns_lame == 1);
now += cfg->host_ttl + 10;
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 0 );
unit_assert( infra_set_lame(slab, &one, onelen,
zone, zonelen, now, 0, 0, LDNS_RR_TYPE_A) );
unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
unit_assert( d->ttl == now+cfg->host_ttl );
unit_assert( d->edns_version == 0 );
unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
!d->lame_other);
lock_rw_unlock(&k->entry.lock);
/* test merge of data */
unit_assert( infra_set_lame(slab, &one, onelen,
zone, zonelen, now, 0, 0, LDNS_RR_TYPE_AAAA) );
unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
d->lame_other);
lock_rw_unlock(&k->entry.lock);
/* test that noEDNS cannot overwrite known-yesEDNS */
now += cfg->host_ttl + 10;
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 0 );
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, 0, now) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 1 );
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
now, &vs, &edns_lame, &to) );
unit_assert( vs == 0 && to == init && edns_lame == 1 );
infra_delete(slab);
config_delete(cfg);
}
#include "util/edns.h"
/* Complete version-invalid client cookie; needs a new one.
* Based on edns_cookie_rfc9018_a2 */
+2
View File
@@ -86,5 +86,7 @@ void zonemd_test(void);
void tcpreuse_test(void);
/** unit test for doq functions */
void doq_test(void);
/** unit test for infra cache functions */
void infra_test(void);
#endif /* TESTCODE_UNITMAIN_H */
+1 -1
View File
@@ -53,7 +53,7 @@ static int negverbose = 0;
/** debug printout of neg cache */
static void print_neg_cache(struct val_neg_cache* neg)
{
char buf[1024];
char buf[LDNS_MAX_DOMAINLEN];
struct val_neg_zone* z;
struct val_neg_data* d;
printf("neg_cache print\n");
+6 -2
View File
@@ -425,7 +425,7 @@ nsec3_hash_test_entry(struct entry* e, rbtree_type* ct,
{
struct query_info qinfo;
struct reply_info* rep = NULL;
struct ub_packed_rrset_key* answer, *nsec3;
struct ub_packed_rrset_key* answer, *nsec3, *nsec3_region;
struct nsec3_cached_hash* hash = NULL;
int ret;
uint8_t* qname;
@@ -443,7 +443,11 @@ nsec3_hash_test_entry(struct entry* e, rbtree_type* ct,
/* check test is OK */
unit_assert(nsec3 && answer && qname);
ret = nsec3_hash_name(ct, region, buf, nsec3, 0, qname,
/* Copy the nsec3 to the region, so it can stay referenced by the
* ct tree entry. The region is freed when the file is done. */
nsec3_region = packed_rrset_copy_region(nsec3, region, 0);
ret = nsec3_hash_name(ct, region, buf, nsec3_region, 0, qname,
qinfo.qname_len, &hash);
if(ret < 1) {
printf("Bad nsec3_hash_name retcode %d\n", ret);
+1 -1
View File
@@ -111,7 +111,7 @@ static void zonemd_generate_test(const char* zname, char* zfile,
digestdup[i] = toupper((unsigned char)digestdup[i]);
}
if(verbosity >= VERB_ALGO) {
char zname[255+1];
char zname[LDNS_MAX_DOMAINLEN];
dname_str(z->name, zname);
printf("zonemd generated for %s in %s with "
"scheme=%d hashalgo=%d\n", zname, z->zonefile,
@@ -13,6 +13,7 @@ server:
msg-cache-size: 4m
rrset-cache-size: 4m
minimal-responses: yes
trust-anchor: "always.empty. 3600 IN DS 50602 8 2 FA8EE175C47325F4BD46D8A4083C3EBEB11C977D689069F2B41F1A29 B22446B1" # This is nonsense, just to kick the validator
view:
name: testview
view-first: yes # Allow falling back to global local data
+23 -1
View File
@@ -68,9 +68,12 @@ fail_answer () {
# Issue an unbound-control command
# $@: command arguments
control_command () {
control_command() {
echo "$PRE/unbound-control $@"
$PRE/unbound-control $@ > outfile
exitstatus=$?
cat outfile
return $exitstatus
}
# Reload the server and check the reload has finished processing
@@ -249,6 +252,25 @@ expect_exit_value 1
teststep "clean reload"
clean_reload
# The flush negative only works if the server is either on 1 thread,
# or there is threading enabled. Multiple processes does not work for the
# test, since the printout does not have the stats of a global cache.
if test $num_threads -le 1 -o "$have_threads" = "yes"; then
teststep "Check negative flushing"
query always.empty.
expect_answer "SERVFAIL"
query always.empty. DNSKEY
expect_answer "SERVFAIL"
control_command -c ub.conf flush_negative
expect_exit_value 0
expect_answer "^ok removed .*, 3 messages and 1 key entries"
control_command -c ub.conf flush_negative
expect_exit_value 0
expect_answer "^ok removed .*, 0 messages and 0 key entries"
else
echo "> skip Check negative flushing, because no threads"
fi
teststep "create a new local zone"
control_command -c ub.conf local_zone example.net static
expect_exit_value 0
+26 -3
View File
@@ -1,5 +1,4 @@
; nameserver test file
$ORIGIN example.com.
$TTL 3600
ENTRY_BEGIN
@@ -7,9 +6,9 @@ MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
www IN A
www.example.com. IN A
SECTION ANSWER
www IN A 10.20.30.40
www.example.com. IN A 10.20.30.40
ENTRY_END
ENTRY_BEGIN
@@ -19,3 +18,27 @@ ADJUST copy_id
SECTION QUESTION
www.example.net. IN A
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
always.empty. IN A
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
always.empty. IN DNSKEY
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
_ta-c5aa.always.empty. IN NULL
ENTRY_END
+14
View File
@@ -139,6 +139,20 @@ server:
interface-view: @INTERFACE@@@PORT_VIEW_EXT@ "ext"
interface-view: @INTERFACE@@@PORT_VIEW_INTEXT@ "intext"
# Interface with scope_id
interface: @INTERFACE@vlan50@@PORT_ALLOW@
interface: @INTERFACE@vlan51@@PORT_ALLOW@
interface-tag: @INTERFACE@vlan50@@PORT_ALLOW@ "one"
interface-tag: @INTERFACE@vlan51@@PORT_ALLOW@ "two"
interface-action: @INTERFACE@vlan50@@PORT_ALLOW@ allow
interface-action: @INTERFACE@vlan51@@PORT_ALLOW@ allow
local-zone: one.vtest. static
local-data: "one.vtest. A 1.1.1.1"
local-zone-tag: one.vtest. "one"
local-zone: two.vtest. static
local-data: "two.vtest. A 2.2.2.2"
local-zone-tag: two.vtest. "two"
# Local zones configuration
local-zone: local. transparent
local-data: "local. A 0.0.0.0"
+15
View File
@@ -17,6 +17,15 @@ ip addr add $INTERFACE_ADDR_3 dev $INTERFACE
ip addr add $INTERFACE_ADDR_4 dev $INTERFACE
ip link set $INTERFACE up
ip link add ${INTERFACE}vlan50 type dummy
ip addr add fe80::2/64 dev ${INTERFACE}vlan50
ip link add ${INTERFACE}vlan51 type dummy
ip addr add fe80::2/64 dev ${INTERFACE}vlan51
ip link set ${INTERFACE}vlan50 up
ip link set ${INTERFACE}vlan51 up
ip addr show
# start the forwarder in the background
get_ldns_testns
$LDNS_TESTNS -p $FORWARD_PORT acl_interface.testns >fwd.log 2>&1 &
@@ -250,4 +259,10 @@ for addr in $INTERFACE_ADDR_1 $INTERFACE_ADDR_2 $INTERFACE_ADDR_3 $INTERFACE_ADD
expect_external_answer
done
query_addr fe80::2%${INTERFACE}vlan50 $PORT_ALLOW "one.vtest."
expect_tag_one_answer
query_addr fe80::2%${INTERFACE}vlan51 $PORT_ALLOW "two.vtest."
expect_tag_two_answer
end 0
+1
View File
@@ -5,6 +5,7 @@
[ -f .tpkg.var.test ] && source .tpkg.var.test
. ../common.sh
#skip_test "Skip test due to no UDP service for SOA query"
PRE="../.."
if test -n "$NSD"; then
:
+1
View File
@@ -5,6 +5,7 @@
[ -f .tpkg.var.test ] && source .tpkg.var.test
. ../common.sh
#skip_test "Skip test due to no UDP service for SOA query"
PRE="../.."
if test -n "$NSD"; then
:
+1
View File
@@ -4,6 +4,7 @@ server:
qname-minimisation: no
minimal-responses: no
serve-expired: yes
serve-expired-client-timeout: 0
module-config: "cachedb iterator"
cachedb:
+1
View File
@@ -4,6 +4,7 @@ server:
qname-minimisation: no
minimal-responses: no
serve-expired: yes
serve-expired-client-timeout: 0
serve-expired-reply-ttl: 30
module-config: "cachedb iterator"

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