Compare commits

...
Author SHA1 Message Date
Mark Andrews 6c7e86aa51 suppress DOXYGEN 2020-02-03 17:44:15 +11:00
Mark Andrews 5c4917f66e remove unused label 2020-02-03 16:45:15 +11:00
Mark Andrews b7f9192ff1 add --library=std.cfg 2020-02-03 16:38:39 +11:00
Mark Andrews d9fa5d5a9a isc_mem_get cannot fail 2020-01-30 19:54:27 +11:00
Mark Andrews 6ab0b3d51a fixup! limit jobs when debugging cppcheck 2020-01-30 19:47:12 +11:00
Mark Andrews 8917d2f9b6 fixup! limit jobs when debugging cppcheck 2020-01-30 19:45:36 +11:00
Mark Andrews 1a8b581510 isc_mem_get cannot fail 2020-01-30 19:41:32 +11:00
Mark Andrews 2c823cc84f delay assignment until after REQUIRE 2020-01-30 19:38:47 +11:00
Mark Andrews e4e753f46a fixup! limit jobs when debugging cppcheck 2020-01-30 19:14:27 +11:00
Mark Andrews 228e769d75 fixup! limit jobs when debugging cppcheck 2020-01-30 19:11:14 +11:00
Mark Andrews 3590a811a2 fixup! limit jobs when debugging cppcheck 2020-01-30 19:07:04 +11:00
Mark Andrews 4de0a36a42 fixup! limit jobs when debugging cppcheck 2020-01-30 19:00:24 +11:00
Mark Andrews bbe83c3b2a delay assignment until after REQUIRE 2020-01-30 18:56:03 +11:00
Mark Andrews fe745d238d skip if first is NULL 2020-01-30 18:55:36 +11:00
Mark Andrews f1326c124a limit jobs when debugging cppcheck 2020-01-30 18:41:50 +11:00
Mark Andrews 05cb183b91 fixup! delay assignment until after REQUIRE 2020-01-30 18:24:22 +11:00
Mark Andrews b7b62bf0b2 delay assignment until after REQUIRE 2020-01-30 18:19:11 +11:00
Mark Andrews 2c17edf417 make expression logical for cppcheck 2020-01-30 17:57:25 +11:00
Mark Andrews feba3113c4 remove brackets 2020-01-30 17:49:15 +11:00
Mark Andrews 18194962f2 simplify ISC_LIKELY/ISC_UNLIKELY for CPPCHECK 2020-01-30 17:27:08 +11:00
Mark Andrews d3786c0cf1 simplify RUNTIME_CHECK for cppcheck 2020-01-30 17:14:42 +11:00
Mark Andrews 1c2f8ab09f add untracked 2020-01-30 16:42:27 +11:00
Mark Andrews 2f7613333f fixup! add --dump 2020-01-30 16:15:47 +11:00
Mark Andrews 0ff879f145 add --dump 2020-01-30 16:13:21 +11:00
Michał Kępień 77332eb2c8 Merge branch 'michal/list-atypical-failures-in-system-test-summary' into 'master'
List atypical failures in system test summary

See merge request isc-projects/bind9!2964
2020-01-29 14:42:19 +00:00
Michał Kępień a8836b381f List atypical failures in system test summary
Each system test can be marked as failed not only due to some tested
component(s) not behaving as expected, but also because of core dumps,
assertion failures, and/or ThreadSanitizer reports being found among its
artifacts.  Make the system test summary list the tests which exhibit
such atypical symptoms to more clearly present the nature of problems
found.
2020-01-29 14:50:26 +01:00
Mark Andrews 4f9bfe1460 Merge branch '1508-case-system-test-failed' into 'master'
Resolve "case system test failed."

Closes #1508

See merge request isc-projects/bind9!2774
2020-01-28 21:21:45 +00:00
Mark Andrews 7b0ba6eb10 wait longer for dynamic zone to be transfered 2020-01-28 04:38:38 +00:00
Evan Hunt 6adcd739ca Merge branch 'each-history-typo' into 'master'
fixed a typo

See merge request isc-projects/bind9!2960
2020-01-24 17:55:29 +00:00
Evan Hunt 0147acd7b6 fixed a typo 2020-01-24 09:54:22 -08:00
Mark Andrews e48b2424aa Merge branch '1559-dnssec-system-test-failed-reload-of-root-server-not-completed-in-time' into 'master'
Resolve "dnssec system test failed: reload of root server not completed in time."

Closes #1559

See merge request isc-projects/bind9!2877
2020-01-23 22:01:11 +00:00
Mark Andrews 784e64f238 wait for root server to complete reloading 2020-01-23 21:39:18 +00:00
Mark Andrews ed52ffba38 Merge branch '1579-dnstap-system-test-appears-to-be-timing-sensitive' into 'master'
Resolve "dnstap system test appears to be timing sensitive"

Closes #1579

See merge request isc-projects/bind9!2950
2020-01-23 21:13:18 +00:00
Mark Andrews 9b6df37303 wait for the ./NS lookup to complete 2020-01-23 19:16:05 +00:00
Mark Andrews 4a992c7a18 check that all servers have finished loading before beginging tests 2020-01-23 19:16:05 +00:00
Mark Andrews a1a5559a8a Merge branch 'marka-signing-clear-notify' into 'master'
Send NOTIFY messages after deleting private-type records.

See merge request isc-projects/bind9!2942
2020-01-23 09:46:31 +00:00
Tony FinchandMark Andrews f3f7b7df5d Send NOFITY messages after deleting private-type records.
The `rndc signing -clear` command cleans up the private-type records
that keep track of zone signing activity, but before this change it
did not tell the secondary servers that the zone has changed.
2020-01-23 07:36:03 +00:00
Mark Andrews 7443bd5cc7 Merge branch '1572-wait-for-mirror-zone-to-be-deleted' into 'master'
Resolve "Wait for mirror zone to be deleted"

Closes #1572

See merge request isc-projects/bind9!2941
2020-01-23 05:09:19 +00:00
Mark Andrews c6ba51cfc4 wait for log message before testing that mirror zone is correctly removed 2020-01-23 04:00:53 +00:00
Mark Andrews 82c418abfa Merge branch '1522-pad-system-test-is-timing-sensitive' into 'master'
Resolve "padding system test is timing sensitive"

Closes #907 and #1522

See merge request isc-projects/bind9!2782
2020-01-23 03:15:07 +00:00
Mark Andrews b3f06729e5 address timing issues in padding system test
'rndc stats' is not instantaneous. Wait for the dump to complete
before looking at the content.
2020-01-23 12:43:03 +11:00
Evan Hunt a2254f01c4 Merge branch '1540-bind-aborts-when-queried-for-non-existing-domain-in-chaos-class' into 'master'
Resolve "bind 9.14.8 and 9.14.9 aborts when queried for non-existing domain in chaos class"

Closes #1569 and #1540

See merge request isc-projects/bind9!2843
2020-01-22 20:24:38 +00:00
Evan HuntandDiego Fronza 42e1fb8322 CHANGES 2020-01-22 16:15:52 -03:00
Diego Fronza 7417b79c7a Added test for the proposed fix
Added test to ensure that NXDOMAIN is returned when BIND is queried for a
non existing domain in CH class (if a view of CHAOS class is configured)
and that it also doesn't crash anymore in those cases.
2020-01-22 16:15:51 -03:00
Diego Fronza 85555f29d7 Fixed crash when querying for non existing domain in chaos class
Function dns_view_findzonecut in view.c wasn't correctly handling
classes other than IN (chaos, hesiod, etc) whenever the name being
looked up wasn't in cache or in any of the configured zone views' database.

That resulted in a NULL fname being used in resolver.c:4900, which
in turn was triggering abort.
2020-01-22 16:15:51 -03:00
Michal Nowak 754f7588c6 Merge branch 'mnowak/prevent-failing-grep-invocations-from-interrupting-mkeys' into 'master'
mkeys: Prevent failing grep invocations

Closes #1567

See merge request isc-projects/bind9!2933
2020-01-22 14:53:02 +00:00
Michal Nowak 20b446cdc3 mkeys: Prevent failing grep invocations
Some 'grep' invocations were not guarded from interrupting the test
prematurely, e.g. when no text was matched.
2020-01-22 14:53:01 +00:00
Witold Krecicki 1f3502f564 Merge branch 'wpk/pipelined-test-fix' into 'master'
Fix pipelined test

See merge request isc-projects/bind9!2927
2020-01-22 13:07:19 +00:00
Witold Kręcicki b5cfc1c056 Get rid of the remains of -Tdelay option 2020-01-22 12:16:59 +01:00
Witold Kręcicki 43279de8e6 pipelined test: we no longer have -Tdelay option, use a python proxy that delays packets as a workaround 2020-01-22 12:16:59 +01:00
Mark Andrews 7a605b4d05 Merge branch '1560-isc_httpd-and-isc_httpdmgr-structures-are-not-reference-counted-and-magic' into 'master'
Resolve "isc_httpd and isc_httpdmgr structures are not reference counted and magic"

Closes #1560

See merge request isc-projects/bind9!2913
2020-01-22 01:33:02 +00:00
Ondřej SurýandMark Andrews 5b448996e5 Clean the ENTER/EXIT/NOTICE debugging from production code 2020-01-22 11:13:53 +11:00
Ondřej SurýandMark Andrews 9643a62dd5 Refactor parts of isc_httpd and isc_httpd for better readability and safety 2020-01-22 11:13:53 +11:00
Mark Andrews 7c3f419d66 add ISC_MAGIC and reference counting to httpd and httpdmgr 2020-01-22 11:13:53 +11:00
Michal Nowak 8b159c33ac Merge branch 'mnowak/enhance_unit_test_debugging' into 'master'
Omit spurious string from unit test debugging efforts

See merge request isc-projects/bind9!2829
2020-01-21 17:41:22 +00:00
Michal Nowak 9e6f6156f7 Omit spurious string from unit test debugging efforts
When both 'broken' and 'failed' test cases appear in unit test output

...
===> Broken tests
lib/isc/tests/socket_test:main  ->  broken: Test case timed out  [300.022s]
===> Failed tests
lib/isc/tests/time_test:main  ->  failed: 2 of 6 tests failed  [0.006s]
===> Summary
...

spurious '===>' string gets matched, that results in the following
error:

  Usage error for command debug: '===>' is not a test case identifier (missing ':'?).

Following change makes sure the string is omitted.

I checked on FreeBSD and OpenBSD that the AWK construct is supported.
2020-01-21 18:14:44 +01:00
Witold Krecicki 8648b7cdb2 Merge branch 'wpk/fix-inline-test' into 'master'
tests: add a missing log nextpart in inline test

Closes #1568

See merge request isc-projects/bind9!2928
2020-01-21 14:23:41 +00:00
Witold Kręcicki 796b38fe0c tests: add a missing log nextpart in inline test 2020-01-21 14:03:09 +00:00
Witold Krecicki 78a6b2689b Merge branch 'wpk/dnssec-test-fixes' into 'master'
dnssec: use less-or-equal when looking at SyncPublish time

See merge request isc-projects/bind9!2929
2020-01-21 14:00:51 +00:00
Witold Kręcicki 741bc11bdb dnssec: use less-or-equal when looking at SyncPublish time
If we created a key, mark its SyncPublish time as 'now' and started
bind the key might not be published if the SyncPublish time is in
the same second as the time the zone is loaded. This is mostly
for dnssec system test, as this kind of scenario is very unlikely
in a real world environment.
2020-01-21 14:37:53 +01:00
Ondřej Surý 4a26f7d149 Merge branch 'ondrej/lower-the-artifact-expiration-time-to-just-12-hours' into 'master'
Lower the artifact expiration time to just 1 day

See merge request isc-projects/bind9!2930
2020-01-21 12:06:24 +00:00
Ondřej Surý 27a9be3034 Lower the artifact expiration time to just 1 day 2020-01-21 12:55:34 +01:00
Witold Krecicki bb061abbb9 Merge branch 'wpk/fix-taskmgr-pause-unpause-detach-race' into 'master'
Fix a race in taskmgr between worker and task pausing/unpausing.

Closes #1571

See merge request isc-projects/bind9!2918
2020-01-21 10:04:07 +00:00
Witold Kręcicki 63b702d0d0 CHANGES note 2020-01-21 10:06:19 +01:00
Witold Kręcicki 1beba0fa59 Unit test for the taskmgr pause/unpause race 2020-01-21 10:06:19 +01:00
Witold Kręcicki e1c4a69197 Fix a race in taskmgr between worker and task pausing/unpausing.
To reproduce the race - create a task, send two events to it, first one
must take some time. Then, from the outside, pause(), unpause() and detach()
the task.
When the long-running event is processed by the task it is in
task_state_running state. When we called pause() the state changed to
task_state_paused, on unpause we checked that there are events in the task
queue, changed the state to task_state_ready and enqueued the task on the
workers readyq. We then detach the task.
The dispatch() is done with processing the event, it processes the second
event in the queue, and then shuts down the task and frees it (as it's not
referenced anymore). Dispatcher then takes the, already freed, task from
the queue where it was wrongly put, causing an use-after free and,
subsequently, either an assertion failure or a segmentation fault.
The probability of this happening is very slim, yet it might happen under a
very high load, more probably on a recursive resolver than on an
authoritative.
The fix introduces a new 'task_state_pausing' state - to which tasks
are moved if they're being paused while still running. They are moved
to task_state_paused state when dispatcher is done with them, and
if we unpause a task in paused state it's moved back to task_state_running
and not requeued.
2020-01-21 10:06:19 +01:00
Mark Andrews 684a44b469 Merge branch 'marka-Psync-future' into 'master'
dnssec: do not publish CDS records when -Psync is in the future

See merge request isc-projects/bind9!2925
2020-01-21 06:11:15 +00:00
Mark Andrews 0cd10c7763 add CHANGES 2020-01-21 16:42:51 +11:00
Tony FinchandMark Andrews 4227b7969b dnssec: do not publish CDS records when -Psync is in the future
This is a bug I encountered when trying to schedule an algorithm
rollover. My plan, for a zone whose maximum TTL is 48h, was to sign
with the new algorithm and schedule a change of CDS records for more
than 48 hours in the future, roughly like this:

    $ dnssec-keygen -a 13 -fk -Psync now+50h $zone
    $ dnssec-keygen -a 13 $zone
    $ dnssec-settime -Dsync now+50h $zone_ksk_old

However the algorithm 13 CDS was published immediately, which could
have made the zone bogus.

To reveal the bug using the `smartsign` test, this change just adds a
KSK with all its times in the future, so it should not affect the
existing checks at all. But the final check (that there are no CDS or
CDSNSKEY records after -Dsync) fails with the old `syncpublish()`
logic, because the future key's sync records appear early. With the
new `syncpublish()` logic the future key does not affect the test, as
expected, and it now passes.
2020-01-21 16:39:31 +11:00
Mark Andrews ccf7bbab5d Merge branch 'marka-omit-spurious-newlines' into 'master'
Omit spurious newlines when reporting DNSKEY changes

See merge request isc-projects/bind9!2922
2020-01-21 05:16:25 +00:00
Tony FinchandMark Andrews 3b1bd3f48b Omit spurious newlines when reporting DNSKEY changes
These caused blank lines to appear in the logs.
2020-01-21 15:55:24 +11:00
Mark Andrews aafb804eb8 Merge branch 'marka-document-authors-bind' into 'master'
document that version also controls authors.bind

See merge request isc-projects/bind9!2919
2020-01-21 03:54:51 +00:00
Mark Andrews 05c6a29c87 document that version also controls authors.bind 2020-01-21 14:36:06 +11:00
Witold Krecicki 6d8d06e82e Merge branch 'fix-shutdown-issues' into 'master'
Fix shutdown issues

See merge request isc-projects/bind9!2907
2020-01-20 22:01:44 +00:00
Witold Kręcicki fd8788eb94 Fix possible race in socket destruction.
When two threads unreferenced handles coming from one socket while
the socket was being destructed we could get a use-after-free:
Having handle H1 coming from socket S1, H2 coming from socket S2,
S0 being a parent socket to S1 and S2:

Thread A                             Thread B
Unref handle H1                      Unref handle H2
Remove H1 from S1 active handles     Remove H2 from S2 active handles
nmsocket_maybe_destroy(S1)           nmsocket_maybe_destroy(S2)
nmsocket_maybe_destroy(S0)           nmsocket_maybe_destroy(S0)
LOCK(S0->lock)
Go through all children, figure
out that we have no more active
handles:
sum of S0->children[i]->ah == 0
UNLOCK(S0->lock)
destroy(S0)
                                     LOCK(S0->lock)
                                      - but S0 is already gone
2020-01-20 22:28:36 +01:00
Witold Kręcicki 42f0e25a4c calling isc__nm_udp_send() on a non-udp socket is not 'unexpected', it's a critical failure 2020-01-20 22:28:36 +01:00
Witold Kręcicki 8d6dc8613a clean up some handle/client reference counting errors in error cases.
We weren't consistent about who should unreference the handle in
case of network error. Make it consistent so that it's always the
client code responsibility to unreference the handle - either
in the callback or right away if send function failed and the callback
will never be called.
2020-01-20 22:28:36 +01:00
Witold Kręcicki dcc0835a3a cleanup properly if we fail to initialize ns_client structure
If taskmgr is shutting down ns_client_setup will fail to create
a task for the newly created client, we weren't cleaning up already
created/attached things (memory context, server, clientmgr).
2020-01-20 22:28:36 +01:00
Witold Kręcicki f75a9e32be netmgr: fix a non-thread-safe access to libuv structures
In tcp and udp stoplistening code we accessed libuv structures
from a different thread, which caused a shutdown crash when named
was under load. Also added additional DbC checks making sure we're
in a proper thread when accessing uv_ functions.
2020-01-20 22:28:36 +01:00
Witold Kręcicki 16908ec3d9 netmgr: don't send to an inactive (closing) udp socket
We had a race in which n UDP socket could have been already closing
by libuv but we still sent data to it. Mark socket as not-active
when stopping listening and verify that socket is not active when
trying to send data to it.
2020-01-20 22:28:36 +01:00
Mark Andrews 402f067fc0 Merge branch '1537-nslookup-manual-page-needs-update-for-default-querytype-a-and-aaaa' into 'master'
Resolve "nslookup manual page needs update for default querytype (A and AAAA)"

Closes #1537

See merge request isc-projects/bind9!2894
2020-01-19 23:43:47 +00:00
Mark Andrews 938fc81493 document that nslookup defaults to A + AAAA lookups 2020-01-19 23:14:07 +00:00
Mark Andrews df709dcf8a Merge branch 'marka-check-CHANGES-SE-in-CI' into 'master'
Check CHANGES.SE in CI

See merge request isc-projects/bind9!2912
2020-01-17 21:09:16 +00:00
Mark Andrews 05f2ba973f check that CHANGES.SE entries are correctly ordered and that whitespace is correct 2020-01-17 09:31:10 +11:00
52 changed files with 953 additions and 336 deletions
+49 -14
View File
@@ -29,6 +29,9 @@ variables:
TARBALL_COMPRESSOR: xz
TARBALL_EXTENSION: xz
# limit jobs when debugging cppcheck
DEBUG_CPPCHECK: 1
stages:
- precheck
- build
@@ -176,7 +179,7 @@ stages:
- configure
- ltmain.sh
- m4/libtool.m4
expire_in: "1 week"
expire_in: "1 day"
.configure: &configure |
${CONFIGURE} \
@@ -208,7 +211,10 @@ stages:
- autoreconf:sid:amd64
artifacts:
untracked: true
expire_in: "1 week"
expire_in: "1 day"
except:
variables:
- $DEBUG_CPPCHECK == "1"
.windows_build: &windows_build_job
stage: build
@@ -238,7 +244,10 @@ stages:
- autoreconf:sid:amd64
artifacts:
untracked: true
expire_in: "1 week"
expire_in: "1 day"
except:
variables:
- $DEBUG_CPPCHECK == "1"
.setup_interfaces: &setup_interfaces |
if [ "$(id -u)" -eq "0" ]; then
@@ -261,8 +270,11 @@ stages:
- test -s bin/tests/system/systests.output
artifacts:
untracked: true
expire_in: "1 week"
expire_in: "1 day"
when: on_failure
except:
variables:
- $DEBUG_CPPCHECK == "1"
.kyua_report: &kyua_report_html |
kyua --logfile /dev/null report-html \
@@ -288,7 +300,7 @@ stages:
- 'If (Test-Path C:/CrashDumps/*) { dir C:/CrashDumps; Throw }'
artifacts:
untracked: true
expire_in: "1 week"
expire_in: "1 day"
when: on_failure
only:
- schedules
@@ -309,14 +321,19 @@ stages:
- kyua.log
- kyua.results
- kyua_html/
expire_in: "1 week"
expire_in: "1 day"
when: on_failure
except:
variables:
- $DEBUG_CPPCHECK == "1"
.cppcheck_args: &run_cppcheck |
cppcheck --enable=warning,performance,portability,information,missingInclude \
--dump \
--include=config.h \
--quiet \
--std=c11 \
--library=std.cfg \
--language=c \
--project=compile_commands.json \
--error-exitcode=2 \
@@ -325,6 +342,7 @@ stages:
--output-file=cppcheck.results \
--relative-paths="$CI_PROJECT_DIR" \
--inline-suppr \
-U DOXYGEN \
--suppressions-list=util/suppressions.txt
.cppcheck_report: &cppcheck_report_html |
@@ -343,11 +361,12 @@ stages:
after_script:
- *cppcheck_report_html
artifacts:
untracked: true
paths:
- compile_commands.json
- cppcheck.results
- cppcheck_html/
expire_in: "1 week"
expire_in: "1 day"
when: on_failure
### Job Definitions
@@ -364,8 +383,11 @@ misc:sid:amd64:
- sh util/checklibs.sh > checklibs.out
- sh util/tabify-changes < CHANGES > CHANGES.tmp
- diff -urNap CHANGES CHANGES.tmp
- rm CHANGES.tmp
- perl util/check-changes CHANGES
- test ! -f CHANGES.SE || sh util/tabify-changes < CHANGES.SE > CHANGES.tmp
- test ! -f CHANGES.SE || diff -urNap CHANGES.SE CHANGES.tmp
- test ! -f CHANGES.SE || perl util/check-changes master=0 CHANGES.SE
- rm CHANGES.tmp
- perl -w util/merge_copyrights
- diff -urNap util/copyrights util/newcopyrights
- rm util/newcopyrights
@@ -378,7 +400,7 @@ misc:sid:amd64:
paths:
- util/newcopyrights
- checklibs.out
expire_in: "1 week"
expire_in: "1 day"
when: on_failure
🐞:sid:amd64:
@@ -422,7 +444,10 @@ docs:sid:amd64:
artifacts:
paths:
- doc/arm/
expire_in: "1 month"
expire_in: "1 day"
except:
variables:
- $DEBUG_CPPCHECK == "1"
push:docs:sid:amd64:
<<: *debian_sid_amd64_image
@@ -629,8 +654,11 @@ scan-build:buster:amd64:
artifacts:
paths:
- scan-build.reports/
expire_in: "1 week"
expire_in: "1 day"
when: on_failure
except:
variables:
- $DEBUG_CPPCHECK == "1"
# Jobs for regular GCC builds on Debian Sid (amd64)
@@ -641,6 +669,7 @@ gcc:sid:amd64:
EXTRA_CONFIGURE: "--enable-dnstap --with-libidn2"
RUN_MAKE_INSTALL: 1
MAKE: bear make
DEBUG_CPPCHECK: 0
<<: *debian_sid_amd64_image
<<: *build_job
@@ -895,7 +924,7 @@ system:tsan:buster:amd64:
after_script:
- find bin -name 'tsan.*' -exec python3 util/parse_tsan.py {} \;
artifacts:
expire_in: "1 week"
expire_in: "1 day"
paths:
- bin/tests/system/*/tsan.*
- bin/tests/system/*/*/tsan.*
@@ -917,7 +946,7 @@ unit:tsan:buster:amd64:
after_script:
- find lib -name 'tsan.*' -exec python3 util/parse_tsan.py {} \;
artifacts:
expire_in: "1 week"
expire_in: "1 day"
paths:
- lib/*/tests/tsan.*
- tsan/
@@ -1126,6 +1155,9 @@ system:msvc:windows:amd64:
dependencies:
- msvc:windows:amd64
needs: ["msvc:windows:amd64"]
except:
variables:
- $DEBUG_CPPCHECK == "1"
msvc-debug:windows:amd64:
<<: *windows_build_job
@@ -1143,6 +1175,9 @@ system:msvc-debug:windows:amd64:
dependencies:
- msvc-debug:windows:amd64
needs: ["msvc-debug:windows:amd64"]
except:
variables:
- $DEBUG_CPPCHECK == "1"
# Job producing a release tarball
@@ -1184,4 +1219,4 @@ release:sid:amd64:
artifacts:
paths:
- "*.tar.gz"
expire_in: "1 week"
expire_in: "1 day"
+9
View File
@@ -1,3 +1,12 @@
5350. [bug] When a view was configured with class CHAOS, the
server could crash while processing a query for a
non-existent record. [GL #1540]
5349. [bug] Fix a race in task_pause/unpause. [GL #1571]
5348. [bug] dnssec-settime -Psync was not being honoured.
[GL !2893]
--- 9.15.8 released ---
5347. [bug] Fixed a bug that could cause an intermittent crash
+1 -1
View File
@@ -150,7 +150,7 @@ releases. New features include:
- "rndc modzone" reconfigures a single zone, without requiring the entire
server to be reconfigured.
- "rndc showzone" displays the current configuration of a zone.
- "rndc managed-keys" can be used to check the status of RFC 5001 managed
- "rndc managed-keys" can be used to check the status of RFC 5011 managed
trust anchors, or to force trust anchors to be refreshed.
- "max-cache-size" can now be set to a percentage of available memory. The
default is 90%.
+28 -22
View File
@@ -308,7 +308,7 @@ nslookup -query=hinfo -timeout=10
The class specifies the protocol group of the information.
</para>
<para>
<para>
(Default = IN; abbreviation = cl)
</para>
</listitem>
@@ -318,10 +318,10 @@ nslookup -query=hinfo -timeout=10
<term><constant><replaceable><optional>no</optional></replaceable>debug</constant></term>
<listitem>
<para>
Turn on or off the display of the full response packet and
any intermediate response packets when searching.
Turn on or off the display of the full response packet and
any intermediate response packets when searching.
</para>
<para>
<para>
(Default = nodebug; abbreviation = <optional>no</optional>deb)
</para>
</listitem>
@@ -332,9 +332,9 @@ nslookup -query=hinfo -timeout=10
<listitem>
<para>
Turn debugging mode on or off. This displays more about
what nslookup is doing.
what nslookup is doing.
</para>
<para>
<para>
(Default = nod2)
</para>
</listitem>
@@ -358,7 +358,7 @@ nslookup -query=hinfo -timeout=10
names in the domain search list to the request until an
answer is received.
</para>
<para>
<para>
(Default = search)
</para>
</listitem>
@@ -370,7 +370,7 @@ nslookup -query=hinfo -timeout=10
<para>
Change the default TCP/UDP name server port to <replaceable>value</replaceable>.
</para>
<para>
<para>
(Default = 53; abbreviation = po)
</para>
</listitem>
@@ -389,9 +389,15 @@ nslookup -query=hinfo -timeout=10
<para>
Change the type of the information query.
</para>
<para>
(Default = A; abbreviations = q, ty)
<para>
(Default = A and then AAAA; abbreviations = q, ty)
</para>
<para>
<emphasis role="bold">Note:</emphasis> It is
only possible to specify one query type, only
the default behavior looks up both when an
alternative is not specified.
</para>
</listitem>
</varlistentry>
@@ -403,7 +409,7 @@ nslookup -query=hinfo -timeout=10
have the
information.
</para>
<para>
<para>
(Default = recurse; abbreviation = [no]rec)
</para>
</listitem>
@@ -413,9 +419,9 @@ nslookup -query=hinfo -timeout=10
<term><constant>ndots=</constant><replaceable>number</replaceable></term>
<listitem>
<para>
Set the number of dots (label separators) in a domain
that will disable searching. Absolute names always
stop searching.
Set the number of dots (label separators) in a domain
that will disable searching. Absolute names always
stop searching.
</para>
</listitem>
</varlistentry>
@@ -446,7 +452,7 @@ nslookup -query=hinfo -timeout=10
Always use a virtual circuit when sending requests to the
server.
</para>
<para>
<para>
(Default = novc)
</para>
</listitem>
@@ -456,15 +462,15 @@ nslookup -query=hinfo -timeout=10
<term><constant><replaceable><optional>no</optional></replaceable>fail</constant></term>
<listitem>
<para>
Try the next nameserver if a nameserver responds with
SERVFAIL or a referral (nofail) or terminate query
(fail) on such a response.
</para>
<para>
Try the next nameserver if a nameserver responds with
SERVFAIL or a referral (nofail) or terminate query
(fail) on such a response.
</para>
<para>
(Default = nofail)
</para>
</listitem>
</varlistentry>
</listitem>
</varlistentry>
</variablelist>
</para>
+1 -8
View File
@@ -141,7 +141,6 @@ static bool nonearest = false;
static bool nosoa = false;
static bool notcp = false;
static bool sigvalinsecs = false;
static unsigned int delay = 0;
/*
* -4 and -6
@@ -638,14 +637,10 @@ parse_T_opt(char *option) {
/*
* force the server to behave (or misbehave) in
* specified ways for testing purposes.
* delay=xxxx: delay client responses by xxxx ms to
* simulate remote servers.
* dscp=x: check that dscp values are as
* expected and assert otherwise.
*/
if (!strncmp(option, "delay=", 6)) {
delay = atoi(option + 6);
} else if (!strcmp(option, "dropedns")) {
if (!strcmp(option, "dropedns")) {
dropedns = true;
} else if (!strncmp(option, "dscp=", 5)) {
isc_dscp_check_value = atoi(option + 5);
@@ -1318,8 +1313,6 @@ setup(void) {
ns_server_setoption(sctx, NS_SERVER_NOTCP, true);
if (sigvalinsecs)
ns_server_setoption(sctx, NS_SERVER_SIGVALINSECS, true);
named_g_server->sctx->delay = delay;
}
static void
+20 -10
View File
@@ -14,6 +14,12 @@ SYSTEMTESTTOP=..
DIGOPTS="+tcp +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
wait_for_serial() (
$DIG $DIGOPTS "@$1" "$2" SOA > "$4"
serial=$(awk '$4 == "SOA" { print $7 }' "$4")
[ "$3" -eq "${serial:--1}" ]
)
status=0
n=0
@@ -91,11 +97,13 @@ digcomp dig.ns1.test$n postupdate.good || ret=1
test $ret -eq 0 || echo_i "failed"
status=`expr $status + $ret`
for i in 1 2 3 4 5 6 7 8 9
do
$DIG $DIGOPTS soa dynamic @10.53.0.2 | grep 2000042408 > /dev/null && break
sleep 1
done
n=`expr $n + 1`
ret=0
echo_i "wait for zone to transfer ($n)"
retry_quiet 20 wait_for_serial 10.53.0.2 dynamic 2000042408 dig.ns2.test$n || ret=1
test $ret -eq 0 || echo_i "failed"
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check SOA owner case is transfered to slave ($n)"
@@ -121,11 +129,13 @@ digcomp dig.ns1.test$n postns1.good || ret=1
test $ret -eq 0 || echo_i "failed"
status=`expr $status + $ret`
for i in 1 2 3 4 5 6 7 8 9
do
$DIG $DIGOPTS soa dynamic @10.53.0.2 | grep 2000042409 > /dev/null && break
sleep 1
done
n=`expr $n + 1`
ret=0
echo_i "wait for zone to transfer ($n)"
retry_quiet 20 wait_for_serial 10.53.0.2 dynamic 2000042409 dig.ns2.test$n || ret=1
test $ret -eq 0 || echo_i "failed"
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check A owner case is transfered to slave ($n)"
+2 -2
View File
@@ -378,14 +378,14 @@ nextpartpeek() {
_search_log() (
msg="$1"
file="$2"
nextpart "$file" | grep -F "$msg" > /dev/null
nextpart "$file" | grep -F -e "$msg" > /dev/null
)
# _search_log_peek: look for message $1 in file $2 with nextpartpeek().
_search_log_peek() (
msg="$1"
file="$2"
nextpartpeek "$file" | grep -F "$msg" > /dev/null
nextpartpeek "$file" | grep -F -e "$msg" > /dev/null
)
# wait_for_log: wait until message $2 in file $3 appears. Bail out after
+8
View File
@@ -3671,11 +3671,19 @@ dig_with_opts . dnskey +ednsopt=KEY-TAG:fffe +ednsopt=KEY-TAG:fffd @10.53.0.1 >
grep "trust-anchor-telemetry './IN' from .* 65534" ns1/named.run > /dev/null || ret=1
grep "trust-anchor-telemetry './IN' from .* 65533" ns1/named.run > /dev/null && ret=1
$PERL $SYSTEMTESTTOP/stop.pl dnssec ns1 || ret=1
nextpart ns1/named.run > /dev/null
$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} dnssec ns1 || ret=1
n=$(($n+1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
echo_i "waiting for root server to finish reloading ($n)"
ret=0
wait_for_log 20 "all zones loaded" ns1/named.run || ret=1
n=$(($n+1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
echo_i "check that the view is logged in messages from the validator when using views ($n)"
ret=0
grep "view rec: *validat" ns4/named.run > /dev/null || ret=1
+1
View File
@@ -12,6 +12,7 @@
rm -f */named.conf
rm -f */named.memstats
rm -f */named.run
rm -f */named.run.prev
rm -f */named.stats
rm -f dig.out*
rm -f dnstap.out dnstap.hex
+15
View File
@@ -35,7 +35,21 @@ do
status=`expr $status + $ret`
done
echo_i "wait for servers to finish loading"
ret=0
wait_for_log 20 "all zones loaded" ns1/named.run || ret=1
wait_for_log 20 "all zones loaded" ns2/named.run || ret=1
wait_for_log 20 "all zones loaded" ns3/named.run || ret=1
wait_for_log 20 "all zones loaded" ns4/named.run || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
# both the 'a.example/A' lookup and the './NS' lookup to ns1
# need tocomplete before reopening/rolling for the counts to
# be correct.
$DIG $DIGOPTS @10.53.0.3 a.example > dig.out
wait_for_log 20 "(./NS): query_reset" ns1/named.run || true
# check three different dnstap reopen/roll methods:
# ns1: dnstap-reopen; ns2: dnstap -reopen; ns3: dnstap -roll
@@ -71,6 +85,7 @@ EOF
$RNDCCMD -s 10.53.0.1 stop | sed 's/^/ns1 /' | cat_i
$RNDCCMD -s 10.53.0.2 stop | sed 's/^/ns2 /' | cat_i
$RNDCCMD -s 10.53.0.3 stop | sed 's/^/ns3 /' | cat_i
sleep 1
echo_i "checking initial message counts"
+1
View File
@@ -1351,6 +1351,7 @@ $PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} inline ns3
# receive_secure_serial() should refrain from introducing any zone changes.
$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --halt --port ${CONTROLPORT} inline ns3
ensure_sigs_only_in_journal delayedkeys ns3/delayedkeys.db.signed
nextpart ns3/named.run > /dev/null
$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} inline ns3
# We can now test whether the secure zone journal was correctly processed:
# unless the records contained in it were scheduled for resigning, no resigning
+2
View File
@@ -540,7 +540,9 @@ n=`expr $n + 1`
echo_i "checking that a mirror zone can be deleted using rndc ($n)"
ret=0
# Remove the mirror zone added in the previous test.
nextpart ns3/named.run > /dev/null
$RNDCCMD 10.53.0.3 delzone verify-addzone > rndc.out.ns3.test$n 2>&1 || ret=1
wait_for_log 20 "zone verify-addzone/IN: mirror zone is no longer in use; reverting to normal recursion" ns3/named.run || ret=1
# Check whether the mirror zone was removed.
$DIG $DIGOPTS @10.53.0.3 +norec verify-addzone SOA > dig.out.ns3.test$n 2>&1 || ret=1
grep "NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
+10 -10
View File
@@ -172,7 +172,7 @@ n=$((n+1))
echo_i "remove untrusted standby key, check timer restarts ($n)"
ret=0
mkeys_sync_on 2 || ret=1
t1=$(grep "trust pending" ns2/managed-keys.bind)
t1=$(grep "trust pending" ns2/managed-keys.bind) || true
$SETTIME -D now -K ns1 "$standby1" > /dev/null
mkeys_loadkeys_on 1 || ret=1
# Less than a second may have passed since the last time ns2 received a
@@ -182,7 +182,7 @@ mkeys_loadkeys_on 1 || ret=1
sleep 1
mkeys_refresh_on 2 || ret=1
mkeys_sync_on 2 || ret=1
t2=$(grep "trust pending" ns2/managed-keys.bind)
t2=$(grep "trust pending" ns2/managed-keys.bind) || true
# trust pending date must be different
[ -n "$t2" ] || ret=1
[ "$t1" = "$t2" ] && ret=1
@@ -220,7 +220,7 @@ count=$(grep -c "remove at" rndc.out.$n) || true
count=$(grep -c "trust pending" rndc.out.$n) || true
[ "$count" -eq 1 ] || ret=1
# pending date moved forward for the standby key
t2=$(grep "trust pending" ns2/managed-keys.bind)
t2=$(grep "trust pending" ns2/managed-keys.bind) || true
[ -n "$t2" ] || ret=1
[ "$t1" = "$t2" ] && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
@@ -254,7 +254,7 @@ count=$(grep -c "remove at" rndc.out.$n) || true
count=$(grep -c "trust pending" rndc.out.$n) || true
[ "$count" -eq 1 ] || ret=1
# pending date moved forward for the standby key
t2=$(grep "trust pending" ns2/managed-keys.bind)
t2=$(grep "trust pending" ns2/managed-keys.bind) || true
[ -n "$t2" ] || ret=1
[ "$t1" = "$t2" ] && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
@@ -292,7 +292,7 @@ count=$(grep -c "remove at" rndc.out.$n) || true
count=$(grep -c "trust pending" rndc.out.$n) || true
[ "$count" -eq 1 ] || ret=1
# pending date moved forward for the standby key
t2=$(grep "trust pending" ns2/managed-keys.bind)
t2=$(grep "trust pending" ns2/managed-keys.bind) || true
[ -n "$t2" ] || ret=1
[ "$t1" = "$t2" ] && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
@@ -571,7 +571,7 @@ ret=0
# set using -T mkeytimers).
mkeys_refresh_on 2 || ret=1
mkeys_status_on 2 > rndc.out.1.$n 2>&1 || ret=1
t1=$(grep 'next refresh:' rndc.out.1.$n)
t1=$(grep 'next refresh:' rndc.out.1.$n) || true
$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port "${CONTROLPORT}" mkeys ns1
rm -f ns1/root.db.signed.jnl
cp ns1/root.db ns1/root.db.signed
@@ -594,7 +594,7 @@ count=$(grep -c "trust" rndc.out.2.$n) || true
[ "$count" -eq 1 ] || ret=1
count=$(grep -c "trusted since" rndc.out.2.$n) || true
[ "$count" -eq 1 ] || ret=1
t2=$(grep 'next refresh:' rndc.out.2.$n)
t2=$(grep 'next refresh:' rndc.out.2.$n) || true
[ "$t1" = "$t2" ] && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status+ret))
@@ -605,7 +605,7 @@ ret=0
# Refresh keys first to prevent previous checks from influencing this one
mkeys_refresh_on 2 || ret=1
mkeys_status_on 2 > rndc.out.1.$n 2>&1 || ret=1
t1=$(grep 'next refresh:' rndc.out.1.$n)
t1=$(grep 'next refresh:' rndc.out.1.$n) || true
$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port "${CONTROLPORT}" mkeys ns1
rm -f ns1/root.db.signed.jnl
cat ns1/K*.key >> ns1/root.db.signed
@@ -632,7 +632,7 @@ count=$(grep -c "trust" rndc.out.2.$n) || true
[ "$count" -eq 1 ] || ret=1
count=$(grep -c "trusted since" rndc.out.2.$n) || true
[ "$count" -eq 1 ] || ret=1
t2=$(grep 'next refresh:' rndc.out.2.$n)
t2=$(grep 'next refresh:' rndc.out.2.$n) || true
[ "$t1" = "$t2" ] && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status+ret))
@@ -682,7 +682,7 @@ echo_i "check that trust-anchor-telemetry queries contain the correct key ($n)"
ret=0
# convert the hexadecimal key from the TAT query into decimal and
# compare against the known key.
tathex=$(grep "query '_ta-[0-9a-f][0-9a-f]*/NULL/IN' approved" ns1/named.run | awk '{print $6; exit 0}' | sed -e 's/(_ta-\([0-9a-f][0-9a-f]*\)):/\1/')
tathex=$(grep "query '_ta-[0-9a-f][0-9a-f]*/NULL/IN' approved" ns1/named.run | awk '{print $6; exit 0}' | sed -e 's/(_ta-\([0-9a-f][0-9a-f]*\)):/\1/') || true
tatkey=$($PERL -e 'printf("%d\n", hex(@ARGV[0]));' "$tathex")
realkey=$(rndccmd 10.53.0.2 secroots - | sed -n 's#.*SHA256/\([0-9][0-9]*\) ; .*managed.*#\1#p')
[ "$tatkey" -eq "$realkey" ] || ret=1
+1
View File
@@ -11,6 +11,7 @@ rm -f dig.out.*
rm -f ns*/named.memstats
rm -f ns*/named.run
rm -f ns*/named.stats
rm -f ns*/named.stats.prev
rm -f ns*/named.lock
rm -f ns*/named.conf
rm -f ns*/managed-keys.bind*
+4
View File
@@ -12,7 +12,11 @@
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
$SHELL ./clean.sh
copy_setports ns1/named.conf.in ns1/named.conf
copy_setports ns2/named.conf.in ns2/named.conf
copy_setports ns3/named.conf.in ns3/named.conf
copy_setports ns4/named.conf.in ns4/named.conf
touch ns2/named.stats
+16 -11
View File
@@ -36,8 +36,11 @@ status=`expr $status + $ret`
echo_i "checking that dig added padding ($n)"
ret=0
n=`expr $n + 1`
nextpart ns2/named.stats > /dev/null
$RNDCCMD 10.53.0.2 stats
grep "EDNS padding option received" ns2/named.stats > /dev/null || ret=1
wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1
nextpart ns2/named.stats | grep "EDNS padding option received" > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
@@ -88,28 +91,30 @@ status=`expr $status + $ret`
echo_i "checking that a TCP and padding server config enables padding ($n)"
ret=0
n=`expr $n + 1`
nextpart ns2/named.stats > /dev/null
$RNDCCMD 10.53.0.2 stats
opad=`grep "EDNS padding option received" ns2/named.stats | \
tail -1 | awk '{ print $1}'`
wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1
opad=`nextpart ns2/named.stats | awk '/EDNS padding option received/ { print $1}'`
$DIG $DIGOPTS foo.example @10.53.0.3 > dig.out.test$n
$RNDCCMD 10.53.0.2 stats
npad=`grep "EDNS padding option received" ns2/named.stats | \
tail -1 | awk '{ print $1}'`
if [ "$opad" -eq "$npad" ]; then ret=1; fi
wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1
npad=`nextpart ns2/named.stats | awk '/EDNS padding option received/ { print $1}'`
if [ "$opad" -eq "$npad" ]; then echo_i "error: opad ($opad) == npad ($npad)"; ret=1; fi
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "checking that a padding server config should enforce TCP ($n)"
ret=0
n=`expr $n + 1`
nextpart ns2/named.stats > /dev/null
$RNDCCMD 10.53.0.2 stats
opad=`grep "EDNS padding option received" ns2/named.stats | \
tail -1 | awk '{ print $1}'`
wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1
opad=`nextpart ns2/named.stats | awk '/EDNS padding option received/ { print $1}'`
$DIG $DIGOPTS foo.example @10.53.0.4 > dig.out.test$n
$RNDCCMD 10.53.0.2 stats
npad=`grep "EDNS padding option received" ns2/named.stats | \
tail -1 | awk '{ print $1}'`
if [ "$opad" -ne "$npad" ]; then ret=1; fi
wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1
npad=`nextpart ns2/named.stats | awk '/EDNS padding option received/ { print $1}'`
if [ "$opad" -ne "$npad" ]; then echo_i "error: opad ($opad) != npad ($npad)"; ret=1; fi
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
+194
View File
@@ -0,0 +1,194 @@
############################################################################
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
############################################################################
############################################################################
#
# This tool acts as a TCP/UDP proxy and delays all incoming packets by 500
# miliseconds.
#
# We use it to check pipelining - a client sents 8 questions over a
# pipelined connection - that require asking a normal (examplea) and a
# slow-responding (exampleb) servers:
# a.examplea
# a.exampleb
# b.examplea
# b.exampleb
# c.examplea
# c.exampleb
# d.examplea
# d.exampleb
#
# If pipelining works properly the answers will be returned out of order
# with all answers from examplea returned first, and then all answers
# from exampleb.
#
############################################################################
from __future__ import print_function
import datetime
import os
import select
import signal
import socket
import sys
import time
import threading
import struct
DELAY = 0.5
THREADS = []
def log(msg):
print(datetime.datetime.now().strftime('%d-%b-%Y %H:%M:%S.%f ') + msg)
def sigterm(*_):
log('SIGTERM received, shutting down')
for thread in THREADS:
thread.close()
thread.join()
os.remove('ans.pid')
sys.exit(0)
class TCPDelayer(threading.Thread):
""" For a given TCP connection conn we open a connection to (ip, port),
and then we delay each incoming packet by DELAY by putting it in a
queue.
In the pipelined test TCP should not be used, but it's here for
completnes.
"""
def __init__(self, conn, ip, port):
threading.Thread.__init__(self)
self.conn = conn
self.cconn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.cconn.connect((ip, port))
self.queue = []
self.running = True
def close(self):
self.running = False
def run(self):
while self.running:
curr_timeout = 0.5
try:
curr_timeout = self.queue[0][0]-time.time()
except StopIteration:
pass
if curr_timeout > 0:
if curr_timeout == 0:
curr_timeout = 0.5
rfds, _, _ = select.select([self.conn, self.cconn], [], [], curr_timeout)
if self.conn in rfds:
data = self.conn.recv(65535)
if not data:
return
self.queue.append((time.time() + DELAY, data))
if self.cconn in rfds:
data = self.cconn.recv(65535)
if not data == 0:
return
self.conn.send(data)
try:
while self.queue[0][0]-time.time() < 0:
_, data = self.queue.pop(0)
self.cconn.send(data)
except StopIteration:
pass
class UDPDelayer(threading.Thread):
""" Every incoming UDP packet is put in a queue for DELAY time, then
it's sent to (ip, port). We remember the query id to send the
response we get to a proper source, responsed are not delayed.
"""
def __init__(self, usock, ip, port):
threading.Thread.__init__(self)
self.sock = usock
self.csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.dst = (ip, port)
self.queue = []
self.qid_mapping = {}
self.running = True
def close(self):
self.running = False
def run(self):
while self.running:
curr_timeout = 0.5
if self.queue:
curr_timeout = self.queue[0][0]-time.time()
if curr_timeout >= 0:
if curr_timeout == 0:
curr_timeout = 0.5
rfds, _, _ = select.select([self.sock, self.csock], [], [], curr_timeout)
if self.sock in rfds:
data, addr = self.sock.recvfrom(65535)
if not data:
return
self.queue.append((time.time() + DELAY, data))
qid = struct.unpack('>H', data[:2])[0]
log('Received a query from %s, queryid %d' % (str(addr), qid))
self.qid_mapping[qid] = addr
if self.csock in rfds:
data, addr = self.csock.recvfrom(65535)
if not data:
return
qid = struct.unpack('>H', data[:2])[0]
dst = self.qid_mapping.get(qid)
if dst is not None:
self.sock.sendto(data, dst)
log('Received a response from %s, queryid %d, sending to %s' % (str(addr), qid, str(dst)))
while self.queue and self.queue[0][0]-time.time() < 0:
_, data = self.queue.pop(0)
qid = struct.unpack('>H', data[:2])[0]
log('Sending a query to %s, queryid %d' % (str(self.dst), qid))
self.csock.sendto(data, self.dst)
def main():
signal.signal(signal.SIGTERM, sigterm)
signal.signal(signal.SIGINT, sigterm)
with open('ans.pid', 'w') as pidfile:
print(os.getpid(), file=pidfile)
listenip = '10.53.0.5'
serverip = '10.53.0.2'
try:
port = int(os.environ['PORT'])
except KeyError:
port = 5300
log('Listening on %s:%d' % (listenip, port))
usock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
usock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
usock.bind((listenip, port))
thread = UDPDelayer(usock, serverip, port)
thread.start()
THREADS.append(thread)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((listenip, port))
sock.listen(1)
while True:
(clientsock, _) = sock.accept()
log('Accepted connection from %s' % clientsock)
thread = TCPDelayer(clientsock, serverip, port)
thread.start()
THREADS.append(thread)
if __name__ == '__main__':
main()
+1 -1
View File
@@ -19,7 +19,7 @@ $TTL 300
a.root-servers.nil. A 10.53.0.1
examplea. NS ns2.examplea.
ns2.examplea. A 10.53.0.2
ns2.examplea. A 10.53.0.5
exampleb. NS ns3.exampleb.
ns3.exampleb. A 10.53.0.3
+1 -1
View File
@@ -17,7 +17,7 @@ examplea IN SOA mname1. . (
3600 ; minimum (1 hour)
)
examplea. NS ns2.examplea.
ns2.examplea. A 10.53.0.2
ns2.examplea. A 10.53.0.5
$ORIGIN examplea.
a A 10.0.1.1
@@ -1 +0,0 @@
-m record,size,mctx -c named.conf -d 99 -D pipelined-ns3 -X named.lock -g -T delay=200
+29
View File
@@ -0,0 +1,29 @@
#!/bin/sh
#
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
if test -n "$PYTHON"
then
if $PYTHON -c "import dns" 2> /dev/null
then
:
else
echo_i "This test requires the dnspython module." >&2
exit 1
fi
else
echo_i "This test requires Python and the dnspython module." >&2
exit 1
fi
exit 0
@@ -0,0 +1,5 @@
$TTL 3600
@ CHAOS SOA @ @ 1970010100 86400 600 86400 300
@ CHAOS NS @
version CHAOS TXT "CH 1.0"
hostname CHAOS TXT "unknown"
+4 -1
View File
@@ -46,7 +46,10 @@ server fd92:7065:b8e:ffff::1000 {
* "globalcache" before the recursive "default"/IN view is configured.
*/
view "class" chaos {
match-clients { none; };
zone "chaostest" CHAOS {
type master;
file "chaostest.db";
};
};
/*
+8
View File
@@ -805,5 +805,13 @@ grep "running as: .* -m record,size,mctx " ns1/named.run > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "checking NXDOMAIN is returned when querying non existing domain in CH class ($n)"
ret=0
$DIG $DIGOPTS @10.53.0.1 id.hostname txt ch > dig.ns1.out.${n} || ret=1
grep "status: NXDOMAIN" dig.ns1.out.${n} > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1
+4
View File
@@ -55,6 +55,9 @@ cksk4=`$REVOKE $cksk3`
echo_i "setting up sync key"
cksk5=`$KEYGEN -q -a rsasha1 -fk -P now+1mo -A now+1mo -Psync now $czone`
echo_i "and future sync key"
cksk6=`$KEYGEN -q -a rsasha1 -fk -P now+1mo -A now+1mo -Psync now+1mo $czone`
echo_i "generating parent keys"
pzsk=`$KEYGEN -q -a rsasha1 $pzone`
pksk=`$KEYGEN -q -a rsasha1 -fk $pzone`
@@ -348,6 +351,7 @@ awk 'BEGIN { r=1 } $2 == "CDS" { r=0 } END { exit r }' $cfile.signed || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
# this also checks that the future sync record is not yet published
echo_i "checking sync record deletion"
ret=0
$SETTIME -P now -A now -Dsync now ${cksk5} > /dev/null
+18
View File
@@ -56,6 +56,24 @@ if [ -n "${FAILED_TESTS}" ]; then
status=1
fi
CRASHED_TESTS=`find . -name 'core*' -or -name '*.core' | cut -d'/' -f2 | sort -u | sed -e 's/^/I: /'`
if [ -n "${CRASHED_TESTS}" ]; then
echoinfo "I:Core dumps were found for the following system tests:"
echoinfo "${CRASHED_TESTS}"
fi
ASSERTION_FAILED_TESTS=`find . -name named.run | xargs grep "assertion failure" | cut -d'/' -f2 | sort -u | sed -e 's/^/I: /'`
if [ -n "${ASSERTION_FAILED_TESTS}" ]; then
echoinfo "I:Assertion failures were detected for the following system tests:"
echoinfo "${ASSERTION_FAILED_TESTS}"
fi
TSAN_REPORT_TESTS=`find . -name 'tsan.*' | cut -d'/' -f2 | sort -u | sed -e 's/^/I: /'`
if [ -n "${TSAN_REPORT_TESTS}" ]; then
echoinfo "I:ThreadSanitizer reported issues for the following system tests:"
echoinfo "${TSAN_REPORT_TESTS}"
fi
RESULTS_FOUND=`grep -c 'R:[a-z0-9_-][a-z0-9_-]*:[A-Z][A-Z]*' systests.output`
TESTS_RUN=`echo "${SUBDIRS}" | wc -w`
if [ "${RESULTS_FOUND}" -ne "${TESTS_RUN}" ]; then
+5
View File
@@ -9300,6 +9300,11 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
Specifying <command>version none</command>
disables processing of the queries.
</para>
<para>
Setting <command>version</command> to any value
(including <literal>none</literal>) will also
disable queries for <literal>authors.bind TXT CH</literal>.
</para>
</listitem>
</varlistentry>
+1 -1
View File
@@ -97,7 +97,7 @@ int main(int argc, char **argv)
UNUSED(argc);
UNUSED(argv);
target = target ? target + 1 : argv[0];
target = (target != NULL) ? target + 1 : argv[0];
if (strncmp(target, "lt-", 3) == 0) {
target += 3;
}
+7 -22
View File
@@ -1340,13 +1340,7 @@ dns_client_startresolve(dns_client_t *client, const dns_name_t *name,
ISC_LIST_INIT(event->answerlist);
rctx = isc_mem_get(mctx, sizeof(*rctx));
if (rctx == NULL)
result = ISC_R_NOMEMORY;
else {
isc_mutex_init(&rctx->lock);
}
if (result != ISC_R_SUCCESS)
goto cleanup;
isc_mutex_init(&rctx->lock);
result = getrdataset(mctx, &rdataset);
if (result != ISC_R_SUCCESS)
@@ -1748,13 +1742,7 @@ dns_client_startrequest(dns_client_t *client, dns_message_t *qmessage,
action, arg, sizeof(*event));
ctx = isc_mem_get(client->mctx, sizeof(*ctx));
if (ctx == NULL)
result = ISC_R_NOMEMORY;
else {
isc_mutex_init(&ctx->lock);
}
if (result != ISC_R_SUCCESS)
goto cleanup;
isc_mutex_init(&ctx->lock);
ctx->client = client;
ISC_LINK_INIT(ctx, link);
@@ -1787,14 +1775,11 @@ dns_client_startrequest(dns_client_t *client, dns_message_t *qmessage,
isc_refcount_decrement(&client->references);
cleanup:
if (ctx != NULL) {
LOCK(&client->lock);
ISC_LIST_UNLINK(client->reqctxs, ctx, link);
UNLOCK(&client->lock);
isc_mutex_destroy(&ctx->lock);
isc_mem_put(client->mctx, ctx, sizeof(*ctx));
}
LOCK(&client->lock);
ISC_LIST_UNLINK(client->reqctxs, ctx, link);
UNLOCK(&client->lock);
isc_mutex_destroy(&ctx->lock);
isc_mem_put(client->mctx, ctx, sizeof(*ctx));
if (event != NULL)
isc_event_free(ISC_EVENT_PTR(&event));
isc_task_detach(&tclone);
+10 -11
View File
@@ -648,6 +648,7 @@ syncpublish(dst_key_t *key, isc_stdtime_t now) {
isc_stdtime_t when;
dst_key_state_t state;
int major, minor;
bool publish;
/*
* Is this an old-style key?
@@ -670,18 +671,16 @@ syncpublish(dst_key_t *key, isc_stdtime_t now) {
}
/* If no kasp state, check timings. */
publish = false;
result = dst_key_gettime(key, DST_TIME_SYNCPUBLISH, &when);
if (result != ISC_R_SUCCESS) {
return (false);
if (result == ISC_R_SUCCESS && when <= now) {
publish = true;
}
result = dst_key_gettime(key, DST_TIME_SYNCDELETE, &when);
if (result != ISC_R_SUCCESS) {
return (true);
if (result == ISC_R_SUCCESS && when < now) {
publish = false;
}
if (when <= now) {
return (false);
}
return (true);
return (publish);
}
/*%<
@@ -1825,14 +1824,14 @@ publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, const dns_name_t *origin,
RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
dst_key_format(key->key, keystr, sizeof(keystr));
report("Fetching %s (%s) from key %s.\n",
report("Fetching %s (%s) from key %s.",
keystr, key->ksk ? (key->zsk ? "CSK" : "KSK") : "ZSK",
key->source == dns_keysource_user ? "file" : "repository");
if (key->prepublish && ttl > key->prepublish) {
isc_stdtime_t now;
report("Key %s: Delaying activation to match the DNSKEY TTL.\n",
report("Key %s: Delaying activation to match the DNSKEY TTL.",
keystr, ttl);
isc_stdtime_get(&now);
@@ -1857,7 +1856,7 @@ remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, const dns_name_t *origin,
char alg[80];
dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg));
report("Removing %s key %d/%s from DNSKEY RRset.\n",
report("Removing %s key %d/%s from DNSKEY RRset.",
reason, dst_key_id(key->key), alg);
RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
+3 -2
View File
@@ -130,7 +130,7 @@ static isc_result_t
write_data(FILE *file, unsigned char *datap, void *arg, uint64_t *crc) {
isc_result_t result;
size_t ret = 0;
data_holder_t *data = (data_holder_t *)datap;
data_holder_t *data;
data_holder_t temp;
off_t where;
@@ -138,7 +138,8 @@ write_data(FILE *file, unsigned char *datap, void *arg, uint64_t *crc) {
REQUIRE(file != NULL);
REQUIRE(crc != NULL);
REQUIRE(data != NULL);
REQUIRE(datap != NULL);
data = (data_holder_t *)datap;
REQUIRE((data->len == 0 && data->data == NULL) ||
(data->len != 0 && data->data != NULL));
+13 -5
View File
@@ -1245,8 +1245,9 @@ dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
ztoptions |= DNS_ZTFIND_NOEXACT;
result = dns_zt_find(view->zonetable, name, ztoptions,
NULL, &zone);
} else
} else {
result = ISC_R_NOTFOUND;
}
UNLOCK(&view->lock);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
result = dns_zone_getdb(zone, &db);
@@ -1261,12 +1262,15 @@ dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
* We have a cache; try it.
*/
dns_db_attach(view->cachedb, &db);
} else {
} else if (use_hints && view->hints != NULL) {
/*
* Maybe we have hints...
*/
try_hints = true;
goto finish;
} else {
result = DNS_R_NXDOMAIN;
goto cleanup;
}
} else if (result != ISC_R_SUCCESS) {
/*
@@ -1287,6 +1291,7 @@ dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
result = ISC_R_SUCCESS;
else if (result != ISC_R_SUCCESS)
goto cleanup;
if (use_cache && view->cachedb != NULL && db != view->hints) {
/*
* We found an answer, but the cache may be better.
@@ -1327,13 +1332,16 @@ dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
* have a zone delegation, so use it.
*/
use_zone = true;
} else {
result = ISC_R_SUCCESS;
} else if (use_hints && view->hints != NULL) {
/*
* Maybe we have hints...
*/
try_hints = true;
result = ISC_R_SUCCESS;
} else {
result = DNS_R_NXDOMAIN;
}
result = ISC_R_SUCCESS;
} else {
/*
* Something bad happened.
@@ -1358,7 +1366,7 @@ dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
if (sigrdataset != NULL &&
dns_rdataset_isassociated(&zrdataset))
dns_rdataset_clone(&zsigrdataset, sigrdataset);
} else if (try_hints && use_hints && view->hints != NULL) {
} else if (try_hints) {
/*
* We've found nothing so far, but we have hints.
*/
+2 -1
View File
@@ -19576,7 +19576,8 @@ keydone(isc_task_t *task, isc_event_t *event) {
commit = true;
LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|
DNS_ZONEFLG_NEEDNOTIFY);
zone_needdump(zone, 30);
UNLOCK_ZONE(zone);
}
+8 -8
View File
@@ -1215,15 +1215,15 @@ verify_nsec3_chains(const vctx_t *vctx, isc_mem_t *mctx) {
result = ISC_R_FAILURE;
}
if (first == NULL || newchain(first, e)) {
if (prev != NULL) {
if (!checknext(vctx, prev, first)) {
result = ISC_R_FAILURE;
}
if (prev != first) {
free_element(mctx, prev);
}
}
if (first != NULL) {
if (prev != NULL) {
if (!checknext(vctx, prev, first)) {
result = ISC_R_FAILURE;
}
if (prev != first) {
free_element(mctx, prev);
}
}
free_element(mctx, first);
}
prev = first = e;
+260 -152
View File
@@ -20,6 +20,7 @@
#include <isc/httpd.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/refcount.h>
#include <isc/socket.h>
#include <isc/string.h>
#include <isc/task.h>
@@ -33,9 +34,6 @@
/*%
* TODO:
*
* o Put in better checks to make certain things are passed in correctly.
* This includes a magic number for externally-visible structures,
* checking for NULL-ness before dereferencing, etc.
* o Make the URL processing external functions which will fill-in a buffer
* structure we provide, or return an error and we will render a generic
* page and close the client.
@@ -44,16 +42,6 @@
#define MSHUTTINGDOWN(cm) ((cm->flags & ISC_HTTPDMGR_FLAGSHUTTINGDOWN) != 0)
#define MSETSHUTTINGDOWN(cm) (cm->flags |= ISC_HTTPDMGR_FLAGSHUTTINGDOWN)
#ifdef DEBUG_HTTPD
#define ENTER(x) do { fprintf(stderr, "ENTER %s\n", (x)); } while (0)
#define EXIT(x) do { fprintf(stderr, "EXIT %s\n", (x)); } while (0)
#define NOTICE(x) do { fprintf(stderr, "NOTICE %s\n", (x)); } while (0)
#else
#define ENTER(x) do { } while(0)
#define EXIT(x) do { } while(0)
#define NOTICE(x) do { } while(0)
#endif
#define HTTP_RECVLEN 1024
#define HTTP_SENDGROW 1024
#define HTTP_SEND_MAXLEN 10240
@@ -61,10 +49,19 @@
#define HTTPD_CLOSE 0x0001 /* Got a Connection: close header */
#define HTTPD_FOUNDHOST 0x0002 /* Got a Host: header */
#define HTTPD_KEEPALIVE 0x0004 /* Got a Connection: Keep-Alive */
#define HTTPD_ACCEPT_DEFLATE 0x0008
#define HTTPD_ACCEPT_DEFLATE 0x0008
#define HTTPD_MAGIC ISC_MAGIC('H', 't', 'p', 'd')
#define VALID_HTTPD(m) ISC_MAGIC_VALID(m, HTTPD_MAGIC)
#define HTTPDMGR_MAGIC ISC_MAGIC('H', 'p', 'd', 'm')
#define VALID_HTTPDMGR(m) ISC_MAGIC_VALID(m, HTTPDMGR_MAGIC)
/*% http client */
struct isc_httpd {
unsigned int magic; /* HTTPD_MAGIC */
isc_refcount_t references;
isc_httpdmgr_t *mgr; /*%< our parent */
ISC_LINK(isc_httpd_t) link;
unsigned int state;
@@ -96,8 +93,8 @@ struct isc_httpd {
* to the client.
*
* The bufflist is the list of buffers we are currently transmitting.
* The headerbuffer is where we render our headers to. If we run out of
* space when rendering a header, we will change the size of our
* The headerbuffer is where we render our headers to. If we run out
* of space when rendering a header, we will change the size of our
* buffer. We will not free it until we are finished, and will
* allocate an additional HTTP_SENDGROW bytes per header space grow.
*
@@ -126,6 +123,8 @@ struct isc_httpd {
/*% lightweight socket manager for httpd output */
struct isc_httpdmgr {
unsigned int magic; /* HTTPDMGR_MAGIC */
isc_refcount_t references;
isc_mem_t *mctx;
isc_socket_t *sock; /*%< listening socket */
isc_task_t *task; /*%< owning task */
@@ -203,48 +202,122 @@ struct isc_httpdmgr {
static void isc_httpd_accept(isc_task_t *, isc_event_t *);
static void isc_httpd_recvdone(isc_task_t *, isc_event_t *);
static void isc_httpd_senddone(isc_task_t *, isc_event_t *);
static void destroy_client(isc_httpd_t **);
static isc_result_t process_request(isc_httpd_t *, int);
static void httpdmgr_destroy(isc_httpdmgr_t *);
static isc_result_t grow_headerspace(isc_httpd_t *);
static void reset_client(isc_httpd_t *httpd);
static isc_httpdaction_t render_404;
static isc_httpdaction_t render_500;
#if ENABLE_AFL
static void (*finishhook)(void) = NULL;
#endif /* ENABLE_AFL */
static void maybe_destroy_httpd(isc_httpd_t *);
static void destroy_httpd(isc_httpd_t *);
static void maybe_destroy_httpdmgr(isc_httpdmgr_t *);
static void destroy_httpdmgr(isc_httpdmgr_t *);
static void
destroy_client(isc_httpd_t **httpdp) {
isc_httpd_t *httpd = *httpdp;
isc_httpdmgr_t *httpdmgr = httpd->mgr;
isc_httpdmgr_attach(isc_httpdmgr_t *, isc_httpdmgr_t **);
static void
isc_httpdmgr_detach(isc_httpdmgr_t **);
static void
maybe_destroy_httpd(isc_httpd_t *httpd) {
if (isc_refcount_decrement(&httpd->references) == 1) {
destroy_httpd(httpd);
}
}
static inline void
free_buffer(isc_mem_t *mctx, isc_buffer_t *buffer) {
isc_region_t r;
*httpdp = NULL;
isc_buffer_region(buffer, &r);
if (r.length > 0) {
isc_mem_put(mctx, r.base, r.length);
}
}
static void
destroy_httpd(isc_httpd_t *httpd) {
isc_httpdmgr_t *httpdmgr;
REQUIRE(VALID_HTTPD(httpd));
httpdmgr = httpd->mgr;
REQUIRE(VALID_HTTPDMGR(httpdmgr));
/*
* Unlink before calling isc_socket_detach so
* isc_httpdmgr_shutdown does not dereference a NULL pointer
* when calling isc_socket_cancel().
*/
LOCK(&httpdmgr->lock);
isc_socket_detach(&httpd->sock);
ISC_LIST_UNLINK(httpdmgr->running, httpd, link);
UNLOCK(&httpdmgr->lock);
isc_buffer_region(&httpd->headerbuffer, &r);
if (r.length > 0) {
isc_mem_put(httpdmgr->mctx, r.base, r.length);
}
httpd->magic = 0;
isc_refcount_destroy(&httpd->references);
isc_socket_detach(&httpd->sock);
isc_buffer_region(&httpd->compbuffer, &r);
if (r.length > 0) {
isc_mem_put(httpdmgr->mctx, r.base, r.length);
}
free_buffer(httpdmgr->mctx, &httpd->headerbuffer);
free_buffer(httpdmgr->mctx, &httpd->compbuffer);
isc_mem_put(httpdmgr->mctx, httpd, sizeof(isc_httpd_t));
UNLOCK(&httpdmgr->lock);
if (finishhook != NULL)
#if ENABLE_AFL
if (finishhook != NULL) {
finishhook();
}
#endif /* ENABLE_AFL */
httpdmgr_destroy(httpdmgr);
isc_httpdmgr_detach(&httpdmgr);
}
static inline isc_result_t
httpdmgr_socket_accept(isc_task_t *task, isc_httpdmgr_t* httpdmgr)
{
isc_result_t result = ISC_R_SUCCESS;
/* decremented in isc_httpd_accept */
isc_refcount_increment(&httpdmgr->references);
result = isc_socket_accept(httpdmgr->sock, task, isc_httpd_accept,
httpdmgr);
if (result != ISC_R_SUCCESS) {
INSIST(isc_refcount_decrement(&httpdmgr->references) > 1);
}
return (result);
}
static inline void
httpd_socket_recv(isc_httpd_t *httpd, isc_region_t *region, isc_task_t *task)
{
isc_result_t result = ISC_R_SUCCESS;
/* decremented in isc_httpd_recvdone */
(void)isc_refcount_increment(&httpd->references);
result = isc_socket_recv(httpd->sock, region, 1, task,
isc_httpd_recvdone, httpd);
if (result != ISC_R_SUCCESS) {
INSIST(isc_refcount_decrement(&httpd->references) > 1);
}
}
static inline void
httpd_socket_send(isc_httpd_t *httpd, isc_region_t *region, isc_task_t *task)
{
isc_result_t result = ISC_R_SUCCESS;
/* decremented in isc_httpd_senddone */
(void)isc_refcount_increment(&httpd->references);
result = isc_socket_send(httpd->sock, region, task,
isc_httpd_senddone, httpd);
if (result != ISC_R_SUCCESS) {
INSIST(isc_refcount_decrement(&httpd->references) > 1);
}
}
isc_result_t
@@ -264,22 +337,25 @@ isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
httpdmgr = isc_mem_get(mctx, sizeof(isc_httpdmgr_t));
*httpdmgr = (isc_httpdmgr_t){
.timermgr = tmgr, /* XXXMLG no attach function? */
.client_ok = client_ok,
.ondestroy = ondestroy,
.cb_arg = cb_arg,
.render_404 = render_404,
.render_500 = render_500
};
isc_mutex_init(&httpdmgr->lock);
httpdmgr->mctx = NULL;
isc_mem_attach(mctx, &httpdmgr->mctx);
httpdmgr->sock = NULL;
isc_socket_attach(sock, &httpdmgr->sock);
httpdmgr->task = NULL;
isc_task_attach(task, &httpdmgr->task);
httpdmgr->timermgr = tmgr; /* XXXMLG no attach function? */
httpdmgr->client_ok = client_ok;
httpdmgr->ondestroy = ondestroy;
httpdmgr->cb_arg = cb_arg;
httpdmgr->flags = 0;
ISC_LIST_INIT(httpdmgr->running);
ISC_LIST_INIT(httpdmgr->urls);
isc_refcount_init(&httpdmgr->references, 1);
/* XXXMLG ignore errors on isc_socket_listen() */
result = isc_socket_listen(sock, SOMAXCONN);
if (result != ISC_R_SUCCESS) {
@@ -291,17 +367,21 @@ isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
(void)isc_socket_filter(sock, "httpready");
result = isc_socket_accept(sock, task, isc_httpd_accept, httpdmgr);
if (result != ISC_R_SUCCESS)
goto cleanup;
httpdmgr->magic = HTTPDMGR_MAGIC;
httpdmgr->render_404 = render_404;
httpdmgr->render_500 = render_500;
result = httpdmgr_socket_accept(task, httpdmgr);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
*httpdmgrp = httpdmgr;
return (ISC_R_SUCCESS);
cleanup:
httpdmgr->magic = 0;
isc_refcount_decrement(&httpdmgr->references);
isc_refcount_destroy(&httpdmgr->references);
isc_task_detach(&httpdmgr->task);
isc_socket_detach(&httpdmgr->sock);
isc_mem_detach(&httpdmgr->mctx);
@@ -311,30 +391,43 @@ isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
}
static void
httpdmgr_destroy(isc_httpdmgr_t *httpdmgr) {
isc_mem_t *mctx;
isc_httpdmgr_attach(isc_httpdmgr_t *source, isc_httpdmgr_t **targetp) {
REQUIRE(VALID_HTTPDMGR(source));
REQUIRE(targetp != NULL && *targetp == NULL);
isc_refcount_increment(&source->references);
*targetp = source;
}
static void
isc_httpdmgr_detach(isc_httpdmgr_t **httpdmgrp) {
REQUIRE(httpdmgrp != NULL && VALID_HTTPDMGR(*httpdmgrp));
isc_httpdmgr_t *httpdmgr = *httpdmgrp;
*httpdmgrp = NULL;
maybe_destroy_httpdmgr(httpdmgr);
}
static void
maybe_destroy_httpdmgr(isc_httpdmgr_t *httpdmgr) {
if (isc_refcount_decrement(&httpdmgr->references) == 1) {
destroy_httpdmgr(httpdmgr);
}
}
static void
destroy_httpdmgr(isc_httpdmgr_t *httpdmgr) {
isc_httpdurl_t *url;
ENTER("httpdmgr_destroy");
isc_refcount_destroy(&httpdmgr->references);
LOCK(&httpdmgr->lock);
if (!MSHUTTINGDOWN(httpdmgr)) {
NOTICE("httpdmgr_destroy not shutting down yet");
UNLOCK(&httpdmgr->lock);
return;
}
httpdmgr->magic = 0;
/*
* If all clients are not shut down, don't do anything yet.
*/
if (!ISC_LIST_EMPTY(httpdmgr->running)) {
NOTICE("httpdmgr_destroy clients still active");
UNLOCK(&httpdmgr->lock);
return;
}
NOTICE("httpdmgr_destroy detaching socket, task, and timermgr");
INSIST(MSHUTTINGDOWN(httpdmgr));
INSIST(ISC_LIST_EMPTY(httpdmgr->running));
isc_socket_detach(&httpdmgr->sock);
isc_task_detach(&httpdmgr->task);
@@ -355,13 +448,10 @@ httpdmgr_destroy(isc_httpdmgr_t *httpdmgr) {
UNLOCK(&httpdmgr->lock);
isc_mutex_destroy(&httpdmgr->lock);
if (httpdmgr->ondestroy != NULL)
if (httpdmgr->ondestroy != NULL) {
(httpdmgr->ondestroy)(httpdmgr->cb_arg);
mctx = httpdmgr->mctx;
isc_mem_putanddetach(&mctx, httpdmgr, sizeof(isc_httpdmgr_t));
EXIT("httpdmgr_destroy");
}
isc_mem_putanddetach(&httpdmgr->mctx, httpdmgr, sizeof(isc_httpdmgr_t));
}
#define LENGTHOK(s) (httpd->recvbuf - (s) < (int)httpd->recvlen)
@@ -440,8 +530,6 @@ process_request(isc_httpd_t *httpd, int length) {
char *p;
int delim;
ENTER("request");
httpd->recvlen += length;
httpd->recvbuf[httpd->recvlen] = 0;
@@ -591,37 +679,70 @@ process_request(isc_httpd_t *httpd, int length) {
&& ((httpd->flags & HTTPD_FOUNDHOST) == 0))
return (ISC_R_RANGE);
EXIT("request");
return (ISC_R_SUCCESS);
}
static void
isc_httpd_accept(isc_task_t *task, isc_event_t *ev) {
isc_result_t result;
isc_httpdmgr_t *httpdmgr = ev->ev_arg;
isc_httpd_create(isc_httpdmgr_t *httpdmgr, isc_socket_t *sock,
isc_httpd_t **httpdp)
{
isc_httpd_t *httpd;
char *headerdata;
REQUIRE(VALID_HTTPDMGR(httpdmgr));
REQUIRE(httpdp != NULL && *httpdp == NULL);
httpd = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpd_t));
*httpd = (isc_httpd_t){
.sock = sock
};
isc_httpdmgr_attach(httpdmgr, &httpd->mgr);
isc_refcount_init(&httpd->references, 1);
ISC_HTTPD_SETRECV(httpd);
isc_socket_setname(httpd->sock, "httpd", NULL);
/*
* Initialize the buffer for our headers.
*/
headerdata = isc_mem_get(httpdmgr->mctx, HTTP_SENDGROW);
isc_buffer_init(&httpd->headerbuffer, headerdata, HTTP_SENDGROW);
isc_buffer_initnull(&httpd->compbuffer);
isc_buffer_initnull(&httpd->bodybuffer);
reset_client(httpd);
ISC_LINK_INIT(httpd, link);
ISC_LIST_APPEND(httpdmgr->running, httpd, link);
httpd->magic = HTTPD_MAGIC;
*httpdp = httpd;
}
static void
isc_httpd_accept(isc_task_t *task, isc_event_t *ev) {
isc_httpdmgr_t *httpdmgr = ev->ev_arg;
isc_httpd_t *httpd = NULL;
isc_region_t r;
isc_socket_newconnev_t *nev = (isc_socket_newconnev_t *)ev;
isc_sockaddr_t peeraddr;
char *headerdata;
ENTER("accept");
REQUIRE(VALID_HTTPDMGR(httpdmgr));
LOCK(&httpdmgr->lock);
if (MSHUTTINGDOWN(httpdmgr)) {
NOTICE("accept shutting down, goto out");
goto out;
}
if (nev->result == ISC_R_CANCELED) {
NOTICE("accept canceled, goto out");
goto out;
}
if (nev->result != ISC_R_SUCCESS) {
/* XXXMLG log failure */
NOTICE("accept returned failure, goto requeue");
goto requeue;
}
@@ -632,51 +753,25 @@ isc_httpd_accept(isc_task_t *task, isc_event_t *ev) {
goto requeue;
}
httpd = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpd_t));
httpd->mgr = httpdmgr;
ISC_LINK_INIT(httpd, link);
ISC_LIST_APPEND(httpdmgr->running, httpd, link);
ISC_HTTPD_SETRECV(httpd);
httpd->sock = nev->newsocket;
isc_socket_setname(httpd->sock, "httpd", NULL);
httpd->flags = 0;
/*
* Initialize the buffer for our headers.
*/
headerdata = isc_mem_get(httpdmgr->mctx, HTTP_SENDGROW);
isc_buffer_init(&httpd->headerbuffer, headerdata, HTTP_SENDGROW);
isc_buffer_initnull(&httpd->compbuffer);
isc_buffer_initnull(&httpd->bodybuffer);
httpd->sendbuffer = NULL;
reset_client(httpd);
isc_httpd_create(httpdmgr, nev->newsocket, &httpd);
r.base = (unsigned char *)httpd->recvbuf;
r.length = HTTP_RECVLEN - 1;
result = isc_socket_recv(httpd->sock, &r, 1, task, isc_httpd_recvdone,
httpd);
/* FIXME!!! */
POST(result);
NOTICE("accept queued recv on socket");
httpd_socket_recv(httpd, &r, task);
requeue:
result = isc_socket_accept(httpdmgr->sock, task, isc_httpd_accept,
httpdmgr);
if (result != ISC_R_SUCCESS) {
/* XXXMLG what to do? Log failure... */
NOTICE("accept could not reaccept due to failure");
}
(void)httpdmgr_socket_accept(task, httpdmgr);
out:
UNLOCK(&httpdmgr->lock);
httpdmgr_destroy(httpdmgr);
if (httpd != NULL) {
maybe_destroy_httpd(httpd);
}
maybe_destroy_httpdmgr(httpdmgr);
isc_event_free(&ev);
EXIT("accept");
}
static isc_result_t
@@ -828,30 +923,25 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
bool is_compressed = false;
char datebuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
ENTER("recv");
REQUIRE(VALID_HTTPD(httpd));
INSIST(ISC_HTTPD_ISRECV(httpd));
if (sev->result != ISC_R_SUCCESS) {
NOTICE("recv destroying client");
destroy_client(&httpd);
goto out;
}
result = process_request(httpd, sev->n);
if (result == ISC_R_NOTFOUND) {
if (httpd->recvlen >= HTTP_RECVLEN - 1) {
destroy_client(&httpd);
goto out;
}
r.base = (unsigned char *)httpd->recvbuf + httpd->recvlen;
r.length = HTTP_RECVLEN - httpd->recvlen - 1;
/* check return code? */
(void)isc_socket_recv(httpd->sock, &r, 1, task,
isc_httpd_recvdone, httpd);
httpd_socket_recv(httpd, &r, task);
goto out;
} else if (result != ISC_R_SUCCESS) {
destroy_client(&httpd);
goto out;
}
@@ -864,13 +954,16 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
isc_buffer_initnull(&httpd->bodybuffer);
isc_time_now(&now);
isc_time_formathttptimestamp(&now, datebuf, sizeof(datebuf));
LOCK(&httpd->mgr->lock);
url = ISC_LIST_HEAD(httpd->mgr->urls);
while (url != NULL) {
if (strcmp(httpd->url, url->url) == 0)
break;
url = ISC_LIST_NEXT(url, link);
}
if (url == NULL)
UNLOCK(&httpd->mgr->lock);
if (url == NULL) {
result = httpd->mgr->render_404(httpd->url, NULL,
httpd->querystring,
NULL, NULL,
@@ -880,7 +973,7 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
&httpd->bodybuffer,
&httpd->freecb,
&httpd->freecb_arg);
else
} else {
result = url->action(httpd->url, url,
httpd->querystring,
httpd->headers,
@@ -888,6 +981,7 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
&httpd->retcode, &httpd->retmsg,
&httpd->mimetype, &httpd->bodybuffer,
&httpd->freecb, &httpd->freecb_arg);
}
if (result != ISC_R_SUCCESS) {
result = httpd->mgr->render_500(httpd->url, url,
httpd->querystring,
@@ -911,8 +1005,9 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
#endif
isc_httpd_response(httpd);
if ((httpd->flags & HTTPD_KEEPALIVE) != 0)
if ((httpd->flags & HTTPD_KEEPALIVE) != 0) {
isc_httpd_addheader(httpd, "Connection", "Keep-Alive");
}
isc_httpd_addheader(httpd, "Content-Type", httpd->mimetype);
isc_httpd_addheader(httpd, "Date", datebuf);
isc_httpd_addheader(httpd, "Expires", datebuf);
@@ -934,7 +1029,7 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
if (is_compressed == true) {
isc_httpd_addheader(httpd, "Content-Encoding", "deflate");
isc_httpd_addheaderuint(httpd, "Content-Length",
isc_buffer_usedlength(&httpd->compbuffer));
isc_buffer_usedlength(&httpd->compbuffer));
} else {
isc_httpd_addheaderuint(httpd, "Content-Length",
isc_buffer_usedlength(&httpd->bodybuffer));
@@ -958,23 +1053,22 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) {
*/
isc_buffer_usedregion(httpd->sendbuffer, &r);
/* check return code? */
(void)isc_socket_send(httpd->sock, &r, task,
isc_httpd_senddone, httpd);
httpd_socket_send(httpd, &r, task);
out:
maybe_destroy_httpd(httpd);
isc_event_free(&ev);
EXIT("recv");
}
void
isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp) {
isc_httpdmgr_t *httpdmgr;
isc_httpd_t *httpd;
REQUIRE(httpdmgrp != NULL);
httpdmgr = *httpdmgrp;
*httpdmgrp = NULL;
ENTER("isc_httpdmgr_shutdown");
REQUIRE(VALID_HTTPDMGR(httpdmgr));
LOCK(&httpdmgr->lock);
@@ -991,7 +1085,8 @@ isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp) {
UNLOCK(&httpdmgr->lock);
EXIT("isc_httpdmgr_shutdown");
maybe_destroy_httpdmgr(httpdmgr);
}
static isc_result_t
@@ -1019,6 +1114,8 @@ isc_httpd_response(isc_httpd_t *httpd) {
isc_result_t result;
unsigned int needlen;
REQUIRE(VALID_HTTPD(httpd));
needlen = strlen(httpd->protocol) + 1; /* protocol + space */
needlen += 3 + 1; /* room for response code, always 3 bytes */
needlen += strlen(httpd->retmsg) + 2; /* return msg + CRLF */
@@ -1035,15 +1132,16 @@ isc_httpd_response(isc_httpd_t *httpd) {
}
isc_result_t
isc_httpd_addheader(isc_httpd_t *httpd, const char *name,
const char *val)
{
isc_httpd_addheader(isc_httpd_t *httpd, const char *name, const char *val) {
isc_result_t result;
unsigned int needlen;
REQUIRE(VALID_HTTPD(httpd));
needlen = strlen(name); /* name itself */
if (val != NULL)
if (val != NULL) {
needlen += 2 + strlen(val); /* :<space> and val */
}
needlen += 2; /* CRLF */
while (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
@@ -1065,6 +1163,8 @@ isc_result_t
isc_httpd_endheaders(isc_httpd_t *httpd) {
isc_result_t result;
REQUIRE(VALID_HTTPD(httpd));
while (isc_buffer_availablelength(&httpd->headerbuffer) < 2) {
result = grow_headerspace(httpd);
if (result != ISC_R_SUCCESS)
@@ -1080,6 +1180,8 @@ isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val) {
unsigned int needlen;
char buf[sizeof "18446744073709551616"];
REQUIRE(VALID_HTTPD(httpd));
snprintf(buf, sizeof(buf), "%d", val);
needlen = strlen(name); /* name itself */
@@ -1102,7 +1204,8 @@ isc_httpd_senddone(isc_task_t *task, isc_event_t *ev) {
isc_region_t r;
isc_socketevent_t *sev = (isc_socketevent_t *)ev;
ENTER("senddone");
REQUIRE(VALID_HTTPD(httpd));
INSIST(ISC_HTTPD_ISSEND(httpd));
isc_buffer_free(&httpd->sendbuffer);
@@ -1120,34 +1223,28 @@ isc_httpd_senddone(isc_task_t *task, isc_event_t *ev) {
b = &httpd->bodybuffer;
httpd->freecb(b, httpd->freecb_arg);
}
NOTICE("senddone free callback performed");
}
if (sev->result != ISC_R_SUCCESS) {
destroy_client(&httpd);
goto out;
}
if ((httpd->flags & HTTPD_CLOSE) != 0) {
destroy_client(&httpd);
goto out;
}
ISC_HTTPD_SETRECV(httpd);
NOTICE("senddone restarting recv on socket");
reset_client(httpd);
r.base = (unsigned char *)httpd->recvbuf;
r.length = HTTP_RECVLEN - 1;
/* check return code? */
(void)isc_socket_recv(httpd->sock, &r, 1, task,
isc_httpd_recvdone, httpd);
httpd_socket_recv(httpd, &r, task);
out:
maybe_destroy_httpd(httpd);
isc_event_free(&ev);
EXIT("senddone");
}
static void
@@ -1178,6 +1275,8 @@ isc_result_t
isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
isc_httpdaction_t *func, void *arg)
{
/* REQUIRE(VALID_HTTPDMGR(httpdmgr)); Dummy function */
return (isc_httpdmgr_addurl2(httpdmgr, url, false, func, arg));
}
@@ -1188,6 +1287,8 @@ isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url,
{
isc_httpdurl_t *item;
REQUIRE(VALID_HTTPDMGR(httpdmgr));
if (url == NULL) {
httpdmgr->render_404 = func;
return (ISC_R_SUCCESS);
@@ -1203,7 +1304,10 @@ isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url,
isc_time_now(&item->loadtime);
ISC_LINK_INIT(item, link);
LOCK(&httpdmgr->lock);
ISC_LIST_APPEND(httpdmgr->urls, item, link);
UNLOCK(&httpdmgr->lock);
return (ISC_R_SUCCESS);
}
@@ -1211,5 +1315,9 @@ isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url,
void
isc_httpd_setfinishhook(void (*fn)(void))
{
#if ENABLE_AFL
finishhook = fn;
#else /* ENABLE_AFL */
UNUSED(fn);
#endif /* ENABLE_AFL */
}
+1 -1
View File
@@ -35,7 +35,7 @@ struct isc_httpdurl {
char *url;
isc_httpdaction_t *action;
void *action_arg;
bool isstatic;
bool isstatic;
isc_time_t loadtime;
ISC_LINK(isc_httpdurl_t) link;
};
+5
View File
@@ -15,6 +15,10 @@
/*%
* Performance
*/
#ifdef CPPCHECK
#define ISC_LIKELY(x) (x)
#define ISC_UNLIKELY(x) (x)
#else
#ifdef HAVE_BUILTIN_EXPECT
#define ISC_LIKELY(x) __builtin_expect(!!(x), 1)
#define ISC_UNLIKELY(x) __builtin_expect(!!(x), 0)
@@ -22,5 +26,6 @@
#define ISC_LIKELY(x) (x)
#define ISC_UNLIKELY(x) (x)
#endif
#endif
#endif /* ISC_LIKELY_H */
+6 -1
View File
@@ -285,12 +285,17 @@ extern void mock_assert(const int result, const char* const expression,
#ifdef UNIT_TESTING
#define RUNTIME_CHECK(expression) \
mock_assert((int)(expression), #expression, __FILE__, __LINE__)
((!(expression)) ? \
(mock_assert(0, #expression, __FILE__, __LINE__), abort()) : (void)0)
#else /* UNIT_TESTING */
#ifndef CPPCHECK
/*% Runtime Check */
#define RUNTIME_CHECK(cond) ISC_ERROR_RUNTIMECHECK(cond)
#else
#define RUNTIME_CHECK(e) if (!(e)) abort()
#endif
#endif /* UNIT_TESTING */
+7
View File
@@ -603,6 +603,13 @@ isc__nmsocket_prep_destroy(isc_nmsocket_t *sock);
* if there are no remaining references or active handles.
*/
bool
isc__nmsocket_active(isc_nmsocket_t *sock);
/*%<
* Determine whether 'sock' is active by checking 'sock->active'
* or, for child sockets, 'sock->parent->active'.
*/
void
isc__nm_async_closecb(isc__networker_t *worker, isc__netievent_t *ev0);
/*%<
+9 -3
View File
@@ -681,7 +681,7 @@ isc__nm_enqueue_ievent(isc__networker_t *worker, isc__netievent_t *event) {
uv_async_send(&worker->async);
}
static bool
bool
isc__nmsocket_active(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
if (sock->parent != NULL) {
@@ -1158,7 +1158,7 @@ nmhandle_deactivate(isc_nmsocket_t *sock, isc_nmhandle_t *handle) {
void
isc_nmhandle_unref(isc_nmhandle_t *handle) {
isc_nmsocket_t *sock = NULL;
isc_nmsocket_t *sock = NULL, *tmp = NULL;
REQUIRE(VALID_NMHANDLE(handle));
@@ -1199,8 +1199,14 @@ isc_nmhandle_unref(isc_nmhandle_t *handle) {
}
}
/*
* Temporarily reference the socket to ensure that it can't
* be deleted by another thread while we're deactivating the
* handle.
*/
isc_nmsocket_attach(sock, &tmp);
nmhandle_deactivate(sock, handle);
nmsocket_maybe_destroy(sock);
isc_nmsocket_detach(&tmp);
}
void *
+1 -1
View File
@@ -419,7 +419,7 @@ stoplistening(isc_nmsocket_t *sock) {
event = isc__nm_get_ievent(sock->mgr, netievent_tcpchildstop);
isc_nmsocket_attach(&sock->children[i], &event->sock);
if (i == sock->tid) {
if (isc_nm_tid() == sock->children[i].tid) {
isc__nm_async_tcpchildstop(&sock->mgr->workers[i],
(isc__netievent_t *) event);
isc__nm_put_ievent(sock->mgr, event);
+1 -2
View File
@@ -470,8 +470,7 @@ isc__nm_tcpdns_send(isc_nmhandle_t *handle, isc_region_t *region,
REQUIRE(sock->type == isc_nm_tcpdnssocket);
if (sock->outer == NULL) {
/* The socket is closed, just issue the callback */
cb(handle, ISC_R_FAILURE, cbarg);
/* The socket is closed */
return (ISC_R_NOTCONNECTED);
}
+24 -8
View File
@@ -122,6 +122,7 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
REQUIRE(sock->type == isc_nm_udpsocket);
REQUIRE(sock->iface != NULL);
REQUIRE(sock->parent != NULL);
REQUIRE(sock->tid == isc_nm_tid());
uv_udp_init(&worker->loop, &sock->uv_handle.udp);
uv_handle_set_data(&sock->uv_handle.handle, NULL);
@@ -164,7 +165,8 @@ udp_close_cb(uv_handle_t *handle) {
static void
stop_udp_child(isc_nmsocket_t *sock) {
INSIST(sock->type == isc_nm_udpsocket);
REQUIRE(sock->type == isc_nm_udpsocket);
REQUIRE(sock->tid == isc_nm_tid());
uv_udp_recv_stop(&sock->uv_handle.udp);
uv_close((uv_handle_t *) &sock->uv_handle.udp, udp_close_cb);
@@ -179,19 +181,25 @@ stop_udp_child(isc_nmsocket_t *sock) {
static void
stoplistening(isc_nmsocket_t *sock) {
REQUIRE(sock->type == isc_nm_udplistener);
/*
* Socket is already closing; there's nothing to do.
*/
if (uv_is_closing((uv_handle_t *) &sock->uv_handle.udp)) {
if (!isc__nmsocket_active(sock)) {
return;
}
INSIST(sock->type == isc_nm_udplistener);
/*
* Mark it inactive now so that all sends will be ignored
* and we won't try to stop listening again.
*/
atomic_store(&sock->active, false);
for (int i = 0; i < sock->nchildren; i++) {
isc__netievent_udpstop_t *event = NULL;
if (i == sock->tid) {
if (isc_nm_tid() == sock->children[i].tid) {
stop_udp_child(&sock->children[i]);
continue;
}
@@ -358,7 +366,11 @@ isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region,
/*
* Simulate a firewall blocking UDP packets bigger than
* 'maxudp' bytes.
* 'maxudp' bytes, for testing purposes.
*
* The client would ordinarily have unreferenced the handle
* in the callback, but that won't happen in this case, so
* we need to do so here.
*/
if (maxudp != 0 && region->length > maxudp) {
isc_nmhandle_unref(handle);
@@ -371,8 +383,12 @@ isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region,
} else if (sock->type == isc_nm_udplistener) {
psock = sock;
} else {
isc_nmhandle_unref(handle);
return (ISC_R_UNEXPECTED);
INSIST(0);
ISC_UNREACHABLE();
}
if (!isc__nmsocket_active(sock)) {
return (ISC_R_CANCELED);
}
if (isc__nm_in_netthread()) {
@@ -425,7 +441,7 @@ isc__nm_async_udpsend(isc__networker_t *worker, isc__netievent_t *ev0) {
REQUIRE(worker->id == ievent->sock->tid);
if (atomic_load(&ievent->sock->active)) {
if (isc__nmsocket_active(ievent->sock)) {
udp_send_direct(ievent->sock, ievent->req, &ievent->peer);
} else {
ievent->req->cb.send(ievent->req->handle,
+2 -2
View File
@@ -103,10 +103,10 @@ void isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line);
#if ISC_MUTEX_PROFILE
#define isc_mutex_destroy(mp) \
(RUNTIME_CHECK(pthread_mutex_destroy((&(mp)->mutex)) == 0))
RUNTIME_CHECK(pthread_mutex_destroy((&(mp)->mutex)) == 0)
#else
#define isc_mutex_destroy(mp) \
(RUNTIME_CHECK(pthread_mutex_destroy((mp)) == 0))
RUNTIME_CHECK(pthread_mutex_destroy((mp)) == 0)
#endif
#if ISC_MUTEX_PROFILE
+31 -11
View File
@@ -78,13 +78,17 @@
***/
typedef enum {
task_state_idle, task_state_ready, task_state_paused,
task_state_running, task_state_done
task_state_idle, /* not doing anything, events queue empty */
task_state_ready, /* waiting in worker's queue */
task_state_paused, /* not running, paused */
task_state_pausing, /* running, waiting to be paused */
task_state_running, /* actively processing events */
task_state_done /* shutting down, no events or references */
} task_state_t;
#if defined(HAVE_LIBXML2) || defined(HAVE_JSON_C)
static const char *statenames[] = {
"idle", "ready", "running", "done",
"idle", "ready", "paused", "pausing", "running", "done",
};
#endif
@@ -381,6 +385,7 @@ task_shutdown(isc__task_t *task) {
}
INSIST(task->state == task_state_ready ||
task->state == task_state_paused ||
task->state == task_state_pausing ||
task->state == task_state_running);
/*
@@ -502,7 +507,8 @@ task_send(isc__task_t *task, isc_event_t **eventp, int c) {
}
INSIST(task->state == task_state_ready ||
task->state == task_state_running ||
task->state == task_state_paused);
task->state == task_state_paused ||
task->state == task_state_pausing);
ENQUEUE(task->events, event, ev_link);
task->nevents++;
*eventp = NULL;
@@ -1200,10 +1206,12 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
finished = true;
task->state = task_state_done;
} else {
/* It might be paused */
if (task->state ==
task_state_running) {
task->state = task_state_idle;
} else if (task->state ==
task_state_pausing) {
task->state = task_state_paused;
}
}
done = true;
@@ -1226,6 +1234,9 @@ dispatch(isc__taskmgr_t *manager, unsigned int threadid) {
*/
task->state = task_state_ready;
requeue = true;
} else if (task->state ==
task_state_pausing) {
task->state = task_state_paused;
}
done = true;
}
@@ -1682,8 +1693,12 @@ isc_task_pause(isc_task_t *task0) {
INSIST(task->state == task_state_idle ||
task->state == task_state_ready ||
task->state == task_state_running);
running = (task->state == task_state_running);
task->state = task_state_paused;
if (task->state == task_state_running) {
running = true;
task->state = task_state_pausing;
} else {
task->state = task_state_paused;
}
UNLOCK(&task->lock);
if (running) {
@@ -1706,13 +1721,18 @@ isc_task_unpause(isc_task_t *task0) {
REQUIRE(ISCAPI_TASK_VALID(task0));
LOCK(&task->lock);
INSIST(task->state == task_state_paused);
if (!EMPTY(task->events)) {
task->state = task_state_ready;
was_idle = true;
INSIST(task->state == task_state_paused ||
task->state == task_state_pausing);
/* If the task was pausing we can't reschedule it */
if (task->state == task_state_pausing) {
task->state = task_state_running;
} else {
task->state = task_state_idle;
}
if (task->state == task_state_idle && !EMPTY(task->events)) {
task->state = task_state_ready;
was_idle = true;
}
UNLOCK(&task->lock);
if (was_idle) {
+79 -1
View File
@@ -48,7 +48,7 @@ static isc_condition_t cv;
atomic_int_fast32_t counter;
static int active[10];
static atomic_bool done;
static atomic_bool done, done2;
static int
_setup(void **state) {
@@ -429,6 +429,83 @@ privilege_drop(void **state) {
assert_null(task2);
}
static void
sleep_cb(isc_task_t *task, isc_event_t *event) {
UNUSED(task);
int p = *(int*)event->ev_arg;
if (p == 1) {
/*
* Signal the main thread that we're running, so that
* it can trigger the race.
*/
LOCK(&lock);
atomic_store(&done2, true);
SIGNAL(&cv);
UNLOCK(&lock);
/*
* Wait for the operations in the main thread to be finished.
*/
LOCK(&lock);
while (!atomic_load(&done)) {
WAIT(&cv, &lock);
}
UNLOCK(&lock);
} else {
/*
* Wait for the operations in the main thread to be finished.
*/
LOCK(&lock);
atomic_store(&done2, true);
SIGNAL(&cv);
UNLOCK(&lock);
}
isc_event_free(&event);
}
static void
pause_unpause(void **state) {
isc_result_t result;
isc_task_t *task = NULL;
isc_event_t *event1,*event2 = NULL;
UNUSED(state);
atomic_store(&done, false);
atomic_store(&done2, false);
result = isc_task_create(taskmgr, 0, &task);
assert_int_equal(result, ISC_R_SUCCESS);
event1 = isc_event_allocate(test_mctx, task, ISC_TASKEVENT_TEST,
sleep_cb, &(int){1}, sizeof (isc_event_t));
assert_non_null(event1);
event2 = isc_event_allocate(test_mctx, task, ISC_TASKEVENT_TEST,
sleep_cb, &(int){2}, sizeof (isc_event_t));
assert_non_null(event2);
isc_task_send(task, &event1);
isc_task_send(task, &event2);
/* Wait for event1 to be running */
LOCK(&lock);
while (!atomic_load(&done2)) {
WAIT(&cv, &lock);
}
UNLOCK(&lock);
/* Pause-unpause-detach is what causes the race */
isc_task_pause(task);
isc_task_unpause(task);
isc_task_detach(&task);
/* Signal event1 to finish */
LOCK(&lock);
atomic_store(&done2, false);
atomic_store(&done, true);
SIGNAL(&cv);
UNLOCK(&lock);
/* Wait for event2 to finish */
LOCK(&lock);
while (!atomic_load(&done2)) {
WAIT(&cv, &lock);
}
UNLOCK(&lock);
}
/*
* Basic task functions:
*/
@@ -1482,6 +1559,7 @@ main(int argc, char **argv) {
cmocka_unit_test_setup_teardown(purgeevent, _setup2, _teardown),
cmocka_unit_test_setup_teardown(purgeevent_notpurge,
_setup, _teardown),
cmocka_unit_test_setup_teardown(pause_unpause, _setup, _teardown),
};
int c;
+19 -13
View File
@@ -239,7 +239,7 @@ isc_timer_create(isc_timermgr_t *manager0, isc_timertype_t type,
isc_task_t *task, isc_taskaction_t action, void *arg,
isc_timer_t **timerp)
{
isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
isc__timermgr_t *manager;
isc__timer_t *timer;
isc_result_t result;
isc_time_t now;
@@ -252,7 +252,8 @@ isc_timer_create(isc_timermgr_t *manager0, isc_timertype_t type,
* in 'timerp'.
*/
REQUIRE(VALID_MANAGER(manager));
REQUIRE(VALID_MANAGER(manager0));
manager = (isc__timermgr_t *)manager0;
REQUIRE(task != NULL);
REQUIRE(action != NULL);
if (expires == NULL)
@@ -352,7 +353,7 @@ isc_timer_reset(isc_timer_t *timer0, isc_timertype_t type,
const isc_time_t *expires, const isc_interval_t *interval,
bool purge)
{
isc__timer_t *timer = (isc__timer_t *)timer0;
isc__timer_t *timer;
isc_time_t now;
isc__timermgr_t *manager;
isc_result_t result;
@@ -363,7 +364,8 @@ isc_timer_reset(isc_timer_t *timer0, isc_timertype_t type,
* are purged from its task's event queue.
*/
REQUIRE(VALID_TIMER(timer));
REQUIRE(VALID_TIMER(timer0));
timer = (isc__timer_t *)timer0;
manager = timer->manager;
REQUIRE(VALID_MANAGER(manager));
@@ -425,10 +427,11 @@ isc_timer_reset(isc_timer_t *timer0, isc_timertype_t type,
isc_timertype_t
isc_timer_gettype(isc_timer_t *timer0) {
isc__timer_t *timer = (isc__timer_t *)timer0;
isc__timer_t *timer;
isc_timertype_t t;
REQUIRE(VALID_TIMER(timer));
REQUIRE(VALID_TIMER(timer0));
timer = (isc__timer_t *)timer0;
LOCK(&timer->lock);
t = timer->type;
@@ -439,7 +442,7 @@ isc_timer_gettype(isc_timer_t *timer0) {
isc_result_t
isc_timer_touch(isc_timer_t *timer0) {
isc__timer_t *timer = (isc__timer_t *)timer0;
isc__timer_t *timer;
isc_result_t result;
isc_time_t now;
@@ -447,7 +450,8 @@ isc_timer_touch(isc_timer_t *timer0) {
* Set the last-touched time of 'timer' to the current time.
*/
REQUIRE(VALID_TIMER(timer));
REQUIRE(VALID_TIMER(timer0));
timer = (isc__timer_t *)timer0;
LOCK(&timer->lock);
@@ -470,13 +474,14 @@ isc_timer_touch(isc_timer_t *timer0) {
void
isc_timer_attach(isc_timer_t *timer0, isc_timer_t **timerp) {
isc__timer_t *timer = (isc__timer_t *)timer0;
isc__timer_t *timer;
/*
* Attach *timerp to timer.
*/
REQUIRE(VALID_TIMER(timer));
REQUIRE(VALID_TIMER(timer0));
timer = (isc__timer_t *)timer0;
REQUIRE(timerp != NULL && *timerp == NULL);
isc_refcount_increment(&timer->references);
@@ -661,8 +666,8 @@ static void
set_index(void *what, unsigned int index) {
isc__timer_t *timer;
REQUIRE(VALID_TIMER(what));
timer = what;
REQUIRE(VALID_TIMER(timer));
timer->index = index;
}
@@ -707,9 +712,10 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
void
isc_timermgr_poke(isc_timermgr_t *manager0) {
isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
isc__timermgr_t *manager;
REQUIRE(VALID_MANAGER(manager));
REQUIRE(VALID_MANAGER(manager0));
manager = (isc__timermgr_t *)manager0;
SIGNAL(&manager->wakeup);
}
+21 -1
View File
@@ -381,8 +381,9 @@ ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
r.base[1] = client->message->id & 0xff;
result = client_sendpkg(client, &buffer);
if (result == ISC_R_SUCCESS)
if (result == ISC_R_SUCCESS) {
return;
}
done:
if (client->tcpbuf != NULL) {
@@ -392,6 +393,7 @@ ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
}
ns_client_drop(client, result);
isc_nmhandle_unref(client->handle);
}
void
@@ -596,6 +598,10 @@ ns_client_send(ns_client_t *client) {
isc_nmhandle_ref(client->handle);
result = client_sendpkg(client, &tcpbuffer);
if (result != ISC_R_SUCCESS) {
/* We won't get a callback to clean it up */
isc_nmhandle_unref(client->handle);
}
switch (isc_sockaddr_pf(&client->peeraddr)) {
case AF_INET:
@@ -629,6 +635,10 @@ ns_client_send(ns_client_t *client) {
isc_nmhandle_ref(client->handle);
result = client_sendpkg(client, &buffer);
if (result != ISC_R_SUCCESS) {
/* We won't get a callback to clean it up */
isc_nmhandle_unref(client->handle);
}
switch (isc_sockaddr_pf(&client->peeraddr)) {
case AF_INET:
@@ -2333,6 +2343,16 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
isc_task_detach(&client->task);
}
if (client->manager != NULL) {
clientmgr_detach(&client->manager);
}
if (client->mctx != NULL) {
isc_mem_detach(&client->mctx);
}
if (client->sctx != NULL) {
ns_server_detach(&client->sctx);
}
return (result);
}
-1
View File
@@ -90,7 +90,6 @@ struct ns_server {
/*% Test options and other configurables */
uint32_t options;
unsigned int delay;
dns_acl_t *blackholeacl;
dns_acl_t *keepresporder;
+2 -4
View File
@@ -1663,8 +1663,6 @@ xfrout_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
xfrout_fail(xfr, result, "send");
} else if (xfr->end_of_stream == false) {
sendstream(xfr);
/* Return now so we don't unref the handle */
return;
} else {
/* End of zone transfer stream. */
uint64_t msecs, persec;
@@ -1690,9 +1688,9 @@ xfrout_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
(unsigned int) persec);
xfrout_ctx_destroy(&xfr);
/* We're done, unreference the handle */
isc_nmhandle_unref(handle);
}
isc_nmhandle_unref(handle);
}
static void
+2 -2
View File
@@ -9,7 +9,7 @@ export CMOCKA_MESSAGE_OUTPUT
GDB="$(command -v gdb)"
kyua_report() {
${KYUA} --logfile /dev/null report --results-file "${KYUA_RESULT:-LATEST}"
${KYUA} --logfile /dev/null report --verbose --results-file "${KYUA_RESULT:-LATEST}"
}
status=0
@@ -36,7 +36,7 @@ then
# Use kyua-debug(1) facility to gather additional data on failed tests.
# Some runs will just show verbose information from the run, some will
# show backtrace via gdb(1).
broken_tests="$(kyua_report | awk '/Broken tests/ { flag=1; next } /Summary/ { flag=0 } flag' | awk '{ print $1 }')"
broken_tests=$(kyua_report | awk '$2 == "->" && ( $3 == "broken:" || $3 == "failed:" ) { print $1 }')
if [ -n "${CI}" ] && [ "$(id -u)" -eq 0 ] && [ -n "${broken_tests}" ] && [ -n "${GDB}" ]; then
if grep '^#define USE_LIBTOOL 1$' "${TOP}/config.h" >/dev/null; then
# kyua debug command misidentifies broken binary when libtool is used
+2 -1
View File
@@ -868,11 +868,12 @@
./bin/tests/system/pending/ns2/sign.sh SH 2009,2010,2012,2014,2016,2017,2018,2019,2020
./bin/tests/system/pending/setup.sh SH 2009,2012,2014,2016,2017,2018,2019,2020
./bin/tests/system/pending/tests.sh SH 2009,2010,2012,2015,2016,2018,2019,2020
./bin/tests/system/pipelined/ans5/ans.py PYTHON 2020
./bin/tests/system/pipelined/clean.sh SH 2014,2015,2016,2018,2019,2020
./bin/tests/system/pipelined/input X 2014,2015,2018,2019,2020
./bin/tests/system/pipelined/inputb X 2014,2015,2018,2019,2020
./bin/tests/system/pipelined/ns3/named.args X 2014,2015,2018,2019,2020
./bin/tests/system/pipelined/pipequeries.c C 2014,2015,2015,2016,2017,2018,2019,2020
./bin/tests/system/pipelined/prereq.sh SH 2020
./bin/tests/system/pipelined/ref X 2014,2015,2018,2019,2020
./bin/tests/system/pipelined/refb X 2014,2015,2018,2019,2020
./bin/tests/system/pipelined/setup.sh SH 2014,2015,2016,2017,2018,2019,2020